@@ -9,225 +9,18 @@ use hir::LangItem;
9
9
use rustc_hir as hir;
10
10
use rustc_infer:: traits:: ObligationCause ;
11
11
use rustc_infer:: traits:: { Obligation , SelectionError , TraitObligation } ;
12
- use rustc_middle:: ty:: print:: with_no_trimmed_paths;
13
12
use rustc_middle:: ty:: { self , Ty , TypeVisitable } ;
14
13
use rustc_target:: spec:: abi:: Abi ;
15
14
16
15
use crate :: traits;
17
- use crate :: traits:: coherence:: Conflict ;
18
16
use crate :: traits:: query:: evaluate_obligation:: InferCtxtExt ;
19
- use crate :: traits:: { util, SelectionResult } ;
20
- use crate :: traits:: { ErrorReporting , Overflow , Unimplemented } ;
17
+ use crate :: traits:: util;
21
18
22
19
use super :: BuiltinImplConditions ;
23
- use super :: IntercrateAmbiguityCause ;
24
- use super :: OverflowError ;
25
- use super :: SelectionCandidate :: { self , * } ;
26
- use super :: { EvaluatedCandidate , SelectionCandidateSet , SelectionContext , TraitObligationStack } ;
20
+ use super :: SelectionCandidate :: * ;
21
+ use super :: { SelectionCandidateSet , SelectionContext , TraitObligationStack } ;
27
22
28
23
impl < ' cx , ' tcx > SelectionContext < ' cx , ' tcx > {
29
- #[ instrument( level = "debug" , skip( self ) , ret) ]
30
- pub ( super ) fn candidate_from_obligation < ' o > (
31
- & mut self ,
32
- stack : & TraitObligationStack < ' o , ' tcx > ,
33
- ) -> SelectionResult < ' tcx , SelectionCandidate < ' tcx > > {
34
- // Watch out for overflow. This intentionally bypasses (and does
35
- // not update) the cache.
36
- self . check_recursion_limit ( & stack. obligation , & stack. obligation ) ?;
37
-
38
- // Check the cache. Note that we freshen the trait-ref
39
- // separately rather than using `stack.fresh_trait_ref` --
40
- // this is because we want the unbound variables to be
41
- // replaced with fresh types starting from index 0.
42
- let cache_fresh_trait_pred = self . infcx . freshen ( stack. obligation . predicate ) ;
43
- debug ! ( ?cache_fresh_trait_pred) ;
44
- debug_assert ! ( !stack. obligation. predicate. has_escaping_bound_vars( ) ) ;
45
-
46
- if let Some ( c) =
47
- self . check_candidate_cache ( stack. obligation . param_env , cache_fresh_trait_pred)
48
- {
49
- debug ! ( "CACHE HIT" ) ;
50
- return c;
51
- }
52
-
53
- // If no match, compute result and insert into cache.
54
- //
55
- // FIXME(nikomatsakis) -- this cache is not taking into
56
- // account cycles that may have occurred in forming the
57
- // candidate. I don't know of any specific problems that
58
- // result but it seems awfully suspicious.
59
- let ( candidate, dep_node) =
60
- self . in_task ( |this| this. candidate_from_obligation_no_cache ( stack) ) ;
61
-
62
- debug ! ( "CACHE MISS" ) ;
63
- self . insert_candidate_cache (
64
- stack. obligation . param_env ,
65
- cache_fresh_trait_pred,
66
- dep_node,
67
- candidate. clone ( ) ,
68
- ) ;
69
- candidate
70
- }
71
-
72
- fn candidate_from_obligation_no_cache < ' o > (
73
- & mut self ,
74
- stack : & TraitObligationStack < ' o , ' tcx > ,
75
- ) -> SelectionResult < ' tcx , SelectionCandidate < ' tcx > > {
76
- if let Err ( conflict) = self . is_knowable ( stack) {
77
- debug ! ( "coherence stage: not knowable" ) ;
78
- if self . intercrate_ambiguity_causes . is_some ( ) {
79
- debug ! ( "evaluate_stack: intercrate_ambiguity_causes is some" ) ;
80
- // Heuristics: show the diagnostics when there are no candidates in crate.
81
- if let Ok ( candidate_set) = self . assemble_candidates ( stack) {
82
- let mut no_candidates_apply = true ;
83
-
84
- for c in candidate_set. vec . iter ( ) {
85
- if self . evaluate_candidate ( stack, & c) ?. may_apply ( ) {
86
- no_candidates_apply = false ;
87
- break ;
88
- }
89
- }
90
-
91
- if !candidate_set. ambiguous && no_candidates_apply {
92
- let trait_ref = stack. obligation . predicate . skip_binder ( ) . trait_ref ;
93
- let self_ty = trait_ref. self_ty ( ) ;
94
- let ( trait_desc, self_desc) = with_no_trimmed_paths ! ( {
95
- let trait_desc = trait_ref. print_only_trait_path( ) . to_string( ) ;
96
- let self_desc = if self_ty. has_concrete_skeleton( ) {
97
- Some ( self_ty. to_string( ) )
98
- } else {
99
- None
100
- } ;
101
- ( trait_desc, self_desc)
102
- } ) ;
103
- let cause = if let Conflict :: Upstream = conflict {
104
- IntercrateAmbiguityCause :: UpstreamCrateUpdate { trait_desc, self_desc }
105
- } else {
106
- IntercrateAmbiguityCause :: DownstreamCrate { trait_desc, self_desc }
107
- } ;
108
- debug ! ( ?cause, "evaluate_stack: pushing cause" ) ;
109
- self . intercrate_ambiguity_causes . as_mut ( ) . unwrap ( ) . insert ( cause) ;
110
- }
111
- }
112
- }
113
- return Ok ( None ) ;
114
- }
115
-
116
- let candidate_set = self . assemble_candidates ( stack) ?;
117
-
118
- if candidate_set. ambiguous {
119
- debug ! ( "candidate set contains ambig" ) ;
120
- return Ok ( None ) ;
121
- }
122
-
123
- let candidates = candidate_set. vec ;
124
-
125
- debug ! ( ?stack, ?candidates, "assembled {} candidates" , candidates. len( ) ) ;
126
-
127
- // At this point, we know that each of the entries in the
128
- // candidate set is *individually* applicable. Now we have to
129
- // figure out if they contain mutual incompatibilities. This
130
- // frequently arises if we have an unconstrained input type --
131
- // for example, we are looking for `$0: Eq` where `$0` is some
132
- // unconstrained type variable. In that case, we'll get a
133
- // candidate which assumes $0 == int, one that assumes `$0 ==
134
- // usize`, etc. This spells an ambiguity.
135
-
136
- let mut candidates = self . filter_impls ( candidates, stack. obligation ) ;
137
-
138
- // If there is more than one candidate, first winnow them down
139
- // by considering extra conditions (nested obligations and so
140
- // forth). We don't winnow if there is exactly one
141
- // candidate. This is a relatively minor distinction but it
142
- // can lead to better inference and error-reporting. An
143
- // example would be if there was an impl:
144
- //
145
- // impl<T:Clone> Vec<T> { fn push_clone(...) { ... } }
146
- //
147
- // and we were to see some code `foo.push_clone()` where `boo`
148
- // is a `Vec<Bar>` and `Bar` does not implement `Clone`. If
149
- // we were to winnow, we'd wind up with zero candidates.
150
- // Instead, we select the right impl now but report "`Bar` does
151
- // not implement `Clone`".
152
- if candidates. len ( ) == 1 {
153
- return self . filter_reservation_impls ( candidates. pop ( ) . unwrap ( ) , stack. obligation ) ;
154
- }
155
-
156
- // Winnow, but record the exact outcome of evaluation, which
157
- // is needed for specialization. Propagate overflow if it occurs.
158
- let mut candidates = candidates
159
- . into_iter ( )
160
- . map ( |c| match self . evaluate_candidate ( stack, & c) {
161
- Ok ( eval) if eval. may_apply ( ) => {
162
- Ok ( Some ( EvaluatedCandidate { candidate : c, evaluation : eval } ) )
163
- }
164
- Ok ( _) => Ok ( None ) ,
165
- Err ( OverflowError :: Canonical ) => Err ( Overflow ( OverflowError :: Canonical ) ) ,
166
- Err ( OverflowError :: ErrorReporting ) => Err ( ErrorReporting ) ,
167
- Err ( OverflowError :: Error ( e) ) => Err ( Overflow ( OverflowError :: Error ( e) ) ) ,
168
- } )
169
- . flat_map ( Result :: transpose)
170
- . collect :: < Result < Vec < _ > , _ > > ( ) ?;
171
-
172
- debug ! ( ?stack, ?candidates, "winnowed to {} candidates" , candidates. len( ) ) ;
173
-
174
- let needs_infer = stack. obligation . predicate . has_non_region_infer ( ) ;
175
-
176
- // If there are STILL multiple candidates, we can further
177
- // reduce the list by dropping duplicates -- including
178
- // resolving specializations.
179
- if candidates. len ( ) > 1 {
180
- let mut i = 0 ;
181
- while i < candidates. len ( ) {
182
- let is_dup = ( 0 ..candidates. len ( ) ) . filter ( |& j| i != j) . any ( |j| {
183
- self . candidate_should_be_dropped_in_favor_of (
184
- & candidates[ i] ,
185
- & candidates[ j] ,
186
- needs_infer,
187
- )
188
- } ) ;
189
- if is_dup {
190
- debug ! ( candidate = ?candidates[ i] , "Dropping candidate #{}/{}" , i, candidates. len( ) ) ;
191
- candidates. swap_remove ( i) ;
192
- } else {
193
- debug ! ( candidate = ?candidates[ i] , "Retaining candidate #{}/{}" , i, candidates. len( ) ) ;
194
- i += 1 ;
195
-
196
- // If there are *STILL* multiple candidates, give up
197
- // and report ambiguity.
198
- if i > 1 {
199
- debug ! ( "multiple matches, ambig" ) ;
200
- return Ok ( None ) ;
201
- }
202
- }
203
- }
204
- }
205
-
206
- // If there are *NO* candidates, then there are no impls --
207
- // that we know of, anyway. Note that in the case where there
208
- // are unbound type variables within the obligation, it might
209
- // be the case that you could still satisfy the obligation
210
- // from another crate by instantiating the type variables with
211
- // a type from another crate that does have an impl. This case
212
- // is checked for in `evaluate_stack` (and hence users
213
- // who might care about this case, like coherence, should use
214
- // that function).
215
- if candidates. is_empty ( ) {
216
- // If there's an error type, 'downgrade' our result from
217
- // `Err(Unimplemented)` to `Ok(None)`. This helps us avoid
218
- // emitting additional spurious errors, since we're guaranteed
219
- // to have emitted at least one.
220
- if stack. obligation . predicate . references_error ( ) {
221
- debug ! ( ?stack. obligation. predicate, "found error type in predicate, treating as ambiguous" ) ;
222
- return Ok ( None ) ;
223
- }
224
- return Err ( Unimplemented ) ;
225
- }
226
-
227
- // Just one candidate left.
228
- self . filter_reservation_impls ( candidates. pop ( ) . unwrap ( ) . candidate , stack. obligation )
229
- }
230
-
231
24
#[ instrument( skip( self , stack) , level = "debug" ) ]
232
25
pub ( super ) fn assemble_candidates < ' o > (
233
26
& mut self ,
0 commit comments