Skip to content

Commit 0ae715c

Browse files
committed
Auto merge of rust-lang#115748 - RalfJung:post-mono, r=<try>
move required_consts check to general post-mono-check function I was hoping this would simplify the code. That didn't entirely happen, but I still think it could be useful to have a single place for the "required const" check -- and this does simplify some code in codegen, where the const-eval functions no longer have to return a `Result`. Also this is in preparation for another post-mono check that will be needed for (the current hackfix for) rust-lang#115709: ensuring that all locals are dynamically sized. I didn't expect this to change diagnostics, but the changes seem either harmless (for the cycle errors) or improvements (where more spans are shown when something goes wrong in a constant). r? `@oli-obk`
2 parents 5d62ab8 + e0b833e commit 0ae715c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

54 files changed

+468
-526
lines changed

compiler/rustc_codegen_cranelift/src/base.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
33
use rustc_ast::InlineAsmOptions;
44
use rustc_index::IndexVec;
5+
use rustc_middle::mir::interpret::ErrorHandled;
56
use rustc_middle::ty::adjustment::PointerCoercion;
67
use rustc_middle::ty::layout::FnAbiOf;
78
use rustc_middle::ty::print::with_no_trimmed_paths;
@@ -250,12 +251,21 @@ pub(crate) fn verify_func(
250251
}
251252

252253
fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
253-
if !crate::constant::check_constants(fx) {
254-
fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
255-
fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
256-
// compilation should have been aborted
257-
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
258-
return;
254+
match fx.mir.post_mono_checks(fx.tcx, ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c))) {
255+
Ok(()) => {}
256+
Err(ErrorHandled::TooGeneric(span)) => {
257+
span_bug!(span, "codegen encountered polymorphic constant");
258+
}
259+
Err(ErrorHandled::Reported(info, span)) => {
260+
if !info.is_tainted_by_errors() {
261+
fx.tcx.sess.span_err(span, "erroneous constant encountered");
262+
}
263+
fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
264+
fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
265+
// compilation should have been aborted
266+
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
267+
return;
268+
}
259269
}
260270

261271
let arg_uninhabited = fx
@@ -723,11 +733,7 @@ fn codegen_stmt<'tcx>(
723733
}
724734
Rvalue::Repeat(ref operand, times) => {
725735
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();
736+
let times = fx.monomorphize(times).try_to_target_usize(fx.tcx).unwrap();
731737
if operand.layout().size.bytes() == 0 {
732738
// Do nothing for ZST's
733739
} else if fx.clif_type(operand.layout().ty) == Some(types::I8) {

compiler/rustc_codegen_cranelift/src/constant.rs

+9-51
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
44
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
55
use rustc_middle::mir::interpret::{
6-
read_target_uint, AllocId, ConstAllocation, ConstValue, ErrorHandled, GlobalAlloc, Scalar,
6+
read_target_uint, AllocId, ConstAllocation, ConstValue, GlobalAlloc, Scalar,
77
};
88

99
use cranelift_module::*;
@@ -33,16 +33,6 @@ impl ConstantCx {
3333
}
3434
}
3535

36-
pub(crate) fn check_constants(fx: &mut FunctionCx<'_, '_, '_>) -> bool {
37-
let mut all_constants_ok = true;
38-
for constant in &fx.mir.required_consts {
39-
if eval_mir_constant(fx, constant).is_none() {
40-
all_constants_ok = false;
41-
}
42-
}
43-
all_constants_ok
44-
}
45-
4636
pub(crate) fn codegen_static(tcx: TyCtxt<'_>, module: &mut dyn Module, def_id: DefId) {
4737
let mut constants_cx = ConstantCx::new();
4838
constants_cx.todo.push(TodoItem::Static(def_id));
@@ -76,52 +66,20 @@ pub(crate) fn codegen_tls_ref<'tcx>(
7666
pub(crate) fn eval_mir_constant<'tcx>(
7767
fx: &FunctionCx<'_, '_, 'tcx>,
7868
constant: &Constant<'tcx>,
79-
) -> 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-
69+
) -> (ConstValue<'tcx>, Ty<'tcx>) {
70+
// This cannot fail because we checked all required_consts in advance.
10271
let val = fx
103-
.tcx
104-
.const_eval_resolve(ty::ParamEnv::reveal_all(), uv, None)
105-
.map_err(|err| match err {
106-
ErrorHandled::Reported(_) => {
107-
fx.tcx.sess.span_err(constant.span, "erroneous constant encountered");
108-
}
109-
ErrorHandled::TooGeneric => {
110-
span_bug!(constant.span, "codegen encountered polymorphic constant: {:?}", err);
111-
}
112-
})
113-
.ok();
114-
val.map(|val| (val, constant_kind.ty()))
72+
.monomorphize(constant.literal)
73+
.eval(fx.tcx, ty::ParamEnv::reveal_all(), Some(constant.span))
74+
.expect("erroneous constant not captured by required_consts");
75+
(val, constant.ty())
11576
}
11677

11778
pub(crate) fn codegen_constant_operand<'tcx>(
11879
fx: &mut FunctionCx<'_, '_, 'tcx>,
11980
constant: &Constant<'tcx>,
12081
) -> CValue<'tcx> {
121-
let (const_val, ty) = eval_mir_constant(fx, constant).unwrap_or_else(|| {
122-
span_bug!(constant.span, "erroneous constant not captured by required_consts")
123-
});
124-
82+
let (const_val, ty) = eval_mir_constant(fx, constant);
12583
codegen_const_value(fx, const_val, ty)
12684
}
12785

@@ -479,7 +437,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
479437
operand: &Operand<'tcx>,
480438
) -> Option<ConstValue<'tcx>> {
481439
match operand {
482-
Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).unwrap().0),
440+
Operand::Constant(const_) => Some(eval_mir_constant(fx, const_).0),
483441
// FIXME(rust-lang/rust#85105): Casts like `IMM8 as u32` result in the const being stored
484442
// inside a temporary before being passed to the intrinsic requiring the const argument.
485443
// This code tries to find a single constant defining definition of the referenced local.

compiler/rustc_codegen_cranelift/src/inline_asm.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,7 @@ pub(crate) fn codegen_inline_asm<'tcx>(
242242
}
243243
}
244244
InlineAsmOperand::Const { ref value } => {
245-
let (const_value, ty) = crate::constant::eval_mir_constant(fx, value)
246-
.unwrap_or_else(|| span_bug!(span, "asm const cannot be resolved"));
245+
let (const_value, ty) = crate::constant::eval_mir_constant(fx, value);
247246
let value = rustc_codegen_ssa::common::asm_const_to_str(
248247
fx.tcx,
249248
span,

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);
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/block.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -1109,9 +1109,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
11091109
InlineAsmOperandRef::InOut { reg, late, in_value, out_place }
11101110
}
11111111
mir::InlineAsmOperand::Const { ref value } => {
1112-
let const_value = self
1113-
.eval_mir_constant(value)
1114-
.unwrap_or_else(|_| span_bug!(span, "asm const cannot be resolved"));
1112+
let const_value = self.eval_mir_constant(value);
11151113
let string = common::asm_const_to_str(
11161114
bx.tcx(),
11171115
span,

compiler/rustc_codegen_ssa/src/mir/constant.rs

+11-40
Original file line numberDiff line numberDiff line change
@@ -14,53 +14,24 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
1414
&self,
1515
bx: &mut Bx,
1616
constant: &mir::Constant<'tcx>,
17-
) -> Result<OperandRef<'tcx, Bx::Value>, ErrorHandled> {
18-
let val = self.eval_mir_constant(constant)?;
17+
) -> OperandRef<'tcx, Bx::Value> {
18+
let val = self.eval_mir_constant(constant);
1919
let ty = self.monomorphize(constant.ty());
20-
Ok(OperandRef::from_const(bx, val, ty))
20+
OperandRef::from_const(bx, val, ty)
2121
}
2222

23-
pub fn eval_mir_constant(
24-
&self,
25-
constant: &mir::Constant<'tcx>,
26-
) -> 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)));
33-
}
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-
})
23+
pub fn eval_mir_constant(&self, constant: &mir::Constant<'tcx>) -> ConstValue<'tcx> {
24+
// This cannot fail because we checked all required_consts in advance.
25+
self.monomorphize(constant.literal)
26+
.eval(self.cx.tcx(), ty::ParamEnv::reveal_all(), Some(constant.span))
27+
.expect("erroneous constant not captured by required_consts")
5928
}
6029

6130
/// This is a convenience helper for `simd_shuffle_indices`. It has the precondition
6231
/// that the given `constant` is an `ConstantKind::Unevaluated` and must be convertible to
6332
/// a `ValTree`. If you want a more general version of this, talk to `wg-const-eval` on zulip.
33+
///
34+
/// Note that this function is cursed, since usually MIR consts should not be evaluated to valtrees!
6435
pub fn eval_unevaluated_mir_constant_to_valtree(
6536
&self,
6637
constant: &mir::Constant<'tcx>,
@@ -80,7 +51,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
8051
// `simd_shuffle` call without wrapping the constant argument in a `const {}` block, but
8152
// the user pass through arbitrary expressions.
8253
// FIXME(oli-obk): replace the magic const generic argument of `simd_shuffle` with a real
83-
// const generic.
54+
// const generic, and get rid of this entire function.
8455
other => span_bug!(constant.span, "{other:#?}"),
8556
};
8657
let uv = self.monomorphize(uv);

compiler/rustc_codegen_ssa/src/mir/debuginfo.rs

+6-17
Original file line numberDiff line numberDiff line change
@@ -579,23 +579,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
579579
if let Some(dbg_var) = dbg_var {
580580
let Some(dbg_loc) = self.dbg_loc(var.source_info) else { continue };
581581

582-
if let Ok(operand) = self.eval_mir_constant_to_operand(bx, &c) {
583-
self.set_debug_loc(bx, var.source_info);
584-
let base = Self::spill_operand_to_stack(
585-
operand,
586-
Some(var.name.to_string()),
587-
bx,
588-
);
589-
590-
bx.dbg_var_addr(
591-
dbg_var,
592-
dbg_loc,
593-
base.llval,
594-
Size::ZERO,
595-
&[],
596-
fragment,
597-
);
598-
}
582+
let operand = self.eval_mir_constant_to_operand(bx, &c);
583+
self.set_debug_loc(bx, var.source_info);
584+
let base =
585+
Self::spill_operand_to_stack(operand, Some(var.name.to_string()), bx);
586+
587+
bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, Size::ZERO, &[], fragment);
599588
}
600589
}
601590
}

compiler/rustc_codegen_ssa/src/mir/mod.rs

+14-16
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use crate::base;
2+
use crate::errors;
23
use crate::traits::*;
34
use rustc_index::bit_set::BitSet;
45
use rustc_index::IndexVec;
@@ -212,25 +213,22 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
212213

213214
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(&mut start_bx);
214215

215-
// Evaluate all required consts; codegen later assumes that CTFE will never fail.
216-
let mut all_consts_ok = true;
217-
for const_ in &mir.required_consts {
218-
if let Err(err) = fx.eval_mir_constant(const_) {
219-
all_consts_ok = false;
220-
match err {
221-
// errored or at least linted
222-
ErrorHandled::Reported(_) => {}
223-
ErrorHandled::TooGeneric => {
224-
span_bug!(const_.span, "codegen encountered polymorphic constant: {:?}", err)
225-
}
216+
// Rust post-monomorphization checks; we later rely on them.
217+
match mir.post_mono_checks(cx.tcx(), ty::ParamEnv::reveal_all(), |c| Ok(fx.monomorphize(c))) {
218+
Ok(()) => {}
219+
Err(ErrorHandled::TooGeneric(span)) => {
220+
cx.tcx().sess.diagnostic().emit_bug(errors::PolymorphicConstantTooGeneric { span });
221+
}
222+
Err(ErrorHandled::Reported(info, span)) => {
223+
if !info.is_tainted_by_errors() {
224+
cx.tcx().sess.emit_err(errors::ErroneousConstant { span });
226225
}
226+
// This IR shouldn't ever be emitted, but let's try to guard against any of this code
227+
// ever running.
228+
start_bx.abort();
229+
return;
227230
}
228231
}
229-
if !all_consts_ok {
230-
// We leave the IR in some half-built state here, and rely on this code not even being
231-
// submitted to LLVM once an error was raised.
232-
return;
233-
}
234232

235233
let memory_locals = analyze::non_ssa_locals(&fx);
236234

compiler/rustc_codegen_ssa/src/mir/operand.rs

+1-6
Original file line numberDiff line numberDiff line change
@@ -569,12 +569,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
569569
self.codegen_consume(bx, place.as_ref())
570570
}
571571

572-
mir::Operand::Constant(ref constant) => {
573-
// This cannot fail because we checked all required_consts in advance.
574-
self.eval_mir_constant_to_operand(bx, constant).unwrap_or_else(|_err| {
575-
span_bug!(constant.span, "erroneous constant not captured by required_consts")
576-
})
577-
}
572+
mir::Operand::Constant(ref constant) => self.eval_mir_constant_to_operand(bx, constant),
578573
}
579574
}
580575
}

compiler/rustc_const_eval/src/const_eval/error.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_middle::mir::AssertKind;
55
use rustc_middle::ty::TyCtxt;
66
use rustc_middle::ty::{layout::LayoutError, ConstInt};
77
use rustc_span::source_map::Spanned;
8-
use rustc_span::{ErrorGuaranteed, Span, Symbol};
8+
use rustc_span::{ErrorGuaranteed, Span, Symbol, DUMMY_SP};
99

1010
use super::InterpCx;
1111
use crate::errors::{self, FrameNote, ReportErrorExt};
@@ -134,11 +134,11 @@ where
134134
match error {
135135
// Don't emit a new diagnostic for these errors
136136
err_inval!(Layout(LayoutError::Unknown(_))) | err_inval!(TooGeneric) => {
137-
ErrorHandled::TooGeneric
137+
ErrorHandled::TooGeneric(span.unwrap_or(DUMMY_SP))
138138
}
139-
err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar),
139+
err_inval!(AlreadyReported(guar)) => ErrorHandled::Reported(guar, span.unwrap_or(DUMMY_SP)),
140140
err_inval!(Layout(LayoutError::ReferencesError(guar))) => {
141-
ErrorHandled::Reported(guar.into())
141+
ErrorHandled::Reported(guar.into(), span.unwrap_or(DUMMY_SP))
142142
}
143143
err_inval!(Layout(layout_error @ LayoutError::SizeOverflow(_))) => {
144144
// We must *always* hard error on these, even if the caller wants just a lint.
@@ -157,7 +157,7 @@ where
157157
err.eager_subdiagnostic(handler, frame);
158158
}
159159

160-
ErrorHandled::Reported(handler.emit_diagnostic(&mut err).unwrap().into())
160+
ErrorHandled::Reported(handler.emit_diagnostic(&mut err).unwrap().into(), span)
161161
}
162162
_ => {
163163
// Report as hard error.
@@ -171,7 +171,7 @@ where
171171

172172
// Use *our* span to label the interp error
173173
err.span_label(our_span, msg);
174-
ErrorHandled::Reported(err.emit().into())
174+
ErrorHandled::Reported(err.emit().into(), span)
175175
}
176176
}
177177
}

compiler/rustc_const_eval/src/const_eval/eval_queries.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ pub fn eval_to_const_value_raw_provider<'tcx>(
235235
key.param_env = key.param_env.with_user_facing();
236236
match tcx.eval_to_const_value_raw(key) {
237237
// try again with reveal all as requested
238-
Err(ErrorHandled::TooGeneric) => {}
238+
Err(ErrorHandled::TooGeneric(_)) => {}
239239
// deduplicate calls
240240
other => return other,
241241
}
@@ -282,7 +282,7 @@ pub fn eval_to_allocation_raw_provider<'tcx>(
282282
key.param_env = key.param_env.with_user_facing();
283283
match tcx.eval_to_allocation_raw(key) {
284284
// try again with reveal all as requested
285-
Err(ErrorHandled::TooGeneric) => {}
285+
Err(ErrorHandled::TooGeneric(_)) => {}
286286
// deduplicate calls
287287
other => return other,
288288
}

0 commit comments

Comments
 (0)