@@ -59,6 +59,17 @@ pub(super) fn infer_predicates(
5959 }
6060 }
6161
62+ DefKind :: TyAlias if tcx. type_alias_is_lazy ( item_did) => {
63+ insert_required_predicates_to_be_wf (
64+ tcx,
65+ tcx. type_of ( item_did) . instantiate_identity ( ) ,
66+ tcx. def_span ( item_did) ,
67+ & global_inferred_outlives,
68+ & mut item_required_predicates,
69+ & mut explicit_map,
70+ ) ;
71+ }
72+
6273 _ => { }
6374 } ;
6475
@@ -88,78 +99,41 @@ pub(super) fn infer_predicates(
8899
89100fn insert_required_predicates_to_be_wf < ' tcx > (
90101 tcx : TyCtxt < ' tcx > ,
91- field_ty : Ty < ' tcx > ,
92- field_span : Span ,
102+ ty : Ty < ' tcx > ,
103+ span : Span ,
93104 global_inferred_outlives : & FxHashMap < DefId , ty:: EarlyBinder < RequiredPredicates < ' tcx > > > ,
94105 required_predicates : & mut RequiredPredicates < ' tcx > ,
95106 explicit_map : & mut ExplicitPredicatesMap < ' tcx > ,
96107) {
97- for arg in field_ty . walk ( ) {
98- let ty = match arg. unpack ( ) {
108+ for arg in ty . walk ( ) {
109+ let leaf_ty = match arg. unpack ( ) {
99110 GenericArgKind :: Type ( ty) => ty,
100111
101112 // No predicates from lifetimes or constants, except potentially
102113 // constants' types, but `walk` will get to them as well.
103114 GenericArgKind :: Lifetime ( _) | GenericArgKind :: Const ( _) => continue ,
104115 } ;
105116
106- match * ty. kind ( ) {
107- // The field is of type &'a T which means that we will have
108- // a predicate requirement of T: 'a (T outlives 'a).
109- //
110- // We also want to calculate potential predicates for the T
117+ match * leaf_ty. kind ( ) {
111118 ty:: Ref ( region, rty, _) => {
119+ // The type is `&'a T` which means that we will have
120+ // a predicate requirement of `T: 'a` (`T` outlives `'a`).
121+ //
122+ // We also want to calculate potential predicates for the `T`.
112123 debug ! ( "Ref" ) ;
113- insert_outlives_predicate ( tcx, rty. into ( ) , region, field_span , required_predicates) ;
124+ insert_outlives_predicate ( tcx, rty. into ( ) , region, span , required_predicates) ;
114125 }
115126
116- // For each Adt (struct/enum/union) type `Foo<'a, T>`, we
117- // can load the current set of inferred and explicit
118- // predicates from `global_inferred_outlives` and filter the
119- // ones that are TypeOutlives.
120127 ty:: Adt ( def, args) => {
121- // First check the inferred predicates
122- //
123- // Example 1:
124- //
125- // struct Foo<'a, T> {
126- // field1: Bar<'a, T>
127- // }
128- //
129- // struct Bar<'b, U> {
130- // field2: &'b U
131- // }
132- //
133- // Here, when processing the type of `field1`, we would
134- // request the set of implicit predicates computed for `Bar`
135- // thus far. This will initially come back empty, but in next
136- // round we will get `U: 'b`. We then apply the substitution
137- // `['b => 'a, U => T]` and thus get the requirement that `T:
138- // 'a` holds for `Foo`.
128+ // For ADTs (structs/enums/unions), we check inferred and explicit predicates.
139129 debug ! ( "Adt" ) ;
140- if let Some ( unsubstituted_predicates) = global_inferred_outlives. get ( & def. did ( ) ) {
141- for ( unsubstituted_predicate, & span) in
142- unsubstituted_predicates. as_ref ( ) . skip_binder ( )
143- {
144- // `unsubstituted_predicate` is `U: 'b` in the
145- // example above. So apply the substitution to
146- // get `T: 'a` (or `predicate`):
147- let predicate = unsubstituted_predicates
148- . rebind ( * unsubstituted_predicate)
149- . instantiate ( tcx, args) ;
150- insert_outlives_predicate (
151- tcx,
152- predicate. 0 ,
153- predicate. 1 ,
154- span,
155- required_predicates,
156- ) ;
157- }
158- }
159-
160- // Check if the type has any explicit predicates that need
161- // to be added to `required_predicates`
162- // let _: () = args.region_at(0);
130+ check_inferred_predicates (
131+ tcx,
132+ def. did ( ) ,
133+ args,
134+ global_inferred_outlives,
135+ required_predicates,
136+ ) ;
163137 check_explicit_predicates (
164138 tcx,
165139 def. did ( ) ,
@@ -170,13 +144,31 @@ fn insert_required_predicates_to_be_wf<'tcx>(
170144 ) ;
171145 }
172146
147+ ty:: Alias ( ty:: Weak , alias) => {
148+ // This corresponds to a type like `Type<'a, T>`.
149+ // We check inferred and explicit predicates.
150+ debug ! ( "Weak" ) ;
151+ check_inferred_predicates (
152+ tcx,
153+ alias. def_id ,
154+ alias. args ,
155+ global_inferred_outlives,
156+ required_predicates,
157+ ) ;
158+ check_explicit_predicates (
159+ tcx,
160+ alias. def_id ,
161+ alias. args ,
162+ required_predicates,
163+ explicit_map,
164+ None ,
165+ ) ;
166+ }
167+
173168 ty:: Dynamic ( obj, ..) => {
174169 // This corresponds to `dyn Trait<..>`. In this case, we should
175170 // use the explicit predicates as well.
176-
177171 debug ! ( "Dynamic" ) ;
178- debug ! ( "field_ty = {}" , & field_ty) ;
179- debug ! ( "ty in field = {}" , & ty) ;
180172 if let Some ( ex_trait_ref) = obj. principal ( ) {
181173 // Here, we are passing the type `usize` as a
182174 // placeholder value with the function
@@ -198,41 +190,44 @@ fn insert_required_predicates_to_be_wf<'tcx>(
198190 }
199191 }
200192
201- ty:: Alias ( ty:: Projection , obj) => {
202- // This corresponds to `<T as Foo<'a>>::Bar`. In this case, we should use the
203- // explicit predicates as well.
193+ ty:: Alias ( ty:: Projection , alias) => {
194+ // This corresponds to a type like `<() as Trait<'a, T>>::Type`.
195+ // We only use the explicit predicates of the trait but
196+ // not the ones of the associated type itself.
204197 debug ! ( "Projection" ) ;
205198 check_explicit_predicates (
206199 tcx,
207- tcx. parent ( obj . def_id ) ,
208- obj . args ,
200+ tcx. parent ( alias . def_id ) ,
201+ alias . args ,
209202 required_predicates,
210203 explicit_map,
211204 None ,
212205 ) ;
213206 }
214207
215- // FIXME(inherent_associated_types): Handle this case properly .
208+ // FIXME(inherent_associated_types): Use the explicit predicates from the parent impl .
216209 ty:: Alias ( ty:: Inherent , _) => { }
217210
218211 _ => { }
219212 }
220213 }
221214}
222215
223- /// We also have to check the explicit predicates
224- /// declared on the type.
216+ /// Check the explicit predicates declared on the type.
217+ ///
218+ /// ### Example
219+ ///
225220/// ```ignore (illustrative)
226- /// struct Foo <'a, T> {
227- /// field1: Bar <T>
221+ /// struct Outer <'a, T> {
222+ /// field: Inner <T>,
228223/// }
229224///
230- /// struct Bar <U> where U: 'static, U: Foo {
231- /// ...
225+ /// struct Inner <U> where U: 'static, U: Outer {
226+ /// // ...
232227/// }
233228/// ```
234229/// Here, we should fetch the explicit predicates, which
235- /// will give us `U: 'static` and `U: Foo `. The latter we
230+ /// will give us `U: 'static` and `U: Outer `. The latter we
236231/// can ignore, but we will want to process `U: 'static`,
237232/// applying the substitution as above.
238233fn check_explicit_predicates < ' tcx > (
@@ -303,3 +298,45 @@ fn check_explicit_predicates<'tcx>(
303298 insert_outlives_predicate ( tcx, predicate. 0 , predicate. 1 , span, required_predicates) ;
304299 }
305300}
301+
302+ /// Check the inferred predicates declared on the type.
303+ ///
304+ /// ### Example
305+ ///
306+ /// ```ignore (illustrative)
307+ /// struct Outer<'a, T> {
308+ /// outer: Inner<'a, T>,
309+ /// }
310+ ///
311+ /// struct Inner<'b, U> {
312+ /// inner: &'b U,
313+ /// }
314+ /// ```
315+ ///
316+ /// Here, when processing the type of field `outer`, we would request the
317+ /// set of implicit predicates computed for `Inner` thus far. This will
318+ /// initially come back empty, but in next round we will get `U: 'b`.
319+ /// We then apply the substitution `['b => 'a, U => T]` and thus get the
320+ /// requirement that `T: 'a` holds for `Outer`.
321+ fn check_inferred_predicates < ' tcx > (
322+ tcx : TyCtxt < ' tcx > ,
323+ def_id : DefId ,
324+ args : ty:: GenericArgsRef < ' tcx > ,
325+ global_inferred_outlives : & FxHashMap < DefId , ty:: EarlyBinder < RequiredPredicates < ' tcx > > > ,
326+ required_predicates : & mut RequiredPredicates < ' tcx > ,
327+ ) {
328+ // Load the current set of inferred and explicit predicates from `global_inferred_outlives`
329+ // and filter the ones that are `TypeOutlives`.
330+
331+ let Some ( predicates) = global_inferred_outlives. get ( & def_id) else {
332+ return ;
333+ } ;
334+
335+ for ( & predicate, & span) in predicates. as_ref ( ) . skip_binder ( ) {
336+ // `predicate` is `U: 'b` in the example above.
337+ // So apply the substitution to get `T: 'a`.
338+ let ty:: OutlivesPredicate ( arg, region) =
339+ predicates. rebind ( predicate) . instantiate ( tcx, args) ;
340+ insert_outlives_predicate ( tcx, arg, region, span, required_predicates) ;
341+ }
342+ }
0 commit comments