From d5797e938a371c96c6ed649e605091a9ca0ad775 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Fri, 10 May 2024 20:30:24 -0400 Subject: [PATCH 1/6] Make it possible to derive Lift/TypeVisitable/TypeFoldable in rustc_type_ir --- Cargo.lock | 11 ++ compiler/rustc_type_ir/Cargo.toml | 1 + compiler/rustc_type_ir/src/canonical.rs | 151 +++--------------- compiler/rustc_type_ir/src/const_kind.rs | 4 +- compiler/rustc_type_ir/src/predicate_kind.rs | 127 +-------------- compiler/rustc_type_ir/src/region_kind.rs | 5 +- compiler/rustc_type_ir/src/trait_ref.rs | 44 +---- compiler/rustc_type_ir/src/ty_kind.rs | 32 +--- compiler/rustc_type_ir_macros/Cargo.toml | 15 ++ compiler/rustc_type_ir_macros/src/lib.rs | 159 +++++++++++++++++++ 10 files changed, 218 insertions(+), 331 deletions(-) create mode 100644 compiler/rustc_type_ir_macros/Cargo.toml create mode 100644 compiler/rustc_type_ir_macros/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index f49bcf7c865..2aed7ebacd5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4837,9 +4837,20 @@ dependencies = [ "rustc_macros", "rustc_serialize", "rustc_span", + "rustc_type_ir_macros", "smallvec", ] +[[package]] +name = "rustc_type_ir_macros" +version = "0.0.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.62", + "synstructure", +] + [[package]] name = "rustc_version" version = "0.4.0" diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index 79ff60802d2..d12052625ea 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -11,6 +11,7 @@ rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_index = { path = "../rustc_index", default-features = false } rustc_macros = { path = "../rustc_macros", optional = true } +rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_span = { path = "../rustc_span", optional = true } smallvec = { version = "1.8.1" } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index f7c7ec242c1..efefd174cd6 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -1,20 +1,25 @@ -use rustc_ast_ir::try_visit; -use rustc_ast_ir::visit::VisitorResult; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use std::fmt; use std::hash::Hash; -use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::inherent::*; -use crate::visit::{TypeVisitable, TypeVisitor}; use crate::{Interner, UniverseIndex}; /// A "canonicalized" type `V` is one where all free inference /// variables have been rewritten to "canonical vars". These are /// numbered starting from 0 in order of first appearance. #[derive(derivative::Derivative)] -#[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))] +#[derivative( + Clone(bound = "V: Clone"), + Hash(bound = "V: Hash"), + PartialEq(bound = "V: PartialEq"), + Eq(bound = "V: Eq"), + Debug(bound = "V: fmt::Debug"), + Copy(bound = "V: Copy") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub struct Canonical { pub value: V, @@ -64,18 +69,6 @@ pub fn unchecked_rebind(self, value: W) -> Canonical { } } -impl Eq for Canonical {} - -impl PartialEq for Canonical { - fn eq(&self, other: &Self) -> bool { - let Self { value, max_universe, variables, defining_opaque_types } = self; - *value == other.value - && *max_universe == other.max_universe - && *variables == other.variables - && *defining_opaque_types == other.defining_opaque_types - } -} - impl fmt::Display for Canonical { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let Self { value, max_universe, variables, defining_opaque_types } = self; @@ -86,84 +79,25 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -impl fmt::Debug for Canonical { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let Self { value, max_universe, variables, defining_opaque_types } = self; - f.debug_struct("Canonical") - .field("value", &value) - .field("max_universe", &max_universe) - .field("variables", &variables) - .field("defining_opaque_types", &defining_opaque_types) - .finish() - } -} - -impl Copy for Canonical where I::CanonicalVars: Copy {} - -impl> TypeFoldable for Canonical -where - I::CanonicalVars: TypeFoldable, -{ - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(Canonical { - value: self.value.try_fold_with(folder)?, - max_universe: self.max_universe.try_fold_with(folder)?, - variables: self.variables.try_fold_with(folder)?, - defining_opaque_types: self.defining_opaque_types, - }) - } -} - -impl> TypeVisitable for Canonical -where - I::CanonicalVars: TypeVisitable, -{ - fn visit_with>(&self, folder: &mut F) -> F::Result { - let Self { value, max_universe, variables, defining_opaque_types } = self; - try_visit!(value.visit_with(folder)); - try_visit!(max_universe.visit_with(folder)); - try_visit!(defining_opaque_types.visit_with(folder)); - variables.visit_with(folder) - } -} - /// Information about a canonical variable that is included with the /// canonical value. This is sufficient information for code to create /// a copy of the canonical value in some other inference context, /// with fresh inference variables replacing the canonical values. #[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + Debug(bound = ""), + Eq(bound = ""), + PartialEq(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct CanonicalVarInfo { pub kind: CanonicalVarKind, } -impl PartialEq for CanonicalVarInfo { - fn eq(&self, other: &Self) -> bool { - self.kind == other.kind - } -} - -impl Eq for CanonicalVarInfo {} - -impl TypeVisitable for CanonicalVarInfo -where - I::Ty: TypeVisitable, -{ - fn visit_with>(&self, visitor: &mut V) -> V::Result { - self.kind.visit_with(visitor) - } -} - -impl TypeFoldable for CanonicalVarInfo -where - I::Ty: TypeFoldable, -{ - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(CanonicalVarInfo { kind: self.kind.try_fold_with(folder)? }) - } -} - impl CanonicalVarInfo { pub fn universe(self) -> UniverseIndex { self.kind.universe() @@ -216,6 +150,7 @@ pub fn expect_placeholder_index(self) -> usize { /// that analyzes type-like values. #[derive(derivative::Derivative)] #[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub enum CanonicalVarKind { /// Some kind of type inference variable. @@ -258,51 +193,6 @@ fn eq(&self, other: &Self) -> bool { } } -impl Eq for CanonicalVarKind {} - -impl TypeVisitable for CanonicalVarKind -where - I::Ty: TypeVisitable, -{ - fn visit_with>(&self, visitor: &mut V) -> V::Result { - match self { - CanonicalVarKind::Ty(_) - | CanonicalVarKind::PlaceholderTy(_) - | CanonicalVarKind::Region(_) - | CanonicalVarKind::PlaceholderRegion(_) - | CanonicalVarKind::Effect => V::Result::output(), - CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => { - ty.visit_with(visitor) - } - } - } -} - -impl TypeFoldable for CanonicalVarKind -where - I::Ty: TypeFoldable, -{ - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(match self { - CanonicalVarKind::Ty(kind) => CanonicalVarKind::Ty(kind), - CanonicalVarKind::Region(kind) => CanonicalVarKind::Region(kind), - CanonicalVarKind::Const(kind, ty) => { - CanonicalVarKind::Const(kind, ty.try_fold_with(folder)?) - } - CanonicalVarKind::PlaceholderTy(placeholder) => { - CanonicalVarKind::PlaceholderTy(placeholder) - } - CanonicalVarKind::PlaceholderRegion(placeholder) => { - CanonicalVarKind::PlaceholderRegion(placeholder) - } - CanonicalVarKind::PlaceholderConst(placeholder, ty) => { - CanonicalVarKind::PlaceholderConst(placeholder, ty.try_fold_with(folder)?) - } - CanonicalVarKind::Effect => CanonicalVarKind::Effect, - }) - } -} - impl CanonicalVarKind { pub fn universe(self) -> UniverseIndex { match self { @@ -355,6 +245,7 @@ pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarKind { /// usize or f32). In order to faithfully reproduce a type, we need to /// know what set of types a given type variable can be unified with. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub enum CanonicalTyVarKind { /// General type variable `?T` that can be unified with arbitrary types. diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index c1506f9252b..c748cdf6ed2 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -10,7 +10,7 @@ /// Represents a constant in Rust. #[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))] +#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum ConstKind { /// A const generic parameter. @@ -58,8 +58,6 @@ fn eq(&self, other: &Self) -> bool { } } -impl Eq for ConstKind {} - impl fmt::Debug for ConstKind { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { WithInfcx::with_no_infcx(self).fmt(f) diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index 5260d9061cf..c477ab14153 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -1,17 +1,15 @@ -use rustc_ast_ir::try_visit; -use rustc_ast_ir::visit::VisitorResult; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use std::fmt; -use crate::fold::{FallibleTypeFolder, TypeFoldable}; -use crate::visit::{TypeVisitable, TypeVisitor}; use crate::Interner; /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. #[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))] +#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum ClauseKind { /// Corresponds to `where Foo: Bar`. `Foo` here would be @@ -55,61 +53,6 @@ fn eq(&self, other: &Self) -> bool { } } -impl Eq for ClauseKind {} - -impl TypeFoldable for ClauseKind -where - I::Ty: TypeFoldable, - I::Const: TypeFoldable, - I::GenericArg: TypeFoldable, - I::TraitPredicate: TypeFoldable, - I::ProjectionPredicate: TypeFoldable, - I::TypeOutlivesPredicate: TypeFoldable, - I::RegionOutlivesPredicate: TypeFoldable, -{ - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(match self { - ClauseKind::Trait(p) => ClauseKind::Trait(p.try_fold_with(folder)?), - ClauseKind::RegionOutlives(p) => ClauseKind::RegionOutlives(p.try_fold_with(folder)?), - ClauseKind::TypeOutlives(p) => ClauseKind::TypeOutlives(p.try_fold_with(folder)?), - ClauseKind::Projection(p) => ClauseKind::Projection(p.try_fold_with(folder)?), - ClauseKind::ConstArgHasType(c, t) => { - ClauseKind::ConstArgHasType(c.try_fold_with(folder)?, t.try_fold_with(folder)?) - } - ClauseKind::WellFormed(p) => ClauseKind::WellFormed(p.try_fold_with(folder)?), - ClauseKind::ConstEvaluatable(p) => { - ClauseKind::ConstEvaluatable(p.try_fold_with(folder)?) - } - }) - } -} - -impl TypeVisitable for ClauseKind -where - I::Ty: TypeVisitable, - I::Const: TypeVisitable, - I::GenericArg: TypeVisitable, - I::TraitPredicate: TypeVisitable, - I::ProjectionPredicate: TypeVisitable, - I::TypeOutlivesPredicate: TypeVisitable, - I::RegionOutlivesPredicate: TypeVisitable, -{ - fn visit_with>(&self, visitor: &mut V) -> V::Result { - match self { - ClauseKind::Trait(p) => p.visit_with(visitor), - ClauseKind::RegionOutlives(p) => p.visit_with(visitor), - ClauseKind::TypeOutlives(p) => p.visit_with(visitor), - ClauseKind::Projection(p) => p.visit_with(visitor), - ClauseKind::ConstArgHasType(c, t) => { - try_visit!(c.visit_with(visitor)); - t.visit_with(visitor) - } - ClauseKind::WellFormed(p) => p.visit_with(visitor), - ClauseKind::ConstEvaluatable(p) => p.visit_with(visitor), - } - } -} - #[derive(derivative::Derivative)] #[derivative( Clone(bound = ""), @@ -118,6 +61,7 @@ fn visit_with>(&self, visitor: &mut V) -> V::Result { PartialEq(bound = ""), Eq(bound = "") )] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum PredicateKind { /// Prove a clause @@ -167,69 +111,6 @@ pub enum PredicateKind { AliasRelate(I::Term, I::Term, AliasRelationDirection), } -impl TypeFoldable for PredicateKind -where - I::DefId: TypeFoldable, - I::Const: TypeFoldable, - I::GenericArgs: TypeFoldable, - I::Term: TypeFoldable, - I::CoercePredicate: TypeFoldable, - I::SubtypePredicate: TypeFoldable, - I::NormalizesTo: TypeFoldable, - ClauseKind: TypeFoldable, -{ - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(match self { - PredicateKind::Clause(c) => PredicateKind::Clause(c.try_fold_with(folder)?), - PredicateKind::ObjectSafe(d) => PredicateKind::ObjectSafe(d.try_fold_with(folder)?), - PredicateKind::Subtype(s) => PredicateKind::Subtype(s.try_fold_with(folder)?), - PredicateKind::Coerce(s) => PredicateKind::Coerce(s.try_fold_with(folder)?), - PredicateKind::ConstEquate(a, b) => { - PredicateKind::ConstEquate(a.try_fold_with(folder)?, b.try_fold_with(folder)?) - } - PredicateKind::Ambiguous => PredicateKind::Ambiguous, - PredicateKind::NormalizesTo(p) => PredicateKind::NormalizesTo(p.try_fold_with(folder)?), - PredicateKind::AliasRelate(a, b, d) => PredicateKind::AliasRelate( - a.try_fold_with(folder)?, - b.try_fold_with(folder)?, - d.try_fold_with(folder)?, - ), - }) - } -} - -impl TypeVisitable for PredicateKind -where - I::DefId: TypeVisitable, - I::Const: TypeVisitable, - I::GenericArgs: TypeVisitable, - I::Term: TypeVisitable, - I::CoercePredicate: TypeVisitable, - I::SubtypePredicate: TypeVisitable, - I::NormalizesTo: TypeVisitable, - ClauseKind: TypeVisitable, -{ - fn visit_with>(&self, visitor: &mut V) -> V::Result { - match self { - PredicateKind::Clause(p) => p.visit_with(visitor), - PredicateKind::ObjectSafe(d) => d.visit_with(visitor), - PredicateKind::Subtype(s) => s.visit_with(visitor), - PredicateKind::Coerce(s) => s.visit_with(visitor), - PredicateKind::ConstEquate(a, b) => { - try_visit!(a.visit_with(visitor)); - b.visit_with(visitor) - } - PredicateKind::Ambiguous => V::Result::output(), - PredicateKind::NormalizesTo(p) => p.visit_with(visitor), - PredicateKind::AliasRelate(a, b, d) => { - try_visit!(a.visit_with(visitor)); - try_visit!(b.visit_with(visitor)); - d.visit_with(visitor) - } - } - } -} - #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)] #[cfg_attr(feature = "nightly", derive(HashStable_NoContext, Encodable, Decodable))] pub enum AliasRelationDirection { diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs index d1b86b495e9..eaae4ee0130 100644 --- a/compiler/rustc_type_ir/src/region_kind.rs +++ b/compiler/rustc_type_ir/src/region_kind.rs @@ -115,7 +115,7 @@ /// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/ /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html #[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))] +#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))] pub enum RegionKind { /// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`. @@ -208,9 +208,6 @@ fn eq(&self, other: &RegionKind) -> bool { } } -// This is manually implemented because a derive would require `I: Eq` -impl Eq for RegionKind {} - impl DebugWithInfcx for RegionKind { fn fmt>( this: WithInfcx<'_, Infcx, &Self>, diff --git a/compiler/rustc_type_ir/src/trait_ref.rs b/compiler/rustc_type_ir/src/trait_ref.rs index 4bd513ab7e1..3b37df5b39d 100644 --- a/compiler/rustc_type_ir/src/trait_ref.rs +++ b/compiler/rustc_type_ir/src/trait_ref.rs @@ -1,9 +1,7 @@ use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; -use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::inherent::*; -use crate::lift::Lift; -use crate::visit::{TypeVisitable, TypeVisitor}; use crate::Interner; /// A complete reference to a trait. These take numerous guises in syntax, @@ -25,6 +23,7 @@ PartialEq(bound = ""), Eq(bound = "") )] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] #[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] pub struct TraitRef { pub def_id: I::DefId, @@ -68,42 +67,3 @@ pub fn self_ty(&self) -> I::Ty { self.args.type_at(0) } } - -// FIXME(compiler-errors): Make this into a `Lift_Generic` impl. -impl Lift for TraitRef -where - I::DefId: Lift, - I::GenericArgs: Lift, -{ - type Lifted = TraitRef; - - fn lift_to_tcx(self, tcx: U) -> Option { - Some(TraitRef { - def_id: self.def_id.lift_to_tcx(tcx)?, - args: self.args.lift_to_tcx(tcx)?, - _use_trait_ref_new_instead: (), - }) - } -} - -impl TypeVisitable for TraitRef -where - I::GenericArgs: TypeVisitable, -{ - fn visit_with>(&self, visitor: &mut V) -> V::Result { - self.args.visit_with(visitor) - } -} - -impl TypeFoldable for TraitRef -where - I::GenericArgs: TypeFoldable, -{ - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(TraitRef { - def_id: self.def_id, - args: self.args.try_fold_with(folder)?, - _use_trait_ref_new_instead: (), - }) - } -} diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index f2e4afecc40..d67327926ff 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1,14 +1,12 @@ -use rustc_ast_ir::try_visit; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] use rustc_data_structures::unify::{EqUnifyValue, UnifyKey}; #[cfg(feature = "nightly")] use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable}; +use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic}; use std::fmt; -use crate::fold::{FallibleTypeFolder, TypeFoldable}; -use crate::visit::{TypeVisitable, TypeVisitor}; use crate::Interner; use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx}; @@ -65,7 +63,7 @@ pub fn descr(self) -> &'static str { /// converted to this representation using `::lower_ty`. #[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")] #[derive(derivative::Derivative)] -#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))] +#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] pub enum TyKind { /// The primitive boolean type. Written as `bool`. @@ -341,9 +339,6 @@ fn eq(&self, other: &TyKind) -> bool { } } -// This is manually implemented because a derive would require `I: Eq` -impl Eq for TyKind {} - impl DebugWithInfcx for TyKind { fn fmt>( this: WithInfcx<'_, Infcx, &Self>, @@ -804,29 +799,8 @@ fn fmt>( Debug(bound = "") )] #[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic)] pub struct TypeAndMut { pub ty: I::Ty, pub mutbl: Mutability, } - -impl TypeFoldable for TypeAndMut -where - I::Ty: TypeFoldable, -{ - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(TypeAndMut { - ty: self.ty.try_fold_with(folder)?, - mutbl: self.mutbl.try_fold_with(folder)?, - }) - } -} - -impl TypeVisitable for TypeAndMut -where - I::Ty: TypeVisitable, -{ - fn visit_with>(&self, visitor: &mut V) -> V::Result { - try_visit!(self.ty.visit_with(visitor)); - self.mutbl.visit_with(visitor) - } -} diff --git a/compiler/rustc_type_ir_macros/Cargo.toml b/compiler/rustc_type_ir_macros/Cargo.toml new file mode 100644 index 00000000000..cb95ca68346 --- /dev/null +++ b/compiler/rustc_type_ir_macros/Cargo.toml @@ -0,0 +1,15 @@ +[package] +name = "rustc_type_ir_macros" +version = "0.0.0" +edition = "2021" + +[lib] +proc-macro = true + +[dependencies] +# tidy-alphabetical-start +proc-macro2 = "1" +quote = "1" +syn = { version = "2.0.9", features = ["full"] } +synstructure = "0.13.0" +# tidy-alphabetical-end diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs new file mode 100644 index 00000000000..eb45001cc67 --- /dev/null +++ b/compiler/rustc_type_ir_macros/src/lib.rs @@ -0,0 +1,159 @@ +use synstructure::decl_derive; +use quote::quote; +use syn::{parse_quote, visit_mut::VisitMut}; + +decl_derive!( + [TypeFoldable_Generic] => type_foldable_derive +); +decl_derive!( + [TypeVisitable_Generic] => type_visitable_derive +); +decl_derive!( + [Lift_Generic] => lift_derive +); + +fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { + if let syn::Data::Union(_) = s.ast().data { + panic!("cannot derive on union") + } + + if !s.ast().generics.type_params().any(|ty| ty.ident == "I") { + s.add_impl_generic(parse_quote! { I }); + } + + s.add_where_predicate(parse_quote! { I: Interner }); + s.add_bounds(synstructure::AddBounds::Fields); + s.bind_with(|_| synstructure::BindStyle::Move); + let body_fold = s.each_variant(|vi| { + let bindings = vi.bindings(); + vi.construct(|_, index| { + let bind = &bindings[index]; + quote! { + ::rustc_type_ir::fold::TypeFoldable::try_fold_with(#bind, __folder)? + } + }) + }); + + s.bound_impl( + quote!(::rustc_type_ir::fold::TypeFoldable), + quote! { + fn try_fold_with<__F: ::rustc_type_ir::fold::FallibleTypeFolder>( + self, + __folder: &mut __F + ) -> Result { + Ok(match self { #body_fold }) + } + }, + ) +} + +fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { + if let syn::Data::Union(_) = s.ast().data { + panic!("cannot derive on union") + } + + if !s.ast().generics.type_params().any(|ty| ty.ident == "I") { + s.add_impl_generic(parse_quote! { I }); + } + + s.add_bounds(synstructure::AddBounds::None); + s.add_where_predicate(parse_quote! { I: Interner }); + s.add_impl_generic(parse_quote! { J }); + s.add_where_predicate(parse_quote! { J: Interner }); + + let mut wc = vec![]; + s.bind_with(|_| synstructure::BindStyle::Move); + let body_fold = s.each_variant(|vi| { + let bindings = vi.bindings(); + vi.construct(|field, index| { + let ty = field.ty.clone(); + let lifted_ty = lift(ty.clone()); + wc.push(parse_quote! { #ty: ::rustc_type_ir::lift::Lift }); + let bind = &bindings[index]; + quote! { + #bind.lift_to_tcx(interner)? + } + }) + }); + for wc in wc { + s.add_where_predicate(wc); + } + + let (_, ty_generics, _) = s.ast().generics.split_for_impl(); + let name = s.ast().ident.clone(); + let self_ty: syn::Type = parse_quote! { #name #ty_generics }; + let lifted_ty = lift(self_ty); + + s.bound_impl( + quote!(::rustc_type_ir::lift::Lift), + quote! { + type Lifted = #lifted_ty; + + fn lift_to_tcx( + self, + interner: J, + ) -> Option { + Some(match self { #body_fold }) + } + }, + ) +} + +fn lift(mut ty: syn::Type) -> syn::Type { + struct ItoJ; + impl VisitMut for ItoJ { + fn visit_type_path_mut(&mut self, i: &mut syn::TypePath) { + if i.qself.is_none() { + if let Some(first) = i.path.segments.first_mut() { + if first.ident == "I" { + *first = parse_quote! { J }; + } + } + } + syn::visit_mut::visit_type_path_mut(self, i); + } + } + + ItoJ.visit_type_mut(&mut ty); + + ty +} + +fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream { + if let syn::Data::Union(_) = s.ast().data { + panic!("cannot derive on union") + } + + if !s.ast().generics.type_params().any(|ty| ty.ident == "I") { + s.add_impl_generic(parse_quote! { I }); + } + + s.add_where_predicate(parse_quote! { I: Interner }); + s.add_bounds(synstructure::AddBounds::Fields); + let body_visit = s.each(|bind| { + quote! { + match ::rustc_ast_ir::visit::VisitorResult::branch( + ::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor) + ) { + ::core::ops::ControlFlow::Continue(()) => {}, + ::core::ops::ControlFlow::Break(r) => { + return ::rustc_ast_ir::visit::VisitorResult::from_residual(r); + }, + } + } + }); + s.bind_with(|_| synstructure::BindStyle::Move); + + s.bound_impl( + quote!(::rustc_type_ir::visit::TypeVisitable), + quote! { + fn visit_with<__V: ::rustc_type_ir::visit::TypeVisitor>( + &self, + __visitor: &mut __V + ) -> __V::Result { + match *self { #body_visit } + <__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output() + } + }, + ) +} \ No newline at end of file From 204cde4564665301cb053e004b80b0673d28999f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 11 May 2024 02:03:53 -0400 Subject: [PATCH 2/6] Uplift `TraitPredicate` --- .../src/opaque_hidden_inferred_bound.rs | 5 +- compiler/rustc_middle/src/ty/mod.rs | 31 -------- compiler/rustc_middle/src/ty/predicate.rs | 31 +------- compiler/rustc_middle/src/ty/print/pretty.rs | 21 ++--- .../rustc_middle/src/ty/structural_impls.rs | 7 -- .../src/traits/error_reporting/suggestions.rs | 4 +- .../error_reporting/type_err_ctxt_ext.rs | 3 +- compiler/rustc_type_ir/Cargo.toml | 4 +- compiler/rustc_type_ir/src/interner.rs | 4 +- compiler/rustc_type_ir/src/ir_print.rs | 12 ++- compiler/rustc_type_ir/src/macros.rs | 1 + compiler/rustc_type_ir/src/trait_ref.rs | 77 +++++++++++++++++++ compiler/rustc_type_ir_macros/src/lib.rs | 4 +- 13 files changed, 114 insertions(+), 90 deletions(-) diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs index 1ea1f496e50..1d2e12ec575 100644 --- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs +++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs @@ -1,9 +1,8 @@ use rustc_hir as hir; use rustc_infer::infer::TyCtxtInferExt; use rustc_macros::{LintDiagnostic, Subdiagnostic}; -use rustc_middle::ty::{ - self, fold::BottomUpFolder, print::TraitPredPrintModifiersAndPath, Ty, TypeFoldable, -}; +use rustc_middle::ty::print::{PrintTraitPredicateExt as _, TraitPredPrintModifiersAndPath}; +use rustc_middle::ty::{self, fold::BottomUpFolder, Ty, TypeFoldable}; use rustc_session::{declare_lint, declare_lint_pass}; use rustc_span::{symbol::kw, Span}; use rustc_trait_selection::traits; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 12cefc23233..28baa334840 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -299,37 +299,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -/// Polarity for a trait predicate. May either be negative or positive. -/// Distinguished from [`ImplPolarity`] since we never compute goals with -/// "reservation" level. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] -#[derive(TypeFoldable, TypeVisitable)] -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"), - } - } -} - #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] #[derive(TypeFoldable, TypeVisitable)] pub enum Asyncness { diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 5387036d409..80a9499e862 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -5,6 +5,7 @@ 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 std::cmp::Ordering; @@ -15,6 +16,7 @@ }; pub type TraitRef<'tcx> = IrTraitRef>; +pub type TraitPredicate<'tcx> = IrTraitPredicate>; pub type ClauseKind<'tcx> = IrClauseKind>; pub type PredicateKind<'tcx> = IrPredicateKind>; @@ -578,37 +580,8 @@ pub fn instantiate_supertrait( } } -#[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: PredicatePolarity, -} - 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. diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 14a628ab064..fc42ba6fcd3 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2953,8 +2953,9 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } +#[extension(pub trait PrintTraitPredicateExt<'tcx>)] impl<'tcx> ty::TraitPredicate<'tcx> { - pub fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> { + fn print_modifiers_and_trait_path(self) -> TraitPredPrintModifiersAndPath<'tcx> { TraitPredPrintModifiersAndPath(self) } } @@ -3037,6 +3038,15 @@ macro_rules! define_print_and_forward_display { p!(write("<{} as {}>", self.self_ty(), self.print_only_trait_path())) } + ty::TraitPredicate<'tcx> { + p!(print(self.trait_ref.self_ty()), ": "); + p!(pretty_print_bound_constness(self.trait_ref)); + if let ty::PredicatePolarity::Negative = self.polarity { + p!("!"); + } + p!(print(self.trait_ref.print_trait_sugared())) + } + ty::TypeAndMut<'tcx> { p!(write("{}", self.mutbl.prefix_str()), print(self.ty)) } @@ -3176,15 +3186,6 @@ macro_rules! define_print_and_forward_display { p!(print(self.b)) } - ty::TraitPredicate<'tcx> { - p!(print(self.trait_ref.self_ty()), ": "); - p!(pretty_print_bound_constness(self.trait_ref)); - if let ty::PredicatePolarity::Negative = self.polarity { - p!("!"); - } - p!(print(self.trait_ref.print_trait_sugared())) - } - ty::ProjectionPredicate<'tcx> { p!(print(self.projection_ty), " == "); 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 a7770f71926..e0fbcb1a7f0 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -158,13 +158,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -impl<'tcx> fmt::Debug for ty::TraitPredicate<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // FIXME(effects) printing? - write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity) - } -} - 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) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 51a4e910d62..ea1752a6e98 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -45,7 +45,9 @@ use crate::infer::InferCtxtExt as _; use crate::traits::error_reporting::type_err_ctxt_ext::InferCtxtPrivExt; use crate::traits::query::evaluate_obligation::InferCtxtExt as _; -use rustc_middle::ty::print::{with_forced_trimmed_paths, with_no_trimmed_paths}; +use rustc_middle::ty::print::{ + with_forced_trimmed_paths, with_no_trimmed_paths, PrintTraitPredicateExt as _, +}; use itertools::EitherOrBoth; use itertools::Itertools; diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 92fe50883d0..08ffe37b8b4 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -38,7 +38,8 @@ use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fold::{BottomUpFolder, TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::print::{ - with_forced_trimmed_paths, FmtPrinter, Print, PrintTraitRefExt as _, + with_forced_trimmed_paths, FmtPrinter, Print, PrintTraitPredicateExt as _, + PrintTraitRefExt as _, }; use rustc_middle::ty::{ self, SubtypePredicate, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml index d12052625ea..cef3f4e8ce0 100644 --- a/compiler/rustc_type_ir/Cargo.toml +++ b/compiler/rustc_type_ir/Cargo.toml @@ -11,10 +11,10 @@ rustc_ast_ir = { path = "../rustc_ast_ir" } rustc_data_structures = { path = "../rustc_data_structures", optional = true } rustc_index = { path = "../rustc_index", default-features = false } rustc_macros = { path = "../rustc_macros", optional = true } -rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } rustc_serialize = { path = "../rustc_serialize", optional = true } rustc_span = { path = "../rustc_span", optional = true } -smallvec = { version = "1.8.1" } +rustc_type_ir_macros = { path = "../rustc_type_ir_macros" } +smallvec = { version = "1.8.1", default-features = false } # tidy-alphabetical-end [features] diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index c8bd7fea11b..fe14836b1d5 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -5,9 +5,9 @@ use crate::inherent::*; use crate::ir_print::IrPrint; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; -use crate::{CanonicalVarInfo, DebugWithInfcx, TraitRef}; +use crate::{CanonicalVarInfo, DebugWithInfcx, TraitPredicate, TraitRef}; -pub trait Interner: Sized + Copy + IrPrint> { +pub trait Interner: Sized + Copy + IrPrint> + IrPrint> { type DefId: Copy + Debug + Hash + Eq; type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable; type AdtDef: Copy + Debug + Hash + Eq; diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs index 84e889b486a..715fb317669 100644 --- a/compiler/rustc_type_ir/src/ir_print.rs +++ b/compiler/rustc_type_ir/src/ir_print.rs @@ -1,6 +1,6 @@ use std::fmt; -use crate::{Interner, TraitRef}; +use crate::{Interner, TraitPredicate, TraitRef}; pub trait IrPrint { fn print(t: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; @@ -15,7 +15,13 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { >>::print(self, fmt) } } + )* + } +} +macro_rules! define_debug_via_print { + ($($ty:ident),+ $(,)?) => { + $( impl fmt::Debug for $ty { fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { >>::print_debug(self, fmt) @@ -25,4 +31,6 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { } } -define_display_via_print!(TraitRef,); +define_display_via_print!(TraitRef, TraitPredicate,); + +define_debug_via_print!(TraitRef,); diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs index 7dcc8851a43..f2f7b165de5 100644 --- a/compiler/rustc_type_ir/src/macros.rs +++ b/compiler/rustc_type_ir/src/macros.rs @@ -53,4 +53,5 @@ fn visit_with>( crate::UniverseIndex, rustc_ast_ir::Mutability, rustc_ast_ir::Movability, + crate::PredicatePolarity, } diff --git a/compiler/rustc_type_ir/src/trait_ref.rs b/compiler/rustc_type_ir/src/trait_ref.rs index 3b37df5b39d..0aae75ebf43 100644 --- a/compiler/rustc_type_ir/src/trait_ref.rs +++ b/compiler/rustc_type_ir/src/trait_ref.rs @@ -1,3 +1,5 @@ +use std::fmt; + use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic}; @@ -67,3 +69,78 @@ 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 { + pub trait_ref: TraitRef, + + /// 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 TraitPredicate { + 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 fmt::Debug for TraitPredicate { + 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"), + } + } +} diff --git a/compiler/rustc_type_ir_macros/src/lib.rs b/compiler/rustc_type_ir_macros/src/lib.rs index eb45001cc67..000bcf2d3b2 100644 --- a/compiler/rustc_type_ir_macros/src/lib.rs +++ b/compiler/rustc_type_ir_macros/src/lib.rs @@ -1,6 +1,6 @@ -use synstructure::decl_derive; use quote::quote; use syn::{parse_quote, visit_mut::VisitMut}; +use synstructure::decl_derive; decl_derive!( [TypeFoldable_Generic] => type_foldable_derive @@ -156,4 +156,4 @@ fn visit_with<__V: ::rustc_type_ir::visit::TypeVisitor>( } }, ) -} \ No newline at end of file +} From 0d4dca2b8225a5ed9af715de5c2a07f63fadb26f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 11 May 2024 12:46:11 -0400 Subject: [PATCH 3/6] Uplift `ExistentialTraitRef`, `ExistentialProjection`, `ProjectionPredicate` --- compiler/rustc_errors/src/diagnostic_impls.rs | 8 + compiler/rustc_middle/src/ty/context.rs | 14 +- compiler/rustc_middle/src/ty/predicate.rs | 147 +-------- compiler/rustc_middle/src/ty/print/pretty.rs | 28 +- .../rustc_middle/src/ty/structural_impls.rs | 12 - compiler/rustc_middle/src/ty/sty.rs | 30 ++ compiler/rustc_type_ir/src/inherent.rs | 28 +- compiler/rustc_type_ir/src/interner.rs | 21 +- compiler/rustc_type_ir/src/ir_print.rs | 15 +- compiler/rustc_type_ir/src/lib.rs | 4 +- compiler/rustc_type_ir/src/predicate.rs | 298 ++++++++++++++++++ compiler/rustc_type_ir/src/trait_ref.rs | 146 --------- 12 files changed, 427 insertions(+), 324 deletions(-) create mode 100644 compiler/rustc_type_ir/src/predicate.rs delete mode 100644 compiler/rustc_type_ir/src/trait_ref.rs 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 @@ fn into_diag_arg(self) -> DiagArgValue { } } + + +impl IntoDiagArg for rustc_type_ir::ExistentialTraitRef { + 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>; type AliasTy = ty::AliasTy<'tcx>; type ParamTy = ParamTy; type BoundTy = ty::BoundTy; type PlaceholderTy = ty::PlaceholderType; - type ErrorGuaranteed = ErrorGuaranteed; + type BoundExistentialPredicates = &'tcx List>; 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 @@ fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics { 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 @@ fn check_and_mk_args( ) -> 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, ()>; 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>; +pub type ProjectionPredicate<'tcx> = IrProjectionPredicate>; +pub type ExistentialTraitRef<'tcx> = IrExistentialTraitRef>; +pub type ExistentialProjection<'tcx> = IrExistentialProjection>; pub type TraitPredicate<'tcx> = IrTraitPredicate>; pub type ClauseKind<'tcx> = IrClauseKind>; pub type PredicateKind<'tcx> = IrPredicateKind>; @@ -342,52 +346,6 @@ pub fn def_id(&self) -> DefId { } } -/// 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 @@ pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::PolyTrai } } -/// 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. ::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. `>::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 @@ macro_rules! define_print_and_forward_display { ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)), } } -} - -define_print_and_forward_display! { - (self, cx): - - &'tcx ty::List> { - p!("{{", comma_sep(self.iter()), "}}") - } ty::ExistentialTraitRef<'tcx> { // Use a type that can't appear in defaults of type parameters. @@ -3108,6 +3100,20 @@ macro_rules! 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> { + p!("{{", comma_sep(self.iter()), "}}") + } + ty::ExistentialPredicate<'tcx> { match *self { ty::ExistentialPredicate::Trait(x) => p!(print(x)), @@ -3186,12 +3192,6 @@ macro_rules! 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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -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 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -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> for AliasTy<'tcx> { + fn new( + interner: TyCtxt<'tcx>, + trait_def_id: DefId, + args: impl IntoIterator>>, + ) -> 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> { } pub trait GenericArgs>: - Copy + DebugWithInfcx + Hash + Eq + IntoIterator + Copy + + DebugWithInfcx + + Hash + + Eq + + IntoIterator + + Deref> { fn type_at(self, i: usize) -> I::Ty; @@ -83,3 +89,23 @@ pub trait BoundVars { fn has_no_bound_vars(&self) -> bool; } + +// TODO: Uplift `AliasTy` +pub trait AliasTy: Copy + DebugWithInfcx + Hash + Eq + Sized { + fn new( + interner: I, + trait_def_id: I::DefId, + args: impl IntoIterator>, + ) -> 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 crate::inherent::*; use crate::ir_print::IrPrint; 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> + IrPrint> { +pub trait Interner: + Sized + + Copy + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> +{ type DefId: Copy + Debug + Hash + Eq; type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable; type AdtDef: Copy + Debug + Hash + Eq; @@ -25,7 +36,7 @@ pub trait Interner: Sized + Copy + IrPrint> + IrPrint; type Tys: Copy + Debug + Hash + Eq + IntoIterator; - type AliasTy: Copy + DebugWithInfcx + Hash + Eq; + type AliasTy: AliasTy; 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> + IrPrint; 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>, ) -> 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 { fn print(t: &T, fmt: &mut fmt::Formatter<'_>) -> fmt::Result; @@ -31,6 +34,12 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { } } -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 interner; mod predicate_kind; mod region_kind; -mod trait_ref; +mod predicate; pub use canonical::*; #[cfg(feature = "nightly")] @@ -51,7 +51,7 @@ 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 +/// ``` +/// 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`, 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 { + 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 TraitRef { + pub fn new( + interner: I, + trait_def_id: I::DefId, + args: impl IntoIterator>, + ) -> 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 { + 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` where `Pi` + /// are the parameters defined on trait. + pub fn identity(interner: I, def_id: I::DefId) -> TraitRef { + 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 { + pub trait_ref: TraitRef, + + /// 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 TraitPredicate { + 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 fmt::Debug for TraitPredicate { + 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 { + pub def_id: I::DefId, + pub args: I::GenericArgs, +} + +impl ExistentialTraitRef { + pub fn erase_self_ty(interner: I, trait_ref: TraitRef) -> ExistentialTraitRef { + // 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 { + // 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 { + pub def_id: I::DefId, + pub args: I::GenericArgs, + pub term: I::Term, +} + +impl ExistentialProjection { + /// Extracts the underlying existential trait reference from this projection. + /// For example, if this is a projection of `exists T. ::Item == X`, + /// then this function would return an `exists T. T: Iterator` existential trait + /// reference. + pub fn trait_ref(&self, tcx: I) -> ExistentialTraitRef { + 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 { + // 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) -> 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. `>::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 { + pub projection_ty: I::AliasTy, + pub term: I::Term, +} + +impl ProjectionPredicate { + 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 { + 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 fmt::Debug for ProjectionPredicate { + 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 -/// ``` -/// 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`, 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 { - 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 TraitRef { - pub fn new( - interner: I, - trait_def_id: I::DefId, - args: impl IntoIterator>, - ) -> 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 { - 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` where `Pi` - /// are the parameters defined on trait. - pub fn identity(interner: I, def_id: I::DefId) -> TraitRef { - 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 { - pub trait_ref: TraitRef, - - /// 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 TraitPredicate { - 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 fmt::Debug for TraitPredicate { - 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"), - } - } -} From 0a8f33830c1ff5607ab731bc40b07fd0a15edfd8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 11 May 2024 13:51:25 -0400 Subject: [PATCH 4/6] Uplift `NormalizesTo`, `CoercePredicate`, and `SubtypePredicate` --- compiler/rustc_errors/src/diagnostic_impls.rs | 2 - compiler/rustc_middle/src/ty/context.rs | 4 +- compiler/rustc_middle/src/ty/predicate.rs | 60 +++---------- compiler/rustc_middle/src/ty/print/pretty.rs | 36 ++++---- .../rustc_middle/src/ty/structural_impls.rs | 6 -- compiler/rustc_type_ir/src/inherent.rs | 3 +- compiler/rustc_type_ir/src/interner.rs | 7 +- compiler/rustc_type_ir/src/ir_print.rs | 9 +- compiler/rustc_type_ir/src/lib.rs | 4 +- compiler/rustc_type_ir/src/predicate.rs | 84 ++++++++++++++++++- 10 files changed, 128 insertions(+), 87 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index 60a2f5469fe..2cc0167dbaa 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -100,8 +100,6 @@ fn into_diag_arg(self) -> DiagArgValue { } } - - impl IntoDiagArg for rustc_type_ir::ExistentialTraitRef { fn into_diag_arg(self) -> DiagArgValue { self.to_string().into_diag_arg() diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 93fba3fbc86..70fb937cae7 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -149,7 +149,7 @@ fn generics_of(self, def_id: DefId) -> &'tcx ty::Generics { fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs { self.mk_args(args) } - + fn check_and_mk_args( self, def_id: DefId, @@ -157,7 +157,7 @@ fn check_and_mk_args( ) -> ty::GenericArgsRef<'tcx> { self.check_and_mk_args(def_id, args) } - + fn parent(self, def_id: Self::DefId) -> Self::DefId { self.parent(def_id) } diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index bc5f75f58c3..dbbb86cb28e 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -3,17 +3,20 @@ 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::CoercePredicate as IrCoercePredicate; +use rustc_type_ir::ExistentialProjection as IrExistentialProjection; +use rustc_type_ir::ExistentialTraitRef as IrExistentialTraitRef; +use rustc_type_ir::NormalizesTo as IrNormalizesTo; use rustc_type_ir::PredicateKind as IrPredicateKind; +use rustc_type_ir::ProjectionPredicate as IrProjectionPredicate; +use rustc_type_ir::SubtypePredicate as IrSubtypePredicate; 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::{ - self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, - PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo, + self, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, PredicatePolarity, Term, Ty, TyCtxt, + TypeFlags, WithCachedTypeInfo, }; pub type TraitRef<'tcx> = IrTraitRef>; @@ -23,6 +26,9 @@ pub type TraitPredicate<'tcx> = IrTraitPredicate>; pub type ClauseKind<'tcx> = IrClauseKind>; pub type PredicateKind<'tcx> = IrPredicateKind>; +pub type NormalizesTo<'tcx> = IrNormalizesTo>; +pub type CoercePredicate<'tcx> = IrCoercePredicate>; +pub type SubtypePredicate<'tcx> = IrSubtypePredicate>; /// 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, @@ -511,25 +517,8 @@ pub fn polarity(self) -> PredicatePolarity { 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>>; pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; @@ -568,33 +557,6 @@ pub fn projection_def_id(&self) -> DefId { } } -/// 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>; } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 9e5edb97fe2..6137a5fd48a 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3105,6 +3105,24 @@ macro_rules! define_print_and_forward_display { cx.reset_type_limit(); p!(print(self.term)) } + + ty::SubtypePredicate<'tcx> { + p!(print(self.a), " <: "); + cx.reset_type_limit(); + p!(print(self.b)) + } + + ty::CoercePredicate<'tcx> { + p!(print(self.a), " -> "); + cx.reset_type_limit(); + p!(print(self.b)) + } + + ty::NormalizesTo<'tcx> { + p!(print(self.alias), " normalizes-to "); + cx.reset_type_limit(); + p!(print(self.term)) + } } define_print_and_forward_display! { @@ -3180,24 +3198,6 @@ macro_rules! define_print_and_forward_display { p!(write("{}", self.name)) } - ty::SubtypePredicate<'tcx> { - p!(print(self.a), " <: "); - cx.reset_type_limit(); - p!(print(self.b)) - } - - ty::CoercePredicate<'tcx> { - p!(print(self.a), " -> "); - cx.reset_type_limit(); - p!(print(self.b)) - } - - ty::NormalizesTo<'tcx> { - p!(print(self.alias), " normalizes-to "); - cx.reset_type_limit(); - p!(print(self.term)) - } - ty::Term<'tcx> { match self.unpack() { ty::TermKind::Ty(ty) => p!(print(ty)), diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index b08ae4e5890..dc071b295aa 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -152,12 +152,6 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } -impl<'tcx> fmt::Debug for ty::NormalizesTo<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term) - } -} - impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?}", self.kind()) diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index cf67f82efd7..a50967a3b18 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -90,7 +90,7 @@ pub trait BoundVars { fn has_no_bound_vars(&self) -> bool; } -// TODO: Uplift `AliasTy` +// FIXME: Uplift `AliasTy` pub trait AliasTy: Copy + DebugWithInfcx + Hash + Eq + Sized { fn new( interner: I, @@ -107,5 +107,4 @@ fn new( 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 bfa769237a1..17d9f4242fd 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -6,8 +6,8 @@ use crate::ir_print::IrPrint; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{ - CanonicalVarInfo, DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, - ProjectionPredicate, TraitPredicate, TraitRef, + CanonicalVarInfo, CoercePredicate, DebugWithInfcx, ExistentialProjection, ExistentialTraitRef, + NormalizesTo, ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, }; pub trait Interner: @@ -18,6 +18,9 @@ pub trait Interner: + IrPrint> + IrPrint> + IrPrint> + + IrPrint> + + IrPrint> + + IrPrint> { type DefId: Copy + Debug + Hash + Eq; type DefiningOpaqueTypes: Copy + Debug + Hash + Default + Eq + TypeVisitable; diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs index 9b72764b4d1..5885139754a 100644 --- a/compiler/rustc_type_ir/src/ir_print.rs +++ b/compiler/rustc_type_ir/src/ir_print.rs @@ -1,8 +1,8 @@ use std::fmt; use crate::{ - ExistentialProjection, ExistentialTraitRef, Interner, ProjectionPredicate, TraitPredicate, - TraitRef, + CoercePredicate, ExistentialProjection, ExistentialTraitRef, Interner, NormalizesTo, + ProjectionPredicate, SubtypePredicate, TraitPredicate, TraitRef, }; pub trait IrPrint { @@ -39,7 +39,10 @@ fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { TraitPredicate, ExistentialTraitRef, ExistentialProjection, - ProjectionPredicate + ProjectionPredicate, + NormalizesTo, + SubtypePredicate, + CoercePredicate, ); 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 184b882c2b7..04cacd987d0 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -37,9 +37,9 @@ mod flags; mod infcx; mod interner; +mod predicate; mod predicate_kind; mod region_kind; -mod predicate; pub use canonical::*; #[cfg(feature = "nightly")] @@ -49,9 +49,9 @@ pub use flags::*; pub use infcx::InferCtxtLike; pub use interner::*; +pub use predicate::*; pub use predicate_kind::*; pub use region_kind::*; -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 index 9cd9319a1b1..b16227ee10f 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -187,7 +187,11 @@ pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef { // 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())) + TraitRef::new( + interner, + self.def_id, + [self_ty.into()].into_iter().chain(self.args.into_iter()), + ) } } @@ -296,3 +300,81 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_ty, self.term) } } + +/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be +/// proven by actually normalizing `alias`. +#[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 NormalizesTo { + pub alias: I::AliasTy, + pub term: I::Term, +} + +impl NormalizesTo { + pub fn self_ty(self) -> I::Ty { + self.alias.self_ty() + } + + pub fn with_self_ty(self, tcx: I, self_ty: I::Ty) -> NormalizesTo { + Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self } + } + + pub fn trait_def_id(self, tcx: I) -> I::DefId { + self.alias.trait_def_id(tcx) + } + + pub fn def_id(self) -> I::DefId { + self.alias.def_id() + } +} + +impl fmt::Debug for NormalizesTo { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term) + } +} + +/// 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(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub struct SubtypePredicate { + pub a_is_expected: bool, + pub a: I::Ty, + pub b: I::Ty, +} + +/// Encodes that we have to coerce *from* the `a` type to the `b` type. +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub struct CoercePredicate { + pub a: I::Ty, + pub b: I::Ty, +} From 905f5658246ae2f108dee3620ace203c0d5286e1 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 11 May 2024 18:14:44 -0400 Subject: [PATCH 5/6] Apply nits, uplift ExistentialPredicate too --- .../src/hir_ty_lowering/object_safety.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 1 + compiler/rustc_middle/src/ty/mod.rs | 14 ++-- compiler/rustc_middle/src/ty/predicate.rs | 80 +++++++------------ compiler/rustc_middle/src/ty/print/pretty.rs | 20 ++--- compiler/rustc_middle/src/ty/relate.rs | 27 ++++--- .../cfi/typeid/itanium_cxx_abi/transform.rs | 3 +- .../src/traits/object_safety.rs | 3 +- compiler/rustc_type_ir/src/predicate.rs | 32 +++++++- 9 files changed, 100 insertions(+), 82 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs index 297cfe7027e..37d4d4ec355 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/object_safety.rs @@ -7,7 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_lint_defs::builtin::UNUSED_ASSOCIATED_TYPE_BOUNDS; use rustc_middle::ty::fold::BottomUpFolder; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeFoldable}; use rustc_middle::ty::{DynKind, ToPredicate}; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits::error_reporting::report_object_safety_error; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 70fb937cae7..f9d1a77c3d9 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -26,6 +26,7 @@ use crate::traits::solve::{ ExternalConstraints, ExternalConstraintsData, PredefinedOpaques, PredefinedOpaquesData, }; +use crate::ty::predicate::ExistentialPredicateStableCmpExt as _; use crate::ty::{ self, AdtDef, AdtDefData, AdtKind, Binder, Clause, Clauses, Const, ConstData, GenericParamDefKind, ImplPolarity, List, ListWithCachedTypeInfo, ParamConst, ParamTy, Pattern, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 28baa334840..2b0d8796968 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -96,13 +96,13 @@ pub use self::parameterized::ParameterizedOverTcx; pub use self::pattern::{Pattern, PatternKind}; 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, + Clause, ClauseKind, CoercePredicate, ExistentialPredicate, ExistentialPredicateStableCmpExt, + 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, diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index dbbb86cb28e..c1de23b2498 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -1,34 +1,28 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::intern::Interned; 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::CoercePredicate as IrCoercePredicate; -use rustc_type_ir::ExistentialProjection as IrExistentialProjection; -use rustc_type_ir::ExistentialTraitRef as IrExistentialTraitRef; -use rustc_type_ir::NormalizesTo as IrNormalizesTo; -use rustc_type_ir::PredicateKind as IrPredicateKind; -use rustc_type_ir::ProjectionPredicate as IrProjectionPredicate; -use rustc_type_ir::SubtypePredicate as IrSubtypePredicate; -use rustc_type_ir::TraitPredicate as IrTraitPredicate; -use rustc_type_ir::TraitRef as IrTraitRef; +use rustc_macros::{ + extension, HashStable, Lift, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, +}; +use rustc_type_ir as ir; use std::cmp::Ordering; use crate::ty::{ - self, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, PredicatePolarity, Term, Ty, TyCtxt, - TypeFlags, WithCachedTypeInfo, + self, Binder, DebruijnIndex, EarlyBinder, PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, + WithCachedTypeInfo, }; -pub type TraitRef<'tcx> = IrTraitRef>; -pub type ProjectionPredicate<'tcx> = IrProjectionPredicate>; -pub type ExistentialTraitRef<'tcx> = IrExistentialTraitRef>; -pub type ExistentialProjection<'tcx> = IrExistentialProjection>; -pub type TraitPredicate<'tcx> = IrTraitPredicate>; -pub type ClauseKind<'tcx> = IrClauseKind>; -pub type PredicateKind<'tcx> = IrPredicateKind>; -pub type NormalizesTo<'tcx> = IrNormalizesTo>; -pub type CoercePredicate<'tcx> = IrCoercePredicate>; -pub type SubtypePredicate<'tcx> = IrSubtypePredicate>; +pub type TraitRef<'tcx> = ir::TraitRef>; +pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate>; +pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate>; +pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef>; +pub type ExistentialProjection<'tcx> = ir::ExistentialProjection>; +pub type TraitPredicate<'tcx> = ir::TraitPredicate>; +pub type ClauseKind<'tcx> = ir::ClauseKind>; +pub type PredicateKind<'tcx> = ir::PredicateKind>; +pub type NormalizesTo<'tcx> = ir::NormalizesTo>; +pub type CoercePredicate<'tcx> = ir::CoercePredicate>; +pub type SubtypePredicate<'tcx> = ir::SubtypePredicate>; /// 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, @@ -207,43 +201,25 @@ pub fn as_region_outlives_clause( } } -#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub enum ExistentialPredicate<'tcx> { - /// E.g., `Iterator`. - Trait(ExistentialTraitRef<'tcx>), - /// E.g., `Iterator::Item = T`. - Projection(ExistentialProjection<'tcx>), - /// E.g., `Send`. - AutoTrait(DefId), -} - -impl<'tcx> DebugWithInfcx> for ExistentialPredicate<'tcx> { - fn fmt>>( - this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>, - f: &mut std::fmt::Formatter<'_>, - ) -> std::fmt::Result { - std::fmt::Debug::fmt(&this.data, f) - } -} - +#[extension(pub trait ExistentialPredicateStableCmpExt<'tcx>)] impl<'tcx> ExistentialPredicate<'tcx> { /// Compares via an ordering that will not change if modules are reordered or other changes are /// made to the tree. In particular, this ordering is preserved across incremental compilations. - pub fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering { - use self::ExistentialPredicate::*; + fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering { match (*self, *other) { - (Trait(_), Trait(_)) => Ordering::Equal, - (Projection(ref a), Projection(ref b)) => { + (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal, + (ExistentialPredicate::Projection(ref a), ExistentialPredicate::Projection(ref b)) => { tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id)) } - (AutoTrait(ref a), AutoTrait(ref b)) => { + (ExistentialPredicate::AutoTrait(ref a), ExistentialPredicate::AutoTrait(ref b)) => { tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b)) } - (Trait(_), _) => Ordering::Less, - (Projection(_), Trait(_)) => Ordering::Greater, - (Projection(_), _) => Ordering::Less, - (AutoTrait(_), _) => Ordering::Greater, + (ExistentialPredicate::Trait(_), _) => Ordering::Less, + (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => { + Ordering::Greater + } + (ExistentialPredicate::Projection(_), _) => Ordering::Less, + (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater, } } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 6137a5fd48a..be9525a083c 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3088,6 +3088,16 @@ macro_rules! define_print_and_forward_display { } } + ty::ExistentialPredicate<'tcx> { + match *self { + ty::ExistentialPredicate::Trait(x) => p!(print(x)), + ty::ExistentialPredicate::Projection(x) => p!(print(x)), + ty::ExistentialPredicate::AutoTrait(def_id) => { + p!(print_def_path(def_id, &[])); + } + } + } + ty::ExistentialTraitRef<'tcx> { // Use a type that can't appear in defaults of type parameters. let dummy_self = Ty::new_fresh(cx.tcx(), 0); @@ -3132,16 +3142,6 @@ macro_rules! define_print_and_forward_display { p!("{{", comma_sep(self.iter()), "}}") } - ty::ExistentialPredicate<'tcx> { - match *self { - ty::ExistentialPredicate::Trait(x) => p!(print(x)), - ty::ExistentialPredicate::Projection(x) => p!(print(x)), - ty::ExistentialPredicate::AutoTrait(def_id) => { - p!(print_def_path(def_id, &[])); - } - } - } - ty::FnSig<'tcx> { p!(write("{}", self.unsafety.prefix_str())); diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 7063ef07201..417edda10ca 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -5,8 +5,10 @@ //! subtyping, type equality, etc. use crate::ty::error::{ExpectedFound, TypeError}; -use crate::ty::{self, Expr, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable}; -use crate::ty::{GenericArg, GenericArgKind, GenericArgsRef}; +use crate::ty::{ + self, ExistentialPredicate, ExistentialPredicateStableCmpExt as _, Expr, GenericArg, + GenericArgKind, GenericArgsRef, ImplSubject, Term, TermKind, Ty, TyCtxt, TypeFoldable, +}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; @@ -702,14 +704,21 @@ fn relate>( } let v = iter::zip(a_v, b_v).map(|(ep_a, ep_b)| { - use crate::ty::ExistentialPredicate::*; match (ep_a.skip_binder(), ep_b.skip_binder()) { - (Trait(a), Trait(b)) => Ok(ep_a - .rebind(Trait(relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder()))), - (Projection(a), Projection(b)) => Ok(ep_a.rebind(Projection( - relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), - ))), - (AutoTrait(a), AutoTrait(b)) if a == b => Ok(ep_a.rebind(AutoTrait(a))), + (ExistentialPredicate::Trait(a), ExistentialPredicate::Trait(b)) => Ok(ep_a + .rebind(ExistentialPredicate::Trait( + relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), + ))), + (ExistentialPredicate::Projection(a), ExistentialPredicate::Projection(b)) => { + Ok(ep_a.rebind(ExistentialPredicate::Projection( + relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(), + ))) + } + (ExistentialPredicate::AutoTrait(a), ExistentialPredicate::AutoTrait(b)) + if a == b => + { + Ok(ep_a.rebind(ExistentialPredicate::AutoTrait(a))) + } _ => Err(TypeError::ExistentialMismatch(expected_found(a, b))), } }); diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 7141c6c9bb0..21433cfdb61 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -8,7 +8,8 @@ use rustc_middle::bug; use rustc_middle::ty::fold::{TypeFolder, TypeSuperFoldable}; use rustc_middle::ty::{ - self, Instance, IntTy, List, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, UintTy, + self, ExistentialPredicateStableCmpExt as _, Instance, IntTy, List, Ty, TyCtxt, TypeFoldable, + TypeVisitableExt, UintTy, }; use rustc_span::sym; use rustc_trait_selection::traits; diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 5cb61dff831..75e43bc8f5d 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -18,7 +18,8 @@ use rustc_hir::def_id::DefId; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, EarlyBinder, ExistentialPredicateStableCmpExt as _, Ty, TyCtxt, TypeSuperVisitable, + TypeVisitable, TypeVisitor, }; use rustc_middle::ty::{GenericArg, GenericArgs}; use rustc_middle::ty::{ToPredicate, TypeVisitableExt}; diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index b16227ee10f..b2510cb01df 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -5,7 +5,7 @@ use crate::inherent::*; use crate::visit::TypeVisitableExt as _; -use crate::Interner; +use crate::{DebugWithInfcx, Interner}; /// A complete reference to a trait. These take numerous guises in syntax, /// but perhaps the most recognizable form is in a where-clause: @@ -146,6 +146,36 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } +#[derive(derivative::Derivative)] +#[derivative( + Clone(bound = ""), + Copy(bound = ""), + Hash(bound = ""), + PartialEq(bound = ""), + Eq(bound = ""), + Debug(bound = "") +)] +#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub enum ExistentialPredicate { + /// E.g., `Iterator`. + Trait(ExistentialTraitRef), + /// E.g., `Iterator::Item = T`. + Projection(ExistentialProjection), + /// E.g., `Send`. + AutoTrait(I::DefId), +} + +// FIXME: Implement this the right way after +impl DebugWithInfcx for ExistentialPredicate { + fn fmt>( + this: rustc_type_ir::WithInfcx<'_, Infcx, &Self>, + f: &mut fmt::Formatter<'_>, + ) -> fmt::Result { + fmt::Debug::fmt(&this.data, f) + } +} + /// An existential reference to a trait, where `Self` is erased. /// For example, the trait object `Trait<'a, 'b, X, Y>` is: /// ```ignore (illustrative) From d13e5c483dcdfed9724d03dbb2c28827fda4c365 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 11 May 2024 19:28:58 -0400 Subject: [PATCH 6/6] And `ImplPolarity` too --- compiler/rustc_middle/src/ty/mod.rs | 24 ------------------------ compiler/rustc_type_ir/src/predicate.rs | 24 ++++++++++++++++++++++++ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2b0d8796968..4d3b92bf2af 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -275,30 +275,6 @@ pub enum ImplSubject<'tcx> { Inherent(Ty<'tcx>), } -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] -#[derive(TypeFoldable, TypeVisitable)] -pub enum ImplPolarity { - /// `impl Trait for Type` - Positive, - /// `impl !Trait for Type` - Negative, - /// `#[rustc_reservation_impl] impl Trait for Type` - /// - /// This is a "stability hack", not a real Rust feature. - /// See #64631 for details. - Reservation, -} - -impl fmt::Display for ImplPolarity { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - match self { - Self::Positive => f.write_str("positive"), - Self::Negative => f.write_str("negative"), - Self::Reservation => f.write_str("reservation"), - } - } -} - #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] #[derive(TypeFoldable, TypeVisitable)] pub enum Asyncness { diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index b2510cb01df..f84f8f47c67 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -115,6 +115,30 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { } } +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))] +pub enum ImplPolarity { + /// `impl Trait for Type` + Positive, + /// `impl !Trait for Type` + Negative, + /// `#[rustc_reservation_impl] impl Trait for Type` + /// + /// This is a "stability hack", not a real Rust feature. + /// See #64631 for details. + Reservation, +} + +impl fmt::Display for ImplPolarity { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::Positive => f.write_str("positive"), + Self::Negative => f.write_str("negative"), + Self::Reservation => f.write_str("reservation"), + } + } +} + /// Polarity for a trait predicate. May either be negative or positive. /// Distinguished from [`ImplPolarity`] since we never compute goals with /// "reservation" level.