Skip to main content

rustc_middle/traits/
select.rs

1//! Candidate selection. See the [rustc dev guide] for more information on how this works.
2//!
3//! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html#selection
4
5use rustc_errors::ErrorGuaranteed;
6use rustc_hir::def_id::DefId;
7use rustc_macros::{StableHash, TypeVisitable};
8use rustc_type_ir::solve::AliasBoundKind;
9
10use self::EvaluationResult::*;
11use super::{SelectionError, SelectionResult};
12use crate::traits::cache::WithDepNodeCache;
13use crate::ty;
14
15pub type SelectionCache<'tcx, ENV> =
16    WithDepNodeCache<(ENV, ty::TraitClause<'tcx>), SelectionResult<'tcx, SelectionCandidate<'tcx>>>;
17
18pub type EvaluationCache<'tcx, ENV> =
19    WithDepNodeCache<(ENV, ty::PolyTraitClause<'tcx>), EvaluationResult>;
20
21/// The selection process begins by considering all impls, where
22/// clauses, and so forth that might resolve an obligation. Sometimes
23/// we'll be able to say definitively that (e.g.) an impl does not
24/// apply to the obligation: perhaps it is defined for `usize` but the
25/// obligation is for `i32`. In that case, we drop the impl out of the
26/// list. But the other cases are considered *candidates*.
27///
28/// For selection to succeed, there must be exactly one matching
29/// candidate. If the obligation is fully known, this is guaranteed
30/// by coherence. However, if the obligation contains type parameters
31/// or variables, there may be multiple such impls.
32///
33/// It is not a real problem if multiple matching impls exist because
34/// of type variables - it just means the obligation isn't sufficiently
35/// elaborated. In that case we report an ambiguity, and the caller can
36/// try again after more type information has been gathered or report a
37/// "type annotations needed" error.
38///
39/// However, with type parameters, this can be a real problem - type
40/// parameters don't unify with regular types, but they *can* unify
41/// with variables from blanket impls, and (unless we know its bounds
42/// will always be satisfied) picking the blanket impl will be wrong
43/// for at least *some* generic parameters. To make this concrete, if
44/// we have
45///
46/// ```rust, ignore
47/// trait AsDebug { type Out: fmt::Debug; fn debug(self) -> Self::Out; }
48/// impl<T: fmt::Debug> AsDebug for T {
49///     type Out = T;
50///     fn debug(self) -> fmt::Debug { self }
51/// }
52/// fn foo<T: AsDebug>(t: T) { println!("{:?}", <T as AsDebug>::debug(t)); }
53/// ```
54///
55/// we can't just use the impl to resolve the `<T as AsDebug>` obligation
56/// -- a type from another crate (that doesn't implement `fmt::Debug`) could
57/// implement `AsDebug`.
58///
59/// Because where-clauses match the type exactly, multiple clauses can
60/// only match if there are unresolved variables, and we can mostly just
61/// report this ambiguity in that case. This is still a problem - we can't
62/// *do anything* with ambiguities that involve only regions. This is issue
63/// #21974.
64///
65/// If a single where-clause matches and there are no inference
66/// variables left, then it definitely matches and we can just select
67/// it.
68///
69/// In fact, we even select the where-clause when the obligation contains
70/// inference variables. The can lead to inference making "leaps of logic",
71/// for example in this situation:
72///
73/// ```rust, ignore
74/// pub trait Foo<T> { fn foo(&self) -> T; }
75/// impl<T> Foo<()> for T { fn foo(&self) { } }
76/// impl Foo<bool> for bool { fn foo(&self) -> bool { *self } }
77///
78/// pub fn foo<T>(t: T) where T: Foo<bool> {
79///     println!("{:?}", <T as Foo<_>>::foo(&t));
80/// }
81/// fn main() { foo(false); }
82/// ```
83///
84/// Here the obligation `<T as Foo<$0>>` can be matched by both the blanket
85/// impl and the where-clause. We select the where-clause and unify `$0=bool`,
86/// so the program prints "false". However, if the where-clause is omitted,
87/// the blanket impl is selected, we unify `$0=()`, and the program prints
88/// "()".
89///
90/// Exactly the same issues apply to projection and object candidates, except
91/// that we can have both a projection candidate and a where-clause candidate
92/// for the same obligation. In that case either would do (except that
93/// different "leaps of logic" would occur if inference variables are
94/// present), and we just pick the where-clause. This is, for example,
95/// required for associated types to work in default impls, as the bounds
96/// are visible both as projection bounds and as where-clauses from the
97/// parameter environment.
98#[derive(#[automatically_derived]
impl<'tcx> ::core::marker::StructuralPartialEq for SelectionCandidate<'tcx> {
}
#[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for SelectionCandidate<'tcx> {
    #[inline]
    fn eq(&self, other: &SelectionCandidate<'tcx>) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (SelectionCandidate::ParamCandidate(__self_0),
                    SelectionCandidate::ParamCandidate(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (SelectionCandidate::ImplCandidate(__self_0),
                    SelectionCandidate::ImplCandidate(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (SelectionCandidate::ProjectionCandidate {
                    idx: __self_0, kind: __self_1 },
                    SelectionCandidate::ProjectionCandidate {
                    idx: __arg1_0, kind: __arg1_1 }) =>
                    __self_0 == __arg1_0 && __self_1 == __arg1_1,
                (SelectionCandidate::ClosureCandidate { is_const: __self_0 },
                    SelectionCandidate::ClosureCandidate { is_const: __arg1_0 })
                    => __self_0 == __arg1_0,
                (SelectionCandidate::ObjectCandidate(__self_0),
                    SelectionCandidate::ObjectCandidate(__arg1_0)) =>
                    __self_0 == __arg1_0,
                (SelectionCandidate::TraitUpcastingUnsizeCandidate(__self_0),
                    SelectionCandidate::TraitUpcastingUnsizeCandidate(__arg1_0))
                    => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for SelectionCandidate<'tcx> {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ty::PolyTraitClause<'tcx>>;
        let _: ::core::cmp::AssertParamIsEq<DefId>;
        let _: ::core::cmp::AssertParamIsEq<usize>;
        let _: ::core::cmp::AssertParamIsEq<AliasBoundKind>;
        let _: ::core::cmp::AssertParamIsEq<bool>;
    }
}Eq, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for SelectionCandidate<'tcx> {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            SelectionCandidate::SizedCandidate =>
                ::core::fmt::Formatter::write_str(f, "SizedCandidate"),
            SelectionCandidate::BuiltinCandidate =>
                ::core::fmt::Formatter::write_str(f, "BuiltinCandidate"),
            SelectionCandidate::TransmutabilityCandidate =>
                ::core::fmt::Formatter::write_str(f,
                    "TransmutabilityCandidate"),
            SelectionCandidate::ParamCandidate(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ParamCandidate", &__self_0),
            SelectionCandidate::ImplCandidate(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ImplCandidate", &__self_0),
            SelectionCandidate::AutoImplCandidate =>
                ::core::fmt::Formatter::write_str(f, "AutoImplCandidate"),
            SelectionCandidate::ProjectionCandidate {
                idx: __self_0, kind: __self_1 } =>
                ::core::fmt::Formatter::debug_struct_field2_finish(f,
                    "ProjectionCandidate", "idx", __self_0, "kind", &__self_1),
            SelectionCandidate::ClosureCandidate { is_const: __self_0 } =>
                ::core::fmt::Formatter::debug_struct_field1_finish(f,
                    "ClosureCandidate", "is_const", &__self_0),
            SelectionCandidate::AsyncClosureCandidate =>
                ::core::fmt::Formatter::write_str(f, "AsyncClosureCandidate"),
            SelectionCandidate::AsyncFnKindHelperCandidate =>
                ::core::fmt::Formatter::write_str(f,
                    "AsyncFnKindHelperCandidate"),
            SelectionCandidate::CoroutineCandidate =>
                ::core::fmt::Formatter::write_str(f, "CoroutineCandidate"),
            SelectionCandidate::FutureCandidate =>
                ::core::fmt::Formatter::write_str(f, "FutureCandidate"),
            SelectionCandidate::IteratorCandidate =>
                ::core::fmt::Formatter::write_str(f, "IteratorCandidate"),
            SelectionCandidate::AsyncIteratorCandidate =>
                ::core::fmt::Formatter::write_str(f,
                    "AsyncIteratorCandidate"),
            SelectionCandidate::FnPointerCandidate =>
                ::core::fmt::Formatter::write_str(f, "FnPointerCandidate"),
            SelectionCandidate::TraitAliasCandidate =>
                ::core::fmt::Formatter::write_str(f, "TraitAliasCandidate"),
            SelectionCandidate::ObjectCandidate(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "ObjectCandidate", &__self_0),
            SelectionCandidate::TraitUpcastingUnsizeCandidate(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f,
                    "TraitUpcastingUnsizeCandidate", &__self_0),
            SelectionCandidate::BuiltinObjectCandidate =>
                ::core::fmt::Formatter::write_str(f,
                    "BuiltinObjectCandidate"),
            SelectionCandidate::BuiltinUnsizeCandidate =>
                ::core::fmt::Formatter::write_str(f,
                    "BuiltinUnsizeCandidate"),
            SelectionCandidate::BikeshedGuaranteedNoDropCandidate =>
                ::core::fmt::Formatter::write_str(f,
                    "BikeshedGuaranteedNoDropCandidate"),
            SelectionCandidate::TryAsDynCandidate =>
                ::core::fmt::Formatter::write_str(f, "TryAsDynCandidate"),
        }
    }
}Debug, #[automatically_derived]
impl<'tcx> ::core::clone::Clone for SelectionCandidate<'tcx> {
    #[inline]
    fn clone(&self) -> SelectionCandidate<'tcx> {
        match self {
            SelectionCandidate::SizedCandidate =>
                SelectionCandidate::SizedCandidate,
            SelectionCandidate::BuiltinCandidate =>
                SelectionCandidate::BuiltinCandidate,
            SelectionCandidate::TransmutabilityCandidate =>
                SelectionCandidate::TransmutabilityCandidate,
            SelectionCandidate::ParamCandidate(__self_0) =>
                SelectionCandidate::ParamCandidate(::core::clone::Clone::clone(__self_0)),
            SelectionCandidate::ImplCandidate(__self_0) =>
                SelectionCandidate::ImplCandidate(::core::clone::Clone::clone(__self_0)),
            SelectionCandidate::AutoImplCandidate =>
                SelectionCandidate::AutoImplCandidate,
            SelectionCandidate::ProjectionCandidate {
                idx: __self_0, kind: __self_1 } =>
                SelectionCandidate::ProjectionCandidate {
                    idx: ::core::clone::Clone::clone(__self_0),
                    kind: ::core::clone::Clone::clone(__self_1),
                },
            SelectionCandidate::ClosureCandidate { is_const: __self_0 } =>
                SelectionCandidate::ClosureCandidate {
                    is_const: ::core::clone::Clone::clone(__self_0),
                },
            SelectionCandidate::AsyncClosureCandidate =>
                SelectionCandidate::AsyncClosureCandidate,
            SelectionCandidate::AsyncFnKindHelperCandidate =>
                SelectionCandidate::AsyncFnKindHelperCandidate,
            SelectionCandidate::CoroutineCandidate =>
                SelectionCandidate::CoroutineCandidate,
            SelectionCandidate::FutureCandidate =>
                SelectionCandidate::FutureCandidate,
            SelectionCandidate::IteratorCandidate =>
                SelectionCandidate::IteratorCandidate,
            SelectionCandidate::AsyncIteratorCandidate =>
                SelectionCandidate::AsyncIteratorCandidate,
            SelectionCandidate::FnPointerCandidate =>
                SelectionCandidate::FnPointerCandidate,
            SelectionCandidate::TraitAliasCandidate =>
                SelectionCandidate::TraitAliasCandidate,
            SelectionCandidate::ObjectCandidate(__self_0) =>
                SelectionCandidate::ObjectCandidate(::core::clone::Clone::clone(__self_0)),
            SelectionCandidate::TraitUpcastingUnsizeCandidate(__self_0) =>
                SelectionCandidate::TraitUpcastingUnsizeCandidate(::core::clone::Clone::clone(__self_0)),
            SelectionCandidate::BuiltinObjectCandidate =>
                SelectionCandidate::BuiltinObjectCandidate,
            SelectionCandidate::BuiltinUnsizeCandidate =>
                SelectionCandidate::BuiltinUnsizeCandidate,
            SelectionCandidate::BikeshedGuaranteedNoDropCandidate =>
                SelectionCandidate::BikeshedGuaranteedNoDropCandidate,
            SelectionCandidate::TryAsDynCandidate =>
                SelectionCandidate::TryAsDynCandidate,
        }
    }
}Clone, const _: () =
    {
        impl<'tcx>
            ::rustc_middle::ty::TypeVisitable<::rustc_middle::ty::TyCtxt<'tcx>>
            for SelectionCandidate<'tcx> {
            fn visit_with<__V: ::rustc_middle::ty::TypeVisitor<::rustc_middle::ty::TyCtxt<'tcx>>>(&self,
                __visitor: &mut __V) -> __V::Result {
                match *self {
                    SelectionCandidate::SizedCandidate => {}
                    SelectionCandidate::BuiltinCandidate => {}
                    SelectionCandidate::TransmutabilityCandidate => {}
                    SelectionCandidate::ParamCandidate(ref __binding_0) => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                    SelectionCandidate::ImplCandidate(ref __binding_0) => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                    SelectionCandidate::AutoImplCandidate => {}
                    SelectionCandidate::ProjectionCandidate {
                        idx: ref __binding_0, kind: ref __binding_1 } => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_1,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                    SelectionCandidate::ClosureCandidate {
                        is_const: ref __binding_0 } => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                    SelectionCandidate::AsyncClosureCandidate => {}
                    SelectionCandidate::AsyncFnKindHelperCandidate => {}
                    SelectionCandidate::CoroutineCandidate => {}
                    SelectionCandidate::FutureCandidate => {}
                    SelectionCandidate::IteratorCandidate => {}
                    SelectionCandidate::AsyncIteratorCandidate => {}
                    SelectionCandidate::FnPointerCandidate => {}
                    SelectionCandidate::TraitAliasCandidate => {}
                    SelectionCandidate::ObjectCandidate(ref __binding_0) => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                    SelectionCandidate::TraitUpcastingUnsizeCandidate(ref __binding_0)
                        => {
                        {
                            match ::rustc_middle::ty::VisitorResult::branch(::rustc_middle::ty::TypeVisitable::visit_with(__binding_0,
                                        __visitor)) {
                                ::core::ops::ControlFlow::Continue(()) => {}
                                ::core::ops::ControlFlow::Break(r) => {
                                    return ::rustc_middle::ty::VisitorResult::from_residual(r);
                                }
                            }
                        }
                    }
                    SelectionCandidate::BuiltinObjectCandidate => {}
                    SelectionCandidate::BuiltinUnsizeCandidate => {}
                    SelectionCandidate::BikeshedGuaranteedNoDropCandidate => {}
                    SelectionCandidate::TryAsDynCandidate => {}
                }
                <__V::Result as ::rustc_middle::ty::VisitorResult>::output()
            }
        }
    };TypeVisitable)]
99pub enum SelectionCandidate<'tcx> {
100    /// A built-in implementation for the `Sized` trait. This is preferred
101    /// over all other candidates.
102    SizedCandidate,
103
104    /// A builtin implementation for some specific traits, used in cases
105    /// where we cannot rely an ordinary library implementations.
106    ///
107    /// The most notable examples are `Copy` and `Clone`. This is also
108    /// used for the `DiscriminantKind` and `Pointee` trait, both of which have
109    /// an associated type.
110    BuiltinCandidate,
111
112    /// Implementation of transmutability trait.
113    TransmutabilityCandidate,
114
115    ParamCandidate(ty::PolyTraitClause<'tcx>),
116    ImplCandidate(DefId),
117    AutoImplCandidate,
118
119    /// This is a trait matching with a projected type as `Self`, and we found
120    /// an applicable bound in the trait definition. The `usize` is an index
121    /// into the list returned by `tcx.item_bounds` and the `AliasBoundKind`
122    /// is whether this is candidate from recursion on the self type of a
123    /// projection.
124    ProjectionCandidate {
125        idx: usize,
126        kind: AliasBoundKind,
127    },
128
129    /// Implementation of a `Fn`-family trait by one of the anonymous types
130    /// generated for an `||` expression.
131    ClosureCandidate {
132        is_const: bool,
133    },
134
135    /// Implementation of an `AsyncFn`-family trait by one of the anonymous types
136    /// generated for an `async ||` expression.
137    AsyncClosureCandidate,
138
139    /// Implementation of the `AsyncFnKindHelper` helper trait, which
140    /// is used internally to delay computation for async closures until after
141    /// upvar analysis is performed in HIR typeck.
142    AsyncFnKindHelperCandidate,
143
144    /// Implementation of a `Coroutine` trait by one of the anonymous types
145    /// generated for a coroutine.
146    CoroutineCandidate,
147
148    /// Implementation of a `Future` trait by one of the coroutine types
149    /// generated for an async construct.
150    FutureCandidate,
151
152    /// Implementation of an `Iterator` trait by one of the coroutine types
153    /// generated for a `gen` construct.
154    IteratorCandidate,
155
156    /// Implementation of an `AsyncIterator` trait by one of the coroutine types
157    /// generated for a `async gen` construct.
158    AsyncIteratorCandidate,
159
160    /// Implementation of a `Fn`-family trait by one of the anonymous
161    /// types generated for a fn pointer type (e.g., `fn(int) -> int`)
162    FnPointerCandidate,
163
164    TraitAliasCandidate,
165
166    /// Matching `dyn Trait` with a supertrait of `Trait`. The index is the
167    /// position in the iterator returned by
168    /// `rustc_infer::traits::util::supertraits`.
169    ObjectCandidate(usize),
170
171    /// Perform trait upcasting coercion of `dyn Trait` to a supertrait of `Trait`.
172    /// The index is the position in the iterator returned by
173    /// `rustc_infer::traits::util::supertraits`.
174    TraitUpcastingUnsizeCandidate(usize),
175
176    BuiltinObjectCandidate,
177
178    BuiltinUnsizeCandidate,
179
180    BikeshedGuaranteedNoDropCandidate,
181
182    TryAsDynCandidate,
183}
184
185/// The result of trait evaluation. The order is important
186/// here as the evaluation of a list is the maximum of the
187/// evaluations.
188///
189/// The evaluation results are ordered:
190///     - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions`
191///       implies `EvaluatedToAmbig` implies `EvaluatedToAmbigStackDependent`
192///     - the "union" of evaluation results is equal to their maximum -
193///     all the "potential success" candidates can potentially succeed,
194///     so they are noops when unioned with a definite error, and within
195///     the categories it's easy to see that the unions are correct.
196#[derive(#[automatically_derived]
impl ::core::marker::Copy for EvaluationResult { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for EvaluationResult { }
#[automatically_derived]
impl ::core::clone::Clone for EvaluationResult {
    #[inline]
    fn clone(&self) -> EvaluationResult { *self }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for EvaluationResult {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                EvaluationResult::EvaluatedToOk => "EvaluatedToOk",
                EvaluationResult::EvaluatedToOkModuloRegions =>
                    "EvaluatedToOkModuloRegions",
                EvaluationResult::EvaluatedToOkModuloOpaqueTypes =>
                    "EvaluatedToOkModuloOpaqueTypes",
                EvaluationResult::EvaluatedToAmbig => "EvaluatedToAmbig",
                EvaluationResult::EvaluatedToAmbigStackDependent =>
                    "EvaluatedToAmbigStackDependent",
                EvaluationResult::EvaluatedToErr => "EvaluatedToErr",
            })
    }
}Debug, #[automatically_derived]
impl ::core::cmp::PartialOrd for EvaluationResult {
    #[inline]
    fn partial_cmp(&self, other: &EvaluationResult)
        -> ::core::option::Option<::core::cmp::Ordering> {
        ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Ord for EvaluationResult {
    #[inline]
    fn cmp(&self, other: &EvaluationResult) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}Ord, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for EvaluationResult { }
#[automatically_derived]
impl ::core::cmp::PartialEq for EvaluationResult {
    #[inline]
    fn eq(&self, other: &EvaluationResult) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for EvaluationResult {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for
            EvaluationResult {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    EvaluationResult::EvaluatedToOk => {}
                    EvaluationResult::EvaluatedToOkModuloRegions => {}
                    EvaluationResult::EvaluatedToOkModuloOpaqueTypes => {}
                    EvaluationResult::EvaluatedToAmbig => {}
                    EvaluationResult::EvaluatedToAmbigStackDependent => {}
                    EvaluationResult::EvaluatedToErr => {}
                }
            }
        }
    };StableHash)]
197pub enum EvaluationResult {
198    /// Evaluation successful.
199    EvaluatedToOk,
200    /// Evaluation successful, but there were unevaluated region obligations.
201    EvaluatedToOkModuloRegions,
202    /// Evaluation successful, but need to rerun because opaque types got
203    /// hidden types assigned without it being known whether the opaque types
204    /// are within their defining scope
205    EvaluatedToOkModuloOpaqueTypes,
206    /// Evaluation is known to be ambiguous -- it *might* hold for some
207    /// assignment of inference variables, but it might not.
208    ///
209    /// While this has the same meaning as `EvaluatedToAmbigStackDependent` -- we can't
210    /// know whether this obligation holds or not -- it is the result we
211    /// would get with an empty stack, and therefore is cacheable.
212    EvaluatedToAmbig,
213    /// Evaluation failed because of recursion involving inference
214    /// variables. We are somewhat imprecise there, so we don't actually
215    /// know the real result.
216    ///
217    /// This can't be trivially cached because the result depends on the
218    /// stack results.
219    EvaluatedToAmbigStackDependent,
220    /// Evaluation failed.
221    EvaluatedToErr,
222}
223
224impl EvaluationResult {
225    /// Returns `true` if this evaluation result is known to apply, even
226    /// considering outlives constraints.
227    pub fn must_apply_considering_regions(self) -> bool {
228        self == EvaluatedToOk
229    }
230
231    /// Returns `true` if this evaluation result is known to apply, ignoring
232    /// outlives constraints.
233    pub fn must_apply_modulo_regions(self) -> bool {
234        self <= EvaluatedToOkModuloRegions
235    }
236
237    pub fn may_apply(self) -> bool {
238        match self {
239            EvaluatedToOkModuloOpaqueTypes
240            | EvaluatedToOk
241            | EvaluatedToOkModuloRegions
242            | EvaluatedToAmbig
243            | EvaluatedToAmbigStackDependent => true,
244
245            EvaluatedToErr => false,
246        }
247    }
248
249    pub fn is_stack_dependent(self) -> bool {
250        match self {
251            EvaluatedToAmbigStackDependent => true,
252
253            EvaluatedToOkModuloOpaqueTypes
254            | EvaluatedToOk
255            | EvaluatedToOkModuloRegions
256            | EvaluatedToAmbig
257            | EvaluatedToErr => false,
258        }
259    }
260}
261
262/// Indicates that trait evaluation caused overflow and in which pass.
263#[derive(#[automatically_derived]
impl ::core::marker::Copy for OverflowError { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for OverflowError { }
#[automatically_derived]
impl ::core::clone::Clone for OverflowError {
    #[inline]
    fn clone(&self) -> OverflowError {
        let _: ::core::clone::AssertParamIsClone<ErrorGuaranteed>;
        *self
    }
}Clone, #[automatically_derived]
impl ::core::fmt::Debug for OverflowError {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match self {
            OverflowError::Error(__self_0) =>
                ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Error",
                    &__self_0),
            OverflowError::Canonical =>
                ::core::fmt::Formatter::write_str(f, "Canonical"),
        }
    }
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for OverflowError { }
#[automatically_derived]
impl ::core::cmp::PartialEq for OverflowError {
    #[inline]
    fn eq(&self, other: &OverflowError) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr &&
            match (self, other) {
                (OverflowError::Error(__self_0),
                    OverflowError::Error(__arg1_0)) => __self_0 == __arg1_0,
                _ => true,
            }
    }
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for OverflowError {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {
        let _: ::core::cmp::AssertParamIsEq<ErrorGuaranteed>;
    }
}Eq, const _: () =
    {
        impl ::rustc_data_structures::stable_hash::StableHash for
            OverflowError {
            #[inline]
            fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
                __hcx: &mut __Hcx,
                __hasher:
                    &mut ::rustc_data_structures::stable_hash::StableHasher) {
                ::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
                match *self {
                    OverflowError::Error(ref __binding_0) => {
                        { __binding_0.stable_hash(__hcx, __hasher); }
                    }
                    OverflowError::Canonical => {}
                }
            }
        }
    };StableHash)]
264pub enum OverflowError {
265    Error(ErrorGuaranteed),
266    Canonical,
267}
268
269impl From<ErrorGuaranteed> for OverflowError {
270    fn from(e: ErrorGuaranteed) -> OverflowError {
271        OverflowError::Error(e)
272    }
273}
274
275impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
276    fn from(overflow_error: OverflowError) -> SelectionError<'tcx> {
277        match overflow_error {
278            OverflowError::Error(e) => SelectionError::Overflow(OverflowError::Error(e)),
279            OverflowError::Canonical => SelectionError::Overflow(OverflowError::Canonical),
280        }
281    }
282}