@@ -59,6 +59,17 @@ pub(super) fn infer_predicates(
59
59
}
60
60
}
61
61
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
+
62
73
_ => { }
63
74
} ;
64
75
@@ -88,78 +99,41 @@ pub(super) fn infer_predicates(
88
99
89
100
fn insert_required_predicates_to_be_wf < ' tcx > (
90
101
tcx : TyCtxt < ' tcx > ,
91
- field_ty : Ty < ' tcx > ,
92
- field_span : Span ,
102
+ ty : Ty < ' tcx > ,
103
+ span : Span ,
93
104
global_inferred_outlives : & FxHashMap < DefId , ty:: EarlyBinder < RequiredPredicates < ' tcx > > > ,
94
105
required_predicates : & mut RequiredPredicates < ' tcx > ,
95
106
explicit_map : & mut ExplicitPredicatesMap < ' tcx > ,
96
107
) {
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 ( ) {
99
110
GenericArgKind :: Type ( ty) => ty,
100
111
101
112
// No predicates from lifetimes or constants, except potentially
102
113
// constants' types, but `walk` will get to them as well.
103
114
GenericArgKind :: Lifetime ( _) | GenericArgKind :: Const ( _) => continue ,
104
115
} ;
105
116
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 ( ) {
111
118
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`.
112
123
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) ;
114
125
}
115
126
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.
120
127
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.
139
129
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
+ ) ;
163
137
check_explicit_predicates (
164
138
tcx,
165
139
def. did ( ) ,
@@ -170,13 +144,31 @@ fn insert_required_predicates_to_be_wf<'tcx>(
170
144
) ;
171
145
}
172
146
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
+
173
168
ty:: Dynamic ( obj, ..) => {
174
169
// This corresponds to `dyn Trait<..>`. In this case, we should
175
170
// use the explicit predicates as well.
176
-
177
171
debug ! ( "Dynamic" ) ;
178
- debug ! ( "field_ty = {}" , & field_ty) ;
179
- debug ! ( "ty in field = {}" , & ty) ;
180
172
if let Some ( ex_trait_ref) = obj. principal ( ) {
181
173
// Here, we are passing the type `usize` as a
182
174
// placeholder value with the function
@@ -198,41 +190,44 @@ fn insert_required_predicates_to_be_wf<'tcx>(
198
190
}
199
191
}
200
192
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.
204
197
debug ! ( "Projection" ) ;
205
198
check_explicit_predicates (
206
199
tcx,
207
- tcx. parent ( obj . def_id ) ,
208
- obj . args ,
200
+ tcx. parent ( alias . def_id ) ,
201
+ alias . args ,
209
202
required_predicates,
210
203
explicit_map,
211
204
None ,
212
205
) ;
213
206
}
214
207
215
- // FIXME(inherent_associated_types): Handle this case properly .
208
+ // FIXME(inherent_associated_types): Use the explicit predicates from the parent impl .
216
209
ty:: Alias ( ty:: Inherent , _) => { }
217
210
218
211
_ => { }
219
212
}
220
213
}
221
214
}
222
215
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
+ ///
225
220
/// ```ignore (illustrative)
226
- /// struct Foo <'a, T> {
227
- /// field1: Bar <T>
221
+ /// struct Outer <'a, T> {
222
+ /// field: Inner <T>,
228
223
/// }
229
224
///
230
- /// struct Bar <U> where U: 'static, U: Foo {
231
- /// ...
225
+ /// struct Inner <U> where U: 'static, U: Outer {
226
+ /// // ...
232
227
/// }
233
228
/// ```
234
229
/// 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
236
231
/// can ignore, but we will want to process `U: 'static`,
237
232
/// applying the substitution as above.
238
233
fn check_explicit_predicates < ' tcx > (
@@ -303,3 +298,45 @@ fn check_explicit_predicates<'tcx>(
303
298
insert_outlives_predicate ( tcx, predicate. 0 , predicate. 1 , span, required_predicates) ;
304
299
}
305
300
}
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