1
1
//! Code shared by trait and projection goals for candidate assembly.
2
2
3
3
use super :: infcx_ext:: InferCtxtExt ;
4
- use super :: {
5
- instantiate_canonical_query_response, CanonicalGoal , CanonicalResponse , Certainty , EvalCtxt ,
6
- Goal ,
7
- } ;
4
+ use super :: { CanonicalResponse , Certainty , EvalCtxt , Goal } ;
8
5
use rustc_hir:: def_id:: DefId ;
9
- use rustc_infer:: infer:: TyCtxtInferExt ;
10
- use rustc_infer:: infer:: {
11
- canonical:: { CanonicalVarValues , OriginalQueryValues } ,
12
- InferCtxt ,
13
- } ;
14
6
use rustc_infer:: traits:: query:: NoSolution ;
15
7
use rustc_middle:: ty:: TypeFoldable ;
16
8
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
17
- use rustc_span:: DUMMY_SP ;
18
9
use std:: fmt:: Debug ;
19
10
20
11
/// A candidate is a possible way to prove a goal.
@@ -40,7 +31,7 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy {
40
31
fn trait_def_id ( self , tcx : TyCtxt < ' tcx > ) -> DefId ;
41
32
42
33
fn consider_impl_candidate (
43
- acx : & mut AssemblyCtxt < ' _ , ' tcx , Self > ,
34
+ acx : & mut AssemblyCtxt < ' _ , ' _ , ' tcx , Self > ,
44
35
goal : Goal < ' tcx , Self > ,
45
36
impl_def_id : DefId ,
46
37
) ;
@@ -49,21 +40,17 @@ pub(super) trait GoalKind<'tcx>: TypeFoldable<'tcx> + Copy {
49
40
/// An abstraction which correctly deals with the canonical results for candidates.
50
41
///
51
42
/// It also deduplicates the behavior between trait and projection predicates.
52
- pub ( super ) struct AssemblyCtxt < ' a , ' tcx , G : GoalKind < ' tcx > > {
53
- pub ( super ) cx : & ' a mut EvalCtxt < ' tcx > ,
54
- pub ( super ) infcx : & ' a InferCtxt < ' tcx > ,
55
- var_values : CanonicalVarValues < ' tcx > ,
43
+ pub ( super ) struct AssemblyCtxt < ' a , ' b , ' tcx , G : GoalKind < ' tcx > > {
44
+ pub ( super ) cx : & ' a mut EvalCtxt < ' b , ' tcx > ,
56
45
candidates : Vec < Candidate < ' tcx , G > > ,
57
46
}
58
47
59
- impl < ' a , ' tcx , G : GoalKind < ' tcx > > AssemblyCtxt < ' a , ' tcx , G > {
48
+ impl < ' a , ' b , ' tcx , G : GoalKind < ' tcx > > AssemblyCtxt < ' a , ' b , ' tcx , G > {
60
49
pub ( super ) fn assemble_and_evaluate_candidates (
61
- cx : & ' a mut EvalCtxt < ' tcx > ,
62
- goal : CanonicalGoal < ' tcx , G > ,
50
+ cx : & ' a mut EvalCtxt < ' b , ' tcx > ,
51
+ goal : Goal < ' tcx , G > ,
63
52
) -> Vec < Candidate < ' tcx , G > > {
64
- let ( ref infcx, goal, var_values) =
65
- cx. tcx . infer_ctxt ( ) . build_with_canonical ( DUMMY_SP , & goal) ;
66
- let mut acx = AssemblyCtxt { cx, infcx, var_values, candidates : Vec :: new ( ) } ;
53
+ let mut acx = AssemblyCtxt { cx, candidates : Vec :: new ( ) } ;
67
54
68
55
acx. assemble_candidates_after_normalizing_self_ty ( goal) ;
69
56
@@ -77,7 +64,7 @@ impl<'a, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'tcx, G> {
77
64
source : G :: CandidateSource ,
78
65
certainty : Certainty ,
79
66
) {
80
- match self . infcx . make_canonical_response ( self . var_values . clone ( ) , certainty) {
67
+ match self . cx . make_canonical_response ( certainty) {
81
68
Ok ( result) => self . candidates . push ( Candidate { source, result } ) ,
82
69
Err ( NoSolution ) => debug ! ( ?source, ?certainty, "failed leakcheck" ) ,
83
70
}
@@ -89,57 +76,46 @@ impl<'a, 'tcx, G: GoalKind<'tcx>> AssemblyCtxt<'a, 'tcx, G> {
89
76
/// self type to the list of candidates in case that succeeds. Note that we can't just eagerly return in
90
77
/// this case as projections as self types add `
91
78
fn assemble_candidates_after_normalizing_self_ty ( & mut self , goal : Goal < ' tcx , G > ) {
92
- let tcx = self . cx . tcx ;
79
+ let tcx = self . cx . tcx ( ) ;
80
+ let infcx = self . cx . infcx ;
93
81
// FIXME: We also have to normalize opaque types, not sure where to best fit that in.
94
82
let & ty:: Alias ( ty:: Projection , projection_ty) = goal. predicate . self_ty ( ) . kind ( ) else {
95
83
return
96
84
} ;
97
- self . infcx . probe ( |_| {
98
- let normalized_ty = self . infcx . next_ty_infer ( ) ;
85
+ infcx. probe ( |_| {
86
+ let normalized_ty = infcx. next_ty_infer ( ) ;
99
87
let normalizes_to_goal = goal. with (
100
88
tcx,
101
89
ty:: Binder :: dummy ( ty:: ProjectionPredicate {
102
90
projection_ty,
103
91
term : normalized_ty. into ( ) ,
104
92
} ) ,
105
93
) ;
106
- let normalization_certainty =
107
- match self . cx . evaluate_goal ( & self . infcx , normalizes_to_goal) {
108
- Ok ( ( _, certainty) ) => certainty,
109
- Err ( NoSolution ) => return ,
110
- } ;
94
+ let normalization_certainty = match self . cx . evaluate_goal ( normalizes_to_goal) {
95
+ Ok ( ( _, certainty) ) => certainty,
96
+ Err ( NoSolution ) => return ,
97
+ } ;
111
98
112
99
// NOTE: Alternatively we could call `evaluate_goal` here and only have a `Normalized` candidate.
113
100
// This doesn't work as long as we use `CandidateSource` in both winnowing and to resolve associated items.
114
101
let goal = goal. with ( tcx, goal. predicate . with_self_ty ( tcx, normalized_ty) ) ;
115
- let mut orig_values = OriginalQueryValues :: default ( ) ;
116
- let goal = self . infcx . canonicalize_query ( goal, & mut orig_values) ;
117
102
let normalized_candidates =
118
103
AssemblyCtxt :: assemble_and_evaluate_candidates ( self . cx , goal) ;
119
-
120
- // Map each candidate from being canonical wrt the current inference context to being
121
- // canonical wrt the caller.
122
- for Candidate { source, result } in normalized_candidates {
123
- self . infcx . probe ( |_| {
124
- let candidate_certainty =
125
- instantiate_canonical_query_response ( & self . infcx , & orig_values, result) ;
126
-
127
- // FIXME: This is a bit scary if the `normalizes_to_goal` overflows.
128
- //
129
- // If we have an ambiguous candidate it hides that normalization
130
- // caused an overflow which may cause issues.
131
- self . try_insert_candidate (
132
- source,
133
- normalization_certainty. unify_and ( candidate_certainty) ,
134
- )
135
- } )
104
+ for mut normalized_candidate in normalized_candidates {
105
+ normalized_candidate. result =
106
+ normalized_candidate. result . unchecked_map ( |mut response| {
107
+ response. certainty = response. certainty . unify_and ( normalization_certainty) ;
108
+ response
109
+ } ) ;
110
+ self . candidates . push ( normalized_candidate) ;
136
111
}
137
112
} )
138
113
}
139
114
140
115
fn assemble_impl_candidates ( & mut self , goal : Goal < ' tcx , G > ) {
141
- self . cx . tcx . for_each_relevant_impl (
142
- goal. predicate . trait_def_id ( self . cx . tcx ) ,
116
+ let tcx = self . cx . tcx ( ) ;
117
+ tcx. for_each_relevant_impl (
118
+ goal. predicate . trait_def_id ( tcx) ,
143
119
goal. predicate . self_ty ( ) ,
144
120
|impl_def_id| G :: consider_impl_candidate ( self , goal, impl_def_id) ,
145
121
) ;
0 commit comments