@@ -45,22 +45,6 @@ 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 ,
64
48
}
65
49
66
50
// A stack that walks back up the stack frame.
@@ -158,20 +142,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
158
142
param_env : param_env,
159
143
typer : typer,
160
144
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 ,
175
145
}
176
146
}
177
147
@@ -244,20 +214,44 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
244
214
// The result is "true" if the obligation *may* hold and "false" if
245
215
// we can be sure it does not.
246
216
247
- pub fn evaluate_obligation ( & mut self ,
248
- obligation : & Obligation )
249
- -> bool
217
+ pub fn evaluate_obligation_intercrate ( & mut self ,
218
+ obligation : & Obligation )
219
+ -> bool
250
220
{
251
221
/*!
252
222
* Evaluates whether the obligation `obligation` can be
253
- * satisfied (by any means).
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.
254
228
*/
255
229
256
- debug ! ( "evaluate_obligation ({})" ,
230
+ debug ! ( "evaluate_obligation_intercrate ({})" ,
257
231
obligation. repr( self . tcx( ) ) ) ;
258
232
259
233
let stack = self . push_stack ( None , obligation) ;
260
- self . evaluate_stack ( & stack) . may_apply ( )
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 ( )
261
255
}
262
256
263
257
fn evaluate_builtin_bound_recursively ( & mut self ,
@@ -294,53 +288,46 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
294
288
295
289
let stack = self . push_stack ( previous_stack. map ( |x| x) , obligation) ;
296
290
297
- let result = self . evaluate_stack ( & stack) ;
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) ;
298
304
299
305
debug ! ( "result: {}" , result) ;
300
306
result
301
307
}
302
308
303
- fn evaluate_stack ( & mut self ,
309
+ fn evaluate_stack_intercrate ( & mut self ,
304
310
stack : & ObligationStack )
305
311
-> EvaluationResult
306
312
{
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.
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.
331
317
let input_types = stack. skol_trait_ref . input_types ( ) ;
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" ,
318
+ if input_types. iter ( ) . any ( |& t| ty:: type_is_skolemized ( t) ) {
319
+ debug ! ( "evaluate_stack_intercrate({}) --> unbound argument, must be ambiguous" ,
340
320
stack. skol_trait_ref. repr( self . tcx( ) ) ) ;
341
321
return EvaluatedToAmbig ;
342
322
}
343
323
324
+ self . evaluate_stack_intracrate ( stack)
325
+ }
326
+
327
+ fn evaluate_stack_intracrate ( & mut self ,
328
+ stack : & ObligationStack )
329
+ -> EvaluationResult
330
+ {
344
331
// If there is any previous entry on the stack that precisely
345
332
// matches this obligation, then we can assume that the
346
333
// obligation is satisfied for now (still all other conditions
@@ -605,7 +592,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
605
592
Err ( _) => { return Err ( ( ) ) ; }
606
593
}
607
594
608
- if self . evaluate_obligation ( obligation) {
595
+ if self . evaluate_obligation_intracrate ( obligation) {
609
596
Ok ( ( ) )
610
597
} else {
611
598
Err ( ( ) )
@@ -817,12 +804,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
817
804
& candidates[ i] ,
818
805
& candidates[ j] ) ) ;
819
806
if is_dup {
820
- debug ! ( "Dropping candidate #{}/{}: {}" ,
807
+ debug ! ( "Dropping candidate #{}/# {}: {}" ,
821
808
i, candidates. len( ) , candidates[ i] . repr( self . tcx( ) ) ) ;
822
809
candidates. swap_remove ( i) ;
823
810
} else {
824
- debug ! ( "Retaining candidate #{}/{}: {}" ,
825
- i, candidates. len( ) , candidates [ i ] . repr ( self . tcx ( ) ) ) ;
811
+ debug ! ( "Retaining candidate #{}/# {}" ,
812
+ i, candidates. len( ) ) ;
826
813
i += 1 ;
827
814
}
828
815
}
@@ -841,7 +828,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
841
828
// be the case that you could still satisfy the obligation
842
829
// from another crate by instantiating the type variables with
843
830
// a type from another crate that does have an impl. This case
844
- // is checked for in `evaluate_stack ` (and hence users
831
+ // is checked for in `evaluate_obligation ` (and hence users
845
832
// who might care about this case, like coherence, should use
846
833
// that function).
847
834
if candidates. len ( ) == 0 {
@@ -862,17 +849,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
862
849
// global cache. We want the cache that is specific to this
863
850
// scope whenever where clauses might affect the result.
864
851
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
-
876
852
// If the trait refers to any parameters in scope, then use
877
853
// the cache of the param-environment.
878
854
if
0 commit comments