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(pub T); //~^ ERROR private trait `Foo` in public interface [E0445] +//~| NOTE can't leak private trait pub fn 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 or the MIT license +// , 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 {} + 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 = u8; + type Alias3: PubTrAux2 = 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 or the MIT license +// , 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 (::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 (::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 ::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 ::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 ::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 TraitWithTyParam for u8 {} impl TraitWithTyParam2 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 { 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 {