9
9
//!
10
10
//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
11
11
use super :: { CanonicalInput , Certainty , EvalCtxt , Goal } ;
12
+ use crate :: solve:: eval_ctxt:: NestedGoals ;
12
13
use crate :: solve:: {
13
14
inspect, response_no_constraints_raw, CanonicalResponse , QueryResult , Response ,
14
15
} ;
@@ -19,6 +20,7 @@ use rustc_infer::infer::canonical::CanonicalVarValues;
19
20
use rustc_infer:: infer:: canonical:: { CanonicalExt , QueryRegionConstraints } ;
20
21
use rustc_infer:: infer:: resolve:: EagerResolver ;
21
22
use rustc_infer:: infer:: { InferCtxt , InferOk } ;
23
+ use rustc_infer:: traits:: solve:: NestedNormalizationGoals ;
22
24
use rustc_middle:: infer:: canonical:: Canonical ;
23
25
use rustc_middle:: traits:: query:: NoSolution ;
24
26
use rustc_middle:: traits:: solve:: {
@@ -28,6 +30,7 @@ use rustc_middle::traits::ObligationCause;
28
30
use rustc_middle:: ty:: { self , BoundVar , GenericArgKind , Ty , TyCtxt , TypeFoldable } ;
29
31
use rustc_next_trait_solver:: canonicalizer:: { CanonicalizeMode , Canonicalizer } ;
30
32
use rustc_span:: DUMMY_SP ;
33
+ use std:: assert_matches:: assert_matches;
31
34
use std:: iter;
32
35
use std:: ops:: Deref ;
33
36
@@ -93,13 +96,31 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
93
96
previous call to `try_evaluate_added_goals!`"
94
97
) ;
95
98
96
- let certainty = certainty. unify_with ( goals_certainty) ;
97
-
98
- let var_values = self . var_values ;
99
- let external_constraints = self . compute_external_query_constraints ( ) ?;
100
-
99
+ // When normalizing, we've replaced the expected term with an unconstrained
100
+ // inference variable. This means that we dropped information which could
101
+ // have been important. We handle this by instead returning the nested goals
102
+ // to the caller, where they are then handled.
103
+ //
104
+ // As we return all ambiguous nested goals, we can ignore the certainty returned
105
+ // by `try_evaluate_added_goals()`.
106
+ let ( certainty, normalization_nested_goals) = if self . is_normalizes_to_goal {
107
+ let NestedGoals { normalizes_to_goals, goals } = std:: mem:: take ( & mut self . nested_goals ) ;
108
+ if cfg ! ( debug_assertions) {
109
+ assert ! ( normalizes_to_goals. is_empty( ) ) ;
110
+ if goals. is_empty ( ) {
111
+ assert_matches ! ( goals_certainty, Certainty :: Yes ) ;
112
+ }
113
+ }
114
+ ( certainty, NestedNormalizationGoals ( goals) )
115
+ } else {
116
+ let certainty = certainty. unify_with ( goals_certainty) ;
117
+ ( certainty, NestedNormalizationGoals :: empty ( ) )
118
+ } ;
119
+
120
+ let external_constraints =
121
+ self . compute_external_query_constraints ( normalization_nested_goals) ?;
101
122
let ( var_values, mut external_constraints) =
102
- ( var_values, external_constraints) . fold_with ( & mut EagerResolver :: new ( self . infcx ) ) ;
123
+ ( self . var_values , external_constraints) . fold_with ( & mut EagerResolver :: new ( self . infcx ) ) ;
103
124
// Remove any trivial region constraints once we've resolved regions
104
125
external_constraints
105
126
. region_constraints
@@ -146,6 +167,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
146
167
#[ instrument( level = "debug" , skip( self ) , ret) ]
147
168
fn compute_external_query_constraints (
148
169
& self ,
170
+ normalization_nested_goals : NestedNormalizationGoals < ' tcx > ,
149
171
) -> Result < ExternalConstraintsData < ' tcx > , NoSolution > {
150
172
// We only check for leaks from universes which were entered inside
151
173
// of the query.
@@ -176,7 +198,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
176
198
self . predefined_opaques_in_body . opaque_types . iter ( ) . all ( |( pa, _) | pa != a)
177
199
} ) ;
178
200
179
- Ok ( ExternalConstraintsData { region_constraints, opaque_types } )
201
+ Ok ( ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals } )
180
202
}
181
203
182
204
/// After calling a canonical query, we apply the constraints returned
@@ -185,13 +207,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
185
207
/// This happens in three steps:
186
208
/// - we instantiate the bound variables of the query response
187
209
/// - we unify the `var_values` of the response with the `original_values`
188
- /// - we apply the `external_constraints` returned by the query
210
+ /// - we apply the `external_constraints` returned by the query, returning
211
+ /// the `normalization_nested_goals`
189
212
pub ( super ) fn instantiate_and_apply_query_response (
190
213
& mut self ,
191
214
param_env : ty:: ParamEnv < ' tcx > ,
192
215
original_values : Vec < ty:: GenericArg < ' tcx > > ,
193
216
response : CanonicalResponse < ' tcx > ,
194
- ) -> Certainty {
217
+ ) -> ( NestedNormalizationGoals < ' tcx > , Certainty ) {
195
218
let instantiation = Self :: compute_query_response_instantiation_values (
196
219
self . infcx ,
197
220
& original_values,
@@ -203,11 +226,14 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
203
226
204
227
Self :: unify_query_var_values ( self . infcx , param_env, & original_values, var_values) ;
205
228
206
- let ExternalConstraintsData { region_constraints, opaque_types } =
207
- external_constraints. deref ( ) ;
229
+ let ExternalConstraintsData {
230
+ region_constraints,
231
+ opaque_types,
232
+ normalization_nested_goals,
233
+ } = external_constraints. deref ( ) ;
208
234
self . register_region_constraints ( region_constraints) ;
209
235
self . register_new_opaque_types ( param_env, opaque_types) ;
210
- certainty
236
+ ( normalization_nested_goals . clone ( ) , certainty)
211
237
}
212
238
213
239
/// This returns the canoncial variable values to instantiate the bound variables of
0 commit comments