1 //! Candidate selection. See the [rustc dev guide] for more information on how this works.
3 //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
5 use self::EvaluationResult::*;
7 use super::{SelectionError, SelectionResult};
11 use rustc_hir::def_id::DefId;
12 use rustc_query_system::cache::Cache;
14 pub type SelectionCache<'tcx> = Cache<
15 (ty::ConstnessAnd<ty::ParamEnvAnd<'tcx, ty::TraitRef<'tcx>>>, ty::ImplPolarity),
16 SelectionResult<'tcx, SelectionCandidate<'tcx>>,
19 pub type EvaluationCache<'tcx> = Cache<
20 (ty::ParamEnvAnd<'tcx, ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>>, ty::ImplPolarity),
24 /// The selection process begins by considering all impls, where
25 /// clauses, and so forth that might resolve an obligation. Sometimes
26 /// we'll be able to say definitively that (e.g.) an impl does not
27 /// apply to the obligation: perhaps it is defined for `usize` but the
28 /// obligation is for `i32`. In that case, we drop the impl out of the
29 /// list. But the other cases are considered *candidates*.
31 /// For selection to succeed, there must be exactly one matching
32 /// candidate. If the obligation is fully known, this is guaranteed
33 /// by coherence. However, if the obligation contains type parameters
34 /// or variables, there may be multiple such impls.
36 /// It is not a real problem if multiple matching impls exist because
37 /// of type variables - it just means the obligation isn't sufficiently
38 /// elaborated. In that case we report an ambiguity, and the caller can
39 /// try again after more type information has been gathered or report a
40 /// "type annotations needed" error.
42 /// However, with type parameters, this can be a real problem - type
43 /// parameters don't unify with regular types, but they *can* unify
44 /// with variables from blanket impls, and (unless we know its bounds
45 /// will always be satisfied) picking the blanket impl will be wrong
46 /// for at least *some* substitutions. To make this concrete, if we have
49 /// trait AsDebug { type Out: fmt::Debug; fn debug(self) -> Self::Out; }
50 /// impl<T: fmt::Debug> AsDebug for T {
52 /// fn debug(self) -> fmt::Debug { self }
54 /// fn foo<T: AsDebug>(t: T) { println!("{:?}", <T as AsDebug>::debug(t)); }
57 /// we can't just use the impl to resolve the `<T as AsDebug>` obligation
58 /// -- a type from another crate (that doesn't implement `fmt::Debug`) could
59 /// implement `AsDebug`.
61 /// Because where-clauses match the type exactly, multiple clauses can
62 /// only match if there are unresolved variables, and we can mostly just
63 /// report this ambiguity in that case. This is still a problem - we can't
64 /// *do anything* with ambiguities that involve only regions. This is issue
67 /// If a single where-clause matches and there are no inference
68 /// variables left, then it definitely matches and we can just select
71 /// In fact, we even select the where-clause when the obligation contains
72 /// inference variables. The can lead to inference making "leaps of logic",
73 /// for example in this situation:
76 /// pub trait Foo<T> { fn foo(&self) -> T; }
77 /// impl<T> Foo<()> for T { fn foo(&self) { } }
78 /// impl Foo<bool> for bool { fn foo(&self) -> bool { *self } }
80 /// pub fn foo<T>(t: T) where T: Foo<bool> {
81 /// println!("{:?}", <T as Foo<_>>::foo(&t));
83 /// fn main() { foo(false); }
86 /// Here the obligation `<T as Foo<$0>>` can be matched by both the blanket
87 /// impl and the where-clause. We select the where-clause and unify `$0=bool`,
88 /// so the program prints "false". However, if the where-clause is omitted,
89 /// the blanket impl is selected, we unify `$0=()`, and the program prints
92 /// Exactly the same issues apply to projection and object candidates, except
93 /// that we can have both a projection candidate and a where-clause candidate
94 /// for the same obligation. In that case either would do (except that
95 /// different "leaps of logic" would occur if inference variables are
96 /// present), and we just pick the where-clause. This is, for example,
97 /// required for associated types to work in default impls, as the bounds
98 /// are visible both as projection bounds and as where-clauses from the
99 /// parameter environment.
100 #[derive(PartialEq, Eq, Debug, Clone, TypeFoldable)]
101 pub enum SelectionCandidate<'tcx> {
103 /// `false` if there are no *further* obligations.
106 ParamCandidate((ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, ty::ImplPolarity)),
107 ImplCandidate(DefId),
108 AutoImplCandidate(DefId),
110 /// This is a trait matching with a projected type as `Self`, and we found
111 /// an applicable bound in the trait definition. The `usize` is an index
112 /// into the list returned by `tcx.item_bounds`.
113 ProjectionCandidate(usize),
115 /// Implementation of a `Fn`-family trait by one of the anonymous types
116 /// generated for an `||` expression.
119 /// Implementation of a `Generator` trait by one of the anonymous types
120 /// generated for a generator.
123 /// Implementation of a `Fn`-family trait by one of the anonymous
124 /// types generated for a fn pointer type (e.g., `fn(int) -> int`)
129 /// Builtin implementation of `DiscriminantKind`.
130 DiscriminantKindCandidate,
132 /// Builtin implementation of `Pointee`.
135 TraitAliasCandidate(DefId),
137 /// Matching `dyn Trait` with a supertrait of `Trait`. The index is the
138 /// position in the iterator returned by
139 /// `rustc_infer::traits::util::supertraits`.
140 ObjectCandidate(usize),
142 /// Perform trait upcasting coercion of `dyn Trait` to a supertrait of `Trait`.
143 /// The index is the position in the iterator returned by
144 /// `rustc_infer::traits::util::supertraits`.
145 TraitUpcastingUnsizeCandidate(usize),
147 BuiltinObjectCandidate,
149 BuiltinUnsizeCandidate,
151 /// Implementation of `const Drop`.
155 /// The result of trait evaluation. The order is important
156 /// here as the evaluation of a list is the maximum of the
159 /// The evaluation results are ordered:
160 /// - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions`
161 /// implies `EvaluatedToAmbig` implies `EvaluatedToUnknown`
162 /// - `EvaluatedToErr` implies `EvaluatedToRecur`
163 /// - the "union" of evaluation results is equal to their maximum -
164 /// all the "potential success" candidates can potentially succeed,
165 /// so they are noops when unioned with a definite error, and within
166 /// the categories it's easy to see that the unions are correct.
167 #[derive(Copy, Clone, Debug, PartialOrd, Ord, PartialEq, Eq, HashStable)]
168 pub enum EvaluationResult {
169 /// Evaluation successful.
171 /// Evaluation successful, but there were unevaluated region obligations.
172 EvaluatedToOkModuloRegions,
173 /// Evaluation is known to be ambiguous -- it *might* hold for some
174 /// assignment of inference variables, but it might not.
176 /// While this has the same meaning as `EvaluatedToUnknown` -- we can't
177 /// know whether this obligation holds or not -- it is the result we
178 /// would get with an empty stack, and therefore is cacheable.
180 /// Evaluation failed because of recursion involving inference
181 /// variables. We are somewhat imprecise there, so we don't actually
182 /// know the real result.
184 /// This can't be trivially cached for the same reason as `EvaluatedToRecur`.
186 /// Evaluation failed because we encountered an obligation we are already
187 /// trying to prove on this branch.
189 /// We know this branch can't be a part of a minimal proof-tree for
190 /// the "root" of our cycle, because then we could cut out the recursion
191 /// and maintain a valid proof tree. However, this does not mean
192 /// that all the obligations on this branch do not hold -- it's possible
193 /// that we entered this branch "speculatively", and that there
194 /// might be some other way to prove this obligation that does not
195 /// go through this cycle -- so we can't cache this as a failure.
197 /// For example, suppose we have this:
199 /// ```rust,ignore (pseudo-Rust)
200 /// pub trait Trait { fn xyz(); }
201 /// // This impl is "useless", but we can still have
202 /// // an `impl Trait for SomeUnsizedType` somewhere.
203 /// impl<T: Trait + Sized> Trait for T { fn xyz() {} }
205 /// pub fn foo<T: Trait + ?Sized>() {
206 /// <T as Trait>::xyz();
210 /// When checking `foo`, we have to prove `T: Trait`. This basically
211 /// translates into this:
214 /// (T: Trait + Sized →_\impl T: Trait), T: Trait ⊢ T: Trait
217 /// When we try to prove it, we first go the first option, which
218 /// recurses. This shows us that the impl is "useless" -- it won't
219 /// tell us that `T: Trait` unless it already implemented `Trait`
220 /// by some other means. However, that does not prevent `T: Trait`
221 /// does not hold, because of the bound (which can indeed be satisfied
222 /// by `SomeUnsizedType` from another crate).
224 // FIXME: when an `EvaluatedToRecur` goes past its parent root, we
225 // ought to convert it to an `EvaluatedToErr`, because we know
226 // there definitely isn't a proof tree for that obligation. Not
227 // doing so is still sound -- there isn't any proof tree, so the
228 // branch still can't be a part of a minimal one -- but does not re-enable caching.
230 /// Evaluation failed.
234 impl EvaluationResult {
235 /// Returns `true` if this evaluation result is known to apply, even
236 /// considering outlives constraints.
237 pub fn must_apply_considering_regions(self) -> bool {
238 self == EvaluatedToOk
241 /// Returns `true` if this evaluation result is known to apply, ignoring
242 /// outlives constraints.
243 pub fn must_apply_modulo_regions(self) -> bool {
244 self <= EvaluatedToOkModuloRegions
247 pub fn may_apply(self) -> bool {
249 EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToUnknown => {
253 EvaluatedToErr | EvaluatedToRecur => false,
257 pub fn is_stack_dependent(self) -> bool {
259 EvaluatedToUnknown | EvaluatedToRecur => true,
261 EvaluatedToOk | EvaluatedToOkModuloRegions | EvaluatedToAmbig | EvaluatedToErr => false,
266 /// Indicates that trait evaluation caused overflow and in which pass.
267 #[derive(Copy, Clone, Debug, PartialEq, Eq, HashStable)]
268 pub enum OverflowError {
273 impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
274 fn from(overflow_error: OverflowError) -> SelectionError<'tcx> {
275 match overflow_error {
276 OverflowError::Canonical => SelectionError::Overflow,
277 OverflowError::ErrorReporting => SelectionError::ErrorReporting,