diff options
Diffstat (limited to 'compiler/rustc_middle/src/mir')
-rw-r--r-- | compiler/rustc_middle/src/mir/interpret/error.rs | 19 | ||||
-rw-r--r-- | compiler/rustc_middle/src/mir/interpret/pointer.rs | 2 | ||||
-rw-r--r-- | compiler/rustc_middle/src/mir/interpret/queries.rs | 42 | ||||
-rw-r--r-- | compiler/rustc_middle/src/mir/mod.rs | 114 | ||||
-rw-r--r-- | compiler/rustc_middle/src/mir/mono.rs | 6 | ||||
-rw-r--r-- | compiler/rustc_middle/src/mir/pretty.rs | 3 | ||||
-rw-r--r-- | compiler/rustc_middle/src/mir/query.rs | 9 | ||||
-rw-r--r-- | compiler/rustc_middle/src/mir/syntax.rs | 26 | ||||
-rw-r--r-- | compiler/rustc_middle/src/mir/tcx.rs | 5 | ||||
-rw-r--r-- | compiler/rustc_middle/src/mir/type_foldable.rs | 28 | ||||
-rw-r--r-- | compiler/rustc_middle/src/mir/type_visitable.rs | 19 | ||||
-rw-r--r-- | compiler/rustc_middle/src/mir/visit.rs | 7 |
12 files changed, 168 insertions, 112 deletions
diff --git a/compiler/rustc_middle/src/mir/interpret/error.rs b/compiler/rustc_middle/src/mir/interpret/error.rs index e4039cc7c..b5a50cc15 100644 --- a/compiler/rustc_middle/src/mir/interpret/error.rs +++ b/compiler/rustc_middle/src/mir/interpret/error.rs @@ -479,12 +479,7 @@ impl<T: Any> AsAny for T { } /// A trait for machine-specific errors (or other "machine stop" conditions). -pub trait MachineStopType: AsAny + fmt::Display + Send { - /// If `true`, emit a hard error instead of going through the `CONST_ERR` lint - fn is_hard_err(&self) -> bool { - false - } -} +pub trait MachineStopType: AsAny + fmt::Display + Send {} impl dyn MachineStopType { #[inline(always)] @@ -543,16 +538,4 @@ impl InterpError<'_> { | InterpError::UndefinedBehavior(UndefinedBehaviorInfo::Ub(_)) ) } - - /// Should this error be reported as a hard error, preventing compilation, or a soft error, - /// causing a deny-by-default lint? - pub fn is_hard_err(&self) -> bool { - use InterpError::*; - match *self { - MachineStop(ref err) => err.is_hard_err(), - UndefinedBehavior(_) => true, - ResourceExhaustion(ResourceExhaustionInfo::MemoryExhausted) => true, - _ => false, - } - } } diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 95e52e391..23c2ce647 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -43,7 +43,7 @@ pub trait PointerArithmetic: HasDataLayout { let val = val as i64; // Now wrap-around into the machine_isize range. if val > self.machine_isize_max() { - // This can only happen the the ptr size is < 64, so we know max_usize_plus_1 fits into + // This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into // i64. debug_assert!(self.pointer_size().bits() < 64); let max_usize_plus_1 = 1u128 << self.pointer_size().bits(); diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index 4207988d7..473894ac1 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -4,7 +4,9 @@ use crate::mir; use crate::ty::subst::InternalSubsts; use crate::ty::visit::TypeVisitable; use crate::ty::{self, query::TyCtxtAt, query::TyCtxtEnsure, TyCtxt}; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; +use rustc_session::lint; use rustc_span::{Span, DUMMY_SP}; impl<'tcx> TyCtxt<'tcx> { @@ -36,7 +38,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_resolve( self, param_env: ty::ParamEnv<'tcx>, - ct: ty::Unevaluated<'tcx>, + ct: mir::UnevaluatedConst<'tcx>, span: Option<Span>, ) -> EvalToConstValueResult<'tcx> { // Cannot resolve `Unevaluated` constants that contain inference @@ -45,11 +47,15 @@ impl<'tcx> TyCtxt<'tcx> { // // When trying to evaluate constants containing inference variables, // use `Infcx::const_eval_resolve` instead. - if ct.substs.has_infer_types_or_consts() { + if ct.substs.has_non_region_infer() { bug!("did not expect inference variables here"); } - match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { + match ty::Instance::resolve_opt_const_arg( + self, param_env, + // FIXME: maybe have a separate version for resolving mir::UnevaluatedConst? + ct.def, ct.substs, + ) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: ct.promoted }; self.const_eval_global_id(param_env, cid, span) @@ -63,7 +69,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn const_eval_resolve_for_typeck( self, param_env: ty::ParamEnv<'tcx>, - ct: ty::Unevaluated<'tcx, ()>, + ct: ty::UnevaluatedConst<'tcx>, span: Option<Span>, ) -> EvalToValTreeResult<'tcx> { // Cannot resolve `Unevaluated` constants that contain inference @@ -72,14 +78,36 @@ impl<'tcx> TyCtxt<'tcx> { // // When trying to evaluate constants containing inference variables, // use `Infcx::const_eval_resolve` instead. - if ct.substs.has_infer_types_or_consts() { + if ct.substs.has_non_region_infer() { bug!("did not expect inference variables here"); } match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) { Ok(Some(instance)) => { let cid = GlobalId { instance, promoted: None }; - self.const_eval_global_id_for_typeck(param_env, cid, span) + self.const_eval_global_id_for_typeck(param_env, cid, span).inspect(|_| { + // We are emitting the lint here instead of in `is_const_evaluatable` + // as we normalize obligations before checking them, and normalization + // uses this function to evaluate this constant. + // + // @lcnr believes that successfully evaluating even though there are + // used generic parameters is a bug of evaluation, so checking for it + // here does feel somewhat sensible. + if !self.features().generic_const_exprs && ct.substs.has_non_region_param() { + assert!(matches!(self.def_kind(ct.def.did), DefKind::AnonConst)); + let mir_body = self.mir_for_ctfe_opt_const_arg(ct.def); + if mir_body.is_polymorphic { + let Some(local_def_id) = ct.def.did.as_local() else { return }; + self.struct_span_lint_hir( + lint::builtin::CONST_EVALUATABLE_UNCHECKED, + self.hir().local_def_id_to_hir_id(local_def_id), + self.def_span(ct.def.did), + "cannot use constants which depend on generic parameters in types", + |err| err, + ) + } + } + }) } Ok(None) => Err(ErrorHandled::TooGeneric), Err(error_reported) => Err(ErrorHandled::Reported(error_reported)), @@ -211,7 +239,7 @@ impl<'tcx> TyCtxt<'tcx> { self, param_env: ty::ParamEnv<'tcx>, constant: mir::ConstantKind<'tcx>, - ) -> mir::DestructuredMirConstant<'tcx> { + ) -> mir::DestructuredConstant<'tcx> { self.try_destructure_mir_constant(param_env.and(constant)).unwrap() } } diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 3d7a6230e..79db35a76 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -7,12 +7,12 @@ use crate::mir::interpret::{ }; use crate::mir::visit::MirVisitable; use crate::ty::codec::{TyDecoder, TyEncoder}; -use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable}; +use crate::ty::fold::{FallibleTypeFolder, TypeFoldable}; use crate::ty::print::{FmtPrinter, Printer}; -use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef}; -use crate::ty::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor}; +use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::{self, List, Ty, TyCtxt}; use crate::ty::{AdtDef, InstanceDef, ScalarInt, UserTypeAnnotationIndex}; +use crate::ty::{GenericArg, InternalSubsts, SubstsRef}; use rustc_data_structures::captures::Captures; use rustc_errors::ErrorGuaranteed; @@ -116,11 +116,6 @@ pub trait MirPass<'tcx> { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); - /// If this pass causes the MIR to enter a new phase, return that phase. - fn phase_change(&self) -> Option<MirPhase> { - None - } - fn is_mir_dump_enabled(&self) -> bool { true } @@ -145,6 +140,35 @@ impl MirPhase { } } +impl Display for MirPhase { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + MirPhase::Built => write!(f, "built"), + MirPhase::Analysis(p) => write!(f, "analysis-{}", p), + MirPhase::Runtime(p) => write!(f, "runtime-{}", p), + } + } +} + +impl Display for AnalysisPhase { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + AnalysisPhase::Initial => write!(f, "initial"), + AnalysisPhase::PostCleanup => write!(f, "post_cleanup"), + } + } +} + +impl Display for RuntimePhase { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + match self { + RuntimePhase::Initial => write!(f, "initial"), + RuntimePhase::PostCleanup => write!(f, "post_cleanup"), + RuntimePhase::Optimized => write!(f, "optimized"), + } + } +} + /// Where a specific `mir::Body` comes from. #[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable, TypeVisitable)] @@ -207,6 +231,9 @@ pub struct Body<'tcx> { /// us to see the difference and forego optimization on the inlined promoted items. pub phase: MirPhase, + /// How many passses we have executed since starting the current phase. Used for debug output. + pub pass_count: usize, + pub source: MirSource<'tcx>, /// A list of source scopes; these are referenced by statements @@ -292,6 +319,7 @@ impl<'tcx> Body<'tcx> { let mut body = Body { phase: MirPhase::Built, + pass_count: 1, source, basic_blocks: BasicBlocks::new(basic_blocks), source_scopes, @@ -313,7 +341,7 @@ impl<'tcx> Body<'tcx> { is_polymorphic: false, tainted_by_errors, }; - body.is_polymorphic = body.has_param_types_or_consts(); + body.is_polymorphic = body.has_non_region_param(); body } @@ -325,6 +353,7 @@ impl<'tcx> Body<'tcx> { pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self { let mut body = Body { phase: MirPhase::Built, + pass_count: 1, source: MirSource::item(CRATE_DEF_ID.to_def_id()), basic_blocks: BasicBlocks::new(basic_blocks), source_scopes: IndexVec::new(), @@ -339,7 +368,7 @@ impl<'tcx> Body<'tcx> { is_polymorphic: false, tainted_by_errors: None, }; - body.is_polymorphic = body.has_param_types_or_consts(); + body.is_polymorphic = body.has_non_region_param(); body } @@ -1380,6 +1409,7 @@ impl<V, T> ProjectionElem<V, T> { Self::Field(_, _) | Self::Index(_) + | Self::OpaqueCast(_) | Self::ConstantIndex { .. } | Self::Subslice { .. } | Self::Downcast(_, _) => false, @@ -1574,7 +1604,9 @@ impl Debug for Place<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { for elem in self.projection.iter().rev() { match elem { - ProjectionElem::Downcast(_, _) | ProjectionElem::Field(_, _) => { + ProjectionElem::OpaqueCast(_) + | ProjectionElem::Downcast(_, _) + | ProjectionElem::Field(_, _) => { write!(fmt, "(").unwrap(); } ProjectionElem::Deref => { @@ -1590,6 +1622,9 @@ impl Debug for Place<'_> { for elem in self.projection.iter() { match elem { + ProjectionElem::OpaqueCast(ty) => { + write!(fmt, " as {})", ty)?; + } ProjectionElem::Downcast(Some(name), _index) => { write!(fmt, " as {})", name)?; } @@ -1818,7 +1853,6 @@ impl<'tcx> Rvalue<'tcx> { // While the model is undecided, we should be conservative. See // <https://www.ralfj.de/blog/2022/04/11/provenance-exposed.html> Rvalue::Cast(CastKind::PointerExposeAddress, _, _) => false, - Rvalue::Cast(CastKind::DynStar, _, _) => false, Rvalue::Use(_) | Rvalue::CopyForDeref(_) @@ -1828,7 +1862,15 @@ impl<'tcx> Rvalue<'tcx> { | Rvalue::AddressOf(_, _) | Rvalue::Len(_) | Rvalue::Cast( - CastKind::Misc | CastKind::Pointer(_) | CastKind::PointerFromExposedAddress, + CastKind::IntToInt + | CastKind::FloatToInt + | CastKind::FloatToFloat + | CastKind::IntToFloat + | CastKind::FnPtrToPtr + | CastKind::PtrToPtr + | CastKind::Pointer(_) + | CastKind::PointerFromExposedAddress + | CastKind::DynStar, _, _, ) @@ -2043,13 +2085,13 @@ pub struct Constant<'tcx> { } #[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable, Debug)] -#[derive(Lift)] +#[derive(Lift, TypeFoldable, TypeVisitable)] pub enum ConstantKind<'tcx> { /// This constant came from the type system Ty(ty::Const<'tcx>), /// An unevaluated mir constant which is not part of the type system. - Unevaluated(ty::Unevaluated<'tcx, Option<Promoted>>, Ty<'tcx>), + Unevaluated(UnevaluatedConst<'tcx>, Ty<'tcx>), /// This constant cannot go back into the type system, as it represents /// something the type system cannot handle (e.g. pointers). @@ -2309,12 +2351,11 @@ impl<'tcx> ConstantKind<'tcx> { ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty }) .substs; - let uneval = ty::Unevaluated { + let uneval = UnevaluatedConst { def: ty::WithOptConstParam::unknown(def_id).to_global(), substs, promoted: None, }; - debug_assert!(!uneval.has_free_regions()); Self::Unevaluated(uneval, ty) @@ -2398,7 +2439,7 @@ impl<'tcx> ConstantKind<'tcx> { let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); let span = tcx.hir().span(hir_id); - let uneval = ty::Unevaluated::new(def.to_global(), substs); + let uneval = UnevaluatedConst::new(def.to_global(), substs); debug!(?span, ?param_env); match tcx.const_eval_resolve(param_env, uneval, Some(span)) { @@ -2411,7 +2452,7 @@ impl<'tcx> ConstantKind<'tcx> { // Error was handled in `const_eval_resolve`. Here we just create a // new unevaluated const and error hard later in codegen Self::Unevaluated( - ty::Unevaluated { + UnevaluatedConst { def: def.to_global(), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), promoted: None, @@ -2434,6 +2475,34 @@ impl<'tcx> ConstantKind<'tcx> { } } +/// An unevaluated (potentially generic) constant used in MIR. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] +#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct UnevaluatedConst<'tcx> { + pub def: ty::WithOptConstParam<DefId>, + pub substs: SubstsRef<'tcx>, + pub promoted: Option<Promoted>, +} + +impl<'tcx> UnevaluatedConst<'tcx> { + // FIXME: probably should get rid of this method. It's also wrong to + // shrink and then later expand a promoted. + #[inline] + pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> { + ty::UnevaluatedConst { def: self.def, substs: self.substs } + } +} + +impl<'tcx> UnevaluatedConst<'tcx> { + #[inline] + pub fn new( + def: ty::WithOptConstParam<DefId>, + substs: SubstsRef<'tcx>, + ) -> UnevaluatedConst<'tcx> { + UnevaluatedConst { def, substs, promoted: Default::default() } + } +} + /// A collection of projections into user types. /// /// They are projections because a binding can occur a part of a @@ -2727,7 +2796,7 @@ fn pretty_print_const_value<'tcx>( } // Aggregates, printed as array/tuple/struct/variant construction syntax. // - // NB: the `has_param_types_or_consts` check ensures that we can use + // NB: the `has_non_region_param` check ensures that we can use // the `destructure_const` query with an empty `ty::ParamEnv` without // introducing ICEs (e.g. via `layout_of`) from missing bounds. // E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized` @@ -2735,7 +2804,7 @@ fn pretty_print_const_value<'tcx>( // // FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the // correct `ty::ParamEnv` to allow printing *all* constant values. - (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => { + (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_non_region_param() => { let ct = tcx.lift(ct).unwrap(); let ty = tcx.lift(ty).unwrap(); if let Some(contents) = tcx.try_destructure_mir_constant( @@ -2906,11 +2975,12 @@ impl Location { mod size_asserts { use super::*; use rustc_data_structures::static_assert_size; - // These are in alphabetical order, which is easy to maintain. + // tidy-alphabetical-start static_assert_size!(BasicBlockData<'_>, 144); static_assert_size!(LocalDecl<'_>, 56); static_assert_size!(Statement<'_>, 32); static_assert_size!(StatementKind<'_>, 16); static_assert_size!(Terminator<'_>, 112); static_assert_size!(TerminatorKind<'_>, 96); + // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/mir/mono.rs b/compiler/rustc_middle/src/mir/mono.rs index 21ae121e1..15a24aa4a 100644 --- a/compiler/rustc_middle/src/mir/mono.rs +++ b/compiler/rustc_middle/src/mir/mono.rs @@ -81,7 +81,7 @@ impl<'tcx> MonoItem<'tcx> { MonoItem::Fn(instance) => tcx.symbol_name(instance), MonoItem::Static(def_id) => tcx.symbol_name(Instance::mono(tcx, def_id)), MonoItem::GlobalAsm(item_id) => { - SymbolName::new(tcx, &format!("global_asm_{:?}", item_id.def_id)) + SymbolName::new(tcx, &format!("global_asm_{:?}", item_id.owner_id)) } } } @@ -182,7 +182,7 @@ impl<'tcx> MonoItem<'tcx> { match *self { MonoItem::Fn(Instance { def, .. }) => def.def_id().as_local(), MonoItem::Static(def_id) => def_id.as_local(), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id), + MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.def_id), } .map(|def_id| tcx.def_span(def_id)) } @@ -373,7 +373,7 @@ impl<'tcx> CodegenUnit<'tcx> { } } MonoItem::Static(def_id) => def_id.as_local().map(Idx::index), - MonoItem::GlobalAsm(item_id) => Some(item_id.def_id.index()), + MonoItem::GlobalAsm(item_id) => Some(item_id.owner_id.def_id.index()), }, item.symbol_name(tcx), ) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 0b42137d4..05dcfba77 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -466,10 +466,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> { ty::ConstKind::Param(p) => format!("Param({})", p), ty::ConstKind::Unevaluated(uv) => { format!( - "Unevaluated({}, {:?}, {:?})", + "Unevaluated({}, {:?})", self.tcx.def_path_str(uv.def.did), uv.substs, - uv.promoted, ) } ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)), diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index d89efe2b3..efd7357af 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -392,16 +392,9 @@ pub enum ClosureOutlivesSubject<'tcx> { Region(ty::RegionVid), } -/// The constituent parts of a type level constant of kind ADT or array. -#[derive(Copy, Clone, Debug, HashStable)] -pub struct DestructuredConst<'tcx> { - pub variant: Option<VariantIdx>, - pub fields: &'tcx [ty::Const<'tcx>], -} - /// The constituent parts of a mir constant of kind ADT or array. #[derive(Copy, Clone, Debug, HashStable)] -pub struct DestructuredMirConstant<'tcx> { +pub struct DestructuredConstant<'tcx> { pub variant: Option<VariantIdx>, pub fields: &'tcx [ConstantKind<'tcx>], } diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index c7d0283aa..85ef51f12 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -82,9 +82,10 @@ pub enum MirPhase { /// access to. This occurs in generator bodies. Such locals do not behave like other locals, /// because they eg may be aliased in surprising ways. Runtime MIR has no such special locals - /// all generator bodies are lowered and so all places that look like locals really are locals. - /// - Const prop lints: The lint pass which reports eg `200_u8 + 200_u8` as an error is run as a - /// part of analysis to runtime MIR lowering. This means that transformations which may supress - /// such errors may not run on analysis MIR. + /// + /// Also note that the lint pass which reports eg `200_u8 + 200_u8` as an error is run as a part + /// of analysis to runtime MIR lowering. To ensure lints are reported reliably, this means that + /// transformations which may supress such errors should not run on analysis MIR. Runtime(RuntimePhase), } @@ -829,6 +830,9 @@ pub type AssertMessage<'tcx> = AssertKind<Operand<'tcx>>; /// generator has more than one variant, the parent place's variant index must be set, indicating /// which variant is being used. If it has just one variant, the variant index may or may not be /// included - the single possible variant is inferred if it is not included. +/// - [`OpaqueCast`](ProjectionElem::OpaqueCast): This projection changes the place's type to the +/// given one, and makes no other changes. A `OpaqueCast` projection on any type other than an +/// opaque type from the current crate is not well-formed. /// - [`ConstantIndex`](ProjectionElem::ConstantIndex): Computes an offset in units of `T` into the /// place as described in the documentation for the `ProjectionElem`. The resulting address is /// the parent's address plus that offset, and the type is `T`. This is only legal if the parent @@ -928,6 +932,10 @@ pub enum ProjectionElem<V, T> { /// /// The included Symbol is the name of the variant, used for printing MIR. Downcast(Option<Symbol>, VariantIdx), + + /// Like an explicit cast from an opaque type to a concrete type, but without + /// requiring an intermediate variable. + OpaqueCast(T), } /// Alias for projections as they appear in places, where the base is a place @@ -1141,8 +1149,12 @@ pub enum CastKind { Pointer(PointerCast), /// Cast into a dyn* object. DynStar, - /// Remaining unclassified casts. - Misc, + IntToInt, + FloatToInt, + FloatToFloat, + IntToFloat, + PtrToPtr, + FnPtrToPtr, } #[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] @@ -1233,11 +1245,11 @@ pub enum BinOp { #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] mod size_asserts { use super::*; - // These are in alphabetical order, which is easy to maintain. - #[cfg(not(bootstrap))] + // tidy-alphabetical-start static_assert_size!(AggregateKind<'_>, 40); static_assert_size!(Operand<'_>, 24); static_assert_size!(Place<'_>, 16); static_assert_size!(PlaceElem<'_>, 24); static_assert_size!(Rvalue<'_>, 40); + // tidy-alphabetical-end } diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 405003156..fa3adafd4 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -4,7 +4,6 @@ */ use crate::mir::*; -use crate::ty::subst::Subst; use crate::ty::{self, Ty, TyCtxt}; use rustc_hir as hir; use rustc_target::abi::VariantIdx; @@ -57,7 +56,7 @@ impl<'tcx> PlaceTy<'tcx> { /// `PlaceElem`, where we can just use the `Ty` that is already /// stored inline on field projection elems. pub fn projection_ty(self, tcx: TyCtxt<'tcx>, elem: PlaceElem<'tcx>) -> PlaceTy<'tcx> { - self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty) + self.projection_ty_core(tcx, ty::ParamEnv::empty(), &elem, |_, _, ty| ty, |_, ty| ty) } /// `place_ty.projection_ty_core(tcx, elem, |...| { ... })` @@ -71,6 +70,7 @@ impl<'tcx> PlaceTy<'tcx> { param_env: ty::ParamEnv<'tcx>, elem: &ProjectionElem<V, T>, mut handle_field: impl FnMut(&Self, Field, T) -> Ty<'tcx>, + mut handle_opaque_cast: impl FnMut(&Self, T) -> Ty<'tcx>, ) -> PlaceTy<'tcx> where V: ::std::fmt::Debug, @@ -109,6 +109,7 @@ impl<'tcx> PlaceTy<'tcx> { PlaceTy { ty: self.ty, variant_index: Some(index) } } ProjectionElem::Field(f, fty) => PlaceTy::from_ty(handle_field(&self, f, fty)), + ProjectionElem::OpaqueCast(ty) => PlaceTy::from_ty(handle_opaque_cast(&self, ty)), }; debug!("projection_ty self: {:?} elem: {:?} yields: {:?}", self, elem, answer); answer diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 9d098c808..4c0974f86 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -26,6 +26,12 @@ TrivialTypeTraversalAndLiftImpls! { GeneratorSavedLocal, } +TrivialTypeTraversalImpls! { + for <'tcx> { + ConstValue<'tcx>, + } +} + impl<'tcx> TypeFoldable<'tcx> for &'tcx [InlineAsmTemplatePiece] { fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, _folder: &mut F) -> Result<Self, F::Error> { Ok(self) @@ -49,25 +55,3 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> { Ok(self) } } - -impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { - #[inline(always)] - fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { - folder.try_fold_mir_const(self) - } -} - -impl<'tcx> TypeSuperFoldable<'tcx> for ConstantKind<'tcx> { - fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>( - self, - folder: &mut F, - ) -> Result<Self, F::Error> { - match self { - ConstantKind::Ty(c) => Ok(ConstantKind::Ty(c.try_fold_with(folder)?)), - ConstantKind::Val(v, t) => Ok(ConstantKind::Val(v, t.try_fold_with(folder)?)), - ConstantKind::Unevaluated(uv, t) => { - Ok(ConstantKind::Unevaluated(uv.try_fold_with(folder)?, t.try_fold_with(folder)?)) - } - } - } -} diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs index be19bb486..e7cd497b2 100644 --- a/compiler/rustc_middle/src/mir/type_visitable.rs +++ b/compiler/rustc_middle/src/mir/type_visitable.rs @@ -7,22 +7,3 @@ impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> { ControlFlow::CONTINUE } } - -impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> { - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - visitor.visit_mir_const(*self) - } -} - -impl<'tcx> TypeSuperVisitable<'tcx> for ConstantKind<'tcx> { - fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { - match *self { - ConstantKind::Ty(c) => c.visit_with(visitor), - ConstantKind::Val(_, t) => t.visit_with(visitor), - ConstantKind::Unevaluated(uv, t) => { - uv.visit_with(visitor)?; - t.visit_with(visitor) - } - } - } -} diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index d9b24566b..ddcf3711b 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -1084,6 +1084,11 @@ macro_rules! visit_place_fns { self.visit_ty(&mut new_ty, TyContext::Location(location)); if ty != new_ty { Some(PlaceElem::Field(field, new_ty)) } else { None } } + PlaceElem::OpaqueCast(ty) => { + let mut new_ty = ty; + self.visit_ty(&mut new_ty, TyContext::Location(location)); + if ty != new_ty { Some(PlaceElem::OpaqueCast(new_ty)) } else { None } + } PlaceElem::Deref | PlaceElem::ConstantIndex { .. } | PlaceElem::Subslice { .. } @@ -1153,7 +1158,7 @@ macro_rules! visit_place_fns { location: Location, ) { match elem { - ProjectionElem::Field(_field, ty) => { + ProjectionElem::OpaqueCast(ty) | ProjectionElem::Field(_, ty) => { self.visit_ty(ty, TyContext::Location(location)); } ProjectionElem::Index(local) => { |