@@ -22,7 +22,7 @@ impl<'tcx> InferCtxt<'tcx> {
22
22
/// subtyping could occur. This also does the occurs checks, detecting whether
23
23
/// instantiating `target_vid` would result in a cyclic type. We eagerly error
24
24
/// in this case.
25
- #[ instrument( skip( self , relation, target_is_expected) , level = "debug" ) ]
25
+ #[ instrument( level = "debug" , skip( self , relation, target_is_expected) ) ]
26
26
pub ( super ) fn instantiate_ty_var < R : ObligationEmittingRelation < ' tcx > > (
27
27
& self ,
28
28
relation : & mut R ,
@@ -158,36 +158,48 @@ impl<'tcx> InferCtxt<'tcx> {
158
158
/// As `3 + 4` contains `N` in its args, this must not succeed.
159
159
///
160
160
/// See `tests/ui/const-generics/occurs-check/` for more examples where this is relevant.
161
- #[ instrument( level = "debug" , skip( self ) ) ]
162
- pub ( super ) fn instantiate_const_var (
161
+ #[ instrument( level = "debug" , skip( self , relation ) ) ]
162
+ pub ( super ) fn instantiate_const_var < R : ObligationEmittingRelation < ' tcx > > (
163
163
& self ,
164
+ relation : & mut R ,
165
+ target_is_expected : bool ,
164
166
target_vid : ty:: ConstVid ,
165
167
source_ct : ty:: Const < ' tcx > ,
166
- ) -> RelateResult < ' tcx , ty:: Const < ' tcx > > {
167
- let span = match self . inner . borrow_mut ( ) . const_unification_table ( ) . probe_value ( target_vid) {
168
- ConstVariableValue :: Known { value } => {
169
- bug ! ( "instantiating a known const var: {target_vid:?} {value} {source_ct}" )
170
- }
171
- ConstVariableValue :: Unknown { origin, universe : _ } => origin. span ,
172
- } ;
168
+ ) -> RelateResult < ' tcx , ( ) > {
173
169
// FIXME(generic_const_exprs): Occurs check failures for unevaluated
174
170
// constants and generic expressions are not yet handled correctly.
175
171
let Generalization { value_may_be_infer : generalized_ct, has_unconstrained_ty_var } =
176
- self . generalize ( span, target_vid, ty:: Variance :: Invariant , source_ct) ?;
172
+ self . generalize ( relation . span ( ) , target_vid, ty:: Variance :: Invariant , source_ct) ?;
177
173
178
174
debug_assert ! ( !generalized_ct. is_ct_infer( ) ) ;
179
175
if has_unconstrained_ty_var {
180
- span_bug ! ( span , "unconstrained ty var when generalizing `{source_ct:?}`" ) ;
176
+ bug ! ( "unconstrained ty var when generalizing `{source_ct:?}`" ) ;
181
177
}
182
178
183
179
self . inner
184
180
. borrow_mut ( )
185
181
. const_unification_table ( )
186
182
. union_value ( target_vid, ConstVariableValue :: Known { value : generalized_ct } ) ;
187
183
188
- // FIXME(generic_const_exprs): We have to make sure we actually equate
189
- // `generalized_ct` and `source_ct` here.
190
- Ok ( generalized_ct)
184
+ // HACK: make sure that we `a_is_expected` continues to be
185
+ // correct when relating the generalized type with the source.
186
+ if target_is_expected == relation. a_is_expected ( ) {
187
+ relation. relate_with_variance (
188
+ ty:: Variance :: Invariant ,
189
+ ty:: VarianceDiagInfo :: default ( ) ,
190
+ generalized_ct,
191
+ source_ct,
192
+ ) ?;
193
+ } else {
194
+ relation. relate_with_variance (
195
+ ty:: Variance :: Invariant ,
196
+ ty:: VarianceDiagInfo :: default ( ) ,
197
+ source_ct,
198
+ generalized_ct,
199
+ ) ?;
200
+ }
201
+
202
+ Ok ( ( ) )
191
203
}
192
204
193
205
/// Attempts to generalize `source_term` for the type variable `target_vid`.
@@ -287,6 +299,49 @@ impl<'tcx> Generalizer<'_, 'tcx> {
287
299
ty:: TermKind :: Const ( ct) => TypeError :: CyclicConst ( ct) ,
288
300
}
289
301
}
302
+
303
+ /// An occurs check failure inside of an alias does not mean
304
+ /// that the types definitely don't unify. We may be able
305
+ /// to normalize the alias after all.
306
+ ///
307
+ /// We handle this by lazily equating the alias and generalizing
308
+ /// it to an inference variable.
309
+ ///
310
+ /// This is incomplete and will hopefully soon get fixed by #119106.
311
+ fn generalize_alias_ty (
312
+ & mut self ,
313
+ alias : ty:: AliasTy < ' tcx > ,
314
+ ) -> Result < Ty < ' tcx > , TypeError < ' tcx > > {
315
+ let is_nested_alias = mem:: replace ( & mut self . in_alias , true ) ;
316
+ let result = match self . relate ( alias, alias) {
317
+ Ok ( alias) => Ok ( alias. to_ty ( self . tcx ( ) ) ) ,
318
+ Err ( e) => {
319
+ if is_nested_alias {
320
+ return Err ( e) ;
321
+ } else {
322
+ let mut visitor = MaxUniverse :: new ( ) ;
323
+ alias. visit_with ( & mut visitor) ;
324
+ let infer_replacement_is_complete =
325
+ self . for_universe . can_name ( visitor. max_universe ( ) )
326
+ && !alias. has_escaping_bound_vars ( ) ;
327
+ if !infer_replacement_is_complete {
328
+ warn ! ( "may incompletely handle alias type: {alias:?}" ) ;
329
+ }
330
+
331
+ debug ! ( "generalization failure in alias" ) ;
332
+ Ok ( self . infcx . next_ty_var_in_universe (
333
+ TypeVariableOrigin {
334
+ kind : TypeVariableOriginKind :: MiscVariable ,
335
+ span : self . span ,
336
+ } ,
337
+ self . for_universe ,
338
+ ) )
339
+ }
340
+ }
341
+ } ;
342
+ self . in_alias = is_nested_alias;
343
+ result
344
+ }
290
345
}
291
346
292
347
impl < ' tcx > TypeRelation < ' tcx > for Generalizer < ' _ , ' tcx > {
@@ -433,43 +488,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
433
488
}
434
489
}
435
490
436
- ty:: Alias ( kind, data) => {
437
- // An occurs check failure inside of an alias does not mean
438
- // that the types definitely don't unify. We may be able
439
- // to normalize the alias after all.
440
- //
441
- // We handle this by lazily equating the alias and generalizing
442
- // it to an inference variable.
443
- let is_nested_alias = mem:: replace ( & mut self . in_alias , true ) ;
444
- let result = match self . relate ( data, data) {
445
- Ok ( data) => Ok ( Ty :: new_alias ( self . tcx ( ) , kind, data) ) ,
446
- Err ( e) => {
447
- if is_nested_alias {
448
- return Err ( e) ;
449
- } else {
450
- let mut visitor = MaxUniverse :: new ( ) ;
451
- t. visit_with ( & mut visitor) ;
452
- let infer_replacement_is_complete =
453
- self . for_universe . can_name ( visitor. max_universe ( ) )
454
- && !t. has_escaping_bound_vars ( ) ;
455
- if !infer_replacement_is_complete {
456
- warn ! ( "may incompletely handle alias type: {t:?}" ) ;
457
- }
458
-
459
- debug ! ( "generalization failure in alias" ) ;
460
- Ok ( self . infcx . next_ty_var_in_universe (
461
- TypeVariableOrigin {
462
- kind : TypeVariableOriginKind :: MiscVariable ,
463
- span : self . span ,
464
- } ,
465
- self . for_universe ,
466
- ) )
467
- }
468
- }
469
- } ;
470
- self . in_alias = is_nested_alias;
471
- result
472
- }
491
+ ty:: Alias ( _, data) => self . generalize_alias_ty ( data) ,
473
492
474
493
_ => relate:: structurally_relate_tys ( self , t, t) ,
475
494
} ?;
0 commit comments