about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2013-02-11 16:28:39 -0800
committerPatrick Walton <pcwalton@mimiga.net>2013-02-13 09:47:20 -0800
commite07623d70b5f1841a3e958195a0f8df4606d264c (patch)
treec51b22dddf3c61f327e91b774d86a0f816f93b2a
parent6016214101d40c627f2c52412fb77d56254c901e (diff)
downloadrust-e07623d70b5f1841a3e958195a0f8df4606d264c.tar.gz
rust-e07623d70b5f1841a3e958195a0f8df4606d264c.zip
librustc: Make monomorphic newtype structs work cross-crate
-rw-r--r--src/librustc/metadata/common.rs3
-rw-r--r--src/librustc/metadata/csearch.rs5
-rw-r--r--src/librustc/metadata/decoder.rs24
-rw-r--r--src/librustc/metadata/encoder.rs90
-rw-r--r--src/librustc/middle/resolve.rs9
-rw-r--r--src/librustc/middle/trans/base.rs9
-rw-r--r--src/librustc/middle/trans/reachable.rs3
-rw-r--r--src/librustc/middle/ty.rs2
-rw-r--r--src/librustc/middle/typeck/coherence.rs2
-rw-r--r--src/test/auxiliary/newtype_struct_xc.rs4
-rw-r--r--src/test/run-pass/newtype-struct-xc-2.rs14
-rw-r--r--src/test/run-pass/newtype-struct-xc.rs9
12 files changed, 138 insertions, 36 deletions
diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs
index 37c19e80600..27c9435bcbc 100644
--- a/src/librustc/metadata/common.rs
+++ b/src/librustc/metadata/common.rs
@@ -153,5 +153,8 @@ pub const tag_lang_items_item: uint = 0x73;
 pub const tag_lang_items_item_id: uint = 0x74;
 pub const tag_lang_items_item_node_id: uint = 0x75;
 
+pub const tag_item_unnamed_field: uint = 0x76;
+pub const tag_items_data_item_struct_ctor: uint = 0x77;
+
 pub type link_meta = {name: @str, vers: @str, extras_hash: @str};
 
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs
index 2cb5cfbddd7..fa82e6c92c0 100644
--- a/src/librustc/metadata/csearch.rs
+++ b/src/librustc/metadata/csearch.rs
@@ -166,8 +166,9 @@ pub fn get_item_attrs(cstore: @mut cstore::CStore,
     decoder::get_item_attrs(cdata, def_id.node, f)
 }
 
-pub fn get_struct_fields(tcx: ty::ctxt, def: ast::def_id) -> ~[ty::field_ty] {
-    let cstore = tcx.cstore;
+pub fn get_struct_fields(cstore: @mut cstore::CStore,
+                         def: ast::def_id)
+                      -> ~[ty::field_ty] {
     let cdata = cstore::get_crate_data(cstore, def.crate);
     decoder::get_struct_fields(cstore.intr, cdata, def.node)
 }
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 67498ad5aaf..14dda962282 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -42,7 +42,7 @@ use std::serialize::Decodable;
 use syntax::ast_map;
 use syntax::attr;
 use syntax::diagnostic::span_handler;
-use syntax::parse::token::ident_interner;
+use syntax::parse::token::{ident_interner, special_idents};
 use syntax::print::pprust;
 use syntax::{ast, ast_util};
 use syntax::codemap;
@@ -231,7 +231,9 @@ pub fn item_type(item_id: ast::def_id, item: ebml::Doc,
     let t = doc_type(item, tcx, cdata);
     if family_names_type(item_family(item)) {
         ty::mk_with_id(tcx, t, item_id)
-    } else { t }
+    } else {
+        t
+    }
 }
 
 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,
     rslt
 }
 
-pub fn get_impls_for_mod(intr: @ident_interner, cdata: cmd,
-                         m_id: ast::node_id, name: Option<ast::ident>,
-                         get_cdata: fn(ast::crate_num) -> cmd)
+pub fn get_impls_for_mod(intr: @ident_interner,
+                         cdata: cmd,
+                         m_id: ast::node_id,
+                         name: Option<ast::ident>,
+                         get_cdata: &fn(ast::crate_num) -> cmd)
                       -> @~[@_impl] {
-
     let data = cdata.data;
     let mod_item = lookup_item(m_id, data);
     let mut result = ~[];
@@ -887,6 +890,15 @@ pub fn get_struct_fields(intr: @ident_interner, cdata: cmd, id: ast::node_id)
             });
         }
     }
+    for reader::tagged_docs(item, tag_item_unnamed_field) |an_item| {
+        let did = item_def_id(an_item, cdata);
+        result.push(ty::field_ty {
+            ident: special_idents::unnamed_field,
+            id: did,
+            vis: ast::inherited,
+            mutability: ast::struct_immutable,
+        });
+    }
     result
 }
 
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index fcc1a4e806d..3c39a4032f5 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -46,6 +46,7 @@ use syntax::ast_map;
 use syntax::ast_util::*;
 use syntax::attr;
 use syntax::diagnostic::span_handler;
+use syntax::parse::token::special_idents;
 use syntax::print::pprust;
 use syntax::{ast_util, visit};
 use syntax;
@@ -328,7 +329,7 @@ fn encode_info_for_mod(ecx: @encode_ctxt, ebml_w: writer::Encoder,
     // Encode info about all the module children.
     for md.items.each |item| {
         match item.node {
-            item_impl(*) | item_struct(*) => {
+            item_impl(*) => {
                 let (ident, did) = (item.ident, item.id);
                 debug!("(encoding info for module) ... encoding impl %s \
                         (%?/%?)",
@@ -432,25 +433,28 @@ fn encode_info_for_struct(ecx: @encode_ctxt, ebml_w: writer::Encoder,
      /* We encode both private and public fields -- need to include
         private fields to get the offsets right */
     for fields.each |field| {
-        match field.node.kind {
-            named_field(nm, mt, vis) => {
-                let id = field.node.id;
-                index.push({val: id, pos: ebml_w.writer.tell()});
-                global_index.push({val: id,
-                                    pos: ebml_w.writer.tell()});
-                ebml_w.start_tag(tag_items_data_item);
-                debug!("encode_info_for_struct: doing %s %d",
-                       tcx.sess.str_of(nm), id);
-                encode_visibility(ebml_w, vis);
-                encode_name(ecx, ebml_w, nm);
-                encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
-                encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
-                encode_mutability(ebml_w, mt);
-                encode_def_id(ebml_w, local_def(id));
-                ebml_w.end_tag();
-            }
-            unnamed_field => {}
-        }
+        let (nm, mt, vis) = match field.node.kind {
+            named_field(nm, mt, vis) => (nm, mt, vis),
+            unnamed_field => (
+                special_idents::unnamed_field,
+                struct_immutable,
+                inherited
+            )
+        };
+
+        let id = field.node.id;
+        index.push({val: id, pos: ebml_w.writer.tell()});
+        global_index.push({val: id, pos: ebml_w.writer.tell()});
+        ebml_w.start_tag(tag_items_data_item);
+        debug!("encode_info_for_struct: doing %s %d",
+               tcx.sess.str_of(nm), id);
+        encode_visibility(ebml_w, vis);
+        encode_name(ecx, ebml_w, nm);
+        encode_path(ecx, ebml_w, path, ast_map::path_name(nm));
+        encode_type(ecx, ebml_w, node_id_to_type(tcx, id));
+        encode_mutability(ebml_w, mt);
+        encode_def_id(ebml_w, local_def(id));
+        ebml_w.end_tag();
     }
     /*bad*/copy *index
 }
@@ -481,6 +485,28 @@ fn encode_info_for_ctor(ecx: @encode_ctxt, ebml_w: writer::Encoder,
         ebml_w.end_tag();
 }
 
+fn encode_info_for_struct_ctor(ecx: @encode_ctxt,
+                               ebml_w: writer::Encoder,
+                               path: &[ast_map::path_elt],
+                               name: ast::ident,
+                               ctor_id: node_id,
+                               index: @mut ~[entry<int>]) {
+    index.push({ val: ctor_id, pos: ebml_w.writer.tell() });
+
+    ebml_w.start_tag(tag_items_data_item);
+    encode_def_id(ebml_w, local_def(ctor_id));
+    encode_family(ebml_w, 'f');
+    encode_name(ecx, ebml_w, name);
+    encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, ctor_id));
+    encode_path(ecx, ebml_w, path, ast_map::path_name(name));
+
+    if ecx.item_symbols.contains_key(&ctor_id) {
+        encode_symbol(ecx, ebml_w, ctor_id);
+    }
+
+    ebml_w.end_tag();
+}
+
 fn encode_info_for_method(ecx: @encode_ctxt,
                           ebml_w: writer::Encoder,
                           impl_path: &[ast_map::path_elt],
@@ -674,6 +700,24 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder,
         encode_family(ebml_w, 'S');
         encode_type_param_bounds(ebml_w, ecx, tps);
         encode_type(ecx, ebml_w, node_id_to_type(tcx, item.id));
+
+        // If this is a tuple- or enum-like struct, encode the type of the
+        // constructor.
+        if struct_def.fields.len() > 0 &&
+                struct_def.fields[0].node.kind == ast::unnamed_field {
+            let ctor_id = match struct_def.ctor_id {
+                Some(ctor_id) => ctor_id,
+                None => ecx.tcx.sess.bug(~"struct def didn't have ctor id"),
+            };
+
+            encode_info_for_struct_ctor(ecx,
+                                        ebml_w,
+                                        path,
+                                        item.ident,
+                                        ctor_id,
+                                        index);
+        }
+
         encode_name(ecx, ebml_w, item.ident);
         encode_path(ecx, ebml_w, path, ast_map::path_name(item.ident));
         encode_region_param(ecx, ebml_w, item);
@@ -697,7 +741,11 @@ fn encode_info_for_item(ecx: @encode_ctxt, ebml_w: writer::Encoder,
                    encode_def_id(ebml_w, local_def(f.node.id));
                    ebml_w.end_tag();
                 }
-                unnamed_field => {}
+                unnamed_field => {
+                    ebml_w.start_tag(tag_item_unnamed_field);
+                    encode_def_id(ebml_w, local_def(f.node.id));
+                    ebml_w.end_tag();
+                }
             }
         }
 
diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs
index ba550dbbde8..ea840da73cd 100644
--- a/src/librustc/middle/resolve.rs
+++ b/src/librustc/middle/resolve.rs
@@ -13,7 +13,8 @@ use core::prelude::*;
 use driver::session;
 use driver::session::Session;
 use metadata::csearch::{each_path, get_method_names_if_trait};
-use metadata::csearch::{get_static_methods_if_impl, get_type_name_if_impl};
+use metadata::csearch::{get_static_methods_if_impl, get_struct_fields};
+use metadata::csearch::{get_type_name_if_impl};
 use metadata::cstore::find_use_stmt_cnum;
 use metadata::decoder::{def_like, dl_def, dl_field, dl_impl};
 use middle::lang_items::LanguageItems;
@@ -1745,10 +1746,12 @@ pub impl Resolver {
                                        OverwriteDuplicates,
                                        dummy_sp());
 
-                    self.handle_external_def(def, modules,
+                    self.handle_external_def(def,
+                                             modules,
                                              child_name_bindings,
                                              self.session.str_of(final_ident),
-                                             final_ident, new_parent);
+                                             final_ident,
+                                             new_parent);
                 }
                 dl_impl(def) => {
                     // We only process static methods of impls here.
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index ced47bb5681..c61ff7d5e02 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -1905,8 +1905,13 @@ pub fn trans_tuple_struct(ccx: @crate_ctxt,
         }
     };
 
-    let fcx = new_fn_ctxt_w_id(ccx, ~[], llfndecl, ctor_id, None,
-                               param_substs, None);
+    let fcx = new_fn_ctxt_w_id(ccx,
+                               ~[],
+                               llfndecl,
+                               ctor_id,
+                               None,
+                               param_substs,
+                               None);
 
     // XXX: Bad copy.
     let raw_llargs = create_llargs_for_fn_args(fcx, no_self, copy fn_args);
diff --git a/src/librustc/middle/trans/reachable.rs b/src/librustc/middle/trans/reachable.rs
index f77aa33407d..bf417e9a5f4 100644
--- a/src/librustc/middle/trans/reachable.rs
+++ b/src/librustc/middle/trans/reachable.rs
@@ -122,6 +122,9 @@ fn traverse_public_item(cx: ctx, item: @item) {
         }
       }
       item_struct(struct_def, tps) => {
+        for struct_def.ctor_id.each |&ctor_id| {
+            cx.rmap.insert(ctor_id, ());
+        }
         do option::iter(&struct_def.dtor) |dtor| {
             cx.rmap.insert(dtor.node.id, ());
             if tps.len() > 0u || attr::find_inline_attr(dtor.node.attrs)
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index cef4f9ff1b4..d38eef0fcf9 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -4012,7 +4012,7 @@ pub fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
     }
         }
   else {
-        return csearch::get_struct_fields(cx, did);
+        return csearch::get_struct_fields(cx.sess.cstore, did);
     }
 }
 
diff --git a/src/librustc/middle/typeck/coherence.rs b/src/librustc/middle/typeck/coherence.rs
index 5e51c216093..fdf936f7aec 100644
--- a/src/librustc/middle/typeck/coherence.rs
+++ b/src/librustc/middle/typeck/coherence.rs
@@ -828,7 +828,7 @@ pub impl CoherenceChecker {
         let implementations = get_impls_for_mod(crate_store,
                                                 module_def_id,
                                                 None);
-        for (*implementations).each |implementation| {
+        for implementations.each |implementation| {
             debug!("coherence: adding impl from external crate: %s",
                    ty::item_path_str(self.crate_context.tcx,
                                      implementation.did));
diff --git a/src/test/auxiliary/newtype_struct_xc.rs b/src/test/auxiliary/newtype_struct_xc.rs
new file mode 100644
index 00000000000..90036e0f96c
--- /dev/null
+++ b/src/test/auxiliary/newtype_struct_xc.rs
@@ -0,0 +1,4 @@
+#[crate_type="lib"];
+
+pub struct Au(int);
+
diff --git a/src/test/run-pass/newtype-struct-xc-2.rs b/src/test/run-pass/newtype-struct-xc-2.rs
new file mode 100644
index 00000000000..a7c686daa7f
--- /dev/null
+++ b/src/test/run-pass/newtype-struct-xc-2.rs
@@ -0,0 +1,14 @@
+// xfail-fast
+// aux-build:newtype_struct_xc.rs
+
+extern mod newtype_struct_xc;
+use newtype_struct_xc::Au;
+
+fn f() -> Au {
+    Au(2)
+}
+
+fn main() {
+    let _ = f();
+}
+
diff --git a/src/test/run-pass/newtype-struct-xc.rs b/src/test/run-pass/newtype-struct-xc.rs
new file mode 100644
index 00000000000..8b15d73dc93
--- /dev/null
+++ b/src/test/run-pass/newtype-struct-xc.rs
@@ -0,0 +1,9 @@
+// xfail-fast
+// aux-build:newtype_struct_xc.rs
+
+extern mod newtype_struct_xc;
+
+fn main() {
+    let _ = newtype_struct_xc::Au(2);
+}
+