about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2013-03-28 14:27:54 -0400
committerNiko Matsakis <niko@alum.mit.edu>2013-04-05 05:36:02 -0400
commit569596573a2f90d52c7f7610d8c7c637dc587f0a (patch)
treec717329b162919aafda417fbf672405fe5806737
parent007abe935209ab35d85e1b7fa0bfc88460340560 (diff)
downloadrust-569596573a2f90d52c7f7610d8c7c637dc587f0a.tar.gz
rust-569596573a2f90d52c7f7610d8c7c637dc587f0a.zip
Compute a ty::method for methods that appear in impls as well
-rw-r--r--src/librustc/metadata/decoder.rs7
-rw-r--r--src/librustc/metadata/encoder.rs63
-rw-r--r--src/librustc/middle/typeck/collect.rs89
-rw-r--r--src/libsyntax/ast.rs9
4 files changed, 89 insertions, 79 deletions
diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs
index 800df628bc2..598539609e9 100644
--- a/src/librustc/metadata/decoder.rs
+++ b/src/librustc/metadata/decoder.rs
@@ -714,18 +714,19 @@ pub fn get_method(intr: @ident_interner, cdata: cmd, id: ast::node_id,
                   tcx: ty::ctxt) -> ty::method
 {
     let method_doc = lookup_item(id, cdata.data);
+    let def_id = item_def_id(method_doc, cdata);
+    let name = item_name(intr, method_doc);
     let bounds = item_ty_param_bounds(method_doc, tcx, cdata,
                                       tag_item_method_tps);
-    let name = item_name(intr, method_doc);
-    let def_id = item_def_id(method_doc, cdata);
     let fty = doc_method_fty(method_doc, tcx, cdata);
+    let vis = item_visibility(method_doc);
     let self_ty = get_self_ty(method_doc);
     ty::method {
         ident: name,
         tps: bounds,
         fty: fty,
         self_ty: self_ty,
-        vis: ast::public,
+        vis: vis,
         def_id: def_id
     }
 }
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index 61501d83083..2e3008a0cdc 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -562,13 +562,25 @@ fn encode_info_for_struct_ctor(ecx: @EncodeContext,
     ebml_w.end_tag();
 }
 
+fn encode_method_ty_fields(ecx: @EncodeContext,
+                           ebml_w: writer::Encoder,
+                           method_ty: &ty::method)
+{
+    encode_def_id(ebml_w, method_ty.def_id);
+    encode_name(ecx, ebml_w, method_ty.ident);
+    encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps,
+                                tag_item_method_tps);
+    encode_method_fty(ecx, ebml_w, &method_ty.fty);
+    encode_visibility(ebml_w, method_ty.vis);
+    encode_self_type(ebml_w, method_ty.self_ty);
+}
+
 fn encode_info_for_method(ecx: @EncodeContext,
                           ebml_w: writer::Encoder,
                           impl_path: &[ast_map::path_elt],
                           should_inline: bool,
                           parent_id: node_id,
                           m: @method,
-                          parent_visibility: ast::visibility,
                           owner_generics: &ast::Generics,
                           method_generics: &ast::Generics) {
     debug!("encode_info_for_method: %d %s %u %u", m.id,
@@ -576,7 +588,10 @@ fn encode_info_for_method(ecx: @EncodeContext,
            owner_generics.ty_params.len(),
            method_generics.ty_params.len());
     ebml_w.start_tag(tag_items_data_item);
-    encode_def_id(ebml_w, local_def(m.id));
+
+    let method_def_id = local_def(m.id);
+    let method_ty: @ty::method = ty::method(ecx.tcx, method_def_id);
+    encode_method_ty_fields(ecx, ebml_w, method_ty);
 
     match m.self_ty.node {
         ast::sty_static => {
@@ -592,16 +607,7 @@ fn encode_info_for_method(ecx: @EncodeContext,
     encode_type_param_bounds(ebml_w, ecx, &combined_ty_params);
 
     encode_type(ecx, ebml_w, node_id_to_type(ecx.tcx, m.id));
-    encode_name(ecx, ebml_w, m.ident);
     encode_path(ecx, ebml_w, impl_path, ast_map::path_name(m.ident));
-    encode_self_type(ebml_w, m.self_ty.node);
-
-    // Combine parent visibility and this visibility.
-    let visibility = match m.vis {
-        ast::inherited => parent_visibility,
-        vis => vis,
-    };
-    encode_visibility(ebml_w, visibility);
 
     if len > 0u || should_inline {
         (ecx.encode_inlined_item)(
@@ -610,6 +616,7 @@ fn encode_info_for_method(ecx: @EncodeContext,
     } else {
         encode_symbol(ecx, ebml_w, m.id);
     }
+
     ebml_w.end_tag();
 }
 
@@ -863,17 +870,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
         let mut impl_path = vec::append(~[], path);
         impl_path += ~[ast_map::path_name(item.ident)];
 
-        // If there is a trait reference, treat the methods as always public.
-        // This is to work around some incorrect behavior in privacy checking:
-        // when the method belongs to a trait, it should acquire the privacy
-        // from the trait, not the impl. Forcing the visibility to be public
-        // makes things sorta work.
-        let parent_visibility = if opt_trait.is_some() {
-            ast::public
-        } else {
-            item.vis
-        };
-
         for methods.each |m| {
             index.push(entry {val: m.id, pos: ebml_w.writer.tell()});
             encode_info_for_method(ecx,
@@ -882,7 +878,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
                                    should_inline(m.attrs),
                                    item.id,
                                    *m,
-                                   parent_visibility,
                                    generics,
                                    &m.generics);
         }
@@ -909,11 +904,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
         ebml_w.end_tag();
 
         // Now output the method info for each method.
-        //
-        // Note: for the moment, the data structures here are *slightly*
-        // different from those expected by `encode_info_for_method()`,
-        // but I do plan to refactor this later in this patch to avoid the
-        // duplication.
         for ty::trait_method_def_ids(tcx, local_def(item.id)).eachi |i, &method_def_id| {
             assert!(method_def_id.crate == ast::local_crate);
 
@@ -923,9 +913,13 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
 
             ebml_w.start_tag(tag_items_data_item);
 
-            encode_def_id(ebml_w, method_def_id);
+            encode_method_ty_fields(ecx, ebml_w, method_ty);
+
             encode_parent_item(ebml_w, local_def(item.id));
-            encode_name(ecx, ebml_w, method_ty.ident);
+
+            let mut trait_path = vec::append(~[], path);
+            trait_path.push(ast_map::path_name(item.ident));
+            encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
 
             match method_ty.self_ty {
                 sty_static => {
@@ -946,15 +940,6 @@ fn encode_info_for_item(ecx: @EncodeContext, ebml_w: writer::Encoder,
                 }
             }
 
-            encode_ty_type_param_bounds(ebml_w, ecx, method_ty.tps,
-                                        tag_item_method_tps);
-            encode_method_fty(ecx, ebml_w, &method_ty.fty);
-            encode_visibility(ebml_w, method_ty.vis);
-            encode_self_type(ebml_w, method_ty.self_ty);
-            let mut trait_path = vec::append(~[], path);
-            trait_path.push(ast_map::path_name(item.ident));
-            encode_path(ecx, ebml_w, trait_path, ast_map::path_name(method_ty.ident));
-
             match ms[i] {
                 required(_) => {
                     encode_method_sort(ebml_w, 'r');
diff --git a/src/librustc/middle/typeck/collect.rs b/src/librustc/middle/typeck/collect.rs
index d89d1c407d7..3ac3766e89d 100644
--- a/src/librustc/middle/typeck/collect.rs
+++ b/src/librustc/middle/typeck/collect.rs
@@ -315,7 +315,6 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
                                 ty: ty});
     }
 
-
     fn ty_method_of_trait_method(self: &CrateCtxt,
                                  trait_rp: Option<ty::region_variance>,
                                  trait_generics: &ast::Generics,
@@ -336,8 +335,8 @@ pub fn ensure_trait_methods(ccx: &CrateCtxt,
                                         AbiSet::Rust(),
                                         &m_generics.lifetimes,
                                         m_decl),
-            // assume public, because this is only invoked on trait methods
             self_ty: m_self_ty.node,
+            // assume public, because this is only invoked on trait methods
             vis: ast::public,
             def_id: local_def(*m_id)
         }
@@ -599,7 +598,7 @@ pub fn convert_field(ccx: &CrateCtxt,
 }
 
 pub struct ConvertedMethod {
-    mty: ty::method,
+    mty: @ty::method,
     id: ast::node_id,
     span: span,
     body_id: ast::node_id
@@ -609,13 +608,15 @@ pub fn convert_methods(ccx: &CrateCtxt,
                        ms: &[@ast::method],
                        rp: Option<ty::region_variance>,
                        rcvr_bounds: @~[ty::param_bounds],
-                       rcvr_generics: &ast::Generics)
-                    -> ~[ConvertedMethod] {
-
+                       rcvr_generics: &ast::Generics,
+                       rcvr_visibility: ast::visibility)
+                    -> ~[ConvertedMethod]
+{
     let tcx = ccx.tcx;
-    do vec::map(ms) |m| {
+    return vec::map(ms, |m| {
         let bounds = ty_param_bounds(ccx, &m.generics);
-        let mty = ty_of_method(ccx, *m, rp, rcvr_generics, &m.generics);
+        let mty = @ty_of_method(ccx, *m, rp, rcvr_generics,
+                                rcvr_visibility, &m.generics);
         let fty = ty::mk_bare_fn(tcx, copy mty.fty);
         tcx.tcache.insert(
             local_def(m.id),
@@ -628,8 +629,34 @@ pub fn convert_methods(ccx: &CrateCtxt,
                 ty: fty
             });
         write_ty_to_tcx(tcx, m.id, fty);
+        tcx.methods.insert(mty.def_id, mty);
         ConvertedMethod {mty: mty, id: m.id,
                          span: m.span, body_id: m.body.node.id}
+    });
+
+    fn ty_of_method(ccx: &CrateCtxt,
+                    m: @ast::method,
+                    rp: Option<ty::region_variance>,
+                    rcvr_generics: &ast::Generics,
+                    rcvr_visibility: ast::visibility,
+                    method_generics: &ast::Generics) -> ty::method
+    {
+        let rscope = MethodRscope::new(m.self_ty.node,
+                                       rp,
+                                       rcvr_generics);
+        ty::method {
+            ident: m.ident,
+            tps: ty_param_bounds(ccx, &m.generics),
+            fty: astconv::ty_of_bare_fn(ccx,
+                                        &rscope,
+                                        m.purity,
+                                        ast::RustAbi,
+                                        &method_generics.lifetimes,
+                                        &m.decl),
+            self_ty: m.self_ty.node,
+            vis: m.vis.inherit_from(rcvr_visibility),
+            def_id: local_def(m.id)
+        }
     }
 }
 
@@ -665,7 +692,7 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
                                generics,
                                rp);
       }
-      ast::item_impl(ref generics, trait_ref, selfty, ref ms) => {
+      ast::item_impl(ref generics, opt_trait_ref, selfty, ref ms) => {
         let i_bounds = ty_param_bounds(ccx, generics);
         let region_parameterization =
             RegionParameterization::from_variance_and_generics(rp, generics);
@@ -677,9 +704,20 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
                             region_param: rp,
                             ty: selfty});
 
-        // XXX: Bad copy of `ms` below.
-        let cms = convert_methods(ccx, *ms, rp, i_bounds, generics);
-        for trait_ref.each |t| {
+        // If there is a trait reference, treat the methods as always public.
+        // This is to work around some incorrect behavior in privacy checking:
+        // when the method belongs to a trait, it should acquire the privacy
+        // from the trait, not the impl. Forcing the visibility to be public
+        // makes things sorta work.
+        let parent_visibility = if opt_trait_ref.is_some() {
+            ast::public
+        } else {
+            it.vis
+        };
+
+        let cms = convert_methods(ccx, *ms, rp, i_bounds, generics,
+                                  parent_visibility);
+        for opt_trait_ref.each |t| {
             check_methods_against_trait(ccx, generics, rp, selfty, *t, cms);
         }
       }
@@ -694,7 +732,8 @@ pub fn convert(ccx: &CrateCtxt, it: @ast::item) {
         let (_, provided_methods) =
             split_trait_methods(*trait_methods);
         let (bounds, _) = mk_substs(ccx, generics, rp);
-        let _ = convert_methods(ccx, provided_methods, rp, bounds, generics);
+        let _ = convert_methods(ccx, provided_methods, rp, bounds, generics,
+                                it.vis);
       }
       ast::item_struct(struct_def, ref generics) => {
         ensure_no_ty_param_bounds(ccx, it.span, generics, "structure");
@@ -794,30 +833,6 @@ pub fn convert_foreign(ccx: &CrateCtxt, i: @ast::foreign_item) {
     ccx.tcx.tcache.insert(local_def(i.id), tpt);
 }
 
-pub fn ty_of_method(ccx: &CrateCtxt,
-                    m: @ast::method,
-                    rp: Option<ty::region_variance>,
-                    rcvr_generics: &ast::Generics,
-                    method_generics: &ast::Generics)
-                 -> ty::method {
-    let rscope = MethodRscope::new(m.self_ty.node,
-                                   rp,
-                                   rcvr_generics);
-    ty::method {
-        ident: m.ident,
-        tps: ty_param_bounds(ccx, &m.generics),
-        fty: astconv::ty_of_bare_fn(ccx,
-                                    &rscope,
-                                    m.purity,
-                                    AbiSet::Rust(),
-                                    &method_generics.lifetimes,
-                                    &m.decl),
-        self_ty: m.self_ty.node,
-        vis: m.vis,
-        def_id: local_def(m.id)
-    }
-}
-
 /*
   Instantiates the path for the given trait reference, assuming that
   it's bound to a valid trait type. Returns the def_id for the defining
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 31dc476cbe4..4a0e58b09c8 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1186,6 +1186,15 @@ pub struct trait_ref {
 #[deriving(Eq)]
 pub enum visibility { public, private, inherited }
 
+impl visibility {
+    fn inherit_from(&self, parent_visibility: visibility) -> visibility {
+        match self {
+            &inherited => parent_visibility,
+            &public | &private => *self
+        }
+    }
+}
+
 #[auto_encode]
 #[auto_decode]
 #[deriving(Eq)]