@@ -22,7 +22,7 @@ impl<'tcx> InferCtxt<'tcx> {
2222 /// subtyping could occur. This also does the occurs checks, detecting whether
2323 /// instantiating `target_vid` would result in a cyclic type. We eagerly error
2424 /// in this case.
25- #[ instrument( skip( self , relation, target_is_expected) , level = "debug" ) ]
25+ #[ instrument( level = "debug" , skip( self , relation, target_is_expected) ) ]
2626 pub ( super ) fn instantiate_ty_var < R : ObligationEmittingRelation < ' tcx > > (
2727 & self ,
2828 relation : & mut R ,
@@ -158,36 +158,48 @@ impl<'tcx> InferCtxt<'tcx> {
158158 /// As `3 + 4` contains `N` in its args, this must not succeed.
159159 ///
160160 /// 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 > > (
163163 & self ,
164+ relation : & mut R ,
165+ target_is_expected : bool ,
164166 target_vid : ty:: ConstVid ,
165167 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 , ( ) > {
173169 // FIXME(generic_const_exprs): Occurs check failures for unevaluated
174170 // constants and generic expressions are not yet handled correctly.
175171 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) ?;
177173
178174 debug_assert ! ( !generalized_ct. is_ct_infer( ) ) ;
179175 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:?}`" ) ;
181177 }
182178
183179 self . inner
184180 . borrow_mut ( )
185181 . const_unification_table ( )
186182 . union_value ( target_vid, ConstVariableValue :: Known { value : generalized_ct } ) ;
187183
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 ( ( ) )
191203 }
192204
193205 /// Attempts to generalize `source_term` for the type variable `target_vid`.
@@ -287,6 +299,49 @@ impl<'tcx> Generalizer<'_, 'tcx> {
287299 ty:: TermKind :: Const ( ct) => TypeError :: CyclicConst ( ct) ,
288300 }
289301 }
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+ }
290345}
291346
292347impl < ' tcx > TypeRelation < ' tcx > for Generalizer < ' _ , ' tcx > {
@@ -433,43 +488,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
433488 }
434489 }
435490
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) ,
473492
474493 _ => relate:: structurally_relate_tys ( self , t, t) ,
475494 } ?;
0 commit comments