From 1ccb1de5992dce38f7b8a941ee390a4f9aee1159 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Fri, 3 Mar 2023 04:54:42 +0100 Subject: [PATCH 01/11] Place size limits on query keys and values --- compiler/rustc_middle/src/ty/query.rs | 30 +++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/compiler/rustc_middle/src/ty/query.rs b/compiler/rustc_middle/src/ty/query.rs index 2bc51baf87905..9d41e4af959c7 100644 --- a/compiler/rustc_middle/src/ty/query.rs +++ b/compiler/rustc_middle/src/ty/query.rs @@ -250,6 +250,36 @@ macro_rules! define_callbacks { )* } + $( + // Ensure that keys grow no larger than 64 bytes + #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] + const _: () = { + if mem::size_of::>() > 64 { + panic!("{}", concat!( + "the query `", + stringify!($name), + "` has a key type `", + stringify!($($K)*), + "` that is too large" + )); + } + }; + + // Ensure that values grow no larger than 64 bytes + #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] + const _: () = { + if mem::size_of::>() > 64 { + panic!("{}", concat!( + "the query `", + stringify!($name), + "` has a value type `", + stringify!($V), + "` that is too large" + )); + } + }; + )* + pub struct QueryArenas<'tcx> { $($(#[$attr])* pub $name: query_if_arena!([$($modifiers)*] (WorkerLocal::Target>>) From 40185dba540dcbbc9e20e29b15fd69a25d52c256 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Fri, 3 Mar 2023 16:56:07 -0800 Subject: [PATCH 02/11] Delete old re-exports from rustc_smir This approach didn't seem to work well. --- compiler/rustc_smir/src/lib.rs | 4 ---- compiler/rustc_smir/src/mir.rs | 10 --------- compiler/rustc_smir/src/very_unstable.rs | 27 ------------------------ 3 files changed, 41 deletions(-) delete mode 100644 compiler/rustc_smir/src/mir.rs delete mode 100644 compiler/rustc_smir/src/very_unstable.rs diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index 3e93c6bba977f..280b704f23326 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -13,7 +13,3 @@ #![cfg_attr(not(feature = "default"), feature(rustc_private))] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] - -pub mod mir; - -pub mod very_unstable; diff --git a/compiler/rustc_smir/src/mir.rs b/compiler/rustc_smir/src/mir.rs deleted file mode 100644 index 887e657293066..0000000000000 --- a/compiler/rustc_smir/src/mir.rs +++ /dev/null @@ -1,10 +0,0 @@ -pub use crate::very_unstable::hir::ImplicitSelfKind; -pub use crate::very_unstable::middle::mir::{ - visit::MutVisitor, AggregateKind, AssertKind, BasicBlock, BasicBlockData, BinOp, BindingForm, - BlockTailInfo, Body, BorrowKind, CastKind, ClearCrossCrate, Constant, ConstantKind, - CopyNonOverlapping, Coverage, FakeReadCause, Field, GeneratorInfo, InlineAsmOperand, Local, - LocalDecl, LocalInfo, LocalKind, Location, MirPhase, MirSource, NullOp, Operand, Place, - PlaceRef, ProjectionElem, ProjectionKind, Promoted, RetagKind, Rvalue, Safety, SourceInfo, - SourceScope, SourceScopeData, SourceScopeLocalData, Statement, StatementKind, UnOp, - UserTypeProjection, UserTypeProjections, VarBindingForm, VarDebugInfo, VarDebugInfoContents, -}; diff --git a/compiler/rustc_smir/src/very_unstable.rs b/compiler/rustc_smir/src/very_unstable.rs deleted file mode 100644 index 12ba133dbb169..0000000000000 --- a/compiler/rustc_smir/src/very_unstable.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! This module reexports various crates and modules from unstable rustc APIs. -//! Add anything you need here and it will get slowly transferred to a stable API. -//! Only use rustc_smir in your dependencies and use the reexports here instead of -//! directly referring to the unstable crates. - -macro_rules! crates { - ($($rustc_name:ident -> $name:ident,)*) => { - $( - #[cfg(not(feature = "default"))] - pub extern crate $rustc_name as $name; - #[cfg(feature = "default")] - pub use $rustc_name as $name; - )* - } -} - -crates! { - rustc_borrowck -> borrowck, - rustc_driver -> driver, - rustc_hir -> hir, - rustc_interface -> interface, - rustc_middle -> middle, - rustc_mir_dataflow -> dataflow, - rustc_mir_transform -> transform, - rustc_serialize -> serialize, - rustc_trait_selection -> trait_selection, -} From 118afdf071ce38f91c054f013c1774926fa28b15 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 4 Mar 2023 23:31:56 +0000 Subject: [PATCH 03/11] Retry pred_known_to_hold_modulo_regions with fulfillment if ambiguous --- compiler/rustc_trait_selection/src/traits/mod.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index b2317f55d2595..4e30108be94b8 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -155,10 +155,12 @@ fn pred_known_to_hold_modulo_regions<'tcx>( predicate: pred.to_predicate(infcx.tcx), }; - let result = infcx.predicate_must_hold_modulo_regions(&obligation); + let result = infcx.evaluate_obligation_no_overflow(&obligation); debug!(?result); - if result && has_non_region_infer { + if result.must_apply_modulo_regions() && !has_non_region_infer { + true + } else if result.may_apply() { // Because of inference "guessing", selection can sometimes claim // to succeed while the success requires a guess. To ensure // this function's result remains infallible, we must confirm @@ -179,7 +181,7 @@ fn pred_known_to_hold_modulo_regions<'tcx>( } } } else { - result + false } } From bfefd11bddc10f732045f61b188c5e567412dcf2 Mon Sep 17 00:00:00 2001 From: Jubilee <46493976+workingjubilee@users.noreply.github.com> Date: Sat, 4 Mar 2023 19:44:23 -0800 Subject: [PATCH 04/11] 1.41.1 supported 32-bit Apple targets --- RELEASES.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 00d0171de6dfc..edc16438b3b94 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -3765,6 +3765,8 @@ Version 1.41.1 (2020-02-27) * [Always check types of static items][69145] * [Always check lifetime bounds of `Copy` impls][69145] * [Fix miscompilation in callers of `Layout::repeat`][69225] +* [Rust 1.41.0 was announced as the last Rust release with tier 1 or tier 2 support for 32-bit Apple targets][apple-32bit-drop]. + That announcement did not expect a patch release. 1.41.1 also includes release binaries for these targets. [69225]: https://github.com/rust-lang/rust/issues/69225 [69145]: https://github.com/rust-lang/rust/pull/69145 @@ -3857,7 +3859,7 @@ Misc Compatibility Notes ------------------- -- [As previously announced 1.41.0 will be the last tier 1 release for 32-bit +- [As previously announced 1.41 will be the last tier 1 release for 32-bit Apple targets.][apple-32bit-drop] This means that the source code is still available to build, but the targets are no longer being tested and release binaries for those platforms will no longer be distributed by the Rust project. From ef807cb321604ae96ed0f78c78e3e9348d6d11ba Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 23 Dec 2022 14:59:42 +0000 Subject: [PATCH 05/11] use problem matchers for tidy CI --- src/ci/github-actions/problem_matchers.json | 15 +++++++++++++++ src/ci/scripts/run-build-from-ci.sh | 2 ++ 2 files changed, 17 insertions(+) create mode 100644 src/ci/github-actions/problem_matchers.json diff --git a/src/ci/github-actions/problem_matchers.json b/src/ci/github-actions/problem_matchers.json new file mode 100644 index 0000000000000..37561924b7d4f --- /dev/null +++ b/src/ci/github-actions/problem_matchers.json @@ -0,0 +1,15 @@ +{ + "problemMatcher": [ + { + "owner": "tidy-error-file-line", + "pattern": [ + { + "regexp": "^tidy error: /checkout/(.+):(\\d+): (.+)$", + "file": 1, + "line": 2, + "message": 3 + } + ] + } + ] +} diff --git a/src/ci/scripts/run-build-from-ci.sh b/src/ci/scripts/run-build-from-ci.sh index c02117f459de0..55e75800d91c4 100755 --- a/src/ci/scripts/run-build-from-ci.sh +++ b/src/ci/scripts/run-build-from-ci.sh @@ -10,6 +10,8 @@ source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" export CI="true" export SRC=. +echo "::add-matcher::src/ci/github-actions/problem_matchers.json" + # Remove any preexisting rustup installation since it can interfere # with the cargotest step and its auto-detection of things like Clippy in # the environment From a2040de541057a4d8d25c4d3f075f2e81276eef8 Mon Sep 17 00:00:00 2001 From: Deadbeef Date: Fri, 6 Jan 2023 10:50:09 +0000 Subject: [PATCH 06/11] do not run tidy on x86_64-gnu-llvm-13 --- src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile index db6032f875211..a007bf183ee11 100644 --- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile +++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-14/Dockerfile @@ -62,6 +62,4 @@ ENV SCRIPT ../x.py --stage 2 test --exclude src/tools/tidy && \ # work. # ../x.ps1 --stage 2 test tests/ui --pass=check \ - --host='' --target=i686-unknown-linux-gnu && \ - # Run tidy at the very end, after all the other tests. - python2.7 ../x.py --stage 2 test src/tools/tidy + --host='' --target=i686-unknown-linux-gnu From b66db7e4e04ba039967b659473595a13409e0b18 Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Fri, 3 Mar 2023 17:08:49 -0800 Subject: [PATCH 07/11] Create new rustc_smir struct to map future crates + Add some information to the README.md --- Cargo.lock | 10 +- compiler/rustc_smir/Cargo.toml | 19 +--- compiler/rustc_smir/README.md | 37 ++++++ compiler/rustc_smir/rust-toolchain.toml | 2 +- compiler/rustc_smir/src/lib.rs | 8 +- compiler/rustc_smir/src/rustc_internal/mod.rs | 12 ++ compiler/rustc_smir/src/rustc_smir/mod.rs | 52 +++++++++ compiler/rustc_smir/src/stable_mir/mod.rs | 52 +++++++++ tests/ui-fulldeps/stable-mir/crate-info.rs | 106 ++++++++++++++++++ 9 files changed, 271 insertions(+), 27 deletions(-) create mode 100644 compiler/rustc_smir/src/rustc_internal/mod.rs create mode 100644 compiler/rustc_smir/src/rustc_smir/mod.rs create mode 100644 compiler/rustc_smir/src/stable_mir/mod.rs create mode 100644 tests/ui-fulldeps/stable-mir/crate-info.rs diff --git a/Cargo.lock b/Cargo.lock index 5530541cdd0f1..24e39e9d3f8a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4654,15 +4654,9 @@ dependencies = [ name = "rustc_smir" version = "0.0.0" dependencies = [ - "rustc_borrowck", - "rustc_driver", - "rustc_hir", - "rustc_interface", "rustc_middle", - "rustc_mir_dataflow", - "rustc_mir_transform", - "rustc_serialize", - "rustc_trait_selection", + "rustc_span", + "tracing", ] [[package]] diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index 5e0d1f369a6a2..fb97ee5bebe6e 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -4,25 +4,12 @@ version = "0.0.0" edition = "2021" [dependencies] -rustc_borrowck = { path = "../rustc_borrowck", optional = true } -rustc_driver = { path = "../rustc_driver", optional = true } -rustc_hir = { path = "../rustc_hir", optional = true } -rustc_interface = { path = "../rustc_interface", optional = true } rustc_middle = { path = "../rustc_middle", optional = true } -rustc_mir_dataflow = { path = "../rustc_mir_dataflow", optional = true } -rustc_mir_transform = { path = "../rustc_mir_transform", optional = true } -rustc_serialize = { path = "../rustc_serialize", optional = true } -rustc_trait_selection = { path = "../rustc_trait_selection", optional = true } +rustc_span = { path = "../rustc_span", optional = true } +tracing = "0.1" [features] default = [ - "rustc_borrowck", - "rustc_driver", - "rustc_hir", - "rustc_interface", "rustc_middle", - "rustc_mir_dataflow", - "rustc_mir_transform", - "rustc_serialize", - "rustc_trait_selection", + "rustc_span", ] diff --git a/compiler/rustc_smir/README.md b/compiler/rustc_smir/README.md index ae49098dd0ce6..31dee955f491f 100644 --- a/compiler/rustc_smir/README.md +++ b/compiler/rustc_smir/README.md @@ -73,3 +73,40 @@ git subtree pull --prefix=compiler/rustc_smir https://github.com/rust-lang/proje Note: only ever sync to rustc from the project-stable-mir's `smir` branch. Do not sync with your own forks. Then open a PR against rustc just like a regular PR. + +## Stable MIR Design + +The stable-mir will follow a similar approach to proc-macro2. It’s +implementation will eventually be broken down into two main crates: + +- `stable_mir`: Public crate, to be published on crates.io, which will contain +the stable data structure as well as proxy APIs to make calls to the +compiler. +- `rustc_smir`: The compiler crate that will translate from internal MIR to +SMIR. This crate will also implement APIs that will be invoked by +stable-mir to query the compiler for more information. + +This will help tools to communicate with the rust compiler via stable APIs. Tools will depend on +`stable_mir` crate, which will invoke the compiler using APIs defined in `rustc_smir`. I.e.: + +``` + ┌──────────────────────────────────┐ ┌──────────────────────────────────┐ + │ External Tool ┌──────────┐ │ │ ┌──────────┐ Rust Compiler │ + │ │ │ │ │ │ │ │ + │ │stable_mir| │ │ │rustc_smir│ │ + │ │ │ ├──────────►| │ │ │ + │ │ │ │◄──────────┤ │ │ │ + │ │ │ │ │ │ │ │ + │ │ │ │ │ │ │ │ + │ └──────────┘ │ │ └──────────┘ │ + └──────────────────────────────────┘ └──────────────────────────────────┘ +``` + +More details can be found here: +https://hackmd.io/XhnYHKKuR6-LChhobvlT-g?view + +For now, the code for these two crates are in separate modules of this crate. +The modules have the same name for simplicity. We also have a third module, +`rustc_internal` which will expose APIs and definitions that allow users to +gather information from internal MIR constructs that haven't been exposed in +the `stable_mir` module. diff --git a/compiler/rustc_smir/rust-toolchain.toml b/compiler/rustc_smir/rust-toolchain.toml index 7b696fc1f5cec..157dfd620ee1b 100644 --- a/compiler/rustc_smir/rust-toolchain.toml +++ b/compiler/rustc_smir/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2022-06-01" +channel = "nightly-2023-02-28" components = [ "rustfmt", "rustc-dev" ] diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index 280b704f23326..54d474db038e9 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -11,5 +11,9 @@ test(attr(allow(unused_variables), deny(warnings))) )] #![cfg_attr(not(feature = "default"), feature(rustc_private))] -#![deny(rustc::untranslatable_diagnostic)] -#![deny(rustc::diagnostic_outside_of_impl)] + +pub mod rustc_internal; +pub mod stable_mir; + +// Make this module private for now since external users should not call these directly. +mod rustc_smir; diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs new file mode 100644 index 0000000000000..044d6a2419f69 --- /dev/null +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -0,0 +1,12 @@ +//! Module that implements the bridge between Stable MIR and internal compiler MIR. +//! +//! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs +//! until stable MIR is complete. + +use crate::stable_mir::CrateItem; + +pub type DefId = rustc_span::def_id::DefId; + +pub fn item_def_id(item: &CrateItem) -> DefId { + item.0 +} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs new file mode 100644 index 0000000000000..768b01f526f73 --- /dev/null +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -0,0 +1,52 @@ +//! Module that implements what will become the rustc side of Stable MIR. +//! +//! This module is responsible for building Stable MIR components from internal components. +//! +//! This module is not intended to be invoked directly by users. It will eventually +//! become the public API of rustc that will be invoked by the `stable_mir` crate. +//! +//! For now, we are developing everything inside `rustc`, thus, we keep this module private. + +use crate::stable_mir::{self}; +use rustc_middle::ty::{tls::with, TyCtxt}; +use rustc_span::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use tracing::debug; + +/// Get information about the local crate. +pub fn local_crate() -> stable_mir::Crate { + with(|tcx| smir_crate(tcx, LOCAL_CRATE)) +} + +/// Find a crate with the given name. +pub fn find_crate(name: &str) -> Option { + with(|tcx| { + [LOCAL_CRATE].iter().chain(tcx.crates(()).iter()).find_map(|crate_num| { + let crate_name = tcx.crate_name(*crate_num).to_string(); + (name == crate_name).then(|| smir_crate(tcx, *crate_num)) + }) + }) +} + +/// Build a stable mir crate from a given crate number. +fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate { + let crate_name = tcx.crate_name(crate_num).to_string(); + let is_local = crate_num == LOCAL_CRATE; + let mod_id = DefId { index: CRATE_DEF_INDEX, krate: crate_num }; + let items = if is_local { + tcx.hir_module_items(mod_id.expect_local()) + .items() + .map(|item| { + let def_id = item.owner_id.def_id.to_def_id(); + stable_mir::CrateItem(def_id) + }) + .collect() + } else { + tcx.module_children(mod_id) + .iter() + .filter_map(|item| item.res.opt_def_id()) + .map(stable_mir::CrateItem) + .collect::>() + }; + debug!(?crate_name, ?crate_num, "smir_crate"); + stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local, root_items: items } +} diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs new file mode 100644 index 0000000000000..f61ea461dfa85 --- /dev/null +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -0,0 +1,52 @@ +//! Module that implements the public interface to the Stable MIR. +//! +//! This module shall contain all type definitions and APIs that we expect 3P tools to invoke to +//! interact with the compiler. +//! +//! The goal is to eventually move this module to its own crate which shall be published on +//! [crates.io](https://crates.io). +//! +//! ## Note: +//! +//! There shouldn't be any direct references to internal compiler constructs in this module. +//! If you need an internal construct, consider using `rustc_internal` or `rustc_smir`. + +use crate::rustc_internal; + +/// Use String for now but we should replace it. +pub type Symbol = String; + +/// The number that identifies a crate. +pub type CrateNum = usize; + +/// A unique identification number for each item accessible for the current compilation unit. +pub type DefId = usize; + +/// A list of crate items. +pub type CrateItems = Vec; + +/// Holds information about a crate. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct Crate { + pub(crate) id: CrateNum, + pub name: Symbol, + pub is_local: bool, + /// The items defined in the root of this crate. + pub root_items: CrateItems, +} + +/// Holds information about an item in the crate. +/// For now, it only stores the item DefId. Use functions inside `rustc_internal` module to +/// use this item. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct CrateItem(pub(crate) rustc_internal::DefId); + +/// Access to the local crate. +pub fn local_crate() -> Crate { + crate::rustc_smir::local_crate() +} + +/// Try to find a crate with the given name. +pub fn find_crate(name: &str) -> Option { + crate::rustc_smir::find_crate(name) +} diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs new file mode 100644 index 0000000000000..62cfb809fcbe9 --- /dev/null +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -0,0 +1,106 @@ +// run-pass +// Test that users are able to use stable mir APIs to retrieve information of the current crate + +// ignore-stage-1 +// ignore-cross-compile +// ignore-remote + +#![feature(rustc_private)] + +extern crate rustc_driver; +extern crate rustc_hir; +extern crate rustc_interface; +extern crate rustc_middle; +extern crate rustc_smir; + +use rustc_driver::{Callbacks, Compilation, RunCompiler}; +use rustc_hir::def::DefKind; +use rustc_interface::{interface, Queries}; +use rustc_middle::ty::TyCtxt; +use rustc_smir::{rustc_internal, stable_mir}; +use std::io::Write; + +const CRATE_NAME: &str = "input"; + +/// This function uses the Stable MIR APIs to get information about the test crate. +fn test_stable_mir(tcx: TyCtxt<'_>) { + // Get the local crate using stable_mir API. + let local = stable_mir::local_crate(); + assert_eq!(&local.name, CRATE_NAME); + + // Find items in the local crate. + assert!(has_root_item(tcx, &local, (DefKind::Fn, "foo_bar"))); + assert!(has_root_item(tcx, &local, (DefKind::Mod, "foo"))); + assert!(!has_root_item(tcx, &local, (DefKind::Fn, "foo::bar"))); + + // Check that we can find items in the `std` crate. + let std_crate = stable_mir::find_crate("std").unwrap(); + assert!(has_root_item(tcx, &std_crate, (DefKind::Mod, "std::any"))); + assert!(!has_root_item(tcx, &std_crate, (DefKind::Fn, "std::any::type_name"))); +} + +// Use internal API to find a function in a crate. +fn has_root_item(tcx: TyCtxt, krate: &stable_mir::Crate, item: (DefKind, &str)) -> bool { + krate.root_items.iter().any(|crate_item| { + let def_id = rustc_internal::item_def_id(crate_item); + tcx.def_kind(def_id) == item.0 && tcx.def_path_str(def_id) == item.1 + }) +} + +/// This test will generate and analyze a dummy crate using the stable mir. +/// For that, it will first write the dummy crate into a file. +/// It will invoke the compiler using a custom Callback implementation, which will +/// invoke Stable MIR APIs after the compiler has finished its analysis. +fn main() { + let path = "input.rs"; + generate_input(&path).unwrap(); + let args = vec![ + "rustc".to_string(), + "--crate-type=lib".to_string(), + "--crate-name".to_string(), + CRATE_NAME.to_string(), + path.to_string(), + ]; + rustc_driver::catch_fatal_errors(|| { + RunCompiler::new(&args, &mut SMirCalls {}).run().unwrap(); + }) + .unwrap(); +} + +struct SMirCalls {} + +impl Callbacks for SMirCalls { + /// Called after analysis. Return value instructs the compiler whether to + /// continue the compilation afterwards (defaults to `Compilation::Continue`) + fn after_analysis<'tcx>( + &mut self, + _compiler: &interface::Compiler, + queries: &'tcx Queries<'tcx>, + ) -> Compilation { + queries.global_ctxt().unwrap().enter(|tcx| { + test_stable_mir(tcx); + }); + // No need to keep going. + Compilation::Stop + } +} + +fn generate_input(path: &str) -> std::io::Result<()> { + let mut file = std::fs::File::create(path)?; + write!( + file, + r#" + mod foo {{ + pub fn bar(i: i32) -> i64 {{ + i as i64 + }} + }} + + pub fn foo_bar(x: i32, y: i32) -> i64 {{ + let x_64 = foo::bar(x); + let y_64 = foo::bar(y); + x_64.wrapping_add(y_64) + }}"# + )?; + Ok(()) +} From c5d4e4d907047580f028c6ca7b36a82ef94d28d1 Mon Sep 17 00:00:00 2001 From: Giacomo Pasini Date: Sun, 5 Mar 2023 21:02:14 +0100 Subject: [PATCH 08/11] Remove DropAndReplace terminator PR 107844 made DropAndReplace unused, let's remove it completely from the codebase. --- compiler/rustc_borrowck/src/invalidation.rs | 9 -- compiler/rustc_borrowck/src/lib.rs | 10 -- .../src/type_check/liveness/trace.rs | 3 +- compiler/rustc_borrowck/src/type_check/mod.rs | 19 --- compiler/rustc_borrowck/src/used_muts.rs | 3 - compiler/rustc_codegen_cranelift/src/base.rs | 1 - .../rustc_codegen_cranelift/src/constant.rs | 3 +- compiler/rustc_codegen_ssa/src/mir/analyze.rs | 1 - compiler/rustc_codegen_ssa/src/mir/block.rs | 4 - .../src/interpret/terminator.rs | 6 +- .../src/transform/check_consts/check.rs | 3 +- .../check_consts/post_drop_elaboration.rs | 3 +- .../src/transform/check_consts/resolver.rs | 12 -- .../src/transform/validate.rs | 12 -- compiler/rustc_middle/src/mir/spanview.rs | 1 - compiler/rustc_middle/src/mir/syntax.rs | 38 ------ compiler/rustc_middle/src/mir/terminator.rs | 13 +- compiler/rustc_middle/src/mir/visit.rs | 14 --- .../src/build/custom/parse/instruction.rs | 8 -- compiler/rustc_mir_build/src/build/scope.rs | 4 +- compiler/rustc_mir_build/src/lints.rs | 1 - .../src/framework/direction.rs | 1 - .../src/impls/borrowed_locals.rs | 3 +- .../src/impls/storage_liveness.rs | 2 - .../src/move_paths/builder.rs | 5 - .../rustc_mir_dataflow/src/value_analysis.rs | 2 +- .../src/abort_unwinding_calls.rs | 2 +- .../src/add_moves_for_packed_drops.rs | 3 - compiler/rustc_mir_transform/src/add_retag.rs | 2 +- .../rustc_mir_transform/src/check_unsafety.rs | 1 - .../rustc_mir_transform/src/const_prop.rs | 1 - .../src/const_prop_lint.rs | 1 - .../rustc_mir_transform/src/coverage/debug.rs | 1 - .../rustc_mir_transform/src/coverage/graph.rs | 1 - .../rustc_mir_transform/src/coverage/spans.rs | 1 - .../rustc_mir_transform/src/coverage/tests.rs | 2 - compiler/rustc_mir_transform/src/dest_prop.rs | 3 +- .../src/elaborate_drops.rs | 119 +----------------- compiler/rustc_mir_transform/src/generator.rs | 2 - compiler/rustc_mir_transform/src/inline.rs | 10 +- .../src/remove_noop_landing_pads.rs | 1 - .../src/remove_uninit_drops.rs | 23 +--- .../src/separate_const_switch.rs | 2 - compiler/rustc_monomorphize/src/collector.rs | 3 +- library/core/src/intrinsics/mir.rs | 3 +- .../clippy_utils/src/qualify_min_const_fn.rs | 4 - .../terminators.drop_first.built.after.mir | 5 +- tests/mir-opt/building/custom/terminators.rs | 3 +- 48 files changed, 33 insertions(+), 341 deletions(-) diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 6217676d5c150..1006a047cce09 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -118,15 +118,6 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> { LocalMutationIsAllowed::Yes, ); } - TerminatorKind::DropAndReplace { - place: drop_place, - value: new_value, - target: _, - unwind: _, - } => { - self.mutate_place(location, *drop_place, Deep); - self.consume_operand(location, new_value); - } TerminatorKind::Call { func, args, diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 115e512a97429..18c465d18c6fe 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -744,15 +744,6 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx flow_state, ); } - TerminatorKind::DropAndReplace { - place: drop_place, - value: new_value, - target: _, - unwind: _, - } => { - self.mutate_place(loc, (*drop_place, span), Deep, flow_state); - self.consume_operand(loc, (new_value, span), flow_state); - } TerminatorKind::Call { func, args, @@ -867,7 +858,6 @@ impl<'cx, 'tcx> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtx | TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ } | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } | TerminatorKind::Goto { .. } diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 473c059630073..5d4b1d10b1ebd 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -435,8 +435,7 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { // // What we *actually* generate is a store to a temporary // for the call (`TMP = call()...`) and then a - // `DropAndReplace` to swap that with `X` - // (`DropAndReplace` has very particular semantics). + // `Drop(X)` followed by `X = TMP` to swap that with `X`. } } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a49da3da6c013..b32cda2719af0 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1312,24 +1312,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // no checks needed for these } - TerminatorKind::DropAndReplace { place, value, target: _, unwind: _ } => { - let place_ty = place.ty(body, tcx).ty; - let rv_ty = value.ty(body, tcx); - - let locations = term_location.to_locations(); - if let Err(terr) = - self.sub_types(rv_ty, place_ty, locations, ConstraintCategory::Assignment) - { - span_mirbug!( - self, - term, - "bad DropAndReplace ({:?} = {:?}): {:?}", - place_ty, - rv_ty, - terr - ); - } - } TerminatorKind::SwitchInt { discr, .. } => { self.check_operand(discr, term_location); @@ -1629,7 +1611,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } TerminatorKind::Unreachable => {} TerminatorKind::Drop { target, unwind, .. } - | TerminatorKind::DropAndReplace { target, unwind, .. } | TerminatorKind::Assert { target, cleanup: unwind, .. } => { self.assert_iscleanup(body, block_data, target, is_cleanup); if let Some(unwind) = unwind { diff --git a/compiler/rustc_borrowck/src/used_muts.rs b/compiler/rustc_borrowck/src/used_muts.rs index e297b1230ea0c..10ade142b24dd 100644 --- a/compiler/rustc_borrowck/src/used_muts.rs +++ b/compiler/rustc_borrowck/src/used_muts.rs @@ -71,9 +71,6 @@ impl<'visit, 'cx, 'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'visit, 'cx, 'tc TerminatorKind::Call { destination, .. } => { self.remove_never_initialized_mut_locals(*destination); } - TerminatorKind::DropAndReplace { place, .. } => { - self.remove_never_initialized_mut_locals(*place); - } _ => {} } diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 7f857528c7c5c..cb0e272cedaba 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -499,7 +499,6 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) { TerminatorKind::Yield { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::GeneratorDrop => { bug!("shouldn't exist at codegen {:?}", bb_data.terminator()); } diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index 49c4f1aaaefc6..1930db72ead44 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -543,8 +543,7 @@ pub(crate) fn mir_operand_get_const_val<'tcx>( | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } | TerminatorKind::Assert { .. } => {} - TerminatorKind::DropAndReplace { .. } - | TerminatorKind::Yield { .. } + TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } => unreachable!(), diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs index 95aad10fdb0f9..0ce395e912db3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs +++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs @@ -295,7 +295,6 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec { if let Some(unwind) = unwind { debug!( diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 57a19a4ab1eab..71c71d59b7ab9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1305,10 +1305,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mergeable_succ(), ), - mir::TerminatorKind::DropAndReplace { .. } => { - bug!("undesugared DropAndReplace in codegen: {:?}", terminator); - } - mir::TerminatorKind::Call { ref func, ref args, diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs index 2aea7c79b6d3e..685a5599cdedf 100644 --- a/compiler/rustc_const_eval/src/interpret/terminator.rs +++ b/compiler/rustc_const_eval/src/interpret/terminator.rs @@ -171,11 +171,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { Unreachable => throw_ub!(Unreachable), // These should never occur for MIR we actually run. - DropAndReplace { .. } - | FalseEdge { .. } - | FalseUnwind { .. } - | Yield { .. } - | GeneratorDrop => span_bug!( + FalseEdge { .. } | FalseUnwind { .. } | Yield { .. } | GeneratorDrop => span_bug!( terminator.source_info.span, "{:#?} should have been eliminated by MIR pass", terminator.kind diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs index aa24d9053b98a..e8f8c87111f72 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs @@ -977,8 +977,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { // Forbid all `Drop` terminators unless the place being dropped is a local with no // projections that cannot be `NeedsNonConstDrop`. - TerminatorKind::Drop { place: dropped_place, .. } - | TerminatorKind::DropAndReplace { place: dropped_place, .. } => { + TerminatorKind::Drop { place: dropped_place, .. } => { // If we are checking live drops after drop-elaboration, don't emit duplicate // errors here. if super::post_drop_elaboration::checking_enabled(self.ccx) { diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs index cf4e875c91f0b..43806035a44a0 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs @@ -80,8 +80,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> { trace!("visit_terminator: terminator={:?} location={:?}", terminator, location); match &terminator.kind { - mir::TerminatorKind::Drop { place: dropped_place, .. } - | mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => { + mir::TerminatorKind::Drop { place: dropped_place, .. } => { let dropped_ty = dropped_place.ty(self.body, self.tcx).ty; if !NeedsNonConstDrop::in_any_value_of_ty(self.ccx, dropped_ty) { // Instead of throwing a bug, we just return here. This is because we have to diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index 805e6096b35c8..148aff9be4b5b 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -222,18 +222,6 @@ where // The effect of assignment to the return place in `TerminatorKind::Call` is not applied // here; that occurs in `apply_call_return_effect`. - if let mir::TerminatorKind::DropAndReplace { value, place, .. } = &terminator.kind { - let qualif = qualifs::in_operand::( - self.ccx, - &mut |l| self.state.qualif.contains(l), - value, - ); - - if !place.is_indirect() { - self.assign_qualif_direct(place, qualif); - } - } - // We ignore borrow on drop because custom drop impls are not allowed in consts. // FIXME: Reconsider if accounting for borrows in drops is necessary for const drop. diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index fb37eb79a335f..b83024cb6b949 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -835,18 +835,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { self.check_edge(location, *unwind, EdgeKind::Unwind); } } - TerminatorKind::DropAndReplace { target, unwind, .. } => { - if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) { - self.fail( - location, - "`DropAndReplace` should have been removed during drop elaboration", - ); - } - self.check_edge(location, *target, EdgeKind::Normal); - if let Some(unwind) = unwind { - self.check_edge(location, *unwind, EdgeKind::Unwind); - } - } TerminatorKind::Call { func, args, destination, target, cleanup, .. } => { let func_ty = func.ty(&self.body.local_decls, self.tcx); match func_ty.kind() { diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs index 28a3b51b7fc92..e52610faf5af7 100644 --- a/compiler/rustc_middle/src/mir/spanview.rs +++ b/compiler/rustc_middle/src/mir/spanview.rs @@ -265,7 +265,6 @@ pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str { Return => "Return", Unreachable => "Unreachable", Drop { .. } => "Drop", - DropAndReplace { .. } => "DropAndReplace", Call { .. } => "Call", Assert { .. } => "Assert", Yield { .. } => "Yield", diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index ae09562a85e98..58c060db66003 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -133,7 +133,6 @@ pub enum AnalysisPhase { pub enum RuntimePhase { /// In addition to the semantic changes, beginning with this phase, the following variants are /// disallowed: - /// * [`TerminatorKind::DropAndReplace`] /// * [`TerminatorKind::Yield`] /// * [`TerminatorKind::GeneratorDrop`] /// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array` @@ -596,43 +595,6 @@ pub enum TerminatorKind<'tcx> { /// > consider indirect assignments. Drop { place: Place<'tcx>, target: BasicBlock, unwind: Option }, - /// Drops the place and assigns a new value to it. - /// - /// This first performs the exact same operation as the pre drop-elaboration `Drop` terminator; - /// it then additionally assigns the `value` to the `place` as if by an assignment statement. - /// This assignment occurs both in the unwind and the regular code paths. The semantics are best - /// explained by the elaboration: - /// - /// ```ignore (MIR) - /// BB0 { - /// DropAndReplace(P <- V, goto BB1, unwind BB2) - /// } - /// ``` - /// - /// becomes - /// - /// ```ignore (MIR) - /// BB0 { - /// Drop(P, goto BB1, unwind BB2) - /// } - /// BB1 { - /// // P is now uninitialized - /// P <- V - /// } - /// BB2 { - /// // P is now uninitialized -- its dtor panicked - /// P <- V - /// } - /// ``` - /// - /// Disallowed after drop elaboration. - DropAndReplace { - place: Place<'tcx>, - value: Operand<'tcx>, - target: BasicBlock, - unwind: Option, - }, - /// Roughly speaking, evaluates the `func` operand and the arguments, and starts execution of /// the referred to function. The operand types must match the argument types of the function. /// The return place type must match the return type. The type of the `func` operand must be diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 6e905224c1336..cd970270727f9 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -148,7 +148,6 @@ impl<'tcx> TerminatorKind<'tcx> { | Call { target: None, cleanup: Some(t), .. } | Call { target: Some(t), cleanup: None, .. } | Yield { resume: t, drop: None, .. } - | DropAndReplace { target: t, unwind: None, .. } | Drop { target: t, unwind: None, .. } | Assert { target: t, cleanup: None, .. } | FalseUnwind { real_target: t, unwind: None } @@ -158,7 +157,6 @@ impl<'tcx> TerminatorKind<'tcx> { } Call { target: Some(t), cleanup: Some(ref u), .. } | Yield { resume: t, drop: Some(ref u), .. } - | DropAndReplace { target: t, unwind: Some(ref u), .. } | Drop { target: t, unwind: Some(ref u), .. } | Assert { target: t, cleanup: Some(ref u), .. } | FalseUnwind { real_target: t, unwind: Some(ref u) } @@ -188,7 +186,6 @@ impl<'tcx> TerminatorKind<'tcx> { | Call { target: None, cleanup: Some(ref mut t), .. } | Call { target: Some(ref mut t), cleanup: None, .. } | Yield { resume: ref mut t, drop: None, .. } - | DropAndReplace { target: ref mut t, unwind: None, .. } | Drop { target: ref mut t, unwind: None, .. } | Assert { target: ref mut t, cleanup: None, .. } | FalseUnwind { real_target: ref mut t, unwind: None } @@ -198,7 +195,6 @@ impl<'tcx> TerminatorKind<'tcx> { } Call { target: Some(ref mut t), cleanup: Some(ref mut u), .. } | Yield { resume: ref mut t, drop: Some(ref mut u), .. } - | DropAndReplace { target: ref mut t, unwind: Some(ref mut u), .. } | Drop { target: ref mut t, unwind: Some(ref mut u), .. } | Assert { target: ref mut t, cleanup: Some(ref mut u), .. } | FalseUnwind { real_target: ref mut t, unwind: Some(ref mut u) } @@ -225,7 +221,6 @@ impl<'tcx> TerminatorKind<'tcx> { | TerminatorKind::FalseEdge { .. } => None, TerminatorKind::Call { cleanup: ref unwind, .. } | TerminatorKind::Assert { cleanup: ref unwind, .. } - | TerminatorKind::DropAndReplace { ref unwind, .. } | TerminatorKind::Drop { ref unwind, .. } | TerminatorKind::FalseUnwind { ref unwind, .. } | TerminatorKind::InlineAsm { cleanup: ref unwind, .. } => Some(unwind), @@ -245,7 +240,6 @@ impl<'tcx> TerminatorKind<'tcx> { | TerminatorKind::FalseEdge { .. } => None, TerminatorKind::Call { cleanup: ref mut unwind, .. } | TerminatorKind::Assert { cleanup: ref mut unwind, .. } - | TerminatorKind::DropAndReplace { ref mut unwind, .. } | TerminatorKind::Drop { ref mut unwind, .. } | TerminatorKind::FalseUnwind { ref mut unwind, .. } | TerminatorKind::InlineAsm { cleanup: ref mut unwind, .. } => Some(unwind), @@ -309,9 +303,6 @@ impl<'tcx> TerminatorKind<'tcx> { Yield { value, resume_arg, .. } => write!(fmt, "{:?} = yield({:?})", resume_arg, value), Unreachable => write!(fmt, "unreachable"), Drop { place, .. } => write!(fmt, "drop({:?})", place), - DropAndReplace { place, value, .. } => { - write!(fmt, "replace({:?} <- {:?})", place, value) - } Call { func, args, destination, .. } => { write!(fmt, "{:?} = ", destination)?; write!(fmt, "{:?}(", func)?; @@ -403,10 +394,10 @@ impl<'tcx> TerminatorKind<'tcx> { Call { target: None, cleanup: None, .. } => vec![], Yield { drop: Some(_), .. } => vec!["resume".into(), "drop".into()], Yield { drop: None, .. } => vec!["resume".into()], - DropAndReplace { unwind: None, .. } | Drop { unwind: None, .. } => { + Drop { unwind: None, .. } => { vec!["return".into()] } - DropAndReplace { unwind: Some(_), .. } | Drop { unwind: Some(_), .. } => { + Drop { unwind: Some(_), .. } => { vec!["return".into(), "unwind".into()] } Assert { cleanup: None, .. } => vec!["".into()], diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index 5c056b29975c4..14b18618aa8d8 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -495,20 +495,6 @@ macro_rules! make_mir_visitor { ); } - TerminatorKind::DropAndReplace { - place, - value, - target: _, - unwind: _, - } => { - self.visit_place( - place, - PlaceContext::MutatingUse(MutatingUseContext::Drop), - location - ); - self.visit_operand(value, location); - } - TerminatorKind::Call { func, args, diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index dbba529aef7a5..42a948e78d768 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -58,14 +58,6 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { unwind: None, }) }, - @call("mir_drop_and_replace", args) => { - Ok(TerminatorKind::DropAndReplace { - place: self.parse_place(args[0])?, - value: self.parse_operand(args[1])?, - target: self.parse_block(args[2])?, - unwind: None, - }) - }, @call("mir_call", args) => { let destination = self.parse_place(args[0])?; let target = self.parse_block(args[1])?; diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 770701b3750df..4bc2c0ca791e6 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -1072,7 +1072,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::InlineAsm { .. } ), @@ -1432,8 +1431,7 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind { *unwind = Some(to); } } - TerminatorKind::DropAndReplace { unwind, .. } - | TerminatorKind::FalseUnwind { unwind, .. } + TerminatorKind::FalseUnwind { unwind, .. } | TerminatorKind::Call { cleanup: unwind, .. } | TerminatorKind::Assert { cleanup: unwind, .. } | TerminatorKind::InlineAsm { cleanup: unwind, .. } => { diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index f67f24b43c4d7..f6db329fd7cfe 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -128,7 +128,6 @@ impl<'mir, 'tcx> TriColorVisitor> for Search<'mir, 'tcx> { TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Goto { .. } diff --git a/compiler/rustc_mir_dataflow/src/framework/direction.rs b/compiler/rustc_mir_dataflow/src/framework/direction.rs index 2ae3ae02fcc4e..a40c38aa4c333 100644 --- a/compiler/rustc_mir_dataflow/src/framework/direction.rs +++ b/compiler/rustc_mir_dataflow/src/framework/direction.rs @@ -480,7 +480,6 @@ impl Direction for Forward { Assert { target, cleanup: unwind, expected: _, msg: _, cond: _ } | Drop { target, unwind, place: _ } - | DropAndReplace { target, unwind, value: _, place: _ } | FalseUnwind { real_target: target, unwind } => { if let Some(unwind) = unwind { propagate(unwind, exit_state); diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs index 6f4e7fd4682c1..08fadfe68a17a 100644 --- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs +++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs @@ -111,8 +111,7 @@ where self.super_terminator(terminator, location); match terminator.kind { - mir::TerminatorKind::Drop { place: dropped_place, .. } - | mir::TerminatorKind::DropAndReplace { place: dropped_place, .. } => { + mir::TerminatorKind::Drop { place: dropped_place, .. } => { // Drop terminators may call custom drop glue (`Drop::drop`), which takes `&mut // self` as a parameter. In the general case, a drop impl could launder that // reference into the surrounding environment through a raw pointer, thus creating diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs index fcf0ce9d82118..60fd5169054d3 100644 --- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs +++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs @@ -202,7 +202,6 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc TerminatorKind::Abort | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop @@ -240,7 +239,6 @@ impl<'mir, 'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'mir, 'tc | TerminatorKind::Abort | TerminatorKind::Assert { .. } | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::GeneratorDrop diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index 4a163028fcf4a..fa62960eee0ff 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -392,11 +392,6 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { self.create_move_path(place); self.gather_init(place.as_ref(), InitKind::Deep); } - TerminatorKind::DropAndReplace { place, ref value, .. } => { - self.create_move_path(place); - self.gather_operand(value); - self.gather_init(place.as_ref(), InitKind::Deep); - } TerminatorKind::Call { ref func, ref args, diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index 401db890a9810..4cb28aadbaf44 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -230,7 +230,7 @@ pub trait ValueAnalysis<'tcx> { TerminatorKind::Drop { place, .. } => { state.flood_with(place.as_ref(), self.map(), Self::Value::bottom()); } - TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } => { + TerminatorKind::Yield { .. } => { // They would have an effect, but are not allowed in this phase. bug!("encountered disallowed terminator"); } diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index 9b4b720702b6f..893018e0d8e73 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -74,7 +74,7 @@ impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { }; layout::fn_can_unwind(tcx, fn_def_id, sig.abi()) } - TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => { + TerminatorKind::Drop { .. } => { tcx.sess.opts.unstable_opts.panic_in_drop == PanicStrategy::Unwind && layout::fn_can_unwind(tcx, None, Abi::Rust) } diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 9b2260f68251a..896fcd9cdd608 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -64,9 +64,6 @@ fn add_moves_for_packed_drops_patch<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { add_move_for_packed_drop(tcx, body, &mut patch, terminator, loc, data.is_cleanup); } - TerminatorKind::DropAndReplace { .. } => { - span_bug!(terminator.source_info.span, "replace in AddMovesForPackedDrops"); - } _ => {} } } diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 7d2146214c6dc..916f2904dda80 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -100,7 +100,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag { } // `Drop` is also a call, but it doesn't return anything so we are good. - TerminatorKind::Drop { .. } | TerminatorKind::DropAndReplace { .. } => None, + TerminatorKind::Drop { .. } => None, // Not a block ending in a Call -> ignore. _ => None, } diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs index d00ee1f4babe8..ada55a4bf6db1 100644 --- a/compiler/rustc_mir_transform/src/check_unsafety.rs +++ b/compiler/rustc_mir_transform/src/check_unsafety.rs @@ -55,7 +55,6 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> { | TerminatorKind::Drop { .. } | TerminatorKind::Yield { .. } | TerminatorKind::Assert { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::Resume | TerminatorKind::Abort diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index 6b2eefce24d50..9bc4b26db92eb 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -1007,7 +1007,6 @@ impl<'tcx> MutVisitor<'tcx> for ConstPropagator<'_, 'tcx> { | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 6c1980ff3ad93..77402b8737e24 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -686,7 +686,6 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> { | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs index 22ea8710e6a96..0e7dc171a5d0c 100644 --- a/compiler/rustc_mir_transform/src/coverage/debug.rs +++ b/compiler/rustc_mir_transform/src/coverage/debug.rs @@ -822,7 +822,6 @@ pub(super) fn term_type(kind: &TerminatorKind<'_>) -> &'static str { TerminatorKind::Return => "Return", TerminatorKind::Unreachable => "Unreachable", TerminatorKind::Drop { .. } => "Drop", - TerminatorKind::DropAndReplace { .. } => "DropAndReplace", TerminatorKind::Call { .. } => "Call", TerminatorKind::Assert { .. } => "Assert", TerminatorKind::Yield { .. } => "Yield", diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs index a2671eef2e940..c03cacd8615e3 100644 --- a/compiler/rustc_mir_transform/src/coverage/graph.rs +++ b/compiler/rustc_mir_transform/src/coverage/graph.rs @@ -156,7 +156,6 @@ impl CoverageGraph { | TerminatorKind::Resume | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Call { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::Assert { .. } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 8ee316773aeaf..d9f68f5d93acc 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -850,7 +850,6 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option MockBlocks<'tcx> { TerminatorKind::Assert { ref mut target, .. } | TerminatorKind::Call { target: Some(ref mut target), .. } | TerminatorKind::Drop { ref mut target, .. } - | TerminatorKind::DropAndReplace { ref mut target, .. } | TerminatorKind::FalseEdge { real_target: ref mut target, .. } | TerminatorKind::FalseUnwind { real_target: ref mut target, .. } | TerminatorKind::Goto { ref mut target } @@ -184,7 +183,6 @@ fn debug_basic_blocks(mir_body: &Body<'_>) -> String { TerminatorKind::Assert { target, .. } | TerminatorKind::Call { target: Some(target), .. } | TerminatorKind::Drop { target, .. } - | TerminatorKind::DropAndReplace { target, .. } | TerminatorKind::FalseEdge { real_target: target, .. } | TerminatorKind::FalseUnwind { real_target: target, .. } | TerminatorKind::Goto { target } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index 2e481b972781c..3823b6201c347 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -650,8 +650,7 @@ impl WriteInfo { TerminatorKind::Drop { .. } => { // `Drop`s create a `&mut` and so are not considered } - TerminatorKind::DropAndReplace { .. } - | TerminatorKind::Yield { .. } + TerminatorKind::Yield { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } | TerminatorKind::FalseUnwind { .. } => { diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index 29424f09695f1..3faccca823a57 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -18,15 +18,14 @@ use rustc_span::{DesugaringKind, Span}; use rustc_target::abi::VariantIdx; use std::fmt; -/// During MIR building, Drop and DropAndReplace terminators are inserted in every place where a drop may occur. +/// During MIR building, Drop terminators are inserted in every place where a drop may occur. /// However, in this phase, the presence of these terminators does not guarantee that a destructor will run, /// as the target of the drop may be uninitialized. /// In general, the compiler cannot determine at compile time whether a destructor will run or not. /// -/// At a high level, this pass refines Drop and DropAndReplace to only run the destructor if the +/// At a high level, this pass refines Drop to only run the destructor if the /// target is initialized. The way this is achievied is by inserting drop flags for every variable /// that may be dropped, and then using those flags to determine whether a destructor should run. -/// This pass also removes DropAndReplace, replacing it with a Drop paired with an assign statement. /// Once this is complete, Drop terminators in the MIR correspond to a call to the "drop glue" or /// "drop shim" for the type of the dropped place. /// @@ -121,8 +120,7 @@ fn remove_dead_unwinds<'tcx>( .into_results_cursor(body); for (bb, bb_data) in body.basic_blocks.iter_enumerated() { let place = match bb_data.terminator().kind { - TerminatorKind::Drop { ref place, unwind: Some(_), .. } - | TerminatorKind::DropAndReplace { ref place, unwind: Some(_), .. } => { + TerminatorKind::Drop { ref place, unwind: Some(_), .. } => { und.derefer(place.as_ref(), body).unwrap_or(*place) } _ => continue, @@ -343,8 +341,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } let terminator = data.terminator(); let place = match terminator.kind { - TerminatorKind::Drop { ref place, .. } - | TerminatorKind::DropAndReplace { ref place, .. } => { + TerminatorKind::Drop { ref place, .. } => { self.un_derefer.derefer(place.as_ref(), self.body).unwrap_or(*place) } _ => continue, @@ -441,103 +438,11 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { } } } - TerminatorKind::DropAndReplace { mut place, ref value, target, unwind } => { - assert!(!data.is_cleanup); - - if let Some(new_place) = self.un_derefer.derefer(place.as_ref(), self.body) { - place = new_place; - } - self.elaborate_replace(loc, place, value, target, unwind); - } _ => continue, } } } - /// Elaborate a MIR `replace` terminator. This instruction - /// is not directly handled by codegen, and therefore - /// must be desugared. - /// - /// The desugaring drops the location if needed, and then writes - /// the value (including setting the drop flag) over it in *both* arms. - /// - /// The `replace` terminator can also be called on places that - /// are not tracked by elaboration (for example, - /// `replace x[i] <- tmp0`). The borrow checker requires that - /// these locations are initialized before the assignment, - /// so we just generate an unconditional drop. - fn elaborate_replace( - &mut self, - loc: Location, - place: Place<'tcx>, - value: &Operand<'tcx>, - target: BasicBlock, - unwind: Option, - ) { - let bb = loc.block; - let data = &self.body[bb]; - let terminator = data.terminator(); - assert!(!data.is_cleanup, "DropAndReplace in unwind path not supported"); - - let assign = Statement { - kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value.clone())))), - source_info: terminator.source_info, - }; - - let unwind = unwind.unwrap_or_else(|| self.patch.resume_block()); - let unwind = self.patch.new_block(BasicBlockData { - statements: vec![assign.clone()], - terminator: Some(Terminator { - kind: TerminatorKind::Goto { target: unwind }, - ..*terminator - }), - is_cleanup: true, - }); - - let target = self.patch.new_block(BasicBlockData { - statements: vec![assign], - terminator: Some(Terminator { kind: TerminatorKind::Goto { target }, ..*terminator }), - is_cleanup: false, - }); - - match self.move_data().rev_lookup.find(place.as_ref()) { - LookupResult::Exact(path) => { - debug!("elaborate_drop_and_replace({:?}) - tracked {:?}", terminator, path); - self.init_data.seek_before(loc); - elaborate_drop( - &mut Elaborator { ctxt: self }, - terminator.source_info, - place, - path, - target, - Unwind::To(unwind), - bb, - ); - on_all_children_bits(self.tcx, self.body, self.move_data(), path, |child| { - self.set_drop_flag( - Location { block: target, statement_index: 0 }, - child, - DropFlagState::Present, - ); - self.set_drop_flag( - Location { block: unwind, statement_index: 0 }, - child, - DropFlagState::Present, - ); - }); - } - LookupResult::Parent(parent) => { - // drop and replace behind a pointer/array/whatever. The location - // must be initialized. - debug!("elaborate_drop_and_replace({:?}) - untracked {:?}", terminator, parent); - self.patch.patch_terminator( - bb, - TerminatorKind::Drop { place, target, unwind: Some(unwind) }, - ); - } - } - } - fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> { Rvalue::Use(Operand::Constant(Box::new(Constant { span, @@ -609,22 +514,12 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { debug!("drop_flags_for_locs({:?})", data); for i in 0..(data.statements.len() + 1) { debug!("drop_flag_for_locs: stmt {}", i); - let mut allow_initializations = true; if i == data.statements.len() { match data.terminator().kind { TerminatorKind::Drop { .. } => { // drop elaboration should handle that by itself continue; } - TerminatorKind::DropAndReplace { .. } => { - // this contains the move of the source and - // the initialization of the destination. We - // only want the former - the latter is handled - // by the elaboration code and must be done - // *after* the destination is dropped. - assert!(self.patch.is_patched(bb)); - allow_initializations = false; - } TerminatorKind::Resume => { // It is possible for `Resume` to be patched // (in particular it can be patched to be replaced with @@ -641,11 +536,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> { self.body, self.env, loc, - |path, ds| { - if ds == DropFlagState::Absent || allow_initializations { - self.set_drop_flag(loc, path, ds) - } - }, + |path, ds| self.set_drop_flag(loc, path, ds), ) } diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs index 2e97312ee5048..f43657e435835 100644 --- a/compiler/rustc_mir_transform/src/generator.rs +++ b/compiler/rustc_mir_transform/src/generator.rs @@ -1199,7 +1199,6 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { // These may unwind. TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } | TerminatorKind::Assert { .. } => return true, @@ -1691,7 +1690,6 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> { | TerminatorKind::Return | TerminatorKind::Unreachable | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Assert { .. } | TerminatorKind::GeneratorDrop | TerminatorKind::FalseEdge { .. } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 6e6d6566f4bc0..9cba8870f2377 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -453,9 +453,7 @@ impl<'tcx> Inliner<'tcx> { checker.visit_basic_block_data(bb, blk); let term = blk.terminator(); - if let TerminatorKind::Drop { ref place, target, unwind } - | TerminatorKind::DropAndReplace { ref place, target, unwind, .. } = term.kind - { + if let TerminatorKind::Drop { ref place, target, unwind } = term.kind { work_list.push(target); // If the place doesn't actually need dropping, treat it like a regular goto. @@ -815,8 +813,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { fn visit_terminator(&mut self, terminator: &Terminator<'tcx>, location: Location) { let tcx = self.tcx; match terminator.kind { - TerminatorKind::Drop { ref place, unwind, .. } - | TerminatorKind::DropAndReplace { ref place, unwind, .. } => { + TerminatorKind::Drop { ref place, unwind, .. } => { // If the place doesn't actually need dropping, treat it like a regular goto. let ty = self.instance.subst_mir(tcx, &place.ty(self.callee_body, tcx).ty); if ty.needs_drop(tcx, self.param_env) { @@ -1120,8 +1117,7 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> { *tgt = self.map_block(*tgt); } } - TerminatorKind::Drop { ref mut target, ref mut unwind, .. } - | TerminatorKind::DropAndReplace { ref mut target, ref mut unwind, .. } => { + TerminatorKind::Drop { ref mut target, ref mut unwind, .. } => { *target = self.map_block(*target); *unwind = self.map_unwind(*unwind); } diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index e3a03aa08af4b..6c067f4529929 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -75,7 +75,6 @@ impl RemoveNoopLandingPads { | TerminatorKind::Unreachable | TerminatorKind::Call { .. } | TerminatorKind::Assert { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Drop { .. } | TerminatorKind::InlineAsm { .. } => false, } diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index 78b6f714a9b0b..e72729b152e69 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -1,5 +1,5 @@ use rustc_index::bit_set::ChunkedBitSet; -use rustc_middle::mir::{Body, Field, Rvalue, Statement, StatementKind, TerminatorKind}; +use rustc_middle::mir::{Body, Field, TerminatorKind}; use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; @@ -8,7 +8,7 @@ use rustc_mir_dataflow::{self, move_path_children_matching, Analysis, MoveDataPa use crate::MirPass; -/// Removes `Drop` and `DropAndReplace` terminators whose target is known to be uninitialized at +/// Removes `Drop` terminators whose target is known to be uninitialized at /// that point. /// /// This is redundant with drop elaboration, but we need to do it prior to const-checking, and @@ -37,8 +37,7 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { let mut to_remove = vec![]; for (bb, block) in body.basic_blocks.iter_enumerated() { let terminator = block.terminator(); - let (TerminatorKind::Drop { place, .. } | TerminatorKind::DropAndReplace { place, .. }) - = &terminator.kind + let TerminatorKind::Drop { place, .. } = &terminator.kind else { continue }; maybe_inits.seek_before_primary_effect(body.terminator_loc(bb)); @@ -64,24 +63,12 @@ impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { for bb in to_remove { let block = &mut body.basic_blocks_mut()[bb]; - let (TerminatorKind::Drop { target, .. } | TerminatorKind::DropAndReplace { target, .. }) + let TerminatorKind::Drop { target, .. } = &block.terminator().kind else { unreachable!() }; // Replace block terminator with `Goto`. - let target = *target; - let old_terminator_kind = std::mem::replace( - &mut block.terminator_mut().kind, - TerminatorKind::Goto { target }, - ); - - // If this is a `DropAndReplace`, we need to emulate the assignment to the return place. - if let TerminatorKind::DropAndReplace { place, value, .. } = old_terminator_kind { - block.statements.push(Statement { - source_info: block.terminator().source_info, - kind: StatementKind::Assign(Box::new((place, Rvalue::Use(value)))), - }); - } + block.terminator_mut().kind = TerminatorKind::Goto { target: *target }; } } } diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs index a24d2d34d791b..c3f5b881ab8b2 100644 --- a/compiler/rustc_mir_transform/src/separate_const_switch.rs +++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs @@ -108,7 +108,6 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { // The following terminators are not allowed TerminatorKind::Resume | TerminatorKind::Drop { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::Call { .. } | TerminatorKind::Assert { .. } | TerminatorKind::FalseUnwind { .. } @@ -170,7 +169,6 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize { | TerminatorKind::Unreachable | TerminatorKind::GeneratorDrop | TerminatorKind::Assert { .. } - | TerminatorKind::DropAndReplace { .. } | TerminatorKind::FalseUnwind { .. } | TerminatorKind::Drop { .. } | TerminatorKind::Call { .. } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 45e659eab6c85..f529944acce63 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -808,8 +808,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { let callee_ty = self.monomorphize(callee_ty); visit_fn_use(self.tcx, callee_ty, true, source, &mut self.output) } - mir::TerminatorKind::Drop { ref place, .. } - | mir::TerminatorKind::DropAndReplace { ref place, .. } => { + mir::TerminatorKind::Drop { ref place, .. } => { let ty = place.ty(self.body, self.tcx).ty; let ty = self.monomorphize(ty); visit_drop_use(self.tcx, ty, true, source, self.output); diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs index 72db1d87ca3c0..d2d9771bdce2e 100644 --- a/library/core/src/intrinsics/mir.rs +++ b/library/core/src/intrinsics/mir.rs @@ -227,7 +227,7 @@ //! are no resume and abort terminators, and terminators that might unwind do not have any way to //! indicate the unwind block. //! -//! - [`Goto`], [`Return`], [`Unreachable`], [`Drop`](Drop()), and [`DropAndReplace`] have associated functions. +//! - [`Goto`], [`Return`], [`Unreachable`] and [`Drop`](Drop()) have associated functions. //! - `match some_int_operand` becomes a `SwitchInt`. Each arm should be `literal => basic_block` //! - The exception is the last arm, which must be `_ => basic_block` and corresponds to the //! otherwise branch. @@ -259,7 +259,6 @@ define!("mir_return", fn Return() -> BasicBlock); define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock); define!("mir_unreachable", fn Unreachable() -> BasicBlock); define!("mir_drop", fn Drop(place: T, goto: BasicBlock)); -define!("mir_drop_and_replace", fn DropAndReplace(place: T, value: T, goto: BasicBlock)); define!("mir_call", fn Call(place: T, goto: BasicBlock, call: T)); define!("mir_storage_live", fn StorageLive(local: T)); define!("mir_storage_dead", fn StorageDead(local: T)); diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 1a35fe05067fc..c00800291dbd3 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -299,10 +299,6 @@ fn check_terminator<'tcx>( | TerminatorKind::Unreachable => Ok(()), TerminatorKind::Drop { place, .. } => check_place(tcx, *place, span, body), - TerminatorKind::DropAndReplace { place, value, .. } => { - check_place(tcx, *place, span, body)?; - check_operand(tcx, value, span, body) - }, TerminatorKind::SwitchInt { discr, targets: _ } => check_operand(tcx, discr, span, body), diff --git a/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir b/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir index c903e5946961b..ada78c0fc782e 100644 --- a/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir +++ b/tests/mir-opt/building/custom/terminators.drop_first.built.after.mir @@ -4,10 +4,11 @@ fn drop_first(_1: WriteOnDrop<'_>, _2: WriteOnDrop<'_>) -> () { let mut _0: (); // return place in scope 0 at $DIR/terminators.rs:+0:59: +0:59 bb0: { - replace(_1 <- move _2) -> bb1; // scope 0 at $DIR/terminators.rs:+3:13: +3:49 + drop(_1) -> bb1; // scope 0 at $DIR/terminators.rs:+3:13: +3:30 } bb1: { - return; // scope 0 at $DIR/terminators.rs:+7:13: +7:21 + _1 = move _2; // scope 0 at $DIR/terminators.rs:+7:13: +7:24 + return; // scope 0 at $DIR/terminators.rs:+8:13: +8:21 } } diff --git a/tests/mir-opt/building/custom/terminators.rs b/tests/mir-opt/building/custom/terminators.rs index c23233fcf9aca..f12405661685b 100644 --- a/tests/mir-opt/building/custom/terminators.rs +++ b/tests/mir-opt/building/custom/terminators.rs @@ -48,10 +48,11 @@ impl<'a> Drop for WriteOnDrop<'a> { fn drop_first<'a>(a: WriteOnDrop<'a>, b: WriteOnDrop<'a>) { mir!( { - DropAndReplace(a, Move(b), retblock) + Drop(a, retblock) } retblock = { + a = Move(b); Return() } ) From 153bfa06e5b8ff57ac5d9274c174c8230a7399eb Mon Sep 17 00:00:00 2001 From: Giacomo Pasini Date: Tue, 7 Mar 2023 20:01:22 +0100 Subject: [PATCH 09/11] remove leftover comment --- .../rustc_const_eval/src/transform/check_consts/resolver.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs index 148aff9be4b5b..78c74e1892dc5 100644 --- a/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs +++ b/compiler/rustc_const_eval/src/transform/check_consts/resolver.rs @@ -224,9 +224,6 @@ where // We ignore borrow on drop because custom drop impls are not allowed in consts. // FIXME: Reconsider if accounting for borrows in drops is necessary for const drop. - - // We need to assign qualifs to the dropped location before visiting the operand that - // replaces it since qualifs can be cleared on move. self.super_terminator(terminator, location); } } From 5eaeb71b9f0c27a3bfab666b3f5288c83c63eafe Mon Sep 17 00:00:00 2001 From: "Celina G. Val" Date: Tue, 7 Mar 2023 12:47:25 -0800 Subject: [PATCH 10/11] Change item collection to be on demand --- compiler/rustc_smir/src/rustc_internal/mod.rs | 11 ++++--- compiler/rustc_smir/src/rustc_smir/mod.rs | 32 ++++++++----------- compiler/rustc_smir/src/stable_mir/mod.rs | 12 +++++-- tests/ui-fulldeps/stable-mir/crate-info.rs | 16 ++++------ 4 files changed, 38 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 044d6a2419f69..3eaff9c051f1c 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -3,10 +3,13 @@ //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! until stable MIR is complete. -use crate::stable_mir::CrateItem; +use crate::stable_mir; +pub use rustc_span::def_id::{CrateNum, DefId}; -pub type DefId = rustc_span::def_id::DefId; - -pub fn item_def_id(item: &CrateItem) -> DefId { +pub fn item_def_id(item: &stable_mir::CrateItem) -> DefId { item.0 } + +pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { + item.id.into() +} diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index 768b01f526f73..d956f0ac80213 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -9,7 +9,7 @@ use crate::stable_mir::{self}; use rustc_middle::ty::{tls::with, TyCtxt}; -use rustc_span::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; +use rustc_span::def_id::{CrateNum, LOCAL_CRATE}; use tracing::debug; /// Get information about the local crate. @@ -17,6 +17,11 @@ pub fn local_crate() -> stable_mir::Crate { with(|tcx| smir_crate(tcx, LOCAL_CRATE)) } +/// Retrieve a list of all external crates. +pub fn external_crates() -> Vec { + with(|tcx| tcx.crates(()).iter().map(|crate_num| smir_crate(tcx, *crate_num)).collect()) +} + /// Find a crate with the given name. pub fn find_crate(name: &str) -> Option { with(|tcx| { @@ -27,26 +32,17 @@ pub fn find_crate(name: &str) -> Option { }) } +/// Retrieve all items of the local crate that have a MIR associated with them. +pub fn all_local_items() -> stable_mir::CrateItems { + with(|tcx| { + tcx.mir_keys(()).iter().map(|item| stable_mir::CrateItem(item.to_def_id())).collect() + }) +} + /// Build a stable mir crate from a given crate number. fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate { let crate_name = tcx.crate_name(crate_num).to_string(); let is_local = crate_num == LOCAL_CRATE; - let mod_id = DefId { index: CRATE_DEF_INDEX, krate: crate_num }; - let items = if is_local { - tcx.hir_module_items(mod_id.expect_local()) - .items() - .map(|item| { - let def_id = item.owner_id.def_id.to_def_id(); - stable_mir::CrateItem(def_id) - }) - .collect() - } else { - tcx.module_children(mod_id) - .iter() - .filter_map(|item| item.res.opt_def_id()) - .map(stable_mir::CrateItem) - .collect::>() - }; debug!(?crate_name, ?crate_num, "smir_crate"); - stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local, root_items: items } + stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local } } diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs index f61ea461dfa85..cbf52e691fb47 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/rustc_smir/src/stable_mir/mod.rs @@ -31,8 +31,6 @@ pub struct Crate { pub(crate) id: CrateNum, pub name: Symbol, pub is_local: bool, - /// The items defined in the root of this crate. - pub root_items: CrateItems, } /// Holds information about an item in the crate. @@ -50,3 +48,13 @@ pub fn local_crate() -> Crate { pub fn find_crate(name: &str) -> Option { crate::rustc_smir::find_crate(name) } + +/// Try to find a crate with the given name. +pub fn external_crates() -> Vec { + crate::rustc_smir::external_crates() +} + +/// Retrieve all items in the local crate that have a MIR associated with them. +pub fn all_local_items() -> CrateItems { + crate::rustc_smir::all_local_items() +} diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index 62cfb809fcbe9..4458ab0162e95 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -29,19 +29,17 @@ fn test_stable_mir(tcx: TyCtxt<'_>) { assert_eq!(&local.name, CRATE_NAME); // Find items in the local crate. - assert!(has_root_item(tcx, &local, (DefKind::Fn, "foo_bar"))); - assert!(has_root_item(tcx, &local, (DefKind::Mod, "foo"))); - assert!(!has_root_item(tcx, &local, (DefKind::Fn, "foo::bar"))); + let items = stable_mir::all_local_items(); + assert!(has_item(tcx, &items, (DefKind::Fn, "foo_bar"))); + assert!(has_item(tcx, &items, (DefKind::Fn, "foo::bar"))); - // Check that we can find items in the `std` crate. - let std_crate = stable_mir::find_crate("std").unwrap(); - assert!(has_root_item(tcx, &std_crate, (DefKind::Mod, "std::any"))); - assert!(!has_root_item(tcx, &std_crate, (DefKind::Fn, "std::any::type_name"))); + // Find the `std` crate. + assert!(stable_mir::find_crate("std").is_some()); } // Use internal API to find a function in a crate. -fn has_root_item(tcx: TyCtxt, krate: &stable_mir::Crate, item: (DefKind, &str)) -> bool { - krate.root_items.iter().any(|crate_item| { +fn has_item(tcx: TyCtxt, items: &stable_mir::CrateItems, item: (DefKind, &str)) -> bool { + items.iter().any(|crate_item| { let def_id = rustc_internal::item_def_id(crate_item); tcx.def_kind(def_id) == item.0 && tcx.def_path_str(def_id) == item.1 }) From 8a99ffc3442329d2fb2f07ce87852c3e12cc4d6a Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 7 Mar 2023 23:37:52 +0000 Subject: [PATCH 11/11] Suppress copy impl error when post-normalized type references errors --- .../rustc_trait_selection/src/traits/misc.rs | 7 ++++++- .../ui/coherence/illegal-copy-bad-projection.rs | 16 ++++++++++++++++ .../coherence/illegal-copy-bad-projection.stderr | 9 +++++++++ .../const-generics/bad-generic-in-copy-impl.rs | 9 +++++++++ .../bad-generic-in-copy-impl.stderr | 9 +++++++++ 5 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tests/ui/coherence/illegal-copy-bad-projection.rs create mode 100644 tests/ui/coherence/illegal-copy-bad-projection.stderr create mode 100644 tests/ui/const-generics/bad-generic-in-copy-impl.rs create mode 100644 tests/ui/const-generics/bad-generic-in-copy-impl.stderr diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index b94346b09560a..336db4fee6ced 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -87,7 +87,12 @@ pub fn type_allowed_to_implement_copy<'tcx>( }; let ty = ocx.normalize(&normalization_cause, param_env, unnormalized_ty); let normalization_errors = ocx.select_where_possible(); - if !normalization_errors.is_empty() { + + // NOTE: The post-normalization type may also reference errors, + // such as when we project to a missing type or we have a mismatch + // between expected and found const-generic types. Don't report an + // additional copy error here, since it's not typically useful. + if !normalization_errors.is_empty() || ty.references_error() { tcx.sess.delay_span_bug(field_span, format!("couldn't normalize struct field `{unnormalized_ty}` when checking Copy implementation")); continue; } diff --git a/tests/ui/coherence/illegal-copy-bad-projection.rs b/tests/ui/coherence/illegal-copy-bad-projection.rs new file mode 100644 index 0000000000000..797443a0abe5a --- /dev/null +++ b/tests/ui/coherence/illegal-copy-bad-projection.rs @@ -0,0 +1,16 @@ +trait AsPtr { + type Ptr; +} + +impl AsPtr for () { + type Ptr = *const void; + //~^ ERROR cannot find type `void` in this scope +} + +#[derive(Copy, Clone)] +struct Foo { + p: <() as AsPtr>::Ptr, + // Do not report a "`Copy` cannot be implemented" here. +} + +fn main() {} diff --git a/tests/ui/coherence/illegal-copy-bad-projection.stderr b/tests/ui/coherence/illegal-copy-bad-projection.stderr new file mode 100644 index 0000000000000..8fed9ba23b24b --- /dev/null +++ b/tests/ui/coherence/illegal-copy-bad-projection.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `void` in this scope + --> $DIR/illegal-copy-bad-projection.rs:6:23 + | +LL | type Ptr = *const void; + | ^^^^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`. diff --git a/tests/ui/const-generics/bad-generic-in-copy-impl.rs b/tests/ui/const-generics/bad-generic-in-copy-impl.rs new file mode 100644 index 0000000000000..b5663464cf422 --- /dev/null +++ b/tests/ui/const-generics/bad-generic-in-copy-impl.rs @@ -0,0 +1,9 @@ +#[derive(Copy, Clone)] +pub struct Foo { + x: [u8; SIZE], + //~^ ERROR mismatched types +} + +const SIZE: u32 = 1; + +fn main() {} diff --git a/tests/ui/const-generics/bad-generic-in-copy-impl.stderr b/tests/ui/const-generics/bad-generic-in-copy-impl.stderr new file mode 100644 index 0000000000000..25701ce68ccc8 --- /dev/null +++ b/tests/ui/const-generics/bad-generic-in-copy-impl.stderr @@ -0,0 +1,9 @@ +error[E0308]: mismatched types + --> $DIR/bad-generic-in-copy-impl.rs:3:13 + | +LL | x: [u8; SIZE], + | ^^^^ expected `usize`, found `u32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`.