55
66use rustc_arena:: DroplessArena ;
77use rustc_hir:: def:: DefKind ;
8- use rustc_hir:: def_id:: DefId ;
8+ use rustc_hir:: def_id:: { DefId , LocalDefId } ;
99use rustc_middle:: ty:: query:: Providers ;
10- use rustc_middle:: ty:: { self , CrateVariancesMap , TyCtxt } ;
10+ use rustc_middle:: ty:: { self , CrateVariancesMap , TyCtxt , TypeSuperVisitable , TypeVisitable } ;
11+ use std:: ops:: ControlFlow ;
1112
1213/// Defines the `TermsContext` basically houses an arena where we can
1314/// allocate terms.
@@ -50,6 +51,9 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
5051 | DefKind :: Union
5152 | DefKind :: Variant
5253 | DefKind :: Ctor ( ..) => { }
54+ DefKind :: OpaqueTy | DefKind :: ImplTraitPlaceholder => {
55+ return variance_of_opaque ( tcx, item_def_id. expect_local ( ) ) ;
56+ }
5357 _ => {
5458 // Variance not relevant.
5559 span_bug ! ( tcx. def_span( item_def_id) , "asked to compute variance for wrong kind of item" )
@@ -61,3 +65,89 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: DefId) -> &[ty::Variance] {
6165 let crate_map = tcx. crate_variances ( ( ) ) ;
6266 crate_map. variances . get ( & item_def_id) . copied ( ) . unwrap_or ( & [ ] )
6367}
68+
69+ #[ instrument( level = "trace" , skip( tcx) , ret) ]
70+ fn variance_of_opaque ( tcx : TyCtxt < ' _ > , item_def_id : LocalDefId ) -> & [ ty:: Variance ] {
71+ let generics = tcx. generics_of ( item_def_id) ;
72+
73+ // Opaque types may only use regions that are bound. So for
74+ // ```rust
75+ // type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
76+ // ```
77+ // we may not use `'c` in the hidden type.
78+ struct OpaqueTypeLifetimeCollector {
79+ variances : Vec < ty:: Variance > ,
80+ }
81+
82+ impl < ' tcx > ty:: TypeVisitor < ' tcx > for OpaqueTypeLifetimeCollector {
83+ #[ instrument( level = "trace" , skip( self ) , ret) ]
84+ fn visit_region ( & mut self , r : ty:: Region < ' tcx > ) -> ControlFlow < Self :: BreakTy > {
85+ if let ty:: RegionKind :: ReEarlyBound ( ebr) = r. kind ( ) {
86+ self . variances [ ebr. index as usize ] = ty:: Invariant ;
87+ }
88+ r. super_visit_with ( self )
89+ }
90+ }
91+
92+ // By default, we RPIT are invariant wrt type and const generics, but they are bivariant wrt
93+ // lifetime generics.
94+ let mut variances: Vec < _ > = std:: iter:: repeat ( ty:: Invariant ) . take ( generics. count ( ) ) . collect ( ) ;
95+
96+ // Mark all lifetimes from parent generics as unused (Bivariant).
97+ // This will be overridden later if required.
98+ {
99+ let mut generics = generics;
100+ while let Some ( def_id) = generics. parent {
101+ generics = tcx. generics_of ( def_id) ;
102+ for param in & generics. params {
103+ match param. kind {
104+ ty:: GenericParamDefKind :: Lifetime => {
105+ variances[ param. index as usize ] = ty:: Bivariant ;
106+ }
107+ ty:: GenericParamDefKind :: Type { .. }
108+ | ty:: GenericParamDefKind :: Const { .. } => { }
109+ }
110+ }
111+ }
112+ }
113+
114+ let mut collector = OpaqueTypeLifetimeCollector { variances } ;
115+ let id_substs = ty:: InternalSubsts :: identity_for_item ( tcx, item_def_id. to_def_id ( ) ) ;
116+ for pred in tcx. bound_explicit_item_bounds ( item_def_id. to_def_id ( ) ) . transpose_iter ( ) {
117+ let pred = pred. map_bound ( |( pred, _) | * pred) . subst ( tcx, id_substs) ;
118+ debug ! ( ?pred) ;
119+
120+ // We only ignore opaque type substs if the opaque type is the outermost type.
121+ // The opaque type may be nested within itself via recursion in e.g.
122+ // type Foo<'a> = impl PartialEq<Foo<'a>>;
123+ // which thus mentions `'a` and should thus accept hidden types that borrow 'a
124+ // instead of requiring an additional `+ 'a`.
125+ match pred. kind ( ) . skip_binder ( ) {
126+ ty:: PredicateKind :: Trait ( ty:: TraitPredicate {
127+ trait_ref : ty:: TraitRef { def_id : _, substs } ,
128+ constness : _,
129+ polarity : _,
130+ } ) => {
131+ for subst in & substs[ 1 ..] {
132+ subst. visit_with ( & mut collector) ;
133+ }
134+ }
135+ ty:: PredicateKind :: Projection ( ty:: ProjectionPredicate {
136+ projection_ty : ty:: ProjectionTy { substs, item_def_id : _ } ,
137+ term,
138+ } ) => {
139+ for subst in & substs[ 1 ..] {
140+ subst. visit_with ( & mut collector) ;
141+ }
142+ term. visit_with ( & mut collector) ;
143+ }
144+ ty:: PredicateKind :: TypeOutlives ( ty:: OutlivesPredicate ( _, region) ) => {
145+ region. visit_with ( & mut collector) ;
146+ }
147+ _ => {
148+ pred. visit_with ( & mut collector) ;
149+ }
150+ }
151+ }
152+ tcx. arena . alloc_from_iter ( collector. variances . into_iter ( ) )
153+ }
0 commit comments