2020-04-12 05:02:35 +09:00
|
|
|
//! Trait Resolution. See the [rustc-dev-guide] for more information on how this works.
|
2020-02-22 11:44:18 +01:00
|
|
|
//!
|
2020-04-12 05:02:35 +09:00
|
|
|
//! [rustc-dev-guide]: https://rustc-dev-guide.rust-lang.org/traits/resolution.html
|
2020-02-22 11:44:18 +01:00
|
|
|
|
|
|
|
mod engine;
|
|
|
|
pub mod error_reporting;
|
|
|
|
mod project;
|
|
|
|
mod structural_impls;
|
2020-03-31 16:50:15 -07:00
|
|
|
pub mod util;
|
2020-02-22 11:44:18 +01:00
|
|
|
|
2023-03-14 14:56:16 +01:00
|
|
|
use std::cmp;
|
2023-08-08 13:41:50 +10:00
|
|
|
use std::hash::{Hash, Hasher};
|
2023-03-14 14:56:16 +01:00
|
|
|
|
2023-01-15 12:58:46 +01:00
|
|
|
use hir::def_id::LocalDefId;
|
2020-03-29 17:19:48 +02:00
|
|
|
use rustc_hir as hir;
|
2023-11-21 20:37:36 +01:00
|
|
|
use rustc_middle::traits::query::NoSolution;
|
|
|
|
use rustc_middle::traits::solve::Certainty;
|
2020-03-29 16:41:09 +02:00
|
|
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
2022-11-09 10:49:28 +00:00
|
|
|
use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt};
|
2020-02-22 11:44:18 +01:00
|
|
|
use rustc_span::Span;
|
|
|
|
|
2020-05-11 15:25:33 +00:00
|
|
|
pub use self::ImplSource::*;
|
2020-02-22 11:44:18 +01:00
|
|
|
pub use self::SelectionError::*;
|
2023-11-21 20:37:36 +01:00
|
|
|
use crate::infer::InferCtxt;
|
2020-02-22 11:44:18 +01:00
|
|
|
|
|
|
|
pub use self::engine::{TraitEngine, TraitEngineExt};
|
|
|
|
pub use self::project::MismatchedProjectionTypes;
|
2020-02-25 13:08:38 +01:00
|
|
|
pub(crate) use self::project::UndoLog;
|
2020-02-22 11:44:18 +01:00
|
|
|
pub use self::project::{
|
|
|
|
Normalized, NormalizedTy, ProjectionCache, ProjectionCacheEntry, ProjectionCacheKey,
|
2020-03-16 16:43:03 +01:00
|
|
|
ProjectionCacheStorage, Reveal,
|
2020-02-22 11:44:18 +01:00
|
|
|
};
|
2020-03-29 16:41:09 +02:00
|
|
|
pub use rustc_middle::traits::*;
|
2020-02-22 11:44:18 +01:00
|
|
|
|
2020-06-06 12:05:37 +02:00
|
|
|
/// An `Obligation` represents some trait reference (e.g., `i32: Eq`) for
|
2021-08-22 14:46:15 +02:00
|
|
|
/// which the "impl_source" must be found. The process of finding an "impl_source" is
|
2020-02-22 11:44:18 +01:00
|
|
|
/// called "resolving" the `Obligation`. This process consists of
|
2020-06-06 12:05:37 +02:00
|
|
|
/// either identifying an `impl` (e.g., `impl Eq for i32`) that
|
2020-05-11 15:25:33 +00:00
|
|
|
/// satisfies the obligation, or else finding a bound that is in
|
2020-02-22 11:44:18 +01:00
|
|
|
/// scope. The eventual result is usually a `Selection` (defined below).
|
2023-08-08 13:41:50 +10:00
|
|
|
#[derive(Clone)]
|
2020-02-22 11:44:18 +01:00
|
|
|
pub struct Obligation<'tcx, T> {
|
|
|
|
/// The reason we have to prove this thing.
|
|
|
|
pub cause: ObligationCause<'tcx>,
|
|
|
|
|
|
|
|
/// The environment in which we should prove this thing.
|
|
|
|
pub param_env: ty::ParamEnv<'tcx>,
|
|
|
|
|
|
|
|
/// The thing we are trying to prove.
|
|
|
|
pub predicate: T,
|
|
|
|
|
|
|
|
/// If we started proving this as a result of trying to prove
|
|
|
|
/// something else, track the total depth to ensure termination.
|
|
|
|
/// If this goes over a certain threshold, we abort compilation --
|
|
|
|
/// in such cases, we can not say whether or not the predicate
|
|
|
|
/// holds for certain. Stupid halting problem; such a drag.
|
|
|
|
pub recursion_depth: usize,
|
|
|
|
}
|
|
|
|
|
2023-08-08 13:41:50 +10:00
|
|
|
impl<'tcx, T: PartialEq> PartialEq<Obligation<'tcx, T>> for Obligation<'tcx, T> {
|
|
|
|
#[inline]
|
|
|
|
fn eq(&self, other: &Obligation<'tcx, T>) -> bool {
|
|
|
|
// Ignore `cause` and `recursion_depth`. This is a small performance
|
|
|
|
// win for a few crates, and a huge performance win for the crate in
|
|
|
|
// https://github.com/rust-lang/rustc-perf/pull/1680, which greatly
|
|
|
|
// stresses the trait system.
|
|
|
|
self.param_env == other.param_env && self.predicate == other.predicate
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T: Eq> Eq for Obligation<'_, T> {}
|
|
|
|
|
|
|
|
impl<T: Hash> Hash for Obligation<'_, T> {
|
|
|
|
fn hash<H: Hasher>(&self, state: &mut H) -> () {
|
|
|
|
// See the comment on `Obligation::eq`.
|
|
|
|
self.param_env.hash(state);
|
|
|
|
self.predicate.hash(state);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-15 02:08:05 +00:00
|
|
|
impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
|
|
|
|
fn from(value: Obligation<'tcx, P>) -> Self {
|
|
|
|
solve::Goal { param_env: value.param_env, predicate: value.predicate }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-22 11:44:18 +01:00
|
|
|
pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
|
2023-07-03 22:23:37 +00:00
|
|
|
pub type TraitObligation<'tcx> = Obligation<'tcx, ty::TraitPredicate<'tcx>>;
|
2023-07-03 21:42:31 +00:00
|
|
|
pub type PolyTraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
|
2020-02-22 11:44:18 +01:00
|
|
|
|
2021-12-13 16:50:58 -05:00
|
|
|
impl<'tcx> PredicateObligation<'tcx> {
|
2021-10-22 09:34:36 -03:00
|
|
|
/// Flips the polarity of the inner predicate.
|
|
|
|
///
|
|
|
|
/// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`.
|
2021-10-12 12:11:00 -03:00
|
|
|
pub fn flip_polarity(&self, tcx: TyCtxt<'tcx>) -> Option<PredicateObligation<'tcx>> {
|
|
|
|
Some(PredicateObligation {
|
|
|
|
cause: self.cause.clone(),
|
|
|
|
param_env: self.param_env,
|
|
|
|
predicate: self.predicate.flip_polarity(tcx)?,
|
|
|
|
recursion_depth: self.recursion_depth,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-07-03 21:42:31 +00:00
|
|
|
impl<'tcx> PolyTraitObligation<'tcx> {
|
2022-05-10 09:26:09 +00:00
|
|
|
pub fn derived_cause(
|
|
|
|
&self,
|
2024-05-09 20:25:11 -04:00
|
|
|
variant: impl FnOnce(DerivedCause<'tcx>) -> ObligationCauseCode<'tcx>,
|
2022-05-10 09:26:09 +00:00
|
|
|
) -> ObligationCause<'tcx> {
|
|
|
|
self.cause.clone().derived_cause(self.predicate, variant)
|
|
|
|
}
|
2021-12-12 12:34:46 +08:00
|
|
|
}
|
|
|
|
|
2020-02-22 11:44:18 +01:00
|
|
|
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
|
2024-04-16 17:02:20 +10:00
|
|
|
#[cfg(target_pointer_width = "64")]
|
2024-04-29 14:59:24 +10:00
|
|
|
rustc_data_structures::static_assert_size!(PredicateObligation<'_>, 48);
|
2020-02-22 11:44:18 +01:00
|
|
|
|
|
|
|
pub type PredicateObligations<'tcx> = Vec<PredicateObligation<'tcx>>;
|
|
|
|
|
2020-05-11 15:25:33 +00:00
|
|
|
pub type Selection<'tcx> = ImplSource<'tcx, PredicateObligation<'tcx>>;
|
2020-02-22 11:44:18 +01:00
|
|
|
|
2023-11-21 20:37:36 +01:00
|
|
|
/// A callback that can be provided to `inspect_typeck`. Invoked on evaluation
|
|
|
|
/// of root obligations.
|
|
|
|
pub type ObligationInspector<'tcx> =
|
|
|
|
fn(&InferCtxt<'tcx>, &PredicateObligation<'tcx>, Result<Certainty, NoSolution>);
|
|
|
|
|
2020-02-22 11:44:18 +01:00
|
|
|
pub struct FulfillmentError<'tcx> {
|
|
|
|
pub obligation: PredicateObligation<'tcx>,
|
|
|
|
pub code: FulfillmentErrorCode<'tcx>,
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 16:55:39 -04:00
|
|
|
/// Diagnostics only: the 'root' obligation which resulted in
|
|
|
|
/// the failure to process `obligation`. This is the obligation
|
|
|
|
/// that was initially passed to `register_predicate_obligation`
|
|
|
|
pub root_obligation: PredicateObligation<'tcx>,
|
2020-02-22 11:44:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
pub enum FulfillmentErrorCode<'tcx> {
|
2024-02-23 10:12:08 +01:00
|
|
|
/// Inherently impossible to fulfill; this trait is implemented if and only
|
|
|
|
/// if it is already implemented.
|
2024-01-12 16:16:17 +00:00
|
|
|
Cycle(Vec<PredicateObligation<'tcx>>),
|
2024-05-09 14:09:55 -04:00
|
|
|
Select(SelectionError<'tcx>),
|
|
|
|
Project(MismatchedProjectionTypes<'tcx>),
|
|
|
|
Subtype(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
|
|
|
|
ConstEquate(ExpectedFound<Const<'tcx>>, TypeError<'tcx>),
|
2024-01-12 16:16:17 +00:00
|
|
|
Ambiguity {
|
2024-02-23 10:12:08 +01:00
|
|
|
/// Overflow is only `Some(suggest_recursion_limit)` when using the next generation
|
|
|
|
/// trait solver `-Znext-solver`. With the old solver overflow is eagerly handled by
|
|
|
|
/// emitting a fatal error instead.
|
|
|
|
overflow: Option<bool>,
|
2023-04-09 04:29:43 +00:00
|
|
|
},
|
2020-02-22 11:44:18 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx, O> Obligation<'tcx, O> {
|
|
|
|
pub fn new(
|
2022-11-09 10:49:28 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2020-02-22 11:44:18 +01:00
|
|
|
cause: ObligationCause<'tcx>,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2022-11-09 10:49:28 +00:00
|
|
|
predicate: impl ToPredicate<'tcx, O>,
|
2020-02-22 11:44:18 +01:00
|
|
|
) -> Obligation<'tcx, O> {
|
2022-11-09 10:49:28 +00:00
|
|
|
Self::with_depth(tcx, cause, 0, param_env, predicate)
|
2020-02-22 11:44:18 +01:00
|
|
|
}
|
|
|
|
|
2023-03-14 14:56:16 +01:00
|
|
|
/// We often create nested obligations without setting the correct depth.
|
|
|
|
///
|
|
|
|
/// To deal with this evaluate and fulfill explicitly update the depth
|
|
|
|
/// of nested obligations using this function.
|
|
|
|
pub fn set_depth_from_parent(&mut self, parent_depth: usize) {
|
|
|
|
self.recursion_depth = cmp::max(parent_depth + 1, self.recursion_depth);
|
|
|
|
}
|
|
|
|
|
2020-02-22 11:44:18 +01:00
|
|
|
pub fn with_depth(
|
2022-11-09 10:49:28 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2020-02-22 11:44:18 +01:00
|
|
|
cause: ObligationCause<'tcx>,
|
|
|
|
recursion_depth: usize,
|
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2022-11-09 10:49:28 +00:00
|
|
|
predicate: impl ToPredicate<'tcx, O>,
|
2020-02-22 11:44:18 +01:00
|
|
|
) -> Obligation<'tcx, O> {
|
2022-11-09 10:49:28 +00:00
|
|
|
let predicate = predicate.to_predicate(tcx);
|
2020-02-22 11:44:18 +01:00
|
|
|
Obligation { cause, param_env, recursion_depth, predicate }
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn misc(
|
2022-11-09 10:49:28 +00:00
|
|
|
tcx: TyCtxt<'tcx>,
|
2020-02-22 11:44:18 +01:00
|
|
|
span: Span,
|
2023-01-15 12:58:46 +01:00
|
|
|
body_id: LocalDefId,
|
2020-02-22 11:44:18 +01:00
|
|
|
param_env: ty::ParamEnv<'tcx>,
|
2022-11-09 10:49:28 +00:00
|
|
|
trait_ref: impl ToPredicate<'tcx, O>,
|
2020-02-22 11:44:18 +01:00
|
|
|
) -> Obligation<'tcx, O> {
|
2022-11-09 10:49:28 +00:00
|
|
|
Obligation::new(tcx, ObligationCause::misc(span, body_id), param_env, trait_ref)
|
2020-02-22 11:44:18 +01:00
|
|
|
}
|
|
|
|
|
2022-11-09 10:49:28 +00:00
|
|
|
pub fn with<P>(
|
|
|
|
&self,
|
|
|
|
tcx: TyCtxt<'tcx>,
|
|
|
|
value: impl ToPredicate<'tcx, P>,
|
|
|
|
) -> Obligation<'tcx, P> {
|
|
|
|
Obligation::with_depth(tcx, self.cause.clone(), self.recursion_depth, self.param_env, value)
|
2020-02-22 11:44:18 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> FulfillmentError<'tcx> {
|
|
|
|
pub fn new(
|
|
|
|
obligation: PredicateObligation<'tcx>,
|
|
|
|
code: FulfillmentErrorCode<'tcx>,
|
Add initial implementation of HIR-based WF checking for diagnostics
During well-formed checking, we walk through all types 'nested' in
generic arguments. For example, WF-checking `Option<MyStruct<u8>>`
will cause us to check `MyStruct<u8>` and `u8`. However, this is done
on a `rustc_middle::ty::Ty`, which has no span information. As a result,
any errors that occur will have a very general span (e.g. the
definintion of an associated item).
This becomes a problem when macros are involved. In general, an
associated type like `type MyType = Option<MyStruct<u8>>;` may
have completely different spans for each nested type in the HIR. Using
the span of the entire associated item might end up pointing to a macro
invocation, even though a user-provided span is available in one of the
nested types.
This PR adds a framework for HIR-based well formed checking. This check
is only run during error reporting, and is used to obtain a more precise
span for an existing error. This is accomplished by individually
checking each 'nested' type in the HIR for the type, allowing us to
find the most-specific type (and span) that produces a given error.
The majority of the changes are to the error-reporting code. However,
some of the general trait code is modified to pass through more
information.
Since this has no soundness implications, I've implemented a minimal
version to begin with, which can be extended over time. In particular,
this only works for HIR items with a corresponding `DefId` (e.g. it will
not work for WF-checking performed within function bodies).
2021-04-04 16:55:39 -04:00
|
|
|
root_obligation: PredicateObligation<'tcx>,
|
2020-02-22 11:44:18 +01:00
|
|
|
) -> FulfillmentError<'tcx> {
|
2021-09-07 11:19:57 +00:00
|
|
|
FulfillmentError { obligation, code, root_obligation }
|
2020-02-22 11:44:18 +01:00
|
|
|
}
|
2024-05-01 17:22:39 -04:00
|
|
|
|
|
|
|
pub fn is_true_error(&self) -> bool {
|
|
|
|
match self.code {
|
2024-05-09 14:09:55 -04:00
|
|
|
FulfillmentErrorCode::Select(_)
|
|
|
|
| FulfillmentErrorCode::Project(_)
|
|
|
|
| FulfillmentErrorCode::Subtype(_, _)
|
|
|
|
| FulfillmentErrorCode::ConstEquate(_, _) => true,
|
2024-05-01 17:22:39 -04:00
|
|
|
FulfillmentErrorCode::Cycle(_) | FulfillmentErrorCode::Ambiguity { overflow: _ } => {
|
|
|
|
false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-02-22 11:44:18 +01:00
|
|
|
}
|
|
|
|
|
2023-07-03 21:42:31 +00:00
|
|
|
impl<'tcx> PolyTraitObligation<'tcx> {
|
2024-03-21 15:45:28 -04:00
|
|
|
pub fn polarity(&self) -> ty::PredicatePolarity {
|
2021-10-20 14:12:11 -03:00
|
|
|
self.predicate.skip_binder().polarity
|
|
|
|
}
|
|
|
|
|
2020-10-05 16:51:33 -04:00
|
|
|
pub fn self_ty(&self) -> ty::Binder<'tcx, Ty<'tcx>> {
|
2020-02-22 11:44:18 +01:00
|
|
|
self.predicate.map_bound(|p| p.self_ty())
|
|
|
|
}
|
|
|
|
}
|