From 36728f1cdd6a8c379393372259cc280df7251913 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 19 Mar 2024 10:17:15 +0000 Subject: [PATCH] Replace `mir_built` query with a hook and use mir_const everywhere instead --- .../src/persist/dirty_clean.rs | 2 +- compiler/rustc_middle/src/hooks/mod.rs | 6 ++ compiler/rustc_middle/src/query/mod.rs | 7 -- .../rustc_mir_build/src/build/custom/mod.rs | 2 +- compiler/rustc_mir_build/src/build/mod.rs | 11 +--- .../rustc_mir_build/src/check_unsafety.rs | 4 +- compiler/rustc_mir_build/src/lib.rs | 4 +- .../rustc_mir_transform/src/check_unsafety.rs | 4 +- .../src/ffi_unwind_calls.rs | 2 +- compiler/rustc_mir_transform/src/lib.rs | 7 +- .../binding/issue-53114-safety-checks.stderr | 64 +++++++++---------- tests/ui/coroutine/clone-rpit.next.stderr | 7 +- ...tiple_definitions_attribute_merging.stderr | 2 +- .../proc_macro_generated_packed.stderr | 2 +- .../self-in-enum-definition.stderr | 5 -- 15 files changed, 56 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs index 24512dea939..90edc8a5d00 100644 --- a/compiler/rustc_incremental/src/persist/dirty_clean.rs +++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs @@ -65,7 +65,7 @@ const BASE_HIR: &[&str] = &[ const BASE_IMPL: &[&str] = &[label_strs::associated_item_def_ids, label_strs::generics_of, label_strs::impl_trait_header]; -/// DepNodes for mir_built/Optimized, which is relevant in "executable" +/// DepNodes for exported mir bodies, which is relevant in "executable" /// code, i.e., functions+methods const BASE_MIR: &[&str] = &[label_strs::optimized_mir, label_strs::promoted_mir]; diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs index b984df3646e..33447dfed93 100644 --- a/compiler/rustc_middle/src/hooks/mod.rs +++ b/compiler/rustc_middle/src/hooks/mod.rs @@ -77,4 +77,10 @@ declare_hooks! { /// /// (Eligible functions might nevertheless be skipped for other reasons.) hook is_eligible_for_coverage(key: LocalDefId) -> bool; + + /// Create the MIR for a given `DefId` - this includes + /// unreachable code. + /// You do not want to call this yourself, instead use the cached version + /// via `mir_const` + hook build_mir(key: LocalDefId) -> mir::Body<'tcx>; } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 9f0d2a89e6d..5e9432296ea 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -485,19 +485,12 @@ rustc_queries! { separate_provide_extern } - /// Fetch the MIR for a given `DefId` right after it's built - this includes - /// unreachable code. - query mir_built(key: LocalDefId) -> &'tcx Steal> { - desc { |tcx| "building MIR for `{}`", tcx.def_path_str(key) } - } - /// Fetch the MIR for a given `DefId` up till the point where it is /// ready for const qualification. /// /// See the README for the `mir` module for details. query mir_const(key: LocalDefId) -> &'tcx Steal> { desc { |tcx| "preparing `{}` for borrow checking", tcx.def_path_str(key) } - no_hash } /// Try to build an abstract representation of the given constant. diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index 288b787798b..edd72c2a10f 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -6,7 +6,7 @@ //! present, and if so we branch off into this module, which implements the attribute by //! implementing a custom lowering from THIR to MIR. //! -//! The result of this lowering is returned "normally" from the `mir_built` query, with the only +//! The result of this lowering is returned "normally" from the `build_mir` hook, with the only //! notable difference being that the `injected` field in the body is set. Various components of the //! MIR pipeline, like borrowck and the pass manager will then consult this field (via //! `body.should_skip()`) to skip the parts of the MIR pipeline that precede the MIR phase the user diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 411119b521b..dcd4a408986 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -18,6 +18,7 @@ use rustc_middle::hir::place::PlaceBase as HirPlaceBase; use rustc_middle::middle::region; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::*; +use rustc_middle::query::TyCtxtAt; use rustc_middle::thir::{ self, BindingMode, ExprId, LintLevel, LocalVarId, Param, ParamId, PatKind, Thir, }; @@ -30,13 +31,6 @@ use rustc_target::spec::abi::Abi; use super::lints; -pub(crate) fn mir_built( - tcx: TyCtxt<'_>, - def: LocalDefId, -) -> &rustc_data_structures::steal::Steal> { - tcx.alloc_steal_mir(mir_build(tcx, def)) -} - pub(crate) fn closure_saved_names_of_captured_variables<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, @@ -54,7 +48,8 @@ pub(crate) fn closure_saved_names_of_captured_variables<'tcx>( } /// Construct the MIR for a given `DefId`. -fn mir_build<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> Body<'tcx> { +pub(crate) fn mir_build<'tcx>(tcx: TyCtxtAt<'tcx>, def: LocalDefId) -> Body<'tcx> { + let tcx = tcx.tcx; tcx.ensure_with_value().thir_abstract_const(def); if let Err(e) = tcx.check_match(def) { return construct_error(tcx, def, e); diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 1ce8da162bf..9ccf71744a1 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -139,7 +139,7 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { fn visit_inner_body(&mut self, def: LocalDefId) { if let Ok((inner_thir, expr)) = self.tcx.thir_body(def) { // Runs all other queries that depend on THIR. - self.tcx.ensure_with_value().mir_built(def); + self.tcx.ensure_with_value().mir_const(def); let inner_thir = &inner_thir.steal(); let hir_context = self.tcx.local_def_id_to_hir_id(def); let safety_context = mem::replace(&mut self.safety_context, SafetyContext::Safe); @@ -921,7 +921,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { let Ok((thir, expr)) = tcx.thir_body(def) else { return }; // Runs all other queries that depend on THIR. - tcx.ensure_with_value().mir_built(def); + tcx.ensure_with_value().mir_const(def); let thir = &thir.steal(); // If `thir` is empty, a type error occurred, skip this body. if thir.exprs.is_empty() { diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index b9a20cb21e9..25bd43de88f 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -23,14 +23,14 @@ mod errors; pub mod lints; mod thir; -use rustc_middle::query::Providers; +use rustc_middle::util::Providers; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } pub fn provide(providers: &mut Providers) { providers.check_match = thir::pattern::check_match; providers.lit_to_const = thir::constant::lit_to_const; - providers.mir_built = build::mir_built; + providers.hooks.build_mir = build::mir_build; providers.closure_saved_names_of_captured_variables = build::closure_saved_names_of_captured_variables; providers.check_unsafety = check_unsafety::check_unsafety; diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index a0c3de3af58..bf463021d4b 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -497,8 +497,8 @@ fn mir_unsafety_check_result(tcx: TyCtxt<'_>, def: LocalDefId) -> &UnsafetyCheck debug!("unsafety_violations({:?})", def); // N.B., this borrow is valid because all the consumers of - // `mir_built` force this. - let body = &tcx.mir_built(def).borrow(); + // `mir_const` force this. + let body = &tcx.mir_const(def).borrow(); if body.is_custom_mir() || body.tainted_by_errors.is_some() { return tcx.arena.alloc(UnsafetyCheckResult { diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs index 0970c4de19f..16a417d9a38 100644 --- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs +++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs @@ -53,7 +53,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool { return false; } - let body = &*tcx.mir_built(local_def_id).borrow(); + let body = &*tcx.mir_const(local_def_id).borrow(); let body_ty = tcx.type_of(def_id).skip_binder(); let body_abi = match body_ty.kind() { diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index afe228be127..9d6463b34ad 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -288,10 +288,7 @@ fn mir_const(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal> { tcx.ensure_with_value().mir_unsafety_check_result(def); } - // has_ffi_unwind_calls query uses the raw mir, so make sure it is run. - tcx.ensure_with_value().has_ffi_unwind_calls(def); - - let mut body = tcx.mir_built(def).steal(); + let mut body = tcx.build_mir(def); pass_manager::dump_mir_for_phase_change(tcx, &body); @@ -339,6 +336,8 @@ fn mir_promoted( | DefKind::AnonConst => tcx.mir_const_qualif(def), _ => ConstQualifs::default(), }; + // has_ffi_unwind_calls query uses the raw mir, so make sure it is run. + tcx.ensure_with_value().has_ffi_unwind_calls(def); let mut body = tcx.mir_const(def).steal(); if let Some(error_reported) = const_qualifs.tainted_by_errors { body.tainted_by_errors = Some(error_reported); diff --git a/tests/ui/binding/issue-53114-safety-checks.stderr b/tests/ui/binding/issue-53114-safety-checks.stderr index b7d805d9171..9d909e915c2 100644 --- a/tests/ui/binding/issue-53114-safety-checks.stderr +++ b/tests/ui/binding/issue-53114-safety-checks.stderr @@ -1,3 +1,23 @@ +error[E0793]: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:23:13 + | +LL | let _ = &p.b; + | ^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + +error[E0793]: reference to packed field is unaligned + --> $DIR/issue-53114-safety-checks.rs:28:17 + | +LL | let (_,) = (&p.b,); + | ^^^^ + | + = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses + = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) + = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) + error[E0133]: access to union field is unsafe and requires unsafe function or block --> $DIR/issue-53114-safety-checks.rs:24:13 | @@ -31,20 +51,20 @@ LL | let (_,) = (&u2.a,); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0793]: reference to packed field is unaligned - --> $DIR/issue-53114-safety-checks.rs:23:13 + --> $DIR/issue-53114-safety-checks.rs:37:16 | -LL | let _ = &p.b; - | ^^^^ +LL | let _: _ = &p.b; + | ^^^^ | = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/issue-53114-safety-checks.rs:28:17 + --> $DIR/issue-53114-safety-checks.rs:42:20 | -LL | let (_,) = (&p.b,); - | ^^^^ +LL | let (_,): _ = (&p.b,); + | ^^^^ | = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) @@ -83,20 +103,20 @@ LL | let (_,): _ = (&u2.a,); = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior error[E0793]: reference to packed field is unaligned - --> $DIR/issue-53114-safety-checks.rs:37:16 + --> $DIR/issue-53114-safety-checks.rs:51:11 | -LL | let _: _ = &p.b; - | ^^^^ +LL | match &p.b { _ => { } } + | ^^^^ | = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) error[E0793]: reference to packed field is unaligned - --> $DIR/issue-53114-safety-checks.rs:42:20 + --> $DIR/issue-53114-safety-checks.rs:56:12 | -LL | let (_,): _ = (&p.b,); - | ^^^^ +LL | match (&p.b,) { (_,) => { } } + | ^^^^ | = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) @@ -134,26 +154,6 @@ LL | match (&u2.a,) { (_,) => { } } | = note: the field may not be properly initialized: using uninitialized data will cause undefined behavior -error[E0793]: reference to packed field is unaligned - --> $DIR/issue-53114-safety-checks.rs:51:11 - | -LL | match &p.b { _ => { } } - | ^^^^ - | - = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses - = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) - = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) - -error[E0793]: reference to packed field is unaligned - --> $DIR/issue-53114-safety-checks.rs:56:12 - | -LL | match (&p.b,) { (_,) => { } } - | ^^^^ - | - = note: packed structs are only aligned by one byte, and many modern architectures penalize unaligned field accesses - = note: creating a misaligned reference is undefined behavior (even if that reference is never dereferenced) - = help: copy the field contents to a local variable, or replace the reference with a raw pointer and use `read_unaligned`/`write_unaligned` (loads and stores via `*p` must be properly aligned even when using raw pointers) - error: aborting due to 18 previous errors Some errors have detailed explanations: E0133, E0793. diff --git a/tests/ui/coroutine/clone-rpit.next.stderr b/tests/ui/coroutine/clone-rpit.next.stderr index 02d3390496a..f1634324d3f 100644 --- a/tests/ui/coroutine/clone-rpit.next.stderr +++ b/tests/ui/coroutine/clone-rpit.next.stderr @@ -14,17 +14,12 @@ note: ...which requires promoting constants in MIR for `foo::{closure#0}`... | LL | move |_: ()| { | ^^^^^^^^^^^^ -note: ...which requires preparing `foo::{closure#0}` for borrow checking... - --> $DIR/clone-rpit.rs:14:5 - | -LL | move |_: ()| { - | ^^^^^^^^^^^^ note: ...which requires checking if `foo::{closure#0}` contains FFI-unwind calls... --> $DIR/clone-rpit.rs:14:5 | LL | move |_: ()| { | ^^^^^^^^^^^^ -note: ...which requires building MIR for `foo::{closure#0}`... +note: ...which requires preparing `foo::{closure#0}` for borrow checking... --> $DIR/clone-rpit.rs:14:5 | LL | move |_: ()| { diff --git a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr index b2d20af883a..563db44c946 100644 --- a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr +++ b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr @@ -19,7 +19,7 @@ LL | struct Dealigned(u8, T); = Box query stack during panic: #0 [mir_const] preparing `::eq` for borrow checking -#1 [mir_promoted] promoting constants in MIR for `::eq` +#1 [check_unsafety] unsafety-checking `::eq` end of query stack error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/proc_macro_generated_packed.stderr b/tests/ui/resolve/proc_macro_generated_packed.stderr index 507e5867c90..4c515b9809b 100644 --- a/tests/ui/resolve/proc_macro_generated_packed.stderr +++ b/tests/ui/resolve/proc_macro_generated_packed.stderr @@ -10,7 +10,7 @@ LL | struct Dealigned(u8, T); = Box query stack during panic: #0 [mir_const] preparing `::eq` for borrow checking -#1 [mir_promoted] promoting constants in MIR for `::eq` +#1 [check_unsafety] unsafety-checking `::eq` end of query stack error: aborting due to 1 previous error diff --git a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr index df466609a12..f1e3518aa82 100644 --- a/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr +++ b/tests/ui/type-alias-enum-variants/self-in-enum-definition.stderr @@ -37,11 +37,6 @@ LL | V3 = Self::V1 {} as u8 + 2, note: ...which requires preparing `Alpha::V3::{constant#0}` for borrow checking... --> $DIR/self-in-enum-definition.rs:5:10 | -LL | V3 = Self::V1 {} as u8 + 2, - | ^^^^^^^^^^^^^^^^^^^^^ -note: ...which requires building MIR for `Alpha::V3::{constant#0}`... - --> $DIR/self-in-enum-definition.rs:5:10 - | LL | V3 = Self::V1 {} as u8 + 2, | ^^^^^^^^^^^^^^^^^^^^^ = note: ...which requires computing layout of `Alpha`...