Skip to content

Commit 9a963e3

Browse files
committed
Auto merge of #102056 - b-naber:unevaluated, r=lcnr
Introduce mir::Unevaluated Previously the distinction between unevaluated constants in the type-system and in mir was not explicit and a little confusing. Probably better to introduce its own type for that. r? `@lcnr`
2 parents 4d44e09 + a705e65 commit 9a963e3

File tree

38 files changed

+220
-156
lines changed

38 files changed

+220
-156
lines changed

compiler/rustc_codegen_cranelift/src/constant.rs

+2-11
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
55
use rustc_middle::mir::interpret::{
66
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
77
};
8-
use rustc_middle::ty::ConstKind;
98
use rustc_span::DUMMY_SP;
109

1110
use cranelift_codegen::ir::GlobalValueData;
@@ -42,15 +41,7 @@ pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
4241
let mut all_constants_ok = true;
4342
for constant in &fx.mir.required_consts {
4443
let unevaluated = match fx.monomorphize(constant.literal) {
45-
ConstantKind::Ty(ct) => match ct.kind() {
46-
ConstKind::Unevaluated(uv) => uv.expand(),
47-
ConstKind::Value(_) => continue,
48-
ConstKind::Param(_)
49-
| ConstKind::Infer(_)
50-
| ConstKind::Bound(_, _)
51-
| ConstKind::Placeholder(_)
52-
| ConstKind::Error(_) => unreachable!("{:?}", ct),
53-
},
44+
ConstantKind::Ty(_) => unreachable!(),
5445
ConstantKind::Unevaluated(uv, _) => uv,
5546
ConstantKind::Val(..) => continue,
5647
};
@@ -118,7 +109,7 @@ pub(crate) fn codegen_constant<'tcx>(
118109
) -> CValue<'tcx> {
119110
let (const_val, ty) = match fx.monomorphize(constant.literal) {
120111
ConstantKind::Ty(const_) => unreachable!("{:?}", const_),
121-
ConstantKind::Unevaluated(ty::Unevaluated { def, substs, promoted }, ty)
112+
ConstantKind::Unevaluated(mir::UnevaluatedConst { def, substs, promoted }, ty)
122113
if fx.tcx.is_static(def.did) =>
123114
{
124115
assert!(substs.is_empty());

compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs

+6-12
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use rustc_errors::ErrorGuaranteed;
66
use rustc_hir::LangItem;
77
use rustc_infer::infer::TyCtxtInferExt;
8+
use rustc_middle::mir;
89
use rustc_middle::mir::*;
910
use rustc_middle::ty::{self, subst::SubstsRef, AdtDef, Ty};
1011
use rustc_span::DUMMY_SP;
@@ -350,29 +351,22 @@ where
350351
// FIXME(valtrees): check whether const qualifs should behave the same
351352
// way for type and mir constants.
352353
let uneval = match constant.literal {
353-
ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Unevaluated(_)) => {
354-
let ty::ConstKind::Unevaluated(uv) = ct.kind() else { unreachable!() };
355-
356-
Some(uv.expand())
357-
}
358-
ConstantKind::Ty(_) => None,
354+
ConstantKind::Ty(ct) if matches!(ct.kind(), ty::ConstKind::Param(_)) => None,
355+
ConstantKind::Ty(c) => bug!("expected ConstKind::Param here, found {:?}", c),
359356
ConstantKind::Unevaluated(uv, _) => Some(uv),
360357
ConstantKind::Val(..) => None,
361358
};
362359

363-
if let Some(ty::Unevaluated { def, substs: _, promoted }) = uneval {
360+
if let Some(mir::UnevaluatedConst { def, substs: _, promoted }) = uneval {
364361
// Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
365362
// only for `NeedsNonConstDrop` with precise drop checking. This is the only const
366363
// check performed after the promotion. Verify that with an assertion.
367364
assert!(promoted.is_none() || Q::ALLOW_PROMOTED);
368365

369366
// Don't peek inside trait associated constants.
370367
if promoted.is_none() && cx.tcx.trait_of_item(def.did).is_none() {
371-
let qualifs = if let Some((did, param_did)) = def.as_const_arg() {
372-
cx.tcx.at(constant.span).mir_const_qualif_const_arg((did, param_did))
373-
} else {
374-
cx.tcx.at(constant.span).mir_const_qualif(def.did)
375-
};
368+
assert_eq!(def.const_param_did, None, "expected associated const: {def:?}");
369+
let qualifs = cx.tcx.at(constant.span).mir_const_qualif(def.did);
376370

377371
if !Q::in_qualifs(&qualifs) {
378372
return false;

compiler/rustc_const_eval/src/transform/promote_consts.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
//! move analysis runs after promotion on broken MIR.
1414
1515
use rustc_hir as hir;
16+
use rustc_middle::mir;
1617
use rustc_middle::mir::traversal::ReversePostorderIter;
1718
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
1819
use rustc_middle::mir::*;
@@ -840,7 +841,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
840841
promoted.span = span;
841842
promoted.local_decls[RETURN_PLACE] = LocalDecl::new(ty, span);
842843
let substs = tcx.erase_regions(InternalSubsts::identity_for_item(tcx, def.did));
843-
let uneval = ty::Unevaluated { def, substs, promoted: Some(promoted_id) };
844+
let uneval = mir::UnevaluatedConst { def, substs, promoted: Some(promoted_id) };
844845

845846
Operand::Constant(Box::new(Constant {
846847
span,

compiler/rustc_infer/src/infer/combine.rs

+4-8
Original file line numberDiff line numberDiff line change
@@ -734,9 +734,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
734734
}
735735
}
736736
}
737-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
738-
assert_eq!(promoted, ());
739-
737+
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
740738
let substs = self.relate_with_variance(
741739
ty::Variance::Invariant,
742740
ty::VarianceDiagInfo::default(),
@@ -745,7 +743,7 @@ impl<'tcx> TypeRelation<'tcx> for Generalizer<'_, 'tcx> {
745743
)?;
746744
Ok(self.tcx().mk_const(ty::ConstS {
747745
ty: c.ty(),
748-
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
746+
kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }),
749747
}))
750748
}
751749
_ => relate::super_relate_consts(self, c, c),
@@ -949,9 +947,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
949947
}
950948
}
951949
}
952-
ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }) => {
953-
assert_eq!(promoted, ());
954-
950+
ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }) => {
955951
let substs = self.relate_with_variance(
956952
ty::Variance::Invariant,
957953
ty::VarianceDiagInfo::default(),
@@ -961,7 +957,7 @@ impl<'tcx> TypeRelation<'tcx> for ConstInferUnifier<'_, 'tcx> {
961957

962958
Ok(self.tcx().mk_const(ty::ConstS {
963959
ty: c.ty(),
964-
kind: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
960+
kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst { def, substs }),
965961
}))
966962
}
967963
_ => relate::super_relate_consts(self, c, c),

compiler/rustc_infer/src/infer/mod.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -705,8 +705,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
705705
#[instrument(skip(self), level = "debug")]
706706
pub fn try_unify_abstract_consts(
707707
&self,
708-
a: ty::Unevaluated<'tcx, ()>,
709-
b: ty::Unevaluated<'tcx, ()>,
708+
a: ty::UnevaluatedConst<'tcx>,
709+
b: ty::UnevaluatedConst<'tcx>,
710710
param_env: ty::ParamEnv<'tcx>,
711711
) -> bool {
712712
// Reject any attempt to unify two unevaluated constants that contain inference
@@ -1690,7 +1690,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16901690
pub fn try_const_eval_resolve(
16911691
&self,
16921692
param_env: ty::ParamEnv<'tcx>,
1693-
unevaluated: ty::Unevaluated<'tcx, ()>,
1693+
unevaluated: ty::UnevaluatedConst<'tcx>,
16941694
ty: Ty<'tcx>,
16951695
span: Option<Span>,
16961696
) -> Result<ty::Const<'tcx>, ErrorHandled> {
@@ -1725,7 +1725,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17251725
pub fn const_eval_resolve(
17261726
&self,
17271727
mut param_env: ty::ParamEnv<'tcx>,
1728-
unevaluated: ty::Unevaluated<'tcx, ()>,
1728+
unevaluated: ty::UnevaluatedConst<'tcx>,
17291729
span: Option<Span>,
17301730
) -> EvalToValTreeResult<'tcx> {
17311731
let mut substs = self.resolve_vars_if_possible(unevaluated.substs);
@@ -1756,8 +1756,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17561756
debug!(?param_env_erased);
17571757
debug!(?substs_erased);
17581758

1759-
let unevaluated =
1760-
ty::Unevaluated { def: unevaluated.def, substs: substs_erased, promoted: () };
1759+
let unevaluated = ty::UnevaluatedConst { def: unevaluated.def, substs: substs_erased };
17611760

17621761
// The return value is the evaluated value which doesn't contain any reference to inference
17631762
// variables, thus we don't need to substitute back the original values.

compiler/rustc_middle/src/mir/interpret/queries.rs

+7-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ impl<'tcx> TyCtxt<'tcx> {
3636
pub fn const_eval_resolve(
3737
self,
3838
param_env: ty::ParamEnv<'tcx>,
39-
ct: ty::Unevaluated<'tcx>,
39+
ct: mir::UnevaluatedConst<'tcx>,
4040
span: Option<Span>,
4141
) -> EvalToConstValueResult<'tcx> {
4242
// Cannot resolve `Unevaluated` constants that contain inference
@@ -49,7 +49,11 @@ impl<'tcx> TyCtxt<'tcx> {
4949
bug!("did not expect inference variables here");
5050
}
5151

52-
match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
52+
match ty::Instance::resolve_opt_const_arg(
53+
self, param_env,
54+
// FIXME: maybe have a seperate version for resolving mir::UnevaluatedConst?
55+
ct.def, ct.substs,
56+
) {
5357
Ok(Some(instance)) => {
5458
let cid = GlobalId { instance, promoted: ct.promoted };
5559
self.const_eval_global_id(param_env, cid, span)
@@ -63,7 +67,7 @@ impl<'tcx> TyCtxt<'tcx> {
6367
pub fn const_eval_resolve_for_typeck(
6468
self,
6569
param_env: ty::ParamEnv<'tcx>,
66-
ct: ty::Unevaluated<'tcx, ()>,
70+
ct: ty::UnevaluatedConst<'tcx>,
6771
span: Option<Span>,
6872
) -> EvalToValTreeResult<'tcx> {
6973
// Cannot resolve `Unevaluated` constants that contain inference

compiler/rustc_middle/src/mir/mod.rs

+32-5
Original file line numberDiff line numberDiff line change
@@ -2055,7 +2055,7 @@ pub enum ConstantKind<'tcx> {
20552055
Ty(ty::Const<'tcx>),
20562056

20572057
/// An unevaluated mir constant which is not part of the type system.
2058-
Unevaluated(ty::Unevaluated<'tcx, Option<Promoted>>, Ty<'tcx>),
2058+
Unevaluated(UnevaluatedConst<'tcx>, Ty<'tcx>),
20592059

20602060
/// This constant cannot go back into the type system, as it represents
20612061
/// something the type system cannot handle (e.g. pointers).
@@ -2315,12 +2315,11 @@ impl<'tcx> ConstantKind<'tcx> {
23152315
ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty })
23162316
.substs;
23172317

2318-
let uneval = ty::Unevaluated {
2318+
let uneval = UnevaluatedConst {
23192319
def: ty::WithOptConstParam::unknown(def_id).to_global(),
23202320
substs,
23212321
promoted: None,
23222322
};
2323-
23242323
debug_assert!(!uneval.has_free_regions());
23252324

23262325
Self::Unevaluated(uneval, ty)
@@ -2404,7 +2403,7 @@ impl<'tcx> ConstantKind<'tcx> {
24042403

24052404
let hir_id = tcx.hir().local_def_id_to_hir_id(def.did);
24062405
let span = tcx.hir().span(hir_id);
2407-
let uneval = ty::Unevaluated::new(def.to_global(), substs);
2406+
let uneval = UnevaluatedConst::new(def.to_global(), substs);
24082407
debug!(?span, ?param_env);
24092408

24102409
match tcx.const_eval_resolve(param_env, uneval, Some(span)) {
@@ -2417,7 +2416,7 @@ impl<'tcx> ConstantKind<'tcx> {
24172416
// Error was handled in `const_eval_resolve`. Here we just create a
24182417
// new unevaluated const and error hard later in codegen
24192418
Self::Unevaluated(
2420-
ty::Unevaluated {
2419+
UnevaluatedConst {
24212420
def: def.to_global(),
24222421
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
24232422
promoted: None,
@@ -2440,6 +2439,34 @@ impl<'tcx> ConstantKind<'tcx> {
24402439
}
24412440
}
24422441

2442+
/// An unevaluated (potentially generic) constant used in MIR.
2443+
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
2444+
#[derive(Hash, HashStable)]
2445+
pub struct UnevaluatedConst<'tcx> {
2446+
pub def: ty::WithOptConstParam<DefId>,
2447+
pub substs: SubstsRef<'tcx>,
2448+
pub promoted: Option<Promoted>,
2449+
}
2450+
2451+
impl<'tcx> UnevaluatedConst<'tcx> {
2452+
// FIXME: probably should get rid of this method. It's also wrong to
2453+
// shrink and then later expand a promoted.
2454+
#[inline]
2455+
pub fn shrink(self) -> ty::UnevaluatedConst<'tcx> {
2456+
ty::UnevaluatedConst { def: self.def, substs: self.substs }
2457+
}
2458+
}
2459+
2460+
impl<'tcx> UnevaluatedConst<'tcx> {
2461+
#[inline]
2462+
pub fn new(
2463+
def: ty::WithOptConstParam<DefId>,
2464+
substs: SubstsRef<'tcx>,
2465+
) -> UnevaluatedConst<'tcx> {
2466+
UnevaluatedConst { def, substs, promoted: Default::default() }
2467+
}
2468+
}
2469+
24432470
/// A collection of projections into user types.
24442471
///
24452472
/// They are projections because a binding can occur a part of a

compiler/rustc_middle/src/mir/pretty.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,9 @@ impl<'tcx> Visitor<'tcx> for ExtraComments<'tcx> {
466466
ty::ConstKind::Param(p) => format!("Param({})", p),
467467
ty::ConstKind::Unevaluated(uv) => {
468468
format!(
469-
"Unevaluated({}, {:?}, {:?})",
469+
"Unevaluated({}, {:?})",
470470
self.tcx.def_path_str(uv.def.did),
471471
uv.substs,
472-
uv.promoted,
473472
)
474473
}
475474
ty::ConstKind::Value(val) => format!("Value({})", fmt_valtree(&val)),

compiler/rustc_middle/src/mir/type_foldable.rs

+20
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use rustc_ast::InlineAsmTemplatePiece;
44

55
use super::*;
6+
use crate::mir;
67
use crate::ty;
78

89
TrivialTypeTraversalAndLiftImpls! {
@@ -50,6 +51,25 @@ impl<'tcx, R: Idx, C: Idx> TypeFoldable<'tcx> for BitMatrix<R, C> {
5051
}
5152
}
5253

54+
impl<'tcx> TypeFoldable<'tcx> for mir::UnevaluatedConst<'tcx> {
55+
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {
56+
folder.try_fold_mir_unevaluated(self)
57+
}
58+
}
59+
60+
impl<'tcx> TypeSuperFoldable<'tcx> for mir::UnevaluatedConst<'tcx> {
61+
fn try_super_fold_with<F: FallibleTypeFolder<'tcx>>(
62+
self,
63+
folder: &mut F,
64+
) -> Result<Self, F::Error> {
65+
Ok(mir::UnevaluatedConst {
66+
def: self.def,
67+
substs: self.substs.try_fold_with(folder)?,
68+
promoted: self.promoted,
69+
})
70+
}
71+
}
72+
5373
impl<'tcx> TypeFoldable<'tcx> for ConstantKind<'tcx> {
5474
#[inline(always)]
5575
fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> {

compiler/rustc_middle/src/mir/type_visitable.rs

+13
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,26 @@
11
//! `TypeVisitable` implementations for MIR types
22
33
use super::*;
4+
use crate::mir;
45

56
impl<'tcx, R: Idx, C: Idx> TypeVisitable<'tcx> for BitMatrix<R, C> {
67
fn visit_with<V: TypeVisitor<'tcx>>(&self, _: &mut V) -> ControlFlow<V::BreakTy> {
78
ControlFlow::CONTINUE
89
}
910
}
1011

12+
impl<'tcx> TypeVisitable<'tcx> for mir::UnevaluatedConst<'tcx> {
13+
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
14+
visitor.visit_mir_unevaluated(*self)
15+
}
16+
}
17+
18+
impl<'tcx> TypeSuperVisitable<'tcx> for mir::UnevaluatedConst<'tcx> {
19+
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
20+
self.substs.visit_with(visitor)
21+
}
22+
}
23+
1124
impl<'tcx> TypeVisitable<'tcx> for ConstantKind<'tcx> {
1225
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
1326
visitor.visit_mir_const(*self)

compiler/rustc_middle/src/query/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -381,7 +381,7 @@ rustc_queries! {
381381
}
382382

383383
query try_unify_abstract_consts(key:
384-
ty::ParamEnvAnd<'tcx, (ty::Unevaluated<'tcx, ()>, ty::Unevaluated<'tcx, ()>
384+
ty::ParamEnvAnd<'tcx, (ty::UnevaluatedConst<'tcx>, ty::UnevaluatedConst<'tcx>
385385
)>) -> bool {
386386
desc {
387387
|tcx| "trying to unify the generic constants {} and {}",

compiler/rustc_middle/src/ty/abstract_const.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ pub struct AbstractConst<'tcx> {
3030
impl<'tcx> AbstractConst<'tcx> {
3131
pub fn new(
3232
tcx: TyCtxt<'tcx>,
33-
uv: ty::Unevaluated<'tcx, ()>,
33+
uv: ty::UnevaluatedConst<'tcx>,
3434
) -> Result<Option<AbstractConst<'tcx>>, ErrorGuaranteed> {
3535
let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
3636
debug!("AbstractConst::new({:?}) = {:?}", uv, inner);

compiler/rustc_middle/src/ty/consts.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,9 @@ impl<'tcx> Const<'tcx> {
7878
match Self::try_eval_lit_or_param(tcx, ty, expr) {
7979
Some(v) => v,
8080
None => tcx.mk_const(ty::ConstS {
81-
kind: ty::ConstKind::Unevaluated(ty::Unevaluated {
81+
kind: ty::ConstKind::Unevaluated(ty::UnevaluatedConst {
8282
def: def.to_global(),
8383
substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
84-
promoted: (),
8584
}),
8685
ty,
8786
}),

0 commit comments

Comments
 (0)