about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-06-03 17:51:32 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-07-06 23:50:02 +0300
commit08a1d45818d022095d597919aa0d50ee7be2a0c6 (patch)
tree2e28223d18da10b973c4b4e8ebe78ad8fefef104
parent85fb9e0d9103326b353da46b7171d90841f4e940 (diff)
downloadrust-08a1d45818d022095d597919aa0d50ee7be2a0c6.tar.gz
rust-08a1d45818d022095d597919aa0d50ee7be2a0c6.zip
Check adjustments and node substs
Cleanup checking of inherent static methods and fix checking of inherent associated constants
Add more tests
-rw-r--r--src/librustc_privacy/lib.rs72
-rw-r--r--src/test/compile-fail/auxiliary/private-inferred-type.rs5
-rw-r--r--src/test/compile-fail/private-inferred-type-3.rs2
-rw-r--r--src/test/compile-fail/private-inferred-type.rs66
-rw-r--r--src/test/compile-fail/private-type-in-interface.rs4
5 files changed, 113 insertions, 36 deletions
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index bce7943b305..54f693a5a81 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -591,12 +591,23 @@ impl<'a, 'tcx> TypePrivacyVisitor<'a, 'tcx> {
     }
 
     fn check_expr_pat_type(&mut self, id: ast::NodeId, span: Span) -> bool {
+        self.span = span;
         if let Some(ty) = self.tables.node_id_to_type_opt(id) {
-            self.span = span;
-            ty.visit_with(self)
-        } else {
-            false
+            if ty.visit_with(self) {
+                return true;
+            }
+        }
+        if self.tables.node_substs(id).visit_with(self) {
+            return true;
         }
+        if let Some(adjustments) = self.tables.adjustments.get(&id) {
+            for adjustment in adjustments {
+                if adjustment.target.visit_with(self) {
+                    return true;
+                }
+            }
+        }
+        false
     }
 
     fn check_item(&mut self, item_id: ast::NodeId) -> &mut Self {
@@ -660,11 +671,10 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
             }
             hir::ExprMethodCall(name, ..) => {
                 // Method calls have to be checked specially.
-                if let Some(method) = self.tables.method_map.get(&ty::MethodCall::expr(expr.id)) {
-                    self.span = name.span;
-                    if method.ty.visit_with(self) || method.substs.visit_with(self) {
-                        return;
-                    }
+                let def_id = self.tables.type_dependent_defs[&expr.id].def_id();
+                self.span = name.span;
+                if self.tcx.type_of(def_id).visit_with(self) {
+                    return;
                 }
             }
             _ => {}
@@ -673,6 +683,24 @@ impl<'a, 'tcx> Visitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
         intravisit::walk_expr(self, expr);
     }
 
+    fn visit_qpath(&mut self, qpath: &'tcx hir::QPath, id: ast::NodeId, span: Span) {
+        // Inherent associated constants don't have self type in substs,
+        // we have to check it additionally.
+        if let hir::QPath::TypeRelative(..) = *qpath {
+            if let Some(def) = self.tables.type_dependent_defs.get(&id).cloned() {
+                if let Some(assoc_item) = self.tcx.opt_associated_item(def.def_id()) {
+                    if let ty::ImplContainer(impl_def_id) = assoc_item.container {
+                        if self.tcx.type_of(impl_def_id).visit_with(self) {
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+
+        intravisit::walk_qpath(self, qpath, id, span);
+    }
+
     // Check types of patterns
     fn visit_pat(&mut self, pattern: &'tcx hir::Pat) {
         if self.check_expr_pat_type(pattern.id, pattern.span) {
@@ -769,25 +797,11 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
                     self.tcx.sess.span_err(self.span, &msg);
                     return true;
                 }
-                if let ty::TyFnDef(..) = ty.sty {
-                    // Inherent static methods don't have self type in substs,
-                    // we have to check it additionally.
-                    let mut impl_def_id = None;
-                    if let Some(node_id) = self.tcx.hir.as_local_node_id(def_id) {
-                        if let hir::map::NodeImplItem(..) = self.tcx.hir.get(node_id) {
-                            impl_def_id = Some(self.tcx.hir.get_parent_did(node_id));
-                        }
-                    } else if let Some(Def::Method(..)) = self.tcx.describe_def(def_id) {
-                        let candidate_impl_def_id = self.tcx.parent_def_id(def_id)
-                                                            .expect("no parent for method def_id");
-                        // `is_none` means it's an impl, not a trait
-                        if self.tcx.describe_def(candidate_impl_def_id).is_none() {
-                            impl_def_id = Some(candidate_impl_def_id)
-                        }
-                    }
-                    if let Some(impl_def_id) = impl_def_id {
-                        let self_ty = self.tcx.type_of(impl_def_id);
-                        if self_ty.visit_with(self) {
+                // Inherent static methods don't have self type in substs,
+                // we have to check it additionally.
+                if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) {
+                    if let ty::ImplContainer(impl_def_id) = assoc_item.container {
+                        if self.tcx.type_of(impl_def_id).visit_with(self) {
                             return true;
                         }
                     }
@@ -829,7 +843,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for TypePrivacyVisitor<'a, 'tcx> {
                             self.tcx.sess.span_err(self.span, &msg);
                             return true;
                         }
-                        // Skip `Self` to avoid infinite recursion
+                        // `Self` here is the same `TyAnon`, so skip it to avoid infinite recursion
                         for subst in trait_ref.substs.iter().skip(1) {
                             if subst.visit_with(self) {
                                 return true;
diff --git a/src/test/compile-fail/auxiliary/private-inferred-type.rs b/src/test/compile-fail/auxiliary/private-inferred-type.rs
index 1230ae8f84a..28bf9e08157 100644
--- a/src/test/compile-fail/auxiliary/private-inferred-type.rs
+++ b/src/test/compile-fail/auxiliary/private-inferred-type.rs
@@ -28,6 +28,9 @@ pub struct Pub<T = Alias>(pub T);
 impl Pub<Priv> {
     pub fn static_method() {}
 }
+impl Pub<u8> {
+    fn priv_metod(&self) {}
+}
 
 pub macro m() {
     priv_fn;
@@ -37,5 +40,5 @@ pub macro m() {
     <u8 as PubTrait>::method;
     PrivTupleStruct;
     PubTupleStruct;
-    Pub::static_method;
+    Pub(0u8).priv_metod();
 }
diff --git a/src/test/compile-fail/private-inferred-type-3.rs b/src/test/compile-fail/private-inferred-type-3.rs
index fb9357f9373..438dd5e1933 100644
--- a/src/test/compile-fail/private-inferred-type-3.rs
+++ b/src/test/compile-fail/private-inferred-type-3.rs
@@ -15,7 +15,7 @@
 // error-pattern:type `fn() {<u8 as ext::PrivTrait>::method}` is private
 // error-pattern:type `fn(u8) -> ext::PrivTupleStruct {ext::PrivTupleStruct::{{constructor}}}` is pr
 // error-pattern:type `fn(u8) -> ext::PubTupleStruct {ext::PubTupleStruct::{{constructor}}}` is priv
-// error-pattern:type `ext::Priv` is private
+// error-pattern:type `fn(&ext::Pub<u8>) {<ext::Pub<u8>>::priv_metod}` is private
 
 #![feature(decl_macro)]
 
diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs
index 6f39872ecf6..c00bfe5e574 100644
--- a/src/test/compile-fail/private-inferred-type.rs
+++ b/src/test/compile-fail/private-inferred-type.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+#![feature(associated_consts)]
 #![feature(conservative_impl_trait)]
 #![feature(decl_macro)]
 
@@ -29,7 +30,19 @@ mod m {
 
     impl Pub<Priv> {
         pub fn static_method() {}
+        pub const INHERENT_ASSOC_CONST: u8 = 0;
     }
+    impl<T> Pub<T> {
+        pub fn static_method_generic_self() {}
+        pub const INHERENT_ASSOC_CONST_GENERIC_SELF: u8 = 0;
+    }
+    impl Pub<u8> {
+        fn priv_metod(&self) {}
+        pub fn method_with_substs<T>(&self) {}
+        pub fn method_with_priv_params(&self, _: Priv) {}
+    }
+    impl TraitWithAssocConst for Priv {}
+    impl TraitWithAssocTy for Priv { type AssocTy = u8; }
 
     pub macro m() {
         priv_fn; //~ ERROR type `fn() {m::priv_fn}` is private
@@ -41,28 +54,71 @@ mod m {
         //~^ ERROR type `fn(u8) -> m::PrivTupleStruct {m::PrivTupleStruct::{{constructor}}}` is priv
         PubTupleStruct;
         //~^ ERROR type `fn(u8) -> m::PubTupleStruct {m::PubTupleStruct::{{constructor}}}` is privat
-        Pub::static_method; //~ ERROR type `m::Priv` is private
+        Pub(0u8).priv_metod();
+        //~^ ERROR type `fn(&m::Pub<u8>) {<m::Pub<u8>>::priv_metod}` is private
     }
 
     trait Trait {}
     pub trait TraitWithTyParam<T> {}
-    pub trait TraitWithAssocTy { type X; }
+    pub trait TraitWithTyParam2<T> { fn pub_method() {} }
+    pub trait TraitWithAssocTy { type AssocTy; }
+    pub trait TraitWithAssocConst { const TRAIT_ASSOC_CONST: u8 = 0; }
     impl Trait for u8 {}
     impl<T> TraitWithTyParam<T> for u8 {}
-    impl TraitWithAssocTy for u8 { type X = Priv; }
+    impl TraitWithTyParam2<Priv> for u8 {}
+    impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
 
     pub fn leak_anon1() -> impl Trait + 'static { 0 }
     pub fn leak_anon2() -> impl TraitWithTyParam<Alias> { 0 }
-    pub fn leak_anon3() -> impl TraitWithAssocTy<X = Alias> { 0 }
+    pub fn leak_anon3() -> impl TraitWithAssocTy<AssocTy = Alias> { 0 }
 
     pub fn leak_dyn1() -> Box<Trait + 'static> { Box::new(0) }
     pub fn leak_dyn2() -> Box<TraitWithTyParam<Alias>> { Box::new(0) }
-    pub fn leak_dyn3() -> Box<TraitWithAssocTy<X = Alias>> { Box::new(0) }
+    pub fn leak_dyn3() -> Box<TraitWithAssocTy<AssocTy = Alias>> { Box::new(0) }
+}
+
+mod adjust {
+    // Construct a chain of derefs with a private type in the middle
+    use std::ops::Deref;
+
+    pub struct S1;
+    struct S2;
+    pub type S2Alias = S2;
+    pub struct S3;
+
+    impl Deref for S1 {
+        type Target = S2Alias;
+        fn deref(&self) -> &Self::Target { loop {} }
+    }
+    impl Deref for S2 {
+        type Target = S3;
+        fn deref(&self) -> &Self::Target { loop {} }
+    }
+
+    impl S3 {
+        pub fn method_s3(&self) {}
+    }
 }
 
 fn main() {
+    let _: m::Alias; //~ ERROR type `m::Priv` is private
+    let _: <m::Alias as m::TraitWithAssocTy>::AssocTy; // FIXME
     m::Alias {}; //~ ERROR type `m::Priv` is private
     m::Pub { 0: m::Alias {} }; //~ ERROR type `m::Priv` is private
+    m::Pub { 0: loop {} }; // FIXME
+    m::Pub::static_method; //~ ERROR type `m::Priv` is private
+    m::Pub::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
+    m::Pub(0u8).method_with_substs::<m::Alias>(); //~ ERROR type `m::Priv` is private
+    m::Pub(0u8).method_with_priv_params(loop{}); //~ ERROR type `m::Priv` is private
+    <m::Alias as m::TraitWithAssocConst>::TRAIT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
+    <m::Pub<m::Alias>>::INHERENT_ASSOC_CONST; //~ ERROR type `m::Priv` is private
+    <m::Pub<m::Alias>>::INHERENT_ASSOC_CONST_GENERIC_SELF; //~ ERROR type `m::Priv` is private
+    <m::Pub<m::Alias>>::static_method_generic_self; //~ ERROR type `m::Priv` is private
+    use m::TraitWithTyParam2;
+    u8::pub_method; //~ ERROR type `m::Priv` is private
+
+    adjust::S1.method_s3(); //~ ERROR type `adjust::S2` is private
+
     m::m!();
 
     m::leak_anon1(); //~ ERROR trait `m::Trait` is private
diff --git a/src/test/compile-fail/private-type-in-interface.rs b/src/test/compile-fail/private-type-in-interface.rs
index e4b52895c14..925d692f8ae 100644
--- a/src/test/compile-fail/private-type-in-interface.rs
+++ b/src/test/compile-fail/private-type-in-interface.rs
@@ -17,6 +17,9 @@ extern crate private_inferred_type as ext;
 mod m {
     struct Priv;
     pub type Alias = Priv;
+
+    pub trait Trait { type X; }
+    impl Trait for Priv { type X = u8; }
 }
 
 fn f(_: m::Alias) {} //~ ERROR type `m::Priv` is private
@@ -28,6 +31,7 @@ trait Tr1 {}
 impl m::Alias {} //~ ERROR type `m::Priv` is private
 impl Tr1 for ext::Alias {} //~ ERROR type `ext::Priv` is private
                            //~^ ERROR type `ext::Priv` is private
+type A = <m::Alias as m::Trait>::X; //~ ERROR type `m::Priv` is private
 
 trait Tr2<T> {}
 impl<T> Tr2<T> for u8 {}