@@ -355,13 +355,51 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxUniverse {
355355 }
356356}
357357
358+ /// This state determines how generalization treats aliases.
359+ ///
360+ /// Based on which state we're in, we treat them either as rigid or normalizable,
361+ /// which might change depending on what types the generalization visitor encounters.
362+ /// See `handle_alias_ty` for the logic of how we change states.
358363#[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash ) ]
359364enum GeneralizerState {
360365 /// Treat aliases as potentially normalizable.
366+ ///
367+ /// This is the default state that generalization starts in, unless we're
368+ /// treating aliases as rigid. It also means we're not currently inside an
369+ /// alias, since then we change the state to `IncompletelyRelateAliasArgs`.
361370 Default ,
362- IncompletelyRelateHigherRankedAlias ,
363- /// Only one layer
371+ /// We enter this state when we're generalizing the arguments of a
372+ /// potentially normalizeable alias.
373+ ///
374+ /// The behavior here is different between the old and the new solver:
375+ ///
376+ /// In the old solver, the difference between this and `Default` is needed to
377+ /// correctly handle `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. That
378+ /// equality can hold by either normalizing the outer or the inner
379+ /// associated type. In the old solver, we always structurally relate
380+ /// aliases. If we we encounter an occurs check failure, we propagate the
381+ /// failure to the outermost alias, for which we then emit a `Projection`
382+ /// goal instead.
383+ ///
384+ /// In the new solver, we rarely get into this state.
385+ /// When we encounter aliases we instead attempt to normalize them, and treat
386+ /// them as rigid using `ShallowStructurallyRelate`. Only when an alias has
387+ /// escaping bound variables do we continue with similar logic to the old
388+ /// solver, except now we also explicitly relate the type and consts in the
389+ /// arguments of aliases while in this mode.
390+ ///
391+ /// FIXME: Because we relate the type and consts in the arguments of aliases
392+ /// while in this mode, this is incomplete.
393+ IncompletelyRelateAliasArgs ,
394+ /// During generalization, when we encounter aliases, we will first attempt
395+ /// to normalize them when we're using the next trait solver. We can now
396+ /// treat the normalized alias as rigid, but only for "one layer", hence
397+ /// shallow. New aliases encountered inside the arguments of the outer alias
398+ /// should once again be related as normal.
364399 ShallowStructurallyRelateAliases ,
400+ /// Treat aliases as rigid when relating them.
401+ ///
402+ /// This corresponds to `relation.structurally_relate_aliases()`.
365403 StructurallyRelateAliases ,
366404}
367405
@@ -400,11 +438,10 @@ struct Generalizer<'me, 'tcx> {
400438 /// some other type. What will be the variance at this point?
401439 ambient_variance : ty:: Variance ,
402440
403- /// This is set once we're generalizing the arguments of an alias .
441+ /// This field keeps track of how we treat aliases during generalization .
404442 ///
405- /// This is necessary to correctly handle
406- /// `<T as Bar<<?0 as Foo>::Assoc>::Assoc == ?0`. This equality can
407- /// hold by either normalizing the outer or the inner associated type.
443+ /// Refer to [`GeneralizerState`]'s docs for more information about the
444+ /// all the possible values this can have, and when we use which.
408445 state : GeneralizerState ,
409446
410447 cache : SsoHashMap < ( Ty < ' tcx > , ty:: Variance , GeneralizerState ) , Ty < ' tcx > > ,
@@ -483,11 +520,11 @@ impl<'tcx> Generalizer<'_, 'tcx> {
483520
484521 return res;
485522 }
486- GeneralizerState :: Default | GeneralizerState :: IncompletelyRelateHigherRankedAlias => { }
523+ GeneralizerState :: Default | GeneralizerState :: IncompletelyRelateAliasArgs => { }
487524 }
488525
489526 let previous_state =
490- mem:: replace ( & mut self . state , GeneralizerState :: IncompletelyRelateHigherRankedAlias ) ;
527+ mem:: replace ( & mut self . state , GeneralizerState :: IncompletelyRelateAliasArgs ) ;
491528 let result = match self . relate ( alias, alias) {
492529 Ok ( alias) => Ok ( alias. to_ty ( self . cx ( ) ) ) ,
493530 Err ( e) => match previous_state {
@@ -504,7 +541,7 @@ impl<'tcx> Generalizer<'_, 'tcx> {
504541 debug ! ( "generalization failure in alias" ) ;
505542 Ok ( self . next_ty_var_for_alias ( ) )
506543 }
507- GeneralizerState :: IncompletelyRelateHigherRankedAlias => return Err ( e) ,
544+ GeneralizerState :: IncompletelyRelateAliasArgs => return Err ( e) ,
508545
509546 // Early return.
510547 GeneralizerState :: ShallowStructurallyRelateAliases
@@ -613,6 +650,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
613650 // of each other. This is currently only used for diagnostics.
614651 // To see why, see the docs in the `type_variables` module.
615652 inner. type_variables ( ) . sub_unify ( vid, new_var_id) ;
653+
616654 // If we're in the new solver and create a new inference
617655 // variable inside of an alias we eagerly constrain that
618656 // inference variable to prevent unexpected ambiguity errors.
@@ -632,13 +670,13 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
632670 && !matches ! ( self . infcx. typing_mode( ) , TypingMode :: Coherence )
633671 {
634672 match self . state {
635- GeneralizerState :: IncompletelyRelateHigherRankedAlias => {
673+ GeneralizerState :: IncompletelyRelateAliasArgs => {
636674 inner. type_variables ( ) . equate ( vid, new_var_id) ;
637675 }
676+ GeneralizerState :: Default
677+ | GeneralizerState :: ShallowStructurallyRelateAliases
678+ | GeneralizerState :: StructurallyRelateAliases => { }
638679 }
639- GeneralizerState :: Default
640- | GeneralizerState :: ShallowStructurallyRelateAliases
641- | GeneralizerState :: StructurallyRelateAliases => { }
642680 }
643681
644682 debug ! ( "replacing original vid={:?} with new={:?}" , vid, new_var_id) ;
@@ -765,13 +803,13 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for Generalizer<'_, 'tcx> {
765803 && !matches ! ( self . infcx. typing_mode( ) , TypingMode :: Coherence )
766804 {
767805 match self . state {
768- GeneralizerState :: IncompletelyRelateHigherRankedAlias => {
806+ GeneralizerState :: IncompletelyRelateAliasArgs => {
769807 variable_table. union ( vid, new_var_id) ;
770808 }
809+ GeneralizerState :: Default
810+ | GeneralizerState :: ShallowStructurallyRelateAliases
811+ | GeneralizerState :: StructurallyRelateAliases => { }
771812 }
772- GeneralizerState :: Default
773- | GeneralizerState :: ShallowStructurallyRelateAliases
774- | GeneralizerState :: StructurallyRelateAliases => { }
775813 }
776814 Ok ( ty:: Const :: new_var ( self . cx ( ) , new_var_id) )
777815 }
0 commit comments