diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 6b4ed9b9d40..aac64d854a6 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -5,7 +5,6 @@ use rustc_middle::mir::interpret::{ read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar, }; -use rustc_middle::ty::ConstKind; use rustc_span::DUMMY_SP; use cranelift_codegen::ir::GlobalValueData; @@ -42,15 +41,7 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool { let mut all_constants_ok = true; for constant in &fx.mir.required_consts { let unevaluated = match fx.monomorphize(constant.literal) { - ConstantKind::Ty(ct) => match ct.kind() { - ConstKind::Unevaluated(uv) => uv.expand(), - ConstKind::Value(_) => continue, - ConstKind::Param(_) - | ConstKind::Infer(_) - | ConstKind::Bound(_, _) - | ConstKind::Placeholder(_) - | ConstKind::Error(_) => unreachable!("{:?}", ct), - }, + ConstantKind::Ty(_) => unreachable!(), ConstantKind::Unevaluated(uv, _) => uv, ConstantKind::Val(..) => continue, }; @@ -118,7 +109,7 @@ pub(crate) fn codegen_constant<'tcx>( ) -> CValue<'tcx> { let (const_val, ty) = match fx.monomorphize(constant.literal) { ConstantKind::Ty(const_) => unreachable!("{:?}", const_), - ConstantKind::Unevaluated(ty::Unevaluated { def, substs, promoted }, ty) + ConstantKind::Unevaluated(mir::Unevaluated { def, substs, promoted }, ty) if fx.tcx.is_static(def.did) => { assert!(substs.is_empty()); diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs index fb22befd0a4..b1d140726d1 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs @@ -5,6 +5,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_hir::LangItem; use rustc_infer::infer::TyCtxtInferExt; +use rustc_middle::mir; use rustc_middle::mir::*; use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty}; use rustc_span::DUMMY_SP; @@ -350,17 +351,13 @@ pub fn in_operand<'tcx, Q, F>( // FIXME(valtrees): check whether const qualifs should behave the same // way for type and mir constants. let uneval = match constant.literal { - ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Unevaluated(_)) => { - let ty::ConstKind::Unevaluated(uv) = ct.kind() else { unreachable!() }; - - Some(uv.expand()) - } - ConstantKind::Ty(_) => None, + ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Param(_)) => None, + ConstantKind::Ty(c) => bug!("expected ConstKind::Param here, found {:?}", c), ConstantKind::Unevaluated(uv, _) => Some(uv), ConstantKind::Val(..) => None, }; - if let Some(ty::Unevaluated { def, substs: _, promoted }) = uneval { + if let Some(mir::Unevaluated { def, substs: _, promoted }) = uneval { // Use qualifs of the type for the promoted. Promoteds in MIR body should be possible // only for `NeedsNonConstDrop` with precise drop checking. This is the only const // check performed after the promotion. Verify that with an assertion. @@ -368,11 +365,7 @@ pub fn in_operand<'tcx, Q, F>( // Don't peek inside trait associated constants. if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() { - let qualifs = if let Some((did, param_did)) = def.as_const_arg() { - cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did)) - } else { - cx.tcx.at(constant.span).mir_const_qualif(def.did) - }; + let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did); if !Q::in_qualifs(&qualifs) { return false; diff --git a/compiler/rustc_const_eval/src/transform/promote_consts.rs b/compiler/rustc_const_eval/src/transform/promote_consts.rs index 461051574e5..733683bf7ba 100644 --- a/compiler/rustc_const_eval/src/transform/promote_consts.rs +++ b/compiler/rustc_const_eval/src/transform/promote_consts.rs @@ -13,6 +13,7 @@ //! move analysis runs after promotion on broken MIR. use rustc_hir as hir; +use rustc_middle::mir; use rustc_middle::mir::traversal::ReversePostorderIter; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; @@ -840,7 +841,7 @@ fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span); let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did)); - let uneval = ty::Unevaluated { def, substs, promoted: Some(promoted_id) }; + let uneval = mir::Unevaluated { def, substs, promoted: Some(promoted_id) }; Operand::Constant(Box::new(Constant { span, diff --git a/compiler/rustc_infer/src/infer/combine.rs b/compiler/rustc_infer/src/infer/combine.rs index c406df9e411..18e05fa37f7 100644 --- a/compiler/rustc_infer/src/infer/combine.rs +++ b/compiler/rustc_infer/src/infer/combine.rs @@ -742,9 +742,7 @@ fn consts( } } } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { - assert_eq!(promoted, ()); - + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => { let substs = self.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), @@ -753,7 +751,7 @@ fn consts( )?; Ok(self.tcx().mk_const(ty::ConstS { ty: c.ty(), - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), + kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }), })) } _ => relate::super_relate_consts(self, c, c), @@ -964,9 +962,7 @@ fn consts( } } } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { - assert_eq!(promoted, ()); - + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => { let substs = self.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), @@ -976,7 +972,7 @@ fn consts( Ok(self.tcx().mk_const(ty::ConstS { ty: c.ty(), - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }), + kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }), })) } _ => relate::super_relate_consts(self, c, c), diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 3abed12217c..0a37aa035c2 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -705,8 +705,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { #[instrument(skip(self), level = "debug")] pub fn try_unify_abstract_consts( &self, - a: ty::Unevaluated<'tcx, ()>, - b: ty::Unevaluated<'tcx, ()>, + a: ty::Unevaluated<'tcx>, + b: ty::Unevaluated<'tcx>, param_env: ty::ParamEnv<'tcx>, ) -> bool { // Reject any attempt to unify two unevaluated constants that contain inference @@ -1690,7 +1690,7 @@ pub fn create_next_universe(&self) -> ty::UniverseIndex { pub fn try_const_eval_resolve( &self, param_env: ty::ParamEnv<'tcx>, - unevaluated: ty::Unevaluated<'tcx, ()>, + unevaluated: ty::Unevaluated<'tcx>, ty: Ty<'tcx>, span: Option, ) -> Result, ErrorHandled> { @@ -1725,7 +1725,7 @@ pub fn try_const_eval_resolve( pub fn const_eval_resolve( &self, mut param_env: ty::ParamEnv<'tcx>, - unevaluated: ty::Unevaluated<'tcx, ()>, + unevaluated: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToValTreeResult<'tcx> { let mut substs = self.resolve_vars_if_possible(unevaluated.substs); @@ -1756,8 +1756,7 @@ pub fn const_eval_resolve( debug!(?param_env_erased); debug!(?substs_erased); - let unevaluated = - ty::Unevaluated { def: unevaluated.def, substs: substs_erased, promoted: () }; + let unevaluated = ty::Unevaluated { def: unevaluated.def, substs: substs_erased }; // The return value is the evaluated value which doesn't contain any reference to inference // variables, thus we don't need to substitute back the original values. diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs index a8c7505329c..5f3124e482d 100644 --- a/compiler/rustc_middle/src/mir/interpret/queries.rs +++ b/compiler/rustc_middle/src/mir/interpret/queries.rs @@ -36,7 +36,7 @@ pub fn const_eval_poly(self, def_id: DefId) -> EvalToConstValueResult<'tcx> { pub fn const_eval_resolve( self, param_env: ty::ParamEnv<'tcx>, - ct: ty::Unevaluated<'tcx>, + ct: mir::Unevaluated<'tcx>, span: Option, ) -> EvalToConstValueResult<'tcx> { // Cannot resolve `Unevaluated` constants that contain inference @@ -49,7 +49,11 @@ pub fn const_eval_resolve( 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 seperate version for resolving mir::Unevaluated? + 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 +67,7 @@ pub fn const_eval_resolve( pub fn const_eval_resolve_for_typeck( self, param_env: ty::ParamEnv<'tcx>, - ct: ty::Unevaluated<'tcx, ()>, + ct: ty::Unevaluated<'tcx>, span: Option, ) -> EvalToValTreeResult<'tcx> { // Cannot resolve `Unevaluated` constants that contain inference diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 86ffce8ceb4..4b3a3085b71 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2055,7 +2055,7 @@ pub enum ConstantKind<'tcx> { Ty(ty::Const<'tcx>), /// An unevaluated mir constant which is not part of the type system. - Unevaluated(ty::Unevaluated<'tcx, Option>, Ty<'tcx>), + Unevaluated(Unevaluated<'tcx, Option>, Ty<'tcx>), /// This constant cannot go back into the type system, as it represents /// something the type system cannot handle (e.g. pointers). @@ -2315,12 +2315,11 @@ pub fn from_inline_const(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty }) .substs; - let uneval = ty::Unevaluated { + let uneval = Unevaluated { def: ty::WithOptConstParam::unknown(def_id).to_global(), substs, promoted: None, }; - debug_assert!(!uneval.has_free_regions()); Self::Unevaluated(uneval, ty) @@ -2404,7 +2403,7 @@ fn from_opt_const_arg_anon_const( 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 = Unevaluated::new(def.to_global(), substs); debug!(?span, ?param_env); match tcx.const_eval_resolve(param_env, uneval, Some(span)) { @@ -2417,7 +2416,7 @@ fn from_opt_const_arg_anon_const( // 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 { + Unevaluated { def: def.to_global(), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), promoted: None, @@ -2440,6 +2439,31 @@ pub fn from_const(c: ty::Const<'tcx>, tcx: TyCtxt<'tcx>) -> Self { } } +/// An unevaluated (potentially generic) constant used in MIR. +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] +#[derive(Hash, HashStable)] +pub struct Unevaluated<'tcx, P = Option> { + pub def: ty::WithOptConstParam, + pub substs: SubstsRef<'tcx>, + pub promoted: P, +} + +impl<'tcx> Unevaluated<'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::Unevaluated<'tcx> { + ty::Unevaluated { def: self.def, substs: self.substs } + } +} + +impl<'tcx, P: Default> Unevaluated<'tcx, P> { + #[inline] + pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> { + Unevaluated { def, substs, promoted: Default::default() } + } +} + /// A collection of projections into user types. /// /// They are projections because a binding can occur a part of a diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 0b42137d4e3..05dcfba77b2 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -466,10 +466,9 @@ fn visit_constant(&mut self, constant: &Constant<'tcx>, _location: Location) { 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/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index 9d098c8083e..88c07ca17e2 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -3,6 +3,7 @@ use rustc_ast::InlineAsmTemplatePiece; use super::*; +use crate::mir; use crate::ty; TrivialTypeTraversalAndLiftImpls! { @@ -50,6 +51,25 @@ fn try_fold_with>(self, _: &mut F) -> Result TypeFoldable<'tcx> for mir::Unevaluated<'tcx> { + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_mir_unevaluated(self) + } +} + +impl<'tcx> TypeSuperFoldable<'tcx> for mir::Unevaluated<'tcx> { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + Ok(mir::Unevaluated { + def: self.def, + substs: self.substs.try_fold_with(folder)?, + promoted: self.promoted, + }) + } +} + impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> { #[inline(always)] fn try_fold_with>(self, folder: &mut F) -> Result { diff --git a/compiler/rustc_middle/src/mir/type_visitable.rs b/compiler/rustc_middle/src/mir/type_visitable.rs index be19bb486d4..3f213697884 100644 --- a/compiler/rustc_middle/src/mir/type_visitable.rs +++ b/compiler/rustc_middle/src/mir/type_visitable.rs @@ -1,6 +1,7 @@ //! `TypeVisitable` implementations for MIR types use super::*; +use crate::mir; impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix { fn visit_with>(&self, _: &mut V) -> ControlFlow { @@ -8,6 +9,18 @@ fn visit_with>(&self, _: &mut V) -> ControlFlow } } +impl<'tcx> TypeVisitable<'tcx> for mir::Unevaluated<'tcx> { + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_mir_unevaluated(*self) + } +} + +impl<'tcx> TypeSuperVisitable<'tcx> for mir::Unevaluated<'tcx> { + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { + self.substs.visit_with(visitor) + } +} + impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { visitor.visit_mir_const(*self) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1afea4864b8..9b112dcdb1b 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -381,7 +381,7 @@ } query try_unify_abstract_consts(key: - ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()> + ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx> )>) -> bool { desc { |tcx| "trying to unify the generic constants {} and {}", diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 8e0a1f1f9ac..f6f86540dd0 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -30,7 +30,7 @@ pub struct AbstractConst<'tcx> { impl<'tcx> AbstractConst<'tcx> { pub fn new( tcx: TyCtxt<'tcx>, - uv: ty::Unevaluated<'tcx, ()>, + uv: ty::Unevaluated<'tcx>, ) -> Result>, ErrorGuaranteed> { let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?; debug!("AbstractConst::new({:?}) = {:?}", uv, inner); diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 4bc821dcfa1..c2c6076e12b 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -81,7 +81,6 @@ pub fn from_opt_const_arg_anon_const( kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def: def.to_global(), substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), - promoted: (), }), ty, }), diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index 4550152804e..a04bdb1319e 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -1,7 +1,7 @@ use std::convert::TryInto; +use crate::mir; use crate::mir::interpret::{AllocId, ConstValue, Scalar}; -use crate::mir::Promoted; use crate::ty::subst::{InternalSubsts, SubstsRef}; use crate::ty::ParamEnv; use crate::ty::{self, TyCtxt, TypeVisitable}; @@ -12,13 +12,12 @@ use super::ScalarInt; -/// An unevaluated, potentially generic, constant. +/// An unevaluated (potentially generic) constant used in the type-system. #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)] #[derive(Hash, HashStable)] -pub struct Unevaluated<'tcx, P = Option> { +pub struct Unevaluated<'tcx> { pub def: ty::WithOptConstParam, pub substs: SubstsRef<'tcx>, - pub promoted: P, } impl rustc_errors::IntoDiagnosticArg for Unevaluated<'_> { @@ -29,23 +28,15 @@ fn into_diagnostic_arg(self) -> rustc_errors::DiagnosticArgValue<'static> { impl<'tcx> Unevaluated<'tcx> { #[inline] - pub fn shrink(self) -> Unevaluated<'tcx, ()> { - debug_assert_eq!(self.promoted, None); - Unevaluated { def: self.def, substs: self.substs, promoted: () } + pub fn expand(self) -> mir::Unevaluated<'tcx> { + mir::Unevaluated { def: self.def, substs: self.substs, promoted: None } } } -impl<'tcx> Unevaluated<'tcx, ()> { +impl<'tcx> Unevaluated<'tcx> { #[inline] - pub fn expand(self) -> Unevaluated<'tcx> { - Unevaluated { def: self.def, substs: self.substs, promoted: None } - } -} - -impl<'tcx, P: Default> Unevaluated<'tcx, P> { - #[inline] - pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> { - Unevaluated { def, substs, promoted: Default::default() } + pub fn new(def: ty::WithOptConstParam, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx> { + Unevaluated { def, substs } } } @@ -67,7 +58,7 @@ pub enum ConstKind<'tcx> { /// Used in the HIR by using `Unevaluated` everywhere and later normalizing to one of the other /// variants when the code is monomorphic enough for that. - Unevaluated(Unevaluated<'tcx, ()>), + Unevaluated(Unevaluated<'tcx>), /// Used to hold computed value. Value(ty::ValTree<'tcx>), @@ -185,8 +176,6 @@ fn try_eval_inner( if let ConstKind::Unevaluated(unevaluated) = self { use crate::mir::interpret::ErrorHandled; - assert_eq!(unevaluated.promoted, ()); - // HACK(eddyb) this erases lifetimes even though `const_eval_resolve` // also does later, but we want to do it before checking for // inference variables. @@ -207,7 +196,6 @@ fn try_eval_inner( tcx.param_env(unevaluated.def.did).and(ty::Unevaluated { def: unevaluated.def, substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did), - promoted: (), }) } else { param_env_and diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 98b8a7386fe..2c2acfa0697 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -313,7 +313,7 @@ fn add_const(&mut self, c: ty::Const<'_>) { } } - fn add_unevaluated_const

(&mut self, ct: ty::Unevaluated<'_, P>) { + fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'_>) { self.add_substs(ct.substs); self.add_flags(TypeFlags::HAS_CT_PROJECTION); } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index cac95e14a23..b921ae829e5 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -128,7 +128,11 @@ fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { c.super_fold_with(self) } - fn fold_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> { + fn fold_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ty::Unevaluated<'tcx> { + uv.super_fold_with(self) + } + + fn fold_mir_unevaluated(&mut self, uv: mir::Unevaluated<'tcx>) -> mir::Unevaluated<'tcx> { uv.super_fold_with(self) } @@ -172,13 +176,20 @@ fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result, Self c.try_super_fold_with(self) } - fn try_fold_unevaluated( + fn try_fold_ty_unevaluated( &mut self, c: ty::Unevaluated<'tcx>, ) -> Result, Self::Error> { c.try_super_fold_with(self) } + fn try_fold_mir_unevaluated( + &mut self, + c: mir::Unevaluated<'tcx>, + ) -> Result, Self::Error> { + c.try_super_fold_with(self) + } + fn try_fold_predicate( &mut self, p: ty::Predicate<'tcx>, @@ -225,11 +236,18 @@ fn try_fold_const(&mut self, c: ty::Const<'tcx>) -> Result, !> { Ok(self.fold_const(c)) } - fn try_fold_unevaluated( + fn try_fold_ty_unevaluated( &mut self, c: ty::Unevaluated<'tcx>, ) -> Result, !> { - Ok(self.fold_unevaluated(c)) + Ok(self.fold_ty_unevaluated(c)) + } + + fn try_fold_mir_unevaluated( + &mut self, + c: mir::Unevaluated<'tcx>, + ) -> Result, !> { + Ok(self.fold_mir_unevaluated(c)) } fn try_fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> Result, !> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 982aacc7686..6cc73f2561f 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -682,7 +682,7 @@ pub enum PredicateKind<'tcx> { Coerce(CoercePredicate<'tcx>), /// Constant initializer must evaluate successfully. - ConstEvaluatable(ty::Unevaluated<'tcx, ()>), + ConstEvaluatable(ty::Unevaluated<'tcx>), /// Constants must be equal. The first component is the const that is expected. ConstEquate(Const<'tcx>, Const<'tcx>), diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index b6cd5396b1d..6318fe679df 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -1201,9 +1201,7 @@ macro_rules! print_underscore { } match ct.kind() { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => { - assert_eq!(promoted, ()); - + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) => { match self.tcx().def_kind(def.did) { DefKind::Static(..) | DefKind::Const | DefKind::AssocConst => { p!(print_value_path(def.did, substs)) diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index 0d97d4acdfc..a56010146c0 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -621,11 +621,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( // While this is slightly incorrect, it shouldn't matter for `min_const_generics` // and is the better alternative to waiting until `generic_const_exprs` can // be stabilized. - (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) - if au.def == bu.def && au.promoted == bu.promoted => - { - assert_eq!(au.promoted, ()); - + (ty::ConstKind::Unevaluated(au), ty::ConstKind::Unevaluated(bu)) if au.def == bu.def => { let substs = relation.relate_with_variance( ty::Variance::Invariant, ty::VarianceDiagInfo::default(), @@ -633,11 +629,7 @@ pub fn super_relate_consts<'tcx, R: TypeRelation<'tcx>>( bu.substs, )?; return Ok(tcx.mk_const(ty::ConstS { - kind: ty::ConstKind::Unevaluated(ty::Unevaluated { - def: au.def, - substs, - promoted: (), - }), + kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def: au.def, substs }), ty: a.ty(), })); } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 004fcffdc40..9cabce5f82c 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -831,13 +831,13 @@ fn visit_with>(&self, _visitor: &mut V) -> ControlFlow TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { fn try_fold_with>(self, folder: &mut F) -> Result { - folder.try_fold_unevaluated(self) + folder.try_fold_ty_unevaluated(self) } } impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx> { fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - visitor.visit_unevaluated(*self) + visitor.visit_ty_unevaluated(*self) } } @@ -846,11 +846,7 @@ fn try_super_fold_with>( self, folder: &mut F, ) -> Result { - Ok(ty::Unevaluated { - def: self.def, - substs: self.substs.try_fold_with(folder)?, - promoted: self.promoted, - }) + Ok(ty::Unevaluated { def: self.def, substs: self.substs.try_fold_with(folder)? }) } } @@ -859,15 +855,3 @@ fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow self.substs.visit_with(visitor) } } - -impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx, ()> { - fn try_fold_with>(self, folder: &mut F) -> Result { - Ok(self.expand().try_fold_with(folder)?.shrink()) - } -} - -impl<'tcx> TypeVisitable<'tcx> for ty::Unevaluated<'tcx, ()> { - fn visit_with>(&self, visitor: &mut V) -> ControlFlow { - self.expand().visit_with(visitor) - } -} diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 5f8cb578202..7b913de83ac 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -199,7 +199,11 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { c.super_visit_with(self) } - fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + fn visit_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + uv.super_visit_with(self) + } + + fn visit_mir_unevaluated(&mut self, uv: mir::Unevaluated<'tcx>) -> ControlFlow { uv.super_visit_with(self) } @@ -597,7 +601,7 @@ fn visit_const(&mut self, c: ty::Const<'tcx>) -> ControlFlow { #[inline] #[instrument(level = "trace", ret)] - fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + fn visit_ty_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { let flags = FlagComputation::for_unevaluated_const(uv); trace!(r.flags=?flags); if flags.intersects(self.flags) { @@ -607,6 +611,16 @@ fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow) -> ControlFlow { + let flags = FlagComputation::for_unevaluated_const(uv.shrink()); + trace!(r.flags=?flags); + if flags.intersects(self.flags) { + ControlFlow::Break(FoundFlags) + } else { + ControlFlow::CONTINUE + } + } + #[inline] #[instrument(level = "trace", ret)] fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow { diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index c9bec130cc8..00fbdb42435 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -2,6 +2,7 @@ use crate::build::{parse_float_into_constval, Builder}; use rustc_ast as ast; +use rustc_middle::mir; use rustc_middle::mir::interpret::{ Allocation, ConstValue, LitToConstError, LitToConstInput, Scalar, }; @@ -66,7 +67,7 @@ pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> { }) }); - let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); + let uneval = mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); let literal = ConstantKind::Unevaluated(uneval, ty); Constant { user_ty, span, literal } @@ -79,7 +80,7 @@ pub(crate) fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> { Constant { user_ty: None, span, literal } } ExprKind::ConstBlock { did: def_id, substs } => { - let uneval = ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); + let uneval = mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs); let literal = ConstantKind::Unevaluated(uneval, ty); Constant { user_ty: None, span, literal } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 2885f06b19c..351c86b5d63 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -16,8 +16,8 @@ use rustc_index::vec::IndexVec; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{ - AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, Location, Operand, Place, - Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, + self, AssertKind, BinOp, Body, Constant, ConstantKind, Local, LocalDecl, Location, Operand, + Place, Rvalue, SourceInfo, SourceScope, SourceScopeData, Statement, StatementKind, Terminator, TerminatorKind, UnOp, RETURN_PLACE, }; use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; @@ -301,7 +301,7 @@ fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Opti let lint_only = match c.literal { ConstantKind::Ty(ct) => ct.needs_subst(), ConstantKind::Unevaluated( - ty::Unevaluated { def: _, substs: _, promoted: Some(_) }, + mir::Unevaluated { def: _, substs: _, promoted: Some(_) }, _, ) => { // Promoteds must lint and not error as the user didn't ask for them diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 71cab023215..a054bc67462 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -8,6 +8,7 @@ use rustc_hir::{def::DefKind, def_id::DefId, ConstContext}; use rustc_index::bit_set::FiniteBitSet; use rustc_middle::mir::{ + self, visit::{TyContext, Visitor}, Constant, ConstantKind, Local, LocalDecl, Location, }; @@ -299,11 +300,9 @@ fn visit_const(&mut self, c: Const<'tcx>) -> ControlFlow { self.unused_parameters.clear(param.index); ControlFlow::CONTINUE } - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs }) if matches!(self.tcx.def_kind(def.did), DefKind::AnonConst) => { - assert_eq!(promoted, ()); - self.visit_child_body(def.did, substs); ControlFlow::CONTINUE } @@ -318,7 +317,7 @@ fn visit_mir_const(&mut self, constant: ConstantKind<'tcx>) -> ControlFlow ct.visit_with(self), - ConstantKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p) }, _) + ConstantKind::Unevaluated(mir::Unevaluated { def, substs: _, promoted: Some(p) }, _) // Avoid considering `T` unused when constants are of the form: // `>::foo::promoted[p]` if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self => diff --git a/compiler/rustc_query_impl/src/keys.rs b/compiler/rustc_query_impl/src/keys.rs index 31de83ee141..046b3f405e9 100644 --- a/compiler/rustc_query_impl/src/keys.rs +++ b/compiler/rustc_query_impl/src/keys.rs @@ -276,7 +276,7 @@ fn default_span(&self, tcx: TyCtxt<'_>) -> Span { } } -impl<'tcx> Key for (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>) { +impl<'tcx> Key for (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>) { #[inline(always)] fn query_crate_is_local(&self) -> bool { (self.0).def.did.krate == LOCAL_CRATE diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index bcdfa4f12d3..6ed4f1b8c49 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -834,7 +834,7 @@ fn evaluate_nested_obligations( let reported = tcx.sess.emit_err(UnableToConstructConstantValue { span: tcx.def_span(def_id), - unevaluated: unevaluated.expand(), + unevaluated: unevaluated, }); Err(ErrorHandled::Reported(reported)) } diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 5a213987e87..37a0278f0b1 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -138,7 +138,7 @@ pub fn try_unify(&self, a: AbstractConst<'tcx>, b: AbstractConst<'tcx>) -> bool #[instrument(skip(tcx), level = "debug")] pub fn try_unify_abstract_consts<'tcx>( tcx: TyCtxt<'tcx>, - (a, b): (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>), + (a, b): (ty::Unevaluated<'tcx>, ty::Unevaluated<'tcx>), param_env: ty::ParamEnv<'tcx>, ) -> bool { (|| { @@ -161,7 +161,7 @@ pub fn try_unify_abstract_consts<'tcx>( #[instrument(skip(infcx), level = "debug")] pub fn is_const_evaluatable<'cx, 'tcx>( infcx: &InferCtxt<'cx, 'tcx>, - uv: ty::Unevaluated<'tcx, ()>, + uv: ty::Unevaluated<'tcx>, param_env: ty::ParamEnv<'tcx>, span: Span, ) -> Result<(), NotConstEvaluatable> { diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index a54b725753c..163c5f2c089 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -838,7 +838,10 @@ fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { } } - fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow { + fn visit_ty_unevaluated( + &mut self, + uv: ty::Unevaluated<'tcx>, + ) -> ControlFlow { // Constants can only influence object safety if they reference `Self`. // This is only possible for unevaluated constants, so we walk these here. // @@ -852,7 +855,7 @@ fn visit_unevaluated(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow self.visit_const(leaf), Node::Cast(_, _, ty) => self.visit_ty(ty), diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index afc8a9600ad..359a79e9979 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -2393,7 +2393,6 @@ fn visit_anon_const(&mut self, c: &'tcx hir::AnonConst) { let def_id = self.tcx.hir().local_def_id(c.hir_id); let ct = ty::Const::from_anon_const(self.tcx, def_id); if let ty::ConstKind::Unevaluated(uv) = ct.kind() { - assert_eq!(uv.promoted, ()); let span = self.tcx.hir().span(c.hir_id); self.preds.insert(( ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv)) diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 3eaedaf1083..af0b300e22b 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -234,8 +234,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol { pub(crate) fn print_const(cx: &DocContext<'_>, n: ty::Const<'_>) -> String { match n.kind() { - ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => { - assert_eq!(promoted, ()); + ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _ }) => { let s = if let Some(def) = def.as_local() { print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(def.did)) } else { diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs index 72c86f28bbc..85024b0b05c 100644 --- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs +++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs @@ -195,7 +195,7 @@ fn is_value_unfrozen_expr<'tcx>(cx: &LateContext<'tcx>, hir_id: HirId, def_id: D let result = cx.tcx.const_eval_resolve( cx.param_env, - ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), + mir::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs), None, ); is_value_unfrozen_raw(cx, result, ty) diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 1b8a9c05559..ac5bac3714f 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -424,7 +424,7 @@ fn fetch_path(&mut self, qpath: &QPath<'_>, id: HirId, ty: Ty<'tcx>) -> Option