Move predicate, region, and const stuff into their own modules in middle
This commit is contained in:
@@ -80,23 +80,34 @@ pub use self::closure::{
|
||||
CapturedPlace, ClosureTypeInfo, MinCaptureInformationMap, MinCaptureList,
|
||||
RootVariableMinCaptureList, UpvarCapture, UpvarId, UpvarPath, CAPTURE_STRUCT_LOCAL,
|
||||
};
|
||||
pub use self::consts::{Const, ConstData, ConstInt, Expr, ScalarInt, UnevaluatedConst, ValTree};
|
||||
pub use self::consts::{
|
||||
Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree,
|
||||
};
|
||||
pub use self::context::{
|
||||
tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed,
|
||||
};
|
||||
pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams};
|
||||
pub use self::list::List;
|
||||
pub use self::parameterized::ParameterizedOverTcx;
|
||||
pub use self::predicate::{
|
||||
Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialProjection,
|
||||
ExistentialTraitRef, NormalizesTo, OutlivesPredicate, PolyCoercePredicate,
|
||||
PolyExistentialPredicate, PolyExistentialProjection, PolyExistentialTraitRef,
|
||||
PolyProjectionPredicate, PolyRegionOutlivesPredicate, PolySubtypePredicate, PolyTraitPredicate,
|
||||
PolyTraitRef, PolyTypeOutlivesPredicate, Predicate, PredicateKind, ProjectionPredicate,
|
||||
RegionOutlivesPredicate, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitPredicate,
|
||||
TraitRef, TypeOutlivesPredicate,
|
||||
};
|
||||
pub use self::region::{
|
||||
BoundRegion, BoundRegionKind, BoundRegionKind::*, EarlyParamRegion, LateParamRegion, Region,
|
||||
RegionKind, RegionVid,
|
||||
};
|
||||
pub use self::rvalue_scopes::RvalueScopes;
|
||||
pub use self::sty::BoundRegionKind::*;
|
||||
pub use self::sty::{
|
||||
AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind,
|
||||
BoundVariableKind, CanonicalPolyFnSig, ClauseKind, ClosureArgs, ClosureArgsParts, ConstKind,
|
||||
CoroutineArgs, CoroutineArgsParts, EarlyParamRegion, ExistentialPredicate,
|
||||
ExistentialProjection, ExistentialTraitRef, FnSig, GenSig, InlineConstArgs,
|
||||
InlineConstArgsParts, LateParamRegion, ParamConst, ParamTy, PolyExistentialPredicate,
|
||||
PolyExistentialProjection, PolyExistentialTraitRef, PolyFnSig, PolyTraitRef, PredicateKind,
|
||||
Region, RegionKind, RegionVid, TraitRef, TyKind, TypeAndMut, UpvarArgs, VarianceDiagInfo,
|
||||
AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig,
|
||||
ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, FnSig, GenSig,
|
||||
InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut,
|
||||
UpvarArgs, VarianceDiagInfo,
|
||||
};
|
||||
pub use self::trait_def::TraitDef;
|
||||
pub use self::typeck_results::{
|
||||
@@ -139,6 +150,8 @@ mod instance;
|
||||
mod list;
|
||||
mod opaque_types;
|
||||
mod parameterized;
|
||||
mod predicate;
|
||||
mod region;
|
||||
mod rvalue_scopes;
|
||||
mod structural_impls;
|
||||
#[allow(hidden_glob_reexports)]
|
||||
@@ -491,165 +504,6 @@ impl EarlyParamRegion {
|
||||
}
|
||||
}
|
||||
|
||||
/// A statement that can be proven by a trait solver. This includes things that may
|
||||
/// show up in where clauses, such as trait predicates and projection predicates,
|
||||
/// and also things that are emitted as part of type checking such as `ObjectSafe`
|
||||
/// predicate which is emitted when a type is coerced to a trait object.
|
||||
///
|
||||
/// Use this rather than `PredicateKind`, whenever possible.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
|
||||
#[rustc_pass_by_value]
|
||||
pub struct Predicate<'tcx>(
|
||||
Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
|
||||
);
|
||||
|
||||
impl<'tcx> Predicate<'tcx> {
|
||||
/// Gets the inner `Binder<'tcx, PredicateKind<'tcx>>`.
|
||||
#[inline]
|
||||
pub fn kind(self) -> Binder<'tcx, PredicateKind<'tcx>> {
|
||||
self.0.internee
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn flags(self) -> TypeFlags {
|
||||
self.0.flags
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn outer_exclusive_binder(self) -> DebruijnIndex {
|
||||
self.0.outer_exclusive_binder
|
||||
}
|
||||
|
||||
/// Flips the polarity of a 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<Predicate<'tcx>> {
|
||||
let kind = self
|
||||
.kind()
|
||||
.map_bound(|kind| match kind {
|
||||
PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
|
||||
trait_ref,
|
||||
polarity,
|
||||
})) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
|
||||
trait_ref,
|
||||
polarity: polarity.flip()?,
|
||||
}))),
|
||||
|
||||
_ => None,
|
||||
})
|
||||
.transpose()?;
|
||||
|
||||
Some(tcx.mk_predicate(kind))
|
||||
}
|
||||
|
||||
#[instrument(level = "debug", skip(tcx), ret)]
|
||||
pub fn is_coinductive(self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
match self.kind().skip_binder() {
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
|
||||
tcx.trait_is_coinductive(data.def_id())
|
||||
}
|
||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Whether this projection can be soundly normalized.
|
||||
///
|
||||
/// Wf predicates must not be normalized, as normalization
|
||||
/// can remove required bounds which would cause us to
|
||||
/// unsoundly accept some programs. See #91068.
|
||||
#[inline]
|
||||
pub fn allow_normalization(self) -> bool {
|
||||
match self.kind().skip_binder() {
|
||||
PredicateKind::Clause(ClauseKind::WellFormed(_)) => false,
|
||||
// `NormalizesTo` is only used in the new solver, so this shouldn't
|
||||
// matter. Normalizing `term` would be 'wrong' however, as it changes whether
|
||||
// `normalizes-to(<T as Trait>::Assoc, <T as Trait>::Assoc)` holds.
|
||||
PredicateKind::NormalizesTo(..) => false,
|
||||
PredicateKind::Clause(ClauseKind::Trait(_))
|
||||
| PredicateKind::Clause(ClauseKind::RegionOutlives(_))
|
||||
| PredicateKind::Clause(ClauseKind::TypeOutlives(_))
|
||||
| PredicateKind::Clause(ClauseKind::Projection(_))
|
||||
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
|
||||
| PredicateKind::AliasRelate(..)
|
||||
| PredicateKind::ObjectSafe(_)
|
||||
| PredicateKind::Subtype(_)
|
||||
| PredicateKind::Coerce(_)
|
||||
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
|
||||
| PredicateKind::ConstEquate(_, _)
|
||||
| PredicateKind::Ambiguous => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl rustc_errors::IntoDiagnosticArg for Predicate<'_> {
|
||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue {
|
||||
rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
impl rustc_errors::IntoDiagnosticArg for Clause<'_> {
|
||||
fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue {
|
||||
rustc_errors::DiagnosticArgValue::Str(std::borrow::Cow::Owned(self.to_string()))
|
||||
}
|
||||
}
|
||||
|
||||
/// A subset of predicates which can be assumed by the trait solver. They show up in
|
||||
/// an item's where clauses, hence the name `Clause`, and may either be user-written
|
||||
/// (such as traits) or may be inserted during lowering.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
|
||||
#[rustc_pass_by_value]
|
||||
pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>);
|
||||
|
||||
impl<'tcx> Clause<'tcx> {
|
||||
pub fn as_predicate(self) -> Predicate<'tcx> {
|
||||
Predicate(self.0)
|
||||
}
|
||||
|
||||
pub fn kind(self) -> Binder<'tcx, ClauseKind<'tcx>> {
|
||||
self.0.internee.map_bound(|kind| match kind {
|
||||
PredicateKind::Clause(clause) => clause,
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn as_trait_clause(self) -> Option<Binder<'tcx, TraitPredicate<'tcx>>> {
|
||||
let clause = self.kind();
|
||||
if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() {
|
||||
Some(clause.rebind(trait_clause))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_projection_clause(self) -> Option<Binder<'tcx, ProjectionPredicate<'tcx>>> {
|
||||
let clause = self.kind();
|
||||
if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() {
|
||||
Some(clause.rebind(projection_clause))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_type_outlives_clause(self) -> Option<Binder<'tcx, TypeOutlivesPredicate<'tcx>>> {
|
||||
let clause = self.kind();
|
||||
if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() {
|
||||
Some(clause.rebind(o))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub fn as_region_outlives_clause(self) -> Option<Binder<'tcx, RegionOutlivesPredicate<'tcx>>> {
|
||||
let clause = self.kind();
|
||||
if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() {
|
||||
Some(clause.rebind(o))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The crate outlives map is computed during typeck and contains the
|
||||
/// outlives of every item in the local crate. You should not use it
|
||||
/// directly, because to do so will make your pass dependent on the
|
||||
@@ -664,189 +518,6 @@ pub struct CratePredicatesMap<'tcx> {
|
||||
pub predicates: DefIdMap<&'tcx [(Clause<'tcx>, Span)]>,
|
||||
}
|
||||
|
||||
impl<'tcx> Clause<'tcx> {
|
||||
/// Performs a substitution suitable for going from a
|
||||
/// poly-trait-ref to supertraits that must hold if that
|
||||
/// poly-trait-ref holds. This is slightly different from a normal
|
||||
/// substitution in terms of what happens with bound regions. See
|
||||
/// lengthy comment below for details.
|
||||
pub fn subst_supertrait(
|
||||
self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
trait_ref: &ty::PolyTraitRef<'tcx>,
|
||||
) -> Clause<'tcx> {
|
||||
// The interaction between HRTB and supertraits is not entirely
|
||||
// obvious. Let me walk you (and myself) through an example.
|
||||
//
|
||||
// Let's start with an easy case. Consider two traits:
|
||||
//
|
||||
// trait Foo<'a>: Bar<'a,'a> { }
|
||||
// trait Bar<'b,'c> { }
|
||||
//
|
||||
// Now, if we have a trait reference `for<'x> T: Foo<'x>`, then
|
||||
// we can deduce that `for<'x> T: Bar<'x,'x>`. Basically, if we
|
||||
// knew that `Foo<'x>` (for any 'x) then we also know that
|
||||
// `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
|
||||
// normal substitution.
|
||||
//
|
||||
// In terms of why this is sound, the idea is that whenever there
|
||||
// is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>`
|
||||
// holds. So if there is an impl of `T:Foo<'a>` that applies to
|
||||
// all `'a`, then we must know that `T:Bar<'a,'a>` holds for all
|
||||
// `'a`.
|
||||
//
|
||||
// Another example to be careful of is this:
|
||||
//
|
||||
// trait Foo1<'a>: for<'b> Bar1<'a,'b> { }
|
||||
// trait Bar1<'b,'c> { }
|
||||
//
|
||||
// Here, if we have `for<'x> T: Foo1<'x>`, then what do we know?
|
||||
// The answer is that we know `for<'x,'b> T: Bar1<'x,'b>`. The
|
||||
// reason is similar to the previous example: any impl of
|
||||
// `T:Foo1<'x>` must show that `for<'b> T: Bar1<'x, 'b>`. So
|
||||
// basically we would want to collapse the bound lifetimes from
|
||||
// the input (`trait_ref`) and the supertraits.
|
||||
//
|
||||
// To achieve this in practice is fairly straightforward. Let's
|
||||
// consider the more complicated scenario:
|
||||
//
|
||||
// - We start out with `for<'x> T: Foo1<'x>`. In this case, `'x`
|
||||
// has a De Bruijn index of 1. We want to produce `for<'x,'b> T: Bar1<'x,'b>`,
|
||||
// where both `'x` and `'b` would have a DB index of 1.
|
||||
// The substitution from the input trait-ref is therefore going to be
|
||||
// `'a => 'x` (where `'x` has a DB index of 1).
|
||||
// - The supertrait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
|
||||
// early-bound parameter and `'b` is a late-bound parameter with a
|
||||
// DB index of 1.
|
||||
// - If we replace `'a` with `'x` from the input, it too will have
|
||||
// a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
|
||||
// just as we wanted.
|
||||
//
|
||||
// There is only one catch. If we just apply the substitution `'a
|
||||
// => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will
|
||||
// adjust the DB index because we substituting into a binder (it
|
||||
// tries to be so smart...) resulting in `for<'x> for<'b>
|
||||
// Bar1<'x,'b>` (we have no syntax for this, so use your
|
||||
// imagination). Basically the 'x will have DB index of 2 and 'b
|
||||
// will have DB index of 1. Not quite what we want. So we apply
|
||||
// the substitution to the *contents* of the trait reference,
|
||||
// rather than the trait reference itself (put another way, the
|
||||
// substitution code expects equal binding levels in the values
|
||||
// from the substitution and the value being substituted into, and
|
||||
// this trick achieves that).
|
||||
|
||||
// Working through the second example:
|
||||
// trait_ref: for<'x> T: Foo1<'^0.0>; args: [T, '^0.0]
|
||||
// predicate: for<'b> Self: Bar1<'a, '^0.0>; args: [Self, 'a, '^0.0]
|
||||
// We want to end up with:
|
||||
// for<'x, 'b> T: Bar1<'^0.0, '^0.1>
|
||||
// To do this:
|
||||
// 1) We must shift all bound vars in predicate by the length
|
||||
// of trait ref's bound vars. So, we would end up with predicate like
|
||||
// Self: Bar1<'a, '^0.1>
|
||||
// 2) We can then apply the trait args to this, ending up with
|
||||
// T: Bar1<'^0.0, '^0.1>
|
||||
// 3) Finally, to create the final bound vars, we concatenate the bound
|
||||
// vars of the trait ref with those of the predicate:
|
||||
// ['x, 'b]
|
||||
let bound_pred = self.kind();
|
||||
let pred_bound_vars = bound_pred.bound_vars();
|
||||
let trait_bound_vars = trait_ref.bound_vars();
|
||||
// 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1>
|
||||
let shifted_pred =
|
||||
tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
|
||||
// 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
|
||||
let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args);
|
||||
// 3) ['x] + ['b] -> ['x, 'b]
|
||||
let bound_vars =
|
||||
tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
|
||||
|
||||
// FIXME: Is it really perf sensitive to use reuse_or_mk_predicate here?
|
||||
tcx.reuse_or_mk_predicate(
|
||||
self.as_predicate(),
|
||||
ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
|
||||
)
|
||||
.expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct TraitPredicate<'tcx> {
|
||||
pub trait_ref: TraitRef<'tcx>,
|
||||
|
||||
/// If polarity is Positive: we are proving that the trait is implemented.
|
||||
///
|
||||
/// If polarity is Negative: we are proving that a negative impl of this trait
|
||||
/// exists. (Note that coherence also checks whether negative impls of supertraits
|
||||
/// exist via a series of predicates.)
|
||||
///
|
||||
/// If polarity is Reserved: that's a bug.
|
||||
pub polarity: ImplPolarity,
|
||||
}
|
||||
|
||||
pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
|
||||
|
||||
impl<'tcx> TraitPredicate<'tcx> {
|
||||
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
|
||||
Self { trait_ref: self.trait_ref.with_self_ty(tcx, self_ty), ..self }
|
||||
}
|
||||
|
||||
pub fn def_id(self) -> DefId {
|
||||
self.trait_ref.def_id
|
||||
}
|
||||
|
||||
pub fn self_ty(self) -> Ty<'tcx> {
|
||||
self.trait_ref.self_ty()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> PolyTraitPredicate<'tcx> {
|
||||
pub fn def_id(self) -> DefId {
|
||||
// Ok to skip binder since trait `DefId` does not care about regions.
|
||||
self.skip_binder().def_id()
|
||||
}
|
||||
|
||||
pub fn self_ty(self) -> ty::Binder<'tcx, Ty<'tcx>> {
|
||||
self.map_bound(|trait_ref| trait_ref.self_ty())
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn polarity(self) -> ImplPolarity {
|
||||
self.skip_binder().polarity
|
||||
}
|
||||
}
|
||||
|
||||
/// `A: B`
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct OutlivesPredicate<A, B>(pub A, pub B);
|
||||
pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>;
|
||||
pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>;
|
||||
pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
|
||||
pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
|
||||
|
||||
/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
|
||||
/// whether the `a` type is the type that we should label as "expected" when
|
||||
/// presenting user diagnostics.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct SubtypePredicate<'tcx> {
|
||||
pub a_is_expected: bool,
|
||||
pub a: Ty<'tcx>,
|
||||
pub b: Ty<'tcx>,
|
||||
}
|
||||
pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
|
||||
|
||||
/// Encodes that we have to coerce *from* the `a` type to the `b` type.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct CoercePredicate<'tcx> {
|
||||
pub a: Ty<'tcx>,
|
||||
pub b: Ty<'tcx>,
|
||||
}
|
||||
pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Term<'tcx> {
|
||||
ptr: NonNull<()>,
|
||||
@@ -1048,351 +719,6 @@ impl From<ty::ConstVid> for TermVid {
|
||||
}
|
||||
}
|
||||
|
||||
/// This kind of predicate has no *direct* correspondent in the
|
||||
/// syntax, but it roughly corresponds to the syntactic forms:
|
||||
///
|
||||
/// 1. `T: TraitRef<..., Item = Type>`
|
||||
/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
|
||||
///
|
||||
/// In particular, form #1 is "desugared" to the combination of a
|
||||
/// normal trait predicate (`T: TraitRef<...>`) and one of these
|
||||
/// predicates. Form #2 is a broader form in that it also permits
|
||||
/// equality between arbitrary types. Processing an instance of
|
||||
/// Form #2 eventually yields one of these `ProjectionPredicate`
|
||||
/// instances to normalize the LHS.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct ProjectionPredicate<'tcx> {
|
||||
pub projection_ty: AliasTy<'tcx>,
|
||||
pub term: Term<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> ProjectionPredicate<'tcx> {
|
||||
pub fn self_ty(self) -> Ty<'tcx> {
|
||||
self.projection_ty.self_ty()
|
||||
}
|
||||
|
||||
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> {
|
||||
Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
|
||||
}
|
||||
|
||||
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
|
||||
self.projection_ty.trait_def_id(tcx)
|
||||
}
|
||||
|
||||
pub fn def_id(self) -> DefId {
|
||||
self.projection_ty.def_id
|
||||
}
|
||||
}
|
||||
|
||||
pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
|
||||
|
||||
impl<'tcx> PolyProjectionPredicate<'tcx> {
|
||||
/// Returns the `DefId` of the trait of the associated item being projected.
|
||||
#[inline]
|
||||
pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId {
|
||||
self.skip_binder().projection_ty.trait_def_id(tcx)
|
||||
}
|
||||
|
||||
/// Get the [PolyTraitRef] required for this projection to be well formed.
|
||||
/// Note that for generic associated types the predicates of the associated
|
||||
/// type also need to be checked.
|
||||
#[inline]
|
||||
pub fn required_poly_trait_ref(&self, tcx: TyCtxt<'tcx>) -> PolyTraitRef<'tcx> {
|
||||
// Note: unlike with `TraitRef::to_poly_trait_ref()`,
|
||||
// `self.0.trait_ref` is permitted to have escaping regions.
|
||||
// This is because here `self` has a `Binder` and so does our
|
||||
// return value, so we are preserving the number of binding
|
||||
// levels.
|
||||
self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx))
|
||||
}
|
||||
|
||||
pub fn term(&self) -> Binder<'tcx, Term<'tcx>> {
|
||||
self.map_bound(|predicate| predicate.term)
|
||||
}
|
||||
|
||||
/// The `DefId` of the `TraitItem` for the associated type.
|
||||
///
|
||||
/// Note that this is not the `DefId` of the `TraitRef` containing this
|
||||
/// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
|
||||
pub fn projection_def_id(&self) -> DefId {
|
||||
// Ok to skip binder since trait `DefId` does not care about regions.
|
||||
self.skip_binder().projection_ty.def_id
|
||||
}
|
||||
}
|
||||
|
||||
/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be
|
||||
/// proven by actually normalizing `alias`.
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
||||
pub struct NormalizesTo<'tcx> {
|
||||
pub alias: AliasTy<'tcx>,
|
||||
pub term: Term<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> NormalizesTo<'tcx> {
|
||||
pub fn self_ty(self) -> Ty<'tcx> {
|
||||
self.alias.self_ty()
|
||||
}
|
||||
|
||||
pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> {
|
||||
Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self }
|
||||
}
|
||||
|
||||
pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
|
||||
self.alias.trait_def_id(tcx)
|
||||
}
|
||||
|
||||
pub fn def_id(self) -> DefId {
|
||||
self.alias.def_id
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToPolyTraitRef<'tcx> {
|
||||
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>;
|
||||
}
|
||||
|
||||
impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> {
|
||||
fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> {
|
||||
self.map_bound_ref(|trait_pred| trait_pred.trait_ref)
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ToPredicate<'tcx, P = Predicate<'tcx>> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> P;
|
||||
}
|
||||
|
||||
impl<'tcx, T> ToPredicate<'tcx, T> for T {
|
||||
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> T {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for PredicateKind<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
ty::Binder::dummy(self).to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, PredicateKind<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
tcx.mk_predicate(self)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for ClauseKind<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
tcx.mk_predicate(ty::Binder::dummy(ty::PredicateKind::Clause(self)))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, ClauseKind<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
tcx.mk_predicate(self.map_bound(ty::PredicateKind::Clause))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for Clause<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
self.as_predicate()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ClauseKind<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||
tcx.mk_predicate(Binder::dummy(ty::PredicateKind::Clause(self))).expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, ClauseKind<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||
tcx.mk_predicate(self.map_bound(|clause| ty::PredicateKind::Clause(clause))).expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
ty::Binder::dummy(self).to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, TraitPredicate<'tcx>> for TraitRef<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, _tcx: TyCtxt<'tcx>) -> TraitPredicate<'tcx> {
|
||||
TraitPredicate { trait_ref: self, polarity: ImplPolarity::Positive }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitRef<'tcx> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||
let p: Predicate<'tcx> = self.to_predicate(tcx);
|
||||
p.expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for Binder<'tcx, TraitRef<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
|
||||
pred.to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||
let pred: PolyTraitPredicate<'tcx> = self.to_predicate(tcx);
|
||||
pred.to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef<'tcx>> {
|
||||
#[inline(always)]
|
||||
fn to_predicate(self, _: TyCtxt<'tcx>) -> PolyTraitPredicate<'tcx> {
|
||||
self.map_bound(|trait_ref| TraitPredicate {
|
||||
trait_ref,
|
||||
polarity: ty::ImplPolarity::Positive,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||
let p: Predicate<'tcx> = self.to_predicate(tcx);
|
||||
p.expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||
let p: Predicate<'tcx> = self.to_predicate(tcx);
|
||||
p.expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
self.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(self))).to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for ProjectionPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(self))).to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
self.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||
let p: Predicate<'tcx> = self.to_predicate(tcx);
|
||||
p.expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||
let p: Predicate<'tcx> = self.to_predicate(tcx);
|
||||
p.expect_clause()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> ToPredicate<'tcx> for NormalizesTo<'tcx> {
|
||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||
PredicateKind::NormalizesTo(self).to_predicate(tcx)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Predicate<'tcx> {
|
||||
pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
|
||||
let predicate = self.kind();
|
||||
match predicate.skip_binder() {
|
||||
PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
|
||||
PredicateKind::Clause(ClauseKind::Projection(..))
|
||||
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
|
||||
| PredicateKind::NormalizesTo(..)
|
||||
| PredicateKind::AliasRelate(..)
|
||||
| PredicateKind::Subtype(..)
|
||||
| PredicateKind::Coerce(..)
|
||||
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
|
||||
| PredicateKind::Clause(ClauseKind::WellFormed(..))
|
||||
| PredicateKind::ObjectSafe(..)
|
||||
| PredicateKind::Clause(ClauseKind::TypeOutlives(..))
|
||||
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
|
||||
| PredicateKind::ConstEquate(..)
|
||||
| PredicateKind::Ambiguous => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_opt_poly_projection_pred(self) -> Option<PolyProjectionPredicate<'tcx>> {
|
||||
let predicate = self.kind();
|
||||
match predicate.skip_binder() {
|
||||
PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
|
||||
PredicateKind::Clause(ClauseKind::Trait(..))
|
||||
| PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
|
||||
| PredicateKind::NormalizesTo(..)
|
||||
| PredicateKind::AliasRelate(..)
|
||||
| PredicateKind::Subtype(..)
|
||||
| PredicateKind::Coerce(..)
|
||||
| PredicateKind::Clause(ClauseKind::RegionOutlives(..))
|
||||
| PredicateKind::Clause(ClauseKind::WellFormed(..))
|
||||
| PredicateKind::ObjectSafe(..)
|
||||
| PredicateKind::Clause(ClauseKind::TypeOutlives(..))
|
||||
| PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
|
||||
| PredicateKind::ConstEquate(..)
|
||||
| PredicateKind::Ambiguous => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`.
|
||||
pub fn as_clause(self) -> Option<Clause<'tcx>> {
|
||||
match self.kind().skip_binder() {
|
||||
PredicateKind::Clause(..) => Some(self.expect_clause()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Assert that the predicate is a clause.
|
||||
pub fn expect_clause(self) -> Clause<'tcx> {
|
||||
match self.kind().skip_binder() {
|
||||
PredicateKind::Clause(..) => Clause(self.0),
|
||||
_ => bug!("{self} is not a clause"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents the bounds declared on a particular set of type
|
||||
/// parameters. Should eventually be generalized into a flag list of
|
||||
/// where-clauses. You can obtain an `InstantiatedPredicates` list from a
|
||||
|
||||
Reference in New Issue
Block a user