diff options
| author | Michael Goulet <michael@errs.io> | 2024-05-11 12:46:11 -0400 |
|---|---|---|
| committer | Michael Goulet <michael@errs.io> | 2024-05-11 18:20:00 -0400 |
| commit | 0d4dca2b8225a5ed9af715de5c2a07f63fadb26f (patch) | |
| tree | 364b7aa724d099d6762b917dcfbc3aa86475ff8e | |
| parent | 204cde4564665301cb053e004b80b0673d28999f (diff) | |
| download | rust-0d4dca2b8225a5ed9af715de5c2a07f63fadb26f.tar.gz rust-0d4dca2b8225a5ed9af715de5c2a07f63fadb26f.zip | |
Uplift `ExistentialTraitRef`, `ExistentialProjection`, `ProjectionPredicate`
| -rw-r--r-- | compiler/rustc_errors/src/diagnostic_impls.rs | 8 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 14 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/predicate.rs | 147 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/print/pretty.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/structural_impls.rs | 12 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 30 | ||||
| -rw-r--r-- | compiler/rustc_type_ir/src/inherent.rs | 28 | ||||
| -rw-r--r-- | compiler/rustc_type_ir/src/interner.rs | 23 | ||||
| -rw-r--r-- | compiler/rustc_type_ir/src/ir_print.rs | 15 | ||||
| -rw-r--r-- | compiler/rustc_type_ir/src/lib.rs | 4 | ||||
| -rw-r--r-- | compiler/rustc_type_ir/src/predicate.rs | 298 | ||||
| -rw-r--r-- | compiler/rustc_type_ir/src/trait_ref.rs | 146 |
12 files changed, 428 insertions, 325 deletions
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 40560a5ad79..60a2f5469fe 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -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); impl IntoDiagArg for bool { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0464be2df06..93fba3fbc86 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -99,17 +99,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type CanonicalVars = CanonicalVarInfos<'tcx>; type Ty = Ty<'tcx>; - type Pat = Pattern<'tcx>; type Tys = &'tcx List<Ty<'tcx>>; type AliasTy = ty::AliasTy<'tcx>; type ParamTy = ParamTy; type BoundTy = ty::BoundTy; type PlaceholderTy = ty::PlaceholderType; - type ErrorGuaranteed = ErrorGuaranteed; + type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>; type PolyFnSig = PolyFnSig<'tcx>; type AllocId = crate::mir::interpret::AllocId; + type Pat = Pattern<'tcx>; type Const = ty::Const<'tcx>; type AliasConst = ty::UnevaluatedConst<'tcx>; @@ -121,8 +121,8 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Region = Region<'tcx>; type EarlyParamRegion = ty::EarlyParamRegion; - type BoundRegion = ty::BoundRegion; type LateParamRegion = ty::LateParamRegion; + type BoundRegion = ty::BoundRegion; type InferRegion = ty::RegionVid; type PlaceholderRegion = ty::PlaceholderRegion; @@ -146,6 +146,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.generics_of(def_id) } + fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs { + self.mk_args(args) + } + fn check_and_mk_args( self, def_id: DefId, @@ -153,6 +157,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ) -> ty::GenericArgsRef<'tcx> { 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>, ()>; diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 80a9499e862..bc5f75f58c3 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -1,21 +1,25 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::Interned; -use rustc_errors::{DiagArgValue, IntoDiagArg}; use rustc_hir::def_id::DefId; use rustc_macros::{HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_type_ir::ClauseKind as IrClauseKind; use rustc_type_ir::PredicateKind as IrPredicateKind; use rustc_type_ir::TraitPredicate as IrTraitPredicate; 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 crate::ty::visit::TypeVisitableExt; use crate::ty::{ - self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArgsRef, + self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo, }; 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 ClauseKind<'tcx> = IrClauseKind<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>>; 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>>; -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> { pub fn with_self_ty( &self, @@ -628,43 +532,6 @@ pub struct 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>>; impl<'tcx> PolyProjectionPredicate<'tcx> { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index fc42ba6fcd3..9e5edb97fe2 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3087,14 +3087,6 @@ define_print! { 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> { // 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)) } + 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> { match *self { ty::ExistentialPredicate::Trait(x) => p!(print(x)), @@ -3186,12 +3192,6 @@ define_print_and_forward_display! { p!(print(self.b)) } - ty::ProjectionPredicate<'tcx> { - p!(print(self.projection_ty), " == "); - cx.reset_type_limit(); - p!(print(self.term)) - } - ty::NormalizesTo<'tcx> { p!(print(self.alias), " normalizes-to "); cx.reset_type_limit(); diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index e0fbcb1a7f0..b08ae4e5890 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -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> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 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> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index a97244dda9a..1fc8eefd65f 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1142,6 +1142,36 @@ pub struct AliasTy<'tcx> { _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> { pub fn new( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 0fd34e0a65f..cf67f82efd7 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -1,5 +1,6 @@ use std::fmt::Debug; use std::hash::Hash; +use std::ops::Deref; use crate::fold::TypeSuperFoldable; use crate::visit::{Flags, TypeSuperVisitable}; @@ -50,7 +51,12 @@ pub trait GenericsOf<I: Interner<GenericsOf = 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; @@ -83,3 +89,23 @@ pub trait BoundVars<I: Interner> { 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; + +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index fe14836b1d5..bfa769237a1 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -5,9 +5,20 @@ use std::hash::Hash; use crate::inherent::*; use crate::ir_print::IrPrint; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; -use crate::{CanonicalVarInfo, DebugWithInfcx, TraitPredicate, TraitRef}; - -pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> + IrPrint<TraitPredicate<Self>> { +use crate::{ + CanonicalVarInfo, DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, + ProjectionPredicate, TraitPredicate, TraitRef, +}; + +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 DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable<Self>; type AdtDef: Copy + Debug + Hash + Eq; @@ -25,7 +36,7 @@ pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> + IrPrint<TraitPredic // Kinds of tys type Ty: Ty<Self>; 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 BoundTy: Copy + Debug + Hash + Eq; type PlaceholderTy: PlaceholderLike; @@ -71,11 +82,15 @@ pub trait Interner: Sized + Copy + IrPrint<TraitRef<Self>> + IrPrint<TraitPredic type GenericsOf: GenericsOf<Self>; fn generics_of(self, def_id: Self::DefId) -> Self::GenericsOf; + fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs; + fn check_and_mk_args( self, def_id: Self::DefId, args: impl IntoIterator<Item: Into<Self::GenericArg>>, ) -> Self::GenericArgs; + + fn parent(self, def_id: Self::DefId) -> Self::DefId; } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs index 715fb317669..9b72764b4d1 100644 --- a/compiler/rustc_type_ir/src/ir_print.rs +++ b/compiler/rustc_type_ir/src/ir_print.rs @@ -1,6 +1,9 @@ use std::fmt; -use crate::{Interner, TraitPredicate, TraitRef}; +use crate::{ + ExistentialProjection, ExistentialTraitRef, Interner, ProjectionPredicate, TraitPredicate, + TraitRef, +}; pub trait IrPrint<T> { 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); diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 62efa32c9f2..184b882c2b7 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -39,7 +39,7 @@ mod infcx; mod interner; mod predicate_kind; mod region_kind; -mod trait_ref; +mod predicate; pub use canonical::*; #[cfg(feature = "nightly")] @@ -51,7 +51,7 @@ pub use infcx::InferCtxtLike; pub use interner::*; pub use predicate_kind::*; pub use region_kind::*; -pub use trait_ref::*; +pub use predicate::*; pub use ty_info::*; pub use ty_kind::*; pub use AliasKind::*; diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs new file mode 100644 index 00000000000..9cd9319a1b1 --- /dev/null +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -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) + } +} diff --git a/compiler/rustc_type_ir/src/trait_ref.rs b/compiler/rustc_type_ir/src/trait_ref.rs deleted file mode 100644 index 0aae75ebf43..00000000000 --- a/compiler/rustc_type_ir/src/trait_ref.rs +++ /dev/null @@ -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"), - } - } -} |
