Skip to content

Commit 0b95879

Browse files
committed
Auto merge of #70820 - spastorino:replace-fragile-erroneous-const-sys, r=oli-obk
Replace fragile erroneous const sys Closes #67191 r? @oli-obk
2 parents 5a59527 + 7bc45f6 commit 0b95879

File tree

13 files changed

+133
-82
lines changed

13 files changed

+133
-82
lines changed

src/librustc_codegen_ssa/mir/mod.rs

+14
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use crate::base;
22
use crate::traits::*;
3+
use rustc_errors::ErrorReported;
34
use rustc_middle::mir;
5+
use rustc_middle::mir::interpret::ErrorHandled;
46
use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, TyAndLayout};
57
use rustc_middle::ty::{self, Instance, Ty, TypeFoldable};
68
use rustc_target::abi::call::{FnAbi, PassMode};
@@ -189,6 +191,18 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
189191

190192
fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info();
191193

194+
for const_ in &mir.required_consts {
195+
if let Err(err) = fx.eval_mir_constant(const_) {
196+
match err {
197+
// errored or at least linted
198+
ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {}
199+
ErrorHandled::TooGeneric => {
200+
span_bug!(const_.span, "codgen encountered polymorphic constant: {:?}", err)
201+
}
202+
}
203+
}
204+
}
205+
192206
let memory_locals = analyze::non_ssa_locals(&fx);
193207

194208
// Allocate variable and temp allocas

src/librustc_middle/mir/mod.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ pub struct Body<'tcx> {
156156
/// A span representing this MIR, for error reporting.
157157
pub span: Span,
158158

159+
/// Constants that are required to evaluate successfully for this MIR to be well-formed.
160+
/// We hold in this field all the constants we are not able to evaluate yet.
161+
pub required_consts: Vec<Constant<'tcx>>,
162+
159163
/// The user may be writing e.g. &[(SOME_CELL, 42)][i].1 and this would get promoted, because
160164
/// we'd statically know that no thing with interior mutability will ever be available to the
161165
/// user without some serious unsafe code. Now this means that our promoted is actually
@@ -203,6 +207,7 @@ impl<'tcx> Body<'tcx> {
203207
spread_arg: None,
204208
var_debug_info,
205209
span,
210+
required_consts: Vec::new(),
206211
ignore_interior_mut_in_const_validation: false,
207212
control_flow_destroyed,
208213
predecessor_cache: PredecessorCache::new(),
@@ -227,6 +232,7 @@ impl<'tcx> Body<'tcx> {
227232
arg_count: 0,
228233
spread_arg: None,
229234
span: DUMMY_SP,
235+
required_consts: Vec::new(),
230236
control_flow_destroyed: Vec::new(),
231237
generator_kind: None,
232238
var_debug_info: Vec::new(),
@@ -2395,7 +2401,7 @@ impl<'tcx> Debug for Rvalue<'tcx> {
23952401
/// this does not necessarily mean that they are "==" in Rust -- in
23962402
/// particular one must be wary of `NaN`!
23972403
2398-
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
2404+
#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
23992405
pub struct Constant<'tcx> {
24002406
pub span: Span,
24012407

src/librustc_middle/mir/visit.rs

+5
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,11 @@ macro_rules! make_mir_visitor {
288288
}
289289

290290
self.visit_span(&$($mutability)? body.span);
291+
292+
for const_ in &$($mutability)? body.required_consts {
293+
let location = START_BLOCK.start_location();
294+
self.visit_constant(const_, location);
295+
}
291296
}
292297

293298
fn super_basic_block_data(&mut self,

src/librustc_mir/transform/const_prop.rs

+6
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,12 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> {
830830
self.tcx
831831
}
832832

833+
fn visit_body(&mut self, body: &mut Body<'tcx>) {
834+
for (bb, data) in body.basic_blocks_mut().iter_enumerated_mut() {
835+
self.visit_basic_block_data(bb, data);
836+
}
837+
}
838+
833839
fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) {
834840
trace!("visit_constant: {:?}", constant);
835841
self.super_constant(constant, location);

src/librustc_mir/transform/inline.rs

+11-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
88
use rustc_middle::mir::visit::*;
99
use rustc_middle::mir::*;
1010
use rustc_middle::ty::subst::{Subst, SubstsRef};
11-
use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
11+
use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
1212
use rustc_session::config::Sanitizer;
1313
use rustc_target::spec::abi::Abi;
1414

@@ -123,6 +123,16 @@ impl Inliner<'tcx> {
123123
continue;
124124
};
125125

126+
// Copy only unevaluated constants from the callee_body into the caller_body.
127+
// Although we are only pushing `ConstKind::Unevaluated` consts to
128+
// `required_consts`, here we may not only have `ConstKind::Unevaluated`
129+
// because we are calling `subst_and_normalize_erasing_regions`.
130+
caller_body.required_consts.extend(
131+
callee_body.required_consts.iter().copied().filter(|&constant| {
132+
matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _))
133+
}),
134+
);
135+
126136
let start = caller_body.basic_blocks().len();
127137
debug!("attempting to inline callsite {:?} - body={:?}", callsite, callee_body);
128138
if !self.inline_call(callsite, caller_body, callee_body) {

src/librustc_mir/transform/mod.rs

+12-1
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
use crate::{shim, util};
2+
use required_consts::RequiredConstsVisitor;
23
use rustc_ast::ast;
34
use rustc_hir as hir;
45
use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LocalDefId, LOCAL_CRATE};
56
use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor};
67
use rustc_index::vec::IndexVec;
7-
use rustc_middle::mir::{Body, ConstQualifs, MirPhase, Promoted};
8+
use rustc_middle::mir::visit::Visitor as _;
9+
use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted};
810
use rustc_middle::ty::query::Providers;
911
use rustc_middle::ty::steal::Steal;
1012
use rustc_middle::ty::{InstanceDef, TyCtxt, TypeFoldable};
@@ -29,6 +31,7 @@ pub mod no_landing_pads;
2931
pub mod promote_consts;
3032
pub mod qualify_min_const_fn;
3133
pub mod remove_noop_landing_pads;
34+
pub mod required_consts;
3235
pub mod rustc_peek;
3336
pub mod simplify;
3437
pub mod simplify_branches;
@@ -237,6 +240,14 @@ fn mir_validated(
237240
let _ = tcx.mir_const_qualif(def_id);
238241

239242
let mut body = tcx.mir_const(def_id).steal();
243+
244+
let mut required_consts = Vec::new();
245+
let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts);
246+
for (bb, bb_data) in traversal::reverse_postorder(&body) {
247+
required_consts_visitor.visit_basic_block_data(bb, bb_data);
248+
}
249+
body.required_consts = required_consts;
250+
240251
let promote_pass = promote_consts::PromoteTemps::default();
241252
run_passes(
242253
tcx,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
use rustc_middle::mir::visit::Visitor;
2+
use rustc_middle::mir::{Constant, Location};
3+
use rustc_middle::ty::ConstKind;
4+
5+
pub struct RequiredConstsVisitor<'a, 'tcx> {
6+
required_consts: &'a mut Vec<Constant<'tcx>>,
7+
}
8+
9+
impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
10+
pub fn new(required_consts: &'a mut Vec<Constant<'tcx>>) -> Self {
11+
RequiredConstsVisitor { required_consts }
12+
}
13+
}
14+
15+
impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> {
16+
fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) {
17+
let const_kind = constant.literal.val;
18+
19+
if let ConstKind::Unevaluated(_, _, _) = const_kind {
20+
self.required_consts.push(*constant);
21+
}
22+
}
23+
}

src/librustc_mir/transform/simplify.rs

+10-25
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use rustc_index::bit_set::BitSet;
3232
use rustc_index::vec::{Idx, IndexVec};
3333
use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
3434
use rustc_middle::mir::*;
35-
use rustc_middle::ty::{self, TyCtxt};
35+
use rustc_middle::ty::TyCtxt;
3636
use std::borrow::Cow;
3737

3838
pub struct SimplifyCfg {
@@ -400,33 +400,18 @@ impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> {
400400
if location.statement_index != block.statements.len() {
401401
let stmt = &block.statements[location.statement_index];
402402

403-
fn can_skip_constant(c: &ty::Const<'tcx>) -> bool {
404-
// Keep assignments from unevaluated constants around, since the
405-
// evaluation may report errors, even if the use of the constant
406-
// is dead code.
407-
!matches!(c.val, ty::ConstKind::Unevaluated(..))
408-
}
409-
410-
fn can_skip_operand(o: &Operand<'_>) -> bool {
411-
match o {
412-
Operand::Copy(_) | Operand::Move(_) => true,
413-
Operand::Constant(c) => can_skip_constant(c.literal),
414-
}
415-
}
416-
417403
if let StatementKind::Assign(box (dest, rvalue)) = &stmt.kind {
418404
if !dest.is_indirect() && dest.local == *local {
419405
let can_skip = match rvalue {
420-
Rvalue::Use(op) => can_skip_operand(op),
421-
Rvalue::Discriminant(_) => true,
422-
Rvalue::BinaryOp(_, l, r) | Rvalue::CheckedBinaryOp(_, l, r) => {
423-
can_skip_operand(l) && can_skip_operand(r)
424-
}
425-
Rvalue::Repeat(op, c) => can_skip_operand(op) && can_skip_constant(c),
426-
Rvalue::AddressOf(_, _) => true,
427-
Rvalue::Len(_) => true,
428-
Rvalue::UnaryOp(_, op) => can_skip_operand(op),
429-
Rvalue::Aggregate(_, operands) => operands.iter().all(can_skip_operand),
406+
Rvalue::Use(_)
407+
| Rvalue::Discriminant(_)
408+
| Rvalue::BinaryOp(_, _, _)
409+
| Rvalue::CheckedBinaryOp(_, _, _)
410+
| Rvalue::Repeat(_, _)
411+
| Rvalue::AddressOf(_, _)
412+
| Rvalue::Len(_)
413+
| Rvalue::UnaryOp(_, _)
414+
| Rvalue::Aggregate(_, _) => true,
430415

431416
_ => false,
432417
};

src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir

+15-15
Original file line numberDiff line numberDiff line change
@@ -30,41 +30,41 @@ fn main() -> () {
3030
}
3131

3232
alloc0 (static: FOO, size: 8, align: 4) {
33-
alloc25+0╼ 03 00 00 00 │ ╾──╼....
33+
alloc21+0╼ 03 00 00 00 │ ╾──╼....
3434
}
3535

36-
alloc25 (size: 48, align: 4) {
37-
0x00 │ 00 00 00 00 __ __ __ __ ╾alloc10+0╼ 00 00 00 00 │ ....░░░░╾──╼....
38-
0x10 │ 00 00 00 00 __ __ __ __ ╾alloc15+0╼ 02 00 00 00 │ ....░░░░╾──╼....
39-
0x20 │ 01 00 00 00 2a 00 00 00 ╾alloc23+0╼ 03 00 00 00 │ ....*...╾──╼....
36+
alloc21 (size: 48, align: 4) {
37+
0x00 │ 00 00 00 00 __ __ __ __ ╾alloc4+0─╼ 00 00 00 00 │ ....░░░░╾──╼....
38+
0x10 │ 00 00 00 00 __ __ __ __ ╾alloc9+0─╼ 02 00 00 00 │ ....░░░░╾──╼....
39+
0x20 │ 01 00 00 00 2a 00 00 00 ╾alloc19+0╼ 03 00 00 00 │ ....*...╾──╼....
4040
}
4141

42-
alloc10 (size: 0, align: 4) {}
42+
alloc4 (size: 0, align: 4) {}
4343

44-
alloc15 (size: 8, align: 4) {
45-
alloc13+0╼ ╾alloc14+0╼ │ ╾──╼╾──╼
44+
alloc9 (size: 8, align: 4) {
45+
alloc7+0─╼ ╾alloc8+0─╼ │ ╾──╼╾──╼
4646
}
4747

48-
alloc13 (size: 1, align: 1) {
48+
alloc7 (size: 1, align: 1) {
4949
05 │ .
5050
}
5151

52-
alloc14 (size: 1, align: 1) {
52+
alloc8 (size: 1, align: 1) {
5353
06 │ .
5454
}
5555

56-
alloc23 (size: 12, align: 4) {
57-
alloc19+3╼ ╾alloc20+0╼ ╾alloc22+2╼ │ ╾──╼╾──╼╾──╼
56+
alloc19 (size: 12, align: 4) {
57+
alloc15+3╼ ╾alloc16+0╼ ╾alloc18+2╼ │ ╾──╼╾──╼╾──╼
5858
}
5959

60-
alloc19 (size: 4, align: 1) {
60+
alloc15 (size: 4, align: 1) {
6161
2a 45 15 6f │ *E.o
6262
}
6363

64-
alloc20 (size: 1, align: 1) {
64+
alloc16 (size: 1, align: 1) {
6565
2a │ *
6666
}
6767

68-
alloc22 (size: 4, align: 1) {
68+
alloc18 (size: 4, align: 1) {
6969
2a 45 15 6f │ *E.o
7070
}

src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir

+16-16
Original file line numberDiff line numberDiff line change
@@ -30,44 +30,44 @@ fn main() -> () {
3030
}
3131

3232
alloc0 (static: FOO, size: 16, align: 8) {
33-
╾──────alloc25+0──────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
33+
╾──────alloc21+0──────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........
3434
}
3535

36-
alloc25 (size: 72, align: 8) {
37-
0x00 │ 00 00 00 00 __ __ __ __ ╾──────alloc10+0──────╼ │ ....░░░░╾──────╼
36+
alloc21 (size: 72, align: 8) {
37+
0x00 │ 00 00 00 00 __ __ __ __ ╾──────alloc4+0───────╼ │ ....░░░░╾──────╼
3838
0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░
39-
0x20 │ ╾──────alloc15+0──────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
40-
0x30 │ 01 00 00 00 2a 00 00 00 ╾──────alloc23+0──────╼ │ ....*...╾──────╼
39+
0x20 │ ╾──────alloc9+0───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........
40+
0x30 │ 01 00 00 00 2a 00 00 00 ╾──────alloc19+0──────╼ │ ....*...╾──────╼
4141
0x40 │ 03 00 00 00 00 00 00 00 │ ........
4242
}
4343

44-
alloc10 (size: 0, align: 8) {}
44+
alloc4 (size: 0, align: 8) {}
4545

46-
alloc15 (size: 16, align: 8) {
47-
╾──────alloc13+0──────╼ ╾──────alloc14+0──────╼ │ ╾──────╼╾──────╼
46+
alloc9 (size: 16, align: 8) {
47+
╾──────alloc7+0──────╼ ╾──────alloc8+0───────╼ │ ╾──────╼╾──────╼
4848
}
4949

50-
alloc13 (size: 1, align: 1) {
50+
alloc7 (size: 1, align: 1) {
5151
05 │ .
5252
}
5353

54-
alloc14 (size: 1, align: 1) {
54+
alloc8 (size: 1, align: 1) {
5555
06 │ .
5656
}
5757

58-
alloc23 (size: 24, align: 8) {
59-
0x00 │ ╾──────alloc19+3──────╼ ╾──────alloc20+0──────╼ │ ╾──────╼╾──────╼
60-
0x10 │ ╾──────alloc22+2──────╼ │ ╾──────╼
58+
alloc19 (size: 24, align: 8) {
59+
0x00 │ ╾──────alloc15+3──────╼ ╾──────alloc16+0──────╼ │ ╾──────╼╾──────╼
60+
0x10 │ ╾──────alloc18+2──────╼ │ ╾──────╼
6161
}
6262

63-
alloc19 (size: 4, align: 1) {
63+
alloc15 (size: 4, align: 1) {
6464
2a 45 15 6f │ *E.o
6565
}
6666

67-
alloc20 (size: 1, align: 1) {
67+
alloc16 (size: 1, align: 1) {
6868
2a │ *
6969
}
7070

71-
alloc22 (size: 4, align: 1) {
71+
alloc18 (size: 4, align: 1) {
7272
2a 45 15 6f │ *E.o
7373
}

src/test/mir-opt/retain-never-const.rs src/test/mir-opt/remove-never-const.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
// Regression test for #66975 - ensure that we don't keep unevaluated
2-
// `!`-typed constants until codegen.
1+
// This was originally a regression test for #66975 - ensure that we do not generate never typed
2+
// consts in codegen. We also have tests for this that catches the error, see
3+
// src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs.
34

45
// Force generation of optimized mir for functions that do not reach codegen.
56
// compile-flags: --emit mir,link
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// MIR for `no_codegen` after PreCodegen
2+
3+
fn no_codegen() -> () {
4+
let mut _0: (); // return place in scope 0 at $DIR/remove-never-const.rs:19:20: 19:20
5+
scope 1 {
6+
}
7+
8+
bb0: {
9+
unreachable; // bb0[0]: scope 0 at $DIR/remove-never-const.rs:20:13: 20:33
10+
}
11+
}

src/test/mir-opt/retain-never-const/rustc.no_codegen.PreCodegen.after.mir

-21
This file was deleted.

0 commit comments

Comments
 (0)