1
+ use std:: mem;
1
2
use std:: ops:: ControlFlow ;
2
3
3
- use derive_where:: derive_where;
4
4
#[ cfg( feature = "nightly" ) ]
5
- use rustc_macros:: { Decodable_NoContext , Encodable_NoContext , HashStable_NoContext } ;
5
+ use rustc_macros:: HashStable_NoContext ;
6
6
use rustc_type_ir:: data_structures:: { HashMap , HashSet , ensure_sufficient_stack} ;
7
7
use rustc_type_ir:: fast_reject:: DeepRejectCtxt ;
8
8
use rustc_type_ir:: inherent:: * ;
@@ -14,7 +14,6 @@ use rustc_type_ir::{
14
14
TypeSuperFoldable , TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor ,
15
15
TypingMode ,
16
16
} ;
17
- use rustc_type_ir_macros:: { Lift_Generic , TypeFoldable_Generic , TypeVisitable_Generic } ;
18
17
use tracing:: { instrument, trace} ;
19
18
20
19
use crate :: coherence;
@@ -114,7 +113,7 @@ where
114
113
115
114
pub ( super ) search_graph : & ' a mut SearchGraph < D > ,
116
115
117
- nested_goals : NestedGoals < I > ,
116
+ nested_goals : Vec < ( GoalSource , Goal < I , I :: Predicate > ) > ,
118
117
119
118
pub ( super ) origin_span : I :: Span ,
120
119
@@ -129,38 +128,6 @@ where
129
128
pub ( super ) inspect : ProofTreeBuilder < D > ,
130
129
}
131
130
132
- #[ derive_where( Clone , Debug , Default ; I : Interner ) ]
133
- #[ derive( TypeVisitable_Generic , TypeFoldable_Generic , Lift_Generic ) ]
134
- #[ cfg_attr(
135
- feature = "nightly" ,
136
- derive( Decodable_NoContext , Encodable_NoContext , HashStable_NoContext )
137
- ) ]
138
- struct NestedGoals < I : Interner > {
139
- /// These normalizes-to goals are treated specially during the evaluation
140
- /// loop. In each iteration we take the RHS of the projection, replace it with
141
- /// a fresh inference variable, and only after evaluating that goal do we
142
- /// equate the fresh inference variable with the actual RHS of the predicate.
143
- ///
144
- /// This is both to improve caching, and to avoid using the RHS of the
145
- /// projection predicate to influence the normalizes-to candidate we select.
146
- ///
147
- /// Forgetting to replace the RHS with a fresh inference variable when we evaluate
148
- /// this goal results in an ICE..
149
- pub normalizes_to_goals : Vec < Goal < I , ty:: NormalizesTo < I > > > ,
150
- /// The rest of the goals which have not yet processed or remain ambiguous.
151
- pub goals : Vec < ( GoalSource , Goal < I , I :: Predicate > ) > ,
152
- }
153
-
154
- impl < I : Interner > NestedGoals < I > {
155
- fn new ( ) -> Self {
156
- Self { normalizes_to_goals : Vec :: new ( ) , goals : Vec :: new ( ) }
157
- }
158
-
159
- fn is_empty ( & self ) -> bool {
160
- self . normalizes_to_goals . is_empty ( ) && self . goals . is_empty ( )
161
- }
162
- }
163
-
164
131
#[ derive( PartialEq , Eq , Debug , Hash , Clone , Copy ) ]
165
132
#[ cfg_attr( feature = "nightly" , derive( HashStable_NoContext ) ) ]
166
133
pub enum GenerateProofTree {
@@ -332,7 +299,7 @@ where
332
299
let mut ecx = EvalCtxt {
333
300
delegate,
334
301
search_graph : & mut search_graph,
335
- nested_goals : NestedGoals :: new ( ) ,
302
+ nested_goals : Default :: default ( ) ,
336
303
inspect : ProofTreeBuilder :: new_maybe_root ( generate_proof_tree) ,
337
304
338
305
// Only relevant when canonicalizing the response,
@@ -385,7 +352,7 @@ where
385
352
predefined_opaques_in_body : input. predefined_opaques_in_body ,
386
353
max_input_universe : canonical_input. canonical . max_universe ,
387
354
search_graph,
388
- nested_goals : NestedGoals :: new ( ) ,
355
+ nested_goals : Default :: default ( ) ,
389
356
origin_span : I :: Span :: dummy ( ) ,
390
357
tainted : Ok ( ( ) ) ,
391
358
inspect : canonical_goal_evaluation. new_goal_evaluation_step ( var_values) ,
@@ -629,78 +596,83 @@ where
629
596
/// Goals for the next step get directly added to the nested goals of the `EvalCtxt`.
630
597
fn evaluate_added_goals_step ( & mut self ) -> Result < Option < Certainty > , NoSolution > {
631
598
let cx = self . cx ( ) ;
632
- let mut goals = core:: mem:: take ( & mut self . nested_goals ) ;
633
-
634
599
// If this loop did not result in any progress, what's our final certainty.
635
600
let mut unchanged_certainty = Some ( Certainty :: Yes ) ;
636
- for goal in goals. normalizes_to_goals {
637
- // Replace the goal with an unconstrained infer var, so the
638
- // RHS does not affect projection candidate assembly.
639
- let unconstrained_rhs = self . next_term_infer_of_kind ( goal. predicate . term ) ;
640
- let unconstrained_goal = goal. with (
641
- cx,
642
- ty:: NormalizesTo { alias : goal. predicate . alias , term : unconstrained_rhs } ,
643
- ) ;
644
-
645
- let ( NestedNormalizationGoals ( nested_goals) , _, certainty) = self . evaluate_goal_raw (
646
- GoalEvaluationKind :: Nested ,
647
- GoalSource :: TypeRelating ,
648
- unconstrained_goal,
649
- ) ?;
650
- // Add the nested goals from normalization to our own nested goals.
651
- trace ! ( ?nested_goals) ;
652
- goals. goals . extend ( nested_goals) ;
653
-
654
- // Finally, equate the goal's RHS with the unconstrained var.
601
+ for ( source, goal) in mem:: take ( & mut self . nested_goals ) {
602
+ // We treat normalizes-to goals specially here. In each iteration we take the
603
+ // RHS of the projection, replace it with a fresh inference variable, and only
604
+ // after evaluating that goal do we equate the fresh inference variable with the
605
+ // actual RHS of the predicate.
655
606
//
656
- // SUBTLE:
657
- // We structurally relate aliases here. This is necessary
658
- // as we otherwise emit a nested `AliasRelate` goal in case the
659
- // returned term is a rigid alias, resulting in overflow.
607
+ // This is both to improve caching, and to avoid using the RHS of the
608
+ // projection predicate to influence the normalizes-to candidate we select.
660
609
//
661
- // It is correct as both `goal.predicate.term` and `unconstrained_rhs`
662
- // start out as an unconstrained inference variable so any aliases get
663
- // fully normalized when instantiating it.
664
- //
665
- // FIXME: Strictly speaking this may be incomplete if the normalized-to
666
- // type contains an ambiguous alias referencing bound regions. We should
667
- // consider changing this to only use "shallow structural equality".
668
- self . eq_structurally_relating_aliases (
669
- goal. param_env ,
670
- goal. predicate . term ,
671
- unconstrained_rhs,
672
- ) ?;
673
-
674
- // We only look at the `projection_ty` part here rather than
675
- // looking at the "has changed" return from evaluate_goal,
676
- // because we expect the `unconstrained_rhs` part of the predicate
677
- // to have changed -- that means we actually normalized successfully!
678
- let with_resolved_vars = self . resolve_vars_if_possible ( goal) ;
679
- if goal. predicate . alias != with_resolved_vars. predicate . alias {
680
- unchanged_certainty = None ;
681
- }
682
-
683
- match certainty {
684
- Certainty :: Yes => { }
685
- Certainty :: Maybe ( _) => {
686
- self . nested_goals . normalizes_to_goals . push ( with_resolved_vars) ;
687
- unchanged_certainty = unchanged_certainty. map ( |c| c. unify_with ( certainty) ) ;
610
+ // Forgetting to replace the RHS with a fresh inference variable when we evaluate
611
+ // this goal results in an ICE.
612
+ if let Some ( pred) = goal. predicate . as_normalizes_to ( ) {
613
+ // We should never encounter higher-ranked normalizes-to goals.
614
+ let pred = pred. no_bound_vars ( ) . unwrap ( ) ;
615
+ // Replace the goal with an unconstrained infer var, so the
616
+ // RHS does not affect projection candidate assembly.
617
+ let unconstrained_rhs = self . next_term_infer_of_kind ( pred. term ) ;
618
+ let unconstrained_goal =
619
+ goal. with ( cx, ty:: NormalizesTo { alias : pred. alias , term : unconstrained_rhs } ) ;
620
+
621
+ let ( NestedNormalizationGoals ( nested_goals) , _, certainty) =
622
+ self . evaluate_goal_raw ( GoalEvaluationKind :: Nested , source, unconstrained_goal) ?;
623
+ // Add the nested goals from normalization to our own nested goals.
624
+ trace ! ( ?nested_goals) ;
625
+ self . nested_goals . extend ( nested_goals) ;
626
+
627
+ // Finally, equate the goal's RHS with the unconstrained var.
628
+ //
629
+ // SUBTLE:
630
+ // We structurally relate aliases here. This is necessary
631
+ // as we otherwise emit a nested `AliasRelate` goal in case the
632
+ // returned term is a rigid alias, resulting in overflow.
633
+ //
634
+ // It is correct as both `goal.predicate.term` and `unconstrained_rhs`
635
+ // start out as an unconstrained inference variable so any aliases get
636
+ // fully normalized when instantiating it.
637
+ //
638
+ // FIXME: Strictly speaking this may be incomplete if the normalized-to
639
+ // type contains an ambiguous alias referencing bound regions. We should
640
+ // consider changing this to only use "shallow structural equality".
641
+ self . eq_structurally_relating_aliases (
642
+ goal. param_env ,
643
+ pred. term ,
644
+ unconstrained_rhs,
645
+ ) ?;
646
+
647
+ // We only look at the `projection_ty` part here rather than
648
+ // looking at the "has changed" return from evaluate_goal,
649
+ // because we expect the `unconstrained_rhs` part of the predicate
650
+ // to have changed -- that means we actually normalized successfully!
651
+ let with_resolved_vars = self . resolve_vars_if_possible ( goal) ;
652
+ if pred. alias != goal. predicate . as_normalizes_to ( ) . unwrap ( ) . skip_binder ( ) . alias {
653
+ unchanged_certainty = None ;
688
654
}
689
- }
690
- }
691
655
692
- for ( source, goal) in goals. goals {
693
- let ( has_changed, certainty) =
694
- self . evaluate_goal ( GoalEvaluationKind :: Nested , source, goal) ?;
695
- if has_changed == HasChanged :: Yes {
696
- unchanged_certainty = None ;
697
- }
656
+ match certainty {
657
+ Certainty :: Yes => { }
658
+ Certainty :: Maybe ( _) => {
659
+ self . nested_goals . push ( ( source, with_resolved_vars) ) ;
660
+ unchanged_certainty = unchanged_certainty. map ( |c| c. unify_with ( certainty) ) ;
661
+ }
662
+ }
663
+ } else {
664
+ let ( has_changed, certainty) =
665
+ self . evaluate_goal ( GoalEvaluationKind :: Nested , source, goal) ?;
666
+ if has_changed == HasChanged :: Yes {
667
+ unchanged_certainty = None ;
668
+ }
698
669
699
- match certainty {
700
- Certainty :: Yes => { }
701
- Certainty :: Maybe ( _) => {
702
- self . nested_goals . goals . push ( ( source, goal) ) ;
703
- unchanged_certainty = unchanged_certainty. map ( |c| c. unify_with ( certainty) ) ;
670
+ match certainty {
671
+ Certainty :: Yes => { }
672
+ Certainty :: Maybe ( _) => {
673
+ self . nested_goals . push ( ( source, goal) ) ;
674
+ unchanged_certainty = unchanged_certainty. map ( |c| c. unify_with ( certainty) ) ;
675
+ }
704
676
}
705
677
}
706
678
}
@@ -717,23 +689,12 @@ where
717
689
self . delegate . cx ( )
718
690
}
719
691
720
- #[ instrument( level = "trace" , skip( self ) ) ]
721
- pub ( super ) fn add_normalizes_to_goal ( & mut self , mut goal : Goal < I , ty:: NormalizesTo < I > > ) {
722
- goal. predicate = goal. predicate . fold_with ( & mut ReplaceAliasWithInfer :: new (
723
- self ,
724
- GoalSource :: TypeRelating ,
725
- goal. param_env ,
726
- ) ) ;
727
- self . inspect . add_normalizes_to_goal ( self . delegate , self . max_input_universe , goal) ;
728
- self . nested_goals . normalizes_to_goals . push ( goal) ;
729
- }
730
-
731
692
#[ instrument( level = "debug" , skip( self ) ) ]
732
693
pub ( super ) fn add_goal ( & mut self , source : GoalSource , mut goal : Goal < I , I :: Predicate > ) {
733
694
goal. predicate =
734
695
goal. predicate . fold_with ( & mut ReplaceAliasWithInfer :: new ( self , source, goal. param_env ) ) ;
735
696
self . inspect . add_goal ( self . delegate , self . max_input_universe , source, goal) ;
736
- self . nested_goals . goals . push ( ( source, goal) ) ;
697
+ self . nested_goals . push ( ( source, goal) ) ;
737
698
}
738
699
739
700
#[ instrument( level = "trace" , skip( self , goals) ) ]
0 commit comments