Rollup merge of #57649 - petrochenkov:privexist, r=arielb1
privacy: Account for associated existential types Turns out they *can* be associated (but only in impls, not traits). Fixes https://github.com/rust-lang/rust/issues/53546#issuecomment-454372879 r? @arielb1
This commit is contained in:
commit
4eeb095437
@ -13,7 +13,7 @@ extern crate rustc_typeck;
|
|||||||
extern crate syntax_pos;
|
extern crate syntax_pos;
|
||||||
extern crate rustc_data_structures;
|
extern crate rustc_data_structures;
|
||||||
|
|
||||||
use rustc::hir::{self, Node, PatKind};
|
use rustc::hir::{self, Node, PatKind, AssociatedItemKind};
|
||||||
use rustc::hir::def::Def;
|
use rustc::hir::def::Def;
|
||||||
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
|
use rustc::hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE, CrateNum, DefId};
|
||||||
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
|
||||||
@ -548,7 +548,7 @@ impl<'a, 'tcx> Visitor<'tcx> for EmbargoVisitor<'a, 'tcx> {
|
|||||||
let mut reach = self.reach(trait_item_ref.id.node_id, item_level);
|
let mut reach = self.reach(trait_item_ref.id.node_id, item_level);
|
||||||
reach.generics().predicates();
|
reach.generics().predicates();
|
||||||
|
|
||||||
if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
|
if trait_item_ref.kind == AssociatedItemKind::Type &&
|
||||||
!trait_item_ref.defaultness.has_value() {
|
!trait_item_ref.defaultness.has_value() {
|
||||||
// No type to visit.
|
// No type to visit.
|
||||||
} else {
|
} else {
|
||||||
@ -1343,11 +1343,11 @@ impl<'a, 'tcx> Visitor<'tcx> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx> {
|
|||||||
if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) {
|
if self.item_is_public(&impl_item_ref.id.node_id, &impl_item_ref.vis) {
|
||||||
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
|
let impl_item = self.tcx.hir().impl_item(impl_item_ref.id);
|
||||||
match impl_item_ref.kind {
|
match impl_item_ref.kind {
|
||||||
hir::AssociatedItemKind::Const => {
|
AssociatedItemKind::Const => {
|
||||||
found_pub_static = true;
|
found_pub_static = true;
|
||||||
intravisit::walk_impl_item(self, impl_item);
|
intravisit::walk_impl_item(self, impl_item);
|
||||||
}
|
}
|
||||||
hir::AssociatedItemKind::Method { has_self: false } => {
|
AssociatedItemKind::Method { has_self: false } => {
|
||||||
found_pub_static = true;
|
found_pub_static = true;
|
||||||
intravisit::walk_impl_item(self, impl_item);
|
intravisit::walk_impl_item(self, impl_item);
|
||||||
}
|
}
|
||||||
@ -1568,6 +1568,24 @@ impl<'a, 'tcx> PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
|
|||||||
in_assoc_ty: false,
|
in_assoc_ty: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_trait_or_impl_item(&self, node_id: ast::NodeId, assoc_item_kind: AssociatedItemKind,
|
||||||
|
defaultness: hir::Defaultness, vis: ty::Visibility) {
|
||||||
|
let mut check = self.check(node_id, vis);
|
||||||
|
|
||||||
|
let (check_ty, is_assoc_ty) = match assoc_item_kind {
|
||||||
|
AssociatedItemKind::Const | AssociatedItemKind::Method { .. } => (true, false),
|
||||||
|
AssociatedItemKind::Type => (defaultness.has_value(), true),
|
||||||
|
// `ty()` for existential types is the underlying type,
|
||||||
|
// it's not a part of interface, so we skip it.
|
||||||
|
AssociatedItemKind::Existential => (false, true),
|
||||||
|
};
|
||||||
|
check.in_assoc_ty = is_assoc_ty;
|
||||||
|
check.generics().predicates();
|
||||||
|
if check_ty {
|
||||||
|
check.ty();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
|
impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx> {
|
||||||
@ -1602,16 +1620,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
|
|||||||
self.check(item.id, item_visibility).generics().predicates();
|
self.check(item.id, item_visibility).generics().predicates();
|
||||||
|
|
||||||
for trait_item_ref in trait_item_refs {
|
for trait_item_ref in trait_item_refs {
|
||||||
let mut check = self.check(trait_item_ref.id.node_id, item_visibility);
|
self.check_trait_or_impl_item(trait_item_ref.id.node_id, trait_item_ref.kind,
|
||||||
check.in_assoc_ty = trait_item_ref.kind == hir::AssociatedItemKind::Type;
|
trait_item_ref.defaultness, item_visibility);
|
||||||
check.generics().predicates();
|
|
||||||
|
|
||||||
if trait_item_ref.kind == hir::AssociatedItemKind::Type &&
|
|
||||||
!trait_item_ref.defaultness.has_value() {
|
|
||||||
// No type to visit.
|
|
||||||
} else {
|
|
||||||
check.ty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ItemKind::TraitAlias(..) => {
|
hir::ItemKind::TraitAlias(..) => {
|
||||||
@ -1657,9 +1667,8 @@ impl<'a, 'tcx> Visitor<'tcx> for PrivateItemsInPublicInterfacesVisitor<'a, 'tcx>
|
|||||||
} else {
|
} else {
|
||||||
impl_vis
|
impl_vis
|
||||||
};
|
};
|
||||||
let mut check = self.check(impl_item.id, impl_item_vis);
|
self.check_trait_or_impl_item(impl_item_ref.id.node_id, impl_item_ref.kind,
|
||||||
check.in_assoc_ty = impl_item_ref.kind == hir::AssociatedItemKind::Type;
|
impl_item_ref.defaultness, impl_item_vis);
|
||||||
check.generics().predicates().ty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
// Private types and traits are not allowed in interfaces of associated types.
|
// 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.
|
// This test also ensures that the checks are performed even inside private modules.
|
||||||
|
|
||||||
#![feature(associated_type_defaults)]
|
#![feature(associated_type_defaults, existential_type)]
|
||||||
|
|
||||||
mod m {
|
mod m {
|
||||||
struct Priv;
|
struct Priv;
|
||||||
@ -23,10 +23,17 @@ mod m {
|
|||||||
|
|
||||||
type Alias4 = Priv;
|
type Alias4 = Priv;
|
||||||
//~^ ERROR private type `m::Priv` in public interface
|
//~^ ERROR private type `m::Priv` in public interface
|
||||||
|
|
||||||
|
type Exist;
|
||||||
|
fn infer_exist() -> Self::Exist;
|
||||||
}
|
}
|
||||||
impl PubTr for u8 {
|
impl PubTr for u8 {
|
||||||
type Alias1 = Priv;
|
type Alias1 = Priv;
|
||||||
//~^ ERROR private type `m::Priv` in public interface
|
//~^ ERROR private type `m::Priv` in public interface
|
||||||
|
|
||||||
|
existential type Exist: PrivTr;
|
||||||
|
//~^ ERROR private trait `m::PrivTr` in public interface
|
||||||
|
fn infer_exist() -> Self::Exist { Priv }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ LL | | //~^ WARN private trait `m::PrivTr` in public interface
|
|||||||
LL | | //~| WARN this was previously accepted
|
LL | | //~| WARN this was previously accepted
|
||||||
LL | | //~| WARN private type `m::Priv` in public interface
|
LL | | //~| WARN private type `m::Priv` in public interface
|
||||||
... |
|
... |
|
||||||
LL | | //~^ ERROR private type `m::Priv` in public interface
|
LL | | fn infer_exist() -> Self::Exist;
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
@ -22,7 +22,7 @@ LL | | //~^ WARN private trait `m::PrivTr` in public interface
|
|||||||
LL | | //~| WARN this was previously accepted
|
LL | | //~| WARN this was previously accepted
|
||||||
LL | | //~| WARN private type `m::Priv` in public interface
|
LL | | //~| WARN private type `m::Priv` in public interface
|
||||||
... |
|
... |
|
||||||
LL | | //~^ ERROR private type `m::Priv` in public interface
|
LL | | fn infer_exist() -> Self::Exist;
|
||||||
LL | | }
|
LL | | }
|
||||||
| |_____^
|
| |_____^
|
||||||
|
|
|
|
||||||
@ -39,7 +39,7 @@ LL | type Alias4 = Priv;
|
|||||||
| ^^^^^^^^^^^^^^^^^^^ can't leak private type
|
| ^^^^^^^^^^^^^^^^^^^ can't leak private type
|
||||||
|
|
||||||
error[E0446]: private type `m::Priv` in public interface
|
error[E0446]: private type `m::Priv` in public interface
|
||||||
--> $DIR/private-in-public-assoc-ty.rs:28:9
|
--> $DIR/private-in-public-assoc-ty.rs:31:9
|
||||||
|
|
|
|
||||||
LL | struct Priv;
|
LL | struct Priv;
|
||||||
| - `m::Priv` declared as private
|
| - `m::Priv` declared as private
|
||||||
@ -47,6 +47,16 @@ LL | struct Priv;
|
|||||||
LL | type Alias1 = Priv;
|
LL | type Alias1 = Priv;
|
||||||
| ^^^^^^^^^^^^^^^^^^^ can't leak private type
|
| ^^^^^^^^^^^^^^^^^^^ can't leak private type
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error[E0445]: private trait `m::PrivTr` in public interface
|
||||||
|
--> $DIR/private-in-public-assoc-ty.rs:34:9
|
||||||
|
|
|
||||||
|
LL | trait PrivTr {}
|
||||||
|
| - `m::PrivTr` declared as private
|
||||||
|
...
|
||||||
|
LL | existential type Exist: PrivTr;
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't leak private trait
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0446`.
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
Some errors occurred: E0445, E0446.
|
||||||
|
For more information about an error, try `rustc --explain E0445`.
|
||||||
|
@ -12,4 +12,14 @@ fn check() -> Pub {
|
|||||||
Priv
|
Priv
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait Trait {
|
||||||
|
type Pub: Default;
|
||||||
|
fn method() -> Self::Pub;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Trait for u8 {
|
||||||
|
existential type Pub: Default;
|
||||||
|
fn method() -> Self::Pub { Priv }
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {}
|
fn main() {}
|
||||||
|
Loading…
Reference in New Issue
Block a user