Skip to content

Commit 6e4779a

Browse files
committed
make the eval() functions on our const types return the resulting value
1 parent e5fedce commit 6e4779a

File tree

16 files changed

+169
-247
lines changed

16 files changed

+169
-247
lines changed

compiler/rustc_codegen_cranelift/src/base.rs

+2-5
Original file line numberDiff line numberDiff line change
@@ -723,11 +723,8 @@ fn codegen_stmt<'tcx>(
723723
}
724724
Rvalue::Repeat(ref operand, times) => {
725725
let operand = codegen_operand(fx, operand);
726-
let times = fx
727-
.monomorphize(times)
728-
.eval(fx.tcx, ParamEnv::reveal_all())
729-
.try_to_bits(fx.tcx.data_layout.pointer_size)
730-
.unwrap();
726+
let times =
727+
fx.monomorphize(times).eval_target_usize(fx.tcx, ParamEnv::reveal_all());
731728
if operand.layout().size.bytes() == 0 {
732729
// Do nothing for ZST's
733730
} else if fx.clif_type(operand.layout().ty) == Some(types::I8) {

compiler/rustc_codegen_cranelift/src/constant.rs

+4-26
Original file line numberDiff line numberDiff line change
@@ -77,31 +77,9 @@ pub(crate) fn eval_mir_constant<'tcx>(
7777
fx: &FunctionCx<'_, '_, 'tcx>,
7878
constant: &Constant<'tcx>,
7979
) -> Option<(ConstValue<'tcx>, Ty<'tcx>)> {
80-
let constant_kind = fx.monomorphize(constant.literal);
81-
let uv = match constant_kind {
82-
ConstantKind::Ty(const_) => match const_.kind() {
83-
ty::ConstKind::Unevaluated(uv) => uv.expand(),
84-
ty::ConstKind::Value(val) => {
85-
return Some((fx.tcx.valtree_to_const_val((const_.ty(), val)), const_.ty()));
86-
}
87-
err => span_bug!(
88-
constant.span,
89-
"encountered bad ConstKind after monomorphizing: {:?}",
90-
err
91-
),
92-
},
93-
ConstantKind::Unevaluated(mir::UnevaluatedConst { def, .. }, _)
94-
if fx.tcx.is_static(def) =>
95-
{
96-
span_bug!(constant.span, "MIR constant refers to static");
97-
}
98-
ConstantKind::Unevaluated(uv, _) => uv,
99-
ConstantKind::Val(val, _) => return Some((val, constant_kind.ty())),
100-
};
101-
102-
let val = fx
103-
.tcx
104-
.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None)
80+
let cv = fx.monomorphize(constant.literal);
81+
let val = cv
82+
.eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(constant.span))
10583
.map_err(|err| match err {
10684
ErrorHandled::Reported(_) => {
10785
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
@@ -111,7 +89,7 @@ pub(crate) fn eval_mir_constant<'tcx>(
11189
}
11290
})
11391
.ok();
114-
val.map(|val| (val, constant_kind.ty()))
92+
val.map(|val| (val, cv.ty()))
11593
}
11694

11795
pub(crate) fn codegen_constant_operand<'tcx>(

compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -670,10 +670,8 @@ fn push_const_param<'tcx>(tcx: TyCtxt<'tcx>, ct: ty::Const<'tcx>, output: &mut S
670670
// avoiding collisions and will make the emitted type names shorter.
671671
let hash_short = tcx.with_stable_hashing_context(|mut hcx| {
672672
let mut hasher = StableHasher::new();
673-
let ct = ct.eval(tcx, ty::ParamEnv::reveal_all());
674-
hcx.while_hashing_spans(false, |hcx| {
675-
ct.to_valtree().hash_stable(hcx, &mut hasher)
676-
});
673+
let ct = ct.eval(tcx, ty::ParamEnv::reveal_all(), None).unwrap();
674+
hcx.while_hashing_spans(false, |hcx| ct.hash_stable(hcx, &mut hasher));
677675
hasher.finish::<Hash64>()
678676
});
679677

compiler/rustc_codegen_ssa/src/mir/constant.rs

+20-32
Original file line numberDiff line numberDiff line change
@@ -24,43 +24,31 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
2424
&self,
2525
constant: &mir::Constant<'tcx>,
2626
) -> Result<ConstValue<'tcx>, ErrorHandled> {
27-
let ct = self.monomorphize(constant.literal);
28-
let uv = match ct {
29-
mir::ConstantKind::Ty(ct) => match ct.kind() {
30-
ty::ConstKind::Unevaluated(uv) => uv.expand(),
31-
ty::ConstKind::Value(val) => {
32-
return Ok(self.cx.tcx().valtree_to_const_val((ct.ty(), val)));
27+
self.monomorphize(constant.literal)
28+
.eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span))
29+
.map_err(|err| {
30+
match err {
31+
ErrorHandled::Reported(_) => {
32+
self.cx
33+
.tcx()
34+
.sess
35+
.emit_err(errors::ErroneousConstant { span: constant.span });
36+
}
37+
ErrorHandled::TooGeneric => {
38+
self.cx.tcx().sess.diagnostic().emit_bug(
39+
errors::PolymorphicConstantTooGeneric { span: constant.span },
40+
);
41+
}
3342
}
34-
err => span_bug!(
35-
constant.span,
36-
"encountered bad ConstKind after monomorphizing: {:?}",
37-
err
38-
),
39-
},
40-
mir::ConstantKind::Unevaluated(uv, _) => uv,
41-
mir::ConstantKind::Val(val, _) => return Ok(val),
42-
};
43-
44-
self.cx.tcx().const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None).map_err(|err| {
45-
match err {
46-
ErrorHandled::Reported(_) => {
47-
self.cx.tcx().sess.emit_err(errors::ErroneousConstant { span: constant.span });
48-
}
49-
ErrorHandled::TooGeneric => {
50-
self.cx
51-
.tcx()
52-
.sess
53-
.diagnostic()
54-
.emit_bug(errors::PolymorphicConstantTooGeneric { span: constant.span });
55-
}
56-
}
57-
err
58-
})
43+
err
44+
})
5945
}
6046

6147
/// This is a convenience helper for `simd_shuffle_indices`. It has the precondition
6248
/// that the given `constant` is an `ConstantKind::Unevaluated` and must be convertible to
6349
/// a `ValTree`. If you want a more general version of this, talk to `wg-const-eval` on zulip.
50+
///
51+
/// Note that this function is cursed, since usually MIR consts should not be evaluated to valtrees!
6452
pub fn eval_unevaluated_mir_constant_to_valtree(
6553
&self,
6654
constant: &mir::Constant<'tcx>,
@@ -80,7 +68,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
8068
// `simd_shuffle` call without wrapping the constant argument in a `const {}` block, but
8169
// the user pass through arbitrary expressions.
8270
// FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a real
83-
// const generic.
71+
// const generic, and get rid of this entire function.
8472
other => span_bug!(constant.span, "{other:#?}"),
8573
};
8674
let uv = self.monomorphize(uv);

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

+2
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,8 @@ TrivialTypeTraversalAndLiftImpls! { ErrorHandled }
7171

7272
pub type EvalToAllocationRawResult<'tcx> = Result<ConstAlloc<'tcx>, ErrorHandled>;
7373
pub type EvalToConstValueResult<'tcx> = Result<ConstValue<'tcx>, ErrorHandled>;
74+
/// `Ok(None)` indicates the constant was fine, but the valtree couldn't be constructed.
75+
/// This is needed in `thir::pattern::lower_inline_const`.
7476
pub type EvalToValTreeResult<'tcx> = Result<Option<ValTree<'tcx>>, ErrorHandled>;
7577

7678
pub fn struct_error<'tcx>(

compiler/rustc_middle/src/mir/mod.rs

+56-41
Original file line numberDiff line numberDiff line change
@@ -2342,29 +2342,39 @@ impl<'tcx> ConstantKind<'tcx> {
23422342
}
23432343

23442344
#[inline]
2345-
pub fn eval(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
2346-
match self {
2347-
Self::Ty(c) => {
2348-
if let Some(val) = c.try_eval_for_mir(tcx, param_env) {
2349-
match val {
2350-
Ok(val) => Self::Val(val, c.ty()),
2351-
Err(guar) => Self::Ty(ty::Const::new_error(tcx, guar, self.ty())),
2352-
}
2345+
pub fn eval(
2346+
self,
2347+
tcx: TyCtxt<'tcx>,
2348+
param_env: ty::ParamEnv<'tcx>,
2349+
span: Option<Span>,
2350+
) -> Result<interpret::ConstValue<'tcx>, ErrorHandled> {
2351+
let uneval = match self {
2352+
ConstantKind::Ty(c) => {
2353+
if let ty::ConstKind::Unevaluated(uv) = c.kind() {
2354+
// Avoid the round-trip via valtree, evaluate directly to ConstValue.
2355+
uv.expand()
23532356
} else {
2354-
self
2357+
// It's already a valtree, or an error.
2358+
let val = c.eval(tcx, param_env, span)?;
2359+
return Ok(tcx.valtree_to_const_val((self.ty(), val)));
23552360
}
23562361
}
2357-
Self::Val(_, _) => self,
2358-
Self::Unevaluated(uneval, ty) => {
2359-
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
2360-
match tcx.const_eval_resolve(param_env, uneval, None) {
2361-
Ok(val) => Self::Val(val, ty),
2362-
Err(ErrorHandled::TooGeneric) => self,
2363-
Err(ErrorHandled::Reported(guar)) => {
2364-
Self::Ty(ty::Const::new_error(tcx, guar.into(), ty))
2365-
}
2366-
}
2362+
ConstantKind::Unevaluated(uneval, _) => uneval,
2363+
ConstantKind::Val(val, _) => return Ok(val),
2364+
};
2365+
// FIXME: We might want to have a `try_eval`-like function on `Unevaluated`
2366+
tcx.const_eval_resolve(param_env, uneval, span)
2367+
}
2368+
2369+
/// Normalizes the constant to a value or an error if possible.
2370+
#[inline]
2371+
pub fn normalize(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Self {
2372+
match self.eval(tcx, param_env, None) {
2373+
Ok(val) => Self::Val(val, self.ty()),
2374+
Err(ErrorHandled::Reported(guar)) => {
2375+
Self::Ty(ty::Const::new_error(tcx, guar.into(), self.ty()))
23672376
}
2377+
Err(ErrorHandled::TooGeneric) => self,
23682378
}
23692379
}
23702380

@@ -2406,35 +2416,35 @@ impl<'tcx> ConstantKind<'tcx> {
24062416
}
24072417

24082418
#[inline]
2409-
pub fn try_eval_bool(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> {
2410-
match self {
2411-
Self::Ty(ct) => ct.try_eval_bool(tcx, param_env),
2412-
Self::Val(val, _) => val.try_to_bool(),
2413-
Self::Unevaluated(uneval, _) => {
2414-
match tcx.const_eval_resolve(param_env, *uneval, None) {
2415-
Ok(val) => val.try_to_bool(),
2416-
Err(_) => None,
2417-
}
2418-
}
2419-
}
2419+
pub fn try_eval_scalar(
2420+
self,
2421+
tcx: TyCtxt<'tcx>,
2422+
param_env: ty::ParamEnv<'tcx>,
2423+
) -> Option<Scalar> {
2424+
self.eval(tcx, param_env, None).ok()?.try_to_scalar()
2425+
}
2426+
2427+
#[inline]
2428+
pub fn try_eval_scalar_int(
2429+
self,
2430+
tcx: TyCtxt<'tcx>,
2431+
param_env: ty::ParamEnv<'tcx>,
2432+
) -> Option<ScalarInt> {
2433+
self.try_eval_scalar(tcx, param_env)?.try_to_int().ok()
2434+
}
2435+
2436+
#[inline]
2437+
pub fn try_eval_bool(self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Option<bool> {
2438+
self.try_eval_scalar_int(tcx, param_env)?.try_into().ok()
24202439
}
24212440

24222441
#[inline]
24232442
pub fn try_eval_target_usize(
2424-
&self,
2443+
self,
24252444
tcx: TyCtxt<'tcx>,
24262445
param_env: ty::ParamEnv<'tcx>,
24272446
) -> Option<u64> {
2428-
match self {
2429-
Self::Ty(ct) => ct.try_eval_target_usize(tcx, param_env),
2430-
Self::Val(val, _) => val.try_to_target_usize(tcx),
2431-
Self::Unevaluated(uneval, _) => {
2432-
match tcx.const_eval_resolve(param_env, *uneval, None) {
2433-
Ok(val) => val.try_to_target_usize(tcx),
2434-
Err(_) => None,
2435-
}
2436-
}
2437-
}
2447+
self.try_eval_scalar_int(tcx, param_env)?.try_to_target_usize(tcx).ok()
24382448
}
24392449

24402450
#[inline]
@@ -2610,6 +2620,11 @@ impl<'tcx> UnevaluatedConst<'tcx> {
26102620
pub fn new(def: DefId, args: GenericArgsRef<'tcx>) -> UnevaluatedConst<'tcx> {
26112621
UnevaluatedConst { def, args, promoted: Default::default() }
26122622
}
2623+
2624+
#[inline]
2625+
pub fn from_instance(instance: ty::Instance<'tcx>) -> Self {
2626+
UnevaluatedConst::new(instance.def_id(), instance.args)
2627+
}
26132628
}
26142629

26152630
/// A collection of projections into user types.

0 commit comments

Comments
 (0)