rust/compiler/rustc_infer/src/traits/mod.rs

154 lines
5.2 KiB
Rust
Raw Normal View History

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;
pub mod util;
2020-02-22 11:44:18 +01:00
2020-03-29 17:19:48 +02:00
use rustc_hir as hir;
2020-03-29 16:41:09 +02:00
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{self, Const, Ty, TyCtxt};
2020-02-22 11:44:18 +01:00
use rustc_span::Span;
pub use self::FulfillmentErrorCode::*;
2020-05-11 15:25:33 +00:00
pub use self::ImplSource::*;
2020-02-22 11:44:18 +01:00
pub use self::ObligationCauseCode::*;
pub use self::SelectionError::*;
pub use self::engine::{TraitEngine, TraitEngineExt};
pub use self::project::MismatchedProjectionTypes;
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).
#[derive(Clone, PartialEq, Eq, Hash)]
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,
}
pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
impl 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`.
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,
})
}
}
2020-02-22 11:44:18 +01:00
// `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
static_assert_size!(PredicateObligation<'_>, 32);
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
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> {
CodeSelectionError(SelectionError<'tcx>),
CodeProjectionError(MismatchedProjectionTypes<'tcx>),
CodeSubtypeError(ExpectedFound<Ty<'tcx>>, TypeError<'tcx>), // always comes from a SubtypePredicate
CodeConstEquateError(ExpectedFound<&'tcx Const<'tcx>>, TypeError<'tcx>),
2020-02-22 11:44:18 +01:00
CodeAmbiguity,
}
impl<'tcx, O> Obligation<'tcx, O> {
pub fn new(
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
predicate: O,
) -> Obligation<'tcx, O> {
Obligation { cause, param_env, recursion_depth: 0, predicate }
}
pub fn with_depth(
cause: ObligationCause<'tcx>,
recursion_depth: usize,
param_env: ty::ParamEnv<'tcx>,
predicate: O,
) -> Obligation<'tcx, O> {
Obligation { cause, param_env, recursion_depth, predicate }
}
pub fn misc(
span: Span,
body_id: hir::HirId,
param_env: ty::ParamEnv<'tcx>,
trait_ref: O,
) -> Obligation<'tcx, O> {
Obligation::new(ObligationCause::misc(span, body_id), param_env, trait_ref)
}
pub fn with<P>(&self, value: P) -> Obligation<'tcx, P> {
Obligation {
cause: self.cause.clone(),
param_env: self.param_env,
recursion_depth: self.recursion_depth,
predicate: value,
}
}
}
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> {
FulfillmentError { obligation, code, root_obligation }
2020-02-22 11:44:18 +01:00
}
}
impl<'tcx> TraitObligation<'tcx> {
pub fn polarity(&self) -> ty::ImplPolarity {
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())
}
}