diff --git a/compiler/rustc_ty_utils/src/sig_types.rs b/compiler/rustc_ty_utils/src/sig_types.rs index 63654a453ddee..19c092c5ddf3f 100644 --- a/compiler/rustc_ty_utils/src/sig_types.rs +++ b/compiler/rustc_ty_utils/src/sig_types.rs @@ -13,6 +13,7 @@ pub trait SpannedTypeVisitor<'tcx> { fn visit(&mut self, span: Span, value: impl TypeVisitable>) -> Self::Result; } +#[instrument(level = "trace", skip(tcx, visitor))] pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( tcx: TyCtxt<'tcx>, item: LocalDefId, @@ -36,7 +37,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( for (hir, ty) in hir_sig.inputs.iter().zip(ty_sig.inputs().iter()) { try_visit!(visitor.visit(hir.span, ty.map_bound(|x| *x))); } - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { + for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred)); } } @@ -54,7 +55,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( // Associated types in traits don't necessarily have a type that we can visit try_visit!(visitor.visit(ty.span, tcx.type_of(item).instantiate_identity())); } - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { + for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred)); } } @@ -76,7 +77,7 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( let ty = field.ty(tcx, args); try_visit!(visitor.visit(span, ty)); } - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { + for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred)); } } @@ -95,12 +96,12 @@ pub fn walk_types<'tcx, V: SpannedTypeVisitor<'tcx>>( _ => tcx.def_span(item), }; try_visit!(visitor.visit(span, tcx.type_of(item).instantiate_identity())); - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { + for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred)); } } DefKind::TraitAlias | DefKind::Trait => { - for (pred, span) in tcx.predicates_of(item).instantiate_identity(tcx) { + for (pred, span) in tcx.explicit_predicates_of(item).instantiate_identity(tcx) { try_visit!(visitor.visit(span, pred)); } } diff --git a/tests/ui/privacy/generic_struct_field_projection.rs b/tests/ui/privacy/generic_struct_field_projection.rs new file mode 100644 index 0000000000000..c5bb1233c27b9 --- /dev/null +++ b/tests/ui/privacy/generic_struct_field_projection.rs @@ -0,0 +1,38 @@ +//! To determine all the types that need to be private when looking at `Struct`, we +//! used to invoke `predicates_of` to also look at types in `where` bounds. +//! Unfortunately this also computes the inferred outlives bounds, which means for +//! every field we check that if it is of type `&'a T` then `T: 'a` and if it is of +//! struct type, we check that the struct satisfies its lifetime parameters by looking +//! at its inferred outlives bounds. This means we end up with a `::Assoc: 'a` +//! in the outlives bounds of `Struct`. While this is trivially provable, privacy +//! only sees `Foo` and `Trait` and determines that `Foo` is private and then errors. +//! So now we invoke `explicit_predicates_of` to make sure we only care about user-written +//! predicates. + +//@ check-pass + +mod baz { + struct Foo; + + pub trait Trait { + type Assoc; + } + + impl Trait for Foo { + type Assoc = (); + } + + pub struct Bar<'a, T: Trait> { + source: &'a T::Assoc, + } + + pub struct Baz<'a> { + mode: Bar<'a, Foo>, + } +} + +pub struct Struct<'a> { + lexer: baz::Baz<'a>, +} + +fn main() {}