diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 1bddbd03cc3d3..7cb2e5615b163 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -83,6 +83,7 @@ pub trait DefIdVisitor<'tcx> { DefIdVisitorSkeleton { def_id_visitor: self, visited_opaque_tys: Default::default(), + visited_trait_ref_in_projection: Default::default(), dummy: Default::default(), } } @@ -103,6 +104,7 @@ pub trait DefIdVisitor<'tcx> { pub struct DefIdVisitorSkeleton<'v, 'tcx, V: ?Sized> { def_id_visitor: &'v mut V, visited_opaque_tys: FxHashSet, + visited_trait_ref_in_projection: FxHashSet>, dummy: PhantomData>, } @@ -123,7 +125,9 @@ where fn visit_projection_term(&mut self, projection: ty::AliasTerm<'tcx>) -> V::Result { let tcx = self.def_id_visitor.tcx(); let (trait_ref, assoc_args) = projection.trait_ref_and_own_args(tcx); - try_visit!(self.visit_trait(trait_ref)); + if self.visited_trait_ref_in_projection.insert(trait_ref) { + try_visit!(self.visit_trait(trait_ref)); + } if V::SHALLOW { V::Result::output() } else { diff --git a/tests/ui/privacy/enormous-trait-ref-in-projection-term.rs b/tests/ui/privacy/enormous-trait-ref-in-projection-term.rs new file mode 100644 index 0000000000000..52ca8d2be5164 --- /dev/null +++ b/tests/ui/privacy/enormous-trait-ref-in-projection-term.rs @@ -0,0 +1,230 @@ +//@check-pass + +// issue#145741 + +use std::marker::PhantomData; + +pub struct Fn2 { + _0: PhantomData A>, + _1: PhantomData B>, + _2: PhantomData R>, +} + +impl Tag for Fn2 { + type MaskProjection = MaskToProjection< + MaskOr< + ProjectMask::MaskProjection>, + MaskOr< + ProjectMask::MaskProjection>, + MaskOr::MaskProjection>, Mask>, + >, + >, + >; +} + +// Add 1 generic (and it's part of the associated type) +pub struct Fn3 { + _0: PhantomData A>, + _1: PhantomData B>, + _2: PhantomData C>, + _3: PhantomData R>, +} + +impl Tag for Fn3 { + type MaskProjection = MaskToProjection< + MaskOr< + ProjectMask::MaskProjection>, + MaskOr< + ProjectMask::MaskProjection>, + MaskOr< + ProjectMask::MaskProjection>, + MaskOr::MaskProjection>, Mask>, + >, + >, + >, + >; +} + +pub struct TypeTuple<_0, _1, _2, _3, _4, _5>(_0, _1, _2, _3, _4, _5); + +pub trait TypeTupleAccess { + type _0; + type _1; + type _2; + type _3; + type _4; + type _5; +} + +impl<_0, _1, _2, _3, _4, _5> TypeTupleAccess for TypeTuple<_0, _1, _2, _3, _4, _5> { + type _0 = _0; + type _1 = _1; + type _2 = _2; + type _3 = _3; + type _4 = _4; + type _5 = _5; +} + +pub trait Projection: + TypeTupleAccess< + _0: SlotPicker, + _1: SlotPicker, + _2: SlotPicker, + _3: SlotPicker, + _4: SlotPicker, + _5: SlotPicker, + > +{ +} + +impl<_0, _1, _2, _3, _4, _5> Projection for TypeTuple<_0, _1, _2, _3, _4, _5> +where + _0: SlotPicker, + _1: SlotPicker, + _2: SlotPicker, + _3: SlotPicker, + _4: SlotPicker, + _5: SlotPicker, +{ +} + +pub trait Tag: 'static { + type MaskProjection: Projection; +} + +pub trait Tagged { + type Tag: Tag; +} + +pub struct Pick; + +pub trait SlotPicker: 'static { + type Mask: MaskBits; +} + +impl SlotPicker for Pick<0> { + type Mask = TypeTuple; +} + +impl SlotPicker for Pick<1> { + type Mask = TypeTuple; +} + +impl SlotPicker for Pick<2> { + type Mask = TypeTuple; +} + +impl SlotPicker for Pick<3> { + type Mask = TypeTuple; +} + +impl SlotPicker for Pick<4> { + type Mask = TypeTuple; +} + +impl SlotPicker for Pick<5> { + type Mask = TypeTuple; +} + +pub struct Static; + +impl SlotPicker for Static { + type Mask = TypeTuple; +} + +pub type Projector< + _0 = Static, + _1 = Static, + _2 = Static, + _3 = Static, + _4 = Static, + _5 = Static +> = + TypeTuple<_0, _1, _2, _3, _4, _5>; + +pub trait MaskBit { + type Or: MaskBit; + + type Pick: SlotPicker; +} + +pub type Mask<_0 = Off, _1 = Off, _2 = Off, _3 = Off, _4 = Off, _5 = Off> = + TypeTuple<_0, _1, _2, _3, _4, _5>; + +pub trait MaskBits: + TypeTupleAccess<_0: MaskBit, _1: MaskBit, _2: MaskBit, _3: MaskBit, _4: MaskBit, _5: MaskBit> +{ +} + +impl<_0, _1, _2, _3, _4, _5> MaskBits for TypeTuple<_0, _1, _2, _3, _4, _5> +where + _0: MaskBit, + _1: MaskBit, + _2: MaskBit, + _3: MaskBit, + _4: MaskBit, + _5: MaskBit, +{ +} + +pub struct On; +pub struct Off; + +impl MaskBit for On { + type Or = Self; + + type Pick = T; +} + +impl MaskBit for Off { + type Or = T; + + type Pick = Static; +} + +pub type MaskAllOn = TypeTuple; + +pub type MaskOr = TypeTuple< + <::_0 as MaskBit>::Or<::_0>, + <::_1 as MaskBit>::Or<::_1>, + <::_2 as MaskBit>::Or<::_2>, + <::_3 as MaskBit>::Or<::_3>, + <::_4 as MaskBit>::Or<::_4>, + <::_5 as MaskBit>::Or<::_5>, +>; + +pub type ProjectMask = MaskOr< + MaskOr< + MaskOr< + <::_0 as SlotPicker>::Mask< + ::_0, + >, + <::_1 as SlotPicker>::Mask< + ::_1, + >, + >, + MaskOr< + <::_2 as SlotPicker>::Mask< + ::_2, + >, + <::_3 as SlotPicker>::Mask< + ::_3, + >, + >, + >, + MaskOr< + <::_4 as SlotPicker>::Mask<::_4>, + <::_5 as SlotPicker>::Mask<::_5>, + >, +>; + +pub type MaskToProjection = TypeTuple< + <::_0 as MaskBit>::Pick>, + <::_1 as MaskBit>::Pick>, + <::_2 as MaskBit>::Pick>, + <::_3 as MaskBit>::Pick>, + <::_4 as MaskBit>::Pick>, + <::_5 as MaskBit>::Pick>, +>; + +fn main() {}