1
1
use std:: mem;
2
2
3
+ use super :: StructurallyRelateAliases ;
3
4
use crate :: infer:: type_variable:: { TypeVariableOrigin , TypeVariableOriginKind , TypeVariableValue } ;
4
5
use crate :: infer:: { InferCtxt , ObligationEmittingRelation , RegionVariableOrigin } ;
5
6
use rustc_data_structures:: sso:: SsoHashMap ;
@@ -45,8 +46,14 @@ impl<'tcx> InferCtxt<'tcx> {
45
46
// region/type inference variables.
46
47
//
47
48
// We then relate `generalized_ty <: source_ty`,adding constraints like `'x: '?2` and `?1 <: ?3`.
48
- let Generalization { value_may_be_infer : generalized_ty, has_unconstrained_ty_var } =
49
- self . generalize ( relation. span ( ) , target_vid, instantiation_variance, source_ty) ?;
49
+ let Generalization { value_may_be_infer : generalized_ty, has_unconstrained_ty_var } = self
50
+ . generalize (
51
+ relation. span ( ) ,
52
+ relation. structurally_relate_aliases ( ) ,
53
+ target_vid,
54
+ instantiation_variance,
55
+ source_ty,
56
+ ) ?;
50
57
51
58
// Constrain `b_vid` to the generalized type `generalized_ty`.
52
59
if let & ty:: Infer ( ty:: TyVar ( generalized_vid) ) = generalized_ty. kind ( ) {
@@ -178,8 +185,14 @@ impl<'tcx> InferCtxt<'tcx> {
178
185
) -> RelateResult < ' tcx , ( ) > {
179
186
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
180
187
// constants and generic expressions are not yet handled correctly.
181
- let Generalization { value_may_be_infer : generalized_ct, has_unconstrained_ty_var } =
182
- self . generalize ( relation. span ( ) , target_vid, ty:: Variance :: Invariant , source_ct) ?;
188
+ let Generalization { value_may_be_infer : generalized_ct, has_unconstrained_ty_var } = self
189
+ . generalize (
190
+ relation. span ( ) ,
191
+ relation. structurally_relate_aliases ( ) ,
192
+ target_vid,
193
+ ty:: Variance :: Invariant ,
194
+ source_ct,
195
+ ) ?;
183
196
184
197
debug_assert ! ( !generalized_ct. is_ct_infer( ) ) ;
185
198
if has_unconstrained_ty_var {
@@ -217,6 +230,7 @@ impl<'tcx> InferCtxt<'tcx> {
217
230
fn generalize < T : Into < Term < ' tcx > > + Relate < ' tcx > > (
218
231
& self ,
219
232
span : Span ,
233
+ structurally_relate_aliases : StructurallyRelateAliases ,
220
234
target_vid : impl Into < ty:: TermVid > ,
221
235
ambient_variance : ty:: Variance ,
222
236
source_term : T ,
@@ -237,6 +251,7 @@ impl<'tcx> InferCtxt<'tcx> {
237
251
let mut generalizer = Generalizer {
238
252
infcx : self ,
239
253
span,
254
+ structurally_relate_aliases,
240
255
root_vid,
241
256
for_universe,
242
257
ambient_variance,
@@ -270,6 +285,10 @@ struct Generalizer<'me, 'tcx> {
270
285
271
286
span : Span ,
272
287
288
+ /// Whether aliases should be related structurally. If not, we have to
289
+ /// be careful when generalizing aliases.
290
+ structurally_relate_aliases : StructurallyRelateAliases ,
291
+
273
292
/// The vid of the type variable that is in the process of being
274
293
/// instantiated. If we find this within the value we are folding,
275
294
/// that means we would have created a cyclic value.
@@ -314,13 +333,30 @@ impl<'tcx> Generalizer<'_, 'tcx> {
314
333
/// to normalize the alias after all.
315
334
///
316
335
/// We handle this by lazily equating the alias and generalizing
317
- /// it to an inference variable.
336
+ /// it to an inference variable. In the new solver, we always
337
+ /// generalize to an infer var unless the alias contains escaping
338
+ /// bound variables.
318
339
///
319
- /// This is incomplete and will hopefully soon get fixed by #119106.
340
+ /// Correctly handling aliases with escaping bound variables is
341
+ /// difficult and currently incomplete in two opposite ways:
342
+ /// - if we get an occurs check failure in the alias, replace it with a new infer var.
343
+ /// This causes us to later emit an alias-relate goal and is incomplete in case the
344
+ /// alias normalizes to type containing one of the bound variables.
345
+ /// - if the alias contains an inference variable not nameable by `for_universe`, we
346
+ /// continue generalizing the alias. This ends up pulling down the universe of the
347
+ /// inference variable and is incomplete in case the alias would normalize to a type
348
+ /// which does not mention that inference variable.
320
349
fn generalize_alias_ty (
321
350
& mut self ,
322
351
alias : ty:: AliasTy < ' tcx > ,
323
352
) -> Result < Ty < ' tcx > , TypeError < ' tcx > > {
353
+ if self . infcx . next_trait_solver ( ) && !alias. has_escaping_bound_vars ( ) {
354
+ return Ok ( self . infcx . next_ty_var_in_universe (
355
+ TypeVariableOrigin { kind : TypeVariableOriginKind :: MiscVariable , span : self . span } ,
356
+ self . for_universe ,
357
+ ) ) ;
358
+ }
359
+
324
360
let is_nested_alias = mem:: replace ( & mut self . in_alias , true ) ;
325
361
let result = match self . relate ( alias, alias) {
326
362
Ok ( alias) => Ok ( alias. to_ty ( self . tcx ( ) ) ) ,
@@ -490,7 +526,10 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
490
526
}
491
527
}
492
528
493
- ty:: Alias ( _, data) => self . generalize_alias_ty ( data) ,
529
+ ty:: Alias ( _, data) => match self . structurally_relate_aliases {
530
+ StructurallyRelateAliases :: No => self . generalize_alias_ty ( data) ,
531
+ StructurallyRelateAliases :: Yes => relate:: structurally_relate_tys ( self , t, t) ,
532
+ } ,
494
533
495
534
_ => relate:: structurally_relate_tys ( self , t, t) ,
496
535
} ?;
0 commit comments