Skip to content

Commit e07623d

Browse files
committed
librustc: Make monomorphic newtype structs work cross-crate
1 parent 6016214 commit e07623d

File tree

12 files changed

+138
-36
lines changed

12 files changed

+138
-36
lines changed

src/librustc/metadata/common.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,5 +153,8 @@ pub const tag_lang_items_item: uint = 0x73;
153153
pub const tag_lang_items_item_id: uint = 0x74;
154154
pub const tag_lang_items_item_node_id: uint = 0x75;
155155

156+
pub const tag_item_unnamed_field: uint = 0x76;
157+
pub const tag_items_data_item_struct_ctor: uint = 0x77;
158+
156159
pub type link_meta = {name: @str, vers: @str, extras_hash: @str};
157160

src/librustc/metadata/csearch.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,8 +166,9 @@ pub fn get_item_attrs(cstore: @mut cstore::CStore,
166166
decoder::get_item_attrs(cdata, def_id.node, f)
167167
}
168168

169-
pub fn get_struct_fields(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::field_ty] {
170-
let cstore = tcx.cstore;
169+
pub fn get_struct_fields(cstore: @mut cstore::CStore,
170+
def: ast::def_id)
171+
-> ~[ty::field_ty] {
171172
let cdata = cstore::get_crate_data(cstore, def.crate);
172173
decoder::get_struct_fields(cstore.intr, cdata, def.node)
173174
}

src/librustc/metadata/decoder.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ use std::serialize::Decodable;
4242
use syntax::ast_map;
4343
use syntax::attr;
4444
use syntax::diagnostic::span_handler;
45-
use syntax::parse::token::ident_interner;
45+
use syntax::parse::token::{ident_interner, special_idents};
4646
use syntax::print::pprust;
4747
use syntax::{ast, ast_util};
4848
use syntax::codemap;
@@ -231,7 +231,9 @@ pub fn item_type(item_id: ast::def_id, item: ebml::Doc,
231231
let t = doc_type(item, tcx, cdata);
232232
if family_names_type(item_family(item)) {
233233
ty::mk_with_id(tcx, t, item_id)
234-
} else { t }
234+
} else {
235+
t
236+
}
235237
}
236238

237239
fn item_impl_traits(item: ebml::Doc, tcx: ty::ctxt, cdata: cmd) -> ~[ty::t] {
@@ -661,11 +663,12 @@ fn item_impl_methods(intr: @ident_interner, cdata: cmd, item: ebml::Doc,
661663
rslt
662664
}
663665

664-
pub fn get_impls_for_mod(intr: @ident_interner, cdata: cmd,
665-
m_id: ast::node_id, name: Option<ast::ident>,
666-
get_cdata: fn(ast::crate_num) -> cmd)
666+
pub fn get_impls_for_mod(intr: @ident_interner,
667+
cdata: cmd,
668+
m_id: ast::node_id,
669+
name: Option<ast::ident>,
670+
get_cdata: &fn(ast::crate_num) -> cmd)
667671
-> @~[@_impl] {
668-
669672
let data = cdata.data;
670673
let mod_item = lookup_item(m_id, data);
671674
let mut result = ~[];
@@ -887,6 +890,15 @@ pub fn get_struct_fields(intr: @ident_interner, cdata: cmd, id: ast::node_id)
887890
});
888891
}
889892
}
893+
for reader::tagged_docs(item, tag_item_unnamed_field) |an_item| {
894+
let did = item_def_id(an_item, cdata);
895+
result.push(ty::field_ty {
896+
ident: special_idents::unnamed_field,
897+
id: did,
898+
vis: ast::inherited,
899+
mutability: ast::struct_immutable,
900+
});
901+
}
890902
result
891903
}
892904

src/librustc/metadata/encoder.rs

Lines changed: 69 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ use syntax::ast_map;
4646
use syntax::ast_util::*;
4747
use syntax::attr;
4848
use syntax::diagnostic::span_handler;
49+
use syntax::parse::token::special_idents;
4950
use syntax::print::pprust;
5051
use syntax::{ast_util, visit};
5152
use syntax;
@@ -328,7 +329,7 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: writer::Encoder,
328329
// Encode info about all the module children.
329330
for md.items.each |item| {
330331
match item.node {
331-
item_impl(*) | item_struct(*) => {
332+
item_impl(*) => {
332333
let (ident, did) = (item.ident, item.id);
333334
debug!("(encoding info for module) ... encoding impl %s \
334335
(%?/%?)",
@@ -432,25 +433,28 @@ fn encode_info_for_struct(ecx: @encode_ctxt, ebml_w: writer::Encoder,
432433
/* We encode both private and public fields -- need to include
433434
private fields to get the offsets right */
434435
for fields.each |field| {
435-
match field.node.kind {
436-
named_field(nm, mt, vis) => {
437-
let id = field.node.id;
438-
index.push({val: id, pos: ebml_w.writer.tell()});
439-
global_index.push({val: id,
440-
pos: ebml_w.writer.tell()});
441-
ebml_w.start_tag(tag_items_data_item);
442-
debug!("encode_info_for_struct: doing %s %d",
443-
tcx.sess.str_of(nm), id);
444-
encode_visibility(ebml_w, vis);
445-
encode_name(ecx, ebml_w, nm);
446-
encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
447-
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
448-
encode_mutability(ebml_w, mt);
449-
encode_def_id(ebml_w, local_def(id));
450-
ebml_w.end_tag();
451-
}
452-
unnamed_field => {}
453-
}
436+
let (nm, mt, vis) = match field.node.kind {
437+
named_field(nm, mt, vis) => (nm, mt, vis),
438+
unnamed_field => (
439+
special_idents::unnamed_field,
440+
struct_immutable,
441+
inherited
442+
)
443+
};
444+
445+
let id = field.node.id;
446+
index.push({val: id, pos: ebml_w.writer.tell()});
447+
global_index.push({val: id, pos: ebml_w.writer.tell()});
448+
ebml_w.start_tag(tag_items_data_item);
449+
debug!("encode_info_for_struct: doing %s %d",
450+
tcx.sess.str_of(nm), id);
451+
encode_visibility(ebml_w, vis);
452+
encode_name(ecx, ebml_w, nm);
453+
encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
454+
encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
455+
encode_mutability(ebml_w, mt);
456+
encode_def_id(ebml_w, local_def(id));
457+
ebml_w.end_tag();
454458
}
455459
/*bad*/copy *index
456460
}
@@ -481,6 +485,28 @@ fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: writer::Encoder,
481485
ebml_w.end_tag();
482486
}
483487

488+
fn encode_info_for_struct_ctor(ecx: @encode_ctxt,
489+
ebml_w: writer::Encoder,
490+
path: &[ast_map::path_elt],
491+
name: ast::ident,
492+
ctor_id: node_id,
493+
index: @mut ~[entry<int>]) {
494+
index.push({ val: ctor_id, pos: ebml_w.writer.tell() });
495+
496+
ebml_w.start_tag(tag_items_data_item);
497+
encode_def_id(ebml_w, local_def(ctor_id));
498+
encode_family(ebml_w, 'f');
499+
encode_name(ecx, ebml_w, name);
500+
encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
501+
encode_path(ecx, ebml_w, path, ast_map::path_name(name));
502+
503+
if ecx.item_symbols.contains_key(&ctor_id) {
504+
encode_symbol(ecx, ebml_w, ctor_id);
505+
}
506+
507+
ebml_w.end_tag();
508+
}
509+
484510
fn encode_info_for_method(ecx: @encode_ctxt,
485511
ebml_w: writer::Encoder,
486512
impl_path: &[ast_map::path_elt],
@@ -674,6 +700,24 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder,
674700
encode_family(ebml_w, 'S');
675701
encode_type_param_bounds(ebml_w, ecx, tps);
676702
encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
703+
704+
// If this is a tuple- or enum-like struct, encode the type of the
705+
// constructor.
706+
if struct_def.fields.len() > 0 &&
707+
struct_def.fields[0].node.kind == ast::unnamed_field {
708+
let ctor_id = match struct_def.ctor_id {
709+
Some(ctor_id) => ctor_id,
710+
None => ecx.tcx.sess.bug(~"struct def didn't have ctor id"),
711+
};
712+
713+
encode_info_for_struct_ctor(ecx,
714+
ebml_w,
715+
path,
716+
item.ident,
717+
ctor_id,
718+
index);
719+
}
720+
677721
encode_name(ecx, ebml_w, item.ident);
678722
encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
679723
encode_region_param(ecx, ebml_w, item);
@@ -697,7 +741,11 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder,
697741
encode_def_id(ebml_w, local_def(f.node.id));
698742
ebml_w.end_tag();
699743
}
700-
unnamed_field => {}
744+
unnamed_field => {
745+
ebml_w.start_tag(tag_item_unnamed_field);
746+
encode_def_id(ebml_w, local_def(f.node.id));
747+
ebml_w.end_tag();
748+
}
701749
}
702750
}
703751

src/librustc/middle/resolve.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ use core::prelude::*;
1313
use driver::session;
1414
use driver::session::Session;
1515
use metadata::csearch::{each_path, get_method_names_if_trait};
16-
use metadata::csearch::{get_static_methods_if_impl, get_type_name_if_impl};
16+
use metadata::csearch::{get_static_methods_if_impl, get_struct_fields};
17+
use metadata::csearch::{get_type_name_if_impl};
1718
use metadata::cstore::find_use_stmt_cnum;
1819
use metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
1920
use middle::lang_items::LanguageItems;
@@ -1745,10 +1746,12 @@ pub impl Resolver {
17451746
OverwriteDuplicates,
17461747
dummy_sp());
17471748

1748-
self.handle_external_def(def, modules,
1749+
self.handle_external_def(def,
1750+
modules,
17491751
child_name_bindings,
17501752
self.session.str_of(final_ident),
1751-
final_ident, new_parent);
1753+
final_ident,
1754+
new_parent);
17521755
}
17531756
dl_impl(def) => {
17541757
// We only process static methods of impls here.

src/librustc/middle/trans/base.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1905,8 +1905,13 @@ pub fn trans_tuple_struct(ccx: @crate_ctxt,
19051905
}
19061906
};
19071907
1908-
let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, ctor_id, None,
1909-
param_substs, None);
1908+
let fcx = new_fn_ctxt_w_id(ccx,
1909+
~[],
1910+
llfndecl,
1911+
ctor_id,
1912+
None,
1913+
param_substs,
1914+
None);
19101915
19111916
// XXX: Bad copy.
19121917
let raw_llargs = create_llargs_for_fn_args(fcx, no_self, copy fn_args);

src/librustc/middle/trans/reachable.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ fn traverse_public_item(cx: ctx, item: @item) {
122122
}
123123
}
124124
item_struct(struct_def, tps) => {
125+
for struct_def.ctor_id.each |&ctor_id| {
126+
cx.rmap.insert(ctor_id, ());
127+
}
125128
do option::iter(&struct_def.dtor) |dtor| {
126129
cx.rmap.insert(dtor.node.id, ());
127130
if tps.len() > 0u || attr::find_inline_attr(dtor.node.attrs)

src/librustc/middle/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4012,7 +4012,7 @@ pub fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
40124012
}
40134013
}
40144014
else {
4015-
return csearch::get_struct_fields(cx, did);
4015+
return csearch::get_struct_fields(cx.sess.cstore, did);
40164016
}
40174017
}
40184018

src/librustc/middle/typeck/coherence.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ pub impl CoherenceChecker {
828828
let implementations = get_impls_for_mod(crate_store,
829829
module_def_id,
830830
None);
831-
for (*implementations).each |implementation| {
831+
for implementations.each |implementation| {
832832
debug!("coherence: adding impl from external crate: %s",
833833
ty::item_path_str(self.crate_context.tcx,
834834
implementation.did));
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#[crate_type="lib"];
2+
3+
pub struct Au(int);
4+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// xfail-fast
2+
// aux-build:newtype_struct_xc.rs
3+
4+
extern mod newtype_struct_xc;
5+
use newtype_struct_xc::Au;
6+
7+
fn f() -> Au {
8+
Au(2)
9+
}
10+
11+
fn main() {
12+
let _ = f();
13+
}
14+
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// xfail-fast
2+
// aux-build:newtype_struct_xc.rs
3+
4+
extern mod newtype_struct_xc;
5+
6+
fn main() {
7+
let _ = newtype_struct_xc::Au(2);
8+
}
9+

0 commit comments

Comments
 (0)