about summary refs log tree commit diff
diff options
context:
space:
mode:
authorVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-11-18 20:32:24 +0300
committerVadim Petrochenkov <vadim.petrochenkov@gmail.com>2017-12-21 03:19:05 +0300
commitc6209a36bbef743a25f3823e1ab387080a4f307c (patch)
tree2fff1817e8565a5f8ef3c29a783198eebcee1d8a
parent020961d88027faf901c533634f07bb5bf3bb64d3 (diff)
downloadrust-c6209a36bbef743a25f3823e1ab387080a4f307c.tar.gz
rust-c6209a36bbef743a25f3823e1ab387080a4f307c.zip
Always report private-in-public in associated types as hard errors
according to RFC 2145.

Fix a silly label message.
-rw-r--r--src/librustc_privacy/lib.rs21
-rw-r--r--src/test/compile-fail/E0445.rs3
-rw-r--r--src/test/compile-fail/issue-30079.rs7
-rw-r--r--src/test/compile-fail/private-in-public-assoc-ty.rs43
-rw-r--r--src/test/compile-fail/private-in-public-ill-formed.rs45
-rw-r--r--src/test/compile-fail/private-in-public-warn.rs15
-rw-r--r--src/test/compile-fail/private-inferred-type.rs5
7 files changed, 108 insertions, 31 deletions
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index fc2e2ca6620..5b277402f1e 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -1313,6 +1313,7 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
     min_visibility: ty::Visibility,
     has_pub_restricted: bool,
     has_old_errors: bool,
+    in_assoc_ty: bool,
 }
 
 impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
@@ -1373,11 +1374,11 @@ impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
                 self.min_visibility = vis;
             }
             if !vis.is_at_least(self.required_visibility, self.tcx) {
-                if self.has_pub_restricted || self.has_old_errors {
+                if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty {
                     struct_span_err!(self.tcx.sess, self.span, E0445,
                                      "private trait `{}` in public interface", trait_ref)
                         .span_label(self.span, format!(
-                                    "private trait can't be public"))
+                                    "can't leak private trait"))
                         .emit();
                 } else {
                     self.tcx.lint_node(lint::builtin::PRIVATE_IN_PUBLIC,
@@ -1428,7 +1429,7 @@ impl<'a, 'tcx: 'a> TypeVisitor<'tcx> for SearchInterfaceForPrivateItemsVisitor<'
                     self.min_visibility = vis;
                 }
                 if !vis.is_at_least(self.required_visibility, self.tcx) {
-                    if self.has_pub_restricted || self.has_old_errors {
+                    if self.has_pub_restricted || self.has_old_errors || self.in_assoc_ty {
                         let mut err = struct_span_err!(self.tcx.sess, self.span, E0446,
                             "private type `{}` in public interface", ty);
                         err.span_label(self.span, "can't leak private type");
@@ -1489,6 +1490,7 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
             required_visibility,
             has_pub_restricted: self.has_pub_restricted,
             has_old_errors,
+            in_assoc_ty: false,
         }
     }
 }
@@ -1529,6 +1531,7 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
 
                 for trait_item_ref in trait_item_refs {
                     let mut check = self.check(trait_item_ref.id.node_id, item_visibility);
+                    check.in_assoc_ty = trait_item_ref.kind == hir::AssociatedItemKind::Type;
                     check.generics().predicates();
 
                     if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
@@ -1579,10 +1582,10 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
 
                 for impl_item_ref in impl_item_refs {
                     let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
-                    let impl_item_vis =
-                        ty::Visibility::from_hir(&impl_item.vis, item.id, tcx);
-                    self.check(impl_item.id, min(impl_item_vis, ty_vis))
-                        .generics().predicates().ty();
+                    let impl_item_vis = ty::Visibility::from_hir(&impl_item.vis, item.id, tcx);
+                    let mut check = self.check(impl_item.id, min(impl_item_vis, ty_vis));
+                    check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
+                    check.generics().predicates().ty();
 
                     // Recurse for e.g. `impl Trait` (see `visit_ty`).
                     self.inner_visibility = impl_item_vis;
@@ -1597,7 +1600,9 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
                 self.check(item.id, vis).generics().predicates();
                 for impl_item_ref in impl_item_refs {
                     let impl_item = self.tcx.hir.impl_item(impl_item_ref.id);
-                    self.check(impl_item.id, vis).generics().predicates().ty();
+                    let mut check = self.check(impl_item.id, vis);
+                    check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
+                    check.generics().predicates().ty();
 
                     // Recurse for e.g. `impl Trait` (see `visit_ty`).
                     self.inner_visibility = vis;
diff --git a/src/test/compile-fail/E0445.rs b/src/test/compile-fail/E0445.rs
index a1447e7ebcd..bca1b52d17a 100644
--- a/src/test/compile-fail/E0445.rs
+++ b/src/test/compile-fail/E0445.rs
@@ -14,9 +14,12 @@ trait Foo {
 
 pub trait Bar : Foo {}
 //~^ ERROR private trait `Foo` in public interface [E0445]
+//~| NOTE can't leak private trait
 pub struct Bar2<T: Foo>(pub T);
 //~^ ERROR private trait `Foo` in public interface [E0445]
+//~| NOTE can't leak private trait
 pub fn foo<T: Foo> (t: T) {}
 //~^ ERROR private trait `Foo` in public interface [E0445]
+//~| NOTE can't leak private trait
 
 fn main() {}
diff --git a/src/test/compile-fail/issue-30079.rs b/src/test/compile-fail/issue-30079.rs
index 15b7edb32d4..04ae8f6d255 100644
--- a/src/test/compile-fail/issue-30079.rs
+++ b/src/test/compile-fail/issue-30079.rs
@@ -8,15 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![deny(private_in_public)]
-#![allow(unused)]
-
 struct SemiPriv;
 
 mod m1 {
     struct Priv;
     impl ::SemiPriv {
-        pub fn f(_: Priv) {} //~ ERROR private type `m1::Priv` in public interface
+        pub fn f(_: Priv) {} //~ WARN private type `m1::Priv` in public interface
         //~^ WARNING hard error
     }
 
@@ -29,7 +26,6 @@ mod m2 {
     struct Priv;
     impl ::std::ops::Deref for ::SemiPriv {
         type Target = Priv; //~ ERROR private type `m2::Priv` in public interface
-        //~^ WARNING hard error
         fn deref(&self) -> &Self::Target { unimplemented!() }
     }
 
@@ -47,7 +43,6 @@ mod m3 {
     struct Priv;
     impl ::SemiPrivTrait for () {
         type Assoc = Priv; //~ ERROR private type `m3::Priv` in public interface
-        //~^ WARNING hard error
     }
 }
 
diff --git a/src/test/compile-fail/private-in-public-assoc-ty.rs b/src/test/compile-fail/private-in-public-assoc-ty.rs
new file mode 100644
index 00000000000..59dee256642
--- /dev/null
+++ b/src/test/compile-fail/private-in-public-assoc-ty.rs
@@ -0,0 +1,43 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Private types and traits are not allowed in interfaces of associated types.
+// This test also ensures that the checks are performed even inside private modules.
+
+#![feature(associated_type_defaults)]
+
+mod m {
+    struct Priv;
+    trait PrivTr {}
+    impl PrivTr for Priv {}
+    pub trait PubTrAux1<T> {}
+    pub trait PubTrAux2 { type A; }
+
+    // "Private-in-public in associated types is hard error" in RFC 2145
+    // applies only to the aliased types, not bounds.
+    pub trait PubTr {
+        //~^ WARN private trait `m::PrivTr` in public interface
+        //~| WARN this was previously accepted
+        //~| WARN private type `m::Priv` in public interface
+        //~| WARN this was previously accepted
+        type Alias1: PrivTr;
+        type Alias2: PubTrAux1<Priv> = u8;
+        type Alias3: PubTrAux2<A = Priv> = u8;
+
+        type Alias4 = Priv;
+        //~^ ERROR private type `m::Priv` in public interface
+    }
+    impl PubTr for u8 {
+        type Alias1 = Priv;
+        //~^ ERROR private type `m::Priv` in public interface
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/private-in-public-ill-formed.rs b/src/test/compile-fail/private-in-public-ill-formed.rs
new file mode 100644
index 00000000000..4e10614bf62
--- /dev/null
+++ b/src/test/compile-fail/private-in-public-ill-formed.rs
@@ -0,0 +1,45 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod aliases_pub {
+    struct Priv;
+    mod m {
+        pub struct Pub3;
+    }
+
+    trait PrivTr {
+        type AssocAlias;
+    }
+    impl PrivTr for Priv {
+        type AssocAlias = m::Pub3;
+    }
+
+    impl (<Priv as PrivTr>::AssocAlias) { //~ ERROR no base type found for inherent implementation
+        pub fn f(arg: Priv) {} // private type `aliases_pub::Priv` in public interface
+    }
+}
+
+mod aliases_priv {
+    struct Priv;
+    struct Priv3;
+
+    trait PrivTr {
+        type AssocAlias;
+    }
+    impl PrivTr for Priv {
+        type AssocAlias = Priv3;
+    }
+
+    impl (<Priv as PrivTr>::AssocAlias) { //~ ERROR no base type found for inherent implementation
+        pub fn f(arg: Priv) {} // OK
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/private-in-public-warn.rs b/src/test/compile-fail/private-in-public-warn.rs
index f030012b172..dfcf4dc01b8 100644
--- a/src/test/compile-fail/private-in-public-warn.rs
+++ b/src/test/compile-fail/private-in-public-warn.rs
@@ -13,7 +13,6 @@
 
 #![feature(associated_type_defaults)]
 #![deny(private_in_public)]
-#![allow(unused)]
 #![allow(improper_ctypes)]
 
 mod types {
@@ -35,7 +34,6 @@ mod types {
         const C: Priv = Priv; //~ ERROR private type `types::Priv` in public interface
         //~^ WARNING hard error
         type Alias = Priv; //~ ERROR private type `types::Priv` in public interface
-        //~^ WARNING hard error
         fn f1(arg: Priv) {} //~ ERROR private type `types::Priv` in public interface
         //~^ WARNING hard error
         fn f2() -> Priv { panic!() } //~ ERROR private type `types::Priv` in public interface
@@ -51,7 +49,6 @@ mod types {
     }
     impl PubTr for Pub {
         type Alias = Priv; //~ ERROR private type `types::Priv` in public interface
-        //~^ WARNING hard error
     }
 }
 
@@ -146,7 +143,6 @@ mod impls {
     }
     impl PubTr for Pub {
         type Alias = Priv; //~ ERROR private type `impls::Priv` in public interface
-        //~^ WARNING hard error
     }
 }
 
@@ -220,21 +216,14 @@ mod aliases_pub {
         pub fn f(arg: Priv) {} //~ ERROR private type `aliases_pub::Priv` in public interface
         //~^ WARNING hard error
     }
-    // This doesn't even parse
-    // impl <Priv as PrivTr>::AssocAlias {
-    //     pub fn f(arg: Priv) {} // ERROR private type `aliases_pub::Priv` in public interface
-    // }
     impl PrivUseAliasTr for PrivUseAlias {
         type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
-        //~^ WARNING hard error
     }
     impl PrivUseAliasTr for PrivAlias {
         type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
-        //~^ WARNING hard error
     }
     impl PrivUseAliasTr for <Priv as PrivTr>::AssocAlias {
         type Check = Priv; //~ ERROR private type `aliases_pub::Priv` in public interface
-        //~^ WARNING hard error
     }
 }
 
@@ -273,10 +262,6 @@ mod aliases_priv {
     impl PrivAlias {
         pub fn f(arg: Priv) {} // OK
     }
-    // This doesn't even parse
-    // impl <Priv as PrivTr>::AssocAlias {
-    //     pub fn f(arg: Priv) {} // OK
-    // }
     impl PrivUseAliasTr for PrivUseAlias {
         type Check = Priv; // OK
     }
diff --git a/src/test/compile-fail/private-inferred-type.rs b/src/test/compile-fail/private-inferred-type.rs
index c50d7f59b8e..351dc6b776b 100644
--- a/src/test/compile-fail/private-inferred-type.rs
+++ b/src/test/compile-fail/private-inferred-type.rs
@@ -11,7 +11,7 @@
 #![feature(associated_consts)]
 #![feature(conservative_impl_trait)]
 #![feature(decl_macro)]
-#![allow(warnings)]
+#![allow(private_in_public)]
 
 mod m {
     fn priv_fn() {}
@@ -70,6 +70,7 @@ mod m {
     impl<T> TraitWithTyParam<T> for u8 {}
     impl TraitWithTyParam2<Priv> for u8 {}
     impl TraitWithAssocTy for u8 { type AssocTy = Priv; }
+    //~^ ERROR private type `m::Priv` in public interface
 
     pub fn leak_anon1() -> impl Trait + 'static { 0 }
     pub fn leak_anon2() -> impl TraitWithTyParam<Alias> { 0 }
@@ -90,7 +91,7 @@ mod adjust {
     pub struct S3;
 
     impl Deref for S1 {
-        type Target = S2Alias;
+        type Target = S2Alias; //~ ERROR private type `adjust::S2` in public interface
         fn deref(&self) -> &Self::Target { loop {} }
     }
     impl Deref for S2 {