@@ -9,225 +9,18 @@ use hir::LangItem;
99use rustc_hir as hir;
1010use rustc_infer:: traits:: ObligationCause ;
1111use rustc_infer:: traits:: { Obligation , SelectionError , TraitObligation } ;
12- use rustc_middle:: ty:: print:: with_no_trimmed_paths;
1312use rustc_middle:: ty:: { self , Ty , TypeVisitable } ;
1413use rustc_target:: spec:: abi:: Abi ;
1514
1615use crate :: traits;
17- use crate :: traits:: coherence:: Conflict ;
1816use crate :: traits:: query:: evaluate_obligation:: InferCtxtExt ;
19- use crate :: traits:: { util, SelectionResult } ;
20- use crate :: traits:: { ErrorReporting , Overflow , Unimplemented } ;
17+ use crate :: traits:: util;
2118
2219use 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 } ;
2722
2823impl < ' 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-
23124 #[ instrument( skip( self , stack) , level = "debug" ) ]
23225 pub ( super ) fn assemble_candidates < ' o > (
23326 & mut self ,
0 commit comments