diff options
Diffstat (limited to 'compiler/rustc_middle')
| -rw-r--r-- | compiler/rustc_middle/src/mir/interpret/error.rs | 121 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/mir/interpret/mod.rs | 121 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/traits/mod.rs | 25 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/context.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/flags.rs | 10 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/mod.rs | 86 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/predicate.rs | 284 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/print/pretty.rs | 134 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/relate.rs | 66 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/structural_impls.rs | 27 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/sty.rs | 260 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/typeck_results.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_middle/src/ty/util.rs | 2 |
13 files changed, 578 insertions, 593 deletions
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index 383241465c3..6e152cbcb65 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -188,8 +188,9 @@ impl<'tcx> From<InterpError<'tcx>> for InterpErrorInfo<'tcx> { } /// Error information for when the program we executed turned out not to actually be a valid -/// program. This cannot happen in stand-alone Miri, but it can happen during CTFE/ConstProp -/// where we work on generic code or execution does not have all information available. +/// program. This cannot happen in stand-alone Miri (except for layout errors that are only detect +/// during monomorphization), but it can happen during CTFE/ConstProp where we work on generic code +/// or execution does not have all information available. #[derive(Debug)] pub enum InvalidProgramInfo<'tcx> { /// Resolution can fail if we are in a too generic context. @@ -507,7 +508,7 @@ pub enum ValidationErrorKind<'tcx> { /// Miri engine, e.g., CTFE does not support dereferencing pointers at integral addresses. #[derive(Debug)] pub enum UnsupportedOpInfo { - /// Free-form case. Only for errors that are never caught! + /// Free-form case. Only for errors that are never caught! Used by Miri. // FIXME still use translatable diagnostics Unsupported(String), /// Unsized local variables. @@ -592,3 +593,117 @@ impl InterpError<'_> { ) } } + +// Macros for constructing / throwing `InterpError` +#[macro_export] +macro_rules! err_unsup { + ($($tt:tt)*) => { + $crate::mir::interpret::InterpError::Unsupported( + $crate::mir::interpret::UnsupportedOpInfo::$($tt)* + ) + }; +} + +#[macro_export] +macro_rules! err_unsup_format { + ($($tt:tt)*) => { $crate::err_unsup!(Unsupported(format!($($tt)*))) }; +} + +#[macro_export] +macro_rules! err_inval { + ($($tt:tt)*) => { + $crate::mir::interpret::InterpError::InvalidProgram( + $crate::mir::interpret::InvalidProgramInfo::$($tt)* + ) + }; +} + +#[macro_export] +macro_rules! err_ub { + ($($tt:tt)*) => { + $crate::mir::interpret::InterpError::UndefinedBehavior( + $crate::mir::interpret::UndefinedBehaviorInfo::$($tt)* + ) + }; +} + +#[macro_export] +macro_rules! err_ub_format { + ($($tt:tt)*) => { $crate::err_ub!(Ub(format!($($tt)*))) }; +} + +#[macro_export] +macro_rules! err_ub_custom { + ($msg:expr $(, $($name:ident = $value:expr),* $(,)?)?) => {{ + $( + let ($($name,)*) = ($($value,)*); + )? + $crate::err_ub!(Custom( + $crate::error::CustomSubdiagnostic { + msg: || $msg, + add_args: Box::new(move |mut set_arg| { + $($( + set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name)); + )*)? + }) + } + )) + }}; +} + +#[macro_export] +macro_rules! err_exhaust { + ($($tt:tt)*) => { + $crate::mir::interpret::InterpError::ResourceExhaustion( + $crate::mir::interpret::ResourceExhaustionInfo::$($tt)* + ) + }; +} + +#[macro_export] +macro_rules! err_machine_stop { + ($($tt:tt)*) => { + $crate::mir::interpret::InterpError::MachineStop(Box::new($($tt)*)) + }; +} + +// In the `throw_*` macros, avoid `return` to make them work with `try {}`. +#[macro_export] +macro_rules! throw_unsup { + ($($tt:tt)*) => { do yeet $crate::err_unsup!($($tt)*) }; +} + +#[macro_export] +macro_rules! throw_unsup_format { + ($($tt:tt)*) => { do yeet $crate::err_unsup_format!($($tt)*) }; +} + +#[macro_export] +macro_rules! throw_inval { + ($($tt:tt)*) => { do yeet $crate::err_inval!($($tt)*) }; +} + +#[macro_export] +macro_rules! throw_ub { + ($($tt:tt)*) => { do yeet $crate::err_ub!($($tt)*) }; +} + +#[macro_export] +macro_rules! throw_ub_format { + ($($tt:tt)*) => { do yeet $crate::err_ub_format!($($tt)*) }; +} + +#[macro_export] +macro_rules! throw_ub_custom { + ($($tt:tt)*) => { do yeet $crate::err_ub_custom!($($tt)*) }; +} + +#[macro_export] +macro_rules! throw_exhaust { + ($($tt:tt)*) => { do yeet $crate::err_exhaust!($($tt)*) }; +} + +#[macro_export] +macro_rules! throw_machine_stop { + ($($tt:tt)*) => { do yeet $crate::err_machine_stop!($($tt)*) }; +} diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs index 38cb1d5f9a0..739b1410e6d 100644 --- a/compiler/rustc_middle/src/mir/interpret/mod.rs +++ b/compiler/rustc_middle/src/mir/interpret/mod.rs @@ -1,120 +1,9 @@ //! An interpreter for MIR used in CTFE and by miri. -#[macro_export] -macro_rules! err_unsup { - ($($tt:tt)*) => { - $crate::mir::interpret::InterpError::Unsupported( - $crate::mir::interpret::UnsupportedOpInfo::$($tt)* - ) - }; -} - -#[macro_export] -macro_rules! err_unsup_format { - ($($tt:tt)*) => { err_unsup!(Unsupported(format!($($tt)*))) }; -} - -#[macro_export] -macro_rules! err_inval { - ($($tt:tt)*) => { - $crate::mir::interpret::InterpError::InvalidProgram( - $crate::mir::interpret::InvalidProgramInfo::$($tt)* - ) - }; -} - -#[macro_export] -macro_rules! err_ub { - ($($tt:tt)*) => { - $crate::mir::interpret::InterpError::UndefinedBehavior( - $crate::mir::interpret::UndefinedBehaviorInfo::$($tt)* - ) - }; -} - -#[macro_export] -macro_rules! err_ub_format { - ($($tt:tt)*) => { err_ub!(Ub(format!($($tt)*))) }; -} - -#[macro_export] -macro_rules! err_exhaust { - ($($tt:tt)*) => { - $crate::mir::interpret::InterpError::ResourceExhaustion( - $crate::mir::interpret::ResourceExhaustionInfo::$($tt)* - ) - }; -} - -#[macro_export] -macro_rules! err_machine_stop { - ($($tt:tt)*) => { - $crate::mir::interpret::InterpError::MachineStop(Box::new($($tt)*)) - }; -} - -// In the `throw_*` macros, avoid `return` to make them work with `try {}`. -#[macro_export] -macro_rules! throw_unsup { - ($($tt:tt)*) => { do yeet err_unsup!($($tt)*) }; -} - -#[macro_export] -macro_rules! throw_unsup_format { - ($($tt:tt)*) => { throw_unsup!(Unsupported(format!($($tt)*))) }; -} - -#[macro_export] -macro_rules! throw_inval { - ($($tt:tt)*) => { do yeet err_inval!($($tt)*) }; -} - -#[macro_export] -macro_rules! throw_ub { - ($($tt:tt)*) => { do yeet err_ub!($($tt)*) }; -} - -#[macro_export] -macro_rules! throw_ub_format { - ($($tt:tt)*) => { throw_ub!(Ub(format!($($tt)*))) }; -} - -#[macro_export] -macro_rules! throw_exhaust { - ($($tt:tt)*) => { do yeet err_exhaust!($($tt)*) }; -} - -#[macro_export] -macro_rules! throw_machine_stop { - ($($tt:tt)*) => { do yeet err_machine_stop!($($tt)*) }; -} - -#[macro_export] -macro_rules! err_ub_custom { - ($msg:expr $(, $($name:ident = $value:expr),* $(,)?)?) => {{ - $( - let ($($name,)*) = ($($value,)*); - )? - err_ub!(Custom( - rustc_middle::error::CustomSubdiagnostic { - msg: || $msg, - add_args: Box::new(move |mut set_arg| { - $($( - set_arg(stringify!($name).into(), rustc_errors::IntoDiagArg::into_diag_arg($name)); - )*)? - }) - } - )) - }}; -} - -#[macro_export] -macro_rules! throw_ub_custom { - ($($tt:tt)*) => { do yeet err_ub_custom!($($tt)*) }; -} +#[macro_use] +mod error; mod allocation; -mod error; mod pointer; mod queries; mod value; @@ -150,6 +39,12 @@ pub use self::error::{ ScalarSizeMismatch, UndefinedBehaviorInfo, UnsupportedOpInfo, ValidationErrorInfo, ValidationErrorKind, }; +// Also make the error macros available from this module. +pub use { + err_exhaust, err_inval, err_machine_stop, err_ub, err_ub_custom, err_ub_format, err_unsup, + err_unsup_format, throw_exhaust, throw_inval, throw_machine_stop, throw_ub, throw_ub_custom, + throw_ub_format, throw_unsup, throw_unsup_format, +}; pub use self::value::Scalar; diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 6c33a29ea81..fb796bf87a1 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -247,22 +247,15 @@ pub enum ObligationCauseCode<'tcx> { /// A tuple is WF only if its middle elements are `Sized`. TupleElem, - /// Must satisfy all of the where-clause predicates of the - /// given item. - WhereClause(DefId), - - /// Like `WhereClause`, but carries the span of the - /// predicate when it can be identified. - SpannedWhereClause(DefId, Span), - - /// Like `WhereClause`, but carries the `HirId` of the - /// expression that caused the obligation, and the `usize` - /// indicates exactly which predicate it is in the list of - /// instantiated predicates. - WhereClauseInExpr(DefId, HirId, usize), - - /// Combines `SpannedWhereClause` and `WhereClauseInExpr`. - SpannedWhereClauseInExpr(DefId, Span, HirId, usize), + /// Represents a clause that comes from a specific item. + /// The span corresponds to the clause. + WhereClause(DefId, Span), + + /// Like `WhereClause`, but also identifies the expression + /// which requires the `where` clause to be proven, and also + /// identifies the index of the predicate in the `predicates_of` + /// list of the item. + WhereClauseInExpr(DefId, Span, HirId, usize), /// A type like `&'a T` is WF only if `T: 'a`. ReferenceOutlivesReferent(Ty<'tcx>), diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 0464be2df06..e831db1a41b 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; 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, @@ -99,17 +100,17 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type CanonicalVars = CanonicalVarInfos<'tcx>; type Ty = Ty<'tcx>; - type Pat = Pattern<'tcx>; type Tys = &'tcx List<Ty<'tcx>>; type AliasTy = ty::AliasTy<'tcx>; type ParamTy = ParamTy; type BoundTy = ty::BoundTy; type PlaceholderTy = ty::PlaceholderType; - type ErrorGuaranteed = ErrorGuaranteed; + type BoundExistentialPredicates = &'tcx List<PolyExistentialPredicate<'tcx>>; type PolyFnSig = PolyFnSig<'tcx>; type AllocId = crate::mir::interpret::AllocId; + type Pat = Pattern<'tcx>; type Const = ty::Const<'tcx>; type AliasConst = ty::UnevaluatedConst<'tcx>; @@ -121,8 +122,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; @@ -131,6 +132,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type RegionOutlivesPredicate = ty::RegionOutlivesPredicate<'tcx>; type TypeOutlivesPredicate = ty::TypeOutlivesPredicate<'tcx>; type ProjectionPredicate = ty::ProjectionPredicate<'tcx>; + type AliasTerm = ty::AliasTerm<'tcx>; type NormalizesTo = ty::NormalizesTo<'tcx>; type SubtypePredicate = ty::SubtypePredicate<'tcx>; type CoercePredicate = ty::CoercePredicate<'tcx>; @@ -146,6 +148,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.generics_of(def_id) } + fn mk_args(self, args: &[Self::GenericArg]) -> Self::GenericArgs { + self.mk_args(args) + } + fn check_and_mk_args( self, def_id: DefId, @@ -153,6 +159,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ) -> ty::GenericArgsRef<'tcx> { self.check_and_mk_args(def_id, args) } + + fn parent(self, def_id: Self::DefId) -> Self::DefId { + self.parent(def_id) + } } type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>; diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 0dc835671d5..4de7d532c96 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -294,10 +294,10 @@ impl FlagComputation { self.add_ty(b); } ty::PredicateKind::Clause(ty::ClauseKind::Projection(ty::ProjectionPredicate { - projection_ty, + projection_term, term, })) => { - self.add_alias_ty(projection_ty); + self.add_alias_term(projection_term); self.add_term(term); } ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => { @@ -313,7 +313,7 @@ impl FlagComputation { } ty::PredicateKind::Ambiguous => {} ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term }) => { - self.add_alias_ty(alias); + self.add_alias_term(alias); self.add_term(term); } ty::PredicateKind::AliasRelate(t1, t2, _) => { @@ -410,6 +410,10 @@ impl FlagComputation { self.add_args(alias_ty.args); } + fn add_alias_term(&mut self, alias_term: ty::AliasTerm<'_>) { + self.add_args(alias_term.args); + } + fn add_args(&mut self, args: &[GenericArg<'_>]) { for kind in args { match kind.unpack() { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 12cefc23233..dc5e881843a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -96,13 +96,13 @@ pub use self::list::{List, ListWithCachedTypeInfo}; 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, @@ -110,11 +110,11 @@ pub use self::region::{ }; pub use self::rvalue_scopes::RvalueScopes; pub use self::sty::{ - AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, CanonicalPolyFnSig, - ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, CoroutineClosureArgs, - CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, InlineConstArgs, - InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, UpvarArgs, - VarianceDiagInfo, + AliasTerm, AliasTy, Article, Binder, BoundTy, BoundTyKind, BoundVariableKind, + CanonicalPolyFnSig, ClosureArgs, ClosureArgsParts, CoroutineArgs, CoroutineArgsParts, + CoroutineClosureArgs, CoroutineClosureArgsParts, CoroutineClosureSignature, FnSig, GenSig, + InlineConstArgs, InlineConstArgsParts, ParamConst, ParamTy, PolyFnSig, TyKind, TypeAndMut, + UpvarArgs, VarianceDiagInfo, }; pub use self::trait_def::TraitDef; pub use self::typeck_results::{ @@ -277,61 +277,6 @@ pub enum ImplSubject<'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"), - } - } -} - -/// 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 { Yes, No, @@ -684,15 +629,14 @@ impl<'tcx> Term<'tcx> { } } - /// This function returns the inner `AliasTy` for a `ty::Alias` or `ConstKind::Unevaluated`. - pub fn to_alias_ty(&self, tcx: TyCtxt<'tcx>) -> Option<AliasTy<'tcx>> { + pub fn to_alias_term(self) -> Option<AliasTerm<'tcx>> { match self.unpack() { TermKind::Ty(ty) => match *ty.kind() { - ty::Alias(_kind, alias_ty) => Some(alias_ty), + ty::Alias(_kind, alias_ty) => Some(alias_ty.into()), _ => None, }, TermKind::Const(ct) => match ct.kind() { - ConstKind::Unevaluated(uv) => Some(AliasTy::new(tcx, uv.def, uv.args)), + ConstKind::Unevaluated(uv) => Some(uv.into()), _ => None, }, } diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 5387036d409..e78856517b2 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -1,22 +1,28 @@ 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::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::visit::TypeVisitableExt; use crate::ty::{ - self, AliasTy, Binder, DebruijnIndex, DebugWithInfcx, EarlyBinder, GenericArgsRef, - PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, WithCachedTypeInfo, + self, Binder, DebruijnIndex, EarlyBinder, PredicatePolarity, Term, Ty, TyCtxt, TypeFlags, + WithCachedTypeInfo, }; -pub type TraitRef<'tcx> = IrTraitRef<TyCtxt<'tcx>>; -pub type ClauseKind<'tcx> = IrClauseKind<TyCtxt<'tcx>>; -pub type PredicateKind<'tcx> = IrPredicateKind<TyCtxt<'tcx>>; +pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>; +pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate<TyCtxt<'tcx>>; +pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate<TyCtxt<'tcx>>; +pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef<TyCtxt<'tcx>>; +pub type ExistentialProjection<'tcx> = ir::ExistentialProjection<TyCtxt<'tcx>>; +pub type TraitPredicate<'tcx> = ir::TraitPredicate<TyCtxt<'tcx>>; +pub type ClauseKind<'tcx> = ir::ClauseKind<TyCtxt<'tcx>>; +pub type PredicateKind<'tcx> = ir::PredicateKind<TyCtxt<'tcx>>; +pub type NormalizesTo<'tcx> = ir::NormalizesTo<TyCtxt<'tcx>>; +pub type CoercePredicate<'tcx> = ir::CoercePredicate<TyCtxt<'tcx>>; +pub type SubtypePredicate<'tcx> = ir::SubtypePredicate<TyCtxt<'tcx>>; /// 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, @@ -195,43 +201,25 @@ impl<'tcx> Clause<'tcx> { } } -#[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<TyCtxt<'tcx>> for ExistentialPredicate<'tcx> { - fn fmt<Infcx: rustc_type_ir::InferCtxtLike<Interner = TyCtxt<'tcx>>>( - 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, } } } @@ -340,52 +328,6 @@ impl<'tcx> PolyTraitRef<'tcx> { } } -/// An existential reference to a trait, where `Self` is erased. -/// For example, the trait object `Trait<'a, 'b, X, Y>` is: -/// ```ignore (illustrative) -/// exists T. T: Trait<'a, 'b, X, Y> -/// ``` -/// The generic parameters don't include the erased `Self`, only trait -/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above). -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct ExistentialTraitRef<'tcx> { - pub def_id: DefId, - pub args: GenericArgsRef<'tcx>, -} - -impl<'tcx> ExistentialTraitRef<'tcx> { - pub fn erase_self_ty( - tcx: TyCtxt<'tcx>, - trait_ref: ty::TraitRef<'tcx>, - ) -> ty::ExistentialTraitRef<'tcx> { - // Assert there is a Self. - trait_ref.args.type_at(0); - - ty::ExistentialTraitRef { - def_id: trait_ref.def_id, - args: tcx.mk_args(&trait_ref.args[1..]), - } - } - - /// Object types don't have a self type specified. Therefore, when - /// we convert the principal trait-ref into a normal trait-ref, - /// you must give *some* self type. A common choice is `mk_err()` - /// or some placeholder type. - pub fn with_self_ty(&self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ty::TraitRef<'tcx> { - // otherwise the escaping vars would be captured by the binder - // debug_assert!(!self_ty.has_escaping_bound_vars()); - - ty::TraitRef::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter())) - } -} - -impl<'tcx> IntoDiagArg for ExistentialTraitRef<'tcx> { - fn into_diag_arg(self) -> DiagArgValue { - self.to_string().into_diag_arg() - } -} - pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>; impl<'tcx> PolyExistentialTraitRef<'tcx> { @@ -402,62 +344,8 @@ impl<'tcx> PolyExistentialTraitRef<'tcx> { } } -/// A `ProjectionPredicate` for an `ExistentialTraitRef`. -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct ExistentialProjection<'tcx> { - pub def_id: DefId, - pub args: GenericArgsRef<'tcx>, - pub term: Term<'tcx>, -} - pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>; -impl<'tcx> ExistentialProjection<'tcx> { - /// Extracts the underlying existential trait reference from this projection. - /// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`, - /// then this function would return an `exists T. T: Iterator` existential trait - /// reference. - pub fn trait_ref(&self, tcx: TyCtxt<'tcx>) -> ty::ExistentialTraitRef<'tcx> { - let def_id = tcx.parent(self.def_id); - let args_count = tcx.generics_of(def_id).count() - 1; - let args = tcx.mk_args(&self.args[..args_count]); - ty::ExistentialTraitRef { def_id, args } - } - - pub fn with_self_ty( - &self, - tcx: TyCtxt<'tcx>, - self_ty: Ty<'tcx>, - ) -> ty::ProjectionPredicate<'tcx> { - // otherwise the escaping regions would be captured by the binders - debug_assert!(!self_ty.has_escaping_bound_vars()); - - ty::ProjectionPredicate { - projection_ty: AliasTy::new( - tcx, - self.def_id, - [self_ty.into()].into_iter().chain(self.args), - ), - term: self.term, - } - } - - pub fn erase_self_ty( - tcx: TyCtxt<'tcx>, - projection_predicate: ty::ProjectionPredicate<'tcx>, - ) -> Self { - // Assert there is a Self. - projection_predicate.projection_ty.args.type_at(0); - - Self { - def_id: projection_predicate.projection_ty.def_id, - args: tcx.mk_args(&projection_predicate.projection_ty.args[1..]), - term: projection_predicate.term, - } - } -} - impl<'tcx> PolyExistentialProjection<'tcx> { pub fn with_self_ty( &self, @@ -578,37 +466,8 @@ impl<'tcx> Clause<'tcx> { } } -#[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. @@ -634,71 +493,17 @@ pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<Ty<'tcx>, ty::Region<'t 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>>; -/// This kind of predicate has no *direct* correspondent in the -/// syntax, but it roughly corresponds to the syntactic forms: -/// -/// 1. `T: TraitRef<..., Item = Type>` -/// 2. `<T as TraitRef<...>>::Item == Type` (NYI) -/// -/// In particular, form #1 is "desugared" to the combination of a -/// normal trait predicate (`T: TraitRef<...>`) and one of these -/// predicates. Form #2 is a broader form in that it also permits -/// equality between arbitrary types. Processing an instance of -/// Form #2 eventually yields one of these `ProjectionPredicate` -/// instances to normalize the LHS. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct ProjectionPredicate<'tcx> { - pub projection_ty: AliasTy<'tcx>, - pub term: Term<'tcx>, -} - -impl<'tcx> ProjectionPredicate<'tcx> { - pub fn self_ty(self) -> Ty<'tcx> { - self.projection_ty.self_ty() - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> ProjectionPredicate<'tcx> { - Self { projection_ty: self.projection_ty.with_self_ty(tcx, self_ty), ..self } - } - - pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { - self.projection_ty.trait_def_id(tcx) - } - - pub fn def_id(self) -> DefId { - self.projection_ty.def_id - } -} - pub type PolyProjectionPredicate<'tcx> = Binder<'tcx, ProjectionPredicate<'tcx>>; impl<'tcx> PolyProjectionPredicate<'tcx> { /// Returns the `DefId` of the trait of the associated item being projected. #[inline] pub fn trait_def_id(&self, tcx: TyCtxt<'tcx>) -> DefId { - self.skip_binder().projection_ty.trait_def_id(tcx) + self.skip_binder().projection_term.trait_def_id(tcx) } /// Get the [PolyTraitRef] required for this projection to be well formed. @@ -711,7 +516,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { // This is because here `self` has a `Binder` and so does our // return value, so we are preserving the number of binding // levels. - self.map_bound(|predicate| predicate.projection_ty.trait_ref(tcx)) + self.map_bound(|predicate| predicate.projection_term.trait_ref(tcx)) } pub fn term(&self) -> Binder<'tcx, Term<'tcx>> { @@ -724,34 +529,7 @@ impl<'tcx> PolyProjectionPredicate<'tcx> { /// associated type, which is in `tcx.associated_item(projection_def_id()).container`. pub fn projection_def_id(&self) -> DefId { // Ok to skip binder since trait `DefId` does not care about regions. - self.skip_binder().projection_ty.def_id - } -} - -/// Used by the new solver. Unlike a `ProjectionPredicate` this can only be -/// proven by actually normalizing `alias`. -#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] -#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct NormalizesTo<'tcx> { - pub alias: AliasTy<'tcx>, - pub term: Term<'tcx>, -} - -impl<'tcx> NormalizesTo<'tcx> { - pub fn self_ty(self) -> Ty<'tcx> { - self.alias.self_ty() - } - - pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> NormalizesTo<'tcx> { - Self { alias: self.alias.with_self_ty(tcx, self_ty), ..self } - } - - pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { - self.alias.trait_def_id(tcx) - } - - pub fn def_id(self) -> DefId { - self.alias.def_id + self.skip_binder().projection_term.def_id } } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 14a628ab064..8d8ed70a757 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1277,7 +1277,7 @@ pub trait PrettyPrinter<'tcx>: Printer<'tcx> + fmt::Write { fn pretty_print_inherent_projection( &mut self, - alias_ty: ty::AliasTy<'tcx>, + alias_ty: ty::AliasTerm<'tcx>, ) -> Result<(), PrintError> { let def_key = self.tcx().def_key(alias_ty.def_id); self.path_generic_args( @@ -2953,8 +2953,9 @@ impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> { } } +#[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 @@ define_print! { 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)) } @@ -3077,13 +3087,15 @@ define_print! { ty::PredicateKind::AliasRelate(t1, t2, dir) => p!(print(t1), write(" {} ", dir), print(t2)), } } -} - -define_print_and_forward_display! { - (self, cx): - &'tcx ty::List<Ty<'tcx>> { - p!("{{", comma_sep(self.iter()), "}}") + ty::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> { @@ -3098,14 +3110,36 @@ define_print_and_forward_display! { p!(write("{} = ", name), print(self.term)) } - 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::ProjectionPredicate<'tcx> { + p!(print(self.projection_term), " == "); + 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! { + (self, cx): + + &'tcx ty::List<Ty<'tcx>> { + p!("{{", comma_sep(self.iter()), "}}") } ty::FnSig<'tcx> { @@ -3164,39 +3198,6 @@ 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::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(); - p!(print(self.term)) - } - - 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)), @@ -3205,20 +3206,29 @@ define_print_and_forward_display! { } ty::AliasTy<'tcx> { - if let DefKind::Impl { of_trait: false } = cx.tcx().def_kind(cx.tcx().parent(self.def_id)) { - p!(pretty_print_inherent_projection(*self)) - } else { - // If we're printing verbosely, or don't want to invoke queries - // (`is_impl_trait_in_trait`), then fall back to printing the def path. - // This is likely what you want if you're debugging the compiler anyways. - if !(cx.should_print_verbose() || with_reduced_queries()) - && cx.tcx().is_impl_trait_in_trait(self.def_id) - { - return cx.pretty_print_opaque_impl_type(self.def_id, self.args); - } else { - p!(print_def_path(self.def_id, self.args)); + let alias_term: ty::AliasTerm<'tcx> = (*self).into(); + p!(print(alias_term)) + } + + ty::AliasTerm<'tcx> { + match self.kind(cx.tcx()) { + ty::AliasTermKind::InherentTy => p!(pretty_print_inherent_projection(*self)), + ty::AliasTermKind::ProjectionTy + | ty::AliasTermKind::WeakTy + | ty::AliasTermKind::OpaqueTy + | ty::AliasTermKind::UnevaluatedConst + | ty::AliasTermKind::ProjectionConst => { + // If we're printing verbosely, or don't want to invoke queries + // (`is_impl_trait_in_trait`), then fall back to printing the def path. + // This is likely what you want if you're debugging the compiler anyways. + if !(cx.should_print_verbose() || with_reduced_queries()) + && cx.tcx().is_impl_trait_in_trait(self.def_id) + { + return cx.pretty_print_opaque_impl_type(self.def_id, self.args); + } else { + p!(print_def_path(self.def_id, self.args)); + } } - } } diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 7063ef07201..eaf5fdf5710 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -5,10 +5,11 @@ //! 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; use rustc_macros::TypeVisitable; use rustc_target::spec::abi; @@ -225,8 +226,8 @@ impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> { if a.def_id != b.def_id { Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id))) } else { - let args = match relation.tcx().def_kind(a.def_id) { - DefKind::OpaqueTy => relate_args_with_variances( + let args = match a.kind(relation.tcx()) { + ty::Opaque => relate_args_with_variances( relation, a.def_id, relation.tcx().variances_of(a.def_id), @@ -234,16 +235,46 @@ impl<'tcx> Relate<'tcx> for ty::AliasTy<'tcx> { b.args, false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle )?, - DefKind::AssocTy | DefKind::AssocConst | DefKind::TyAlias => { + ty::Projection | ty::Weak | ty::Inherent => { relate_args_invariantly(relation, a.args, b.args)? } - def => bug!("unknown alias DefKind: {def:?}"), }; Ok(ty::AliasTy::new(relation.tcx(), a.def_id, args)) } } } +impl<'tcx> Relate<'tcx> for ty::AliasTerm<'tcx> { + fn relate<R: TypeRelation<'tcx>>( + relation: &mut R, + a: ty::AliasTerm<'tcx>, + b: ty::AliasTerm<'tcx>, + ) -> RelateResult<'tcx, ty::AliasTerm<'tcx>> { + if a.def_id != b.def_id { + Err(TypeError::ProjectionMismatched(expected_found(a.def_id, b.def_id))) + } else { + let args = match a.kind(relation.tcx()) { + ty::AliasTermKind::OpaqueTy => relate_args_with_variances( + relation, + a.def_id, + relation.tcx().variances_of(a.def_id), + a.args, + b.args, + false, // do not fetch `type_of(a_def_id)`, as it will cause a cycle + )?, + ty::AliasTermKind::ProjectionTy + | ty::AliasTermKind::WeakTy + | ty::AliasTermKind::InherentTy + | ty::AliasTermKind::UnevaluatedConst + | ty::AliasTermKind::ProjectionConst => { + relate_args_invariantly(relation, a.args, b.args)? + } + }; + Ok(ty::AliasTerm::new(relation.tcx(), a.def_id, args)) + } + } +} + impl<'tcx> Relate<'tcx> for ty::ExistentialProjection<'tcx> { fn relate<R: TypeRelation<'tcx>>( relation: &mut R, @@ -702,14 +733,21 @@ impl<'tcx> Relate<'tcx> for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> { } 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_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a7770f71926..6abd685343b 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -55,12 +55,6 @@ impl fmt::Debug for ty::UpvarId { } } -impl<'tcx> fmt::Debug for ty::ExistentialTraitRef<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - with_no_trimmed_paths!(fmt::Display::fmt(self, f)) - } -} - impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{:?} -> {}", self.kind, self.target) @@ -158,25 +152,6 @@ impl fmt::Debug for ty::ParamConst { } } -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) - } -} - -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()) @@ -435,7 +410,7 @@ TrivialTypeTraversalImpls! { crate::ty::BoundRegionKind, crate::ty::AssocItem, crate::ty::AssocKind, - crate::ty::AliasKind, + crate::ty::AliasTyKind, crate::ty::Placeholder<crate::ty::BoundRegion>, crate::ty::Placeholder<crate::ty::BoundTy>, crate::ty::Placeholder<ty::BoundVar>, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index a97244dda9a..16301633247 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1105,14 +1105,14 @@ where } } -/// Represents the projection of an associated type. +/// Represents the unprojected term of a projection goal. /// /// * For a projection, this would be `<Ty as Trait<...>>::N<...>`. /// * For an inherent projection, this would be `Ty::N<...>`. /// * For an opaque type, there is no explicit syntax. #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] -pub struct AliasTy<'tcx> { +pub struct AliasTerm<'tcx> { /// The parameters of the associated or opaque item. /// /// For a projection, these are the generic parameters for the trait and the @@ -1137,7 +1137,232 @@ pub struct AliasTy<'tcx> { /// aka. `tcx.parent(def_id)`. pub def_id: DefId, - /// This field exists to prevent the creation of `AliasTy` without using + /// This field exists to prevent the creation of `AliasTerm` without using + /// [AliasTerm::new]. + _use_alias_term_new_instead: (), +} + +// FIXME: Remove these when we uplift `AliasTerm` +use crate::ty::{DebugWithInfcx, InferCtxtLike, WithInfcx}; +impl<'tcx> std::fmt::Debug for AliasTerm<'tcx> { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + WithInfcx::with_no_infcx(self).fmt(f) + } +} +impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTerm<'tcx> { + fn fmt<Infcx: InferCtxtLike<Interner = TyCtxt<'tcx>>>( + this: WithInfcx<'_, Infcx, &Self>, + f: &mut std::fmt::Formatter<'_>, + ) -> std::fmt::Result { + f.debug_struct("AliasTerm") + .field("args", &this.map(|data| data.args)) + .field("def_id", &this.data.def_id) + .finish() + } +} + +impl<'tcx> rustc_type_ir::inherent::AliasTerm<TyCtxt<'tcx>> for AliasTerm<'tcx> { + fn new( + interner: TyCtxt<'tcx>, + trait_def_id: DefId, + args: impl IntoIterator<Item: Into<ty::GenericArg<'tcx>>>, + ) -> Self { + AliasTerm::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> AliasTerm<'tcx> { + pub fn new( + tcx: TyCtxt<'tcx>, + def_id: DefId, + args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, + ) -> AliasTerm<'tcx> { + let args = tcx.check_and_mk_args(def_id, args); + AliasTerm { def_id, args, _use_alias_term_new_instead: () } + } + + pub fn expect_ty(self, tcx: TyCtxt<'tcx>) -> AliasTy<'tcx> { + match self.kind(tcx) { + ty::AliasTermKind::ProjectionTy + | ty::AliasTermKind::InherentTy + | ty::AliasTermKind::OpaqueTy + | ty::AliasTermKind::WeakTy => {} + ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => { + bug!("Cannot turn `UnevaluatedConst` into `AliasTy`") + } + } + ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () } + } + + pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTermKind { + match tcx.def_kind(self.def_id) { + DefKind::AssocTy => { + if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) { + ty::AliasTermKind::InherentTy + } else { + ty::AliasTermKind::ProjectionTy + } + } + DefKind::OpaqueTy => ty::AliasTermKind::OpaqueTy, + DefKind::TyAlias => ty::AliasTermKind::WeakTy, + DefKind::AnonConst => ty::AliasTermKind::UnevaluatedConst, + DefKind::AssocConst => ty::AliasTermKind::ProjectionConst, + kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), + } + } +} + +/// The following methods work only with (trait) associated item projections. +impl<'tcx> AliasTerm<'tcx> { + pub fn self_ty(self) -> Ty<'tcx> { + self.args.type_at(0) + } + + pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { + AliasTerm::new( + tcx, + self.def_id, + [self_ty.into()].into_iter().chain(self.args.iter().skip(1)), + ) + } + + pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { + match tcx.def_kind(self.def_id) { + DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id), + kind => bug!("expected a projection AliasTy; found {kind:?}"), + } + } + + /// Extracts the underlying trait reference from this projection. + /// For example, if this is a projection of `<T as Iterator>::Item`, + /// then this function would return a `T: Iterator` trait reference. + /// + /// NOTE: This will drop the args for generic associated types + /// consider calling [Self::trait_ref_and_own_args] to get those + /// as well. + pub fn trait_ref(self, tcx: TyCtxt<'tcx>) -> ty::TraitRef<'tcx> { + let def_id = self.trait_def_id(tcx); + ty::TraitRef::new(tcx, def_id, self.args.truncate_to(tcx, tcx.generics_of(def_id))) + } + + /// Extracts the underlying trait reference and own args from this projection. + /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`, + /// then this function would return a `T: StreamingIterator` trait reference and `['a]` as the own args + pub fn trait_ref_and_own_args( + self, + tcx: TyCtxt<'tcx>, + ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { + let trait_def_id = self.trait_def_id(tcx); + let trait_generics = tcx.generics_of(trait_def_id); + ( + ty::TraitRef::new(tcx, trait_def_id, self.args.truncate_to(tcx, trait_generics)), + &self.args[trait_generics.count()..], + ) + } + + pub fn to_term(self, tcx: TyCtxt<'tcx>) -> ty::Term<'tcx> { + match self.kind(tcx) { + ty::AliasTermKind::ProjectionTy => Ty::new_alias( + tcx, + ty::Projection, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into(), + ty::AliasTermKind::InherentTy => Ty::new_alias( + tcx, + ty::Inherent, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into(), + ty::AliasTermKind::OpaqueTy => Ty::new_alias( + tcx, + ty::Opaque, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into(), + ty::AliasTermKind::WeakTy => Ty::new_alias( + tcx, + ty::Weak, + AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }, + ) + .into(), + ty::AliasTermKind::UnevaluatedConst | ty::AliasTermKind::ProjectionConst => { + ty::Const::new_unevaluated( + tcx, + ty::UnevaluatedConst::new(self.def_id, self.args), + tcx.type_of(self.def_id).instantiate(tcx, self.args), + ) + .into() + } + } + } +} + +impl<'tcx> From<AliasTy<'tcx>> for AliasTerm<'tcx> { + fn from(ty: AliasTy<'tcx>) -> Self { + AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () } + } +} + +impl<'tcx> From<ty::UnevaluatedConst<'tcx>> for AliasTerm<'tcx> { + fn from(ct: ty::UnevaluatedConst<'tcx>) -> Self { + AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () } + } +} + +/// Represents the projection of an associated, opaque, or lazy-type-alias type. +/// +/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`. +/// * For an inherent projection, this would be `Ty::N<...>`. +/// * For an opaque type, there is no explicit syntax. +#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] +#[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] +pub struct AliasTy<'tcx> { + /// The parameters of the associated or opaque type. + /// + /// For a projection, these are the generic parameters for the trait and the + /// GAT parameters, if there are any. + /// + /// For an inherent projection, they consist of the self type and the GAT parameters, + /// if there are any. + /// + /// For RPIT the generic parameters are for the generics of the function, + /// while for TAIT it is used for the generic parameters of the alias. + pub args: GenericArgsRef<'tcx>, + + /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether + /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if + /// this is an opaque. + /// + /// During codegen, `tcx.type_of(def_id)` can be used to get the type of the + /// underlying type if the type is an opaque. + /// + /// Note that if this is an associated type, this is not the `DefId` of the + /// `TraitRef` containing this associated type, which is in `tcx.associated_item(def_id).container`, + /// aka. `tcx.parent(def_id)`. + pub def_id: DefId, + + /// This field exists to prevent the creation of `AliasT` without using /// [AliasTy::new]. _use_alias_ty_new_instead: (), } @@ -1152,7 +1377,7 @@ impl<'tcx> AliasTy<'tcx> { ty::AliasTy { def_id, args, _use_alias_ty_new_instead: () } } - pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind { + pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasTyKind { match tcx.def_kind(self.def_id) { DefKind::AssocTy if let DefKind::Impl { of_trait: false } = @@ -1169,24 +1394,7 @@ impl<'tcx> AliasTy<'tcx> { /// Whether this alias type is an opaque. pub fn is_opaque(self, tcx: TyCtxt<'tcx>) -> bool { - matches!(self.opt_kind(tcx), Some(ty::Opaque)) - } - - /// FIXME: rename `AliasTy` to `AliasTerm` and always handle - /// constants. This function can then be removed. - pub fn opt_kind(self, tcx: TyCtxt<'tcx>) -> Option<ty::AliasKind> { - match tcx.def_kind(self.def_id) { - DefKind::AssocTy - if let DefKind::Impl { of_trait: false } = - tcx.def_kind(tcx.parent(self.def_id)) => - { - Some(ty::Inherent) - } - DefKind::AssocTy => Some(ty::Projection), - DefKind::OpaqueTy => Some(ty::Opaque), - DefKind::TyAlias => Some(ty::Weak), - _ => None, - } + matches!(self.kind(tcx), ty::Opaque) } pub fn to_ty(self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { @@ -1194,7 +1402,7 @@ impl<'tcx> AliasTy<'tcx> { } } -/// The following methods work only with associated type projections. +/// The following methods work only with (trait) associated type projections. impl<'tcx> AliasTy<'tcx> { pub fn self_ty(self) -> Ty<'tcx> { self.args.type_at(0) @@ -1203,10 +1411,7 @@ impl<'tcx> AliasTy<'tcx> { pub fn with_self_ty(self, tcx: TyCtxt<'tcx>, self_ty: Ty<'tcx>) -> Self { AliasTy::new(tcx, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter().skip(1))) } -} -/// The following methods work only with trait associated type projections. -impl<'tcx> AliasTy<'tcx> { pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId { match tcx.def_kind(self.def_id) { DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id), @@ -1221,7 +1426,6 @@ impl<'tcx> AliasTy<'tcx> { self, tcx: TyCtxt<'tcx>, ) -> (ty::TraitRef<'tcx>, &'tcx [ty::GenericArg<'tcx>]) { - debug_assert!(matches!(tcx.def_kind(self.def_id), DefKind::AssocTy | DefKind::AssocConst)); let trait_def_id = self.trait_def_id(tcx); let trait_generics = tcx.generics_of(trait_def_id); ( @@ -1511,7 +1715,7 @@ impl<'tcx> Ty<'tcx> { #[inline] pub fn new_alias( tcx: TyCtxt<'tcx>, - kind: ty::AliasKind, + kind: ty::AliasTyKind, alias_ty: ty::AliasTy<'tcx>, ) -> Ty<'tcx> { debug_assert_matches!( diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 41f417dfd4b..24e3e623ff2 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -79,6 +79,10 @@ pub struct TypeckResults<'tcx> { /// Stores the actual binding mode for all instances of [`BindingMode`]. pat_binding_modes: ItemLocalMap<BindingMode>, + /// Top-level patterns whose match ergonomics need to be desugared + /// by the Rust 2021 -> 2024 migration lint. + rust_2024_migration_desugared_pats: ItemLocalSet, + /// Stores the types which were implicitly dereferenced in pattern binding modes /// for later usage in THIR lowering. For example, /// @@ -229,6 +233,7 @@ impl<'tcx> TypeckResults<'tcx> { adjustments: Default::default(), pat_binding_modes: Default::default(), pat_adjustments: Default::default(), + rust_2024_migration_desugared_pats: Default::default(), skipped_ref_pats: Default::default(), closure_kind_origins: Default::default(), liberated_fn_sigs: Default::default(), @@ -432,6 +437,20 @@ impl<'tcx> TypeckResults<'tcx> { LocalTableInContextMut { hir_owner: self.hir_owner, data: &mut self.pat_adjustments } } + pub fn rust_2024_migration_desugared_pats(&self) -> LocalSetInContext<'_> { + LocalSetInContext { + hir_owner: self.hir_owner, + data: &self.rust_2024_migration_desugared_pats, + } + } + + pub fn rust_2024_migration_desugared_pats_mut(&mut self) -> LocalSetInContextMut<'_> { + LocalSetInContextMut { + hir_owner: self.hir_owner, + data: &mut self.rust_2024_migration_desugared_pats, + } + } + pub fn skipped_ref_pats(&self) -> LocalSetInContext<'_> { LocalSetInContext { hir_owner: self.hir_owner, data: &self.skipped_ref_pats } } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 6ad4f492f74..04ce3de8874 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -1086,7 +1086,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for OpaqueTypeExpander<'tcx> { { p.kind() .rebind(ty::ProjectionPredicate { - projection_ty: projection_pred.projection_ty.fold_with(self), + projection_term: projection_pred.projection_term.fold_with(self), // Don't fold the term on the RHS of the projection predicate. // This is because for default trait methods with RPITITs, we // install a `NormalizesTo(Projection(RPITIT) -> Opaque(RPITIT))` |
