Uplift ExistentialTraitRef
, ExistentialProjection
, ProjectionPredicate
This commit is contained in:
parent
204cde4564
commit
0d4dca2b82
12 changed files with 427 additions and 324 deletions
|
@ -100,6 +100,14 @@ impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::TraitRef<I> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
impl<I: rustc_type_ir::Interner> IntoDiagArg for rustc_type_ir::ExistentialTraitRef<I> {
|
||||||
|
fn into_diag_arg(self) -> DiagArgValue {
|
||||||
|
self.to_string().into_diag_arg()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
|
into_diag_arg_for_number!(i8, u8, i16, u16, i32, u32, i64, u64, i128, u128, isize, usize);
|
||||||
|
|
||||||
impl IntoDiagArg for bool {
|
impl IntoDiagArg for bool {
|
||||||
|
|
|
@ -99,17 +99,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||||
type CanonicalVars = CanonicalVarInfos<'tcx>;
|
type CanonicalVars = CanonicalVarInfos<'tcx>;
|
||||||
|
|
||||||
type Ty = Ty<'tcx>;
|
type Ty = Ty<'tcx>;
|
||||||
type Pat = Pattern<'tcx>;
|
|
||||||
type Tys = &'tcx List<Ty<'tcx>>;
|
type Tys = &'tcx List<Ty<'tcx>>;
|
||||||
type AliasTy = ty::AliasTy<'tcx>;
|
type AliasTy = ty::AliasTy<'tcx>;
|
||||||
type ParamTy = ParamTy;
|
type ParamTy = ParamTy;
|
||||||
type BoundTy = ty::BoundTy;
|
type BoundTy = ty::BoundTy;
|
||||||
type PlaceholderTy = ty::PlaceholderType;
|
type PlaceholderTy = ty::PlaceholderType;
|
||||||
|
|
||||||
type ErrorGuaranteed = ErrorGuaranteed;
|
type ErrorGuaranteed = ErrorGuaranteed;
|
||||||
|
|
||||||
type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>;
|
type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>;
|
||||||
type PolyFnSig = PolyFnSig<'tcx>;
|
type PolyFnSig = PolyFnSig<'tcx>;
|
||||||
type AllocId = crate::mir::interpret::AllocId;
|
type AllocId = crate::mir::interpret::AllocId;
|
||||||
|
type Pat = Pattern<'tcx>;
|
||||||
|
|
||||||
type Const = ty::Const<'tcx>;
|
type Const = ty::Const<'tcx>;
|
||||||
type AliasConst = ty::UnevaluatedConst<'tcx>;
|
type AliasConst = ty::UnevaluatedConst<'tcx>;
|
||||||
|
@ -121,8 +121,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||||
|
|
||||||
type Region = Region<'tcx>;
|
type Region = Region<'tcx>;
|
||||||
type EarlyParamRegion = ty::EarlyParamRegion;
|
type EarlyParamRegion = ty::EarlyParamRegion;
|
||||||
type BoundRegion = ty::BoundRegion;
|
|
||||||
type LateParamRegion = ty::LateParamRegion;
|
type LateParamRegion = ty::LateParamRegion;
|
||||||
|
type BoundRegion = ty::BoundRegion;
|
||||||
type InferRegion = ty::RegionVid;
|
type InferRegion = ty::RegionVid;
|
||||||
type PlaceholderRegion = ty::PlaceholderRegion;
|
type PlaceholderRegion = ty::PlaceholderRegion;
|
||||||
|
|
||||||
|
@ -146,6 +146,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||||
self.generics_of(def_id)
|
self.generics_of(def_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs {
|
||||||
|
self.mk_args(args)
|
||||||
|
}
|
||||||
|
|
||||||
fn check_and_mk_args(
|
fn check_and_mk_args(
|
||||||
self,
|
self,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
|
@ -153,6 +157,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||||
) -> ty::GenericArgsRef<'tcx> {
|
) -> ty::GenericArgsRef<'tcx> {
|
||||||
self.check_and_mk_args(def_id, args)
|
self.check_and_mk_args(def_id, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn parent(self, def_id: Self::DefId) -> Self::DefId {
|
||||||
|
self.parent(def_id)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
||||||
|
|
|
@ -1,21 +1,25 @@
|
||||||
use rustc_data_structures::captures::Captures;
|
use rustc_data_structures::captures::Captures;
|
||||||
use rustc_data_structures::intern::Interned;
|
use rustc_data_structures::intern::Interned;
|
||||||
use rustc_errors::{DiagArgValue, IntoDiagArg};
|
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable};
|
||||||
use rustc_type_ir::ClauseKind as IrClauseKind;
|
use rustc_type_ir::ClauseKind as IrClauseKind;
|
||||||
use rustc_type_ir::PredicateKind as IrPredicateKind;
|
use rustc_type_ir::PredicateKind as IrPredicateKind;
|
||||||
use rustc_type_ir::TraitPredicate as IrTraitPredicate;
|
use rustc_type_ir::TraitPredicate as IrTraitPredicate;
|
||||||
use rustc_type_ir::TraitRef as IrTraitRef;
|
use rustc_type_ir::TraitRef as IrTraitRef;
|
||||||
|
use rustc_type_ir::ProjectionPredicate as IrProjectionPredicate;
|
||||||
|
use rustc_type_ir::ExistentialTraitRef as IrExistentialTraitRef;
|
||||||
|
use rustc_type_ir::ExistentialProjection as IrExistentialProjection;
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use crate::ty::visit::TypeVisitableExt;
|
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArgsRef,
|
self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder,
|
||||||
PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo,
|
PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub type TraitRef<'tcx> = IrTraitRef<TyCtxt<'tcx>>;
|
pub type TraitRef<'tcx> = IrTraitRef<TyCtxt<'tcx>>;
|
||||||
|
pub type ProjectionPredicate<'tcx> = IrProjectionPredicate<TyCtxt<'tcx>>;
|
||||||
|
pub type ExistentialTraitRef<'tcx> = IrExistentialTraitRef<TyCtxt<'tcx>>;
|
||||||
|
pub type ExistentialProjection<'tcx> = IrExistentialProjection<TyCtxt<'tcx>>;
|
||||||
pub type TraitPredicate<'tcx> = IrTraitPredicate<TyCtxt<'tcx>>;
|
pub type TraitPredicate<'tcx> = IrTraitPredicate<TyCtxt<'tcx>>;
|
||||||
pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;
|
pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>;
|
||||||
pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>;
|
pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>;
|
||||||
|
@ -342,52 +346,6 @@ impl<'tcx> PolyTraitRef<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An existential reference to a trait, where `Self` is erased.
|
|
||||||
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
|
|
||||||
/// ```ignore (illustrative)
|
|
||||||
/// exists T. T: Trait<'a, 'b, X, Y>
|
|
||||||
/// ```
|
|
||||||
/// The generic parameters don't include the erased `Self`, only trait
|
|
||||||
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
|
|
||||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
|
||||||
pub struct ExistentialTraitRef<'tcx> {
|
|
||||||
pub def_id: DefId,
|
|
||||||
pub args: GenericArgsRef<'tcx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> ExistentialTraitRef<'tcx> {
|
|
||||||
pub fn erase_self_ty(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
trait_ref: ty::TraitRef<'tcx>,
|
|
||||||
) -> ty::ExistentialTraitRef<'tcx> {
|
|
||||||
// Assert there is a Self.
|
|
||||||
trait_ref.args.type_at(0);
|
|
||||||
|
|
||||||
ty::ExistentialTraitRef {
|
|
||||||
def_id: trait_ref.def_id,
|
|
||||||
args: tcx.mk_args(&trait_ref.args[1..]),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Object types don't have a self type specified. Therefore, when
|
|
||||||
/// we convert the principal trait-ref into a normal trait-ref,
|
|
||||||
/// you must give *some* self type. A common choice is `mk_err()`
|
|
||||||
/// or some placeholder type.
|
|
||||||
pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> {
|
|
||||||
// otherwise the escaping vars would be captured by the binder
|
|
||||||
// debug_assert!(!self_ty.has_escaping_bound_vars());
|
|
||||||
|
|
||||||
ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> IntoDiagArg for ExistentialTraitRef<'tcx> {
|
|
||||||
fn into_diag_arg(self) -> DiagArgValue {
|
|
||||||
self.to_string().into_diag_arg()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
|
pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
|
||||||
|
|
||||||
impl<'tcx> PolyExistentialTraitRef<'tcx> {
|
impl<'tcx> PolyExistentialTraitRef<'tcx> {
|
||||||
|
@ -404,62 +362,8 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
|
|
||||||
#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
|
|
||||||
pub struct ExistentialProjection<'tcx> {
|
|
||||||
pub def_id: DefId,
|
|
||||||
pub args: GenericArgsRef<'tcx>,
|
|
||||||
pub term: Term<'tcx>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
|
pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
|
||||||
|
|
||||||
impl<'tcx> ExistentialProjection<'tcx> {
|
|
||||||
/// Extracts the underlying existential trait reference from this projection.
|
|
||||||
/// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
|
|
||||||
/// then this function would return an `exists T. T: Iterator` existential trait
|
|
||||||
/// reference.
|
|
||||||
pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> {
|
|
||||||
let def_id = tcx.parent(self.def_id);
|
|
||||||
let args_count = tcx.generics_of(def_id).count() - 1;
|
|
||||||
let args = tcx.mk_args(&self.args[..args_count]);
|
|
||||||
ty::ExistentialTraitRef { def_id, args }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_self_ty(
|
|
||||||
&self,
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
self_ty: Ty<'tcx>,
|
|
||||||
) -> ty::ProjectionPredicate<'tcx> {
|
|
||||||
// otherwise the escaping regions would be captured by the binders
|
|
||||||
debug_assert!(!self_ty.has_escaping_bound_vars());
|
|
||||||
|
|
||||||
ty::ProjectionPredicate {
|
|
||||||
projection_ty: AliasTy::new(
|
|
||||||
tcx,
|
|
||||||
self.def_id,
|
|
||||||
[self_ty.into()].into_iter().chain(self.args),
|
|
||||||
),
|
|
||||||
term: self.term,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn erase_self_ty(
|
|
||||||
tcx: TyCtxt<'tcx>,
|
|
||||||
projection_predicate: ty::ProjectionPredicate<'tcx>,
|
|
||||||
) -> Self {
|
|
||||||
// Assert there is a Self.
|
|
||||||
projection_predicate.projection_ty.args.type_at(0);
|
|
||||||
|
|
||||||
Self {
|
|
||||||
def_id: projection_predicate.projection_ty.def_id,
|
|
||||||
args: tcx.mk_args(&projection_predicate.projection_ty.args[1..]),
|
|
||||||
term: projection_predicate.term,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> PolyExistentialProjection<'tcx> {
|
impl<'tcx> PolyExistentialProjection<'tcx> {
|
||||||
pub fn with_self_ty(
|
pub fn with_self_ty(
|
||||||
&self,
|
&self,
|
||||||
|
@ -628,43 +532,6 @@ pub struct CoercePredicate<'tcx> {
|
||||||
}
|
}
|
||||||
pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
|
pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
|
||||||
|
|
||||||
/// 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>>;
|
pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>;
|
||||||
|
|
||||||
impl<'tcx> PolyProjectionPredicate<'tcx> {
|
impl<'tcx> PolyProjectionPredicate<'tcx> {
|
||||||
|
|
|
@ -3087,14 +3087,6 @@ define_print! {
|
||||||
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
|
ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
define_print_and_forward_display! {
|
|
||||||
(self, cx):
|
|
||||||
|
|
||||||
&'tcx ty::List<Ty<'tcx>> {
|
|
||||||
p!("{{", comma_sep(self.iter()), "}}")
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::ExistentialTraitRef<'tcx> {
|
ty::ExistentialTraitRef<'tcx> {
|
||||||
// Use a type that can't appear in defaults of type parameters.
|
// Use a type that can't appear in defaults of type parameters.
|
||||||
|
@ -3108,6 +3100,20 @@ define_print_and_forward_display! {
|
||||||
p!(write("{} = ", name), print(self.term))
|
p!(write("{} = ", name), print(self.term))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ty::ProjectionPredicate<'tcx> {
|
||||||
|
p!(print(self.projection_ty), " == ");
|
||||||
|
cx.reset_type_limit();
|
||||||
|
p!(print(self.term))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
define_print_and_forward_display! {
|
||||||
|
(self, cx):
|
||||||
|
|
||||||
|
&'tcx ty::List<Ty<'tcx>> {
|
||||||
|
p!("{{", comma_sep(self.iter()), "}}")
|
||||||
|
}
|
||||||
|
|
||||||
ty::ExistentialPredicate<'tcx> {
|
ty::ExistentialPredicate<'tcx> {
|
||||||
match *self {
|
match *self {
|
||||||
ty::ExistentialPredicate::Trait(x) => p!(print(x)),
|
ty::ExistentialPredicate::Trait(x) => p!(print(x)),
|
||||||
|
@ -3186,12 +3192,6 @@ define_print_and_forward_display! {
|
||||||
p!(print(self.b))
|
p!(print(self.b))
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::ProjectionPredicate<'tcx> {
|
|
||||||
p!(print(self.projection_ty), " == ");
|
|
||||||
cx.reset_type_limit();
|
|
||||||
p!(print(self.term))
|
|
||||||
}
|
|
||||||
|
|
||||||
ty::NormalizesTo<'tcx> {
|
ty::NormalizesTo<'tcx> {
|
||||||
p!(print(self.alias), " normalizes-to ");
|
p!(print(self.alias), " normalizes-to ");
|
||||||
cx.reset_type_limit();
|
cx.reset_type_limit();
|
||||||
|
|
|
@ -55,12 +55,6 @@ impl fmt::Debug for ty::UpvarId {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
with_no_trimmed_paths!(fmt::Display::fmt(self, f))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
|
impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "{:?} -> {}", self.kind, self.target)
|
write!(f, "{:?} -> {}", self.kind, self.target)
|
||||||
|
@ -158,12 +152,6 @@ impl fmt::Debug for ty::ParamConst {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for ty::ProjectionPredicate<'tcx> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'tcx> fmt::Debug for ty::NormalizesTo<'tcx> {
|
impl<'tcx> fmt::Debug for ty::NormalizesTo<'tcx> {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
|
write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
|
||||||
|
|
|
@ -1142,6 +1142,36 @@ pub struct AliasTy<'tcx> {
|
||||||
_use_alias_ty_new_instead: (),
|
_use_alias_ty_new_instead: (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> rustc_type_ir::inherent::AliasTy<TyCtxt<'tcx>> for AliasTy<'tcx> {
|
||||||
|
fn new(
|
||||||
|
interner: TyCtxt<'tcx>,
|
||||||
|
trait_def_id: DefId,
|
||||||
|
args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>,
|
||||||
|
) -> Self {
|
||||||
|
AliasTy::new(interner, trait_def_id, args)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn def_id(self) -> DefId {
|
||||||
|
self.def_id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn args(self) -> ty::GenericArgsRef<'tcx> {
|
||||||
|
self.args
|
||||||
|
}
|
||||||
|
|
||||||
|
fn trait_def_id(self, interner: TyCtxt<'tcx>) -> DefId {
|
||||||
|
self.trait_def_id(interner)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn self_ty(self) -> Ty<'tcx> {
|
||||||
|
self.self_ty()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self {
|
||||||
|
self.with_self_ty(tcx, self_ty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> AliasTy<'tcx> {
|
impl<'tcx> AliasTy<'tcx> {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
use std::ops::Deref;
|
||||||
|
|
||||||
use crate::fold::TypeSuperFoldable;
|
use crate::fold::TypeSuperFoldable;
|
||||||
use crate::visit::{Flags, TypeSuperVisitable};
|
use crate::visit::{Flags, TypeSuperVisitable};
|
||||||
|
@ -50,7 +51,12 @@ pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
|
pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
|
||||||
Copy + DebugWithInfcx<I> + Hash + Eq + IntoIterator<Item = I::GenericArg>
|
Copy
|
||||||
|
+ DebugWithInfcx<I>
|
||||||
|
+ Hash
|
||||||
|
+ Eq
|
||||||
|
+ IntoIterator<Item = I::GenericArg>
|
||||||
|
+ Deref<Target: Deref<Target = [I::GenericArg]>>
|
||||||
{
|
{
|
||||||
fn type_at(self, i: usize) -> I::Ty;
|
fn type_at(self, i: usize) -> I::Ty;
|
||||||
|
|
||||||
|
@ -83,3 +89,23 @@ pub trait BoundVars<I: Interner> {
|
||||||
|
|
||||||
fn has_no_bound_vars(&self) -> bool;
|
fn has_no_bound_vars(&self) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: Uplift `AliasTy`
|
||||||
|
pub trait AliasTy<I: Interner>: Copy + DebugWithInfcx<I> + Hash + Eq + Sized {
|
||||||
|
fn new(
|
||||||
|
interner: I,
|
||||||
|
trait_def_id: I::DefId,
|
||||||
|
args: impl IntoIterator<Item: Into<I::GenericArg>>,
|
||||||
|
) -> Self;
|
||||||
|
|
||||||
|
fn def_id(self) -> I::DefId;
|
||||||
|
|
||||||
|
fn args(self) -> I::GenericArgs;
|
||||||
|
|
||||||
|
fn trait_def_id(self, interner: I) -> I::DefId;
|
||||||
|
|
||||||
|
fn self_ty(self) -> I::Ty;
|
||||||
|
|
||||||
|
fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> Self;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -5,9 +5,20 @@ use std::hash::Hash;
|
||||||
use crate::inherent::*;
|
use crate::inherent::*;
|
||||||
use crate::ir_print::IrPrint;
|
use crate::ir_print::IrPrint;
|
||||||
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
|
||||||
use crate::{CanonicalVarInfo, DebugWithInfcx, TraitPredicate, TraitRef};
|
use crate::{
|
||||||
|
CanonicalVarInfo, DebugWithInfcx, ExistentialProjection, ExistentialTraitRef,
|
||||||
|
ProjectionPredicate, TraitPredicate, TraitRef,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> + IrPrint<TraitPredicate<Self>> {
|
pub trait Interner:
|
||||||
|
Sized
|
||||||
|
+ Copy
|
||||||
|
+ IrPrint<TraitRef<Self>>
|
||||||
|
+ IrPrint<TraitPredicate<Self>>
|
||||||
|
+ IrPrint<ExistentialTraitRef<Self>>
|
||||||
|
+ IrPrint<ExistentialProjection<Self>>
|
||||||
|
+ IrPrint<ProjectionPredicate<Self>>
|
||||||
|
{
|
||||||
type DefId: Copy + Debug + Hash + Eq;
|
type DefId: Copy + Debug + Hash + Eq;
|
||||||
type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>;
|
type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>;
|
||||||
type AdtDef: Copy + Debug + Hash + Eq;
|
type AdtDef: Copy + Debug + Hash + Eq;
|
||||||
|
@ -25,7 +36,7 @@ pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> + IrPrint<TraitPredic
|
||||||
// Kinds of tys
|
// Kinds of tys
|
||||||
type Ty: Ty<Self>;
|
type Ty: Ty<Self>;
|
||||||
type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
|
type Tys: Copy + Debug + Hash + Eq + IntoIterator<Item = Self::Ty>;
|
||||||
type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Eq;
|
type AliasTy: AliasTy<Self>;
|
||||||
type ParamTy: Copy + Debug + Hash + Eq;
|
type ParamTy: Copy + Debug + Hash + Eq;
|
||||||
type BoundTy: Copy + Debug + Hash + Eq;
|
type BoundTy: Copy + Debug + Hash + Eq;
|
||||||
type PlaceholderTy: PlaceholderLike;
|
type PlaceholderTy: PlaceholderLike;
|
||||||
|
@ -71,11 +82,15 @@ pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> + IrPrint<TraitPredic
|
||||||
type GenericsOf: GenericsOf<Self>;
|
type GenericsOf: GenericsOf<Self>;
|
||||||
fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
|
fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf;
|
||||||
|
|
||||||
|
fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs;
|
||||||
|
|
||||||
fn check_and_mk_args(
|
fn check_and_mk_args(
|
||||||
self,
|
self,
|
||||||
def_id: Self::DefId,
|
def_id: Self::DefId,
|
||||||
args: impl IntoIterator<Item: Into<Self::GenericArg>>,
|
args: impl IntoIterator<Item: Into<Self::GenericArg>>,
|
||||||
) -> Self::GenericArgs;
|
) -> Self::GenericArgs;
|
||||||
|
|
||||||
|
fn parent(self, def_id: Self::DefId) -> Self::DefId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
|
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
use crate::{Interner, TraitPredicate, TraitRef};
|
use crate::{
|
||||||
|
ExistentialProjection, ExistentialTraitRef, Interner, ProjectionPredicate, TraitPredicate,
|
||||||
|
TraitRef,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait IrPrint<T> {
|
pub trait IrPrint<T> {
|
||||||
fn print(t: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
|
fn print(t: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result;
|
||||||
|
@ -31,6 +34,12 @@ macro_rules! define_debug_via_print {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
define_display_via_print!(TraitRef, TraitPredicate,);
|
define_display_via_print!(
|
||||||
|
TraitRef,
|
||||||
|
TraitPredicate,
|
||||||
|
ExistentialTraitRef,
|
||||||
|
ExistentialProjection,
|
||||||
|
ProjectionPredicate
|
||||||
|
);
|
||||||
|
|
||||||
define_debug_via_print!(TraitRef,);
|
define_debug_via_print!(TraitRef, ExistentialTraitRef, ExistentialProjection);
|
||||||
|
|
|
@ -39,7 +39,7 @@ mod infcx;
|
||||||
mod interner;
|
mod interner;
|
||||||
mod predicate_kind;
|
mod predicate_kind;
|
||||||
mod region_kind;
|
mod region_kind;
|
||||||
mod trait_ref;
|
mod predicate;
|
||||||
|
|
||||||
pub use canonical::*;
|
pub use canonical::*;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
|
@ -51,7 +51,7 @@ pub use infcx::InferCtxtLike;
|
||||||
pub use interner::*;
|
pub use interner::*;
|
||||||
pub use predicate_kind::*;
|
pub use predicate_kind::*;
|
||||||
pub use region_kind::*;
|
pub use region_kind::*;
|
||||||
pub use trait_ref::*;
|
pub use predicate::*;
|
||||||
pub use ty_info::*;
|
pub use ty_info::*;
|
||||||
pub use ty_kind::*;
|
pub use ty_kind::*;
|
||||||
pub use AliasKind::*;
|
pub use AliasKind::*;
|
||||||
|
|
298
compiler/rustc_type_ir/src/predicate.rs
Normal file
298
compiler/rustc_type_ir/src/predicate.rs
Normal file
|
@ -0,0 +1,298 @@
|
||||||
|
use std::fmt;
|
||||||
|
|
||||||
|
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
||||||
|
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||||
|
|
||||||
|
use crate::inherent::*;
|
||||||
|
use crate::visit::TypeVisitableExt as _;
|
||||||
|
use crate::Interner;
|
||||||
|
|
||||||
|
/// A complete reference to a trait. These take numerous guises in syntax,
|
||||||
|
/// but perhaps the most recognizable form is in a where-clause:
|
||||||
|
/// ```ignore (illustrative)
|
||||||
|
/// T: Foo<U>
|
||||||
|
/// ```
|
||||||
|
/// This would be represented by a trait-reference where the `DefId` is the
|
||||||
|
/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
|
||||||
|
/// and `U` as parameter 1.
|
||||||
|
///
|
||||||
|
/// Trait references also appear in object types like `Foo<U>`, but in
|
||||||
|
/// that case the `Self` parameter is absent from the generic parameters.
|
||||||
|
#[derive(derivative::Derivative)]
|
||||||
|
#[derivative(
|
||||||
|
Clone(bound = ""),
|
||||||
|
Copy(bound = ""),
|
||||||
|
Hash(bound = ""),
|
||||||
|
PartialEq(bound = ""),
|
||||||
|
Eq(bound = "")
|
||||||
|
)]
|
||||||
|
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||||
|
pub struct TraitRef<I: Interner> {
|
||||||
|
pub def_id: I::DefId,
|
||||||
|
pub args: I::GenericArgs,
|
||||||
|
/// This field exists to prevent the creation of `TraitRef` without
|
||||||
|
/// calling [`TraitRef::new`].
|
||||||
|
_use_trait_ref_new_instead: (),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> TraitRef<I> {
|
||||||
|
pub fn new(
|
||||||
|
interner: I,
|
||||||
|
trait_def_id: I::DefId,
|
||||||
|
args: impl IntoIterator<Item: Into<I::GenericArg>>,
|
||||||
|
) -> Self {
|
||||||
|
let args = interner.check_and_mk_args(trait_def_id, args);
|
||||||
|
Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn from_method(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
|
||||||
|
let generics = interner.generics_of(trait_id);
|
||||||
|
TraitRef::new(interner, trait_id, args.into_iter().take(generics.count()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
|
||||||
|
/// are the parameters defined on trait.
|
||||||
|
pub fn identity(interner: I, def_id: I::DefId) -> TraitRef<I> {
|
||||||
|
TraitRef::new(interner, def_id, I::GenericArgs::identity_for_item(interner, def_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
|
||||||
|
TraitRef::new(
|
||||||
|
interner,
|
||||||
|
self.def_id,
|
||||||
|
[self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn self_ty(&self) -> I::Ty {
|
||||||
|
self.args.type_at(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(derivative::Derivative)]
|
||||||
|
#[derivative(
|
||||||
|
Clone(bound = ""),
|
||||||
|
Copy(bound = ""),
|
||||||
|
Hash(bound = ""),
|
||||||
|
PartialEq(bound = ""),
|
||||||
|
Eq(bound = "")
|
||||||
|
)]
|
||||||
|
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||||
|
pub struct TraitPredicate<I: Interner> {
|
||||||
|
pub trait_ref: TraitRef<I>,
|
||||||
|
|
||||||
|
/// 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: PredicatePolarity,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> TraitPredicate<I> {
|
||||||
|
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
|
||||||
|
Self { trait_ref: self.trait_ref.with_self_ty(interner, self_ty), polarity: self.polarity }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn def_id(self) -> I::DefId {
|
||||||
|
self.trait_ref.def_id
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn self_ty(self) -> I::Ty {
|
||||||
|
self.trait_ref.self_ty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> fmt::Debug for TraitPredicate<I> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
// FIXME(effects) printing?
|
||||||
|
write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Polarity for a trait predicate. May either be negative or positive.
|
||||||
|
/// Distinguished from [`ImplPolarity`] since we never compute goals with
|
||||||
|
/// "reservation" level.
|
||||||
|
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||||
|
pub enum PredicatePolarity {
|
||||||
|
/// `Type: Trait`
|
||||||
|
Positive,
|
||||||
|
/// `Type: !Trait`
|
||||||
|
Negative,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PredicatePolarity {
|
||||||
|
/// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
|
||||||
|
pub fn flip(&self) -> PredicatePolarity {
|
||||||
|
match self {
|
||||||
|
PredicatePolarity::Positive => PredicatePolarity::Negative,
|
||||||
|
PredicatePolarity::Negative => PredicatePolarity::Positive,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for PredicatePolarity {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Self::Positive => f.write_str("positive"),
|
||||||
|
Self::Negative => f.write_str("negative"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An existential reference to a trait, where `Self` is erased.
|
||||||
|
/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
|
||||||
|
/// ```ignore (illustrative)
|
||||||
|
/// exists T. T: Trait<'a, 'b, X, Y>
|
||||||
|
/// ```
|
||||||
|
/// The generic parameters don't include the erased `Self`, only trait
|
||||||
|
/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
|
||||||
|
#[derive(derivative::Derivative)]
|
||||||
|
#[derivative(
|
||||||
|
Clone(bound = ""),
|
||||||
|
Copy(bound = ""),
|
||||||
|
Hash(bound = ""),
|
||||||
|
PartialEq(bound = ""),
|
||||||
|
Eq(bound = "")
|
||||||
|
)]
|
||||||
|
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||||
|
pub struct ExistentialTraitRef<I: Interner> {
|
||||||
|
pub def_id: I::DefId,
|
||||||
|
pub args: I::GenericArgs,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> ExistentialTraitRef<I> {
|
||||||
|
pub fn erase_self_ty(interner: I, trait_ref: TraitRef<I>) -> ExistentialTraitRef<I> {
|
||||||
|
// Assert there is a Self.
|
||||||
|
trait_ref.args.type_at(0);
|
||||||
|
|
||||||
|
ExistentialTraitRef {
|
||||||
|
def_id: trait_ref.def_id,
|
||||||
|
args: interner.mk_args(&trait_ref.args[1..]),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Object types don't have a self type specified. Therefore, when
|
||||||
|
/// we convert the principal trait-ref into a normal trait-ref,
|
||||||
|
/// you must give *some* self type. A common choice is `mk_err()`
|
||||||
|
/// or some placeholder type.
|
||||||
|
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef<I> {
|
||||||
|
// otherwise the escaping vars would be captured by the binder
|
||||||
|
// debug_assert!(!self_ty.has_escaping_bound_vars());
|
||||||
|
|
||||||
|
TraitRef::new(interner, self.def_id, [self_ty.into()].into_iter().chain(self.args.into_iter()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
|
||||||
|
#[derive(derivative::Derivative)]
|
||||||
|
#[derivative(
|
||||||
|
Clone(bound = ""),
|
||||||
|
Copy(bound = ""),
|
||||||
|
Hash(bound = ""),
|
||||||
|
PartialEq(bound = ""),
|
||||||
|
Eq(bound = "")
|
||||||
|
)]
|
||||||
|
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||||
|
pub struct ExistentialProjection<I: Interner> {
|
||||||
|
pub def_id: I::DefId,
|
||||||
|
pub args: I::GenericArgs,
|
||||||
|
pub term: I::Term,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> ExistentialProjection<I> {
|
||||||
|
/// Extracts the underlying existential trait reference from this projection.
|
||||||
|
/// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
|
||||||
|
/// then this function would return an `exists T. T: Iterator` existential trait
|
||||||
|
/// reference.
|
||||||
|
pub fn trait_ref(&self, tcx: I) -> ExistentialTraitRef<I> {
|
||||||
|
let def_id = tcx.parent(self.def_id);
|
||||||
|
let args_count = tcx.generics_of(def_id).count() - 1;
|
||||||
|
let args = tcx.mk_args(&self.args[..args_count]);
|
||||||
|
ExistentialTraitRef { def_id, args }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_self_ty(&self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
|
||||||
|
// otherwise the escaping regions would be captured by the binders
|
||||||
|
debug_assert!(!self_ty.has_escaping_bound_vars());
|
||||||
|
|
||||||
|
ProjectionPredicate {
|
||||||
|
projection_ty: I::AliasTy::new(
|
||||||
|
tcx,
|
||||||
|
self.def_id,
|
||||||
|
[self_ty.into()].into_iter().chain(self.args),
|
||||||
|
),
|
||||||
|
term: self.term,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn erase_self_ty(tcx: I, projection_predicate: ProjectionPredicate<I>) -> Self {
|
||||||
|
// Assert there is a Self.
|
||||||
|
projection_predicate.projection_ty.args().type_at(0);
|
||||||
|
|
||||||
|
Self {
|
||||||
|
def_id: projection_predicate.projection_ty.def_id(),
|
||||||
|
args: tcx.mk_args(&projection_predicate.projection_ty.args()[1..]),
|
||||||
|
term: projection_predicate.term,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 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(derivative::Derivative)]
|
||||||
|
#[derivative(
|
||||||
|
Clone(bound = ""),
|
||||||
|
Copy(bound = ""),
|
||||||
|
Hash(bound = ""),
|
||||||
|
PartialEq(bound = ""),
|
||||||
|
Eq(bound = "")
|
||||||
|
)]
|
||||||
|
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||||
|
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||||
|
pub struct ProjectionPredicate<I: Interner> {
|
||||||
|
pub projection_ty: I::AliasTy,
|
||||||
|
pub term: I::Term,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> ProjectionPredicate<I> {
|
||||||
|
pub fn self_ty(self) -> I::Ty {
|
||||||
|
self.projection_ty.self_ty()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
|
||||||
|
Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn trait_def_id(self, tcx: I) -> I::DefId {
|
||||||
|
self.projection_ty.trait_def_id(tcx)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn def_id(self) -> I::DefId {
|
||||||
|
self.projection_ty.def_id()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<I: Interner> fmt::Debug for ProjectionPredicate<I> {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term)
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,146 +0,0 @@
|
||||||
use std::fmt;
|
|
||||||
|
|
||||||
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
|
||||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
|
||||||
|
|
||||||
use crate::inherent::*;
|
|
||||||
use crate::Interner;
|
|
||||||
|
|
||||||
/// A complete reference to a trait. These take numerous guises in syntax,
|
|
||||||
/// but perhaps the most recognizable form is in a where-clause:
|
|
||||||
/// ```ignore (illustrative)
|
|
||||||
/// T: Foo<U>
|
|
||||||
/// ```
|
|
||||||
/// This would be represented by a trait-reference where the `DefId` is the
|
|
||||||
/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
|
|
||||||
/// and `U` as parameter 1.
|
|
||||||
///
|
|
||||||
/// Trait references also appear in object types like `Foo<U>`, but in
|
|
||||||
/// that case the `Self` parameter is absent from the generic parameters.
|
|
||||||
#[derive(derivative::Derivative)]
|
|
||||||
#[derivative(
|
|
||||||
Clone(bound = ""),
|
|
||||||
Copy(bound = ""),
|
|
||||||
Hash(bound = ""),
|
|
||||||
PartialEq(bound = ""),
|
|
||||||
Eq(bound = "")
|
|
||||||
)]
|
|
||||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
|
||||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
|
||||||
pub struct TraitRef<I: Interner> {
|
|
||||||
pub def_id: I::DefId,
|
|
||||||
pub args: I::GenericArgs,
|
|
||||||
/// This field exists to prevent the creation of `TraitRef` without
|
|
||||||
/// calling [`TraitRef::new`].
|
|
||||||
_use_trait_ref_new_instead: (),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I: Interner> TraitRef<I> {
|
|
||||||
pub fn new(
|
|
||||||
interner: I,
|
|
||||||
trait_def_id: I::DefId,
|
|
||||||
args: impl IntoIterator<Item: Into<I::GenericArg>>,
|
|
||||||
) -> Self {
|
|
||||||
let args = interner.check_and_mk_args(trait_def_id, args);
|
|
||||||
Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn from_method(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
|
|
||||||
let generics = interner.generics_of(trait_id);
|
|
||||||
TraitRef::new(interner, trait_id, args.into_iter().take(generics.count()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
|
|
||||||
/// are the parameters defined on trait.
|
|
||||||
pub fn identity(interner: I, def_id: I::DefId) -> TraitRef<I> {
|
|
||||||
TraitRef::new(interner, def_id, I::GenericArgs::identity_for_item(interner, def_id))
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
|
|
||||||
TraitRef::new(
|
|
||||||
interner,
|
|
||||||
self.def_id,
|
|
||||||
[self_ty.into()].into_iter().chain(self.args.into_iter().skip(1)),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
pub fn self_ty(&self) -> I::Ty {
|
|
||||||
self.args.type_at(0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(derivative::Derivative)]
|
|
||||||
#[derivative(
|
|
||||||
Clone(bound = ""),
|
|
||||||
Copy(bound = ""),
|
|
||||||
Hash(bound = ""),
|
|
||||||
PartialEq(bound = ""),
|
|
||||||
Eq(bound = "")
|
|
||||||
)]
|
|
||||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
|
||||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
|
||||||
pub struct TraitPredicate<I: Interner> {
|
|
||||||
pub trait_ref: TraitRef<I>,
|
|
||||||
|
|
||||||
/// 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: PredicatePolarity,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I: Interner> TraitPredicate<I> {
|
|
||||||
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
|
|
||||||
Self { trait_ref: self.trait_ref.with_self_ty(interner, self_ty), polarity: self.polarity }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn def_id(self) -> I::DefId {
|
|
||||||
self.trait_ref.def_id
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn self_ty(self) -> I::Ty {
|
|
||||||
self.trait_ref.self_ty()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<I: Interner> fmt::Debug for TraitPredicate<I> {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
// FIXME(effects) printing?
|
|
||||||
write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Polarity for a trait predicate. May either be negative or positive.
|
|
||||||
/// Distinguished from [`ImplPolarity`] since we never compute goals with
|
|
||||||
/// "reservation" level.
|
|
||||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
|
|
||||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
|
||||||
pub enum PredicatePolarity {
|
|
||||||
/// `Type: Trait`
|
|
||||||
Positive,
|
|
||||||
/// `Type: !Trait`
|
|
||||||
Negative,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl PredicatePolarity {
|
|
||||||
/// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
|
|
||||||
pub fn flip(&self) -> PredicatePolarity {
|
|
||||||
match self {
|
|
||||||
PredicatePolarity::Positive => PredicatePolarity::Negative,
|
|
||||||
PredicatePolarity::Negative => PredicatePolarity::Positive,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Display for PredicatePolarity {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
match self {
|
|
||||||
Self::Positive => f.write_str("positive"),
|
|
||||||
Self::Negative => f.write_str("negative"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Add table
Add a link
Reference in a new issue