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
45use rustc_errors::ErrorGuaranteed;
6use rustc_hir::def_id::DefId;
7use rustc_macros::{HashStable, TypeVisitable};
8use rustc_type_ir::solve::AliasBoundKind;
910use self::EvaluationResult::*;
11use super::{SelectionError, SelectionResult};
12use crate::traits::cache::WithDepNodeCache;
13use crate::ty;
1415pub type SelectionCache<'tcx, ENV> = WithDepNodeCache<
16 (ENV, ty::TraitPredicate<'tcx>),
17SelectionResult<'tcx, SelectionCandidate<'tcx>>,
18>;
1920pub type EvaluationCache<'tcx, ENV> =
21WithDepNodeCache<(ENV, ty::PolyTraitPredicate<'tcx>), EvaluationResult>;
2223/// The selection process begins by considering all impls, where
24/// clauses, and so forth that might resolve an obligation. Sometimes
25/// we'll be able to say definitively that (e.g.) an impl does not
26/// apply to the obligation: perhaps it is defined for `usize` but the
27/// obligation is for `i32`. In that case, we drop the impl out of the
28/// list. But the other cases are considered *candidates*.
29///
30/// For selection to succeed, there must be exactly one matching
31/// candidate. If the obligation is fully known, this is guaranteed
32/// by coherence. However, if the obligation contains type parameters
33/// or variables, there may be multiple such impls.
34///
35/// It is not a real problem if multiple matching impls exist because
36/// of type variables - it just means the obligation isn't sufficiently
37/// elaborated. In that case we report an ambiguity, and the caller can
38/// try again after more type information has been gathered or report a
39/// "type annotations needed" error.
40///
41/// However, with type parameters, this can be a real problem - type
42/// parameters don't unify with regular types, but they *can* unify
43/// with variables from blanket impls, and (unless we know its bounds
44/// will always be satisfied) picking the blanket impl will be wrong
45/// for at least *some* generic parameters. To make this concrete, if
46/// we have
47///
48/// ```rust, ignore
49/// trait AsDebug { type Out: fmt::Debug; fn debug(self) -> Self::Out; }
50/// impl<T: fmt::Debug> AsDebug for T {
51/// type Out = T;
52/// fn debug(self) -> fmt::Debug { self }
53/// }
54/// fn foo<T: AsDebug>(t: T) { println!("{:?}", <T as AsDebug>::debug(t)); }
55/// ```
56///
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`.
60///
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
65/// #21974.
66///
67/// If a single where-clause matches and there are no inference
68/// variables left, then it definitely matches and we can just select
69/// it.
70///
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:
74///
75/// ```rust, ignore
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 } }
79///
80/// pub fn foo<T>(t: T) where T: Foo<bool> {
81/// println!("{:?}", <T as Foo<_>>::foo(&t));
82/// }
83/// fn main() { foo(false); }
84/// ```
85///
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
90/// "()".
91///
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(#[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_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<ty::PolyTraitPredicate<'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::PointerLikeCandidate =>
::core::fmt::Formatter::write_str(f, "PointerLikeCandidate"),
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"),
}
}
}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::PointerLikeCandidate =>
SelectionCandidate::PointerLikeCandidate,
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,
}
}
}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::PointerLikeCandidate => {}
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 => {}
}
<__V::Result as ::rustc_middle::ty::VisitorResult>::output()
}
}
};TypeVisitable)]
101pub enum SelectionCandidate<'tcx> {
102/// A built-in implementation for the `Sized` trait. This is preferred
103 /// over all other candidates.
104SizedCandidate,
105106/// A builtin implementation for some specific traits, used in cases
107 /// where we cannot rely an ordinary library implementations.
108 ///
109 /// The most notable examples are `Copy` and `Clone`. This is also
110 /// used for the `DiscriminantKind` and `Pointee` trait, both of which have
111 /// an associated type.
112BuiltinCandidate,
113114/// Implementation of transmutability trait.
115TransmutabilityCandidate,
116117 ParamCandidate(ty::PolyTraitPredicate<'tcx>),
118 ImplCandidate(DefId),
119 AutoImplCandidate,
120121/// This is a trait matching with a projected type as `Self`, and we found
122 /// an applicable bound in the trait definition. The `usize` is an index
123 /// into the list returned by `tcx.item_bounds` and the `AliasBoundKind`
124 /// is whether this is candidate from recursion on the self type of a
125 /// projection.
126ProjectionCandidate {
127 idx: usize,
128 kind: AliasBoundKind,
129 },
130131/// Implementation of a `Fn`-family trait by one of the anonymous types
132 /// generated for an `||` expression.
133ClosureCandidate {
134 is_const: bool,
135 },
136137/// Implementation of an `AsyncFn`-family trait by one of the anonymous types
138 /// generated for an `async ||` expression.
139AsyncClosureCandidate,
140141/// Implementation of the `AsyncFnKindHelper` helper trait, which
142 /// is used internally to delay computation for async closures until after
143 /// upvar analysis is performed in HIR typeck.
144AsyncFnKindHelperCandidate,
145146/// Implementation of a `Coroutine` trait by one of the anonymous types
147 /// generated for a coroutine.
148CoroutineCandidate,
149150/// Implementation of a `Future` trait by one of the coroutine types
151 /// generated for an async construct.
152FutureCandidate,
153154/// Implementation of an `Iterator` trait by one of the coroutine types
155 /// generated for a `gen` construct.
156IteratorCandidate,
157158/// Implementation of an `AsyncIterator` trait by one of the coroutine types
159 /// generated for a `async gen` construct.
160AsyncIteratorCandidate,
161162/// Implementation of a `Fn`-family trait by one of the anonymous
163 /// types generated for a fn pointer type (e.g., `fn(int) -> int`)
164FnPointerCandidate,
165166/// Builtin impl of the `PointerLike` trait.
167PointerLikeCandidate,
168169 TraitAliasCandidate,
170171/// Matching `dyn Trait` with a supertrait of `Trait`. The index is the
172 /// position in the iterator returned by
173 /// `rustc_infer::traits::util::supertraits`.
174ObjectCandidate(usize),
175176/// Perform trait upcasting coercion of `dyn Trait` to a supertrait of `Trait`.
177 /// The index is the position in the iterator returned by
178 /// `rustc_infer::traits::util::supertraits`.
179TraitUpcastingUnsizeCandidate(usize),
180181 BuiltinObjectCandidate,
182183 BuiltinUnsizeCandidate,
184185 BikeshedGuaranteedNoDropCandidate,
186}
187188/// The result of trait evaluation. The order is important
189/// here as the evaluation of a list is the maximum of the
190/// evaluations.
191///
192/// The evaluation results are ordered:
193/// - `EvaluatedToOk` implies `EvaluatedToOkModuloRegions`
194/// implies `EvaluatedToAmbig` implies `EvaluatedToAmbigStackDependent`
195/// - the "union" of evaluation results is equal to their maximum -
196/// all the "potential success" candidates can potentially succeed,
197/// so they are noops when unioned with a definite error, and within
198/// the categories it's easy to see that the unions are correct.
199#[derive(#[automatically_derived]
impl ::core::marker::Copy for EvaluationResult { }Copy, #[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> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
}
}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::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_receiver_is_total_eq(&self) {}
}Eq, const _: () =
{
impl<'__ctx>
::rustc_data_structures::stable_hasher::HashStable<::rustc_query_system::ich::StableHashingContext<'__ctx>>
for EvaluationResult {
#[inline]
fn hash_stable(&self,
__hcx:
&mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
match *self {
EvaluationResult::EvaluatedToOk => {}
EvaluationResult::EvaluatedToOkModuloRegions => {}
EvaluationResult::EvaluatedToOkModuloOpaqueTypes => {}
EvaluationResult::EvaluatedToAmbig => {}
EvaluationResult::EvaluatedToAmbigStackDependent => {}
EvaluationResult::EvaluatedToErr => {}
}
}
}
};HashStable)]
200pub enum EvaluationResult {
201/// Evaluation successful.
202EvaluatedToOk,
203/// Evaluation successful, but there were unevaluated region obligations.
204EvaluatedToOkModuloRegions,
205/// Evaluation successful, but need to rerun because opaque types got
206 /// hidden types assigned without it being known whether the opaque types
207 /// are within their defining scope
208EvaluatedToOkModuloOpaqueTypes,
209/// Evaluation is known to be ambiguous -- it *might* hold for some
210 /// assignment of inference variables, but it might not.
211 ///
212 /// While this has the same meaning as `EvaluatedToAmbigStackDependent` -- we can't
213 /// know whether this obligation holds or not -- it is the result we
214 /// would get with an empty stack, and therefore is cacheable.
215EvaluatedToAmbig,
216/// Evaluation failed because of recursion involving inference
217 /// variables. We are somewhat imprecise there, so we don't actually
218 /// know the real result.
219 ///
220 /// This can't be trivially cached because the result depends on the
221 /// stack results.
222EvaluatedToAmbigStackDependent,
223/// Evaluation failed.
224EvaluatedToErr,
225}
226227impl EvaluationResult {
228/// Returns `true` if this evaluation result is known to apply, even
229 /// considering outlives constraints.
230pub fn must_apply_considering_regions(self) -> bool {
231self == EvaluatedToOk232 }
233234/// Returns `true` if this evaluation result is known to apply, ignoring
235 /// outlives constraints.
236pub fn must_apply_modulo_regions(self) -> bool {
237self <= EvaluatedToOkModuloRegions238 }
239240pub fn may_apply(self) -> bool {
241match self {
242EvaluatedToOkModuloOpaqueTypes243 | EvaluatedToOk244 | EvaluatedToOkModuloRegions245 | EvaluatedToAmbig246 | EvaluatedToAmbigStackDependent => true,
247248EvaluatedToErr => false,
249 }
250 }
251252pub fn is_stack_dependent(self) -> bool {
253match self {
254EvaluatedToAmbigStackDependent => true,
255256EvaluatedToOkModuloOpaqueTypes257 | EvaluatedToOk258 | EvaluatedToOkModuloRegions259 | EvaluatedToAmbig260 | EvaluatedToErr => false,
261 }
262 }
263}
264265/// Indicates that trait evaluation caused overflow and in which pass.
266#[derive(#[automatically_derived]
impl ::core::marker::Copy for OverflowError { }Copy, #[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::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_receiver_is_total_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<ErrorGuaranteed>;
}
}Eq, const _: () =
{
impl<'__ctx>
::rustc_data_structures::stable_hasher::HashStable<::rustc_query_system::ich::StableHashingContext<'__ctx>>
for OverflowError {
#[inline]
fn hash_stable(&self,
__hcx:
&mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
match *self {
OverflowError::Error(ref __binding_0) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
OverflowError::Canonical => {}
}
}
}
};HashStable)]
267pub enum OverflowError {
268 Error(ErrorGuaranteed),
269 Canonical,
270}
271272impl From<ErrorGuaranteed> for OverflowError {
273fn from(e: ErrorGuaranteed) -> OverflowError {
274 OverflowError::Error(e)
275 }
276}
277278impl<'tcx> From<OverflowError> for SelectionError<'tcx> {
279fn from(overflow_error: OverflowError) -> SelectionError<'tcx> {
280match overflow_error {
281 OverflowError::Error(e) => SelectionError::Overflow(OverflowError::Error(e)),
282 OverflowError::Canonical => SelectionError::Overflow(OverflowError::Canonical),
283 }
284 }
285}