From 68ff5f0a1872a771c72643bc7ed8544493865814 Mon Sep 17 00:00:00 2001 From: oli <oli@uhura.edef.eu> Date: Tue, 20 Oct 2020 15:00:55 +0000 Subject: [PATCH 01/21] Stop optimizing promoteds --- compiler/rustc_mir/src/transform/mod.rs | 1 - .../mir-opt/const-promotion-extern-static.rs | 4 +-- ..._allocation.main.ConstProp.after.32bit.mir | 28 ++++++++-------- ..._allocation.main.ConstProp.after.64bit.mir | 32 +++++++++---------- ...allocation2.main.ConstProp.after.32bit.mir | 26 +++++++-------- ...allocation2.main.ConstProp.after.64bit.mir | 28 ++++++++-------- ...[0].SimplifyCfg-elaborate-drops.after.mir} | 4 +-- ...[0].SimplifyCfg-elaborate-drops.after.mir} | 2 +- 8 files changed, 62 insertions(+), 63 deletions(-) rename src/test/mir-opt/{const_promotion_extern_static.BAR-promoted[0].ConstProp.after.mir => const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir} (92%) rename src/test/mir-opt/{const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir => const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir} (95%) diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 7f3b421cf76f6..1f43752f976c6 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -510,7 +510,6 @@ fn promoted_mir<'tcx>( for body in &mut promoted { run_post_borrowck_cleanup_passes(tcx, body); - run_optimization_passes(tcx, body); } debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR"); diff --git a/src/test/mir-opt/const-promotion-extern-static.rs b/src/test/mir-opt/const-promotion-extern-static.rs index 0f13fe1b48c8a..a0d4e9b2c65ae 100644 --- a/src/test/mir-opt/const-promotion-extern-static.rs +++ b/src/test/mir-opt/const-promotion-extern-static.rs @@ -5,11 +5,11 @@ extern "C" { static Y: i32 = 42; // EMIT_MIR const_promotion_extern_static.BAR.PromoteTemps.diff -// EMIT_MIR const_promotion_extern_static.BAR-promoted[0].ConstProp.after.mir +// EMIT_MIR const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir static mut BAR: *const &i32 = [&Y].as_ptr(); // EMIT_MIR const_promotion_extern_static.FOO.PromoteTemps.diff -// EMIT_MIR const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir +// EMIT_MIR const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir static mut FOO: *const &i32 = [unsafe { &X }].as_ptr(); // EMIT_MIR const_promotion_extern_static.BOP.mir_map.0.mir diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir index 8b09eade06704..a137d7fadba10 100644 --- a/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.32bit.mir @@ -24,42 +24,42 @@ fn main() -> () { } alloc0 (static: FOO, size: 8, align: 4) { - ╾─alloc14─╼ 03 00 00 00 │ ╾──╼.... + ╾─alloc17─╼ 03 00 00 00 │ ╾──╼.... } -alloc14 (size: 48, align: 4) { +alloc17 (size: 48, align: 4) { 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc4──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc7──╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc11─╼ 03 00 00 00 │ ....*...╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc13─╼ 03 00 00 00 │ ....*...╾──╼.... } alloc4 (size: 0, align: 4) {} -alloc7 (size: 16, align: 4) { - ╾─alloc6──╼ 03 00 00 00 ╾─alloc8──╼ 03 00 00 00 │ ╾──╼....╾──╼.... +alloc8 (size: 16, align: 4) { + ╾─alloc7──╼ 03 00 00 00 ╾─alloc9──╼ 03 00 00 00 │ ╾──╼....╾──╼.... } -alloc6 (size: 3, align: 1) { +alloc7 (size: 3, align: 1) { 66 6f 6f │ foo } -alloc8 (size: 3, align: 1) { +alloc9 (size: 3, align: 1) { 62 61 72 │ bar } -alloc11 (size: 24, align: 4) { - 0x00 │ ╾─alloc10─╼ 03 00 00 00 ╾─alloc12─╼ 03 00 00 00 │ ╾──╼....╾──╼.... - 0x10 │ ╾─alloc13─╼ 04 00 00 00 │ ╾──╼.... +alloc13 (size: 24, align: 4) { + 0x00 │ ╾─alloc12─╼ 03 00 00 00 ╾─alloc14─╼ 03 00 00 00 │ ╾──╼....╾──╼.... + 0x10 │ ╾─alloc15─╼ 04 00 00 00 │ ╾──╼.... } -alloc10 (size: 3, align: 1) { +alloc12 (size: 3, align: 1) { 6d 65 68 │ meh } -alloc12 (size: 3, align: 1) { +alloc14 (size: 3, align: 1) { 6d 6f 70 │ mop } -alloc13 (size: 4, align: 1) { +alloc15 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir index 2853a0ac18b0d..ef98cf9c09148 100644 --- a/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation.main.ConstProp.after.64bit.mir @@ -24,46 +24,46 @@ fn main() -> () { } alloc0 (static: FOO, size: 16, align: 8) { - ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────alloc17───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc14 (size: 72, align: 8) { +alloc17 (size: 72, align: 8) { 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc4────────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc7────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc11───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc8────────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc13───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } alloc4 (size: 0, align: 8) {} -alloc7 (size: 32, align: 8) { - 0x00 │ ╾───────alloc6────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────alloc8────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ +alloc8 (size: 32, align: 8) { + 0x00 │ ╾───────alloc7────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────alloc9────────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc6 (size: 3, align: 1) { +alloc7 (size: 3, align: 1) { 66 6f 6f │ foo } -alloc8 (size: 3, align: 1) { +alloc9 (size: 3, align: 1) { 62 61 72 │ bar } -alloc11 (size: 48, align: 8) { - 0x00 │ ╾───────alloc10───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x10 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x20 │ ╾───────alloc13───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ +alloc13 (size: 48, align: 8) { + 0x00 │ ╾───────alloc12───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x10 │ ╾───────alloc14───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x20 │ ╾───────alloc15───────╼ 04 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc10 (size: 3, align: 1) { +alloc12 (size: 3, align: 1) { 6d 65 68 │ meh } -alloc12 (size: 3, align: 1) { +alloc14 (size: 3, align: 1) { 6d 6f 70 │ mop } -alloc13 (size: 4, align: 1) { +alloc15 (size: 4, align: 1) { 6d c3 b6 70 │ m..p } diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir index 710ffeeda075a..c4f10064890a7 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir @@ -24,41 +24,41 @@ fn main() -> () { } alloc0 (static: FOO, size: 8, align: 4) { - ╾─alloc20─╼ 03 00 00 00 │ ╾──╼.... + ╾─alloc23─╼ 03 00 00 00 │ ╾──╼.... } -alloc20 (size: 48, align: 4) { +alloc23 (size: 48, align: 4) { 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc12─╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc19─╼ 03 00 00 00 │ ....*...╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc13─╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc21─╼ 03 00 00 00 │ ....*...╾──╼.... } alloc8 (size: 0, align: 4) {} -alloc12 (size: 8, align: 4) { - ╾─alloc10─╼ ╾─alloc11─╼ │ ╾──╼╾──╼ +alloc13 (size: 8, align: 4) { + ╾─alloc11─╼ ╾─alloc12─╼ │ ╾──╼╾──╼ } -alloc10 (size: 1, align: 1) { +alloc11 (size: 1, align: 1) { 05 │ . } -alloc11 (size: 1, align: 1) { +alloc12 (size: 1, align: 1) { 06 │ . } -alloc19 (size: 12, align: 4) { - ╾─a15+0x3─╼ ╾─alloc16─╼ ╾─a18+0x2─╼ │ ╾──╼╾──╼╾──╼ +alloc21 (size: 12, align: 4) { + ╾─a17+0x3─╼ ╾─alloc18─╼ ╾─a20+0x2─╼ │ ╾──╼╾──╼╾──╼ } -alloc15 (size: 4, align: 1) { +alloc17 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc16 (size: 1, align: 1) { +alloc18 (size: 1, align: 1) { 2a │ * } -alloc18 (size: 4, align: 1) { +alloc20 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index 97a7f76f6bb5d..b16b85c4e95ac 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -24,44 +24,44 @@ fn main() -> () { } alloc0 (static: FOO, size: 16, align: 8) { - ╾───────alloc20───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────alloc23───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc20 (size: 72, align: 8) { +alloc23 (size: 72, align: 8) { 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc8────────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc12───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc19───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc13───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc21───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } alloc8 (size: 0, align: 8) {} -alloc12 (size: 16, align: 8) { - ╾───────alloc10───────╼ ╾───────alloc11───────╼ │ ╾──────╼╾──────╼ +alloc13 (size: 16, align: 8) { + ╾───────alloc11───────╼ ╾───────alloc12───────╼ │ ╾──────╼╾──────╼ } -alloc10 (size: 1, align: 1) { +alloc11 (size: 1, align: 1) { 05 │ . } -alloc11 (size: 1, align: 1) { +alloc12 (size: 1, align: 1) { 06 │ . } -alloc19 (size: 24, align: 8) { - 0x00 │ ╾─────alloc15+0x3─────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾─────alloc18+0x2─────╼ │ ╾──────╼ +alloc21 (size: 24, align: 8) { + 0x00 │ ╾─────alloc17+0x3─────╼ ╾───────alloc18───────╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾─────alloc20+0x2─────╼ │ ╾──────╼ } -alloc15 (size: 4, align: 1) { +alloc17 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc16 (size: 1, align: 1) { +alloc18 (size: 1, align: 1) { 2a │ * } -alloc18 (size: 4, align: 1) { +alloc20 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].ConstProp.after.mir b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir similarity index 92% rename from src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].ConstProp.after.mir rename to src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 509947071b0c1..2497c553e6970 100644 --- a/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].ConstProp.after.mir +++ b/src/test/mir-opt/const_promotion_extern_static.BAR-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -1,4 +1,4 @@ -// MIR for `BAR::promoted[0]` after ConstProp +// MIR for `BAR::promoted[0]` after SimplifyCfg-elaborate-drops promoted[0] in BAR: &[&i32; 1] = { let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 @@ -14,7 +14,7 @@ promoted[0] in BAR: &[&i32; 1] = { // mir::Constant // + span: $DIR/const-promotion-extern-static.rs:9:33: 9:34 // + literal: Const { ty: &i32, val: Value(Scalar(alloc0)) } - _2 = _3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 + _2 = &(*_3); // scope 0 at $DIR/const-promotion-extern-static.rs:9:32: 9:34 _1 = [move _2]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 _0 = &_1; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 return; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35 diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir similarity index 95% rename from src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir rename to src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir index 88d583b815adb..17107ec431eff 100644 --- a/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].ConstProp.after.mir +++ b/src/test/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir @@ -1,4 +1,4 @@ -// MIR for `FOO::promoted[0]` after ConstProp +// MIR for `FOO::promoted[0]` after SimplifyCfg-elaborate-drops promoted[0] in FOO: &[&i32; 1] = { let mut _0: &[&i32; 1]; // return place in scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46 From 552f391969203868ec231b057dcfc72b790c3f60 Mon Sep 17 00:00:00 2001 From: oli <oli@uhura.edef.eu> Date: Wed, 21 Oct 2020 10:27:58 +0000 Subject: [PATCH 02/21] Make `encode_optimized_mir` always perform its action and instead require the callers to know whether they actually want this --- compiler/rustc_metadata/src/rmeta/encoder.rs | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index f6ae8275a8f32..c65f765e268f8 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1118,18 +1118,16 @@ impl EncodeContext<'a, 'tcx> { fn encode_optimized_mir(&mut self, def_id: LocalDefId) { debug!("EntryBuilder::encode_mir({:?})", def_id); - if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { - record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id)); + record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id)); - let unused = self.tcx.unused_generic_params(def_id); - if !unused.is_empty() { - record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused); - } + let unused = self.tcx.unused_generic_params(def_id); + if !unused.is_empty() { + record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused); + } - let abstract_const = self.tcx.mir_abstract_const(def_id); - if let Ok(Some(abstract_const)) = abstract_const { - record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const); - } + let abstract_const = self.tcx.mir_abstract_const(def_id); + if let Ok(Some(abstract_const)) = abstract_const { + record!(self.tables.mir_abstract_consts[def_id.to_def_id()] <- abstract_const); } } @@ -1413,8 +1411,10 @@ impl EncodeContext<'a, 'tcx> { let needs_inline = (generics.requires_monomorphization(tcx) || tcx.codegen_fn_attrs(def_id).requests_inline()) && !self.metadata_output_only(); + + let is_const_fn = sig.header.constness == hir::Constness::Const; let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; - needs_inline || sig.header.constness == hir::Constness::Const || always_encode_mir + needs_inline || is_const_fn || always_encode_mir } _ => false, }; From dadf937a12ca35ba1ea3646d415607278a2ddcbd Mon Sep 17 00:00:00 2001 From: oli <oli@uhura.edef.eu> Date: Mon, 26 Oct 2020 15:48:34 +0000 Subject: [PATCH 03/21] Remove mir encode calls that didn't actually encode anything --- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c65f765e268f8..24225d96ba47b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -758,8 +758,6 @@ impl EncodeContext<'a, 'tcx> { self.encode_generics(def_id); self.encode_explicit_predicates(def_id); self.encode_inferred_outlives(def_id); - self.encode_optimized_mir(def_id.expect_local()); - self.encode_promoted_mir(def_id.expect_local()); } fn encode_enum_variant_ctor(&mut self, def: &ty::AdtDef, index: VariantIdx) { From 248b4dbc4fcc03db855bbd2cfef88652a47c2010 Mon Sep 17 00:00:00 2001 From: oli <oli@uhura.edef.eu> Date: Mon, 26 Oct 2020 15:49:11 +0000 Subject: [PATCH 04/21] Limit trait item mir encoding to items with default bodies --- compiler/rustc_metadata/src/rmeta/encoder.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 24225d96ba47b..2774e817d3b9e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1013,8 +1013,15 @@ impl EncodeContext<'a, 'tcx> { self.encode_inferred_outlives(def_id); // This should be kept in sync with `PrefetchVisitor.visit_trait_item`. - self.encode_optimized_mir(def_id.expect_local()); - self.encode_promoted_mir(def_id.expect_local()); + match trait_item.kind { + ty::AssocKind::Type => {} + ty::AssocKind::Const | ty::AssocKind::Fn => { + if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) { + self.encode_optimized_mir(def_id.expect_local()); + self.encode_promoted_mir(def_id.expect_local()); + } + } + } } fn metadata_output_only(&self) -> bool { From 8e4fe6647f360f5175fd4984f3b5683606fe6879 Mon Sep 17 00:00:00 2001 From: oli <oli@uhura.edef.eu> Date: Mon, 26 Oct 2020 15:49:36 +0000 Subject: [PATCH 05/21] Require the `encode_promoted_mir` caller to know whether MIR for this item actually exists --- compiler/rustc_metadata/src/rmeta/encoder.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 2774e817d3b9e..c0cd82eeab844 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1138,9 +1138,7 @@ impl EncodeContext<'a, 'tcx> { fn encode_promoted_mir(&mut self, def_id: LocalDefId) { debug!("EncodeContext::encode_promoted_mir({:?})", def_id); - if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { - record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id)); - } + record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id)); } // Encodes the inherent implementations of a structure, enumeration, or trait. From cccd40f9b552367a8d1bb958b421a2e5e65c28ab Mon Sep 17 00:00:00 2001 From: oli <oli@uhura.edef.eu> Date: Mon, 26 Oct 2020 19:00:40 +0000 Subject: [PATCH 06/21] Keep an unoptimized duplicate of `const fn` around This allows CTFE to reliably detect UB, as otherwise optimizations may hide UB. --- compiler/rustc_metadata/src/rmeta/decoder.rs | 12 +++ .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 87 +++++++++++++++---- compiler/rustc_metadata/src/rmeta/mod.rs | 1 + compiler/rustc_middle/src/mir/query.rs | 9 ++ compiler/rustc_middle/src/query/mod.rs | 17 ++++ .../rustc_mir/src/interpret/eval_context.rs | 2 +- .../src/monomorphize/polymorphize.rs | 5 +- compiler/rustc_mir/src/transform/mod.rs | 70 +++++++++++++++ compiler/rustc_mir/src/util/pretty.rs | 6 +- .../src/traits/const_evaluatable.rs | 2 +- ...allocation2.main.ConstProp.after.32bit.mir | 30 +++---- ...allocation2.main.ConstProp.after.64bit.mir | 32 +++---- ...allocation3.main.ConstProp.after.32bit.mir | 16 ++-- ...allocation3.main.ConstProp.after.64bit.mir | 14 +-- ...9-assoc-const-static-recursion-impl.stderr | 2 +- ...onst-static-recursion-trait-default.stderr | 2 +- ...-assoc-const-static-recursion-trait.stderr | 2 +- .../ui/consts/const-eval/ub-nonnull.stderr | 4 +- src/test/ui/consts/const-eval/ub-wide-ptr.rs | 12 ++- .../ui/consts/const-eval/ub-wide-ptr.stderr | 74 ++++++++++------ src/test/ui/consts/const-size_of-cycle.stderr | 5 ++ .../const_refers_to_static_cross_crate.stderr | 4 +- src/test/ui/consts/ptr_comparisons.rs | 1 + src/test/ui/consts/ptr_comparisons.stderr | 14 ++- 25 files changed, 312 insertions(+), 112 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index c94893bb3a253..ae8b379703a89 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1162,6 +1162,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { fn is_item_mir_available(&self, id: DefIndex) -> bool { self.root.tables.mir.get(self, id).is_some() + || self.root.tables.mir_for_ctfe.get(self, id).is_some() } fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId { @@ -1183,6 +1184,17 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { .decode((self, tcx)) } + fn get_mir_for_ctfe(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Body<'tcx> { + self.root + .tables + .mir_for_ctfe + .get(self, id) + .unwrap_or_else(|| { + bug!("get_mir_for_ctfe: missing MIR for `{:?}`", self.local_def_id(id)) + }) + .decode((self, tcx)) + } + fn get_mir_abstract_const( &self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index b7f2288521790..0398f9667b62a 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -115,6 +115,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, }) } optimized_mir => { tcx.arena.alloc(cdata.get_optimized_mir(tcx, def_id.index)) } + mir_for_ctfe => { tcx.arena.alloc(cdata.get_mir_for_ctfe(tcx, def_id.index)) } promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) } mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) } unused_generic_params => { cdata.get_unused_generic_params(def_id.index) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index c0cd82eeab844..e74b2935ec35f 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -787,6 +787,7 @@ impl EncodeContext<'a, 'tcx> { self.encode_generics(def_id); self.encode_explicit_predicates(def_id); self.encode_inferred_outlives(def_id); + self.encode_mir_for_ctfe(def_id.expect_local()); self.encode_optimized_mir(def_id.expect_local()); self.encode_promoted_mir(def_id.expect_local()); } @@ -895,6 +896,7 @@ impl EncodeContext<'a, 'tcx> { self.encode_explicit_predicates(def_id); self.encode_inferred_outlives(def_id); self.encode_optimized_mir(def_id.expect_local()); + self.encode_mir_for_ctfe(def_id.expect_local()); self.encode_promoted_mir(def_id.expect_local()); } @@ -1015,7 +1017,13 @@ impl EncodeContext<'a, 'tcx> { // This should be kept in sync with `PrefetchVisitor.visit_trait_item`. match trait_item.kind { ty::AssocKind::Type => {} - ty::AssocKind::Const | ty::AssocKind::Fn => { + ty::AssocKind::Const => { + if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) { + self.encode_mir_for_ctfe(def_id.expect_local()); + self.encode_promoted_mir(def_id.expect_local()); + } + } + ty::AssocKind::Fn => { if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id.expect_local()) { self.encode_optimized_mir(def_id.expect_local()); self.encode_promoted_mir(def_id.expect_local()); @@ -1094,8 +1102,8 @@ impl EncodeContext<'a, 'tcx> { // The following part should be kept in sync with `PrefetchVisitor.visit_impl_item`. - let mir = match ast_item.kind { - hir::ImplItemKind::Const(..) => true, + let (mir, mir_const) = match ast_item.kind { + hir::ImplItemKind::Const(..) => (false, true), hir::ImplItemKind::Fn(ref sig, _) => { let generics = self.tcx.generics_of(def_id); let needs_inline = (generics.requires_monomorphization(self.tcx) @@ -1103,14 +1111,19 @@ impl EncodeContext<'a, 'tcx> { && !self.metadata_output_only(); let is_const_fn = sig.header.constness == hir::Constness::Const; let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; - needs_inline || is_const_fn || always_encode_mir + (needs_inline || always_encode_mir, is_const_fn) } - hir::ImplItemKind::TyAlias(..) => false, + hir::ImplItemKind::TyAlias(..) => (false, false), }; if mir { self.encode_optimized_mir(def_id.expect_local()); + } + if mir || mir_const { self.encode_promoted_mir(def_id.expect_local()); } + if mir_const { + self.encode_mir_for_ctfe(def_id.expect_local()); + } } fn encode_fn_param_names_for_body(&mut self, body_id: hir::BodyId) -> Lazy<[Ident]> { @@ -1121,9 +1134,9 @@ impl EncodeContext<'a, 'tcx> { self.lazy(param_names.iter()) } - fn encode_optimized_mir(&mut self, def_id: LocalDefId) { - debug!("EntryBuilder::encode_mir({:?})", def_id); - record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id)); + fn encode_mir_for_ctfe(&mut self, def_id: LocalDefId) { + debug!("EntryBuilder::encode_mir_for_ctfe({:?})", def_id); + record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- self.tcx.mir_for_ctfe(def_id)); let unused = self.tcx.unused_generic_params(def_id); if !unused.is_empty() { @@ -1136,6 +1149,16 @@ impl EncodeContext<'a, 'tcx> { } } + fn encode_optimized_mir(&mut self, def_id: LocalDefId) { + debug!("EntryBuilder::encode_optimized_mir({:?})", def_id); + record!(self.tables.mir[def_id.to_def_id()] <- self.tcx.optimized_mir(def_id)); + + let unused = self.tcx.unused_generic_params(def_id); + if !unused.is_empty() { + record!(self.tables.unused_generic_params[def_id.to_def_id()] <- unused); + } + } + fn encode_promoted_mir(&mut self, def_id: LocalDefId) { debug!("EncodeContext::encode_promoted_mir({:?})", def_id); record!(self.tables.promoted_mir[def_id.to_def_id()] <- self.tcx.promoted_mir(def_id)); @@ -1407,8 +1430,8 @@ impl EncodeContext<'a, 'tcx> { // The following part should be kept in sync with `PrefetchVisitor.visit_item`. - let mir = match item.kind { - hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true, + let (mir, const_mir) = match item.kind { + hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => (false, true), hir::ItemKind::Fn(ref sig, ..) => { let generics = tcx.generics_of(def_id); let needs_inline = (generics.requires_monomorphization(tcx) @@ -1417,14 +1440,21 @@ impl EncodeContext<'a, 'tcx> { let is_const_fn = sig.header.constness == hir::Constness::Const; let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; - needs_inline || is_const_fn || always_encode_mir + let mir = needs_inline || always_encode_mir; + // We don't need the optimized MIR for const fns. + (mir, is_const_fn) } - _ => false, + _ => (false, false), }; if mir { self.encode_optimized_mir(def_id.expect_local()); + } + if mir || const_mir { self.encode_promoted_mir(def_id.expect_local()); } + if const_mir { + self.encode_mir_for_ctfe(def_id.expect_local()); + } } /// Serialize the text of exported macros @@ -1489,7 +1519,7 @@ impl EncodeContext<'a, 'tcx> { self.encode_generics(def_id.to_def_id()); self.encode_explicit_predicates(def_id.to_def_id()); self.encode_inferred_outlives(def_id.to_def_id()); - self.encode_optimized_mir(def_id); + self.encode_mir_for_ctfe(def_id); self.encode_promoted_mir(def_id); } @@ -1954,6 +1984,12 @@ struct PrefetchVisitor<'tcx> { } impl<'tcx> PrefetchVisitor<'tcx> { + fn prefetch_ctfe_mir(&self, def_id: LocalDefId) { + if self.mir_keys.contains(&def_id) { + self.tcx.ensure().mir_for_ctfe(def_id); + self.tcx.ensure().promoted_mir(def_id); + } + } fn prefetch_mir(&self, def_id: LocalDefId) { if self.mir_keys.contains(&def_id) { self.tcx.ensure().optimized_mir(def_id); @@ -1968,16 +2004,19 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> { let tcx = self.tcx; match item.kind { hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => { - self.prefetch_mir(tcx.hir().local_def_id(item.hir_id)) + self.prefetch_ctfe_mir(tcx.hir().local_def_id(item.hir_id)) } hir::ItemKind::Fn(ref sig, ..) => { let def_id = tcx.hir().local_def_id(item.hir_id); let generics = tcx.generics_of(def_id.to_def_id()); let needs_inline = generics.requires_monomorphization(tcx) || tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline(); - if needs_inline || sig.header.constness == hir::Constness::Const { + if needs_inline { self.prefetch_mir(def_id) } + if sig.header.constness == hir::Constness::Const { + self.prefetch_ctfe_mir(def_id); + } } _ => (), } @@ -1985,7 +2024,16 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> { fn visit_trait_item(&self, trait_item: &'v hir::TraitItem<'v>) { // This should be kept in sync with `encode_info_for_trait_item`. - self.prefetch_mir(self.tcx.hir().local_def_id(trait_item.hir_id)); + let def_id = self.tcx.hir().local_def_id(trait_item.hir_id); + match trait_item.kind { + hir::TraitItemKind::Type(..) => {} + hir::TraitItemKind::Const(..) => { + self.prefetch_ctfe_mir(def_id); + } + hir::TraitItemKind::Fn(..) => { + self.prefetch_mir(def_id); + } + } } fn visit_impl_item(&self, impl_item: &'v hir::ImplItem<'v>) { @@ -1993,7 +2041,7 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> { let tcx = self.tcx; match impl_item.kind { hir::ImplItemKind::Const(..) => { - self.prefetch_mir(tcx.hir().local_def_id(impl_item.hir_id)) + self.prefetch_ctfe_mir(tcx.hir().local_def_id(impl_item.hir_id)) } hir::ImplItemKind::Fn(ref sig, _) => { let def_id = tcx.hir().local_def_id(impl_item.hir_id); @@ -2001,9 +2049,12 @@ impl<'tcx, 'v> ParItemLikeVisitor<'v> for PrefetchVisitor<'tcx> { let needs_inline = generics.requires_monomorphization(tcx) || tcx.codegen_fn_attrs(def_id.to_def_id()).requests_inline(); let is_const_fn = sig.header.constness == hir::Constness::Const; - if needs_inline || is_const_fn { + if needs_inline { self.prefetch_mir(def_id) } + if is_const_fn { + self.prefetch_ctfe_mir(def_id); + } } hir::ImplItemKind::TyAlias(..) => (), } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 5360617890964..59a8bc7fac1be 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -302,6 +302,7 @@ define_tables! { // As an optimization, a missing entry indicates an empty `&[]`. explicit_item_bounds: Table<DefIndex, Lazy!([(ty::Predicate<'tcx>, Span)])>, mir: Table<DefIndex, Lazy!(mir::Body<'tcx>)>, + mir_for_ctfe: Table<DefIndex, Lazy!(mir::Body<'tcx>)>, promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>, mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>, unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>, diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 89a93096f1c22..0fff7d98b29c1 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -450,6 +450,15 @@ impl<'tcx> TyCtxt<'tcx> { } } + #[inline] + pub fn mir_for_ctfe_opt_const_arg(self, def: ty::WithOptConstParam<DefId>) -> &'tcx Body<'tcx> { + if let Some((did, param_did)) = def.as_const_arg() { + self.mir_for_ctfe_of_const_arg((did, param_did)) + } else { + self.mir_for_ctfe(def.did) + } + } + #[inline] pub fn mir_abstract_const_opt_const_arg( self, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1e836d0a84253..5edeb8c9e6532 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -312,6 +312,20 @@ rustc_queries! { desc { |tcx| "elaborating drops for `{}`", tcx.def_path_str(key.did.to_def_id()) } } + query mir_for_ctfe( + key: DefId + ) -> &'tcx mir::Body<'tcx> { + desc { |tcx| "caching mir for `{}` for CTFE", tcx.def_path_str(key) } + cache_on_disk_if { key.is_local() } + } + + query mir_for_ctfe_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> { + desc { + |tcx| "MIR for CTFE of the const argument `{}`", + tcx.def_path_str(key.0.to_def_id()) + } + } + query mir_promoted(key: ty::WithOptConstParam<LocalDefId>) -> ( &'tcx Steal<mir::Body<'tcx>>, @@ -331,6 +345,9 @@ rustc_queries! { desc { |tcx| "optimizing MIR for `{}`", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } } + + // FIXME: now that we have `mir_for_ctfe_of_const_arg` can we get + // rid of this query? query optimized_mir_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> { desc { |tcx| "optimizing MIR for the const argument `{}`", diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 3d955576f0ff2..8cd09613074ef 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -480,7 +480,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { match instance { ty::InstanceDef::Item(def) => { if self.tcx.is_mir_available(def.did) { - Ok(self.tcx.optimized_mir_opt_const_arg(def)) + Ok(self.tcx.mir_for_ctfe_opt_const_arg(def)) } else { throw_unsup!(NoMirFor(def.did)) } diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index 0ce1c5a04893b..7a8f630315fa8 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -69,7 +69,10 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { debug!("unused_generic_params: (after default) unused_parameters={:?}", unused_parameters); // Visit MIR and accumululate used generic parameters. - let body = tcx.optimized_mir(def_id); + let body = match tcx.hir().body_const_context(def_id.expect_local()) { + None => tcx.optimized_mir(def_id), + Some(_) => tcx.mir_for_ctfe(def_id), + }; let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters }; vis.visit_body(body); debug!("unused_generic_params: (after visitor) unused_parameters={:?}", unused_parameters); diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 1f43752f976c6..52c2ba212a5cf 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -71,6 +71,8 @@ pub(crate) fn provide(providers: &mut Providers) { }, mir_promoted, mir_drops_elaborated_and_const_checked, + mir_for_ctfe, + mir_for_ctfe_of_const_arg, optimized_mir, optimized_mir_of_const_arg, is_mir_available, @@ -319,6 +321,63 @@ fn mir_promoted( (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } +fn mir_for_ctfe<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Body<'tcx> { + let did = def_id.expect_local(); + if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) { + tcx.mir_for_ctfe_of_const_arg(def) + } else { + tcx.arena.alloc(inner_mir_for_ctfe(tcx, ty::WithOptConstParam::unknown(did))) + } +} + +fn mir_for_ctfe_of_const_arg<'tcx>( + tcx: TyCtxt<'tcx>, + (did, param_did): (LocalDefId, DefId), +) -> &'tcx Body<'tcx> { + tcx.arena.alloc(inner_mir_for_ctfe( + tcx, + ty::WithOptConstParam { did, const_param_did: Some(param_did) }, + )) +} + +fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> { + // FIXME: don't duplicate this between the optimized_mir/mir_for_ctfe queries + if tcx.is_constructor(def.did.to_def_id()) { + // There's no reason to run all of the MIR passes on constructors when + // we can just output the MIR we want directly. This also saves const + // qualification and borrow checking the trouble of special casing + // constructors. + return shim::build_adt_ctor(tcx, def.did.to_def_id()); + } + + assert_ne!( + tcx.hir().body_const_context(def.did), + None, + "mir_for_ctfe should not be used for runtime functions" + ); + + let mut body = tcx.mir_drops_elaborated_and_const_checked(def).borrow().clone(); + + #[rustfmt::skip] + let optimizations: &[&dyn MirPass<'_>] = &[ + &const_prop::ConstProp, + ]; + + #[rustfmt::skip] + run_passes( + tcx, + &mut body, + MirPhase::Optimization, + &[ + optimizations, + ], + ); + + debug_assert!(!body.has_free_regions(), "Free regions in MIR for CTFE"); + + body +} + fn mir_drops_elaborated_and_const_checked<'tcx>( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>, @@ -484,6 +543,17 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) return shim::build_adt_ctor(tcx, def.did.to_def_id()); } + match tcx.hir().body_const_context(def.did) { + Some(hir::ConstContext::ConstFn) => { + if let Some((did, param_did)) = def.to_global().as_const_arg() { + tcx.ensure().mir_for_ctfe_of_const_arg((did, param_did)) + } else { + tcx.ensure().mir_for_ctfe(def.did) + } + } + None => {} + Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other), + } let mut body = tcx.mir_drops_elaborated_and_const_checked(def).steal(); run_optimization_passes(tcx, &mut body); diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 89ce29bd10129..0d1abd63772a7 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -273,7 +273,11 @@ pub fn write_mir_pretty<'tcx>( let mut first = true; for def_id in dump_mir_def_ids(tcx, single) { - let body = &tcx.optimized_mir(def_id); + let body = match tcx.hir().body_const_context(def_id.expect_local()) { + // FIXME: print both MIRs for `const fn`? + None | Some(rustc_hir::ConstContext::ConstFn) => tcx.optimized_mir(def_id), + Some(_) => tcx.mir_for_ctfe(def_id), + }; if first { first = false; diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index fdb2361ba0360..370ad577170ba 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -152,7 +152,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>( if concrete.is_ok() && substs.has_param_types_or_consts() { match infcx.tcx.def_kind(def.did) { DefKind::AnonConst => { - let mir_body = infcx.tcx.optimized_mir_opt_const_arg(def); + let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(def); if mir_body.is_polymorphic { future_compat_lint(); diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir index c4f10064890a7..d2e764f856f08 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.32bit.mir @@ -24,41 +24,41 @@ fn main() -> () { } alloc0 (static: FOO, size: 8, align: 4) { - ╾─alloc23─╼ 03 00 00 00 │ ╾──╼.... + ╾─alloc27─╼ 03 00 00 00 │ ╾──╼.... } -alloc23 (size: 48, align: 4) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc8──╼ 00 00 00 00 │ ....░░░░╾──╼.... - 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc13─╼ 02 00 00 00 │ ....░░░░╾──╼.... - 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc21─╼ 03 00 00 00 │ ....*...╾──╼.... +alloc27 (size: 48, align: 4) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾─alloc12─╼ 00 00 00 00 │ ....░░░░╾──╼.... + 0x10 │ 00 00 00 00 __ __ __ __ ╾─alloc17─╼ 02 00 00 00 │ ....░░░░╾──╼.... + 0x20 │ 01 00 00 00 2a 00 00 00 ╾─alloc25─╼ 03 00 00 00 │ ....*...╾──╼.... } -alloc8 (size: 0, align: 4) {} +alloc12 (size: 0, align: 4) {} -alloc13 (size: 8, align: 4) { - ╾─alloc11─╼ ╾─alloc12─╼ │ ╾──╼╾──╼ +alloc17 (size: 8, align: 4) { + ╾─alloc15─╼ ╾─alloc16─╼ │ ╾──╼╾──╼ } -alloc11 (size: 1, align: 1) { +alloc15 (size: 1, align: 1) { 05 │ . } -alloc12 (size: 1, align: 1) { +alloc16 (size: 1, align: 1) { 06 │ . } -alloc21 (size: 12, align: 4) { - ╾─a17+0x3─╼ ╾─alloc18─╼ ╾─a20+0x2─╼ │ ╾──╼╾──╼╾──╼ +alloc25 (size: 12, align: 4) { + ╾─a21+0x3─╼ ╾─alloc22─╼ ╾─a24+0x2─╼ │ ╾──╼╾──╼╾──╼ } -alloc17 (size: 4, align: 1) { +alloc21 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc18 (size: 1, align: 1) { +alloc22 (size: 1, align: 1) { 2a │ * } -alloc20 (size: 4, align: 1) { +alloc24 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir index b16b85c4e95ac..00bf91f90bf61 100644 --- a/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation2.main.ConstProp.after.64bit.mir @@ -24,44 +24,44 @@ fn main() -> () { } alloc0 (static: FOO, size: 16, align: 8) { - ╾───────alloc23───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ + ╾───────alloc27───────╼ 03 00 00 00 00 00 00 00 │ ╾──────╼........ } -alloc23 (size: 72, align: 8) { - 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc8────────╼ │ ....░░░░╾──────╼ +alloc27 (size: 72, align: 8) { + 0x00 │ 00 00 00 00 __ __ __ __ ╾───────alloc12───────╼ │ ....░░░░╾──────╼ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 __ __ __ __ │ ............░░░░ - 0x20 │ ╾───────alloc13───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ - 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc21───────╼ │ ....*...╾──────╼ + 0x20 │ ╾───────alloc17───────╼ 02 00 00 00 00 00 00 00 │ ╾──────╼........ + 0x30 │ 01 00 00 00 2a 00 00 00 ╾───────alloc25───────╼ │ ....*...╾──────╼ 0x40 │ 03 00 00 00 00 00 00 00 │ ........ } -alloc8 (size: 0, align: 8) {} +alloc12 (size: 0, align: 8) {} -alloc13 (size: 16, align: 8) { - ╾───────alloc11───────╼ ╾───────alloc12───────╼ │ ╾──────╼╾──────╼ +alloc17 (size: 16, align: 8) { + ╾───────alloc15───────╼ ╾───────alloc16───────╼ │ ╾──────╼╾──────╼ } -alloc11 (size: 1, align: 1) { +alloc15 (size: 1, align: 1) { 05 │ . } -alloc12 (size: 1, align: 1) { +alloc16 (size: 1, align: 1) { 06 │ . } -alloc21 (size: 24, align: 8) { - 0x00 │ ╾─────alloc17+0x3─────╼ ╾───────alloc18───────╼ │ ╾──────╼╾──────╼ - 0x10 │ ╾─────alloc20+0x2─────╼ │ ╾──────╼ +alloc25 (size: 24, align: 8) { + 0x00 │ ╾─────alloc21+0x3─────╼ ╾───────alloc22───────╼ │ ╾──────╼╾──────╼ + 0x10 │ ╾─────alloc24+0x2─────╼ │ ╾──────╼ } -alloc17 (size: 4, align: 1) { +alloc21 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } -alloc18 (size: 1, align: 1) { +alloc22 (size: 1, align: 1) { 2a │ * } -alloc20 (size: 4, align: 1) { +alloc24 (size: 4, align: 1) { 2a 45 15 6f │ *E.o } diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir index 99d3a278d6922..519002da392e2 100644 --- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir +++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.32bit.mir @@ -24,30 +24,30 @@ fn main() -> () { } alloc0 (static: FOO, size: 4, align: 4) { - ╾─alloc9──╼ │ ╾──╼ + ╾─alloc10─╼ │ ╾──╼ } -alloc9 (size: 168, align: 1) { +alloc10 (size: 168, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc4──╼ │ ............╾──╼ + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾─alloc5──╼ │ ............╾──╼ 0x20 │ 01 ef cd ab 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x50 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ - 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc6──╼ 00 00 │ ..........╾──╼.. - 0x90 │ ╾─a7+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ + 0x80 │ 00 00 00 00 00 00 00 00 00 00 ╾─alloc7──╼ 00 00 │ ..........╾──╼.. + 0x90 │ ╾─a8+0x63─╼ 00 00 00 00 00 00 00 00 00 00 00 00 │ ╾──╼............ 0xa0 │ 00 00 00 00 00 00 00 00 │ ........ } -alloc4 (size: 4, align: 4) { +alloc5 (size: 4, align: 4) { 2a 00 00 00 │ *... } -alloc6 (fn: main) +alloc7 (fn: main) -alloc7 (size: 100, align: 1) { +alloc8 (size: 100, align: 1) { 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ diff --git a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir index d6e49892d4c6a..73c4288c32e9d 100644 --- a/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir +++ b/src/test/mir-opt/const_allocation3.main.ConstProp.after.64bit.mir @@ -24,12 +24,12 @@ fn main() -> () { } alloc0 (static: FOO, size: 8, align: 8) { - ╾───────alloc9────────╼ │ ╾──────╼ + ╾───────alloc10───────╼ │ ╾──────╼ } -alloc9 (size: 180, align: 1) { +alloc10 (size: 180, align: 1) { 0x00 │ ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab ab │ ................ - 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc4── │ ............╾─── + 0x10 │ ab ab ab ab ab ab ab ab ab ab ab ab ╾──alloc5── │ ............╾─── 0x20 │ ──────────╼ 01 ef cd ab 00 00 00 00 00 00 00 00 │ ───╼............ 0x30 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x40 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ @@ -37,18 +37,18 @@ alloc9 (size: 180, align: 1) { 0x60 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x70 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x80 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ╾──── │ ..............╾─ - 0x90 │ ─────alloc6─────╼ 00 00 ╾─────alloc7+0x63─────╼ │ ─────╼..╾──────╼ + 0x90 │ ─────alloc7─────╼ 00 00 ╾─────alloc8+0x63─────╼ │ ─────╼..╾──────╼ 0xa0 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0xb0 │ 00 00 00 00 │ .... } -alloc4 (size: 4, align: 4) { +alloc5 (size: 4, align: 4) { 2a 00 00 00 │ *... } -alloc6 (fn: main) +alloc7 (fn: main) -alloc7 (size: 100, align: 1) { +alloc8 (size: 100, align: 1) { 0x00 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x10 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ 0x20 │ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 │ ................ diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr index d9bb7386565fa..f2dfac4ce3ed2 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -30,7 +30,7 @@ note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-a | LL | const BAR: u32 = IMPL_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires optimizing MIR for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR`... +note: ...which requires caching mir for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR` for CTFE... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 | LL | const BAR: u32 = IMPL_REF_BAR; diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr index d000d8ac097a4..2d5e8e869a978 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -30,7 +30,7 @@ note: ...which requires const-evaluating + checking `FooDefault::BAR`... | LL | const BAR: u32 = DEFAULT_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires optimizing MIR for `FooDefault::BAR`... +note: ...which requires caching mir for `FooDefault::BAR` for CTFE... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 | LL | const BAR: u32 = DEFAULT_REF_BAR; diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index 62d2051b6c23a..125961a88a700 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -30,7 +30,7 @@ note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-a | LL | const BAR: u32 = TRAIT_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires optimizing MIR for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR`... +note: ...which requires caching mir for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR` for CTFE... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 | LL | const BAR: u32 = TRAIT_REF_BAR; diff --git a/src/test/ui/consts/const-eval/ub-nonnull.stderr b/src/test/ui/consts/const-eval/ub-nonnull.stderr index afd8a4b9e59ef..39a568d054af4 100644 --- a/src/test/ui/consts/const-eval/ub-nonnull.stderr +++ b/src/test/ui/consts/const-eval/ub-nonnull.stderr @@ -7,13 +7,13 @@ LL | const NULL_PTR: NonNull<u8> = unsafe { mem::transmute(0usize) }; = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error: any use of this value will cause an error - --> $DIR/ub-nonnull.rs:18:29 + --> $DIR/ub-nonnull.rs:18:30 | LL | / const OUT_OF_BOUNDS_PTR: NonNull<u8> = { unsafe { LL | | let ptr: &[u8; 256] = mem::transmute(&0u8); // &0 gets promoted so it does not dangle LL | | // Use address-of-element for pointer arithmetic. This could wrap around to NULL! LL | | let out_of_bounds_ptr = &ptr[255]; - | | ^^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1 + | | ^^^^^^^^ memory access failed: pointer must be in-bounds at offset 256, but is outside bounds of alloc10 which has size 1 LL | | mem::transmute(out_of_bounds_ptr) LL | | } }; | |____- diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs index 3e148af8de9d5..bcd05b4cd7ec8 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs @@ -95,22 +95,26 @@ const RAW_SLICE_LENGTH_UNINIT: *const [u8] = unsafe { // # trait object // bad trait object +#[warn(const_err)] const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) }; -//~^ ERROR it is undefined behavior to use this value +//~^ WARN any use of this value will cause an error [const_err] // bad trait object +#[warn(const_err)] const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; -//~^ ERROR it is undefined behavior to use this value +//~^ WARN any use of this value will cause an error [const_err] // bad trait object +#[warn(const_err)] const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) }; -//~^ ERROR it is undefined behavior to use this value +//~^ WARN any use of this value will cause an error [const_err] const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; //~^ ERROR it is undefined behavior to use this value const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; //~^ ERROR it is undefined behavior to use this value const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; //~^ ERROR it is undefined behavior to use this value +#[warn(const_err)] const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: &dyn Trait = unsafe { mem::transmute((&92u8, &[&42u8; 8])) }; -//~^ ERROR it is undefined behavior to use this value +//~^ WARN any use of this value will cause an error [const_err] // bad data *inside* the trait object const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr index b7509108abc23..ec5d465c88251 100644 --- a/src/test/ui/consts/const-eval/ub-wide-ptr.stderr +++ b/src/test/ui/consts/const-eval/ub-wide-ptr.stderr @@ -134,32 +134,50 @@ LL | | }; | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:98:1 +warning: any use of this value will cause an error + --> $DIR/ub-wide-ptr.rs:99:55 | LL | const TRAIT_OBJ_SHORT_VTABLE_1: &dyn Trait = unsafe { mem::transmute((&92u8, &3u8)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable + | ------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. +note: the lint level is defined here + --> $DIR/ub-wide-ptr.rs:98:8 + | +LL | #[warn(const_err)] + | ^^^^^^^^^ -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:101:1 +warning: any use of this value will cause an error + --> $DIR/ub-wide-ptr.rs:103:55 | LL | const TRAIT_OBJ_SHORT_VTABLE_2: &dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable + | ------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. +note: the lint level is defined here + --> $DIR/ub-wide-ptr.rs:102:8 + | +LL | #[warn(const_err)] + | ^^^^^^^^^ -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:104:1 +warning: any use of this value will cause an error + --> $DIR/ub-wide-ptr.rs:107:51 | LL | const TRAIT_OBJ_INT_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, 4usize)) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer + | --------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unable to turn bytes into a pointer | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. +note: the lint level is defined here + --> $DIR/ub-wide-ptr.rs:106:8 + | +LL | #[warn(const_err)] + | ^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:106:1 + --> $DIR/ub-wide-ptr.rs:109:1 | LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92u8, &[0u8; 128])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered unaligned vtable pointer in wide pointer @@ -167,7 +185,7 @@ LL | const TRAIT_OBJ_UNALIGNED_VTABLE: &dyn Trait = unsafe { mem::transmute((&92 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:108:1 + --> $DIR/ub-wide-ptr.rs:111:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92u8, &[0usize; 8])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function) @@ -175,23 +193,29 @@ LL | const TRAIT_OBJ_BAD_DROP_FN_NULL: &dyn Trait = unsafe { mem::transmute((&92 = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:110:1 + --> $DIR/ub-wide-ptr.rs:113:1 | LL | const TRAIT_OBJ_BAD_DROP_FN_INT: &dyn Trait = unsafe { mem::transmute((&92u8, &[1usize; 8])) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function) | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. -error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:112:1 +warning: any use of this value will cause an error + --> $DIR/ub-wide-ptr.rs:116:63 | LL | const TRAIT_OBJ_BAD_DROP_FN_NOT_FN_PTR: &dyn Trait = unsafe { mem::transmute((&92u8, &[&42u8; 8])) }; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered invalid drop function pointer in vtable (not pointing to a function) + | --------------------------------------------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | "pointer-to-integer cast" needs an rfc before being allowed inside constants | - = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. +note: the lint level is defined here + --> $DIR/ub-wide-ptr.rs:115:8 + | +LL | #[warn(const_err)] + | ^^^^^^^^^ error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:116:1 + --> $DIR/ub-wide-ptr.rs:120:1 | LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0x03 at .<deref>.<dyn-downcast>, but expected a boolean @@ -199,7 +223,7 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:120:1 + --> $DIR/ub-wide-ptr.rs:124:1 | LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered dangling vtable pointer in wide pointer @@ -207,7 +231,7 @@ LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: it is undefined behavior to use this value - --> $DIR/ub-wide-ptr.rs:122:1 + --> $DIR/ub-wide-ptr.rs:126:1 | LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered too small vtable @@ -215,17 +239,17 @@ LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transm = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior. error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:128:5 + --> $DIR/ub-wide-ptr.rs:132:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, 0usize)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ inbounds test failed: 0x0 is not a valid pointer error[E0080]: could not evaluate static initializer - --> $DIR/ub-wide-ptr.rs:132:5 + --> $DIR/ub-wide-ptr.rs:136:5 | LL | mem::transmute::<_, &dyn Trait>((&92u8, &3u64)) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: pointer must be in-bounds at offset N, but is outside bounds of allocN which has size N -error: aborting due to 28 previous errors +error: aborting due to 24 previous errors; 4 warnings emitted For more information about this error, try `rustc --explain E0080`. diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index 129457ebdf929..631fab6e4f7f6 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -14,6 +14,11 @@ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`.. | LL | bytes: [u8; std::mem::size_of::<Foo>()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires simplifying constant for the type system `std::intrinsics::size_of`... + --> $SRC_DIR/core/src/intrinsics.rs:LL:COL + | +LL | pub fn size_of<T>() -> usize; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... = note: ...which requires normalizing `[u8; _]`... = note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle diff --git a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr index b65e50eb9f419..14eeabb49a2a0 100644 --- a/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr +++ b/src/test/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.stderr @@ -35,11 +35,11 @@ LL | U8_MUT => true, | ^^^^^^ warning: any use of this value will cause an error - --> $DIR/const_refers_to_static_cross_crate.rs:26:14 + --> $DIR/const_refers_to_static_cross_crate.rs:26:15 | LL | / const U8_MUT2: &u8 = { LL | | unsafe { &(*static_cross_crate::ZERO_REF)[0] } - | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static LL | | LL | | LL | | }; diff --git a/src/test/ui/consts/ptr_comparisons.rs b/src/test/ui/consts/ptr_comparisons.rs index be998c800381d..595ed30bf9c82 100644 --- a/src/test/ui/consts/ptr_comparisons.rs +++ b/src/test/ui/consts/ptr_comparisons.rs @@ -66,6 +66,7 @@ const _: *const u8 = //~^ NOTE unsafe { std::ptr::raw_const!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; //~^ ERROR any use of this value will cause an error +//~| NOTE const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; //~^ ERROR any use of this value will cause an error diff --git a/src/test/ui/consts/ptr_comparisons.stderr b/src/test/ui/consts/ptr_comparisons.stderr index 63faae275df80..49511b84500de 100644 --- a/src/test/ui/consts/ptr_comparisons.stderr +++ b/src/test/ui/consts/ptr_comparisons.stderr @@ -16,19 +16,17 @@ LL | const _: *const usize = unsafe { (FOO as *const usize).offset(2) }; = note: `#[deny(const_err)]` on by default error: any use of this value will cause an error - --> $DIR/ptr_comparisons.rs:67:14 + --> $DIR/ptr_comparisons.rs:67:35 | LL | / const _: *const u8 = LL | | LL | | unsafe { std::ptr::raw_const!((*(FOO as *const usize as *const [u8; 1000]))[999]) }; - | |______________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^__- - | | - | memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD - | - = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + | |___________________________________^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^___- + | | + | memory access failed: pointer must be in-bounds at offset 1000, but is outside bounds of alloc2 which has size $WORD error: any use of this value will cause an error - --> $DIR/ptr_comparisons.rs:70:27 + --> $DIR/ptr_comparisons.rs:71:27 | LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + 4 }; | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- @@ -36,7 +34,7 @@ LL | const _: usize = unsafe { std::mem::transmute::<*const usize, usize>(FOO) + | "pointer-to-integer cast" needs an rfc before being allowed inside constants error: any use of this value will cause an error - --> $DIR/ptr_comparisons.rs:75:27 + --> $DIR/ptr_comparisons.rs:76:27 | LL | const _: usize = unsafe { *std::mem::transmute::<&&usize, &usize>(&FOO) + 4 }; | --------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- From 1f5fb3e056428c3eb130ebb6fc95c7e1b7a2d20e Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Wed, 28 Oct 2020 13:12:49 +0000 Subject: [PATCH 07/21] Differentiate between the availability of ctfe MIR and runtime MIR --- compiler/rustc_metadata/src/rmeta/decoder.rs | 5 ++++- .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_middle/src/mir/query.rs | 2 +- compiler/rustc_middle/src/query/mod.rs | 13 ++++--------- compiler/rustc_middle/src/ty/mod.rs | 11 ++++++++++- .../rustc_mir/src/interpret/eval_context.rs | 2 +- .../src/monomorphize/polymorphize.rs | 19 +++++++++++++++---- compiler/rustc_mir/src/transform/mod.rs | 14 ++------------ 8 files changed, 38 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index ae8b379703a89..a4cf4f096e0e4 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1160,9 +1160,12 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { } } + fn is_ctfe_mir_available(&self, id: DefIndex) -> bool { + self.root.tables.mir_for_ctfe.get(self, id).is_some() + } + fn is_item_mir_available(&self, id: DefIndex) -> bool { self.root.tables.mir.get(self, id).is_some() - || self.root.tables.mir_for_ctfe.get(self, id).is_some() } fn module_expansion(&self, id: DefIndex, sess: &Session) -> ExpnId { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 0398f9667b62a..96db0157422a7 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -146,6 +146,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, impl_parent => { cdata.get_parent_impl(def_id.index) } trait_of_item => { cdata.get_trait_of_item(def_id.index) } is_mir_available => { cdata.is_item_mir_available(def_id.index) } + is_ctfe_mir_available => { cdata.is_ctfe_mir_available(def_id.index) } dylib_dependency_formats => { cdata.get_dylib_dependency_formats(tcx) } is_panic_runtime => { cdata.root.panic_runtime } diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 0fff7d98b29c1..3e4490e4915f1 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -444,7 +444,7 @@ impl<'tcx> TyCtxt<'tcx> { def: ty::WithOptConstParam<DefId>, ) -> &'tcx Body<'tcx> { if let Some((did, param_did)) = def.as_const_arg() { - self.optimized_mir_of_const_arg((did, param_did)) + self.mir_for_ctfe_of_const_arg((did, param_did)) } else { self.optimized_mir(def.did) } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 5edeb8c9e6532..6da61486a55ca 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -346,15 +346,6 @@ rustc_queries! { cache_on_disk_if { key.is_local() } } - // FIXME: now that we have `mir_for_ctfe_of_const_arg` can we get - // rid of this query? - query optimized_mir_of_const_arg(key: (LocalDefId, DefId)) -> &'tcx mir::Body<'tcx> { - desc { - |tcx| "optimizing MIR for the const argument `{}`", - tcx.def_path_str(key.0.to_def_id()) - } - } - /// Returns coverage summary info for a function, after executing the `InstrumentCoverage` /// MIR pass (assuming the -Zinstrument-coverage option is enabled). query coverageinfo(key: DefId) -> mir::CoverageInfo { @@ -944,6 +935,10 @@ rustc_queries! { } Codegen { + // FIXME: remove after figuring out how to make miri able to detect non-Rust function calls + query is_ctfe_mir_available(key: DefId) -> bool { + desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) } + } query is_mir_available(key: DefId) -> bool { desc { |tcx| "checking if item has mir available: `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1fe1400fabecf..ca4db8abc0ca4 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -3010,7 +3010,16 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns the possibly-auto-generated MIR of a `(DefId, Subst)` pair. pub fn instance_mir(self, instance: ty::InstanceDef<'tcx>) -> &'tcx Body<'tcx> { match instance { - ty::InstanceDef::Item(def) => self.optimized_mir_opt_const_arg(def), + ty::InstanceDef::Item(def) => match self.def_kind(def.did) { + DefKind::Const + | DefKind::Static + | DefKind::AssocConst + | DefKind::Ctor(..) + | DefKind::AnonConst => self.mir_for_ctfe_opt_const_arg(def), + // If the caller wants `mir_for_ctfe` they should not be using `instance_mir`, so + // we'll assume const fn also wants the optimized version. + _ => self.optimized_mir_opt_const_arg(def), + }, ty::InstanceDef::VtableShim(..) | ty::InstanceDef::ReifyShim(..) | ty::InstanceDef::Intrinsic(..) diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index 8cd09613074ef..b3b7c55db6276 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -479,7 +479,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { } match instance { ty::InstanceDef::Item(def) => { - if self.tcx.is_mir_available(def.did) { + if self.tcx.is_ctfe_mir_available(def.did) { Ok(self.tcx.mir_for_ctfe_opt_const_arg(def)) } else { throw_unsup!(NoMirFor(def.did)) diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index 7a8f630315fa8..d4185c063ef4b 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -54,9 +54,17 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { } // Exit early when there is no MIR available. - if !tcx.is_mir_available(def_id) { - debug!("unused_generic_params: (no mir available) def_id={:?}", def_id); - return FiniteBitSet::new_empty(); + let context = tcx.hir().body_const_context(def_id.expect_local()); + match context { + None if !tcx.is_mir_available(def_id) => { + debug!("unused_generic_params: (no mir available) def_id={:?}", def_id); + return FiniteBitSet::new_empty(); + } + Some(_) if !tcx.is_ctfe_mir_available(def_id) => { + debug!("unused_generic_params: (no ctfe mir available) def_id={:?}", def_id); + return FiniteBitSet::new_empty(); + } + _ => {} } // Create a bitset with N rightmost ones for each parameter. @@ -69,8 +77,11 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { debug!("unused_generic_params: (after default) unused_parameters={:?}", unused_parameters); // Visit MIR and accumululate used generic parameters. - let body = match tcx.hir().body_const_context(def_id.expect_local()) { + let body = match context { None => tcx.optimized_mir(def_id), + // FIXME(oli-obk): since this is solely used for codegen (I think?), should we keep using + // the optimized MIR for `const fn`? Need to adjust the above `is_mir_available` check + // in that case. Some(_) => tcx.mir_for_ctfe(def_id), }; let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters }; diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 52c2ba212a5cf..8a4c5c1ef69f0 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -74,8 +74,8 @@ pub(crate) fn provide(providers: &mut Providers) { mir_for_ctfe, mir_for_ctfe_of_const_arg, optimized_mir, - optimized_mir_of_const_arg, is_mir_available, + is_ctfe_mir_available: |tcx, did| is_mir_available(tcx, did), promoted_mir: |tcx, def_id| { let def_id = def_id.expect_local(); if let Some(def) = ty::WithOptConstParam::try_lookup(def_id, tcx) { @@ -518,22 +518,12 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> { let did = did.expect_local(); if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) { - tcx.optimized_mir_of_const_arg(def) + tcx.mir_for_ctfe_of_const_arg(def) } else { tcx.arena.alloc(inner_optimized_mir(tcx, ty::WithOptConstParam::unknown(did))) } } -fn optimized_mir_of_const_arg<'tcx>( - tcx: TyCtxt<'tcx>, - (did, param_did): (LocalDefId, DefId), -) -> &'tcx Body<'tcx> { - tcx.arena.alloc(inner_optimized_mir( - tcx, - ty::WithOptConstParam { did, const_param_did: Some(param_did) }, - )) -} - fn inner_optimized_mir(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> { if tcx.is_constructor(def.did.to_def_id()) { // There's no reason to run all of the MIR passes on constructors when From eb4e94b2e5f479ac44bf8d4094cdcb73d5941b22 Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Wed, 28 Oct 2020 13:49:10 +0000 Subject: [PATCH 08/21] Simplify the `optimize_mir` query --- compiler/rustc_middle/src/mir/query.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 2 +- compiler/rustc_mir/src/transform/mod.rs | 26 +++++++++---------------- 3 files changed, 11 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 3e4490e4915f1..a7b847fc5e0ee 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -439,7 +439,7 @@ impl<'tcx> TyCtxt<'tcx> { } #[inline] - pub fn optimized_mir_opt_const_arg( + pub fn optimized_mir_or_const_arg_mir( self, def: ty::WithOptConstParam<DefId>, ) -> &'tcx Body<'tcx> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ca4db8abc0ca4..ccdec2bf89f12 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -3018,7 +3018,7 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::AnonConst => self.mir_for_ctfe_opt_const_arg(def), // If the caller wants `mir_for_ctfe` they should not be using `instance_mir`, so // we'll assume const fn also wants the optimized version. - _ => self.optimized_mir_opt_const_arg(def), + _ => self.optimized_mir_or_const_arg_mir(def), }, ty::InstanceDef::VtableShim(..) | ty::InstanceDef::ReifyShim(..) diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 8a4c5c1ef69f0..edf6fe2e0efad 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -517,34 +517,26 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> { let did = did.expect_local(); - if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) { - tcx.mir_for_ctfe_of_const_arg(def) - } else { - tcx.arena.alloc(inner_optimized_mir(tcx, ty::WithOptConstParam::unknown(did))) - } + assert_eq!(ty::WithOptConstParam::try_lookup(did, tcx), None); + tcx.arena.alloc(inner_optimized_mir(tcx, did)) } -fn inner_optimized_mir(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> { - if tcx.is_constructor(def.did.to_def_id()) { +fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { + if tcx.is_constructor(did.to_def_id()) { // There's no reason to run all of the MIR passes on constructors when // we can just output the MIR we want directly. This also saves const // qualification and borrow checking the trouble of special casing // constructors. - return shim::build_adt_ctor(tcx, def.did.to_def_id()); + return shim::build_adt_ctor(tcx, did.to_def_id()); } - match tcx.hir().body_const_context(def.did) { - Some(hir::ConstContext::ConstFn) => { - if let Some((did, param_did)) = def.to_global().as_const_arg() { - tcx.ensure().mir_for_ctfe_of_const_arg((did, param_did)) - } else { - tcx.ensure().mir_for_ctfe(def.did) - } - } + match tcx.hir().body_const_context(did) { + Some(hir::ConstContext::ConstFn) => tcx.ensure().mir_for_ctfe(did), None => {} Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other), } - let mut body = tcx.mir_drops_elaborated_and_const_checked(def).steal(); + let mut body = + tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal(); run_optimization_passes(tcx, &mut body); debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR"); From db90150b91c1b3402e1a1419f857031c94fb074e Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Mon, 7 Dec 2020 12:38:26 +0000 Subject: [PATCH 09/21] Polymorphization should look at the runtime MIR of `const fn` --- compiler/rustc_mir/src/monomorphize/polymorphize.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index d4185c063ef4b..e51c9314595a2 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -56,7 +56,7 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { // Exit early when there is no MIR available. let context = tcx.hir().body_const_context(def_id.expect_local()); match context { - None if !tcx.is_mir_available(def_id) => { + Some(ConstContext::Fn) | None if !tcx.is_mir_available(def_id) => { debug!("unused_generic_params: (no mir available) def_id={:?}", def_id); return FiniteBitSet::new_empty(); } @@ -78,10 +78,9 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { // Visit MIR and accumululate used generic parameters. let body = match context { - None => tcx.optimized_mir(def_id), - // FIXME(oli-obk): since this is solely used for codegen (I think?), should we keep using - // the optimized MIR for `const fn`? Need to adjust the above `is_mir_available` check - // in that case. + // Const functions are actually called and should thus be considered for polymorphization + // via their runtime MIR + Some(ConstContext::Fn) | None => tcx.optimized_mir(def_id), Some(_) => tcx.mir_for_ctfe(def_id), }; let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters }; From 680c4022ae744e30e6344882919b444f1353baba Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Mon, 7 Dec 2020 12:39:10 +0000 Subject: [PATCH 10/21] Comment nit --- compiler/rustc_middle/src/ty/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index ccdec2bf89f12..a2c8fdb195060 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -3016,8 +3016,8 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::AssocConst | DefKind::Ctor(..) | DefKind::AnonConst => self.mir_for_ctfe_opt_const_arg(def), - // If the caller wants `mir_for_ctfe` they should not be using `instance_mir`, so - // we'll assume const fn also wants the optimized version. + // If the caller wants `mir_for_ctfe` of a function they should not be using + // `instance_mir`, so we'll assume const fn also wants the optimized version. _ => self.optimized_mir_or_const_arg_mir(def), }, ty::InstanceDef::VtableShim(..) From 720205480098bf08a201f4114d057573a5ece8e8 Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Mon, 7 Dec 2020 12:49:00 +0000 Subject: [PATCH 11/21] Document all the things --- compiler/rustc_mir/src/transform/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index edf6fe2e0efad..03e27991d9308 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -280,6 +280,7 @@ fn mir_const<'tcx>( tcx.alloc_steal_mir(body) } +/// Compute the main MIR body and the list of MIR bodies of the promoteds. fn mir_promoted( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>, @@ -321,6 +322,7 @@ fn mir_promoted( (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } +/// Compute the MIR that is used during CTFE (and thus has no optimizations run on it) fn mir_for_ctfe<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Body<'tcx> { let did = def_id.expect_local(); if let Some(def) = ty::WithOptConstParam::try_lookup(did, tcx) { @@ -330,6 +332,11 @@ fn mir_for_ctfe<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Body<'tcx> { } } +/// Same as `mir_for_ctfe`, but used to get the MIR of a const generic parameter. +/// The docs on `WithOptConstParam` explain this a bit more, but the TLDR is that +/// we'd get cycle errors with `mir_for_ctfe`, because typeck would need to typeck +/// the const parameter while type checking the main body, which in turn would try +/// to type check the main body again. fn mir_for_ctfe_of_const_arg<'tcx>( tcx: TyCtxt<'tcx>, (did, param_did): (LocalDefId, DefId), @@ -378,6 +385,9 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) - body } +/// Obtain just the main MIR (no promoteds) and run some cleanups on it. This also runs +/// mir borrowck *before* doing so in order to ensure that borrowck can be run and doesn't +/// end up missing the source MIR due to stealing happening. fn mir_drops_elaborated_and_const_checked<'tcx>( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>, @@ -515,6 +525,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { ); } +/// Optimize the MIR and prepare it for codegen. fn optimized_mir<'tcx>(tcx: TyCtxt<'tcx>, did: DefId) -> &'tcx Body<'tcx> { let did = did.expect_local(); assert_eq!(ty::WithOptConstParam::try_lookup(did, tcx), None); @@ -544,6 +555,8 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { body } +/// Fetch all the promoteds of an item and prepare their MIR bodies to be ready for +/// constant evaluation once all substitutions become known. fn promoted_mir<'tcx>( tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>, From f6d54aa0c165da52560e5c032b4c65bb11833e0e Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Mon, 7 Dec 2020 13:09:22 +0000 Subject: [PATCH 12/21] Adjust imports --- compiler/rustc_mir/src/monomorphize/polymorphize.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index e51c9314595a2..4ad71ab4913ba 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -5,7 +5,7 @@ //! generic parameters are unused (and eventually, in what ways generic parameters are used - only //! for their size, offset of a field, etc.). -use rustc_hir::{def::DefKind, def_id::DefId}; +use rustc_hir::{def::DefKind, def_id::DefId, ConstContext}; use rustc_index::bit_set::FiniteBitSet; use rustc_middle::mir::{ visit::{TyContext, Visitor}, @@ -56,7 +56,7 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { // Exit early when there is no MIR available. let context = tcx.hir().body_const_context(def_id.expect_local()); match context { - Some(ConstContext::Fn) | None if !tcx.is_mir_available(def_id) => { + Some(ConstContext::ConstFn) | None if !tcx.is_mir_available(def_id) => { debug!("unused_generic_params: (no mir available) def_id={:?}", def_id); return FiniteBitSet::new_empty(); } @@ -80,7 +80,7 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> { let body = match context { // Const functions are actually called and should thus be considered for polymorphization // via their runtime MIR - Some(ConstContext::Fn) | None => tcx.optimized_mir(def_id), + Some(ConstContext::ConstFn) | None => tcx.optimized_mir(def_id), Some(_) => tcx.mir_for_ctfe(def_id), }; let mut vis = MarkUsedGenericParams { tcx, def_id, unused_parameters: &mut unused_parameters }; From caeb3d525d297af51f7c7b509fafbaa32db9ed3e Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Mon, 7 Dec 2020 14:27:46 +0000 Subject: [PATCH 13/21] Move MIR body loading to a machine function --- compiler/rustc_mir/src/const_eval/machine.rs | 16 ++++++++++++++++ compiler/rustc_mir/src/interpret/eval_context.rs | 11 +---------- compiler/rustc_mir/src/interpret/machine.rs | 10 ++++++++++ compiler/rustc_mir/src/transform/const_prop.rs | 7 +++++++ 4 files changed, 34 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_mir/src/const_eval/machine.rs b/compiler/rustc_mir/src/const_eval/machine.rs index 72912dd76ff52..c28dad5d23968 100644 --- a/compiler/rustc_mir/src/const_eval/machine.rs +++ b/compiler/rustc_mir/src/const_eval/machine.rs @@ -200,6 +200,22 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, type MemoryExtra = MemoryExtra; + fn load_mir( + ecx: &InterpCx<'mir, 'tcx, Self>, + instance: ty::InstanceDef<'tcx>, + ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { + match instance { + ty::InstanceDef::Item(def) => { + if ecx.tcx.is_ctfe_mir_available(def.did) { + Ok(ecx.tcx.mir_for_ctfe_opt_const_arg(def)) + } else { + throw_unsup!(NoMirFor(def.did)) + } + } + _ => Ok(ecx.tcx.instance_mir(instance)), + } + } + fn find_mir_or_eval_fn( ecx: &mut InterpCx<'mir, 'tcx, Self>, instance: ty::Instance<'tcx>, diff --git a/compiler/rustc_mir/src/interpret/eval_context.rs b/compiler/rustc_mir/src/interpret/eval_context.rs index b3b7c55db6276..6d7781671d8cc 100644 --- a/compiler/rustc_mir/src/interpret/eval_context.rs +++ b/compiler/rustc_mir/src/interpret/eval_context.rs @@ -477,16 +477,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { if let Some(promoted) = promoted { return Ok(&self.tcx.promoted_mir_opt_const_arg(def)[promoted]); } - match instance { - ty::InstanceDef::Item(def) => { - if self.tcx.is_ctfe_mir_available(def.did) { - Ok(self.tcx.mir_for_ctfe_opt_const_arg(def)) - } else { - throw_unsup!(NoMirFor(def.did)) - } - } - _ => Ok(self.tcx.instance_mir(instance)), - } + M::load_mir(self, instance) } /// Call this on things you got out of the MIR (so it is as generic as the current diff --git a/compiler/rustc_mir/src/interpret/machine.rs b/compiler/rustc_mir/src/interpret/machine.rs index f50cc6c16ea16..32d60ef2ab192 100644 --- a/compiler/rustc_mir/src/interpret/machine.rs +++ b/compiler/rustc_mir/src/interpret/machine.rs @@ -131,6 +131,16 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Whether to enforce the validity invariant fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; + /// Entry point for obtaining the MIR of anything that should get evaluated. + /// So not just functions and shims, but also const/static initializers, anonymous + /// constants, ... + fn load_mir( + ecx: &InterpCx<'mir, 'tcx, Self>, + instance: ty::InstanceDef<'tcx>, + ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { + Ok(ecx.tcx.instance_mir(instance)) + } + /// Entry point to all function calls. /// /// Returns either the mir to use for the call, or `None` if execution should diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 1d949e020ed5c..c802550365697 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -184,6 +184,13 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx> type MemoryExtra = (); + fn load_mir( + _ecx: &InterpCx<'mir, 'tcx, Self>, + _instance: ty::InstanceDef<'tcx>, + ) -> InterpResult<'tcx, &'tcx Body<'tcx>> { + throw_machine_stop_str!("calling functions isn't supported in ConstProp") + } + fn find_mir_or_eval_fn( _ecx: &mut InterpCx<'mir, 'tcx, Self>, _instance: ty::Instance<'tcx>, From 9eaec139d0a71993f5b4eeef739bd565123b607e Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Sat, 26 Dec 2020 14:50:32 +0000 Subject: [PATCH 14/21] Small comment adjustments --- compiler/rustc_middle/src/query/mod.rs | 1 - compiler/rustc_mir/src/transform/mod.rs | 3 +++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 6da61486a55ca..1bf246a7b4f25 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -935,7 +935,6 @@ rustc_queries! { } Codegen { - // FIXME: remove after figuring out how to make miri able to detect non-Rust function calls query is_ctfe_mir_available(key: DefId) -> bool { desc { |tcx| "checking if item has ctfe mir available: `{}`", tcx.def_path_str(key) } } diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 03e27991d9308..a9bc11502bb90 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -542,6 +542,9 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { } match tcx.hir().body_const_context(did) { + /// Run the `mir_for_ctfe` query, which depends on `mir_drops_elaborated_and_const_checked` + /// which we are going to steal below. Thus we need to run `mir_for_ctfe` first, so it + /// computes and caches its result. Some(hir::ConstContext::ConstFn) => tcx.ensure().mir_for_ctfe(did), None => {} Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other), From a76dae4946a9e0d7c0be8e88410c9d729a491f71 Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Sat, 26 Dec 2020 14:51:53 +0000 Subject: [PATCH 15/21] Fix wording of query description --- compiler/rustc_middle/src/query/mod.rs | 2 +- .../issue-24949-assoc-const-static-recursion-impl.stderr | 2 +- ...ssue-24949-assoc-const-static-recursion-trait-default.stderr | 2 +- .../issue-24949-assoc-const-static-recursion-trait.stderr | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1bf246a7b4f25..fd8c1ac23d104 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -315,7 +315,7 @@ rustc_queries! { query mir_for_ctfe( key: DefId ) -> &'tcx mir::Body<'tcx> { - desc { |tcx| "caching mir for `{}` for CTFE", tcx.def_path_str(key) } + desc { |tcx| "caching mir of `{}` for CTFE", tcx.def_path_str(key) } cache_on_disk_if { key.is_local() } } diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr index f2dfac4ce3ed2..61b16cb9d5811 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -30,7 +30,7 @@ note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-a | LL | const BAR: u32 = IMPL_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires caching mir for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR` for CTFE... +note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 13:2>::BAR` for CTFE... --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 | LL | const BAR: u32 = IMPL_REF_BAR; diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr index 2d5e8e869a978..494dc0c0ed447 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -30,7 +30,7 @@ note: ...which requires const-evaluating + checking `FooDefault::BAR`... | LL | const BAR: u32 = DEFAULT_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires caching mir for `FooDefault::BAR` for CTFE... +note: ...which requires caching mir of `FooDefault::BAR` for CTFE... --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 | LL | const BAR: u32 = DEFAULT_REF_BAR; diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr index 125961a88a700..4ff253bffcb32 100644 --- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr +++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -30,7 +30,7 @@ note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-a | LL | const BAR: u32 = TRAIT_REF_BAR; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires caching mir for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR` for CTFE... +note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 13:2>::BAR` for CTFE... --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 | LL | const BAR: u32 = TRAIT_REF_BAR; From 3af7989a7ce0ef0d6bc9b8a6950f90abbf63ac76 Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Sat, 26 Dec 2020 15:10:06 +0000 Subject: [PATCH 16/21] No doc comments on expressions --- compiler/rustc_mir/src/transform/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index a9bc11502bb90..717479b999076 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -542,9 +542,9 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> { } match tcx.hir().body_const_context(did) { - /// Run the `mir_for_ctfe` query, which depends on `mir_drops_elaborated_and_const_checked` - /// which we are going to steal below. Thus we need to run `mir_for_ctfe` first, so it - /// computes and caches its result. + // Run the `mir_for_ctfe` query, which depends on `mir_drops_elaborated_and_const_checked` + // which we are going to steal below. Thus we need to run `mir_for_ctfe` first, so it + // computes and caches its result. Some(hir::ConstContext::ConstFn) => tcx.ensure().mir_for_ctfe(did), None => {} Some(other) => panic!("do not use `optimized_mir` for constants: {:?}", other), From 409195d4e50b2c2ae0fc49602350c8a5bdd6bd28 Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Sat, 26 Dec 2020 15:19:19 +0000 Subject: [PATCH 17/21] Update stderr files after rebase --- src/test/ui/consts/const-size_of-cycle.stderr | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/test/ui/consts/const-size_of-cycle.stderr b/src/test/ui/consts/const-size_of-cycle.stderr index 631fab6e4f7f6..129457ebdf929 100644 --- a/src/test/ui/consts/const-size_of-cycle.stderr +++ b/src/test/ui/consts/const-size_of-cycle.stderr @@ -14,11 +14,6 @@ note: ...which requires const-evaluating + checking `Foo::bytes::{constant#0}`.. | LL | bytes: [u8; std::mem::size_of::<Foo>()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires simplifying constant for the type system `std::intrinsics::size_of`... - --> $SRC_DIR/core/src/intrinsics.rs:LL:COL - | -LL | pub fn size_of<T>() -> usize; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Foo`... = note: ...which requires normalizing `[u8; _]`... = note: ...which again requires simplifying constant for the type system `Foo::bytes::{constant#0}`, completing the cycle From 65ee418e5c2de7d84353979bbd978ca09390ccba Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Mon, 4 Jan 2021 19:05:51 +0000 Subject: [PATCH 18/21] Do not run const prop on the `mir_for_ctfe` of `const fn` --- compiler/rustc_mir/src/transform/mod.rs | 53 ++++++++++++------- .../const_prop/ice-assert-fail-div-by-zero.rs | 4 +- .../ice-assert-fail-div-by-zero.stderr | 4 +- .../ui/consts/const-eval/issue-49296.stderr | 2 +- 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 717479b999076..11f7e6922ccbc 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -357,28 +357,43 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) - return shim::build_adt_ctor(tcx, def.did.to_def_id()); } - assert_ne!( - tcx.hir().body_const_context(def.did), - None, - "mir_for_ctfe should not be used for runtime functions" - ); + let context = tcx + .hir() + .body_const_context(def.did) + .expect("mir_for_ctfe should not be used for runtime functions"); let mut body = tcx.mir_drops_elaborated_and_const_checked(def).borrow().clone(); - #[rustfmt::skip] - let optimizations: &[&dyn MirPass<'_>] = &[ - &const_prop::ConstProp, - ]; - - #[rustfmt::skip] - run_passes( - tcx, - &mut body, - MirPhase::Optimization, - &[ - optimizations, - ], - ); + match context { + // Do not const prop functions, either they get executed at runtime or exported to metadata, + // so we run const prop on them, or they don't, in which case we const evaluate some control + // flow paths of the function and any errors in those paths will get emitted as const eval + // errors. + hir::ConstContext::ConstFn => {} + // Static items always get evaluated, so we can just let const eval see if any erroneous + // control flow paths get executed. + hir::ConstContext::Static(_) => {} + // Associated constants get const prop run so we detect common failure situations in the + // crate that defined the constant. + // Technically we want to not run on regular const items, but oli-obk doesn't know how to + // conveniently detect that at this point without looking at the HIR. + hir::ConstContext::Const => { + #[rustfmt::skip] + let optimizations: &[&dyn MirPass<'_>] = &[ + &const_prop::ConstProp, + ]; + + #[rustfmt::skip] + run_passes( + tcx, + &mut body, + MirPhase::Optimization, + &[ + optimizations, + ], + ); + } + } debug_assert!(!body.has_free_regions(), "Free regions in MIR for CTFE"); diff --git a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs index d19cf00eb9ce4..2afbf3432fb45 100644 --- a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs +++ b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.rs @@ -1,6 +1,8 @@ // check-pass -// compile-flags: --crate-type lib +// need to emit MIR, because const prop (which emits `unconditional_panic`) only runs if +// the `optimized_mir` query is run, which it isn't in check-only mode. +// compile-flags: --crate-type lib --emit=mir,link #![warn(unconditional_panic)] diff --git a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr index 276fb716d4255..865c69c3c8983 100644 --- a/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr +++ b/src/test/ui/const_prop/ice-assert-fail-div-by-zero.stderr @@ -1,11 +1,11 @@ warning: this operation will panic at runtime - --> $DIR/ice-assert-fail-div-by-zero.rs:11:5 + --> $DIR/ice-assert-fail-div-by-zero.rs:13:5 | LL | f.0 / 0; | ^^^^^^^ attempt to divide `_` by zero | note: the lint level is defined here - --> $DIR/ice-assert-fail-div-by-zero.rs:5:9 + --> $DIR/ice-assert-fail-div-by-zero.rs:7:9 | LL | #![warn(unconditional_panic)] | ^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/consts/const-eval/issue-49296.stderr b/src/test/ui/consts/const-eval/issue-49296.stderr index 798f130a4baf6..9363ffbb996e4 100644 --- a/src/test/ui/consts/const-eval/issue-49296.stderr +++ b/src/test/ui/consts/const-eval/issue-49296.stderr @@ -4,7 +4,7 @@ error: any use of this value will cause an error LL | const X: u64 = *wat(42); | ---------------^^^^^^^^- | | - | pointer to alloc2 was dereferenced after this allocation got freed + | pointer to alloc1 was dereferenced after this allocation got freed | = note: `#[deny(const_err)]` on by default From 41a732dfd498af4d5eeed9943ead3692b2d1db0c Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Tue, 5 Jan 2021 12:10:56 +0000 Subject: [PATCH 19/21] Remove a FIXME and explain the decision --- compiler/rustc_mir/src/util/pretty.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 0d1abd63772a7..ca8bcffa8966b 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -274,7 +274,8 @@ pub fn write_mir_pretty<'tcx>( let mut first = true; for def_id in dump_mir_def_ids(tcx, single) { let body = match tcx.hir().body_const_context(def_id.expect_local()) { - // FIXME: print both MIRs for `const fn`? + // For `const fn` we want to render the optimized MIR. If you want the mir used in + // ctfe, you can dump the MIR after the `Deaggregator` optimization pass. None | Some(rustc_hir::ConstContext::ConstFn) => tcx.optimized_mir(def_id), Some(_) => tcx.mir_for_ctfe(def_id), }; From e90b521a15f12863fced1023e700d02e015931a4 Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Mon, 11 Jan 2021 17:24:41 +0000 Subject: [PATCH 20/21] --emit=mir now emits both `mir_for_ctfe` and `optimized_mir` for `const fn` --- compiler/rustc_mir/src/util/pretty.rs | 32 ++++++++++++------ src/test/run-make/const_fn_mir/Makefile | 10 ++++++ src/test/run-make/const_fn_mir/dump.mir | 45 +++++++++++++++++++++++++ src/test/run-make/const_fn_mir/main.rs | 10 ++++++ 4 files changed, 86 insertions(+), 11 deletions(-) create mode 100644 src/test/run-make/const_fn_mir/Makefile create mode 100644 src/test/run-make/const_fn_mir/dump.mir create mode 100644 src/test/run-make/const_fn_mir/main.rs diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index ca8bcffa8966b..7fc1c3a73af91 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -273,13 +273,6 @@ pub fn write_mir_pretty<'tcx>( let mut first = true; for def_id in dump_mir_def_ids(tcx, single) { - let body = match tcx.hir().body_const_context(def_id.expect_local()) { - // For `const fn` we want to render the optimized MIR. If you want the mir used in - // ctfe, you can dump the MIR after the `Deaggregator` optimization pass. - None | Some(rustc_hir::ConstContext::ConstFn) => tcx.optimized_mir(def_id), - Some(_) => tcx.mir_for_ctfe(def_id), - }; - if first { first = false; } else { @@ -287,11 +280,28 @@ pub fn write_mir_pretty<'tcx>( writeln!(w)?; } - write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?; - - for body in tcx.promoted_mir(def_id) { - writeln!(w)?; + let render_body = |w: &mut dyn Write, body| -> io::Result<()> { write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?; + + for body in tcx.promoted_mir(def_id) { + writeln!(w)?; + write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?; + } + Ok(()) + }; + match tcx.hir().body_const_context(def_id.expect_local()) { + None => render_body(w, tcx.optimized_mir(def_id))?, + // For `const fn` we want to render the optimized MIR. If you want the mir used in + // ctfe, you can dump the MIR after the `Deaggregator` optimization pass. + Some(rustc_hir::ConstContext::ConstFn) => { + render_body(w, tcx.optimized_mir(def_id))?; + writeln!(w)?; + writeln!(w, "// MIR FOR CTFE")?; + // Do not use `render_body`, as that would render the promoteds again, but these + // are shared between mir_for_ctfe and optimized_mir + write_mir_fn(tcx, tcx.mir_for_ctfe(def_id), &mut |_, _| Ok(()), w)?; + } + Some(_) => render_body(w, tcx.mir_for_ctfe(def_id))?, } } Ok(()) diff --git a/src/test/run-make/const_fn_mir/Makefile b/src/test/run-make/const_fn_mir/Makefile new file mode 100644 index 0000000000000..2aa0bc9d45dc9 --- /dev/null +++ b/src/test/run-make/const_fn_mir/Makefile @@ -0,0 +1,10 @@ +-include ../../run-make-fulldeps/tools.mk + +all: + $(RUSTC) main.rs --emit=mir -o "$(TMPDIR)"/dump.mir + +ifdef RUSTC_BLESS_TEST + cp "$(TMPDIR)"/dump.mir dump.mir +else + $(DIFF) dump.mir "$(TMPDIR)"/dump.mir +endif diff --git a/src/test/run-make/const_fn_mir/dump.mir b/src/test/run-make/const_fn_mir/dump.mir new file mode 100644 index 0000000000000..3dac42c6782ea --- /dev/null +++ b/src/test/run-make/const_fn_mir/dump.mir @@ -0,0 +1,45 @@ +// WARNING: This output format is intended for human consumers only +// and is subject to change without notice. Knock yourself out. +fn main() -> () { + let mut _0: (); // return place in scope 0 at main.rs:8:11: 8:11 + let _1: i32; // in scope 0 at main.rs:9:5: 9:10 + + bb0: { + StorageLive(_1); // scope 0 at main.rs:9:5: 9:10 + _1 = foo() -> bb1; // scope 0 at main.rs:9:5: 9:10 + // mir::Constant + // + span: main.rs:9:5: 9:8 + // + literal: Const { ty: fn() -> i32 {foo}, val: Value(Scalar(<ZST>)) } + } + + bb1: { + StorageDead(_1); // scope 0 at main.rs:9:10: 9:11 + _0 = const (); // scope 0 at main.rs:8:11: 10:2 + return; // scope 0 at main.rs:10:2: 10:2 + } +} + +fn foo() -> i32 { + let mut _0: i32; // return place in scope 0 at main.rs:4:19: 4:22 + + bb0: { + _0 = const 11_i32; // scope 0 at main.rs:5:5: 5:10 + return; // scope 0 at main.rs:6:2: 6:2 + } +} + +// MIR FOR CTFE +fn foo() -> i32 { + let mut _0: i32; // return place in scope 0 at main.rs:4:19: 4:22 + let mut _1: (i32, bool); // in scope 0 at main.rs:5:5: 5:10 + + bb0: { + _1 = CheckedAdd(const 5_i32, const 6_i32); // scope 0 at main.rs:5:5: 5:10 + assert(!move (_1.1: bool), "attempt to compute `{} + {}`, which would overflow", const 5_i32, const 6_i32) -> bb1; // scope 0 at main.rs:5:5: 5:10 + } + + bb1: { + _0 = move (_1.0: i32); // scope 0 at main.rs:5:5: 5:10 + return; // scope 0 at main.rs:6:2: 6:2 + } +} diff --git a/src/test/run-make/const_fn_mir/main.rs b/src/test/run-make/const_fn_mir/main.rs new file mode 100644 index 0000000000000..e8552bd285a86 --- /dev/null +++ b/src/test/run-make/const_fn_mir/main.rs @@ -0,0 +1,10 @@ +// emit-mir +// check-pass + +const fn foo() -> i32 { + 5 + 6 +} + +fn main() { + foo(); +} From 53e3a23572b599844653fe8f4add4a02966dcd9b Mon Sep 17 00:00:00 2001 From: oli <github35764891676564198441@oli-obk.de> Date: Tue, 12 Jan 2021 15:12:03 +0000 Subject: [PATCH 21/21] Coverage computation needs access to the MIR, too --- .../rustc_mir/src/transform/coverage/query.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir/src/transform/coverage/query.rs b/compiler/rustc_mir/src/transform/coverage/query.rs index aa34ae70ef1a4..4b455a6a1ba72 100644 --- a/compiler/rustc_mir/src/transform/coverage/query.rs +++ b/compiler/rustc_mir/src/transform/coverage/query.rs @@ -4,7 +4,7 @@ use rustc_middle::mir::coverage::*; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, Coverage, CoverageInfo, Location}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::DefId; /// The `query` provider for `CoverageInfo`, requested by `codegen_coverage()` (to inject each @@ -112,7 +112,7 @@ impl Visitor<'_> for CoverageVisitor { } fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo { - let mir_body = tcx.optimized_mir(def_id); + let mir_body = mir_body(tcx, def_id); let mut coverage_visitor = CoverageVisitor { // num_counters always has at least the `ZERO` counter. @@ -129,8 +129,7 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo } fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Symbol> { - let mir_body = tcx.optimized_mir(def_id); - for bb_data in mir_body.basic_blocks().iter() { + for bb_data in mir_body(tcx, def_id).basic_blocks().iter() { for statement in bb_data.statements.iter() { if let StatementKind::Coverage(box ref coverage) = statement.kind { if let Some(code_region) = coverage.code_region.as_ref() { @@ -142,9 +141,17 @@ fn covered_file_name<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<Symbol> { None } +/// This function ensures we obtain the correct MIR for the given item irrespective of +/// whether that means const mir or runtime mir. For `const fn` this opts for runtime +/// mir. +fn mir_body<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx mir::Body<'tcx> { + let id = ty::WithOptConstParam::unknown(def_id); + let def = ty::InstanceDef::Item(id); + tcx.instance_mir(def) +} + fn covered_code_regions<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> Vec<&'tcx CodeRegion> { - let mir_body: &'tcx mir::Body<'tcx> = tcx.optimized_mir(def_id); - mir_body + mir_body(tcx, def_id) .basic_blocks() .iter() .map(|data| {