@@ -45,6 +45,22 @@ pub struct SelectionContext<'cx, 'tcx:'cx> {
45
45
/// which is important for checking for trait bounds that
46
46
/// recursively require themselves.
47
47
skolemizer : TypeSkolemizer < ' cx , ' tcx > ,
48
+
49
+ /// If true, indicates that the evaluation should be conservative
50
+ /// and consider the possibility of types outside this crate.
51
+ /// This comes up primarily when resolving ambiguity. Imagine
52
+ /// there is some trait reference `$0 : Bar` where `$0` is an
53
+ /// inference variable. If `intercrate` is true, then we can never
54
+ /// say for sure that this reference is not implemented, even if
55
+ /// there are *no impls at all for `Bar`*, because `$0` could be
56
+ /// bound to some type that in a downstream crate that implements
57
+ /// `Bar`. This is the suitable mode for coherence. Elsewhere,
58
+ /// though, we set this to false, because we are only interested
59
+ /// in types that the user could actually have written --- in
60
+ /// other words, we consider `$0 : Bar` to be unimplemented if
61
+ /// there is no type that the user could *actually name* that
62
+ /// would satisfy it. This avoids crippling inference, basically.
63
+ intercrate : bool ,
48
64
}
49
65
50
66
// A stack that walks back up the stack frame.
@@ -142,6 +158,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
142
158
param_env : param_env,
143
159
typer : typer,
144
160
skolemizer : infcx. skolemizer ( ) ,
161
+ intercrate : false ,
162
+ }
163
+ }
164
+
165
+ pub fn intercrate ( infcx : & ' cx InferCtxt < ' cx , ' tcx > ,
166
+ param_env : & ' cx ty:: ParameterEnvironment ,
167
+ typer : & ' cx Typer < ' tcx > )
168
+ -> SelectionContext < ' cx , ' tcx > {
169
+ SelectionContext {
170
+ infcx : infcx,
171
+ param_env : param_env,
172
+ typer : typer,
173
+ skolemizer : infcx. skolemizer ( ) ,
174
+ intercrate : true ,
145
175
}
146
176
}
147
177
@@ -214,44 +244,20 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
214
244
// The result is "true" if the obligation *may* hold and "false" if
215
245
// we can be sure it does not.
216
246
217
- pub fn evaluate_obligation_intercrate ( & mut self ,
218
- obligation : & Obligation )
219
- -> bool
247
+ pub fn evaluate_obligation ( & mut self ,
248
+ obligation : & Obligation )
249
+ -> bool
220
250
{
221
251
/*!
222
252
* Evaluates whether the obligation `obligation` can be
223
- * satisfied (by any means). This "intercrate" version allows
224
- * for the possibility that unbound type variables may be
225
- * instantiated with types from another crate. This is
226
- * important for coherence. In practice this means that
227
- * unbound type variables must always be considered ambiguous.
253
+ * satisfied (by any means).
228
254
*/
229
255
230
- debug ! ( "evaluate_obligation_intercrate ({})" ,
256
+ debug ! ( "evaluate_obligation ({})" ,
231
257
obligation. repr( self . tcx( ) ) ) ;
232
258
233
259
let stack = self . push_stack ( None , obligation) ;
234
- self . evaluate_stack_intercrate ( & stack) . may_apply ( )
235
- }
236
-
237
- pub fn evaluate_obligation_intracrate ( & mut self ,
238
- obligation : & Obligation )
239
- -> bool
240
- {
241
- /*!
242
- * Evaluates whether the obligation `obligation` can be
243
- * satisfied (by any means). This "intracrate" version does
244
- * not allow for the possibility that unbound type variables
245
- * may be instantiated with types from another crate; hence,
246
- * if there are unbound inputs but no crates locally visible,
247
- * it considers the result to be unimplemented.
248
- */
249
-
250
- debug ! ( "evaluate_obligation_intracrate({})" ,
251
- obligation. repr( self . tcx( ) ) ) ;
252
-
253
- let stack = self . push_stack ( None , obligation) ;
254
- self . evaluate_stack_intracrate ( & stack) . may_apply ( )
260
+ self . evaluate_stack ( & stack) . may_apply ( )
255
261
}
256
262
257
263
fn evaluate_builtin_bound_recursively ( & mut self ,
@@ -288,46 +294,53 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
288
294
289
295
let stack = self . push_stack ( previous_stack. map ( |x| x) , obligation) ;
290
296
291
- // FIXME(#17901) -- Intercrate vs intracrate resolution is a
292
- // tricky question here. For coherence, we want
293
- // intercrate. Also, there was a nasty cycle around impls like
294
- // `impl<T:Eq> Eq for Vec<T>` (which would wind up checking
295
- // whether `$0:Eq`, where $0 was the value substituted for
296
- // `T`, which could then be checked against the very same
297
- // impl). This problem is avoided by the stricter rules around
298
- // unbound type variables by intercrate. I suspect that in the
299
- // latter case a more fine-grained rule would suffice (i.e.,
300
- // consider it ambiguous if even 1 impl matches, no need to
301
- // figure out which one, but call it unimplemented if 0 impls
302
- // match).
303
- let result = self . evaluate_stack_intercrate ( & stack) ;
297
+ let result = self . evaluate_stack ( & stack) ;
304
298
305
299
debug ! ( "result: {}" , result) ;
306
300
result
307
301
}
308
302
309
- fn evaluate_stack_intercrate ( & mut self ,
303
+ fn evaluate_stack ( & mut self ,
310
304
stack : & ObligationStack )
311
305
-> EvaluationResult
312
306
{
313
- // Whenever any of the types are unbound, there can always be
314
- // an impl. Even if there are no impls in this crate, perhaps
315
- // the type would be unified with something from another crate
316
- // that does provide an impl.
307
+ // In intercrate mode, whenever any of the types are unbound,
308
+ // there can always be an impl. Even if there are no impls in
309
+ // this crate, perhaps the type would be unified with
310
+ // something from another crate that does provide an impl.
311
+ //
312
+ // In intracrate mode, we must still be conservative. The reason is
313
+ // that we want to avoid cycles. Imagine an impl like:
314
+ //
315
+ // impl<T:Eq> Eq for Vec<T>
316
+ //
317
+ // and a trait reference like `$0 : Eq` where `$0` is an
318
+ // unbound variable. When we evaluate this trait-reference, we
319
+ // will unify `$0` with `Vec<$1>` (for some fresh variable
320
+ // `$1`), on the condition that `$1 : Eq`. We will then wind
321
+ // up with many candidates (since that are other `Eq` impls
322
+ // that apply) and try to winnow things down. This results in
323
+ // a recurssive evaluation that `$1 : Eq` -- as you can
324
+ // imagine, this is just where we started. To avoid that, we
325
+ // check for unbound variables and return an ambiguous (hence possible)
326
+ // match if we've seen this trait before.
327
+ //
328
+ // This suffices to allow chains like `FnMut` implemented in
329
+ // terms of `Fn` etc, but we could probably make this more
330
+ // precise still.
317
331
let input_types = stack. skol_trait_ref . input_types ( ) ;
318
- if input_types. iter ( ) . any ( |& t| ty:: type_is_skolemized ( t) ) {
319
- debug ! ( "evaluate_stack_intercrate({}) --> unbound argument, must be ambiguous" ,
332
+ let unbound_input_types = input_types. iter ( ) . any ( |& t| ty:: type_is_skolemized ( t) ) ;
333
+ if
334
+ unbound_input_types &&
335
+ ( self . intercrate ||
336
+ stack. iter ( ) . skip ( 1 ) . any (
337
+ |prev| stack. skol_trait_ref . def_id == prev. skol_trait_ref . def_id ) )
338
+ {
339
+ debug ! ( "evaluate_stack_intracrate({}) --> unbound argument, recursion --> ambiguous" ,
320
340
stack. skol_trait_ref. repr( self . tcx( ) ) ) ;
321
341
return EvaluatedToAmbig ;
322
342
}
323
343
324
- self . evaluate_stack_intracrate ( stack)
325
- }
326
-
327
- fn evaluate_stack_intracrate ( & mut self ,
328
- stack : & ObligationStack )
329
- -> EvaluationResult
330
- {
331
344
// If there is any previous entry on the stack that precisely
332
345
// matches this obligation, then we can assume that the
333
346
// obligation is satisfied for now (still all other conditions
@@ -592,7 +605,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
592
605
Err ( _) => { return Err ( ( ) ) ; }
593
606
}
594
607
595
- if self . evaluate_obligation_intracrate ( obligation) {
608
+ if self . evaluate_obligation ( obligation) {
596
609
Ok ( ( ) )
597
610
} else {
598
611
Err ( ( ) )
@@ -804,12 +817,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
804
817
& candidates[ i] ,
805
818
& candidates[ j] ) ) ;
806
819
if is_dup {
807
- debug ! ( "Dropping candidate #{}/# {}: {}" ,
820
+ debug ! ( "Dropping candidate #{}/{}: {}" ,
808
821
i, candidates. len( ) , candidates[ i] . repr( self . tcx( ) ) ) ;
809
822
candidates. swap_remove ( i) ;
810
823
} else {
811
- debug ! ( "Retaining candidate #{}/# {}" ,
812
- i, candidates. len( ) ) ;
824
+ debug ! ( "Retaining candidate #{}/{}: {}" ,
825
+ i, candidates. len( ) , candidates [ i ] . repr ( self . tcx ( ) ) ) ;
813
826
i += 1 ;
814
827
}
815
828
}
@@ -828,7 +841,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
828
841
// be the case that you could still satisfy the obligation
829
842
// from another crate by instantiating the type variables with
830
843
// a type from another crate that does have an impl. This case
831
- // is checked for in `evaluate_obligation ` (and hence users
844
+ // is checked for in `evaluate_stack ` (and hence users
832
845
// who might care about this case, like coherence, should use
833
846
// that function).
834
847
if candidates. len ( ) == 0 {
@@ -849,6 +862,17 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
849
862
// global cache. We want the cache that is specific to this
850
863
// scope whenever where clauses might affect the result.
851
864
865
+ // Avoid using the master cache during coherence and just rely
866
+ // on the local cache. This effectively disables caching
867
+ // during coherence. It is really just a simplification to
868
+ // avoid us having to fear that coherence results "pollute"
869
+ // the master cache. Since coherence executes pretty quickly,
870
+ // it's not worth going to more trouble to increase the
871
+ // hit-rate I don't think.
872
+ if self . intercrate {
873
+ return & self . param_env . selection_cache ;
874
+ }
875
+
852
876
// If the trait refers to any parameters in scope, then use
853
877
// the cache of the param-environment.
854
878
if
0 commit comments