@@ -41,7 +41,6 @@ use crate::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, Wit
4141use rustc_hir:: def_id:: DefId ;
4242
4343use rustc_data_structures:: fx:: { FxHashMap , FxHashSet } ;
44- use rustc_data_structures:: sync:: Lock ;
4544use rustc_hir as hir;
4645use rustc_index:: bit_set:: GrowableBitSet ;
4746use rustc_span:: symbol:: sym;
@@ -53,6 +52,8 @@ use std::iter;
5352use std:: rc:: Rc ;
5453use syntax:: { ast, attr} ;
5554
55+ pub use rustc:: traits:: types:: select:: * ;
56+
5657pub struct SelectionContext < ' cx , ' tcx > {
5758 infcx : & ' cx InferCtxt < ' cx , ' tcx > ,
5859
@@ -181,146 +182,6 @@ struct TraitObligationStack<'prev, 'tcx> {
181182 dfn : usize ,
182183}
183184
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-
324185struct SelectionCandidateSet < ' tcx > {
325186 // A list of candidates that definitely apply to the current
326187 // obligation (meaning: types unify).
@@ -350,134 +211,6 @@ enum BuiltinImplConditions<'tcx> {
350211 Ambiguous ,
351212}
352213
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-
481214impl < ' cx , ' tcx > SelectionContext < ' cx , ' tcx > {
482215 pub fn new ( infcx : & ' cx InferCtxt < ' cx , ' tcx > ) -> SelectionContext < ' cx , ' tcx > {
483216 SelectionContext {
@@ -3827,13 +3560,6 @@ impl<'tcx> TraitObligation<'tcx> {
38273560 }
38283561}
38293562
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-
38373563impl < ' tcx > EvaluationCache < ' tcx > {
38383564 /// Actually frees the underlying memory in contrast to what stdlib containers do on `clear`
38393565 pub fn clear ( & self ) {
@@ -4126,20 +3852,3 @@ impl<'o, 'tcx> fmt::Debug for TraitObligationStack<'o, 'tcx> {
41263852 write ! ( f, "TraitObligationStack({:?})" , self . obligation)
41273853 }
41283854}
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