@@ -212,29 +212,41 @@ impl<'tcx> InferCtxt<'tcx> {
212212 source_ct,
213213 ) ?;
214214
215- debug_assert ! ( !generalized_ct. is_ct_infer( ) ) ;
216-
217- self . inner
218- . borrow_mut ( )
219- . const_unification_table ( )
220- . union_value ( target_vid, ConstVariableValue :: Known { value : generalized_ct } ) ;
221-
222- // Make sure that the order is correct when relating the
223- // generalized const and the source.
224- if target_is_expected {
225- relation. relate_with_variance (
226- ty:: Invariant ,
227- ty:: VarianceDiagInfo :: default ( ) ,
228- generalized_ct,
229- source_ct,
230- ) ?;
215+ if let ty:: ConstKind :: Infer ( ty:: InferConst :: Var ( generalized_vid) ) = generalized_ct. kind ( ) {
216+ self . inner . borrow_mut ( ) . const_unification_table ( ) . union ( target_vid, generalized_vid) ;
217+
218+ if self . next_trait_solver ( ) {
219+ relation. register_predicates ( [ ty:: PredicateKind :: AliasRelate (
220+ generalized_ct. into ( ) ,
221+ source_ct. into ( ) ,
222+ AliasRelationDirection :: Equate ,
223+ ) ] ) ;
224+ } else {
225+ return Err ( TypeError :: CyclicConst ( source_ct) ) ;
226+ }
231227 } else {
232- relation. relate_with_variance (
233- ty:: Invariant ,
234- ty:: VarianceDiagInfo :: default ( ) ,
235- source_ct,
236- generalized_ct,
237- ) ?;
228+ self . inner
229+ . borrow_mut ( )
230+ . const_unification_table ( )
231+ . union_value ( target_vid, ConstVariableValue :: Known { value : generalized_ct } ) ;
232+
233+ // Make sure that the order is correct when relating the
234+ // generalized const and the source.
235+ if target_is_expected {
236+ relation. relate_with_variance (
237+ ty:: Invariant ,
238+ ty:: VarianceDiagInfo :: default ( ) ,
239+ generalized_ct,
240+ source_ct,
241+ ) ?;
242+ } else {
243+ relation. relate_with_variance (
244+ ty:: Invariant ,
245+ ty:: VarianceDiagInfo :: default ( ) ,
246+ source_ct,
247+ generalized_ct,
248+ ) ?;
249+ }
238250 }
239251
240252 Ok ( ( ) )
@@ -377,8 +389,12 @@ impl<'tcx> Generalizer<'_, 'tcx> {
377389
378390 /// Create a new type variable in the universe of the target when
379391 /// generalizing an alias.
380- fn next_ty_var_for_alias ( & self ) -> Ty < ' tcx > {
381- self . infcx . next_ty_var_in_universe ( self . span , self . for_universe )
392+ fn next_var_for_alias_of_kind ( & self , alias : ty:: AliasTerm < ' tcx > ) -> ty:: Term < ' tcx > {
393+ if alias. kind ( self . cx ( ) ) . is_type ( ) {
394+ self . infcx . next_ty_var_in_universe ( self . span , self . for_universe ) . into ( )
395+ } else {
396+ self . infcx . next_const_var_in_universe ( self . span , self . for_universe ) . into ( )
397+ }
382398 }
383399
384400 /// An occurs check failure inside of an alias does not mean
@@ -399,23 +415,23 @@ impl<'tcx> Generalizer<'_, 'tcx> {
399415 /// continue generalizing the alias. This ends up pulling down the universe of the
400416 /// inference variable and is incomplete in case the alias would normalize to a type
401417 /// which does not mention that inference variable.
402- fn generalize_alias_ty (
418+ fn generalize_alias_term (
403419 & mut self ,
404- alias : ty:: AliasTy < ' tcx > ,
405- ) -> Result < Ty < ' tcx > , TypeError < ' tcx > > {
420+ alias : ty:: AliasTerm < ' tcx > ,
421+ ) -> Result < ty :: Term < ' tcx > , TypeError < ' tcx > > {
406422 // We do not eagerly replace aliases with inference variables if they have
407423 // escaping bound vars, see the method comment for details. However, when we
408424 // are inside of an alias with escaping bound vars replacing nested aliases
409425 // with inference variables can cause incorrect ambiguity.
410426 //
411427 // cc trait-system-refactor-initiative#110
412428 if self . infcx . next_trait_solver ( ) && !alias. has_escaping_bound_vars ( ) && !self . in_alias {
413- return Ok ( self . next_ty_var_for_alias ( ) ) ;
429+ return Ok ( self . next_var_for_alias_of_kind ( alias ) ) ;
414430 }
415431
416432 let is_nested_alias = mem:: replace ( & mut self . in_alias , true ) ;
417433 let result = match self . relate ( alias, alias) {
418- Ok ( alias) => Ok ( alias. to_ty ( self . cx ( ) ) ) ,
434+ Ok ( alias) => Ok ( alias. to_term ( self . cx ( ) ) ) ,
419435 Err ( e) => {
420436 if is_nested_alias {
421437 return Err ( e) ;
@@ -430,7 +446,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
430446 }
431447
432448 debug ! ( "generalization failure in alias" ) ;
433- Ok ( self . next_ty_var_for_alias ( ) )
449+ Ok ( self . next_var_for_alias_of_kind ( alias ) )
434450 }
435451 }
436452 } ;
@@ -507,13 +523,13 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
507523 if TermVid :: Ty ( vid) == self . root_vid {
508524 // If sub-roots are equal, then `root_vid` and
509525 // `vid` are related via subtyping.
510- Err ( self . cyclic_term_error ( ) )
526+ return Err ( self . cyclic_term_error ( ) ) ;
511527 } else {
512528 let probe = inner. type_variables ( ) . probe ( vid) ;
513529 match probe {
514530 TypeVariableValue :: Known { value : u } => {
515531 drop ( inner) ;
516- self . relate ( u, u)
532+ self . relate ( u, u) ?
517533 }
518534 TypeVariableValue :: Unknown { universe } => {
519535 match self . ambient_variance {
@@ -559,7 +575,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
559575 }
560576
561577 debug ! ( "replacing original vid={:?} with new={:?}" , vid, new_var_id) ;
562- Ok ( Ty :: new_var ( self . cx ( ) , new_var_id) )
578+ Ty :: new_var ( self . cx ( ) , new_var_id)
563579 }
564580 }
565581 }
@@ -569,28 +585,30 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
569585 // No matter what mode we are in,
570586 // integer/floating-point types must be equal to be
571587 // relatable.
572- Ok ( t )
588+ t
573589 }
574590
575591 ty:: Placeholder ( placeholder) => {
576592 if self . for_universe . can_name ( placeholder. universe ) {
577- Ok ( t )
593+ t
578594 } else {
579595 debug ! (
580596 "root universe {:?} cannot name placeholder in universe {:?}" ,
581597 self . for_universe, placeholder. universe
582598 ) ;
583- Err ( TypeError :: Mismatch )
599+ return Err ( TypeError :: Mismatch ) ;
584600 }
585601 }
586602
587603 ty:: Alias ( _, data) => match self . structurally_relate_aliases {
588- StructurallyRelateAliases :: No => self . generalize_alias_ty ( data) ,
589- StructurallyRelateAliases :: Yes => relate:: structurally_relate_tys ( self , t, t) ,
604+ StructurallyRelateAliases :: No => {
605+ self . generalize_alias_term ( data. into ( ) ) ?. expect_type ( )
606+ }
607+ StructurallyRelateAliases :: Yes => relate:: structurally_relate_tys ( self , t, t) ?,
590608 } ,
591609
592- _ => relate:: structurally_relate_tys ( self , t, t) ,
593- } ? ;
610+ _ => relate:: structurally_relate_tys ( self , t, t) ? ,
611+ } ;
594612
595613 self . cache . insert ( ( t, self . ambient_variance , self . in_alias ) , g) ;
596614 Ok ( g)
@@ -695,17 +713,26 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
695713 // FIXME: Unevaluated constants are also not rigid, so the current
696714 // approach of always relating them structurally is incomplete.
697715 //
698- // FIXME: remove this branch once `structurally_relate_consts` is fully
699- // structural.
700- ty:: ConstKind :: Unevaluated ( ty:: UnevaluatedConst { def, args } ) => {
701- let args = self . relate_with_variance (
702- ty:: Invariant ,
703- ty:: VarianceDiagInfo :: default ( ) ,
704- args,
705- args,
706- ) ?;
707- Ok ( ty:: Const :: new_unevaluated ( self . cx ( ) , ty:: UnevaluatedConst { def, args } ) )
708- }
716+ // FIXME: replace the StructurallyRelateAliases::Yes branch with
717+ // `structurally_relate_consts` once it is fully structural.
718+ ty:: ConstKind :: Unevaluated ( uv) => match self . structurally_relate_aliases {
719+ // Hack: Fall back to old behavior if GCE is enabled (it used to just be the Yes
720+ // path), as doing this new No path breaks some GCE things. I expect GCE to be
721+ // ripped out soon so this shouldn't matter soon.
722+ StructurallyRelateAliases :: No if !self . cx ( ) . features ( ) . generic_const_exprs ( ) => {
723+ Ok ( self . generalize_alias_term ( uv. into ( ) ) ?. expect_const ( ) )
724+ }
725+ _ => {
726+ let ty:: UnevaluatedConst { def, args } = uv;
727+ let args = self . relate_with_variance (
728+ ty:: Invariant ,
729+ ty:: VarianceDiagInfo :: default ( ) ,
730+ args,
731+ args,
732+ ) ?;
733+ Ok ( ty:: Const :: new_unevaluated ( self . cx ( ) , ty:: UnevaluatedConst { def, args } ) )
734+ }
735+ } ,
709736 ty:: ConstKind :: Placeholder ( placeholder) => {
710737 if self . for_universe . can_name ( placeholder. universe ) {
711738 Ok ( c)
0 commit comments