From 6807bb7482f88d9bfe535d8788664e733a469e7a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 5 Apr 2020 11:08:39 -0300 Subject: [PATCH 01/11] Make mir::Constant Copy --- src/librustc_middle/mir/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index e476729c11b4d..489a47b5411f5 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -2393,7 +2393,7 @@ impl<'tcx> Debug for Rvalue<'tcx> { /// this does not necessarily mean that they are "==" in Rust -- in /// particular one must be wary of `NaN`! -#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)] +#[derive(Clone, Copy, PartialEq, RustcEncodable, RustcDecodable, HashStable)] pub struct Constant<'tcx> { pub span: Span, From f8976e377f694c98c180ce967b295531d1824563 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 3 Apr 2020 18:26:24 -0300 Subject: [PATCH 02/11] Add MirPass to collect Unevaluated consts in MIR body --- src/librustc_middle/mir/mod.rs | 5 ++++ src/librustc_mir/transform/mod.rs | 13 ++++++++++- .../transform/uneval_const_set.rs | 23 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 src/librustc_mir/transform/uneval_const_set.rs diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 489a47b5411f5..5ab4689d2acb7 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -156,6 +156,9 @@ pub struct Body<'tcx> { /// A span representing this MIR, for error reporting. pub span: Span, + /// Unevaluated consts to evaluate them regardless of being optimized out + pub uneval_consts: Vec>, + /// The user may be writing e.g. &[(SOME_CELL, 42)][i].1 and this would get promoted, because /// we'd statically know that no thing with interior mutability will ever be available to the /// user without some serious unsafe code. Now this means that our promoted is actually @@ -203,6 +206,7 @@ impl<'tcx> Body<'tcx> { spread_arg: None, var_debug_info, span, + uneval_consts: Vec::new(), ignore_interior_mut_in_const_validation: false, control_flow_destroyed, predecessor_cache: PredecessorCache::new(), @@ -227,6 +231,7 @@ impl<'tcx> Body<'tcx> { arg_count: 0, spread_arg: None, span: DUMMY_SP, + uneval_consts: Vec::new(), control_flow_destroyed: Vec::new(), generator_kind: None, var_debug_info: Vec::new(), diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index a87955274a779..4735be29f6893 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -4,7 +4,8 @@ use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LocalDefId, LOCAL_CRATE}; use rustc_hir::intravisit::{self, NestedVisitorMap, Visitor}; use rustc_index::vec::IndexVec; -use rustc_middle::mir::{Body, ConstQualifs, MirPhase, Promoted}; +use rustc_middle::mir::visit::Visitor as _; +use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::steal::Steal; use rustc_middle::ty::{InstanceDef, TyCtxt, TypeFoldable}; @@ -33,6 +34,7 @@ pub mod rustc_peek; pub mod simplify; pub mod simplify_branches; pub mod simplify_try; +pub mod uneval_const_set; pub mod uninhabited_enum_branching; pub mod unreachable_prop; @@ -237,6 +239,15 @@ fn mir_validated( let _ = tcx.mir_const_qualif(def_id); let mut body = tcx.mir_const(def_id).steal(); + + let mut uneval_consts = Vec::new(); + let mut uneval_const_visitor = + self::uneval_const_set::UnevalConstSetVisitor::new(&mut uneval_consts); + for (bb, bb_data) in traversal::reverse_postorder(&body) { + uneval_const_visitor.visit_basic_block_data(bb, bb_data); + } + body.uneval_consts = uneval_consts; + let promote_pass = promote_consts::PromoteTemps::default(); run_passes( tcx, diff --git a/src/librustc_mir/transform/uneval_const_set.rs b/src/librustc_mir/transform/uneval_const_set.rs new file mode 100644 index 0000000000000..98190f0f13f42 --- /dev/null +++ b/src/librustc_mir/transform/uneval_const_set.rs @@ -0,0 +1,23 @@ +use rustc_middle::mir::visit::Visitor; +use rustc_middle::mir::{Constant, Location}; +use rustc_middle::ty::ConstKind; + +pub struct UnevalConstSetVisitor<'a, 'tcx> { + uneval_consts: &'a mut Vec>, +} + +impl<'a, 'tcx> UnevalConstSetVisitor<'a, 'tcx> { + pub fn new(uneval_consts: &'a mut Vec>) -> Self { + UnevalConstSetVisitor { uneval_consts } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for UnevalConstSetVisitor<'a, 'tcx> { + fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) { + let const_kind = constant.literal.val; + + if let ConstKind::Unevaluated(_, _, _) = const_kind { + self.uneval_consts.push(*constant); + } + } +} From db18b42343a080024279a0e44b785594dcaf8667 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 5 Apr 2020 10:30:32 -0300 Subject: [PATCH 03/11] Evaluate unevaluated MIR constants in codegen_mir --- src/librustc_codegen_ssa/mir/mod.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index cb6d2d297cd73..663b37d5e6508 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -1,6 +1,8 @@ use crate::base; use crate::traits::*; +use rustc_errors::ErrorReported; use rustc_middle::mir; +use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::ty::layout::{FnAbiExt, HasTyCtxt, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TypeFoldable}; use rustc_target::abi::call::{FnAbi, PassMode}; @@ -189,6 +191,18 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(); + for const_ in &mir.uneval_consts { + if let Err(err) = fx.eval_mir_constant(const_) { + match err { + // errored or at least linted + ErrorHandled::Reported(ErrorReported) | ErrorHandled::Linted => {} + ErrorHandled::TooGeneric => { + span_bug!(const_.span, "codgen encountered polymorphic constant: {:?}", err) + } + } + } + } + let memory_locals = analyze::non_ssa_locals(&fx); // Allocate variable and temp allocas From 5313e2e9296fc1b13e7f1eda3aa5f63dc1e7ce9a Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Sun, 5 Apr 2020 14:09:45 -0300 Subject: [PATCH 04/11] Make inlining carry over unevaluated consts --- src/librustc_mir/transform/inline.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index d8bb8a0b52c66..0408818b7986d 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -8,7 +8,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; use rustc_middle::ty::subst::{Subst, SubstsRef}; -use rustc_middle::ty::{self, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; +use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt}; use rustc_session::config::Sanitizer; use rustc_target::spec::abi::Abi; @@ -123,6 +123,14 @@ impl Inliner<'tcx> { continue; }; + // Copy only unevaluated constants from the callee_body into the caller_body. + // Although we are only pushing `ConstKind::Unevaluated` consts to uneval_consts, + // here we may not only have `ConstKind::Unevaluated` because we are calling + // `subst_and_normalize_erasing_regions`. + caller_body.uneval_consts.extend(callee_body.uneval_consts.iter().copied().filter( + |&constant| matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _)), + )); + let start = caller_body.basic_blocks().len(); debug!("attempting to inline callsite {:?} - body={:?}", callsite, callee_body); if !self.inline_call(callsite, caller_body, callee_body) { From 0107cecc01cf28bd298e33b44d6bacba6e4b3d77 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Mon, 6 Apr 2020 17:49:49 -0300 Subject: [PATCH 05/11] Visit unevaluated constants in super_body --- src/librustc_middle/mir/visit.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs index 9f8355b0cb090..8d3e862aac565 100644 --- a/src/librustc_middle/mir/visit.rs +++ b/src/librustc_middle/mir/visit.rs @@ -288,6 +288,11 @@ macro_rules! make_mir_visitor { } self.visit_span(&$($mutability)? body.span); + + for const_ in &$($mutability)? body.uneval_consts { + let location = START_BLOCK.start_location(); + self.visit_constant(const_, location); + } } fn super_basic_block_data(&mut self, From f925a03eadf5e875b36efaa1c5cc56aa0be78548 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Tue, 21 Apr 2020 15:53:00 -0300 Subject: [PATCH 06/11] Make ConstPropagator only visit basic blocks when visiting body Avoid exercising unevaluated constants and go straight to visit the blocks. --- src/librustc_mir/transform/const_prop.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index beabdf7f784f8..5b415cb806ad4 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -833,6 +833,12 @@ impl<'mir, 'tcx> MutVisitor<'tcx> for ConstPropagator<'mir, 'tcx> { self.tcx } + fn visit_body(&mut self, body: &mut Body<'tcx>) { + for (bb, data) in body.basic_blocks_mut().iter_enumerated_mut() { + self.visit_basic_block_data(bb, data); + } + } + fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) { trace!("visit_constant: {:?}", constant); self.super_constant(constant, location); From 25e0be736c3fefd39a8f3c691b40a0c8c75a94f0 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 17 Apr 2020 18:31:21 -0300 Subject: [PATCH 07/11] Clean up fragile checks of optimized away constants --- src/librustc_mir/transform/simplify.rs | 35 ++++++++------------------ 1 file changed, 10 insertions(+), 25 deletions(-) diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index e579950d8c0ac..491c37cbe06e8 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -32,7 +32,7 @@ use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::{self, TyCtxt}; +use rustc_middle::ty::TyCtxt; use std::borrow::Cow; pub struct SimplifyCfg { @@ -400,33 +400,18 @@ impl<'a, 'tcx> Visitor<'tcx> for DeclMarker<'a, 'tcx> { if location.statement_index != block.statements.len() { let stmt = &block.statements[location.statement_index]; - fn can_skip_constant(c: &ty::Const<'tcx>) -> bool { - // Keep assignments from unevaluated constants around, since the - // evaluation may report errors, even if the use of the constant - // is dead code. - !matches!(c.val, ty::ConstKind::Unevaluated(..)) - } - - fn can_skip_operand(o: &Operand<'_>) -> bool { - match o { - Operand::Copy(_) | Operand::Move(_) => true, - Operand::Constant(c) => can_skip_constant(c.literal), - } - } - if let StatementKind::Assign(box (dest, rvalue)) = &stmt.kind { if !dest.is_indirect() && dest.local == *local { let can_skip = match rvalue { - Rvalue::Use(op) => can_skip_operand(op), - Rvalue::Discriminant(_) => true, - Rvalue::BinaryOp(_, l, r) | Rvalue::CheckedBinaryOp(_, l, r) => { - can_skip_operand(l) && can_skip_operand(r) - } - Rvalue::Repeat(op, c) => can_skip_operand(op) && can_skip_constant(c), - Rvalue::AddressOf(_, _) => true, - Rvalue::Len(_) => true, - Rvalue::UnaryOp(_, op) => can_skip_operand(op), - Rvalue::Aggregate(_, operands) => operands.iter().all(can_skip_operand), + Rvalue::Use(_) + | Rvalue::Discriminant(_) + | Rvalue::BinaryOp(_, _, _) + | Rvalue::CheckedBinaryOp(_, _, _) + | Rvalue::Repeat(_, _) + | Rvalue::AddressOf(_, _) + | Rvalue::Len(_) + | Rvalue::UnaryOp(_, _) + | Rvalue::Aggregate(_, _) => true, _ => false, }; From 39be0b5b6caa0090eaf91c797e2895a007e76354 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Fri, 17 Apr 2020 18:31:42 -0300 Subject: [PATCH 08/11] Bless mir-opt tests --- .../32bit/rustc.main.ConstProp.after.mir | 30 ++++++++--------- .../64bit/rustc.main.ConstProp.after.mir | 32 +++++++++---------- .../rustc.no_codegen.PreCodegen.after.mir | 12 +------ 3 files changed, 32 insertions(+), 42 deletions(-) diff --git a/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir index efd14ea140fe8..7b300782c63f9 100644 --- a/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir +++ b/src/test/mir-opt/const_allocation2/32bit/rustc.main.ConstProp.after.mir @@ -30,41 +30,41 @@ fn main() -> () { } alloc0 (static: FOO, size: 8, align: 4) { - ╾alloc25+0╼ 03 00 00 00 │ ╾──╼.... + ╾alloc21+0╼ 03 00 00 00 │ ╾──╼.... } -alloc25 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾alloc10+0╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾alloc15+0╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾alloc23+0╼ 03 00 00 00 │ ....*...╾──╼.... +alloc21 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾alloc4+0─╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾alloc9+0─╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾alloc19+0╼ 03 00 00 00 │ ....*...╾──╼.... } -alloc10 (size: 0, align: 4) {} +alloc4 (size: 0, align: 4) {} -alloc15 (size: 8, align: 4) { - ╾alloc13+0╼ ╾alloc14+0╼ │ ╾──╼╾──╼ +alloc9 (size: 8, align: 4) { + ╾alloc7+0─╼ ╾alloc8+0─╼ │ ╾──╼╾──╼ } -alloc13 (size: 1, align: 1) { +alloc7 (size: 1, align: 1) { 05 │ . } -alloc14 (size: 1, align: 1) { +alloc8 (size: 1, align: 1) { 06 │ . } -alloc23 (size: 12, align: 4) { - ╾alloc19+3╼ ╾alloc20+0╼ ╾alloc22+2╼ │ ╾──╼╾──╼╾──╼ +alloc19 (size: 12, align: 4) { + ╾alloc15+3╼ ╾alloc16+0╼ ╾alloc18+2╼ │ ╾──╼╾──╼╾──╼ } -alloc19 (size: 4, align: 1) { +alloc15 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc20 (size: 1, align: 1) { +alloc16 (size: 1, align: 1) { 2a │ * } -alloc22 (size: 4, align: 1) { +alloc18 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir b/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir index 3b649ee7a24bd..6821196fe4a5a 100644 --- a/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir +++ b/src/test/mir-opt/const_allocation2/64bit/rustc.main.ConstProp.after.mir @@ -30,44 +30,44 @@ fn main() -> () { } alloc0 (static: FOO, size: 16, align: 8) { - ╾──────alloc25+0──────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾──────alloc21+0──────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc25 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾──────alloc10+0──────╼ │ ....░░░░╾──────╼ +alloc21 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾──────alloc4+0───────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾──────alloc15+0──────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾──────alloc23+0──────╼ │ ....*...╾──────╼ + 0x20 │ ╾──────alloc9+0───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾──────alloc19+0──────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc10 (size: 0, align: 8) {} +alloc4 (size: 0, align: 8) {} -alloc15 (size: 16, align: 8) { - ╾──────alloc13+0──────╼ ╾──────alloc14+0──────╼ │ ╾──────╼╾──────╼ +alloc9 (size: 16, align: 8) { + ╾──────alloc7+0───────╼ ╾──────alloc8+0───────╼ │ ╾──────╼╾──────╼ } -alloc13 (size: 1, align: 1) { +alloc7 (size: 1, align: 1) { 05 │ . } -alloc14 (size: 1, align: 1) { +alloc8 (size: 1, align: 1) { 06 │ . } -alloc23 (size: 24, align: 8) { - 0x00 │ ╾──────alloc19+3──────╼ ╾──────alloc20+0──────╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾──────alloc22+2──────╼ │ ╾──────╼ +alloc19 (size: 24, align: 8) { + 0x00 │ ╾──────alloc15+3──────╼ ╾──────alloc16+0──────╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾──────alloc18+2──────╼ │ ╾──────╼ } -alloc19 (size: 4, align: 1) { +alloc15 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc20 (size: 1, align: 1) { +alloc16 (size: 1, align: 1) { 2a │ * } -alloc22 (size: 4, align: 1) { +alloc18 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/src/test/mir-opt/retain-never-const/rustc.no_codegen.PreCodegen.after.mir b/src/test/mir-opt/retain-never-const/rustc.no_codegen.PreCodegen.after.mir index 2d7a79ee44c07..07d28efb9c39e 100644 --- a/src/test/mir-opt/retain-never-const/rustc.no_codegen.PreCodegen.after.mir +++ b/src/test/mir-opt/retain-never-const/rustc.no_codegen.PreCodegen.after.mir @@ -2,20 +2,10 @@ fn no_codegen() -> () { let mut _0: (); // return place in scope 0 at $DIR/retain-never-const.rs:18:20: 18:20 - let mut _1: !; // in scope 0 at $DIR/retain-never-const.rs:19:13: 19:33 scope 1 { } bb0: { - StorageLive(_1); // bb0[0]: scope 0 at $DIR/retain-never-const.rs:19:13: 19:33 - _1 = const PrintName::::VOID; // bb0[1]: scope 0 at $DIR/retain-never-const.rs:19:13: 19:33 - // ty::Const - // + ty: ! - // + val: Unevaluated(DefId(0:9 ~ retain_never_const[317d]::{{impl}}[0]::VOID[0]), [T], None) - // mir::Constant - // + span: $DIR/retain-never-const.rs:19:13: 19:33 - // + user_ty: UserType(0) - // + literal: Const { ty: !, val: Unevaluated(DefId(0:9 ~ retain_never_const[317d]::{{impl}}[0]::VOID[0]), [T], None) } - unreachable; // bb0[2]: scope 0 at $DIR/retain-never-const.rs:19:13: 19:33 + unreachable; // bb0[0]: scope 0 at $DIR/retain-never-const.rs:19:13: 19:33 } } From da9aa2dd55b69a4c902af9b953904911e9cffb77 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 22 Apr 2020 09:23:06 -0300 Subject: [PATCH 09/11] Adjust name of never typed const test --- .../mir-opt/{retain-never-const.rs => remove-never-const.rs} | 5 +++-- .../rustc.no_codegen.PreCodegen.after.mir | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) rename src/test/mir-opt/{retain-never-const.rs => remove-never-const.rs} (61%) rename src/test/mir-opt/{retain-never-const => remove-never-const}/rustc.no_codegen.PreCodegen.after.mir (73%) diff --git a/src/test/mir-opt/retain-never-const.rs b/src/test/mir-opt/remove-never-const.rs similarity index 61% rename from src/test/mir-opt/retain-never-const.rs rename to src/test/mir-opt/remove-never-const.rs index af1077e6334cc..b2d4f14aa4cd8 100644 --- a/src/test/mir-opt/retain-never-const.rs +++ b/src/test/mir-opt/remove-never-const.rs @@ -1,5 +1,6 @@ -// Regression test for #66975 - ensure that we don't keep unevaluated -// `!`-typed constants until codegen. +// This was originally a regression test for #66975 - ensure that we do not generate never typed +// consts in codegen. We also have tests for this that catches the error, see +// src/test/ui/consts/const-eval/index-out-of-bounds-never-type.rs. // Force generation of optimized mir for functions that do not reach codegen. // compile-flags: --emit mir,link diff --git a/src/test/mir-opt/retain-never-const/rustc.no_codegen.PreCodegen.after.mir b/src/test/mir-opt/remove-never-const/rustc.no_codegen.PreCodegen.after.mir similarity index 73% rename from src/test/mir-opt/retain-never-const/rustc.no_codegen.PreCodegen.after.mir rename to src/test/mir-opt/remove-never-const/rustc.no_codegen.PreCodegen.after.mir index 07d28efb9c39e..1cc2138f19e37 100644 --- a/src/test/mir-opt/retain-never-const/rustc.no_codegen.PreCodegen.after.mir +++ b/src/test/mir-opt/remove-never-const/rustc.no_codegen.PreCodegen.after.mir @@ -1,11 +1,11 @@ // MIR for `no_codegen` after PreCodegen fn no_codegen() -> () { - let mut _0: (); // return place in scope 0 at $DIR/retain-never-const.rs:18:20: 18:20 + let mut _0: (); // return place in scope 0 at $DIR/remove-never-const.rs:19:20: 19:20 scope 1 { } bb0: { - unreachable; // bb0[0]: scope 0 at $DIR/retain-never-const.rs:19:13: 19:33 + unreachable; // bb0[0]: scope 0 at $DIR/remove-never-const.rs:20:13: 20:33 } } From c1ed7cc95f0aaa75e916fc044cce293f56ad04d3 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 22 Apr 2020 11:16:06 -0300 Subject: [PATCH 10/11] Rename uneval_consts to required_consts --- src/librustc_codegen_ssa/mir/mod.rs | 2 +- src/librustc_middle/mir/mod.rs | 9 ++++---- src/librustc_middle/mir/visit.rs | 2 +- src/librustc_mir/transform/inline.rs | 14 ++++++----- src/librustc_mir/transform/mod.rs | 12 +++++----- src/librustc_mir/transform/required_consts.rs | 23 +++++++++++++++++++ .../transform/uneval_const_set.rs | 23 ------------------- 7 files changed, 44 insertions(+), 41 deletions(-) create mode 100644 src/librustc_mir/transform/required_consts.rs delete mode 100644 src/librustc_mir/transform/uneval_const_set.rs diff --git a/src/librustc_codegen_ssa/mir/mod.rs b/src/librustc_codegen_ssa/mir/mod.rs index 663b37d5e6508..1cd01c8c5bcb0 100644 --- a/src/librustc_codegen_ssa/mir/mod.rs +++ b/src/librustc_codegen_ssa/mir/mod.rs @@ -191,7 +191,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( fx.per_local_var_debug_info = fx.compute_per_local_var_debug_info(); - for const_ in &mir.uneval_consts { + for const_ in &mir.required_consts { if let Err(err) = fx.eval_mir_constant(const_) { match err { // errored or at least linted diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs index 5ab4689d2acb7..6d5daf940e1c1 100644 --- a/src/librustc_middle/mir/mod.rs +++ b/src/librustc_middle/mir/mod.rs @@ -156,8 +156,9 @@ pub struct Body<'tcx> { /// A span representing this MIR, for error reporting. pub span: Span, - /// Unevaluated consts to evaluate them regardless of being optimized out - pub uneval_consts: Vec>, + /// Constants that are required to evaluate successfully for this MIR to be well-formed. + /// We hold in this field all the constants we are not able to evaluate yet. + pub required_consts: Vec>, /// The user may be writing e.g. &[(SOME_CELL, 42)][i].1 and this would get promoted, because /// we'd statically know that no thing with interior mutability will ever be available to the @@ -206,7 +207,7 @@ impl<'tcx> Body<'tcx> { spread_arg: None, var_debug_info, span, - uneval_consts: Vec::new(), + required_consts: Vec::new(), ignore_interior_mut_in_const_validation: false, control_flow_destroyed, predecessor_cache: PredecessorCache::new(), @@ -231,7 +232,7 @@ impl<'tcx> Body<'tcx> { arg_count: 0, spread_arg: None, span: DUMMY_SP, - uneval_consts: Vec::new(), + required_consts: Vec::new(), control_flow_destroyed: Vec::new(), generator_kind: None, var_debug_info: Vec::new(), diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs index 8d3e862aac565..d32a8d4344573 100644 --- a/src/librustc_middle/mir/visit.rs +++ b/src/librustc_middle/mir/visit.rs @@ -289,7 +289,7 @@ macro_rules! make_mir_visitor { self.visit_span(&$($mutability)? body.span); - for const_ in &$($mutability)? body.uneval_consts { + for const_ in &$($mutability)? body.required_consts { let location = START_BLOCK.start_location(); self.visit_constant(const_, location); } diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 0408818b7986d..6c9eddc303f51 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -124,12 +124,14 @@ impl Inliner<'tcx> { }; // Copy only unevaluated constants from the callee_body into the caller_body. - // Although we are only pushing `ConstKind::Unevaluated` consts to uneval_consts, - // here we may not only have `ConstKind::Unevaluated` because we are calling - // `subst_and_normalize_erasing_regions`. - caller_body.uneval_consts.extend(callee_body.uneval_consts.iter().copied().filter( - |&constant| matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _)), - )); + // Although we are only pushing `ConstKind::Unevaluated` consts to + // `required_consts`, here we may not only have `ConstKind::Unevaluated` + // because we are calling `subst_and_normalize_erasing_regions`. + caller_body.required_consts.extend( + callee_body.required_consts.iter().copied().filter(|&constant| { + matches!(constant.literal.val, ConstKind::Unevaluated(_, _, _)) + }), + ); let start = caller_body.basic_blocks().len(); debug!("attempting to inline callsite {:?} - body={:?}", callsite, callee_body); diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 4735be29f6893..e3fe0e376f3a1 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -30,11 +30,11 @@ pub mod no_landing_pads; pub mod promote_consts; pub mod qualify_min_const_fn; pub mod remove_noop_landing_pads; +pub mod required_consts; pub mod rustc_peek; pub mod simplify; pub mod simplify_branches; pub mod simplify_try; -pub mod uneval_const_set; pub mod uninhabited_enum_branching; pub mod unreachable_prop; @@ -240,13 +240,13 @@ fn mir_validated( let mut body = tcx.mir_const(def_id).steal(); - let mut uneval_consts = Vec::new(); - let mut uneval_const_visitor = - self::uneval_const_set::UnevalConstSetVisitor::new(&mut uneval_consts); + let mut required_consts = Vec::new(); + let mut required_consts_visitor = + self::required_consts::RequiredConstsVisitor::new(&mut required_consts); for (bb, bb_data) in traversal::reverse_postorder(&body) { - uneval_const_visitor.visit_basic_block_data(bb, bb_data); + required_consts_visitor.visit_basic_block_data(bb, bb_data); } - body.uneval_consts = uneval_consts; + body.required_consts = required_consts; let promote_pass = promote_consts::PromoteTemps::default(); run_passes( diff --git a/src/librustc_mir/transform/required_consts.rs b/src/librustc_mir/transform/required_consts.rs new file mode 100644 index 0000000000000..a63ab30a68fa2 --- /dev/null +++ b/src/librustc_mir/transform/required_consts.rs @@ -0,0 +1,23 @@ +use rustc_middle::mir::visit::Visitor; +use rustc_middle::mir::{Constant, Location}; +use rustc_middle::ty::ConstKind; + +pub struct RequiredConstsVisitor<'a, 'tcx> { + required_consts: &'a mut Vec>, +} + +impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> { + pub fn new(required_consts: &'a mut Vec>) -> Self { + RequiredConstsVisitor { required_consts } + } +} + +impl<'a, 'tcx> Visitor<'tcx> for RequiredConstsVisitor<'a, 'tcx> { + fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) { + let const_kind = constant.literal.val; + + if let ConstKind::Unevaluated(_, _, _) = const_kind { + self.required_consts.push(*constant); + } + } +} diff --git a/src/librustc_mir/transform/uneval_const_set.rs b/src/librustc_mir/transform/uneval_const_set.rs deleted file mode 100644 index 98190f0f13f42..0000000000000 --- a/src/librustc_mir/transform/uneval_const_set.rs +++ /dev/null @@ -1,23 +0,0 @@ -use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{Constant, Location}; -use rustc_middle::ty::ConstKind; - -pub struct UnevalConstSetVisitor<'a, 'tcx> { - uneval_consts: &'a mut Vec>, -} - -impl<'a, 'tcx> UnevalConstSetVisitor<'a, 'tcx> { - pub fn new(uneval_consts: &'a mut Vec>) -> Self { - UnevalConstSetVisitor { uneval_consts } - } -} - -impl<'a, 'tcx> Visitor<'tcx> for UnevalConstSetVisitor<'a, 'tcx> { - fn visit_constant(&mut self, constant: &Constant<'tcx>, _: Location) { - let const_kind = constant.literal.val; - - if let ConstKind::Unevaluated(_, _, _) = const_kind { - self.uneval_consts.push(*constant); - } - } -} From 7bc45f6baae33bf7f55085f801e6eea6fcd11351 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Wed, 22 Apr 2020 12:30:11 -0300 Subject: [PATCH 11/11] Import RequiredConstsVisitor --- src/librustc_mir/transform/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index e3fe0e376f3a1..34d2309d59d78 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -1,4 +1,5 @@ use crate::{shim, util}; +use required_consts::RequiredConstsVisitor; use rustc_ast::ast; use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LocalDefId, LOCAL_CRATE}; @@ -241,8 +242,7 @@ fn mir_validated( let mut body = tcx.mir_const(def_id).steal(); let mut required_consts = Vec::new(); - let mut required_consts_visitor = - self::required_consts::RequiredConstsVisitor::new(&mut required_consts); + let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts); for (bb, bb_data) in traversal::reverse_postorder(&body) { required_consts_visitor.visit_basic_block_data(bb, bb_data); }