@@ -41,7 +41,6 @@ use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, Wit
41
41
use rustc_hir:: def_id:: DefId ;
42
42
43
43
use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
44
- use rustc_data_structures:: sync:: Lock ;
45
44
use rustc_hir as hir;
46
45
use rustc_index:: bit_set:: GrowableBitSet ;
47
46
use rustc_span:: symbol:: sym;
@@ -53,6 +52,8 @@ use std::iter;
53
52
use std:: rc:: Rc ;
54
53
use syntax:: { ast, attr} ;
55
54
55
+ pub use rustc:: traits:: types:: select:: * ;
56
+
56
57
pub struct SelectionContext < ' cx , ' tcx > {
57
58
infcx : & ' cx InferCtxt < ' cx , ' tcx > ,
58
59
@@ -181,146 +182,6 @@ struct TraitObligationStack<'prev, 'tcx> {
181
182
dfn : usize ,
182
183
}
183
184
184
- #[ derive( Clone , Default ) ]
185
- pub struct SelectionCache < ' tcx > {
186
- hashmap : Lock <
187
- FxHashMap <
188
- ty:: ParamEnvAnd < ' tcx , ty:: TraitRef < ' tcx > > ,
189
- WithDepNode < SelectionResult < ' tcx , SelectionCandidate < ' tcx > > > ,
190
- > ,
191
- > ,
192
- }
193
-
194
- /// The selection process begins by considering all impls, where
195
- /// clauses, and so forth that might resolve an obligation. Sometimes
196
- /// we'll be able to say definitively that (e.g.) an impl does not
197
- /// apply to the obligation: perhaps it is defined for `usize` but the
198
- /// obligation is for `int`. In that case, we drop the impl out of the
199
- /// list. But the other cases are considered *candidates*.
200
- ///
201
- /// For selection to succeed, there must be exactly one matching
202
- /// candidate. If the obligation is fully known, this is guaranteed
203
- /// by coherence. However, if the obligation contains type parameters
204
- /// or variables, there may be multiple such impls.
205
- ///
206
- /// It is not a real problem if multiple matching impls exist because
207
- /// of type variables - it just means the obligation isn't sufficiently
208
- /// elaborated. In that case we report an ambiguity, and the caller can
209
- /// try again after more type information has been gathered or report a
210
- /// "type annotations needed" error.
211
- ///
212
- /// However, with type parameters, this can be a real problem - type
213
- /// parameters don't unify with regular types, but they *can* unify
214
- /// with variables from blanket impls, and (unless we know its bounds
215
- /// will always be satisfied) picking the blanket impl will be wrong
216
- /// for at least *some* substitutions. To make this concrete, if we have
217
- ///
218
- /// trait AsDebug { type Out : fmt::Debug; fn debug(self) -> Self::Out; }
219
- /// impl<T: fmt::Debug> AsDebug for T {
220
- /// type Out = T;
221
- /// fn debug(self) -> fmt::Debug { self }
222
- /// }
223
- /// fn foo<T: AsDebug>(t: T) { println!("{:?}", <T as AsDebug>::debug(t)); }
224
- ///
225
- /// we can't just use the impl to resolve the `<T as AsDebug>` obligation
226
- /// -- a type from another crate (that doesn't implement `fmt::Debug`) could
227
- /// implement `AsDebug`.
228
- ///
229
- /// Because where-clauses match the type exactly, multiple clauses can
230
- /// only match if there are unresolved variables, and we can mostly just
231
- /// report this ambiguity in that case. This is still a problem - we can't
232
- /// *do anything* with ambiguities that involve only regions. This is issue
233
- /// #21974.
234
- ///
235
- /// If a single where-clause matches and there are no inference
236
- /// variables left, then it definitely matches and we can just select
237
- /// it.
238
- ///
239
- /// In fact, we even select the where-clause when the obligation contains
240
- /// inference variables. The can lead to inference making "leaps of logic",
241
- /// for example in this situation:
242
- ///
243
- /// pub trait Foo<T> { fn foo(&self) -> T; }
244
- /// impl<T> Foo<()> for T { fn foo(&self) { } }
245
- /// impl Foo<bool> for bool { fn foo(&self) -> bool { *self } }
246
- ///
247
- /// pub fn foo<T>(t: T) where T: Foo<bool> {
248
- /// println!("{:?}", <T as Foo<_>>::foo(&t));
249
- /// }
250
- /// fn main() { foo(false); }
251
- ///
252
- /// Here the obligation `<T as Foo<$0>>` can be matched by both the blanket
253
- /// impl and the where-clause. We select the where-clause and unify `$0=bool`,
254
- /// so the program prints "false". However, if the where-clause is omitted,
255
- /// the blanket impl is selected, we unify `$0=()`, and the program prints
256
- /// "()".
257
- ///
258
- /// Exactly the same issues apply to projection and object candidates, except
259
- /// that we can have both a projection candidate and a where-clause candidate
260
- /// for the same obligation. In that case either would do (except that
261
- /// different "leaps of logic" would occur if inference variables are
262
- /// present), and we just pick the where-clause. This is, for example,
263
- /// required for associated types to work in default impls, as the bounds
264
- /// are visible both as projection bounds and as where-clauses from the
265
- /// parameter environment.
266
- #[ derive( PartialEq , Eq , Debug , Clone , TypeFoldable ) ]
267
- enum SelectionCandidate < ' tcx > {
268
- BuiltinCandidate {
269
- /// `false` if there are no *further* obligations.
270
- has_nested : bool ,
271
- } ,
272
- ParamCandidate ( ty:: PolyTraitRef < ' tcx > ) ,
273
- ImplCandidate ( DefId ) ,
274
- AutoImplCandidate ( DefId ) ,
275
-
276
- /// This is a trait matching with a projected type as `Self`, and
277
- /// we found an applicable bound in the trait definition.
278
- ProjectionCandidate ,
279
-
280
- /// Implementation of a `Fn`-family trait by one of the anonymous types
281
- /// generated for a `||` expression.
282
- ClosureCandidate ,
283
-
284
- /// Implementation of a `Generator` trait by one of the anonymous types
285
- /// generated for a generator.
286
- GeneratorCandidate ,
287
-
288
- /// Implementation of a `Fn`-family trait by one of the anonymous
289
- /// types generated for a fn pointer type (e.g., `fn(int) -> int`)
290
- FnPointerCandidate ,
291
-
292
- TraitAliasCandidate ( DefId ) ,
293
-
294
- ObjectCandidate ,
295
-
296
- BuiltinObjectCandidate ,
297
-
298
- BuiltinUnsizeCandidate ,
299
- }
300
-
301
- impl < ' a , ' tcx > ty:: Lift < ' tcx > for SelectionCandidate < ' a > {
302
- type Lifted = SelectionCandidate < ' tcx > ;
303
- fn lift_to_tcx ( & self , tcx : TyCtxt < ' tcx > ) -> Option < Self :: Lifted > {
304
- Some ( match * self {
305
- BuiltinCandidate { has_nested } => BuiltinCandidate { has_nested } ,
306
- ImplCandidate ( def_id) => ImplCandidate ( def_id) ,
307
- AutoImplCandidate ( def_id) => AutoImplCandidate ( def_id) ,
308
- ProjectionCandidate => ProjectionCandidate ,
309
- ClosureCandidate => ClosureCandidate ,
310
- GeneratorCandidate => GeneratorCandidate ,
311
- FnPointerCandidate => FnPointerCandidate ,
312
- TraitAliasCandidate ( def_id) => TraitAliasCandidate ( def_id) ,
313
- ObjectCandidate => ObjectCandidate ,
314
- BuiltinObjectCandidate => BuiltinObjectCandidate ,
315
- BuiltinUnsizeCandidate => BuiltinUnsizeCandidate ,
316
-
317
- ParamCandidate ( ref trait_ref) => {
318
- return tcx. lift ( trait_ref) . map ( ParamCandidate ) ;
319
- }
320
- } )
321
- }
322
- }
323
-
324
185
struct SelectionCandidateSet < ' tcx > {
325
186
// A list of candidates that definitely apply to the current
326
187
// obligation (meaning: types unify).
@@ -350,134 +211,6 @@ enum BuiltinImplConditions<'tcx> {
350
211
Ambiguous ,
351
212
}
352
213
353
- /// The result of trait evaluation. The order is important
354
- /// here as the evaluation of a list is the maximum of the
355
- /// evaluations.
356
- ///
357
- /// The evaluation results are ordered:
358
- /// - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions`
359
- /// implies `EvaluatedToAmbig` implies `EvaluatedToUnknown`
360
- /// - `EvaluatedToErr` implies `EvaluatedToRecur`
361
- /// - the "union" of evaluation results is equal to their maximum -
362
- /// all the "potential success" candidates can potentially succeed,
363
- /// so they are noops when unioned with a definite error, and within
364
- /// the categories it's easy to see that the unions are correct.
365
- #[ derive( Copy , Clone , Debug , PartialOrd , Ord , PartialEq , Eq , HashStable ) ]
366
- pub enum EvaluationResult {
367
- /// Evaluation successful.
368
- EvaluatedToOk ,
369
- /// Evaluation successful, but there were unevaluated region obligations.
370
- EvaluatedToOkModuloRegions ,
371
- /// Evaluation is known to be ambiguous -- it *might* hold for some
372
- /// assignment of inference variables, but it might not.
373
- ///
374
- /// While this has the same meaning as `EvaluatedToUnknown` -- we can't
375
- /// know whether this obligation holds or not -- it is the result we
376
- /// would get with an empty stack, and therefore is cacheable.
377
- EvaluatedToAmbig ,
378
- /// Evaluation failed because of recursion involving inference
379
- /// variables. We are somewhat imprecise there, so we don't actually
380
- /// know the real result.
381
- ///
382
- /// This can't be trivially cached for the same reason as `EvaluatedToRecur`.
383
- EvaluatedToUnknown ,
384
- /// Evaluation failed because we encountered an obligation we are already
385
- /// trying to prove on this branch.
386
- ///
387
- /// We know this branch can't be a part of a minimal proof-tree for
388
- /// the "root" of our cycle, because then we could cut out the recursion
389
- /// and maintain a valid proof tree. However, this does not mean
390
- /// that all the obligations on this branch do not hold -- it's possible
391
- /// that we entered this branch "speculatively", and that there
392
- /// might be some other way to prove this obligation that does not
393
- /// go through this cycle -- so we can't cache this as a failure.
394
- ///
395
- /// For example, suppose we have this:
396
- ///
397
- /// ```rust,ignore (pseudo-Rust)
398
- /// pub trait Trait { fn xyz(); }
399
- /// // This impl is "useless", but we can still have
400
- /// // an `impl Trait for SomeUnsizedType` somewhere.
401
- /// impl<T: Trait + Sized> Trait for T { fn xyz() {} }
402
- ///
403
- /// pub fn foo<T: Trait + ?Sized>() {
404
- /// <T as Trait>::xyz();
405
- /// }
406
- /// ```
407
- ///
408
- /// When checking `foo`, we have to prove `T: Trait`. This basically
409
- /// translates into this:
410
- ///
411
- /// ```plain,ignore
412
- /// (T: Trait + Sized →_\impl T: Trait), T: Trait ⊢ T: Trait
413
- /// ```
414
- ///
415
- /// When we try to prove it, we first go the first option, which
416
- /// recurses. This shows us that the impl is "useless" -- it won't
417
- /// tell us that `T: Trait` unless it already implemented `Trait`
418
- /// by some other means. However, that does not prevent `T: Trait`
419
- /// does not hold, because of the bound (which can indeed be satisfied
420
- /// by `SomeUnsizedType` from another crate).
421
- //
422
- // FIXME: when an `EvaluatedToRecur` goes past its parent root, we
423
- // ought to convert it to an `EvaluatedToErr`, because we know
424
- // there definitely isn't a proof tree for that obligation. Not
425
- // doing so is still sound -- there isn't any proof tree, so the
426
- // branch still can't be a part of a minimal one -- but does not re-enable caching.
427
- EvaluatedToRecur ,
428
- /// Evaluation failed.
429
- EvaluatedToErr ,
430
- }
431
-
432
- impl EvaluationResult {
433
- /// Returns `true` if this evaluation result is known to apply, even
434
- /// considering outlives constraints.
435
- pub fn must_apply_considering_regions ( self ) -> bool {
436
- self == EvaluatedToOk
437
- }
438
-
439
- /// Returns `true` if this evaluation result is known to apply, ignoring
440
- /// outlives constraints.
441
- pub fn must_apply_modulo_regions ( self ) -> bool {
442
- self <= EvaluatedToOkModuloRegions
443
- }
444
-
445
- pub fn may_apply ( self ) -> bool {
446
- match self {
447
- EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => {
448
- true
449
- }
450
-
451
- EvaluatedToErr | EvaluatedToRecur => false ,
452
- }
453
- }
454
-
455
- fn is_stack_dependent ( self ) -> bool {
456
- match self {
457
- EvaluatedToUnknown | EvaluatedToRecur => true ,
458
-
459
- EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false ,
460
- }
461
- }
462
- }
463
-
464
- /// Indicates that trait evaluation caused overflow.
465
- #[ derive( Copy , Clone , Debug , PartialEq , Eq , HashStable ) ]
466
- pub struct OverflowError ;
467
-
468
- impl < ' tcx > From < OverflowError > for SelectionError < ' tcx > {
469
- fn from ( OverflowError : OverflowError ) -> SelectionError < ' tcx > {
470
- SelectionError :: Overflow
471
- }
472
- }
473
-
474
- #[ derive( Clone , Default ) ]
475
- pub struct EvaluationCache < ' tcx > {
476
- hashmap : Lock <
477
- FxHashMap < ty:: ParamEnvAnd < ' tcx , ty:: PolyTraitRef < ' tcx > > , WithDepNode < EvaluationResult > > ,
478
- > ,
479
- }
480
-
481
214
impl < ' cx , ' tcx > SelectionContext < ' cx , ' tcx > {
482
215
pub fn new ( infcx : & ' cx InferCtxt < ' cx , ' tcx > ) -> SelectionContext < ' cx , ' tcx > {
483
216
SelectionContext {
@@ -3827,13 +3560,6 @@ impl<'tcx> TraitObligation<'tcx> {
3827
3560
}
3828
3561
}
3829
3562
3830
- impl < ' tcx > SelectionCache < ' tcx > {
3831
- /// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
3832
- pub fn clear ( & self ) {
3833
- * self . hashmap . borrow_mut ( ) = Default :: default ( ) ;
3834
- }
3835
- }
3836
-
3837
3563
impl < ' tcx > EvaluationCache < ' tcx > {
3838
3564
/// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
3839
3565
pub fn clear ( & self ) {
@@ -4126,20 +3852,3 @@ impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
4126
3852
write ! ( f, "TraitObligationStack({:?})" , self . obligation)
4127
3853
}
4128
3854
}
4129
-
4130
- #[ derive( Clone , Eq , PartialEq ) ]
4131
- pub struct WithDepNode < T > {
4132
- dep_node : DepNodeIndex ,
4133
- cached_value : T ,
4134
- }
4135
-
4136
- impl < T : Clone > WithDepNode < T > {
4137
- pub fn new ( dep_node : DepNodeIndex , cached_value : T ) -> Self {
4138
- WithDepNode { dep_node, cached_value }
4139
- }
4140
-
4141
- pub fn get ( & self , tcx : TyCtxt < ' _ > ) -> T {
4142
- tcx. dep_graph . read_index ( self . dep_node ) ;
4143
- self . cached_value . clone ( )
4144
- }
4145
- }
0 commit comments