11
11
12
12
use std:: assert_matches:: assert_matches;
13
13
14
- use rustc_infer:: infer:: { DefineOpaqueTypes , InferCtxt , InferOk } ;
14
+ use rustc_infer:: infer:: InferCtxt ;
15
+ use rustc_infer:: traits:: Obligation ;
15
16
use rustc_macros:: extension;
16
17
use rustc_middle:: traits:: ObligationCause ;
17
18
use rustc_middle:: traits:: solve:: { Certainty , Goal , GoalSource , NoSolution , QueryResult } ;
@@ -20,7 +21,7 @@ use rustc_middle::{bug, ty};
20
21
use rustc_next_trait_solver:: resolve:: eager_resolve_vars;
21
22
use rustc_next_trait_solver:: solve:: inspect:: { self , instantiate_canonical_state} ;
22
23
use rustc_next_trait_solver:: solve:: { GenerateProofTree , MaybeCause , SolverDelegateEvalExt as _} ;
23
- use rustc_span:: { DUMMY_SP , Span } ;
24
+ use rustc_span:: Span ;
24
25
use tracing:: instrument;
25
26
26
27
use crate :: solve:: delegate:: SolverDelegate ;
@@ -60,28 +61,29 @@ impl<'tcx> NormalizesToTermHack<'tcx> {
60
61
/// Relate the `term` with the new `unconstrained_term` created
61
62
/// when computing the proof tree for this `NormalizesTo` goals.
62
63
/// This handles nested obligations.
63
- fn constrain (
64
- self ,
64
+ fn constrain_and (
65
+ & self ,
65
66
infcx : & InferCtxt < ' tcx > ,
66
67
span : Span ,
67
68
param_env : ty:: ParamEnv < ' tcx > ,
69
+ f : impl FnOnce ( & ObligationCtxt < ' _ , ' tcx > ) ,
68
70
) -> Result < Certainty , NoSolution > {
69
- infcx
70
- . at ( & ObligationCause :: dummy_with_span ( span ) , param_env )
71
- . eq ( DefineOpaqueTypes :: Yes , self . term , self . unconstrained_term )
72
- . map_err ( |_| NoSolution )
73
- . and_then ( | InferOk { value : ( ) , obligations } | {
74
- let ocx = ObligationCtxt :: new ( infcx ) ;
75
- ocx . register_obligations ( obligations ) ;
76
- let errors = ocx . select_all_or_error ( ) ;
77
- if errors . is_empty ( ) {
78
- Ok ( Certainty :: Yes )
79
- } else if errors . iter ( ) . all ( |e| !e . is_true_error ( ) ) {
80
- Ok ( Certainty :: AMBIGUOUS )
81
- } else {
82
- Err ( NoSolution )
83
- }
84
- } )
71
+ let ocx = ObligationCtxt :: new ( infcx) ;
72
+ ocx . eq (
73
+ & ObligationCause :: dummy_with_span ( span ) ,
74
+ param_env ,
75
+ self . term ,
76
+ self . unconstrained_term ,
77
+ ) ? ;
78
+ f ( & ocx ) ;
79
+ let errors = ocx . select_all_or_error ( ) ;
80
+ if errors . is_empty ( ) {
81
+ Ok ( Certainty :: Yes )
82
+ } else if errors . iter ( ) . all ( |e| !e . is_true_error ( ) ) {
83
+ Ok ( Certainty :: AMBIGUOUS )
84
+ } else {
85
+ Err ( NoSolution )
86
+ }
85
87
}
86
88
}
87
89
@@ -180,11 +182,11 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
180
182
let ( ) =
181
183
instantiate_canonical_state ( infcx, span, param_env, & mut orig_values, self . final_state ) ;
182
184
183
- if let Some ( term_hack) = self . goal . normalizes_to_term_hack {
185
+ if let Some ( term_hack) = & self . goal . normalizes_to_term_hack {
184
186
// FIXME: We ignore the expected term of `NormalizesTo` goals
185
187
// when computing the result of its candidates. This is
186
188
// scuffed.
187
- let _ = term_hack. constrain ( infcx, span, param_env) ;
189
+ let _ = term_hack. constrain_and ( infcx, span, param_env, |_| { } ) ;
188
190
}
189
191
190
192
let opt_impl_args = opt_impl_args. map ( |impl_args| eager_resolve_vars ( infcx, impl_args) ) ;
@@ -218,13 +220,35 @@ impl<'a, 'tcx> InspectCandidate<'a, 'tcx> {
218
220
// building their proof tree, the expected term was unconstrained, but when
219
221
// instantiating the candidate it is already constrained to the result of another
220
222
// candidate.
221
- let proof_tree = infcx
222
- . probe ( |_| infcx. evaluate_root_goal_raw ( goal, GenerateProofTree :: Yes , None ) . 1 ) ;
223
+ let normalizes_to_term_hack = NormalizesToTermHack { term, unconstrained_term } ;
224
+ let ( proof_tree, nested_goals_result) = infcx. probe ( |_| {
225
+ let ( w, proof_tree) =
226
+ infcx. evaluate_root_goal_raw ( goal, GenerateProofTree :: Yes , None ) ;
227
+ let proof_tree = proof_tree. unwrap ( ) ;
228
+ let nested_goals_result = w. and_then ( |( nested, _) | {
229
+ normalizes_to_term_hack. constrain_and (
230
+ infcx,
231
+ span,
232
+ proof_tree. uncanonicalized_goal . param_env ,
233
+ |ocx| {
234
+ ocx. register_obligations ( nested. 0 . into_iter ( ) . map ( |( _, goal) | {
235
+ Obligation :: new (
236
+ infcx. tcx ,
237
+ ObligationCause :: dummy_with_span ( span) ,
238
+ goal. param_env ,
239
+ goal. predicate ,
240
+ )
241
+ } ) ) ;
242
+ } ,
243
+ )
244
+ } ) ;
245
+ ( proof_tree, nested_goals_result)
246
+ } ) ;
223
247
InspectGoal :: new (
224
248
infcx,
225
249
self . goal . depth + 1 ,
226
- proof_tree. unwrap ( ) ,
227
- Some ( NormalizesToTermHack { term , unconstrained_term } ) ,
250
+ proof_tree,
251
+ Some ( ( normalizes_to_term_hack , nested_goals_result ) ) ,
228
252
source,
229
253
)
230
254
}
@@ -371,20 +395,19 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
371
395
infcx : & ' a InferCtxt < ' tcx > ,
372
396
depth : usize ,
373
397
root : inspect:: GoalEvaluation < TyCtxt < ' tcx > > ,
374
- normalizes_to_term_hack : Option < NormalizesToTermHack < ' tcx > > ,
398
+ term_hack_and_nested_certainty : Option < (
399
+ NormalizesToTermHack < ' tcx > ,
400
+ Result < Certainty , NoSolution > ,
401
+ ) > ,
375
402
source : GoalSource ,
376
403
) -> Self {
377
404
let infcx = <& SolverDelegate < ' tcx > >:: from ( infcx) ;
378
405
379
406
let inspect:: GoalEvaluation { uncanonicalized_goal, orig_values, evaluation } = root;
380
407
let result = evaluation. result . and_then ( |ok| {
381
- if let Some ( term_hack) = normalizes_to_term_hack {
382
- infcx
383
- . probe ( |_| term_hack. constrain ( infcx, DUMMY_SP , uncanonicalized_goal. param_env ) )
384
- . map ( |certainty| ok. value . certainty . and ( certainty) )
385
- } else {
386
- Ok ( ok. value . certainty )
387
- }
408
+ let nested_goals_certainty =
409
+ term_hack_and_nested_certainty. map_or ( Ok ( Certainty :: Yes ) , |( _, c) | c) ?;
410
+ Ok ( ok. value . certainty . and ( nested_goals_certainty) )
388
411
} ) ;
389
412
390
413
InspectGoal {
@@ -394,7 +417,7 @@ impl<'a, 'tcx> InspectGoal<'a, 'tcx> {
394
417
goal : eager_resolve_vars ( infcx, uncanonicalized_goal) ,
395
418
result,
396
419
evaluation_kind : evaluation. kind ,
397
- normalizes_to_term_hack,
420
+ normalizes_to_term_hack : term_hack_and_nested_certainty . map ( | ( n , _ ) | n ) ,
398
421
source,
399
422
}
400
423
}
0 commit comments