diff options
180 files changed, 8084 insertions, 624 deletions
diff --git a/Cargo.lock b/Cargo.lock index e67fe08feec..014e14e5399 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3245,6 +3245,7 @@ dependencies = [ "rustc_driver", "rustc_driver_impl", "rustc_smir", + "stable_mir", ] [[package]] @@ -4409,7 +4410,7 @@ dependencies = [ "rustc_session", "rustc_span", "rustc_target", - "scoped-tls", + "stable_mir", "tracing", ] @@ -4947,6 +4948,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" [[package]] +name = "stable_mir" +version = "0.1.0-preview" +dependencies = [ + "scoped-tls", + "tracing", +] + +[[package]] name = "stacker" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" diff --git a/compiler/rustc/Cargo.toml b/compiler/rustc/Cargo.toml index 41003ad83f3..dcb165f9fdb 100644 --- a/compiler/rustc/Cargo.toml +++ b/compiler/rustc/Cargo.toml @@ -13,6 +13,7 @@ rustc_codegen_ssa = { path = "../rustc_codegen_ssa" } # Make sure rustc_smir ends up in the sysroot, because this # crate is intended to be used by stable MIR consumers, which are not in-tree rustc_smir = { path = "../rustc_smir" } +stable_mir = { path = "../stable_mir" } [dependencies.jemalloc-sys] version = "0.5.0" diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index f14463fe940..23fdd272ffd 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -37,9 +37,10 @@ use std::ptr::{self, NonNull}; use std::slice; use std::{cmp, intrinsics}; +/// This calls the passed function while ensuring it won't be inlined into the caller. #[inline(never)] #[cold] -fn cold_path<F: FnOnce() -> R, R>(f: F) -> R { +fn outline<F: FnOnce() -> R, R>(f: F) -> R { f() } @@ -600,7 +601,7 @@ impl DroplessArena { unsafe { self.write_from_iter(iter, len, mem) } } (_, _) => { - cold_path(move || -> &mut [T] { + outline(move || -> &mut [T] { let mut vec: SmallVec<[_; 8]> = iter.collect(); if vec.is_empty() { return &mut []; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 5b172b863ab..85ab5e7223b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1664,7 +1664,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { lifetime.ident, )); - // Now make an arg that we can use for the substs of the opaque tykind. + // Now make an arg that we can use for the generic params of the opaque tykind. let id = self.next_node_id(); let lifetime_arg = self.new_named_lifetime_with_res(id, lifetime.ident, res); let duplicated_lifetime_def_id = self.local_def_id(duplicated_lifetime_node_id); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 30b47d076e2..55d581b3ab1 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -27,7 +27,7 @@ pub(crate) struct RegionName { /// This helps to print the right kinds of diagnostics. #[derive(Debug, Clone)] pub(crate) enum RegionNameSource { - /// A bound (not free) region that was substituted at the def site (not an HRTB). + /// A bound (not free) region that was instantiated at the def site (not an HRTB). NamedEarlyBoundRegion(Span), /// A free region that the user has a name (`'a`) for. NamedFreeRegion(Span), @@ -516,7 +516,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // be the same as those of the ADT. // FIXME: We should be able to do something similar to // match_adt_and_segment in this case. - Res::Def(DefKind::TyAlias { .. }, _) => (), + Res::Def(DefKind::TyAlias, _) => (), _ => { if let Some(last_segment) = path.segments.last() { if let Some(highlight) = self.match_adt_and_segment( @@ -619,7 +619,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { // programs, so we need to use delay_span_bug here. See #82126. self.infcx.tcx.sess.delay_span_bug( hir_arg.span(), - format!("unmatched subst and hir arg: found {kind:?} vs {hir_arg:?}"), + format!("unmatched arg and hir arg: found {kind:?} vs {hir_arg:?}"), ); } } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 1049e7a8bbe..852935676b6 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2250,7 +2250,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { // Query canonicalization can create local superuniverses (for example in - // `InferCtx::query_response_substitution_guess`), but they don't have an associated + // `InferCtx::query_response_instantiation_guess`), but they don't have an associated // `UniverseInfo` explaining why they were created. // This can cause ICEs if these causes are accessed in diagnostics, for example in issue // #114907 where this happens via liveness and dropck outlives results. diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index aa750dd0169..9b952f3fe36 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1007,7 +1007,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } pub(super) fn register_predefined_opaques_in_new_solver(&mut self) { - // OK to use the identity substitutions for each opaque type key, since + // OK to use the identity arguments for each opaque type key, since // we remap opaques from HIR typeck back to their definition params. let opaques: Vec<_> = self .infcx diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index e00299bad66..af437f36b9f 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -639,10 +639,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { }; let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); - let subst_mapping = - iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var())); + let arg_mapping = iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var())); - UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect(), fr_static } + UniversalRegionIndices { indices: global_mapping.chain(arg_mapping).collect(), fr_static } } fn compute_inputs_and_output( diff --git a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs index f782671fe36..03912b18ea5 100755 --- a/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs +++ b/compiler/rustc_codegen_cranelift/scripts/filter_profile.rs @@ -100,9 +100,9 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { stack = &stack[..index + ENCODE_METADATA.len()]; } - const SUBST_AND_NORMALIZE_ERASING_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::<impl rustc_middle::ty::context::TyCtxt>::subst_and_normalize_erasing_regions"; - if let Some(index) = stack.find(SUBST_AND_NORMALIZE_ERASING_REGIONS) { - stack = &stack[..index + SUBST_AND_NORMALIZE_ERASING_REGIONS.len()]; + const INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::<impl rustc_middle::ty::context::TyCtxt>::instantiate_and_normalize_erasing_regions"; + if let Some(index) = stack.find(INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS) { + stack = &stack[..index + INSTANTIATE_AND_NORMALIZE_ERASING_REGIONS.len()]; } const NORMALIZE_ERASING_LATE_BOUND_REGIONS: &str = "rustc_middle::ty::normalize_erasing_regions::<impl rustc_middle::ty::context::TyCtxt>::normalize_erasing_late_bound_regions"; diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index ec2da39398b..359b430b4e5 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -359,7 +359,7 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> { where T: TypeFoldable<TyCtxt<'tcx>> + Copy, { - self.instance.subst_mir_and_normalize_erasing_regions( + self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(value), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs index 5ca2942ac4e..aff764f0224 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs @@ -90,7 +90,7 @@ fn make_mir_scope<'ll, 'tcx>( Some((callee, _)) => { // FIXME(eddyb) this would be `self.monomorphize(&callee)` // if this is moved to `rustc_codegen_ssa::mir::debuginfo`. - let callee = cx.tcx.subst_and_normalize_erasing_regions( + let callee = cx.tcx.instantiate_and_normalize_erasing_regions( instance.args, ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(callee), diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index c862acdc7de..30cc9ea9b82 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -529,7 +529,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> { if let Some(impl_def_id) = cx.tcx.impl_of_method(instance.def_id()) { // If the method does *not* belong to a trait, proceed if cx.tcx.trait_id_of_impl(impl_def_id).is_none() { - let impl_self_ty = cx.tcx.subst_and_normalize_erasing_regions( + let impl_self_ty = cx.tcx.instantiate_and_normalize_erasing_regions( instance.args, ty::ParamEnv::reveal_all(), cx.tcx.type_of(impl_def_id), diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 1e905a7c78e..a61018f9870 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -118,7 +118,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { T: Copy + TypeFoldable<TyCtxt<'tcx>>, { debug!("monomorphize: self.instance={:?}", self.instance); - self.instance.subst_mir_and_normalize_erasing_regions( + self.instance.instantiate_mir_and_normalize_erasing_regions( self.cx.tcx(), ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(value), diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 9205acc527e..0ab2b7ecd9c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -135,15 +135,14 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { assert_eq!(alloc_align, layout.align.abi); let read_scalar = |start, size, s: abi::Scalar, ty| { - let val = alloc - .0 - .read_scalar( - bx, - alloc_range(start, size), - /*read_provenance*/ matches!(s.primitive(), abi::Pointer(_)), - ) - .unwrap(); - bx.scalar_to_backend(val, s, ty) + match alloc.0.read_scalar( + bx, + alloc_range(start, size), + /*read_provenance*/ matches!(s.primitive(), abi::Pointer(_)), + ) { + Ok(val) => bx.scalar_to_backend(val, s, ty), + Err(_) => bx.const_poison(ty), + } }; // It may seem like all types with `Scalar` or `ScalarPair` ABI are fair game at this point. @@ -156,7 +155,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { Abi::Scalar(s @ abi::Scalar::Initialized { .. }) => { let size = s.size(bx); assert_eq!(size, layout.size, "abi::Scalar size does not match layout size"); - let val = read_scalar(Size::ZERO, size, s, bx.type_ptr()); + let val = read_scalar(offset, size, s, bx.backend_type(layout)); OperandRef { val: OperandValue::Immediate(val), layout } } Abi::ScalarPair( @@ -164,10 +163,10 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> { b @ abi::Scalar::Initialized { .. }, ) => { let (a_size, b_size) = (a.size(bx), b.size(bx)); - let b_offset = a_size.align_to(b.align(bx).abi); + let b_offset = (offset + a_size).align_to(b.align(bx).abi); assert!(b_offset.bytes() > 0); let a_val = read_scalar( - Size::ZERO, + offset, a_size, a, bx.scalar_pair_element_backend_type(layout, 0, true), diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 7c743a21d93..94a5cc67d31 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -569,7 +569,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { ) -> Result<T, ErrorHandled> { frame .instance - .try_subst_mir_and_normalize_erasing_regions( + .try_instantiate_mir_and_normalize_erasing_regions( *self.tcx, self.param_env, ty::EarlyBinder::bind(value), diff --git a/compiler/rustc_const_eval/src/interpret/util.rs b/compiler/rustc_const_eval/src/interpret/util.rs index b3319442388..eb639ded70f 100644 --- a/compiler/rustc_const_eval/src/interpret/util.rs +++ b/compiler/rustc_const_eval/src/interpret/util.rs @@ -4,7 +4,7 @@ use rustc_middle::ty::{ }; use std::ops::ControlFlow; -/// Checks whether a type contains generic parameters which require substitution. +/// Checks whether a type contains generic parameters which must be instantiated. /// /// In case it does, returns a `TooGeneric` const eval error. Note that due to polymorphization /// types may be "concrete enough" even though they still contain generic parameters in @@ -43,7 +43,8 @@ where .try_into() .expect("more generic parameters than can fit into a `u32`"); // Only recurse when generic parameters in fns, closures and generators - // are used and require substitution. + // are used and have to be instantiated. + // // Just in case there are closures or generators within this subst, // recurse. if unused_params.is_used(index) && subst.has_param() { diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs index 2f5f2ad6534..0d8733070a4 100644 --- a/compiler/rustc_const_eval/src/transform/validate.rs +++ b/compiler/rustc_const_eval/src/transform/validate.rs @@ -558,8 +558,8 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> { } } -/// A faster version of the validation pass that only checks those things which may break when apply -/// generic substitutions. +/// A faster version of the validation pass that only checks those things which may break when +/// instantiating any generic parameters. pub fn validate_types<'tcx>( tcx: TyCtxt<'tcx>, mir_phase: MirPhase, diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 7d037ddfa98..461ec3a90ed 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -51,9 +51,10 @@ use std::fmt; pub use rustc_index::static_assert_size; +/// This calls the passed function while ensuring it won't be inlined into the caller. #[inline(never)] #[cold] -pub fn cold_path<F: FnOnce() -> R, R>(f: F) -> R { +pub fn outline<F: FnOnce() -> R, R>(f: F) -> R { f() } diff --git a/compiler/rustc_data_structures/src/profiling.rs b/compiler/rustc_data_structures/src/profiling.rs index 3c76c2b7991..e688feb5fe1 100644 --- a/compiler/rustc_data_structures/src/profiling.rs +++ b/compiler/rustc_data_structures/src/profiling.rs @@ -81,8 +81,8 @@ //! //! [mm]: https://github.com/rust-lang/measureme/ -use crate::cold_path; use crate::fx::FxHashMap; +use crate::outline; use std::borrow::Borrow; use std::collections::hash_map::Entry; @@ -697,7 +697,7 @@ impl<'a> TimingGuard<'a> { #[inline] pub fn finish_with_query_invocation_id(self, query_invocation_id: QueryInvocationId) { if let Some(guard) = self.0 { - cold_path(|| { + outline(|| { let event_id = StringId::new_virtual(query_invocation_id.0); let event_id = EventId::from_virtual(event_id); guard.finish_with_override_event_id(event_id); diff --git a/compiler/rustc_data_structures/src/sync/worker_local.rs b/compiler/rustc_data_structures/src/sync/worker_local.rs index 1f838cc4648..ffafdba13ce 100644 --- a/compiler/rustc_data_structures/src/sync/worker_local.rs +++ b/compiler/rustc_data_structures/src/sync/worker_local.rs @@ -6,7 +6,7 @@ use std::ptr; use std::sync::Arc; #[cfg(parallel_compiler)] -use {crate::cold_path, crate::sync::CacheAligned}; +use {crate::outline, crate::sync::CacheAligned}; /// A pointer to the `RegistryData` which uniquely identifies a registry. /// This identifier can be reused if the registry gets freed. @@ -25,11 +25,7 @@ impl RegistryId { fn verify(self) -> usize { let (id, index) = THREAD_DATA.with(|data| (data.registry_id.get(), data.index.get())); - if id == self { - index - } else { - cold_path(|| panic!("Unable to verify registry association")) - } + if id == self { index } else { outline(|| panic!("Unable to verify registry association")) } } } diff --git a/compiler/rustc_error_codes/src/error_codes/E0038.md b/compiler/rustc_error_codes/src/error_codes/E0038.md index 584b78554ef..8f8eabb1519 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0038.md +++ b/compiler/rustc_error_codes/src/error_codes/E0038.md @@ -162,14 +162,13 @@ fn foo<T>(x: T) { ``` The machine code for `foo::<u8>()`, `foo::<bool>()`, `foo::<String>()`, or any -other type substitution is different. Hence the compiler generates the +other instantiation is different. Hence the compiler generates the implementation on-demand. If you call `foo()` with a `bool` parameter, the compiler will only generate code for `foo::<bool>()`. When we have additional type parameters, the number of monomorphized implementations the compiler generates does not grow drastically, since the compiler will only generate an -implementation if the function is called with unparameterized substitutions -(i.e., substitutions where none of the substituted types are themselves -parameterized). +implementation if the function is called with fully concrete arguments +(i.e., arguments which do not contain any generic parameters). However, with trait objects we have to make a table containing _every_ object that implements the trait. Now, if it has type parameters, we need to add diff --git a/compiler/rustc_error_codes/src/error_codes/E0094.md b/compiler/rustc_error_codes/src/error_codes/E0094.md index 67a8c3678c5..d8c1a3cb55c 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0094.md +++ b/compiler/rustc_error_codes/src/error_codes/E0094.md @@ -3,7 +3,7 @@ An invalid number of generic parameters was passed to an intrinsic function. Erroneous code example: ```compile_fail,E0094 -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { @@ -18,7 +18,7 @@ and verify with the function declaration in the Rust source code. Example: ``` -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { diff --git a/compiler/rustc_error_codes/src/error_codes/E0211.md b/compiler/rustc_error_codes/src/error_codes/E0211.md index 70f14fffae6..19a482f6c93 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0211.md +++ b/compiler/rustc_error_codes/src/error_codes/E0211.md @@ -4,7 +4,7 @@ You used a function or type which doesn't fit the requirements for where it was used. Erroneous code examples: ```compile_fail -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { @@ -41,7 +41,7 @@ impl Foo { For the first code example, please check the function definition. Example: ``` -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] #![allow(internal_features)] extern "rust-intrinsic" { diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index f3b88f46bae..94afb6edcf6 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -236,7 +236,7 @@ declare_features! ( /// Allows using the `#[fundamental]` attribute. (active, fundamental, "1.0.0", Some(29635), None), /// Allows using `#[link_name="llvm.*"]`. - (active, link_llvm_intrinsics, "1.0.0", Some(29602), None), + (internal, link_llvm_intrinsics, "1.0.0", Some(29602), None), /// Allows using the `#[linkage = ".."]` attribute. (active, linkage, "1.0.0", Some(29603), None), /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed. @@ -245,6 +245,8 @@ declare_features! ( (active, packed_bundled_libs, "1.69.0", Some(108081), None), /// Allows using the `#![panic_runtime]` attribute. (internal, panic_runtime, "1.10.0", Some(32837), None), + /// Allows `extern "platform-intrinsic" { ... }`. + (internal, platform_intrinsics, "1.4.0", Some(27731), None), /// Allows using `#[rustc_allow_const_fn_unstable]`. /// This is an attribute on `const fn` for the same /// purpose as `#[allow_internal_unstable]`. @@ -526,8 +528,6 @@ declare_features! ( (active, object_safe_for_dispatch, "1.40.0", Some(43561), None), /// Allows using `#[optimize(X)]`. (active, optimize_attribute, "1.34.0", Some(54882), None), - /// Allows `extern "platform-intrinsic" { ... }`. - (active, platform_intrinsics, "1.4.0", Some(27731), None), /// Allows using `#![plugin(myplugin)]`. (active, plugin, "1.0.0", Some(29597), None), /// Allows exhaustive integer pattern matching on `usize` and `isize`. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 04ebe22a9eb..18397af565f 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -537,7 +537,6 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ allow_internal_unsafe, Normal, template!(Word), WarnFollowing, "allow_internal_unsafe side-steps the unsafe_code lint", ), - ungated!(rustc_safe_intrinsic, Normal, template!(Word), DuplicatesOk), rustc_attr!(rustc_allowed_through_unstable_modules, Normal, template!(Word), WarnFollowing, "rustc_allowed_through_unstable_modules special cases accidental stabilizations of stable items \ through unstable paths"), @@ -806,6 +805,10 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing, r#"`rustc_doc_primitive` is a rustc internal attribute"#, ), + rustc_attr!( + rustc_safe_intrinsic, Normal, template!(Word), WarnFollowing, + "the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe" + ), // ========================================================================== // Internal attributes, Testing: diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 64271309664..3a4eb90f7f9 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -61,9 +61,7 @@ pub enum DefKind { Variant, Trait, /// Type alias: `type Foo = Bar;` - TyAlias { - lazy: bool, - }, + TyAlias, /// Type from an `extern` block. ForeignTy, /// Trait alias: `trait IntIterator = Iterator<Item = i32>;` @@ -143,7 +141,7 @@ impl DefKind { DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct", DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct", DefKind::OpaqueTy => "opaque type", - DefKind::TyAlias { .. } => "type alias", + DefKind::TyAlias => "type alias", DefKind::TraitAlias => "trait alias", DefKind::AssocTy => "associated type", DefKind::Union => "union", @@ -199,7 +197,7 @@ impl DefKind { | DefKind::Variant | DefKind::Trait | DefKind::OpaqueTy - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -250,7 +248,7 @@ impl DefKind { | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 644c4d8265d..0d65ddb5642 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -101,7 +101,7 @@ impl Target { DefKind::Mod => Target::Mod, DefKind::ForeignMod => Target::ForeignMod, DefKind::GlobalAsm => Target::GlobalAsm, - DefKind::TyAlias { .. } => Target::TyAlias, + DefKind::TyAlias => Target::TyAlias, DefKind::OpaqueTy => Target::OpaqueTy, DefKind::Enum => Target::Enum, DefKind::Struct => Target::Struct, diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index ba152cd48de..21611e9c586 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -427,7 +427,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { let bound_vars = tcx.late_bound_vars(binding.hir_id); ty::Binder::bind_with_vars(subst_output, bound_vars) } else { - // Include substitutions for generic parameters of associated types + // Append the generic arguments of the associated type to the `trait_ref`. candidate.map_bound(|trait_ref| { let ident = Ident::new(assoc_item.name, binding.item_name.span); let item_segment = hir::PathSegment { diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs index 1372cc896be..e3621ef933a 100644 --- a/compiler/rustc_hir_analysis/src/astconv/generics.rs +++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs @@ -139,22 +139,22 @@ fn generic_arg_mismatch_err( err.emit() } -/// Creates the relevant generic argument substitutions +/// Creates the relevant generic arguments /// corresponding to a set of generic parameters. This is a /// rather complex function. Let us try to explain the role /// of each of its parameters: /// -/// To start, we are given the `def_id` of the thing we are -/// creating the substitutions for, and a partial set of -/// substitutions `parent_args`. In general, the substitutions -/// for an item begin with substitutions for all the "parents" of +/// To start, we are given the `def_id` of the thing whose generic +/// parameters we are instantiating, and a partial set of +/// arguments `parent_args`. In general, the generic arguments +/// for an item begin with arguments for all the "parents" of /// that item -- e.g., for a method it might include the /// parameters from the impl. /// /// Therefore, the method begins by walking down these parents, /// starting with the outermost parent and proceed inwards until /// it reaches `def_id`. For each parent `P`, it will check `parent_args` -/// first to see if the parent's substitutions are listed in there. If so, +/// first to see if the parent's arguments are listed in there. If so, /// we can append those and move on. Otherwise, it invokes the /// three callback functions: /// @@ -188,7 +188,7 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( stack.push((def_id, parent_defs)); } - // We manually build up the substitution, rather than using convenience + // We manually build up the generic arguments, rather than using convenience // methods in `subst.rs`, so that we can iterate over the arguments and // parameters in lock-step linearly, instead of trying to match each pair. let mut args: SmallVec<[ty::GenericArg<'tcx>; 8]> = SmallVec::with_capacity(count); @@ -196,7 +196,8 @@ pub fn create_args_for_parent_generic_args<'tcx, 'a>( while let Some((def_id, defs)) = stack.pop() { let mut params = defs.params.iter().peekable(); - // If we have already computed substitutions for parents, we can use those directly. + // If we have already computed the generic arguments for parents, + // we can use those directly. while let Some(¶m) = params.peek() { if let Some(&kind) = parent_args.get(param.index as usize) { args.push(kind); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 106cd223d30..56b1fd36973 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -289,7 +289,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`, - /// returns an appropriate set of substitutions for this particular reference to `I`. + /// returns an appropriate set of generic arguments for this particular reference to `I`. pub fn ast_path_args_for_ty( &self, span: Span, @@ -315,7 +315,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { /// Given the type/lifetime/const arguments provided to some path (along with /// an implicit `Self`, if this is a trait reference), returns the complete - /// set of substitutions. This may involve applying defaulted type parameters. + /// set of generic arguments. This may involve applying defaulted type parameters. /// Constraints on associated types are created from `create_assoc_bindings_for_generic_args`. /// /// Example: @@ -909,23 +909,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { let tcx = self.tcx(); let args = self.ast_path_args_for_ty(span, did, item_segment); - if let DefKind::TyAlias { lazy: true } = tcx.def_kind(did) { + if let DefKind::TyAlias = tcx.def_kind(did) + && tcx.type_alias_is_lazy(did) + { // Type aliases defined in crates that have the // feature `lazy_type_alias` enabled get encoded as a type alias that normalization will // then actually instantiate the where bounds of. let alias_ty = tcx.mk_alias_ty(did, args); Ty::new_alias(tcx, ty::Weak, alias_ty) } else { - let ty = tcx.at(span).type_of(did); - if ty.skip_binder().has_opaque_types() { - // Type aliases referring to types that contain opaque types (but aren't just directly - // referencing a single opaque type) get encoded as a type alias that normalization will - // then actually instantiate the where bounds of. - let alias_ty = tcx.mk_alias_ty(did, args); - Ty::new_alias(tcx, ty::Weak, alias_ty) - } else { - ty.instantiate(tcx, args) - } + tcx.at(span).type_of(did).instantiate(tcx, args) } } @@ -2164,7 +2157,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } Res::Def( DefKind::Enum - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::Struct | DefKind::Union | DefKind::ForeignTy, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 564206f9e4b..eb1f48d23ff 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -640,7 +640,7 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) { check_opaque(tcx, id); } } - DefKind::TyAlias { .. } => { + DefKind::TyAlias => { let pty_ty = tcx.type_of(id.owner_id).instantiate_identity(); let generics = tcx.generics_of(id.owner_id); check_type_params_are_used(tcx, &generics, pty_ty); diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs index a8149b634ef..d9e0e87eb47 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs @@ -5,7 +5,7 @@ use rustc_infer::infer::{outlives::env::OutlivesEnvironment, TyCtxtInferExt}; use rustc_lint_defs::builtin::REFINING_IMPL_TRAIT; use rustc_middle::traits::{ObligationCause, Reveal}; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, + self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperVisitable, TypeVisitable, TypeVisitor, }; use rustc_span::{Span, DUMMY_SP}; use rustc_trait_selection::traits::{ @@ -176,9 +176,13 @@ pub(super) fn check_refining_return_position_impl_trait_in_trait<'tcx>( return; }; - // For quicker lookup, use an `IndexSet` - // (we don't use one earlier because it's not foldable..) - let trait_bounds = FxIndexSet::from_iter(trait_bounds); + // For quicker lookup, use an `IndexSet` (we don't use one earlier because + // it's not foldable..). + // Also, We have to anonymize binders in these types because they may contain + // `BrNamed` bound vars, which contain unique `DefId`s which correspond to syntax + // locations that we don't care about when checking bound equality. + let trait_bounds = FxIndexSet::from_iter(trait_bounds.fold_with(&mut Anonymize { tcx })); + let impl_bounds = impl_bounds.fold_with(&mut Anonymize { tcx }); // Find any clauses that are present in the impl's RPITITs that are not // present in the trait's RPITITs. This will trigger on trivial predicates, @@ -309,3 +313,20 @@ fn type_visibility<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Option<ty::Visibili _ => None, } } + +struct Anonymize<'tcx> { + tcx: TyCtxt<'tcx>, +} + +impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Anonymize<'tcx> { + fn interner(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> + where + T: TypeFoldable<TyCtxt<'tcx>>, + { + self.tcx.anonymize_bound_vars(t) + } +} diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 00a684f2963..b7b162ce27b 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -246,9 +246,7 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) { // `ForeignItem`s are handled separately. hir::ItemKind::ForeignMod { .. } => {} hir::ItemKind::TyAlias(hir_ty, ast_generics) => { - if tcx.features().lazy_type_alias - || tcx.type_of(item.owner_id).skip_binder().has_opaque_types() - { + if tcx.type_alias_is_lazy(item.owner_id) { // Bounds of lazy type aliases and of eager ones that contain opaque types are respected. // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`. check_item_type(tcx, def_id, hir_ty.span, UnsizedHandling::Allow); @@ -1711,10 +1709,8 @@ fn check_variances_for_type_defn<'tcx>( } } ItemKind::TyAlias(..) => { - let ty = tcx.type_of(item.owner_id).instantiate_identity(); - - if tcx.features().lazy_type_alias || ty.has_opaque_types() { - if ty.references_error() { + if tcx.type_alias_is_lazy(item.owner_id) { + if tcx.type_of(item.owner_id).skip_binder().references_error() { return; } } else { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 01e40c62a8b..cd37221ae6f 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -58,6 +58,7 @@ pub fn provide(providers: &mut Providers) { *providers = Providers { type_of: type_of::type_of, type_of_opaque: type_of::type_of_opaque, + type_alias_is_lazy: type_of::type_alias_is_lazy, item_bounds: item_bounds::item_bounds, explicit_item_bounds: item_bounds::explicit_item_bounds, generics_of: generics_of::generics_of, diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index d9207f2de52..eb4466449a0 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -1519,7 +1519,7 @@ impl<'a, 'tcx> BoundVarContext<'a, 'tcx> { DefKind::Struct | DefKind::Union | DefKind::Enum - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::Trait, def_id, ) if depth == 0 => Some(def_id), @@ -2029,7 +2029,7 @@ fn is_late_bound_map( hir::TyKind::Path(hir::QPath::Resolved( None, - hir::Path { res: Res::Def(DefKind::TyAlias { .. }, alias_def), segments, span }, + hir::Path { res: Res::Def(DefKind::TyAlias, alias_def), segments, span }, )) => { // See comments on `ConstrainedCollectorPostAstConv` for why this arm does not just consider // args to be unconstrained. diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index d12337687e2..ae62119b182 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -623,3 +623,25 @@ fn check_feature_inherent_assoc_ty(tcx: TyCtxt<'_>, span: Span) { .emit(); } } + +pub fn type_alias_is_lazy<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { + use hir::intravisit::Visitor; + if tcx.features().lazy_type_alias { + return true; + } + struct HasTait { + has_type_alias_impl_trait: bool, + } + impl<'tcx> Visitor<'tcx> for HasTait { + fn visit_ty(&mut self, t: &'tcx hir::Ty<'tcx>) { + if let hir::TyKind::OpaqueDef(..) = t.kind { + self.has_type_alias_impl_trait = true; + } else { + hir::intravisit::walk_ty(self, t); + } + } + } + let mut has_tait = HasTait { has_type_alias_impl_trait: false }; + has_tait.visit_ty(tcx.hir().expect_item(def_id).expect_ty_alias().0); + has_tait.has_type_alias_impl_trait +} diff --git a/compiler/rustc_hir_analysis/src/variance/constraints.rs b/compiler/rustc_hir_analysis/src/variance/constraints.rs index 9aac7160f2e..61d9c989e2f 100644 --- a/compiler/rustc_hir_analysis/src/variance/constraints.rs +++ b/compiler/rustc_hir_analysis/src/variance/constraints.rs @@ -6,7 +6,7 @@ use hir::def_id::{DefId, LocalDefId}; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{GenericArgKind, GenericArgsRef}; use super::terms::VarianceTerm::*; @@ -78,9 +78,7 @@ pub fn add_constraints_from_crate<'a, 'tcx>( } } DefKind::Fn | DefKind::AssocFn => constraint_cx.build_constraints_for_item(def_id), - DefKind::TyAlias { lazy } - if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() => - { + DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => { constraint_cx.build_constraints_for_item(def_id) } _ => {} @@ -110,8 +108,8 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> { // The type as returned by `type_of` is the underlying type and generally not a weak projection. // Therefore we need to check the `DefKind` first. - if let DefKind::TyAlias { lazy } = tcx.def_kind(def_id) - && (lazy || ty.has_opaque_types()) + if let DefKind::TyAlias = tcx.def_kind(def_id) + && tcx.type_alias_is_lazy(def_id) { self.add_constraints_from_ty(current_item, ty, self.covariant); return; diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs index d69d7ff904a..85e0000ab47 100644 --- a/compiler/rustc_hir_analysis/src/variance/mod.rs +++ b/compiler/rustc_hir_analysis/src/variance/mod.rs @@ -8,7 +8,7 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, CrateVariancesMap, GenericArgsRef, Ty, TyCtxt}; -use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt}; +use rustc_middle::ty::{TypeSuperVisitable, TypeVisitable}; use std::ops::ControlFlow; /// Defines the `TermsContext` basically houses an arena where we can @@ -56,9 +56,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] { let crate_map = tcx.crate_variances(()); return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); } - DefKind::TyAlias { lazy } - if lazy || tcx.type_of(item_def_id).instantiate_identity().has_opaque_types() => - { + DefKind::TyAlias if tcx.type_alias_is_lazy(item_def_id) => { // These are inferred. let crate_map = tcx.crate_variances(()); return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]); diff --git a/compiler/rustc_hir_analysis/src/variance/terms.rs b/compiler/rustc_hir_analysis/src/variance/terms.rs index 1a8ec5f0853..275df24956c 100644 --- a/compiler/rustc_hir_analysis/src/variance/terms.rs +++ b/compiler/rustc_hir_analysis/src/variance/terms.rs @@ -12,7 +12,7 @@ use rustc_arena::DroplessArena; use rustc_hir::def::DefKind; use rustc_hir::def_id::{LocalDefId, LocalDefIdMap}; -use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, TyCtxt}; use std::fmt; use self::VarianceTerm::*; @@ -97,9 +97,7 @@ pub fn determine_parameters_to_be_inferred<'a, 'tcx>( } } DefKind::Fn | DefKind::AssocFn => terms_cx.add_inferreds_for_item(def_id), - DefKind::TyAlias { lazy } - if lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() => - { + DefKind::TyAlias if tcx.type_alias_is_lazy(def_id) => { terms_cx.add_inferreds_for_item(def_id) } _ => {} diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 31e773585d1..256a4bf9449 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -545,6 +545,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Climb the HIR tree to see if the current `Expr` is part of a `break;` statement. let Some( hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Semi(&ref p), .. }) + | hir::Node::Block(hir::Block { expr: Some(&ref p), .. }) | hir::Node::Expr(&ref p), ) = self.tcx.hir().find(parent_id) else { diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 37ea94d821e..c0332a48be3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1370,10 +1370,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => bug!("unexpected type: {:?}", ty.normalized), }, - Res::Def( - DefKind::Struct | DefKind::Union | DefKind::TyAlias { .. } | DefKind::AssocTy, - _, - ) + Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => match ty.normalized.ty_adt_def() { Some(adt) if !adt.is_enum() => { diff --git a/compiler/rustc_hir_typeck/src/mem_categorization.rs b/compiler/rustc_hir_typeck/src/mem_categorization.rs index 7fb1dc2347e..337d12b2d51 100644 --- a/compiler/rustc_hir_typeck/src/mem_categorization.rs +++ b/compiler/rustc_hir_typeck/src/mem_categorization.rs @@ -464,7 +464,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { // Opaque types can't have field projections, but we can instead convert // the current place in-place (heh) to the hidden type, and then apply all // follow up projections on that. - if node_ty != place_ty && place_ty.has_opaque_types() { + if node_ty != place_ty && matches!(place_ty.kind(), ty::Alias(ty::Opaque, ..)) { projections.push(Projection { kind: ProjectionKind::OpaqueCast, ty: node_ty }); } projections.push(Projection { kind, ty }); @@ -557,10 +557,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx> { Ok(adt_def.variant_index_with_ctor_id(variant_ctor_id)) } Res::Def(DefKind::Ctor(CtorOf::Struct, ..), _) - | Res::Def( - DefKind::Struct | DefKind::Union | DefKind::TyAlias { .. } | DefKind::AssocTy, - _, - ) + | Res::Def(DefKind::Struct | DefKind::Union | DefKind::TyAlias | DefKind::AssocTy, _) | Res::SelfCtor(..) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => { diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index bcaa4091c3a..a9029a8cec0 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -918,7 +918,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { // // See the `need_type_info/issue-103053.rs` test for // a example. - if !matches!(path.res, Res::Def(DefKind::TyAlias { .. }, _)) => { + if !matches!(path.res, Res::Def(DefKind::TyAlias, _)) => { if let Some(ty) = self.opt_node_type(expr.hir_id) && let ty::Adt(_, args) = ty.kind() { @@ -1047,7 +1047,7 @@ impl<'a, 'tcx> FindInferSourceVisitor<'a, 'tcx> { ) => { if tcx.res_generics_def_id(path.res) != Some(def.did()) { match path.res { - Res::Def(DefKind::TyAlias { .. }, _) => { + Res::Def(DefKind::TyAlias, _) => { // FIXME: Ideally we should support this. For that // we have to map back from the self type to the // type alias though. That's difficult. diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 4f6b79d9aee..536f78a73ed 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1454,13 +1454,13 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { let hir::ItemKind::TyAlias(hir_ty, type_alias_generics) = &item.kind else { return }; - if cx.tcx.features().lazy_type_alias { - // Bounds of lazy type aliases are respected. + // Bounds of lazy type aliases and TAITs are respected. + if cx.tcx.type_alias_is_lazy(item.owner_id) { return; } let ty = cx.tcx.type_of(item.owner_id).skip_binder(); - if ty.has_opaque_types() || ty.has_inherent_projections() { + if ty.has_inherent_projections() { // Bounds of type aliases that contain opaque types or inherent projections are respected. // E.g: `type X = impl Trait;`, `type X = (impl Trait, Y);`, `type X = Type::Inherent;`. return; diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 21575bf6b04..69b462d32bd 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2312,6 +2312,57 @@ declare_lint! { } declare_lint! { + /// The `const_patterns_without_partial_eq` lint detects constants that are used in patterns, + /// whose type does not implement `PartialEq`. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![deny(const_patterns_without_partial_eq)] + /// + /// trait EnumSetType { + /// type Repr; + /// } + /// + /// enum Enum8 { } + /// impl EnumSetType for Enum8 { + /// type Repr = u8; + /// } + /// + /// #[derive(PartialEq, Eq)] + /// struct EnumSet<T: EnumSetType> { + /// __enumset_underlying: T::Repr, + /// } + /// + /// const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 }; + /// + /// fn main() { + /// match CONST_SET { + /// CONST_SET => { /* ok */ } + /// _ => panic!("match fell through?"), + /// } + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Previous versions of Rust accepted constants in patterns, even if those constants' types + /// did not have `PartialEq` implemented. The compiler falls back to comparing the value + /// field-by-field. In the future we'd like to ensure that pattern matching always + /// follows `PartialEq` semantics, so that trait bound will become a requirement for + /// matching on constants. + pub CONST_PATTERNS_WITHOUT_PARTIAL_EQ, + Warn, + "constant in pattern does not implement `PartialEq`", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, + reference: "issue #116122 <https://github.com/rust-lang/rust/issues/116122>", + }; +} + +declare_lint! { /// The `ambiguous_associated_items` lint detects ambiguity between /// [associated items] and [enum variants]. /// @@ -3357,6 +3408,7 @@ declare_lint_pass! { CONFLICTING_REPR_HINTS, CONST_EVALUATABLE_UNCHECKED, CONST_ITEM_MUTATION, + CONST_PATTERNS_WITHOUT_PARTIAL_EQ, DEAD_CODE, DEPRECATED, DEPRECATED_CFG_ATTR_CRATE_TYPE_NAME, diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index b56fe375849..f27eee0d79a 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -210,6 +210,7 @@ provide! { tcx, def_id, other, cdata, inferred_outlives_of => { table_defaulted_array } super_predicates_of => { table } type_of => { table } + type_alias_is_lazy => { cdata.root.tables.type_alias_is_lazy.get(cdata, def_id.index) } variances_of => { table } fn_sig => { table } codegen_fn_attrs => { table } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 7506fc1bb05..a4ba943275e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -31,7 +31,6 @@ use rustc_middle::query::Providers; use rustc_middle::traits::specialization_graph; use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams}; -use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, AssocItemContainer, SymbolName, Ty, TyCtxt}; use rustc_middle::util::common::to_readable_str; use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; @@ -827,7 +826,7 @@ fn should_encode_span(def_kind: DefKind) -> bool { | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -862,7 +861,7 @@ fn should_encode_attrs(def_kind: DefKind) -> bool { | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -903,7 +902,7 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool { | DefKind::Variant | DefKind::Trait | DefKind::Impl { .. } => true, - DefKind::TyAlias { .. } + DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -938,7 +937,7 @@ fn should_encode_visibility(def_kind: DefKind) -> bool { | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -982,7 +981,7 @@ fn should_encode_stability(def_kind: DefKind) -> bool { | DefKind::Const | DefKind::Fn | DefKind::ForeignMod - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::Enum | DefKind::Union @@ -1092,9 +1091,7 @@ fn should_encode_variances<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, def_kind: Def | DefKind::Closure | DefKind::Generator | DefKind::ExternCrate => false, - DefKind::TyAlias { lazy } => { - lazy || tcx.type_of(def_id).instantiate_identity().has_opaque_types() - } + DefKind::TyAlias => tcx.type_alias_is_lazy(def_id), } } @@ -1105,7 +1102,7 @@ fn should_encode_generics(def_kind: DefKind) -> bool { | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy @@ -1145,7 +1142,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) -> | DefKind::Fn | DefKind::Const | DefKind::Static(..) - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::Impl { .. } | DefKind::AssocFn @@ -1205,7 +1202,7 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool { | DefKind::Const | DefKind::Static(..) | DefKind::Ctor(..) - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::ForeignTy | DefKind::Impl { .. } @@ -1246,7 +1243,7 @@ fn should_encode_constness(def_kind: DefKind) -> bool { | DefKind::AssocConst | DefKind::AnonConst | DefKind::Static(..) - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::Impl { of_trait: false } | DefKind::ForeignTy @@ -1279,7 +1276,7 @@ fn should_encode_const(def_kind: DefKind) -> bool { | DefKind::Field | DefKind::Fn | DefKind::Static(..) - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::OpaqueTy | DefKind::ForeignTy | DefKind::Impl { .. } @@ -1451,6 +1448,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::Macro(_) = def_kind { self.encode_info_for_macro(local_id); } + if let DefKind::TyAlias = def_kind { + self.tables + .type_alias_is_lazy + .set(def_id.index, self.tcx.type_alias_is_lazy(def_id)); + } if let DefKind::OpaqueTy = def_kind { self.encode_explicit_item_bounds(def_id); self.tables diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 09b2a1a0cb2..42764af52c4 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -383,6 +383,7 @@ define_tables! { is_intrinsic: Table<DefIndex, bool>, is_macro_rules: Table<DefIndex, bool>, is_type_alias_impl_trait: Table<DefIndex, bool>, + type_alias_is_lazy: Table<DefIndex, bool>, attr_flags: Table<DefIndex, AttrFlags>, def_path_hashes: Table<DefIndex, DefPathHash>, explicit_item_bounds: Table<DefIndex, LazyArray<(ty::Clause<'static>, Span)>>, diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index d105dab4814..bb1320942b0 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -145,8 +145,7 @@ fixed_size_enum! { ( Enum ) ( Variant ) ( Trait ) - ( TyAlias { lazy: false } ) - ( TyAlias { lazy: true } ) + ( TyAlias ) ( ForeignTy ) ( TraitAlias ) ( AssocTy ) diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 3491c487f3e..4af2d83e9c7 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -196,9 +196,7 @@ impl<'hir> Map<'hir> { ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind), ItemKind::Mod(..) => DefKind::Mod, ItemKind::OpaqueTy(..) => DefKind::OpaqueTy, - ItemKind::TyAlias(..) => { - DefKind::TyAlias { lazy: self.tcx.features().lazy_type_alias } - } + ItemKind::TyAlias(..) => DefKind::TyAlias, ItemKind::Enum(..) => DefKind::Enum, ItemKind::Struct(..) => DefKind::Struct, ItemKind::Union(..) => DefKind::Union, diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 8f651b2a2db..201926fee3e 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1333,7 +1333,7 @@ pub enum AggregateKind<'tcx> { Generator(DefId, GenericArgsRef<'tcx>, hir::Movability), } -#[derive(Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] +#[derive(Copy, Clone, Debug, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable)] pub enum NullOp<'tcx> { /// Returns the size of a value of that type SizeOf, diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 5986a8b1cd8..340c5a769db 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -229,7 +229,7 @@ rustc_queries! { action = { use rustc_hir::def::DefKind; match tcx.def_kind(key) { - DefKind::TyAlias { .. } => "expanding type alias", + DefKind::TyAlias => "expanding type alias", DefKind::TraitAlias => "expanding trait alias", _ => "computing type of", } @@ -251,6 +251,14 @@ rustc_queries! { } } + query type_alias_is_lazy(key: DefId) -> bool { + desc { |tcx| + "computing whether `{path}` is a lazy type alias", + path = tcx.def_path_str(key), + } + separate_provide_extern + } + query collect_return_position_impl_trait_in_trait_tys(key: DefId) -> Result<&'tcx FxHashMap<DefId, ty::EarlyBinder<Ty<'tcx>>>, ErrorGuaranteed> { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 8c39614903c..89934e4350e 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -732,12 +732,16 @@ pub enum PatKind<'tcx> { }, /// One of the following: - /// * `&str`, which will be handled as a string pattern and thus exhaustiveness - /// checking will detect if you use the same string twice in different patterns. - /// * integer, bool, char or float, which will be handled by exhaustiveness to cover exactly - /// its own value, similar to `&str`, but these values are much simpler. - /// * Opaque constants, that must not be matched structurally. So anything that does not derive - /// `PartialEq` and `Eq`. + /// * `&str` (represented as a valtree), which will be handled as a string pattern and thus + /// exhaustiveness checking will detect if you use the same string twice in different + /// patterns. + /// * integer, bool, char or float (represented as a valtree), which will be handled by + /// exhaustiveness to cover exactly its own value, similar to `&str`, but these values are + /// much simpler. + /// * Opaque constants (represented as `mir::ConstValue`), that must not be matched + /// structurally. So anything that does not derive `PartialEq` and `Eq`. + /// + /// These are always compared with the matched place using (the semantics of) `PartialEq`. Constant { value: mir::Const<'tcx>, }, diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index 219927f5ab4..f50969dd967 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -448,7 +448,7 @@ impl<'tcx> AdtDef<'tcx> { Res::Def(DefKind::Ctor(..), cid) => self.variant_with_ctor_id(cid), Res::Def(DefKind::Struct, _) | Res::Def(DefKind::Union, _) - | Res::Def(DefKind::TyAlias { .. }, _) + | Res::Def(DefKind::TyAlias, _) | Res::Def(DefKind::AssocTy, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a7dd6dc737d..c06b8b2dfa0 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1114,7 +1114,7 @@ impl<'tcx> TyCtxt<'tcx> { if let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) && let hir::TyKind::Path(hir::QPath::Resolved( None, - hir::Path { res: hir::def::Res::Def(DefKind::TyAlias { .. }, def_id), .. }, )) = hir_output.kind + hir::Path { res: hir::def::Res::Def(DefKind::TyAlias, def_id), .. }, )) = hir_output.kind && let Some(local_id) = def_id.as_local() && let Some(alias_ty) = self.hir().get_by_def_id(local_id).alias_ty() // it is type alias && let Some(alias_generics) = self.hir().get_by_def_id(local_id).generics() diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index e7ebb985ca4..f03813a459b 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -493,7 +493,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for IsSuggestableVisitor<'tcx> { Alias(Opaque, AliasTy { def_id, .. }) => { let parent = self.tcx.parent(def_id); let parent_ty = self.tcx.type_of(parent).instantiate_identity(); - if let DefKind::TyAlias { .. } | DefKind::AssocTy = self.tcx.def_kind(parent) + if let DefKind::TyAlias | DefKind::AssocTy = self.tcx.def_kind(parent) && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind() && parent_opaque_def_id == def_id { @@ -577,7 +577,7 @@ impl<'tcx> FallibleTypeFolder<TyCtxt<'tcx>> for MakeSuggestableFolder<'tcx> { Alias(Opaque, AliasTy { def_id, .. }) => { let parent = self.tcx.parent(def_id); let parent_ty = self.tcx.type_of(parent).instantiate_identity(); - if let hir::def::DefKind::TyAlias { .. } | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent) + if let hir::def::DefKind::TyAlias | hir::def::DefKind::AssocTy = self.tcx.def_kind(parent) && let Alias(Opaque, AliasTy { def_id: parent_opaque_def_id, .. }) = *parent_ty.kind() && parent_opaque_def_id == def_id { diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 2b75f6c4e8f..0b0a708e42b 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -118,7 +118,7 @@ impl<'tcx> Instance<'tcx> { /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization. pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { let ty = tcx.type_of(self.def.def_id()); - tcx.subst_and_normalize_erasing_regions(self.args, param_env, ty) + tcx.instantiate_and_normalize_erasing_regions(self.args, param_env, ty) } /// Finds a crate that contains a monomorphization of this instance that @@ -580,7 +580,7 @@ impl<'tcx> Instance<'tcx> { self.def.has_polymorphic_mir_body().then_some(self.args) } - pub fn subst_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T + pub fn instantiate_mir<T>(&self, tcx: TyCtxt<'tcx>, v: EarlyBinder<&T>) -> T where T: TypeFoldable<TyCtxt<'tcx>> + Copy, { @@ -593,7 +593,7 @@ impl<'tcx> Instance<'tcx> { } #[inline(always)] - pub fn subst_mir_and_normalize_erasing_regions<T>( + pub fn instantiate_mir_and_normalize_erasing_regions<T>( &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -603,14 +603,14 @@ impl<'tcx> Instance<'tcx> { T: TypeFoldable<TyCtxt<'tcx>> + Clone, { if let Some(args) = self.args_for_mir_body() { - tcx.subst_and_normalize_erasing_regions(args, param_env, v) + tcx.instantiate_and_normalize_erasing_regions(args, param_env, v) } else { tcx.normalize_erasing_regions(param_env, v.skip_binder()) } } #[inline(always)] - pub fn try_subst_mir_and_normalize_erasing_regions<T>( + pub fn try_instantiate_mir_and_normalize_erasing_regions<T>( &self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -620,7 +620,7 @@ impl<'tcx> Instance<'tcx> { T: TypeFoldable<TyCtxt<'tcx>> + Clone, { if let Some(args) = self.args_for_mir_body() { - tcx.try_subst_and_normalize_erasing_regions(args, param_env, v) + tcx.try_instantiate_and_normalize_erasing_regions(args, param_env, v) } else { tcx.try_normalize_erasing_regions(param_env, v.skip_binder()) } diff --git a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs index 2415d50b278..fd125af2074 100644 --- a/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs +++ b/compiler/rustc_middle/src/ty/normalize_erasing_regions.rs @@ -134,8 +134,9 @@ impl<'tcx> TyCtxt<'tcx> { /// in-scope substitutions and then normalizing any associated /// types. /// Panics if normalization fails. In case normalization might fail - /// use `try_subst_and_normalize_erasing_regions` instead. - pub fn subst_and_normalize_erasing_regions<T>( + /// use `try_instantiate_and_normalize_erasing_regions` instead. + #[instrument(level = "debug", skip(self))] + pub fn instantiate_and_normalize_erasing_regions<T>( self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -144,22 +145,16 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>>, { - debug!( - "subst_and_normalize_erasing_regions(\ - param_args={:?}, \ - value={:?}, \ - param_env={:?})", - param_args, value, param_env, - ); let substituted = value.instantiate(self, param_args); self.normalize_erasing_regions(param_env, substituted) } /// Monomorphizes a type from the AST by first applying the /// in-scope substitutions and then trying to normalize any associated - /// types. Contrary to `subst_and_normalize_erasing_regions` this does + /// types. Contrary to `instantiate_and_normalize_erasing_regions` this does /// not assume that normalization succeeds. - pub fn try_subst_and_normalize_erasing_regions<T>( + #[instrument(level = "debug", skip(self))] + pub fn try_instantiate_and_normalize_erasing_regions<T>( self, param_args: GenericArgsRef<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -168,13 +163,6 @@ impl<'tcx> TyCtxt<'tcx> { where T: TypeFoldable<TyCtxt<'tcx>>, { - debug!( - "subst_and_normalize_erasing_regions(\ - param_args={:?}, \ - value={:?}, \ - param_env={:?})", - param_args, value, param_env, - ); let substituted = value.instantiate(self, param_args); self.try_normalize_erasing_regions(param_env, substituted) } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 99dc0b2607e..2d7350387ca 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -360,7 +360,7 @@ pub trait PrettyPrinter<'tcx>: self.write_str(get_local_name(&self, symbol, parent, parent_key).as_str())?; self.write_str("::")?; } else if let DefKind::Struct | DefKind::Union | DefKind::Enum | DefKind::Trait - | DefKind::TyAlias { .. } | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind + | DefKind::TyAlias | DefKind::Fn | DefKind::Const | DefKind::Static(_) = kind { } else { // If not covered above, like for example items out of `impl` blocks, fallback. @@ -766,7 +766,7 @@ pub trait PrettyPrinter<'tcx>: let parent = self.tcx().parent(def_id); match self.tcx().def_kind(parent) { - DefKind::TyAlias { .. } | DefKind::AssocTy => { + DefKind::TyAlias | DefKind::AssocTy => { // NOTE: I know we should check for NO_QUERIES here, but it's alright. // `type_of` on a type alias or assoc type should never cause a cycle. if let ty::Alias(ty::Opaque, ty::AliasTy { def_id: d, .. }) = @@ -2998,7 +2998,7 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N match child.res { def::Res::Def(DefKind::AssocTy, _) => {} - def::Res::Def(DefKind::TyAlias { .. }, _) => {} + def::Res::Def(DefKind::TyAlias, _) => {} def::Res::Def(defkind, def_id) => { if let Some(ns) = defkind.ns() { collect_fn(&child.ident, ns, def_id); diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index c823c4c2b57..1e57392e0e7 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1223,7 +1223,7 @@ impl<'tcx> AliasTy<'tcx> { DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent, DefKind::AssocTy => ty::Projection, DefKind::OpaqueTy => ty::Opaque, - DefKind::TyAlias { .. } => ty::Weak, + DefKind::TyAlias => ty::Weak, kind => bug!("unexpected DefKind in AliasTy: {kind:?}"), } } @@ -1959,7 +1959,7 @@ impl<'tcx> Ty<'tcx> { (kind, tcx.def_kind(alias_ty.def_id)), (ty::Opaque, DefKind::OpaqueTy) | (ty::Projection | ty::Inherent, DefKind::AssocTy) - | (ty::Weak, DefKind::TyAlias { .. }) + | (ty::Weak, DefKind::TyAlias) ); Ty::new(tcx, Alias(kind, alias_ty)) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 0dda7cd83be..31b52677b27 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -156,7 +156,7 @@ impl<'tcx> TyCtxt<'tcx> { | DefKind::Enum | DefKind::Trait | DefKind::OpaqueTy - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy diff --git a/compiler/rustc_middle/src/values.rs b/compiler/rustc_middle/src/values.rs index dec06363380..578d8e7a975 100644 --- a/compiler/rustc_middle/src/values.rs +++ b/compiler/rustc_middle/src/values.rs @@ -217,7 +217,7 @@ fn find_item_ty_spans( match ty.kind { hir::TyKind::Path(hir::QPath::Resolved(_, path)) => { if let Res::Def(kind, def_id) = path.res - && !matches!(kind, DefKind::TyAlias { .. }) { + && !matches!(kind, DefKind::TyAlias) { let check_params = def_id.as_local().map_or(true, |def_id| { if def_id == needle { spans.push(ty.span); diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl index 938f3edd31b..ce021923f64 100644 --- a/compiler/rustc_mir_build/messages.ftl +++ b/compiler/rustc_mir_build/messages.ftl @@ -229,6 +229,9 @@ mir_build_non_exhaustive_patterns_type_not_empty = non-exhaustive patterns: type .suggestion = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown .help = ensure that all possible cases are being handled by adding a match arm with a wildcard pattern +mir_build_non_partial_eq_match = + to use a constant of type `{$non_peq_ty}` in a pattern, the type must implement `PartialEq` + mir_build_nontrivial_structural_match = to use a constant of type `{$non_sm_ty}` in a pattern, the constant's initializer must be trivial or `{$non_sm_ty}` must be annotated with `#[derive(PartialEq, Eq)]` diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index 3ff3387a781..bee5ac550dd 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -749,6 +749,12 @@ pub struct NontrivialStructuralMatch<'tcx> { } #[derive(LintDiagnostic)] +#[diag(mir_build_non_partial_eq_match)] +pub struct NonPartialEqMatch<'tcx> { + pub non_peq_ty: Ty<'tcx>, +} + +#[derive(LintDiagnostic)] #[diag(mir_build_overlapping_range_endpoints)] #[note] pub struct OverlappingRangeEndpoints<'tcx> { diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 00d9fe72cfc..ae442466029 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -16,14 +16,16 @@ use std::cell::Cell; use super::PatCtxt; use crate::errors::{ - FloatPattern, IndirectStructuralMatch, InvalidPattern, NontrivialStructuralMatch, - PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern, + FloatPattern, IndirectStructuralMatch, InvalidPattern, NonPartialEqMatch, + NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern, }; impl<'a, 'tcx> PatCtxt<'a, 'tcx> { /// Converts an evaluated constant to a pattern (if possible). /// This means aggregate values (like structs and enums) are converted /// to a pattern that matches the value (as if you'd compared via structural equality). + /// + /// `cv` must be a valtree or a `mir::ConstValue`. #[instrument(level = "debug", skip(self), ret)] pub(super) fn const_to_pat( &self, @@ -64,12 +66,10 @@ struct ConstToPat<'tcx> { } /// This error type signals that we encountered a non-struct-eq situation. -/// We bubble this up in order to get back to the reference destructuring and make that emit -/// a const pattern instead of a deref pattern. This allows us to simply call `PartialEq::eq` -/// on such patterns (since that function takes a reference) and not have to jump through any -/// hoops to get a reference to the value. +/// We will fall back to calling `PartialEq::eq` on such patterns, +/// and exhaustiveness checking will consider them as matching nothing. #[derive(Debug)] -struct FallbackToConstRef; +struct FallbackToOpaqueConst; impl<'tcx> ConstToPat<'tcx> { fn new( @@ -136,7 +136,7 @@ impl<'tcx> ConstToPat<'tcx> { } ty::ConstKind::Value(valtree) => self .recur(valtree, cv.ty(), mir_structural_match_violation.unwrap_or(false)) - .unwrap_or_else(|_| { + .unwrap_or_else(|_: FallbackToOpaqueConst| { Box::new(Pat { span: self.span, ty: cv.ty(), @@ -155,8 +155,9 @@ impl<'tcx> ConstToPat<'tcx> { }; if !self.saw_const_match_error.get() { - // If we were able to successfully convert the const to some pat, - // double-check that all types in the const implement `Structural`. + // If we were able to successfully convert the const to some pat (possibly with some + // lints, but no errors), double-check that all types in the const implement + // `Structural` and `PartialEq`. let structural = traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty()); @@ -178,7 +179,7 @@ impl<'tcx> ConstToPat<'tcx> { } if let Some(non_sm_ty) = structural { - if !self.type_may_have_partial_eq_impl(cv.ty()) { + if !self.type_has_partial_eq_impl(cv.ty()) { if let ty::Adt(def, ..) = non_sm_ty.kind() { if def.is_union() { let err = UnionPattern { span: self.span }; @@ -192,8 +193,10 @@ impl<'tcx> ConstToPat<'tcx> { } else { let err = InvalidPattern { span: self.span, non_sm_ty }; self.tcx().sess.emit_err(err); - return Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Wild }); } + // All branches above emitted an error. Don't print any more lints. + // The pattern we return is irrelevant since we errored. + return Box::new(Pat { span: self.span, ty: cv.ty(), kind: PatKind::Wild }); } else if !self.saw_const_match_lint.get() { if let Some(mir_structural_match_violation) = mir_structural_match_violation { match non_sm_ty.kind() { @@ -238,13 +241,24 @@ impl<'tcx> ConstToPat<'tcx> { _ => {} } } + + // Always check for `PartialEq`, even if we emitted other lints. (But not if there were + // any errors.) This ensures it shows up in cargo's future-compat reports as well. + if !self.type_has_partial_eq_impl(cv.ty()) { + self.tcx().emit_spanned_lint( + lint::builtin::CONST_PATTERNS_WITHOUT_PARTIAL_EQ, + self.id, + self.span, + NonPartialEqMatch { non_peq_ty: cv.ty() }, + ); + } } inlined_const_as_pat } #[instrument(level = "trace", skip(self), ret)] - fn type_may_have_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool { + fn type_has_partial_eq_impl(&self, ty: Ty<'tcx>) -> bool { // double-check there even *is* a semantic `PartialEq` to dispatch to. // // (If there isn't, then we can safely issue a hard @@ -259,14 +273,19 @@ impl<'tcx> ConstToPat<'tcx> { ty::TraitRef::new(self.tcx(), partial_eq_trait_id, [ty, ty]), ); - // FIXME: should this call a `predicate_must_hold` variant instead? - self.infcx.predicate_may_hold(&partial_eq_obligation) + // This *could* accept a type that isn't actually `PartialEq`, because region bounds get + // ignored. However that should be pretty much impossible since consts that do not depend on + // generics can only mention the `'static` lifetime, and how would one have a type that's + // `PartialEq` for some lifetime but *not* for `'static`? If this ever becomes a problem + // we'll need to leave some sort of trace of this requirement in the MIR so that borrowck + // can ensure that the type really implements `PartialEq`. + self.infcx.predicate_must_hold_modulo_regions(&partial_eq_obligation) } fn field_pats( &self, vals: impl Iterator<Item = (ValTree<'tcx>, Ty<'tcx>)>, - ) -> Result<Vec<FieldPat<'tcx>>, FallbackToConstRef> { + ) -> Result<Vec<FieldPat<'tcx>>, FallbackToOpaqueConst> { vals.enumerate() .map(|(idx, (val, ty))| { let field = FieldIdx::new(idx); @@ -284,7 +303,7 @@ impl<'tcx> ConstToPat<'tcx> { cv: ValTree<'tcx>, ty: Ty<'tcx>, mir_structural_match_violation: bool, - ) -> Result<Box<Pat<'tcx>>, FallbackToConstRef> { + ) -> Result<Box<Pat<'tcx>>, FallbackToOpaqueConst> { let id = self.id; let span = self.span; let tcx = self.tcx(); @@ -299,7 +318,7 @@ impl<'tcx> ConstToPat<'tcx> { span, FloatPattern, ); - return Err(FallbackToConstRef); + return Err(FallbackToOpaqueConst); } // If the type is not structurally comparable, just emit the constant directly, // causing the pattern match code to treat it opaquely. @@ -323,11 +342,12 @@ impl<'tcx> ConstToPat<'tcx> { // Since we are behind a reference, we can just bubble the error up so we get a // constant at reference type, making it easy to let the fallback call // `PartialEq::eq` on it. - return Err(FallbackToConstRef); + return Err(FallbackToOpaqueConst); } ty::FnDef(..) => { self.saw_const_match_error.set(true); tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty }); + // We errored, so the pattern we generate is irrelevant. PatKind::Wild } ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => { @@ -335,6 +355,7 @@ impl<'tcx> ConstToPat<'tcx> { self.saw_const_match_error.set(true); let err = TypeNotStructural { span, non_sm_ty: ty }; tcx.sess.emit_err(err); + // We errored, so the pattern we generate is irrelevant. PatKind::Wild } ty::Adt(adt_def, args) if adt_def.is_enum() => { @@ -404,13 +425,15 @@ impl<'tcx> ConstToPat<'tcx> { IndirectStructuralMatch { non_sm_ty: *pointee_ty }, ); } - return Err(FallbackToConstRef); + return Err(FallbackToOpaqueConst); } else { if !self.saw_const_match_error.get() { self.saw_const_match_error.set(true); let err = TypeNotStructural { span, non_sm_ty: *pointee_ty }; tcx.sess.emit_err(err); } + tcx.sess.delay_span_bug(span, "`saw_const_match_error` set but no error?"); + // We errored, so the pattern we generate is irrelevant. PatKind::Wild } } @@ -423,6 +446,7 @@ impl<'tcx> ConstToPat<'tcx> { tcx.sess.emit_err(err); // FIXME: introduce PatKind::Error to silence follow up diagnostics due to unreachable patterns. + // We errored, so the pattern we generate is irrelevant. PatKind::Wild } else { let old = self.behind_reference.replace(true); @@ -453,6 +477,7 @@ impl<'tcx> ConstToPat<'tcx> { self.saw_const_match_error.set(true); let err = InvalidPattern { span, non_sm_ty: ty }; tcx.sess.emit_err(err); + // We errored, so the pattern we generate is irrelevant. PatKind::Wild } }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index f1f75c26717..fe47a1cd78c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -439,7 +439,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { DefKind::Struct | DefKind::Ctor(CtorOf::Struct, ..) | DefKind::Union - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::AssocTy, _, ) diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs new file mode 100644 index 00000000000..449bade3322 --- /dev/null +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -0,0 +1,538 @@ +//! Global value numbering. +//! +//! MIR may contain repeated and/or redundant computations. The objective of this pass is to detect +//! such redundancies and re-use the already-computed result when possible. +//! +//! In a first pass, we compute a symbolic representation of values that are assigned to SSA +//! locals. This symbolic representation is defined by the `Value` enum. Each produced instance of +//! `Value` is interned as a `VnIndex`, which allows us to cheaply compute identical values. +//! +//! From those assignments, we construct a mapping `VnIndex -> Vec<(Local, Location)>` of available +//! values, the locals in which they are stored, and a the assignment location. +//! +//! In a second pass, we traverse all (non SSA) assignments `x = rvalue` and operands. For each +//! one, we compute the `VnIndex` of the rvalue. If this `VnIndex` is associated to a constant, we +//! replace the rvalue/operand by that constant. Otherwise, if there is an SSA local `y` +//! associated to this `VnIndex`, and if its definition location strictly dominates the assignment +//! to `x`, we replace the assignment by `x = y`. +//! +//! By opportunity, this pass simplifies some `Rvalue`s based on the accumulated knowledge. +//! +//! # Operational semantic +//! +//! Operationally, this pass attempts to prove bitwise equality between locals. Given this MIR: +//! ```ignore (MIR) +//! _a = some value // has VnIndex i +//! // some MIR +//! _b = some other value // also has VnIndex i +//! ``` +//! +//! We consider it to be replacable by: +//! ```ignore (MIR) +//! _a = some value // has VnIndex i +//! // some MIR +//! _c = some other value // also has VnIndex i +//! assume(_a bitwise equal to _c) // follows from having the same VnIndex +//! _b = _a // follows from the `assume` +//! ``` +//! +//! Which is simplifiable to: +//! ```ignore (MIR) +//! _a = some value // has VnIndex i +//! // some MIR +//! _b = _a +//! ``` +//! +//! # Handling of references +//! +//! We handle references by assigning a different "provenance" index to each Ref/AddressOf rvalue. +//! This ensure that we do not spuriously merge borrows that should not be merged. Meanwhile, we +//! consider all the derefs of an immutable reference to a freeze type to give the same value: +//! ```ignore (MIR) +//! _a = *_b // _b is &Freeze +//! _c = *_b // replaced by _c = _a +//! ``` + +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; +use rustc_data_structures::graph::dominators::Dominators; +use rustc_index::bit_set::BitSet; +use rustc_index::IndexVec; +use rustc_macros::newtype_index; +use rustc_middle::mir::visit::*; +use rustc_middle::mir::*; +use rustc_middle::ty::{self, Ty, TyCtxt}; +use rustc_target::abi::{VariantIdx, FIRST_VARIANT}; + +use crate::ssa::SsaLocals; +use crate::MirPass; + +pub struct GVN; + +impl<'tcx> MirPass<'tcx> for GVN { + fn is_enabled(&self, sess: &rustc_session::Session) -> bool { + sess.mir_opt_level() >= 4 + } + + #[instrument(level = "trace", skip(self, tcx, body))] + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + debug!(def_id = ?body.source.def_id()); + propagate_ssa(tcx, body); + } +} + +fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); + let ssa = SsaLocals::new(body); + // Clone dominators as we need them while mutating the body. + let dominators = body.basic_blocks.dominators().clone(); + + let mut state = VnState::new(tcx, param_env, &ssa, &dominators, &body.local_decls); + for arg in body.args_iter() { + if ssa.is_ssa(arg) { + let value = state.new_opaque().unwrap(); + state.assign(arg, value); + } + } + + ssa.for_each_assignment_mut(&mut body.basic_blocks, |local, rvalue, location| { + let value = state.simplify_rvalue(rvalue, location).or_else(|| state.new_opaque()).unwrap(); + // FIXME(#112651) `rvalue` may have a subtype to `local`. We can only mark `local` as + // reusable if we have an exact type match. + if state.local_decls[local].ty == rvalue.ty(state.local_decls, tcx) { + state.assign(local, value); + } + }); + + // Stop creating opaques during replacement as it is useless. + state.next_opaque = None; + + let reverse_postorder = body.basic_blocks.reverse_postorder().to_vec(); + for bb in reverse_postorder { + let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb]; + state.visit_basic_block_data(bb, data); + } + let any_replacement = state.any_replacement; + + // For each local that is reused (`y` above), we remove its storage statements do avoid any + // difficulty. Those locals are SSA, so should be easy to optimize by LLVM without storage + // statements. + StorageRemover { tcx, reused_locals: state.reused_locals }.visit_body_preserves_cfg(body); + + if any_replacement { + crate::simplify::remove_unused_definitions(body); + } +} + +newtype_index! { + struct VnIndex {} +} + +#[derive(Debug, PartialEq, Eq, Hash)] +enum Value<'tcx> { + // Root values. + /// Used to represent values we know nothing about. + /// The `usize` is a counter incremented by `new_opaque`. + Opaque(usize), + /// Evaluated or unevaluated constant value. + Constant(Const<'tcx>), + /// An aggregate value, either tuple/closure/struct/enum. + /// This does not contain unions, as we cannot reason with the value. + Aggregate(Ty<'tcx>, VariantIdx, Vec<VnIndex>), + /// This corresponds to a `[value; count]` expression. + Repeat(VnIndex, ty::Const<'tcx>), + /// The address of a place. + Address { + place: Place<'tcx>, + /// Give each borrow and pointer a different provenance, so we don't merge them. + provenance: usize, + }, + + // Extractions. + /// This is the *value* obtained by projecting another value. + Projection(VnIndex, ProjectionElem<VnIndex, Ty<'tcx>>), + /// Discriminant of the given value. + Discriminant(VnIndex), + /// Length of an array or slice. + Len(VnIndex), + + // Operations. + NullaryOp(NullOp<'tcx>, Ty<'tcx>), + UnaryOp(UnOp, VnIndex), + BinaryOp(BinOp, VnIndex, VnIndex), + CheckedBinaryOp(BinOp, VnIndex, VnIndex), + Cast { + kind: CastKind, + value: VnIndex, + from: Ty<'tcx>, + to: Ty<'tcx>, + }, +} + +struct VnState<'body, 'tcx> { + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + local_decls: &'body LocalDecls<'tcx>, + /// Value stored in each local. + locals: IndexVec<Local, Option<VnIndex>>, + /// First local to be assigned that value. + rev_locals: FxHashMap<VnIndex, Vec<Local>>, + values: FxIndexSet<Value<'tcx>>, + /// Counter to generate different values. + /// This is an option to stop creating opaques during replacement. + next_opaque: Option<usize>, + ssa: &'body SsaLocals, + dominators: &'body Dominators<BasicBlock>, + reused_locals: BitSet<Local>, + any_replacement: bool, +} + +impl<'body, 'tcx> VnState<'body, 'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + param_env: ty::ParamEnv<'tcx>, + ssa: &'body SsaLocals, + dominators: &'body Dominators<BasicBlock>, + local_decls: &'body LocalDecls<'tcx>, + ) -> Self { + VnState { + tcx, + param_env, + local_decls, + locals: IndexVec::from_elem(None, local_decls), + rev_locals: FxHashMap::default(), + values: FxIndexSet::default(), + next_opaque: Some(0), + ssa, + dominators, + reused_locals: BitSet::new_empty(local_decls.len()), + any_replacement: false, + } + } + + #[instrument(level = "trace", skip(self), ret)] + fn insert(&mut self, value: Value<'tcx>) -> VnIndex { + let (index, _) = self.values.insert_full(value); + VnIndex::from_usize(index) + } + + /// Create a new `Value` for which we have no information at all, except that it is distinct + /// from all the others. + #[instrument(level = "trace", skip(self), ret)] + fn new_opaque(&mut self) -> Option<VnIndex> { + let next_opaque = self.next_opaque.as_mut()?; + let value = Value::Opaque(*next_opaque); + *next_opaque += 1; + Some(self.insert(value)) + } + + /// Create a new `Value::Address` distinct from all the others. + #[instrument(level = "trace", skip(self), ret)] + fn new_pointer(&mut self, place: Place<'tcx>) -> Option<VnIndex> { + let next_opaque = self.next_opaque.as_mut()?; + let value = Value::Address { place, provenance: *next_opaque }; + *next_opaque += 1; + Some(self.insert(value)) + } + + fn get(&self, index: VnIndex) -> &Value<'tcx> { + self.values.get_index(index.as_usize()).unwrap() + } + + /// Record that `local` is assigned `value`. `local` must be SSA. + #[instrument(level = "trace", skip(self))] + fn assign(&mut self, local: Local, value: VnIndex) { + self.locals[local] = Some(value); + + // Only register the value if its type is `Sized`, as we will emit copies of it. + let is_sized = !self.tcx.features().unsized_locals + || self.local_decls[local].ty.is_sized(self.tcx, self.param_env); + if is_sized { + self.rev_locals.entry(value).or_default().push(local); + } + } + + /// Represent the *value* which would be read from `place`, and point `place` to a preexisting + /// place with the same value (if that already exists). + #[instrument(level = "trace", skip(self), ret)] + fn simplify_place_value( + &mut self, + place: &mut Place<'tcx>, + location: Location, + ) -> Option<VnIndex> { + // Invariant: `place` and `place_ref` point to the same value, even if they point to + // different memory locations. + let mut place_ref = place.as_ref(); + + // Invariant: `value` holds the value up-to the `index`th projection excluded. + let mut value = self.locals[place.local]?; + for (index, proj) in place.projection.iter().enumerate() { + if let Some(local) = self.try_as_local(value, location) { + // Both `local` and `Place { local: place.local, projection: projection[..index] }` + // hold the same value. Therefore, following place holds the value in the original + // `place`. + place_ref = PlaceRef { local, projection: &place.projection[index..] }; + } + + let proj = match proj { + ProjectionElem::Deref => { + let ty = Place::ty_from( + place.local, + &place.projection[..index], + self.local_decls, + self.tcx, + ) + .ty; + if let Some(Mutability::Not) = ty.ref_mutability() + && let Some(pointee_ty) = ty.builtin_deref(true) + && pointee_ty.ty.is_freeze(self.tcx, self.param_env) + { + // An immutable borrow `_x` always points to the same value for the + // lifetime of the borrow, so we can merge all instances of `*_x`. + ProjectionElem::Deref + } else { + return None; + } + } + ProjectionElem::Field(f, ty) => ProjectionElem::Field(f, ty), + ProjectionElem::Index(idx) => { + let idx = self.locals[idx]?; + ProjectionElem::Index(idx) + } + ProjectionElem::ConstantIndex { offset, min_length, from_end } => { + ProjectionElem::ConstantIndex { offset, min_length, from_end } + } + ProjectionElem::Subslice { from, to, from_end } => { + ProjectionElem::Subslice { from, to, from_end } + } + ProjectionElem::Downcast(name, index) => ProjectionElem::Downcast(name, index), + ProjectionElem::OpaqueCast(ty) => ProjectionElem::OpaqueCast(ty), + }; + value = self.insert(Value::Projection(value, proj)); + } + + if let Some(local) = self.try_as_local(value, location) + && local != place.local // in case we had no projection to begin with. + { + *place = local.into(); + self.reused_locals.insert(local); + self.any_replacement = true; + } else if place_ref.local != place.local + || place_ref.projection.len() < place.projection.len() + { + // By the invariant on `place_ref`. + *place = place_ref.project_deeper(&[], self.tcx); + self.reused_locals.insert(place_ref.local); + self.any_replacement = true; + } + + Some(value) + } + + #[instrument(level = "trace", skip(self), ret)] + fn simplify_operand( + &mut self, + operand: &mut Operand<'tcx>, + location: Location, + ) -> Option<VnIndex> { + match *operand { + Operand::Constant(ref constant) => Some(self.insert(Value::Constant(constant.const_))), + Operand::Copy(ref mut place) | Operand::Move(ref mut place) => { + let value = self.simplify_place_value(place, location)?; + if let Some(const_) = self.try_as_constant(value) { + *operand = Operand::Constant(Box::new(const_)); + self.any_replacement = true; + } + Some(value) + } + } + } + + #[instrument(level = "trace", skip(self), ret)] + fn simplify_rvalue( + &mut self, + rvalue: &mut Rvalue<'tcx>, + location: Location, + ) -> Option<VnIndex> { + let value = match *rvalue { + // Forward values. + Rvalue::Use(ref mut operand) => return self.simplify_operand(operand, location), + Rvalue::CopyForDeref(place) => { + let mut operand = Operand::Copy(place); + let val = self.simplify_operand(&mut operand, location); + *rvalue = Rvalue::Use(operand); + return val; + } + + // Roots. + Rvalue::Repeat(ref mut op, amount) => { + let op = self.simplify_operand(op, location)?; + Value::Repeat(op, amount) + } + Rvalue::NullaryOp(op, ty) => Value::NullaryOp(op, ty), + Rvalue::Aggregate(box ref kind, ref mut fields) => { + let variant_index = match *kind { + AggregateKind::Array(..) + | AggregateKind::Tuple + | AggregateKind::Closure(..) + | AggregateKind::Generator(..) => FIRST_VARIANT, + AggregateKind::Adt(_, variant_index, _, _, None) => variant_index, + // Do not track unions. + AggregateKind::Adt(_, _, _, _, Some(_)) => return None, + }; + let fields: Option<Vec<_>> = fields + .iter_mut() + .map(|op| self.simplify_operand(op, location).or_else(|| self.new_opaque())) + .collect(); + let ty = rvalue.ty(self.local_decls, self.tcx); + Value::Aggregate(ty, variant_index, fields?) + } + Rvalue::Ref(.., place) | Rvalue::AddressOf(_, place) => return self.new_pointer(place), + + // Operations. + Rvalue::Len(ref mut place) => { + let place = self.simplify_place_value(place, location)?; + Value::Len(place) + } + Rvalue::Cast(kind, ref mut value, to) => { + let from = value.ty(self.local_decls, self.tcx); + let value = self.simplify_operand(value, location)?; + Value::Cast { kind, value, from, to } + } + Rvalue::BinaryOp(op, box (ref mut lhs, ref mut rhs)) => { + let lhs = self.simplify_operand(lhs, location); + let rhs = self.simplify_operand(rhs, location); + Value::BinaryOp(op, lhs?, rhs?) + } + Rvalue::CheckedBinaryOp(op, box (ref mut lhs, ref mut rhs)) => { + let lhs = self.simplify_operand(lhs, location); + let rhs = self.simplify_operand(rhs, location); + Value::CheckedBinaryOp(op, lhs?, rhs?) + } + Rvalue::UnaryOp(op, ref mut arg) => { + let arg = self.simplify_operand(arg, location)?; + Value::UnaryOp(op, arg) + } + Rvalue::Discriminant(ref mut place) => { + let place = self.simplify_place_value(place, location)?; + Value::Discriminant(place) + } + + // Unsupported values. + Rvalue::ThreadLocalRef(..) | Rvalue::ShallowInitBox(..) => return None, + }; + debug!(?value); + Some(self.insert(value)) + } +} + +impl<'tcx> VnState<'_, 'tcx> { + /// If `index` is a `Value::Constant`, return the `Constant` to be put in the MIR. + fn try_as_constant(&mut self, index: VnIndex) -> Option<ConstOperand<'tcx>> { + if let Value::Constant(const_) = *self.get(index) { + // Some constants may contain pointers. We need to preserve the provenance of these + // pointers, but not all constants guarantee this: + // - valtrees purposefully do not; + // - ConstValue::Slice does not either. + match const_ { + Const::Ty(c) => match c.kind() { + ty::ConstKind::Value(valtree) => match valtree { + // This is just an integer, keep it. + ty::ValTree::Leaf(_) => {} + ty::ValTree::Branch(_) => return None, + }, + ty::ConstKind::Param(..) + | ty::ConstKind::Unevaluated(..) + | ty::ConstKind::Expr(..) => {} + // Should not appear in runtime MIR. + ty::ConstKind::Infer(..) + | ty::ConstKind::Bound(..) + | ty::ConstKind::Placeholder(..) + | ty::ConstKind::Error(..) => bug!(), + }, + Const::Unevaluated(..) => {} + // If the same slice appears twice in the MIR, we cannot guarantee that we will + // give the same `AllocId` to the data. + Const::Val(ConstValue::Slice { .. }, _) => return None, + Const::Val( + ConstValue::ZeroSized | ConstValue::Scalar(_) | ConstValue::Indirect { .. }, + _, + ) => {} + } + Some(ConstOperand { span: rustc_span::DUMMY_SP, user_ty: None, const_ }) + } else { + None + } + } + + /// If there is a local which is assigned `index`, and its assignment strictly dominates `loc`, + /// return it. + fn try_as_local(&mut self, index: VnIndex, loc: Location) -> Option<Local> { + let other = self.rev_locals.get(&index)?; + other + .iter() + .copied() + .find(|&other| self.ssa.assignment_dominates(self.dominators, other, loc)) + } +} + +impl<'tcx> MutVisitor<'tcx> for VnState<'_, 'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_operand(&mut self, operand: &mut Operand<'tcx>, location: Location) { + self.simplify_operand(operand, location); + } + + fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, location: Location) { + self.super_statement(stmt, location); + if let StatementKind::Assign(box (_, ref mut rvalue)) = stmt.kind + // Do not try to simplify a constant, it's already in canonical shape. + && !matches!(rvalue, Rvalue::Use(Operand::Constant(_))) + && let Some(value) = self.simplify_rvalue(rvalue, location) + { + if let Some(const_) = self.try_as_constant(value) { + *rvalue = Rvalue::Use(Operand::Constant(Box::new(const_))); + self.any_replacement = true; + } else if let Some(local) = self.try_as_local(value, location) + && *rvalue != Rvalue::Use(Operand::Move(local.into())) + { + *rvalue = Rvalue::Use(Operand::Copy(local.into())); + self.reused_locals.insert(local); + self.any_replacement = true; + } + } + } +} + +struct StorageRemover<'tcx> { + tcx: TyCtxt<'tcx>, + reused_locals: BitSet<Local>, +} + +impl<'tcx> MutVisitor<'tcx> for StorageRemover<'tcx> { + fn tcx(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn visit_operand(&mut self, operand: &mut Operand<'tcx>, _: Location) { + if let Operand::Move(place) = *operand + && let Some(local) = place.as_local() + && self.reused_locals.contains(local) + { + *operand = Operand::Copy(place); + } + } + + fn visit_statement(&mut self, stmt: &mut Statement<'tcx>, loc: Location) { + match stmt.kind { + // When removing storage statements, we need to remove both (#107511). + StatementKind::StorageLive(l) | StatementKind::StorageDead(l) + if self.reused_locals.contains(l) => + { + stmt.make_nop() + } + _ => self.super_statement(stmt, loc), + } + } +} diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 1d9c89477cb..ebd61f8ad95 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -193,7 +193,7 @@ impl<'tcx> Inliner<'tcx> { return Err("optimization fuel exhausted"); } - let Ok(callee_body) = callsite.callee.try_subst_mir_and_normalize_erasing_regions( + let Ok(callee_body) = callsite.callee.try_instantiate_mir_and_normalize_erasing_regions( self.tcx, self.param_env, ty::EarlyBinder::bind(callee_body.clone()), @@ -481,9 +481,10 @@ impl<'tcx> Inliner<'tcx> { work_list.push(target); // If the place doesn't actually need dropping, treat it like a regular goto. - let ty = callsite - .callee - .subst_mir(self.tcx, ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty)); + let ty = callsite.callee.instantiate_mir( + self.tcx, + ty::EarlyBinder::bind(&place.ty(callee_body, tcx).ty), + ); if ty.needs_drop(tcx, self.param_env) && let UnwindAction::Cleanup(unwind) = unwind { work_list.push(unwind); } @@ -650,7 +651,7 @@ impl<'tcx> Inliner<'tcx> { // Copy only unevaluated constants from the callee_body into the caller_body. // Although we are only pushing `ConstKind::Unevaluated` consts to // `required_consts`, here we may not only have `ConstKind::Unevaluated` - // because we are calling `subst_and_normalize_erasing_regions`. + // because we are calling `instantiate_and_normalize_erasing_regions`. caller_body.required_consts.extend( callee_body.required_consts.iter().copied().filter(|&ct| match ct.const_ { Const::Ty(_) => { @@ -811,9 +812,10 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { match terminator.kind { 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, ty::EarlyBinder::bind(&place.ty(self.callee_body, tcx).ty)); + let ty = self.instance.instantiate_mir( + tcx, + ty::EarlyBinder::bind(&place.ty(self.callee_body, tcx).ty), + ); if ty.needs_drop(tcx, self.param_env) { self.cost += CALL_PENALTY; if let UnwindAction::Cleanup(_) = unwind { @@ -824,7 +826,8 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> { } } TerminatorKind::Call { func: Operand::Constant(ref f), unwind, .. } => { - let fn_ty = self.instance.subst_mir(tcx, ty::EarlyBinder::bind(&f.const_.ty())); + let fn_ty = + self.instance.instantiate_mir(tcx, ty::EarlyBinder::bind(&f.const_.ty())); self.cost += if let ty::FnDef(def_id, _) = *fn_ty.kind() && tcx.is_intrinsic(def_id) { // Don't give intrinsics the extra penalty for calls INSTR_COST diff --git a/compiler/rustc_mir_transform/src/inline/cycle.rs b/compiler/rustc_mir_transform/src/inline/cycle.rs index 822634129fc..d30e0bad813 100644 --- a/compiler/rustc_mir_transform/src/inline/cycle.rs +++ b/compiler/rustc_mir_transform/src/inline/cycle.rs @@ -44,7 +44,7 @@ pub(crate) fn mir_callgraph_reachable<'tcx>( ) -> bool { trace!(%caller); for &(callee, args) in tcx.mir_inliner_callees(caller.def) { - let Ok(args) = caller.try_subst_mir_and_normalize_erasing_regions( + let Ok(args) = caller.try_instantiate_mir_and_normalize_erasing_regions( tcx, param_env, ty::EarlyBinder::bind(args), diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index d7fef093278..9e4bc456d51 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -76,6 +76,7 @@ mod errors; mod ffi_unwind_calls; mod function_item_references; mod generator; +mod gvn; pub mod inline; mod instsimplify; mod large_enums; @@ -549,6 +550,7 @@ fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // latter pass will leverage the created opportunities. &separate_const_switch::SeparateConstSwitch, &const_prop::ConstProp, + &gvn::GVN, &dataflow_const_prop::DataflowConstProp, // // Const-prop runs unconditionally, but doesn't mutate the MIR at mir-opt-level=0. diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 49a940b5779..67941cf4395 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -108,7 +108,7 @@ enum Value<'tcx> { } /// For each local, save the place corresponding to `*local`. -#[instrument(level = "trace", skip(tcx, body))] +#[instrument(level = "trace", skip(tcx, body, ssa))] fn compute_replacement<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index b7a51cfd619..2795cf15702 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -29,6 +29,7 @@ use crate::MirPass; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_index::bit_set::BitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_middle::mir::coverage::*; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; @@ -345,24 +346,22 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let basic_blocks = body.basic_blocks.as_mut(); let source_scopes = &body.source_scopes; - let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); - let mut used_blocks = 0; - for alive_index in reachable.iter() { - let alive_index = alive_index.index(); - replacements[alive_index] = BasicBlock::new(used_blocks); - if alive_index != used_blocks { - // Swap the next alive block data with the current available slot. Since - // alive_index is non-decreasing this is a valid operation. - basic_blocks.raw.swap(alive_index, used_blocks); - } - used_blocks += 1; - } - if tcx.sess.instrument_coverage() { - save_unreachable_coverage(basic_blocks, source_scopes, used_blocks); + save_unreachable_coverage(basic_blocks, source_scopes, &reachable); } - basic_blocks.raw.truncate(used_blocks); + let mut replacements: Vec<_> = (0..num_blocks).map(BasicBlock::new).collect(); + let mut orig_index = 0; + let mut used_index = 0; + basic_blocks.raw.retain(|_| { + let keep = reachable.contains(BasicBlock::new(orig_index)); + if keep { + replacements[orig_index] = BasicBlock::new(used_index); + used_index += 1; + } + orig_index += 1; + keep + }); for block in basic_blocks { for target in block.terminator_mut().successors_mut() { @@ -404,11 +403,12 @@ pub fn remove_dead_blocks<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { fn save_unreachable_coverage( basic_blocks: &mut IndexSlice<BasicBlock, BasicBlockData<'_>>, source_scopes: &IndexSlice<SourceScope, SourceScopeData<'_>>, - first_dead_block: usize, + reachable: &BitSet<BasicBlock>, ) { // Identify instances that still have some live coverage counters left. let mut live = FxHashSet::default(); - for basic_block in &basic_blocks.raw[0..first_dead_block] { + for bb in reachable.iter() { + let basic_block = &basic_blocks[bb]; for statement in &basic_block.statements { let StatementKind::Coverage(coverage) = &statement.kind else { continue }; let CoverageKind::Counter { .. } = coverage.kind else { continue }; @@ -417,7 +417,8 @@ fn save_unreachable_coverage( } } - for block in &mut basic_blocks.raw[..first_dead_block] { + for bb in reachable.iter() { + let block = &mut basic_blocks[bb]; for statement in &mut block.statements { let StatementKind::Coverage(_) = &statement.kind else { continue }; let instance = statement.source_info.scope.inlined_instance(source_scopes); @@ -433,7 +434,11 @@ fn save_unreachable_coverage( // Retain coverage for instances that still have some live counters left. let mut retained_coverage = Vec::new(); - for dead_block in &basic_blocks.raw[first_dead_block..] { + for dead_block in basic_blocks.indices() { + if reachable.contains(dead_block) { + continue; + } + let dead_block = &basic_blocks[dead_block]; for statement in &dead_block.statements { let StatementKind::Coverage(coverage) = &statement.kind else { continue }; let Some(code_region) = &coverage.code_region else { continue }; diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs index 04bc461c815..3a675752fba 100644 --- a/compiler/rustc_mir_transform/src/ssa.rs +++ b/compiler/rustc_mir_transform/src/ssa.rs @@ -13,7 +13,6 @@ use rustc_middle::middle::resolve_bound_vars::Set1; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -#[derive(Debug)] pub struct SsaLocals { /// Assignments to each local. This defines whether the local is SSA. assignments: IndexVec<Local, Set1<LocationExtended>>, @@ -129,6 +128,25 @@ impl SsaLocals { self.direct_uses[local] } + pub fn assignment_dominates( + &self, + dominators: &Dominators<BasicBlock>, + local: Local, + location: Location, + ) -> bool { + match self.assignments[local] { + Set1::One(LocationExtended::Arg) => true, + Set1::One(LocationExtended::Plain(ass)) => { + if ass.block == location.block { + ass.statement_index < location.statement_index + } else { + dominators.dominates(ass.block, location.block) + } + } + _ => false, + } + } + pub fn assignments<'a, 'tcx>( &'a self, body: &'a Body<'tcx>, @@ -146,6 +164,24 @@ impl SsaLocals { }) } + pub fn for_each_assignment_mut<'tcx>( + &self, + basic_blocks: &mut BasicBlocks<'tcx>, + mut f: impl FnMut(Local, &mut Rvalue<'tcx>, Location), + ) { + for &local in &self.assignment_order { + if let Set1::One(LocationExtended::Plain(loc)) = self.assignments[local] { + // `loc` must point to a direct assignment to `local`. + let bbs = basic_blocks.as_mut_preserves_cfg(); + let bb = &mut bbs[loc.block]; + let stmt = &mut bb.statements[loc.statement_index]; + let StatementKind::Assign(box (target, ref mut rvalue)) = stmt.kind else { bug!() }; + assert_eq!(target.as_local(), Some(local)); + f(local, rvalue, loc) + } + } + } + /// Compute the equivalence classes for locals, based on copy statements. /// /// The returned vector maps each local to the one it copies. In the following case: diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index bd1724bf842..0b9311a20ef 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -13,7 +13,11 @@ pub struct UnreachablePropagation; impl MirPass<'_> for UnreachablePropagation { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { // Enable only under -Zmir-opt-level=2 as this can make programs less debuggable. - sess.mir_opt_level() >= 2 + + // FIXME(#116171) Coverage gets confused by MIR passes that can remove all + // coverage statements from an instrumented function. This pass can be + // re-enabled when coverage codegen is robust against that happening. + sess.mir_opt_level() >= 2 && !sess.instrument_coverage() } fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 4afa4e597f7..1a9f0e8352e 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -606,7 +606,7 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> { T: TypeFoldable<TyCtxt<'tcx>>, { debug!("monomorphize: self.instance={:?}", self.instance); - self.instance.subst_mir_and_normalize_erasing_regions( + self.instance.instantiate_mir_and_normalize_erasing_regions( self.tcx, ty::ParamEnv::reveal_all(), ty::EarlyBinder::bind(value), diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index c993e64477b..1d8cbe0e21b 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -647,7 +647,7 @@ fn characteristic_def_id_of_mono_item<'tcx>( // parameters, but the self-type of their impl block do will fail to normalize. if !tcx.sess.opts.unstable_opts.polymorphize || !instance.has_param() { // This is a method within an impl, find out what the self-type is: - let impl_self_ty = tcx.subst_and_normalize_erasing_regions( + let impl_self_ty = tcx.instantiate_and_normalize_erasing_regions( instance.args, ty::ParamEnv::reveal_all(), tcx.type_of(impl_def_id), diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs index 0e85f35fc1b..6c206a6bac8 100644 --- a/compiler/rustc_monomorphize/src/polymorphize.rs +++ b/compiler/rustc_monomorphize/src/polymorphize.rs @@ -143,7 +143,7 @@ fn mark_used_by_default_parameters<'tcx>( | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::AssocTy diff --git a/compiler/rustc_monomorphize/src/util.rs b/compiler/rustc_monomorphize/src/util.rs index a3433d3d13d..e25c5c9f27c 100644 --- a/compiler/rustc_monomorphize/src/util.rs +++ b/compiler/rustc_monomorphize/src/util.rs @@ -26,12 +26,12 @@ pub(crate) fn dump_closure_profile<'tcx>(tcx: TyCtxt<'tcx>, closure_instance: In let ClosureSizeProfileData { before_feature_tys, after_feature_tys } = typeck_results.closure_size_eval[&closure_def_id]; - let before_feature_tys = tcx.subst_and_normalize_erasing_regions( + let before_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, param_env, ty::EarlyBinder::bind(before_feature_tys), ); - let after_feature_tys = tcx.subst_and_normalize_erasing_regions( + let after_feature_tys = tcx.instantiate_and_normalize_erasing_regions( closure_instance.args, param_env, ty::EarlyBinder::bind(after_feature_tys), diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index dc0776c5dad..214c6d70960 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -648,6 +648,10 @@ passes_rustc_lint_opt_ty = `#[rustc_lint_opt_ty]` should be applied to a struct .label = not a struct +passes_rustc_safe_intrinsic = + attribute should be applied to intrinsic functions + .label = not an intrinsic function + passes_rustc_std_internal_symbol = attribute should be applied to functions or statics .label = not a function or static diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index 9e4d960af14..153c39977bb 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -21,7 +21,7 @@ pub fn test_abi(tcx: TyCtxt<'_>) { DefKind::Fn | DefKind::AssocFn => { dump_abi_of_fn_item(tcx, id, attr); } - DefKind::TyAlias { .. } => { + DefKind::TyAlias => { dump_abi_of_fn_type(tcx, id, attr); } _ => { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index afba366a365..9a7564cb213 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -195,6 +195,9 @@ impl CheckAttrVisitor<'_> { | sym::rustc_promotable => self.check_stability_promotable(&attr, span, target), sym::link_ordinal => self.check_link_ordinal(&attr, span, target), sym::rustc_confusables => self.check_confusables(&attr, target), + sym::rustc_safe_intrinsic => { + self.check_rustc_safe_intrinsic(hir_id, attr, span, target) + } _ => true, }; @@ -2042,6 +2045,29 @@ impl CheckAttrVisitor<'_> { } } + fn check_rustc_safe_intrinsic( + &self, + hir_id: HirId, + attr: &Attribute, + span: Span, + target: Target, + ) -> bool { + let hir = self.tcx.hir(); + + if let Target::ForeignFn = target + && let Some(parent) = hir.opt_parent_id(hir_id) + && let hir::Node::Item(Item { + kind: ItemKind::ForeignMod { abi: Abi::RustIntrinsic | Abi::PlatformIntrinsic, .. }, + .. + }) = hir.get(parent) + { + return true; + } + + self.tcx.sess.emit_err(errors::RustcSafeIntrinsic { attr_span: attr.span, span }); + false + } + fn check_rustc_std_internal_symbol( &self, attr: &Attribute, diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index d1c3bcf3839..493daf314ce 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -96,7 +96,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> { fn handle_res(&mut self, res: Res) { match res { - Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias { .. }, def_id) => { + Res::Def(DefKind::Const | DefKind::AssocConst | DefKind::TyAlias, def_id) => { self.check_def_id(def_id); } _ if self.in_pat => {} @@ -923,7 +923,7 @@ impl<'tcx> DeadVisitor<'tcx> { | DefKind::Fn | DefKind::Static(_) | DefKind::Const - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::Enum | DefKind::Union | DefKind::ForeignTy => self.warn_dead_code(def_id, "used"), diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 2ec6a0b9241..bcf5abbfe7d 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -621,6 +621,15 @@ pub struct RustcAllowConstFnUnstable { } #[derive(Diagnostic)] +#[diag(passes_rustc_safe_intrinsic)] +pub struct RustcSafeIntrinsic { + #[primary_span] + pub attr_span: Span, + #[label] + pub span: Span, +} + +#[derive(Diagnostic)] #[diag(passes_rustc_std_internal_symbol)] pub struct RustcStdInternalSymbol { #[primary_span] diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index e3a63f2e004..e195f9ab6da 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -23,7 +23,7 @@ pub fn test_layout(tcx: TyCtxt<'_>) { for id in tcx.hir_crate_items(()).definitions() { for attr in tcx.get_attrs(id, sym::rustc_layout) { match tcx.def_kind(id) { - DefKind::TyAlias { .. } | DefKind::Enum | DefKind::Struct | DefKind::Union => { + DefKind::TyAlias | DefKind::Enum | DefKind::Struct | DefKind::Union => { dump_layout_of(tcx, id, attr); } _ => { diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 2e71ac8d7dc..ab85f680fcf 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -588,7 +588,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { self.update(def_id, macro_ev, Level::Reachable); match def_kind { // No type privacy, so can be directly marked as reachable. - DefKind::Const | DefKind::Static(_) | DefKind::TraitAlias | DefKind::TyAlias { .. } => { + DefKind::Const | DefKind::Static(_) | DefKind::TraitAlias | DefKind::TyAlias => { if vis.is_accessible_from(module, self.tcx) { self.update(def_id, macro_ev, Level::Reachable); } @@ -1637,8 +1637,8 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> { let def_kind = tcx.def_kind(def_id); match def_kind { - DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias { .. } => { - if let DefKind::TyAlias { .. } = def_kind { + DefKind::Const | DefKind::Static(_) | DefKind::Fn | DefKind::TyAlias => { + if let DefKind::TyAlias = def_kind { self.check_unnameable(def_id, effective_vis); } self.check(def_id, item_visibility, effective_vis).generics().predicates().ty(); diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs index 2e9ebde296c..f2c1f84fccc 100644 --- a/compiler/rustc_query_system/src/query/job.rs +++ b/compiler/rustc_query_system/src/query/job.rs @@ -580,9 +580,7 @@ pub(crate) fn report_cycle<'a>( }); } - let alias = if stack - .iter() - .all(|entry| matches!(entry.query.def_kind, Some(DefKind::TyAlias { .. }))) + let alias = if stack.iter().all(|entry| matches!(entry.query.def_kind, Some(DefKind::TyAlias))) { Some(crate::error::Alias::Ty) } else if stack.iter().all(|entry| entry.query.def_kind == Some(DefKind::TraitAlias)) { diff --git a/compiler/rustc_query_system/src/query/plumbing.rs b/compiler/rustc_query_system/src/query/plumbing.rs index f93edffca79..ae8414ebba6 100644 --- a/compiler/rustc_query_system/src/query/plumbing.rs +++ b/compiler/rustc_query_system/src/query/plumbing.rs @@ -18,7 +18,7 @@ use rustc_data_structures::sharded::Sharded; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::sync::Lock; #[cfg(parallel_compiler)] -use rustc_data_structures::{cold_path, sync}; +use rustc_data_structures::{outline, sync}; use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed, FatalError}; use rustc_span::{Span, DUMMY_SP}; use std::cell::Cell; @@ -265,7 +265,7 @@ where match result { Ok(()) => { let Some((v, index)) = query.query_cache(qcx).lookup(&key) else { - cold_path(|| { + outline(|| { // We didn't find the query result in the query cache. Check if it was // poisoned due to a panic instead. let lock = query.query_state(qcx).active.get_shard_by_value(&key).lock(); diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 2c36c83ae72..a18109574fe 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -698,10 +698,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // These items live in the type namespace. ItemKind::TyAlias(..) => { - let res = Res::Def( - DefKind::TyAlias { lazy: self.r.tcx.features().lazy_type_alias }, - def_id, - ); + let res = Res::Def(DefKind::TyAlias, def_id); self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion)); } @@ -950,7 +947,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { DefKind::Struct | DefKind::Union | DefKind::Variant - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::OpaqueTy | DefKind::TraitAlias diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 01f9f060594..c3c43346ed8 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -474,7 +474,7 @@ impl<'a> PathSource<'a> { | DefKind::Enum | DefKind::Trait | DefKind::TraitAlias - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::AssocTy | DefKind::TyParam | DefKind::OpaqueTy @@ -513,7 +513,7 @@ impl<'a> PathSource<'a> { DefKind::Struct | DefKind::Union | DefKind::Variant - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::AssocTy, _, ) | Res::SelfTyParam { .. } @@ -1766,7 +1766,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { Res::Def(DefKind::Struct, def_id) | Res::Def(DefKind::Union, def_id) | Res::Def(DefKind::Enum, def_id) - | Res::Def(DefKind::TyAlias { .. }, def_id) + | Res::Def(DefKind::TyAlias, def_id) | Res::Def(DefKind::Trait, def_id) if i + 1 == proj_start => { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 06a08f29a1e..64440a6c04e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1429,7 +1429,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { (Res::Def(DefKind::Macro(MacroKind::Bang), _), _) => { err.span_label(span, fallback_label.to_string()); } - (Res::Def(DefKind::TyAlias { .. }, def_id), PathSource::Trait(_)) => { + (Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => { err.span_label(span, "type aliases cannot be used as traits"); if self.r.tcx.sess.is_nightly_build() { let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \ @@ -1598,7 +1598,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> { err.span_label(span, fallback_label.to_string()); err.note("can't use `Self` as a constructor, you must use the implemented struct"); } - (Res::Def(DefKind::TyAlias { .. } | DefKind::AssocTy, _), _) if ns == ValueNS => { + (Res::Def(DefKind::TyAlias | DefKind::AssocTy, _), _) if ns == ValueNS => { err.note("can't use a type alias as a constructor"); } _ => return false, diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml index 21ec904e43c..4c29f743708 100644 --- a/compiler/rustc_smir/Cargo.toml +++ b/compiler/rustc_smir/Cargo.toml @@ -4,24 +4,14 @@ version = "0.0.0" edition = "2021" [dependencies] -# Use optional dependencies for rustc_* in order to support building this crate separately. -rustc_hir = { path = "../rustc_hir", optional = true } -rustc_middle = { path = "../rustc_middle", optional = true } -rustc_span = { path = "../rustc_span", optional = true } -rustc_target = { path = "../rustc_target", optional = true } -rustc_driver = { path = "../rustc_driver", optional = true } -rustc_interface = { path = "../rustc_interface", optional = true} -rustc_session = {path = "../rustc_session", optional = true} +rustc_hir = { path = "../rustc_hir" } +rustc_middle = { path = "../rustc_middle" } +rustc_span = { path = "../rustc_span" } +rustc_target = { path = "../rustc_target" } +rustc_driver = { path = "../rustc_driver" } +rustc_interface = { path = "../rustc_interface" } +rustc_session = {path = "../rustc_session" } tracing = "0.1" -scoped-tls = "1.0" +stable_mir = {path = "../stable_mir" } [features] -default = [ - "rustc_hir", - "rustc_middle", - "rustc_span", - "rustc_target", - "rustc_driver", - "rustc_interface", - "rustc_session", -] diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs index 8cb533c8d67..b6c36678db5 100644 --- a/compiler/rustc_smir/src/lib.rs +++ b/compiler/rustc_smir/src/lib.rs @@ -10,26 +10,12 @@ html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", test(attr(allow(unused_variables), deny(warnings))) )] -#![cfg_attr(not(feature = "default"), feature(rustc_private))] +#![feature(rustc_private)] #![feature(ptr_metadata)] #![feature(type_alias_impl_trait)] // Used to define opaque types. #![feature(intra_doc_pointers)] -// Declare extern rustc_* crates to enable building this crate separately from the compiler. -#[cfg(not(feature = "default"))] -extern crate rustc_hir; -#[cfg(not(feature = "default"))] -extern crate rustc_middle; -#[cfg(not(feature = "default"))] -extern crate rustc_span; -#[cfg(not(feature = "default"))] -extern crate rustc_target; - 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; - -#[macro_use] -extern crate scoped_tls; diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs index 10ee5af86c6..441aafd1257 100644 --- a/compiler/rustc_smir/src/rustc_internal/mod.rs +++ b/compiler/rustc_smir/src/rustc_internal/mod.rs @@ -3,75 +3,17 @@ //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs //! until stable MIR is complete. -use std::fmt::Debug; use std::ops::{ControlFlow, Index}; use crate::rustc_internal; -use crate::stable_mir::CompilerError; -use crate::{ - rustc_smir::Tables, - stable_mir::{self, with}, -}; +use crate::rustc_smir::Tables; use rustc_driver::{Callbacks, Compilation, RunCompiler}; use rustc_interface::{interface, Queries}; use rustc_middle::mir::interpret::AllocId; use rustc_middle::ty::TyCtxt; pub use rustc_span::def_id::{CrateNum, DefId}; use rustc_span::Span; - -fn with_tables<R>(mut f: impl FnMut(&mut Tables<'_>) -> R) -> R { - let mut ret = None; - with(|tables| tables.rustc_tables(&mut |t| ret = Some(f(t)))); - ret.unwrap() -} - -pub fn item_def_id(item: &stable_mir::CrateItem) -> DefId { - with_tables(|t| t[item.0]) -} - -pub fn crate_item(did: DefId) -> stable_mir::CrateItem { - with_tables(|t| t.crate_item(did)) -} - -pub fn adt_def(did: DefId) -> stable_mir::ty::AdtDef { - with_tables(|t| t.adt_def(did)) -} - -pub fn foreign_def(did: DefId) -> stable_mir::ty::ForeignDef { - with_tables(|t| t.foreign_def(did)) -} - -pub fn fn_def(did: DefId) -> stable_mir::ty::FnDef { - with_tables(|t| t.fn_def(did)) -} - -pub fn closure_def(did: DefId) -> stable_mir::ty::ClosureDef { - with_tables(|t| t.closure_def(did)) -} - -pub fn generator_def(did: DefId) -> stable_mir::ty::GeneratorDef { - with_tables(|t| t.generator_def(did)) -} - -pub fn alias_def(did: DefId) -> stable_mir::ty::AliasDef { - with_tables(|t| t.alias_def(did)) -} - -pub fn param_def(did: DefId) -> stable_mir::ty::ParamDef { - with_tables(|t| t.param_def(did)) -} - -pub fn br_named_def(did: DefId) -> stable_mir::ty::BrNamedDef { - with_tables(|t| t.br_named_def(did)) -} - -pub fn trait_def(did: DefId) -> stable_mir::ty::TraitDef { - with_tables(|t| t.trait_def(did)) -} - -pub fn impl_def(did: DefId) -> stable_mir::ty::ImplDef { - with_tables(|t| t.impl_def(did)) -} +use stable_mir::CompilerError; impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> { type Output = DefId; @@ -82,6 +24,15 @@ impl<'tcx> Index<stable_mir::DefId> for Tables<'tcx> { } } +impl<'tcx> Index<stable_mir::ty::Span> for Tables<'tcx> { + type Output = Span; + + #[inline(always)] + fn index(&self, index: stable_mir::ty::Span) -> &Self::Output { + &self.spans[index.0] + } +} + impl<'tcx> Tables<'tcx> { pub fn crate_item(&mut self, did: DefId) -> stable_mir::CrateItem { stable_mir::CrateItem(self.create_def_id(did)) @@ -178,32 +129,12 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum { } pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) { - crate::stable_mir::run( + stable_mir::run( Tables { tcx, def_ids: vec![], alloc_ids: vec![], spans: vec![], types: vec![] }, f, ); } -/// A type that provides internal information but that can still be used for debug purpose. -#[derive(Clone)] -pub struct Opaque(String); - -impl std::fmt::Display for Opaque { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{}", self.0) - } -} - -impl std::fmt::Debug for Opaque { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - write!(f, "{:?}", self.0) - } -} - -pub(crate) fn opaque<T: Debug>(value: &T) -> Opaque { - Opaque(format!("{value:?}")) -} - pub struct StableMir<B = (), C = ()> where B: Send, diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs index d8766cf8ce2..63a2a145069 100644 --- a/compiler/rustc_smir/src/rustc_smir/alloc.rs +++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs @@ -3,11 +3,9 @@ use rustc_middle::mir::{ ConstValue, }; -use crate::{ - rustc_smir::{Stable, Tables}, - stable_mir::mir::Mutability, - stable_mir::ty::{Allocation, ProvenanceMap}, -}; +use crate::rustc_smir::{Stable, Tables}; +use stable_mir::mir::Mutability; +use stable_mir::ty::{Allocation, ProvenanceMap}; /// Creates new empty `Allocation` from given `Align`. fn new_empty_allocation(align: rustc_target::abi::Align) -> Allocation { diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs index b575445c4d5..5ff17613b4e 100644 --- a/compiler/rustc_smir/src/rustc_smir/mod.rs +++ b/compiler/rustc_smir/src/rustc_smir/mod.rs @@ -7,19 +7,16 @@ //! //! For now, we are developing everything inside `rustc`, thus, we keep this module private. -use crate::rustc_internal::{self, opaque}; -use crate::stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx}; -use crate::stable_mir::ty::{ - FloatTy, GenericParamDef, IntTy, Movability, RigidTy, Span, TyKind, UintTy, -}; -use crate::stable_mir::{self, CompilerError, Context}; +use hir::def::DefKind; use rustc_hir as hir; use rustc_middle::mir; use rustc_middle::mir::interpret::{alloc_range, AllocId}; use rustc_middle::ty::{self, Ty, TyCtxt, Variance}; use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc_span::ErrorGuaranteed; use rustc_target::abi::FieldIdx; +use stable_mir::mir::{CopyNonOverlapping, UserTypeProjection, VariantIdx}; +use stable_mir::ty::{FloatTy, GenericParamDef, IntTy, Movability, RigidTy, Span, TyKind, UintTy}; +use stable_mir::{self, opaque, Context}; use tracing::debug; mod alloc; @@ -44,6 +41,14 @@ impl<'tcx> Context for Tables<'tcx> { self.tcx.def_path_str(self[def_id]) } + fn print_span(&self, span: stable_mir::ty::Span) -> String { + self.tcx.sess.source_map().span_to_diagnostic_string(self[span]) + } + + fn def_kind(&mut self, def_id: stable_mir::DefId) -> stable_mir::DefKind { + self.tcx.def_kind(self[def_id]).stable(self) + } + fn span_of_an_item(&mut self, def_id: stable_mir::DefId) -> Span { self.tcx.def_span(self[def_id]).stable(self) } @@ -104,11 +109,7 @@ impl<'tcx> Context for Tables<'tcx> { } } - fn rustc_tables(&mut self, f: &mut dyn FnMut(&mut Tables<'_>)) { - f(self) - } - - fn ty_kind(&mut self, ty: crate::stable_mir::ty::Ty) -> TyKind { + fn ty_kind(&mut self, ty: stable_mir::ty::Ty) -> TyKind { self.types[ty.0].clone().stable(self) } @@ -276,7 +277,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> { place.stable(tables), ), ThreadLocalRef(def_id) => { - stable_mir::mir::Rvalue::ThreadLocalRef(rustc_internal::crate_item(*def_id)) + stable_mir::mir::Rvalue::ThreadLocalRef(tables.crate_item(*def_id)) } AddressOf(mutability, place) => { stable_mir::mir::Rvalue::AddressOf(mutability.stable(tables), place.stable(tables)) @@ -739,7 +740,7 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { mir::AggregateKind::Tuple => stable_mir::mir::AggregateKind::Tuple, mir::AggregateKind::Adt(def_id, var_idx, generic_arg, user_ty_index, field_idx) => { stable_mir::mir::AggregateKind::Adt( - rustc_internal::adt_def(*def_id), + tables.adt_def(*def_id), var_idx.index(), generic_arg.stable(tables), user_ty_index.map(|idx| idx.index()), @@ -748,13 +749,13 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> { } mir::AggregateKind::Closure(def_id, generic_arg) => { stable_mir::mir::AggregateKind::Closure( - rustc_internal::closure_def(*def_id), + tables.closure_def(*def_id), generic_arg.stable(tables), ) } mir::AggregateKind::Generator(def_id, generic_arg, movability) => { stable_mir::mir::AggregateKind::Generator( - rustc_internal::generator_def(*def_id), + tables.generator_def(*def_id), generic_arg.stable(tables), movability.stable(tables), ) @@ -964,13 +965,13 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> { impl<'tcx> Stable<'tcx> for ty::BoundTyKind { type T = stable_mir::ty::BoundTyKind; - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { use stable_mir::ty::BoundTyKind; match self { ty::BoundTyKind::Anon => BoundTyKind::Anon, ty::BoundTyKind::Param(def_id, symbol) => { - BoundTyKind::Param(rustc_internal::param_def(*def_id), symbol.to_string()) + BoundTyKind::Param(tables.param_def(*def_id), symbol.to_string()) } } } @@ -979,13 +980,13 @@ impl<'tcx> Stable<'tcx> for ty::BoundTyKind { impl<'tcx> Stable<'tcx> for ty::BoundRegionKind { type T = stable_mir::ty::BoundRegionKind; - fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { use stable_mir::ty::BoundRegionKind; match self { ty::BoundRegionKind::BrAnon => BoundRegionKind::BrAnon, ty::BoundRegionKind::BrNamed(def_id, symbol) => { - BoundRegionKind::BrNamed(rustc_internal::br_named_def(*def_id), symbol.to_string()) + BoundRegionKind::BrNamed(tables.br_named_def(*def_id), symbol.to_string()) } ty::BoundRegionKind::BrEnv => BoundRegionKind::BrEnv, } @@ -1072,12 +1073,10 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { ty::Uint(uint_ty) => TyKind::RigidTy(RigidTy::Uint(uint_ty.stable(tables))), ty::Float(float_ty) => TyKind::RigidTy(RigidTy::Float(float_ty.stable(tables))), ty::Adt(adt_def, generic_args) => TyKind::RigidTy(RigidTy::Adt( - rustc_internal::adt_def(adt_def.did()), + tables.adt_def(adt_def.did()), generic_args.stable(tables), )), - ty::Foreign(def_id) => { - TyKind::RigidTy(RigidTy::Foreign(rustc_internal::foreign_def(*def_id))) - } + ty::Foreign(def_id) => TyKind::RigidTy(RigidTy::Foreign(tables.foreign_def(*def_id))), ty::Str => TyKind::RigidTy(RigidTy::Str), ty::Array(ty, constant) => { TyKind::RigidTy(RigidTy::Array(tables.intern_ty(*ty), constant.stable(tables))) @@ -1091,10 +1090,9 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { tables.intern_ty(*ty), mutbl.stable(tables), )), - ty::FnDef(def_id, generic_args) => TyKind::RigidTy(RigidTy::FnDef( - rustc_internal::fn_def(*def_id), - generic_args.stable(tables), - )), + ty::FnDef(def_id, generic_args) => { + TyKind::RigidTy(RigidTy::FnDef(tables.fn_def(*def_id), generic_args.stable(tables))) + } ty::FnPtr(poly_fn_sig) => TyKind::RigidTy(RigidTy::FnPtr(poly_fn_sig.stable(tables))), ty::Dynamic(existential_predicates, region, dyn_kind) => { TyKind::RigidTy(RigidTy::Dynamic( @@ -1107,11 +1105,11 @@ impl<'tcx> Stable<'tcx> for Ty<'tcx> { )) } ty::Closure(def_id, generic_args) => TyKind::RigidTy(RigidTy::Closure( - rustc_internal::closure_def(*def_id), + tables.closure_def(*def_id), generic_args.stable(tables), )), ty::Generator(def_id, generic_args, movability) => TyKind::RigidTy(RigidTy::Generator( - rustc_internal::generator_def(*def_id), + tables.generator_def(*def_id), generic_args.stable(tables), movability.stable(tables), )), @@ -1223,7 +1221,7 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef { use stable_mir::ty::TraitDecl; TraitDecl { - def_id: rustc_internal::trait_def(self.def_id), + def_id: tables.trait_def(self.def_id), unsafety: self.unsafety.stable(tables), paren_sugar: self.paren_sugar, has_auto_impl: self.has_auto_impl, @@ -1272,7 +1270,7 @@ impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> { fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T { use stable_mir::ty::TraitRef; - TraitRef { def_id: rustc_internal::trait_def(self.def_id), args: self.args.stable(tables) } + TraitRef { def_id: tables.trait_def(self.def_id), args: self.args.stable(tables) } } } @@ -1516,8 +1514,11 @@ impl<'tcx> Stable<'tcx> for rustc_span::Span { } } -impl<T> From<ErrorGuaranteed> for CompilerError<T> { - fn from(_error: ErrorGuaranteed) -> Self { - CompilerError::CompilationFailed +impl<'tcx> Stable<'tcx> for DefKind { + type T = stable_mir::DefKind; + + fn stable(&self, _: &mut Tables<'tcx>) -> Self::T { + // FIXME: add a real implementation of stable DefKind + opaque(self) } } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 68724c48037..c58fdbcb5e1 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -33,7 +33,7 @@ extern crate rustc_macros; #[macro_use] extern crate tracing; -use rustc_data_structures::{cold_path, AtomicRef}; +use rustc_data_structures::{outline, AtomicRef}; use rustc_macros::HashStable_Generic; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; @@ -1592,7 +1592,7 @@ impl SourceFile { return &lines[..]; } - cold_path(|| { + outline(|| { self.convert_diffs_to_lines_frozen(); if let Some(SourceFileLines::Lines(lines)) = self.lines.get() { return &lines[..]; diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs index c579da61e38..0f9d36342ad 100644 --- a/compiler/rustc_trait_selection/src/solve/project_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs @@ -59,7 +59,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } DefKind::AnonConst => self.normalize_anon_const(goal), DefKind::OpaqueTy => self.normalize_opaque_type(goal), - DefKind::TyAlias { .. } => self.normalize_weak_type(goal), + DefKind::TyAlias => self.normalize_weak_type(goal), kind => bug!("unknown DefKind {} in projection goal: {goal:#?}", kind.descr(def_id)), } } diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs index 436f10a4f7b..ec2e0daaf88 100644 --- a/compiler/rustc_ty_utils/src/implied_bounds.rs +++ b/compiler/rustc_ty_utils/src/implied_bounds.rs @@ -119,7 +119,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' }, DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), DefKind::OpaqueTy => match tcx.def_kind(tcx.local_parent(def_id)) { - DefKind::TyAlias { .. } => ty::List::empty(), + DefKind::TyAlias => ty::List::empty(), DefKind::AssocTy => tcx.assumed_wf_types(tcx.local_parent(def_id)), // Nested opaque types only occur in associated types: // ` type Opaque<T> = impl Trait<&'static T, AssocTy = impl Nested>; ` @@ -136,7 +136,7 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<' | DefKind::Enum | DefKind::Variant | DefKind::Trait - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::ForeignTy | DefKind::TraitAlias | DefKind::TyParam diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs index 38768f0a05b..06a30677d20 100644 --- a/compiler/rustc_ty_utils/src/opaque_types.rs +++ b/compiler/rustc_ty_utils/src/opaque_types.rs @@ -53,9 +53,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { fn parent(&self) -> Option<LocalDefId> { match self.tcx.def_kind(self.item) { - DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias { .. } => { - None - } + DefKind::AnonConst | DefKind::InlineConst | DefKind::Fn | DefKind::TyAlias => None, DefKind::AssocFn | DefKind::AssocTy | DefKind::AssocConst => { Some(self.tcx.local_parent(self.item)) } @@ -118,7 +116,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> { #[instrument(level = "trace", skip(self))] fn visit_nested_item(&mut self, id: rustc_hir::ItemId) { let id = id.owner_id.def_id; - if let DefKind::TyAlias { .. } = self.collector.tcx.def_kind(id) { + if let DefKind::TyAlias = self.collector.tcx.def_kind(id) { let items = self.collector.tcx.opaque_types_defined_by(id); self.collector.opaques.extend(items); } @@ -297,7 +295,7 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [ collector.collect_body_and_predicate_taits(); } // We're also doing this for `AssocTy` for the wf checks in `check_opaque_meets_bounds` - DefKind::TyAlias { .. } | DefKind::AssocTy => { + DefKind::TyAlias | DefKind::AssocTy => { tcx.type_of(item).instantiate_identity().visit_with(&mut collector); } DefKind::OpaqueTy => { diff --git a/compiler/stable_mir/Cargo.toml b/compiler/stable_mir/Cargo.toml new file mode 100644 index 00000000000..c61e217bf9f --- /dev/null +++ b/compiler/stable_mir/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "stable_mir" +version = "0.1.0-preview" +edition = "2021" + +[dependencies] +tracing = "0.1" +scoped-tls = "1.0" diff --git a/compiler/rustc_smir/README.md b/compiler/stable_mir/README.md index 31dee955f49..31dee955f49 100644 --- a/compiler/rustc_smir/README.md +++ b/compiler/stable_mir/README.md diff --git a/compiler/rustc_smir/rust-toolchain.toml b/compiler/stable_mir/rust-toolchain.toml index d75e8e33b1c..d75e8e33b1c 100644 --- a/compiler/rustc_smir/rust-toolchain.toml +++ b/compiler/stable_mir/rust-toolchain.toml diff --git a/compiler/rustc_smir/src/stable_mir/fold.rs b/compiler/stable_mir/src/fold.rs index 831cfb40a15..16ae62311aa 100644 --- a/compiler/rustc_smir/src/stable_mir/fold.rs +++ b/compiler/stable_mir/src/fold.rs @@ -1,6 +1,6 @@ use std::ops::ControlFlow; -use crate::rustc_internal::Opaque; +use crate::Opaque; use super::ty::{ Allocation, Binder, Const, ConstDef, ConstantKind, ExistentialPredicate, FnSig, GenericArgKind, diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/stable_mir/src/lib.rs index 3c86cb4038a..104985493ef 100644 --- a/compiler/rustc_smir/src/stable_mir/mod.rs +++ b/compiler/stable_mir/src/lib.rs @@ -1,15 +1,21 @@ -//! Module that implements the public interface to the Stable MIR. +//! The WIP stable interface to rustc internals. //! -//! This module shall contain all type definitions and APIs that we expect third-party tools to invoke to -//! interact with the compiler. +//! For more information see <https://github.com/rust-lang/project-stable-mir> //! -//! The goal is to eventually move this module to its own crate which shall be published on -//! [crates.io](https://crates.io). +//! # Note +//! +//! This API is still completely unstable and subject to change. + +#![doc( + html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/", + test(attr(allow(unused_variables), deny(warnings))) +)] //! -//! ## Note: +//! This crate shall contain all type definitions and APIs that we expect third-party tools to invoke to +//! interact with the compiler. //! -//! 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`. +//! The goal is to eventually be published on +//! [crates.io](https://crates.io). use std::cell::Cell; use std::fmt; @@ -18,7 +24,9 @@ use std::fmt::Debug; use self::ty::{ GenericPredicates, Generics, ImplDef, ImplTrait, Span, TraitDecl, TraitDef, Ty, TyKind, }; -use crate::rustc_smir::Tables; + +#[macro_use] +extern crate scoped_tls; pub mod fold; pub mod mir; @@ -33,11 +41,11 @@ pub type CrateNum = usize; /// A unique identification number for each item accessible for the current compilation unit. #[derive(Clone, Copy, PartialEq, Eq)] -pub struct DefId(pub(crate) usize); +pub struct DefId(pub usize); impl Debug for DefId { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("DefId:") + f.debug_struct("DefId") .field("id", &self.0) .field("name", &with(|cx| cx.name_of_def_id(*self))) .finish() @@ -46,7 +54,7 @@ impl Debug for DefId { /// A unique identification number for each provenance #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct AllocId(pub(crate) usize); +pub struct AllocId(pub usize); /// A list of crate items. pub type CrateItems = Vec<CrateItem>; @@ -74,16 +82,18 @@ pub enum CompilerError<T> { /// Holds information about a crate. #[derive(Clone, PartialEq, Eq, Debug)] pub struct Crate { - pub(crate) id: CrateNum, + pub id: CrateNum, pub name: Symbol, pub is_local: bool, } +pub type DefKind = Opaque; + /// 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) DefId); +pub struct CrateItem(pub DefId); impl CrateItem { pub fn body(&self) -> mir::Body { @@ -93,6 +103,14 @@ impl CrateItem { pub fn span(&self) -> Span { with(|cx| cx.span_of_an_item(self.0)) } + + pub fn name(&self) -> String { + with(|cx| cx.name_of_def_id(self.0)) + } + + pub fn kind(&self) -> DefKind { + with(|cx| cx.def_kind(self.0)) + } } /// Return the function where execution starts if the current @@ -161,6 +179,12 @@ pub trait Context { /// Prints the name of given `DefId` fn name_of_def_id(&self, def_id: DefId) -> String; + /// Prints a human readable form of `Span` + fn print_span(&self, span: Span) -> String; + + /// Prints the kind of given `DefId` + fn def_kind(&mut self, def_id: DefId) -> DefKind; + /// `Span` of an item fn span_of_an_item(&mut self, def_id: DefId) -> Span; @@ -169,10 +193,6 @@ pub trait Context { /// Create a new `Ty` from scratch without information from rustc. fn mk_ty(&mut self, kind: TyKind) -> Ty; - - /// HACK: Until we have fully stable consumers, we need an escape hatch - /// to get `DefId`s out of `CrateItem`s. - fn rustc_tables(&mut self, f: &mut dyn FnMut(&mut Tables<'_>)); } // A thread local variable that stores a pointer to the tables mapping between TyCtxt @@ -192,7 +212,7 @@ pub fn run(mut context: impl Context, f: impl FnOnce()) { /// Loads the current context and calls a function with it. /// Do not nest these, as that will ICE. -pub(crate) fn with<R>(f: impl FnOnce(&mut dyn Context) -> R) -> R { +pub fn with<R>(f: impl FnOnce(&mut dyn Context) -> R) -> R { assert!(TLV.is_set()); TLV.with(|tlv| { let ptr = tlv.get(); @@ -200,3 +220,23 @@ pub(crate) fn with<R>(f: impl FnOnce(&mut dyn Context) -> R) -> R { f(unsafe { *(ptr as *mut &mut dyn Context) }) }) } + +/// A type that provides internal information but that can still be used for debug purpose. +#[derive(Clone)] +pub struct Opaque(String); + +impl std::fmt::Display for Opaque { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{}", self.0) + } +} + +impl std::fmt::Debug for Opaque { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } +} + +pub fn opaque<T: Debug>(value: &T) -> Opaque { + Opaque(format!("{value:?}")) +} diff --git a/compiler/rustc_smir/src/stable_mir/mir.rs b/compiler/stable_mir/src/mir.rs index a9dbc3463f8..a9dbc3463f8 100644 --- a/compiler/rustc_smir/src/stable_mir/mir.rs +++ b/compiler/stable_mir/src/mir.rs diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/stable_mir/src/mir/body.rs index 449ca4b8145..6f8f7b06fa3 100644 --- a/compiler/rustc_smir/src/stable_mir/mir/body.rs +++ b/compiler/stable_mir/src/mir/body.rs @@ -1,8 +1,6 @@ -use crate::rustc_internal::Opaque; -use crate::stable_mir::ty::{ - AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region, -}; -use crate::stable_mir::{self, ty::Ty, Span}; +use crate::ty::{AdtDef, ClosureDef, Const, GeneratorDef, GenericArgs, Movability, Region}; +use crate::Opaque; +use crate::{ty::Ty, Span}; #[derive(Clone, Debug)] pub struct Body { @@ -135,7 +133,7 @@ pub enum AsyncGeneratorKind { } pub(crate) type LocalDefId = Opaque; -/// [`rustc_middle::mir::Coverage`] is heavily tied to internal details of the +/// The rustc coverage data structures are heavily tied to internal details of the /// coverage implementation that are likely to change, and are unlikely to be /// useful to third-party tools for the foreseeable future. pub(crate) type Coverage = Opaque; @@ -215,7 +213,7 @@ pub enum Rvalue { /// generator lowering, `Generator` aggregate kinds are disallowed too. Aggregate(AggregateKind, Vec<Operand>), - /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second + /// * `Offset` has the same semantics as `<*const T>::offset`, except that the second /// parameter may be a `usize` as well. /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats, /// raw pointers, or function pointers and return a `bool`. The types of the operands must be @@ -245,16 +243,14 @@ pub enum Rvalue { /// deref operation, immediately followed by one or more projections. CopyForDeref(Place), - /// Computes the discriminant of the place, returning it as an integer of type - /// [`discriminant_ty`]. Returns zero for types without discriminant. + /// Computes the discriminant of the place, returning it as an integer. + /// Returns zero for types without discriminant. /// /// The validity requirements for the underlying value are undecided for this rvalue, see /// [#91095]. Note too that the value of the discriminant is not the same thing as the - /// variant index; use [`discriminant_for_variant`] to convert. + /// variant index; /// - /// [`discriminant_ty`]: rustc_middle::ty::Ty::discriminant_ty /// [#91095]: https://github.com/rust-lang/rust/issues/91095 - /// [`discriminant_for_variant`]: rustc_middle::ty::Ty::discriminant_for_variant Discriminant(Place), /// Yields the length of the place, as a `usize`. @@ -295,7 +291,7 @@ pub enum Rvalue { /// /// **Needs clarification**: Are there weird additional semantics here related to the runtime /// nature of this operation? - ThreadLocalRef(stable_mir::CrateItem), + ThreadLocalRef(crate::CrateItem), /// Computes a value as described by the operation. NullaryOp(NullOp, Ty), diff --git a/compiler/rustc_smir/src/stable_mir/ty.rs b/compiler/stable_mir/src/ty.rs index eb9967b3888..82007e30683 100644 --- a/compiler/rustc_smir/src/stable_mir/ty.rs +++ b/compiler/stable_mir/src/ty.rs @@ -3,7 +3,7 @@ use super::{ mir::{Body, Mutability}, with, AllocId, DefId, }; -use crate::rustc_internal::Opaque; +use crate::Opaque; use std::fmt::{self, Debug, Formatter}; #[derive(Copy, Clone)] @@ -34,15 +34,16 @@ pub struct Const { } type Ident = Opaque; -pub(crate) type Region = Opaque; +pub type Region = Opaque; #[derive(Clone, Copy, PartialEq, Eq)] -pub struct Span(pub(crate) usize); +pub struct Span(pub usize); impl Debug for Span { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - let mut span = None; - with(|context| context.rustc_tables(&mut |tables| span = Some(tables.spans[self.0]))); - f.write_fmt(format_args!("{:?}", &span.unwrap())) + f.debug_struct("Span") + .field("id", &self.0) + .field("repr", &with(|cx| cx.print_span(*self))) + .finish() } } @@ -110,10 +111,10 @@ pub enum Movability { } #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ForeignDef(pub(crate) DefId); +pub struct ForeignDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct FnDef(pub(crate) DefId); +pub struct FnDef(pub DefId); impl FnDef { pub fn body(&self) -> Body { @@ -122,34 +123,34 @@ impl FnDef { } #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ClosureDef(pub(crate) DefId); +pub struct ClosureDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct GeneratorDef(pub(crate) DefId); +pub struct GeneratorDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ParamDef(pub(crate) DefId); +pub struct ParamDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct BrNamedDef(pub(crate) DefId); +pub struct BrNamedDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct AdtDef(pub(crate) DefId); +pub struct AdtDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct AliasDef(pub(crate) DefId); +pub struct AliasDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct TraitDef(pub(crate) DefId); +pub struct TraitDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct GenericDef(pub(crate) DefId); +pub struct GenericDef(pub DefId); #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct ConstDef(pub(crate) DefId); +pub struct ConstDef(pub DefId); #[derive(Clone, PartialEq, Eq, Debug)] -pub struct ImplDef(pub(crate) DefId); +pub struct ImplDef(pub DefId); #[derive(Clone, Debug)] pub struct GenericArgs(pub Vec<GenericArgKind>); @@ -333,7 +334,7 @@ pub type Bytes = Vec<Option<u8>>; pub type Size = usize; #[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub struct Prov(pub(crate) AllocId); +pub struct Prov(pub AllocId); pub type Align = u64; pub type Promoted = u32; pub type InitMaskMaterialized = Vec<u64>; diff --git a/compiler/rustc_smir/src/stable_mir/visitor.rs b/compiler/stable_mir/src/visitor.rs index c86063d2ed6..9c3b4cd994a 100644 --- a/compiler/rustc_smir/src/stable_mir/visitor.rs +++ b/compiler/stable_mir/src/visitor.rs @@ -1,6 +1,6 @@ use std::ops::ControlFlow; -use crate::rustc_internal::Opaque; +use crate::Opaque; use super::ty::{ Allocation, Binder, Const, ConstDef, ExistentialPredicate, FnSig, GenericArgKind, GenericArgs, diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 4f19ffa83db..292ccc5780f 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -1789,7 +1789,10 @@ pub fn run_cargo( // During check builds we need to keep crate metadata keep = true; } else if rlib_only_metadata { - if filename.contains("jemalloc_sys") || filename.contains("rustc_smir") { + if filename.contains("jemalloc_sys") + || filename.contains("rustc_smir") + || filename.contains("stable_mir") + { // jemalloc_sys and rustc_smir are not linked into librustc_driver.so, // so we need to distribute them as rlib to be able to use them. keep |= filename.ends_with(".rlib"); diff --git a/src/doc/embedded-book b/src/doc/embedded-book -Subproject 99ad2847b865e96d8ae7b333d3ee96963557e62 +Subproject eac173690b8cc99094e1d88bd49dd61127fbd28 diff --git a/src/doc/nomicon b/src/doc/nomicon -Subproject e3f3af69dce71cd37a785bccb7e58449197d940 +Subproject ddfa4214487686e91b21aa29afb972c08a8f0d5 diff --git a/src/doc/reference b/src/doc/reference -Subproject ee7c676fd6e287459cb407337652412c990686c +Subproject 5262e1c3b43a2c489df8f6717683a44c7a2260f diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide -Subproject 08bb147d51e815b96e8db7ba4cf870f201c11ff +Subproject a13b7c28ed705891c681ce5417b3d1cdb12cecd diff --git a/src/doc/rustdoc/src/unstable-features.md b/src/doc/rustdoc/src/unstable-features.md index 0d3f6338af4..7473b09920f 100644 --- a/src/doc/rustdoc/src/unstable-features.md +++ b/src/doc/rustdoc/src/unstable-features.md @@ -375,7 +375,7 @@ library, as an equivalent command-line argument is provided to `rustc` when buil This feature allows you to generate an index-page with a given markdown file. A good example of it is the [rust documentation index](https://doc.rust-lang.org/nightly/index.html). -With this, you'll have a page which you can custom as much as you want at the top of your crates. +With this, you'll have a page which you can customize as much as you want at the top of your crates. Using `index-page` option enables `enable-index-page` option as well. diff --git a/src/doc/style-guide/src/items.md b/src/doc/style-guide/src/items.md index a6d941f6d04..b215de6ad28 100644 --- a/src/doc/style-guide/src/items.md +++ b/src/doc/style-guide/src/items.md @@ -367,26 +367,52 @@ where ## Type aliases Keep type aliases on one line when they fit. If necessary to break the line, do -so after the `=`, and block-indent the right-hand side: +so before the `=`, and block-indent the right-hand side: ```rust pub type Foo = Bar<T>; // If multi-line is required -type VeryLongType<T, U: SomeBound> = - AnEvenLongerType<T, U, Foo<T>>; +type VeryLongType<T, U: SomeBound> + = AnEvenLongerType<T, U, Foo<T>>; ``` -Where possible avoid `where` clauses and keep type constraints inline. Where -that is not possible split the line before and after the `where` clause (and -split the `where` clause as normal), e.g., +When there is a trailing `where` clause after the type, and no `where` clause +present before the type, break before the `=` and indent. Then break before the +`where` keyword and format the clauses normally, e.g., ```rust +// With only a trailing where clause type VeryLongType<T, U> + = AnEvenLongerType<T, U, Foo<T>> +where + T: U::AnAssociatedType, + U: SomeBound; +``` + +When there is a `where` clause before the type, format it normally, and break +after the last clause. Do not indent before the `=` to leave it visually +distinct from the indented clauses that precede it. If there is additionally a +`where` clause after the type, break before the `where` keyword and format the +clauses normally. + +```rust +// With only a preceding where clause. +type WithPrecedingWC<T, U> where T: U::AnAssociatedType, U: SomeBound, = AnEvenLongerType<T, U, Foo<T>>; + +// Or with both a preceding and trailing where clause. +type WithPrecedingWC<T, U> +where + T: U::AnAssociatedType, + U: SomeBound, += AnEvenLongerType<T, U, Foo<T>> +where + T: U::AnAssociatedType2, + U: SomeBound2; ``` ## Associated types diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index 9e20662fff3..32b882e763d 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -37,7 +37,7 @@ Most lang items are defined by `core`, but if you're trying to build an executable without the `std` crate, you might run into the need for lang item definitions. -[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/personality/gcc.rs +[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/sys/personality/gcc.rs ## Example: Implementing a `Box` diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index dd43ee03383..fcbcfbf5c67 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -80,7 +80,7 @@ pub(crate) fn try_inline( build_impls(cx, did, attrs_without_docs, &mut ret); clean::UnionItem(build_union(cx, did)) } - Res::Def(DefKind::TyAlias { .. }, did) => { + Res::Def(DefKind::TyAlias, did) => { record_extern_fqn(cx, did, ItemType::TypeAlias); build_impls(cx, did, attrs_without_docs, &mut ret); clean::TypeAliasItem(build_type_alias(cx, did)) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d9ee622848d..34d81f51f76 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1758,7 +1758,7 @@ fn maybe_expand_private_type_alias<'tcx>( cx: &mut DocContext<'tcx>, path: &hir::Path<'tcx>, ) -> Option<Type> { - let Res::Def(DefKind::TyAlias { .. }, def_id) = path.res else { return None }; + let Res::Def(DefKind::TyAlias, def_id) = path.res else { return None }; // Substitute private type aliases let def_id = def_id.as_local()?; let alias = if !cx.cache.effective_visibilities.is_exported(cx.tcx, def_id.to_def_id()) @@ -2027,7 +2027,7 @@ impl<'tcx> ContainerTy<'tcx> { let (DefKind::Struct | DefKind::Union | DefKind::Enum - | DefKind::TyAlias { .. } + | DefKind::TyAlias | DefKind::Trait) = tcx.def_kind(container) else { return ObjectLifetimeDefault::Empty; @@ -2859,7 +2859,7 @@ fn clean_impl<'tcx>( let for_ = clean_ty(impl_.self_ty, cx); let type_alias = for_.def_id(&cx.cache).and_then(|alias_def_id: DefId| match tcx.def_kind(alias_def_id) { - DefKind::TyAlias { .. } => Some(clean_middle_ty( + DefKind::TyAlias => Some(clean_middle_ty( ty::Binder::dummy(tcx.type_of(def_id).instantiate_identity()), cx, Some(def_id.to_def_id()), diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs index fd79160ff4a..be2ee791588 100644 --- a/src/librustdoc/formats/item_type.rs +++ b/src/librustdoc/formats/item_type.rs @@ -115,7 +115,7 @@ impl From<DefKind> for ItemType { DefKind::Struct => Self::Struct, DefKind::Union => Self::Union, DefKind::Trait => Self::Trait, - DefKind::TyAlias { .. } => Self::TypeAlias, + DefKind::TyAlias => Self::TypeAlias, DefKind::TraitAlias => Self::TraitAlias, DefKind::Macro(kind) => match kind { MacroKind::Bang => ItemType::Macro, diff --git a/src/librustdoc/html/templates/type_layout.html b/src/librustdoc/html/templates/type_layout.html index 287cbab07d2..b8b7785a2a1 100644 --- a/src/librustdoc/html/templates/type_layout.html +++ b/src/librustdoc/html/templates/type_layout.html @@ -9,12 +9,12 @@ <strong>Note:</strong> Most layout information is <strong>completely {#+ #} unstable</strong> and may even differ between compilations. {#+ #} The only exception is types with certain <code>repr(...)</code> {#+ #} - attributes. Please see the Rust Reference’s {#+ #} + attributes. Please see the Rust Reference's {#+ #} <a href="https://doc.rust-lang.org/reference/type-layout.html">“Type Layout”</a> {#+ #} chapter for details on type layout guarantees. {# #} </p> {# #} </div> {# #} - <p><strong>Size:</strong> {{ type_layout_size|safe }}</p> {# #} + <p><strong>Size:</strong> {{+ type_layout_size|safe }}</p> {# #} {% if !variants.is_empty() %} <p> {# #} <strong>Size for each variant:</strong> {# #} diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 8ea9b7a418b..d216305e6a9 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -593,7 +593,7 @@ impl<'a, 'tcx> LinkCollector<'a, 'tcx> { .unwrap_or(Vec::new()) } } - Res::Def(DefKind::TyAlias { .. }, did) => { + Res::Def(DefKind::TyAlias, did) => { // Resolve the link on the type the alias points to. // FIXME: if the associated item is defined directly on the type alias, // it will show up on its documentation page, we should link there instead. diff --git a/src/tools/cargo b/src/tools/cargo -Subproject 414d9e3a6d8096f3e276234ce220c868767a879 +Subproject e6aabe8b3fcf639be3a5bf68e77853bd7b3fa27 diff --git a/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs b/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs index b00fa104f98..f95d2c2edb1 100644 --- a/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs +++ b/src/tools/clippy/clippy_lints/src/init_numbered_fields.rs @@ -50,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for NumberedFields { && fields .iter() .all(|f| f.ident.as_str().as_bytes().iter().all(u8::is_ascii_digit)) - && !matches!(cx.qpath_res(path, e.hir_id), Res::Def(DefKind::TyAlias { .. }, ..)) + && !matches!(cx.qpath_res(path, e.hir_id), Res::Def(DefKind::TyAlias, ..)) { let expr_spans = fields .iter() diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs index 5c5ee262052..50d6f3b7e55 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -401,7 +401,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< = get_callee_generic_args_and_args(cx, parent_expr) { // FIXME: the `instantiate_identity()` below seems incorrect, since we eventually - // call `tcx.try_subst_and_normalize_erasing_regions` further down + // call `tcx.try_instantiate_and_normalize_erasing_regions` further down // (i.e., we are explicitly not in the identity context). let fn_sig = cx.tcx.fn_sig(callee_def_id).instantiate_identity().skip_binder(); if let Some(arg_index) = recv.into_iter().chain(call_args).position(|arg| arg.hir_id == expr.hir_id) @@ -452,7 +452,7 @@ fn can_change_type<'a>(cx: &LateContext<'a>, mut expr: &'a Expr<'a>, mut ty: Ty< let output_ty = fn_sig.output(); if output_ty.contains(*param_ty) { - if let Ok(new_ty) = cx.tcx.try_subst_and_normalize_erasing_regions( + if let Ok(new_ty) = cx.tcx.try_instantiate_and_normalize_erasing_regions( new_subst, cx.param_env, EarlyBinder::bind(output_ty)) { expr = parent_expr; ty = new_ty; diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 0f7bc04ccba..13da79fba7e 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -288,7 +288,7 @@ pub fn is_wild(pat: &Pat<'_>) -> bool { /// Checks if the given `QPath` belongs to a type alias. pub fn is_ty_alias(qpath: &QPath<'_>) -> bool { match *qpath { - QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias { .. } | DefKind::AssocTy, ..)), + QPath::Resolved(_, path) => matches!(path.res, Res::Def(DefKind::TyAlias | DefKind::AssocTy, ..)), QPath::TypeRelative(ty, _) if let TyKind::Path(qpath) = ty.kind => { is_ty_alias(&qpath) }, _ => false, } diff --git a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs index d05d9e7640f..75064672326 100644 --- a/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/type_certainty/mod.rs @@ -219,7 +219,7 @@ fn path_segment_certainty( // See the comment preceding `qpath_certainty`. `def_id` could refer to a type or a value. let certainty = lhs.join_clearing_def_ids(rhs); if resolves_to_type { - if let DefKind::TyAlias { .. } = cx.tcx.def_kind(def_id) { + if let DefKind::TyAlias = cx.tcx.def_kind(def_id) { adt_def_id(cx.tcx.type_of(def_id).instantiate_identity()) .map_or(certainty, |def_id| certainty.with_def_id(def_id)) } else { diff --git a/src/tools/miri/tests/pass/function_pointers.rs b/src/tools/miri/tests/pass/function_pointers.rs index b66826e3fcd..1c99a96feda 100644 --- a/src/tools/miri/tests/pass/function_pointers.rs +++ b/src/tools/miri/tests/pass/function_pointers.rs @@ -23,6 +23,10 @@ fn h(i: i32, j: i32) -> i32 { j * i * 7 } +fn i() -> i32 { + 73 +} + fn return_fn_ptr(f: fn() -> i32) -> fn() -> i32 { f } @@ -72,10 +76,18 @@ fn main() { assert_eq!(indirect3(h), 210); assert_eq!(indirect_mut3(h), 210); assert_eq!(indirect_once3(h), 210); - let g = f as fn() -> i32; - assert!(return_fn_ptr(g) == g); - assert!(return_fn_ptr(g) as unsafe fn() -> i32 == g as fn() -> i32 as unsafe fn() -> i32); - assert!(return_fn_ptr(f) != f); + // Check that `i` always has the same address. This is not guaranteed + // but Miri currently uses a fixed address for monomorphic functions. + assert!(return_fn_ptr(i) == i); + assert!(return_fn_ptr(i) as unsafe fn() -> i32 == i as fn() -> i32 as unsafe fn() -> i32); + // We don't check anything for `f`. Miri gives it many different addresses + // but mir-opts can turn them into the same address. + let _val = return_fn_ptr(f) != f; + // However, if we only turn `f` into a function pointer and use that pointer, + // it is equal to itself. + let f2 = f as fn() -> i32; + assert!(return_fn_ptr(f2) == f2); + assert!(return_fn_ptr(f2) as unsafe fn() -> i32 == f2 as fn() -> i32 as unsafe fn() -> i32); // Any non-null value is okay for function pointers. unsafe { diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index c05349c8e8d..7d3ef4197a7 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -58,14 +58,14 @@ const EXCEPTIONS_CARGO: &[(&str, &str)] = &[ // tidy-alphabetical-start ("bitmaps", "MPL-2.0+"), ("bytesize", "Apache-2.0"), + ("byteyarn", "Apache-2.0"), ("ciborium", "Apache-2.0"), ("ciborium-io", "Apache-2.0"), ("ciborium-ll", "Apache-2.0"), ("dunce", "CC0-1.0 OR MIT-0 OR Apache-2.0"), + ("encoding_rs", "(Apache-2.0 OR MIT) AND BSD-3-Clause"), ("fiat-crypto", "MIT OR Apache-2.0 OR BSD-1-Clause"), ("im-rc", "MPL-2.0+"), - ("imara-diff", "Apache-2.0"), - ("instant", "BSD-3-Clause"), ("normalize-line-endings", "Apache-2.0"), ("openssl", "Apache-2.0"), ("ryu", "Apache-2.0 OR BSL-1.0"), diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff new file mode 100644 index 00000000000..3f5173c189e --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-abort.diff @@ -0,0 +1,342 @@ +- // MIR for `arithmetic` before GVN ++ // MIR for `arithmetic` after GVN + + fn arithmetic(_1: u64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: u64; + let mut _4: u64; + let _5: (); + let mut _6: u64; + let mut _7: u64; + let _8: (); + let mut _9: u64; + let mut _10: u64; + let _11: (); + let mut _12: u64; + let mut _13: u64; + let _14: (); + let mut _15: u64; + let mut _16: u64; + let mut _17: bool; + let _18: (); + let mut _19: u64; + let mut _20: u64; + let mut _21: bool; + let _22: (); + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: bool; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: bool; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: bool; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: bool; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: bool; + let _46: (); + let mut _47: u64; + let mut _48: u64; + let _49: (); + let mut _50: u64; + let mut _51: u64; + let _52: (); + let mut _53: u64; + let mut _54: u64; + let _55: (); + let mut _56: u64; + let mut _57: u64; + let _58: (); + let mut _59: u64; + let mut _60: u64; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = Add(move _4, const 0_u64); +- StorageDead(_4); ++ _3 = Add(_1, const 0_u64); + _2 = opaque::<u64>(move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_5); + StorageLive(_6); +- StorageLive(_7); +- _7 = _1; +- _6 = Sub(move _7, const 0_u64); +- StorageDead(_7); ++ _6 = Sub(_1, const 0_u64); + _5 = opaque::<u64>(move _6) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_6); + StorageDead(_5); + StorageLive(_8); + StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- _9 = Mul(move _10, const 0_u64); +- StorageDead(_10); ++ _9 = Mul(_1, const 0_u64); + _8 = opaque::<u64>(move _9) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_11); + StorageLive(_12); +- StorageLive(_13); +- _13 = _1; +- _12 = Mul(move _13, const 1_u64); +- StorageDead(_13); ++ _12 = Mul(_1, const 1_u64); + _11 = opaque::<u64>(move _12) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; + _17 = Eq(const 0_u64, const 0_u64); +- assert(!move _17, "attempt to divide `{}` by zero", _16) -> [success: bb5, unwind unreachable]; ++ assert(!_17, "attempt to divide `{}` by zero", _1) -> [success: bb5, unwind unreachable]; + } + + bb5: { +- _15 = Div(move _16, const 0_u64); +- StorageDead(_16); ++ _15 = Div(_1, const 0_u64); + _14 = opaque::<u64>(move _15) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_18); + StorageLive(_19); +- StorageLive(_20); +- _20 = _1; + _21 = Eq(const 1_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb7, unwind unreachable]; ++ assert(!_21, "attempt to divide `{}` by zero", _1) -> [success: bb7, unwind unreachable]; + } + + bb7: { +- _19 = Div(move _20, const 1_u64); +- StorageDead(_20); ++ _19 = Div(_1, const 1_u64); + _18 = opaque::<u64>(move _19) -> [return: bb8, unwind unreachable]; + } + + bb8: { + StorageDead(_19); + StorageDead(_18); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; +- _25 = Eq(_24, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind unreachable]; ++ _25 = Eq(_1, const 0_u64); ++ assert(!_25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind unreachable]; + } + + bb9: { +- _23 = Div(const 0_u64, move _24); +- StorageDead(_24); ++ _23 = Div(const 0_u64, _1); + _22 = opaque::<u64>(move _23) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_26); + StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- _29 = Eq(_28, const 0_u64); +- assert(!move _29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind unreachable]; ++ assert(!_25, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind unreachable]; + } + + bb11: { +- _27 = Div(const 1_u64, move _28); +- StorageDead(_28); ++ _27 = Div(const 1_u64, _1); + _26 = opaque::<u64>(move _27) -> [return: bb12, unwind unreachable]; + } + + bb12: { + StorageDead(_27); + StorageDead(_26); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _33 = Eq(const 0_u64, const 0_u64); +- assert(!move _33, "attempt to calculate the remainder of `{}` with a divisor of zero", _32) -> [success: bb13, unwind unreachable]; ++ assert(!_17, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb13, unwind unreachable]; + } + + bb13: { +- _31 = Rem(move _32, const 0_u64); +- StorageDead(_32); ++ _31 = Rem(_1, const 0_u64); + _30 = opaque::<u64>(move _31) -> [return: bb14, unwind unreachable]; + } + + bb14: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_34); + StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- _37 = Eq(const 1_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb15, unwind unreachable]; ++ assert(!_21, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb15, unwind unreachable]; + } + + bb15: { +- _35 = Rem(move _36, const 1_u64); +- StorageDead(_36); ++ _35 = Rem(_1, const 1_u64); + _34 = opaque::<u64>(move _35) -> [return: bb16, unwind unreachable]; + } + + bb16: { + StorageDead(_35); + StorageDead(_34); + StorageLive(_38); + StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- _41 = Eq(_40, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind unreachable]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind unreachable]; + } + + bb17: { +- _39 = Rem(const 0_u64, move _40); +- StorageDead(_40); ++ _39 = Rem(const 0_u64, _1); + _38 = opaque::<u64>(move _39) -> [return: bb18, unwind unreachable]; + } + + bb18: { + StorageDead(_39); + StorageDead(_38); + StorageLive(_42); + StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- _45 = Eq(_44, const 0_u64); +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind unreachable]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind unreachable]; + } + + bb19: { +- _43 = Rem(const 1_u64, move _44); +- StorageDead(_44); ++ _43 = Rem(const 1_u64, _1); + _42 = opaque::<u64>(move _43) -> [return: bb20, unwind unreachable]; + } + + bb20: { + StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _47 = BitAnd(move _48, const 0_u64); +- StorageDead(_48); ++ _47 = BitAnd(_1, const 0_u64); + _46 = opaque::<u64>(move _47) -> [return: bb21, unwind unreachable]; + } + + bb21: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_49); + StorageLive(_50); +- StorageLive(_51); +- _51 = _1; +- _50 = BitOr(move _51, const 0_u64); +- StorageDead(_51); ++ _50 = BitOr(_1, const 0_u64); + _49 = opaque::<u64>(move _50) -> [return: bb22, unwind unreachable]; + } + + bb22: { + StorageDead(_50); + StorageDead(_49); + StorageLive(_52); + StorageLive(_53); +- StorageLive(_54); +- _54 = _1; +- _53 = BitXor(move _54, const 0_u64); +- StorageDead(_54); ++ _53 = BitXor(_1, const 0_u64); + _52 = opaque::<u64>(move _53) -> [return: bb23, unwind unreachable]; + } + + bb23: { + StorageDead(_53); + StorageDead(_52); + StorageLive(_55); + StorageLive(_56); +- StorageLive(_57); +- _57 = _1; +- _56 = Shr(move _57, const 0_i32); +- StorageDead(_57); ++ _56 = Shr(_1, const 0_i32); + _55 = opaque::<u64>(move _56) -> [return: bb24, unwind unreachable]; + } + + bb24: { + StorageDead(_56); + StorageDead(_55); + StorageLive(_58); + StorageLive(_59); +- StorageLive(_60); +- _60 = _1; +- _59 = Shl(move _60, const 0_i32); +- StorageDead(_60); ++ _59 = Shl(_1, const 0_i32); + _58 = opaque::<u64>(move _59) -> [return: bb25, unwind unreachable]; + } + + bb25: { + StorageDead(_59); + StorageDead(_58); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff new file mode 100644 index 00000000000..38da21d91d4 --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic.GVN.panic-unwind.diff @@ -0,0 +1,342 @@ +- // MIR for `arithmetic` before GVN ++ // MIR for `arithmetic` after GVN + + fn arithmetic(_1: u64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: u64; + let mut _4: u64; + let _5: (); + let mut _6: u64; + let mut _7: u64; + let _8: (); + let mut _9: u64; + let mut _10: u64; + let _11: (); + let mut _12: u64; + let mut _13: u64; + let _14: (); + let mut _15: u64; + let mut _16: u64; + let mut _17: bool; + let _18: (); + let mut _19: u64; + let mut _20: u64; + let mut _21: bool; + let _22: (); + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: bool; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: bool; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: bool; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: bool; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: bool; + let _46: (); + let mut _47: u64; + let mut _48: u64; + let _49: (); + let mut _50: u64; + let mut _51: u64; + let _52: (); + let mut _53: u64; + let mut _54: u64; + let _55: (); + let mut _56: u64; + let mut _57: u64; + let _58: (); + let mut _59: u64; + let mut _60: u64; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = Add(move _4, const 0_u64); +- StorageDead(_4); ++ _3 = Add(_1, const 0_u64); + _2 = opaque::<u64>(move _3) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_5); + StorageLive(_6); +- StorageLive(_7); +- _7 = _1; +- _6 = Sub(move _7, const 0_u64); +- StorageDead(_7); ++ _6 = Sub(_1, const 0_u64); + _5 = opaque::<u64>(move _6) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_6); + StorageDead(_5); + StorageLive(_8); + StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- _9 = Mul(move _10, const 0_u64); +- StorageDead(_10); ++ _9 = Mul(_1, const 0_u64); + _8 = opaque::<u64>(move _9) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_11); + StorageLive(_12); +- StorageLive(_13); +- _13 = _1; +- _12 = Mul(move _13, const 1_u64); +- StorageDead(_13); ++ _12 = Mul(_1, const 1_u64); + _11 = opaque::<u64>(move _12) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; + _17 = Eq(const 0_u64, const 0_u64); +- assert(!move _17, "attempt to divide `{}` by zero", _16) -> [success: bb5, unwind continue]; ++ assert(!_17, "attempt to divide `{}` by zero", _1) -> [success: bb5, unwind continue]; + } + + bb5: { +- _15 = Div(move _16, const 0_u64); +- StorageDead(_16); ++ _15 = Div(_1, const 0_u64); + _14 = opaque::<u64>(move _15) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_18); + StorageLive(_19); +- StorageLive(_20); +- _20 = _1; + _21 = Eq(const 1_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb7, unwind continue]; ++ assert(!_21, "attempt to divide `{}` by zero", _1) -> [success: bb7, unwind continue]; + } + + bb7: { +- _19 = Div(move _20, const 1_u64); +- StorageDead(_20); ++ _19 = Div(_1, const 1_u64); + _18 = opaque::<u64>(move _19) -> [return: bb8, unwind continue]; + } + + bb8: { + StorageDead(_19); + StorageDead(_18); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; +- _25 = Eq(_24, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind continue]; ++ _25 = Eq(_1, const 0_u64); ++ assert(!_25, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb9, unwind continue]; + } + + bb9: { +- _23 = Div(const 0_u64, move _24); +- StorageDead(_24); ++ _23 = Div(const 0_u64, _1); + _22 = opaque::<u64>(move _23) -> [return: bb10, unwind continue]; + } + + bb10: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_26); + StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- _29 = Eq(_28, const 0_u64); +- assert(!move _29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind continue]; ++ assert(!_25, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb11, unwind continue]; + } + + bb11: { +- _27 = Div(const 1_u64, move _28); +- StorageDead(_28); ++ _27 = Div(const 1_u64, _1); + _26 = opaque::<u64>(move _27) -> [return: bb12, unwind continue]; + } + + bb12: { + StorageDead(_27); + StorageDead(_26); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _33 = Eq(const 0_u64, const 0_u64); +- assert(!move _33, "attempt to calculate the remainder of `{}` with a divisor of zero", _32) -> [success: bb13, unwind continue]; ++ assert(!_17, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb13, unwind continue]; + } + + bb13: { +- _31 = Rem(move _32, const 0_u64); +- StorageDead(_32); ++ _31 = Rem(_1, const 0_u64); + _30 = opaque::<u64>(move _31) -> [return: bb14, unwind continue]; + } + + bb14: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_34); + StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- _37 = Eq(const 1_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb15, unwind continue]; ++ assert(!_21, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb15, unwind continue]; + } + + bb15: { +- _35 = Rem(move _36, const 1_u64); +- StorageDead(_36); ++ _35 = Rem(_1, const 1_u64); + _34 = opaque::<u64>(move _35) -> [return: bb16, unwind continue]; + } + + bb16: { + StorageDead(_35); + StorageDead(_34); + StorageLive(_38); + StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- _41 = Eq(_40, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind continue]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb17, unwind continue]; + } + + bb17: { +- _39 = Rem(const 0_u64, move _40); +- StorageDead(_40); ++ _39 = Rem(const 0_u64, _1); + _38 = opaque::<u64>(move _39) -> [return: bb18, unwind continue]; + } + + bb18: { + StorageDead(_39); + StorageDead(_38); + StorageLive(_42); + StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- _45 = Eq(_44, const 0_u64); +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind continue]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb19, unwind continue]; + } + + bb19: { +- _43 = Rem(const 1_u64, move _44); +- StorageDead(_44); ++ _43 = Rem(const 1_u64, _1); + _42 = opaque::<u64>(move _43) -> [return: bb20, unwind continue]; + } + + bb20: { + StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _47 = BitAnd(move _48, const 0_u64); +- StorageDead(_48); ++ _47 = BitAnd(_1, const 0_u64); + _46 = opaque::<u64>(move _47) -> [return: bb21, unwind continue]; + } + + bb21: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_49); + StorageLive(_50); +- StorageLive(_51); +- _51 = _1; +- _50 = BitOr(move _51, const 0_u64); +- StorageDead(_51); ++ _50 = BitOr(_1, const 0_u64); + _49 = opaque::<u64>(move _50) -> [return: bb22, unwind continue]; + } + + bb22: { + StorageDead(_50); + StorageDead(_49); + StorageLive(_52); + StorageLive(_53); +- StorageLive(_54); +- _54 = _1; +- _53 = BitXor(move _54, const 0_u64); +- StorageDead(_54); ++ _53 = BitXor(_1, const 0_u64); + _52 = opaque::<u64>(move _53) -> [return: bb23, unwind continue]; + } + + bb23: { + StorageDead(_53); + StorageDead(_52); + StorageLive(_55); + StorageLive(_56); +- StorageLive(_57); +- _57 = _1; +- _56 = Shr(move _57, const 0_i32); +- StorageDead(_57); ++ _56 = Shr(_1, const 0_i32); + _55 = opaque::<u64>(move _56) -> [return: bb24, unwind continue]; + } + + bb24: { + StorageDead(_56); + StorageDead(_55); + StorageLive(_58); + StorageLive(_59); +- StorageLive(_60); +- _60 = _1; +- _59 = Shl(move _60, const 0_i32); +- StorageDead(_60); ++ _59 = Shl(_1, const 0_i32); + _58 = opaque::<u64>(move _59) -> [return: bb25, unwind continue]; + } + + bb25: { + StorageDead(_59); + StorageDead(_58); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff new file mode 100644 index 00000000000..0c342799e07 --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-abort.diff @@ -0,0 +1,389 @@ +- // MIR for `arithmetic_checked` before GVN ++ // MIR for `arithmetic_checked` after GVN + + fn arithmetic_checked(_1: u64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: u64; + let mut _4: u64; + let mut _5: (u64, bool); + let _6: (); + let mut _7: u64; + let mut _8: u64; + let mut _9: (u64, bool); + let _10: (); + let mut _11: u64; + let mut _12: u64; + let mut _13: (u64, bool); + let _14: (); + let mut _15: u64; + let mut _16: u64; + let mut _17: (u64, bool); + let _18: (); + let mut _19: u64; + let mut _20: u64; + let mut _21: bool; + let _22: (); + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: bool; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: bool; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: bool; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: bool; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: bool; + let _46: (); + let mut _47: u64; + let mut _48: u64; + let mut _49: bool; + let _50: (); + let mut _51: u64; + let mut _52: u64; + let _53: (); + let mut _54: u64; + let mut _55: u64; + let _56: (); + let mut _57: u64; + let mut _58: u64; + let _59: (); + let mut _60: u64; + let mut _61: u64; + let mut _62: u32; + let mut _63: bool; + let _64: (); + let mut _65: u64; + let mut _66: u64; + let mut _67: u32; + let mut _68: bool; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _5 = CheckedAdd(_4, const 0_u64); +- assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind unreachable]; ++ _5 = CheckedAdd(_1, const 0_u64); ++ assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind unreachable]; + } + + bb1: { + _3 = move (_5.0: u64); +- StorageDead(_4); + _2 = opaque::<u64>(move _3) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_6); + StorageLive(_7); +- StorageLive(_8); +- _8 = _1; +- _9 = CheckedSub(_8, const 0_u64); +- assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind unreachable]; ++ _9 = CheckedSub(_1, const 0_u64); ++ assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind unreachable]; + } + + bb3: { + _7 = move (_9.0: u64); +- StorageDead(_8); + _6 = opaque::<u64>(move _7) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_10); + StorageLive(_11); +- StorageLive(_12); +- _12 = _1; +- _13 = CheckedMul(_12, const 0_u64); +- assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", move _12, const 0_u64) -> [success: bb5, unwind unreachable]; ++ _13 = CheckedMul(_1, const 0_u64); ++ assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb5, unwind unreachable]; + } + + bb5: { + _11 = move (_13.0: u64); +- StorageDead(_12); + _10 = opaque::<u64>(move _11) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; +- _17 = CheckedMul(_16, const 1_u64); +- assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", move _16, const 1_u64) -> [success: bb7, unwind unreachable]; ++ _17 = CheckedMul(_1, const 1_u64); ++ assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb7, unwind unreachable]; + } + + bb7: { + _15 = move (_17.0: u64); +- StorageDead(_16); + _14 = opaque::<u64>(move _15) -> [return: bb8, unwind unreachable]; + } + + bb8: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_18); + StorageLive(_19); +- StorageLive(_20); +- _20 = _1; + _21 = Eq(const 0_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb9, unwind unreachable]; ++ assert(!_21, "attempt to divide `{}` by zero", _1) -> [success: bb9, unwind unreachable]; + } + + bb9: { +- _19 = Div(move _20, const 0_u64); +- StorageDead(_20); ++ _19 = Div(_1, const 0_u64); + _18 = opaque::<u64>(move _19) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageDead(_19); + StorageDead(_18); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; + _25 = Eq(const 1_u64, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", _24) -> [success: bb11, unwind unreachable]; ++ assert(!_25, "attempt to divide `{}` by zero", _1) -> [success: bb11, unwind unreachable]; + } + + bb11: { +- _23 = Div(move _24, const 1_u64); +- StorageDead(_24); ++ _23 = Div(_1, const 1_u64); + _22 = opaque::<u64>(move _23) -> [return: bb12, unwind unreachable]; + } + + bb12: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_26); + StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- _29 = Eq(_28, const 0_u64); +- assert(!move _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb13, unwind unreachable]; ++ _29 = Eq(_1, const 0_u64); ++ assert(!_29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb13, unwind unreachable]; + } + + bb13: { +- _27 = Div(const 0_u64, move _28); +- StorageDead(_28); ++ _27 = Div(const 0_u64, _1); + _26 = opaque::<u64>(move _27) -> [return: bb14, unwind unreachable]; + } + + bb14: { + StorageDead(_27); + StorageDead(_26); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _33 = Eq(_32, const 0_u64); +- assert(!move _33, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb15, unwind unreachable]; ++ assert(!_29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb15, unwind unreachable]; + } + + bb15: { +- _31 = Div(const 1_u64, move _32); +- StorageDead(_32); ++ _31 = Div(const 1_u64, _1); + _30 = opaque::<u64>(move _31) -> [return: bb16, unwind unreachable]; + } + + bb16: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_34); + StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- _37 = Eq(const 0_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb17, unwind unreachable]; ++ assert(!_21, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb17, unwind unreachable]; + } + + bb17: { +- _35 = Rem(move _36, const 0_u64); +- StorageDead(_36); ++ _35 = Rem(_1, const 0_u64); + _34 = opaque::<u64>(move _35) -> [return: bb18, unwind unreachable]; + } + + bb18: { + StorageDead(_35); + StorageDead(_34); + StorageLive(_38); + StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- _41 = Eq(const 1_u64, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", _40) -> [success: bb19, unwind unreachable]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb19, unwind unreachable]; + } + + bb19: { +- _39 = Rem(move _40, const 1_u64); +- StorageDead(_40); ++ _39 = Rem(_1, const 1_u64); + _38 = opaque::<u64>(move _39) -> [return: bb20, unwind unreachable]; + } + + bb20: { + StorageDead(_39); + StorageDead(_38); + StorageLive(_42); + StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- _45 = Eq(_44, const 0_u64); +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb21, unwind unreachable]; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb21, unwind unreachable]; + } + + bb21: { +- _43 = Rem(const 0_u64, move _44); +- StorageDead(_44); ++ _43 = Rem(const 0_u64, _1); + _42 = opaque::<u64>(move _43) -> [return: bb22, unwind unreachable]; + } + + bb22: { + StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _49 = Eq(_48, const 0_u64); +- assert(!move _49, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb23, unwind unreachable]; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb23, unwind unreachable]; + } + + bb23: { +- _47 = Rem(const 1_u64, move _48); +- StorageDead(_48); ++ _47 = Rem(const 1_u64, _1); + _46 = opaque::<u64>(move _47) -> [return: bb24, unwind unreachable]; + } + + bb24: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_50); + StorageLive(_51); +- StorageLive(_52); +- _52 = _1; +- _51 = BitAnd(move _52, const 0_u64); +- StorageDead(_52); ++ _51 = BitAnd(_1, const 0_u64); + _50 = opaque::<u64>(move _51) -> [return: bb25, unwind unreachable]; + } + + bb25: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_53); + StorageLive(_54); +- StorageLive(_55); +- _55 = _1; +- _54 = BitOr(move _55, const 0_u64); +- StorageDead(_55); ++ _54 = BitOr(_1, const 0_u64); + _53 = opaque::<u64>(move _54) -> [return: bb26, unwind unreachable]; + } + + bb26: { + StorageDead(_54); + StorageDead(_53); + StorageLive(_56); + StorageLive(_57); +- StorageLive(_58); +- _58 = _1; +- _57 = BitXor(move _58, const 0_u64); +- StorageDead(_58); ++ _57 = BitXor(_1, const 0_u64); + _56 = opaque::<u64>(move _57) -> [return: bb27, unwind unreachable]; + } + + bb27: { + StorageDead(_57); + StorageDead(_56); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- _61 = _1; + _62 = const 0_i32 as u32 (IntToInt); +- _63 = Lt(move _62, const 64_u32); +- assert(move _63, "attempt to shift right by `{}`, which would overflow", const 0_i32) -> [success: bb28, unwind unreachable]; ++ _63 = Lt(_62, const 64_u32); ++ assert(_63, "attempt to shift right by `{}`, which would overflow", const 0_i32) -> [success: bb28, unwind unreachable]; + } + + bb28: { +- _60 = Shr(move _61, const 0_i32); +- StorageDead(_61); ++ _60 = Shr(_1, const 0_i32); + _59 = opaque::<u64>(move _60) -> [return: bb29, unwind unreachable]; + } + + bb29: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_64); + StorageLive(_65); +- StorageLive(_66); +- _66 = _1; +- _67 = const 0_i32 as u32 (IntToInt); +- _68 = Lt(move _67, const 64_u32); +- assert(move _68, "attempt to shift left by `{}`, which would overflow", const 0_i32) -> [success: bb30, unwind unreachable]; ++ assert(_63, "attempt to shift left by `{}`, which would overflow", const 0_i32) -> [success: bb30, unwind unreachable]; + } + + bb30: { +- _65 = Shl(move _66, const 0_i32); +- StorageDead(_66); ++ _65 = Shl(_1, const 0_i32); + _64 = opaque::<u64>(move _65) -> [return: bb31, unwind unreachable]; + } + + bb31: { + StorageDead(_65); + StorageDead(_64); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff new file mode 100644 index 00000000000..7813c29b962 --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic_checked.GVN.panic-unwind.diff @@ -0,0 +1,389 @@ +- // MIR for `arithmetic_checked` before GVN ++ // MIR for `arithmetic_checked` after GVN + + fn arithmetic_checked(_1: u64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: u64; + let mut _4: u64; + let mut _5: (u64, bool); + let _6: (); + let mut _7: u64; + let mut _8: u64; + let mut _9: (u64, bool); + let _10: (); + let mut _11: u64; + let mut _12: u64; + let mut _13: (u64, bool); + let _14: (); + let mut _15: u64; + let mut _16: u64; + let mut _17: (u64, bool); + let _18: (); + let mut _19: u64; + let mut _20: u64; + let mut _21: bool; + let _22: (); + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: bool; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: bool; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: bool; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: bool; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: bool; + let _46: (); + let mut _47: u64; + let mut _48: u64; + let mut _49: bool; + let _50: (); + let mut _51: u64; + let mut _52: u64; + let _53: (); + let mut _54: u64; + let mut _55: u64; + let _56: (); + let mut _57: u64; + let mut _58: u64; + let _59: (); + let mut _60: u64; + let mut _61: u64; + let mut _62: u32; + let mut _63: bool; + let _64: (); + let mut _65: u64; + let mut _66: u64; + let mut _67: u32; + let mut _68: bool; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _5 = CheckedAdd(_4, const 0_u64); +- assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", move _4, const 0_u64) -> [success: bb1, unwind continue]; ++ _5 = CheckedAdd(_1, const 0_u64); ++ assert(!move (_5.1: bool), "attempt to compute `{} + {}`, which would overflow", _1, const 0_u64) -> [success: bb1, unwind continue]; + } + + bb1: { + _3 = move (_5.0: u64); +- StorageDead(_4); + _2 = opaque::<u64>(move _3) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_6); + StorageLive(_7); +- StorageLive(_8); +- _8 = _1; +- _9 = CheckedSub(_8, const 0_u64); +- assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", move _8, const 0_u64) -> [success: bb3, unwind continue]; ++ _9 = CheckedSub(_1, const 0_u64); ++ assert(!move (_9.1: bool), "attempt to compute `{} - {}`, which would overflow", _1, const 0_u64) -> [success: bb3, unwind continue]; + } + + bb3: { + _7 = move (_9.0: u64); +- StorageDead(_8); + _6 = opaque::<u64>(move _7) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_10); + StorageLive(_11); +- StorageLive(_12); +- _12 = _1; +- _13 = CheckedMul(_12, const 0_u64); +- assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", move _12, const 0_u64) -> [success: bb5, unwind continue]; ++ _13 = CheckedMul(_1, const 0_u64); ++ assert(!move (_13.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 0_u64) -> [success: bb5, unwind continue]; + } + + bb5: { + _11 = move (_13.0: u64); +- StorageDead(_12); + _10 = opaque::<u64>(move _11) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; +- _17 = CheckedMul(_16, const 1_u64); +- assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", move _16, const 1_u64) -> [success: bb7, unwind continue]; ++ _17 = CheckedMul(_1, const 1_u64); ++ assert(!move (_17.1: bool), "attempt to compute `{} * {}`, which would overflow", _1, const 1_u64) -> [success: bb7, unwind continue]; + } + + bb7: { + _15 = move (_17.0: u64); +- StorageDead(_16); + _14 = opaque::<u64>(move _15) -> [return: bb8, unwind continue]; + } + + bb8: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_18); + StorageLive(_19); +- StorageLive(_20); +- _20 = _1; + _21 = Eq(const 0_u64, const 0_u64); +- assert(!move _21, "attempt to divide `{}` by zero", _20) -> [success: bb9, unwind continue]; ++ assert(!_21, "attempt to divide `{}` by zero", _1) -> [success: bb9, unwind continue]; + } + + bb9: { +- _19 = Div(move _20, const 0_u64); +- StorageDead(_20); ++ _19 = Div(_1, const 0_u64); + _18 = opaque::<u64>(move _19) -> [return: bb10, unwind continue]; + } + + bb10: { + StorageDead(_19); + StorageDead(_18); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; + _25 = Eq(const 1_u64, const 0_u64); +- assert(!move _25, "attempt to divide `{}` by zero", _24) -> [success: bb11, unwind continue]; ++ assert(!_25, "attempt to divide `{}` by zero", _1) -> [success: bb11, unwind continue]; + } + + bb11: { +- _23 = Div(move _24, const 1_u64); +- StorageDead(_24); ++ _23 = Div(_1, const 1_u64); + _22 = opaque::<u64>(move _23) -> [return: bb12, unwind continue]; + } + + bb12: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_26); + StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- _29 = Eq(_28, const 0_u64); +- assert(!move _29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb13, unwind continue]; ++ _29 = Eq(_1, const 0_u64); ++ assert(!_29, "attempt to divide `{}` by zero", const 0_u64) -> [success: bb13, unwind continue]; + } + + bb13: { +- _27 = Div(const 0_u64, move _28); +- StorageDead(_28); ++ _27 = Div(const 0_u64, _1); + _26 = opaque::<u64>(move _27) -> [return: bb14, unwind continue]; + } + + bb14: { + StorageDead(_27); + StorageDead(_26); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _33 = Eq(_32, const 0_u64); +- assert(!move _33, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb15, unwind continue]; ++ assert(!_29, "attempt to divide `{}` by zero", const 1_u64) -> [success: bb15, unwind continue]; + } + + bb15: { +- _31 = Div(const 1_u64, move _32); +- StorageDead(_32); ++ _31 = Div(const 1_u64, _1); + _30 = opaque::<u64>(move _31) -> [return: bb16, unwind continue]; + } + + bb16: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_34); + StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- _37 = Eq(const 0_u64, const 0_u64); +- assert(!move _37, "attempt to calculate the remainder of `{}` with a divisor of zero", _36) -> [success: bb17, unwind continue]; ++ assert(!_21, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb17, unwind continue]; + } + + bb17: { +- _35 = Rem(move _36, const 0_u64); +- StorageDead(_36); ++ _35 = Rem(_1, const 0_u64); + _34 = opaque::<u64>(move _35) -> [return: bb18, unwind continue]; + } + + bb18: { + StorageDead(_35); + StorageDead(_34); + StorageLive(_38); + StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- _41 = Eq(const 1_u64, const 0_u64); +- assert(!move _41, "attempt to calculate the remainder of `{}` with a divisor of zero", _40) -> [success: bb19, unwind continue]; ++ assert(!_25, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb19, unwind continue]; + } + + bb19: { +- _39 = Rem(move _40, const 1_u64); +- StorageDead(_40); ++ _39 = Rem(_1, const 1_u64); + _38 = opaque::<u64>(move _39) -> [return: bb20, unwind continue]; + } + + bb20: { + StorageDead(_39); + StorageDead(_38); + StorageLive(_42); + StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- _45 = Eq(_44, const 0_u64); +- assert(!move _45, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb21, unwind continue]; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 0_u64) -> [success: bb21, unwind continue]; + } + + bb21: { +- _43 = Rem(const 0_u64, move _44); +- StorageDead(_44); ++ _43 = Rem(const 0_u64, _1); + _42 = opaque::<u64>(move _43) -> [return: bb22, unwind continue]; + } + + bb22: { + StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _49 = Eq(_48, const 0_u64); +- assert(!move _49, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb23, unwind continue]; ++ assert(!_29, "attempt to calculate the remainder of `{}` with a divisor of zero", const 1_u64) -> [success: bb23, unwind continue]; + } + + bb23: { +- _47 = Rem(const 1_u64, move _48); +- StorageDead(_48); ++ _47 = Rem(const 1_u64, _1); + _46 = opaque::<u64>(move _47) -> [return: bb24, unwind continue]; + } + + bb24: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_50); + StorageLive(_51); +- StorageLive(_52); +- _52 = _1; +- _51 = BitAnd(move _52, const 0_u64); +- StorageDead(_52); ++ _51 = BitAnd(_1, const 0_u64); + _50 = opaque::<u64>(move _51) -> [return: bb25, unwind continue]; + } + + bb25: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_53); + StorageLive(_54); +- StorageLive(_55); +- _55 = _1; +- _54 = BitOr(move _55, const 0_u64); +- StorageDead(_55); ++ _54 = BitOr(_1, const 0_u64); + _53 = opaque::<u64>(move _54) -> [return: bb26, unwind continue]; + } + + bb26: { + StorageDead(_54); + StorageDead(_53); + StorageLive(_56); + StorageLive(_57); +- StorageLive(_58); +- _58 = _1; +- _57 = BitXor(move _58, const 0_u64); +- StorageDead(_58); ++ _57 = BitXor(_1, const 0_u64); + _56 = opaque::<u64>(move _57) -> [return: bb27, unwind continue]; + } + + bb27: { + StorageDead(_57); + StorageDead(_56); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- _61 = _1; + _62 = const 0_i32 as u32 (IntToInt); +- _63 = Lt(move _62, const 64_u32); +- assert(move _63, "attempt to shift right by `{}`, which would overflow", const 0_i32) -> [success: bb28, unwind continue]; ++ _63 = Lt(_62, const 64_u32); ++ assert(_63, "attempt to shift right by `{}`, which would overflow", const 0_i32) -> [success: bb28, unwind continue]; + } + + bb28: { +- _60 = Shr(move _61, const 0_i32); +- StorageDead(_61); ++ _60 = Shr(_1, const 0_i32); + _59 = opaque::<u64>(move _60) -> [return: bb29, unwind continue]; + } + + bb29: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_64); + StorageLive(_65); +- StorageLive(_66); +- _66 = _1; +- _67 = const 0_i32 as u32 (IntToInt); +- _68 = Lt(move _67, const 64_u32); +- assert(move _68, "attempt to shift left by `{}`, which would overflow", const 0_i32) -> [success: bb30, unwind continue]; ++ assert(_63, "attempt to shift left by `{}`, which would overflow", const 0_i32) -> [success: bb30, unwind continue]; + } + + bb30: { +- _65 = Shl(move _66, const 0_i32); +- StorageDead(_66); ++ _65 = Shl(_1, const 0_i32); + _64 = opaque::<u64>(move _65) -> [return: bb31, unwind continue]; + } + + bb31: { + StorageDead(_65); + StorageDead(_64); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.arithmetic_float.GVN.panic-abort.diff b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-abort.diff new file mode 100644 index 00000000000..7d5ac8353fe --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-abort.diff @@ -0,0 +1,165 @@ +- // MIR for `arithmetic_float` before GVN ++ // MIR for `arithmetic_float` after GVN + + fn arithmetic_float(_1: f64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: f64; + let mut _4: f64; + let _5: (); + let mut _6: f64; + let mut _7: f64; + let _8: (); + let mut _9: f64; + let mut _10: f64; + let _11: (); + let mut _12: f64; + let mut _13: f64; + let _14: (); + let mut _15: f64; + let mut _16: f64; + let _17: (); + let mut _18: f64; + let mut _19: f64; + let _20: (); + let mut _21: f64; + let mut _22: f64; + let _23: (); + let mut _24: bool; + let mut _25: f64; + let mut _26: f64; + let _27: (); + let mut _28: bool; + let mut _29: f64; + let mut _30: f64; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = Add(move _4, const 0f64); +- StorageDead(_4); ++ _3 = Add(_1, const 0f64); + _2 = opaque::<f64>(move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_5); + StorageLive(_6); +- StorageLive(_7); +- _7 = _1; +- _6 = Sub(move _7, const 0f64); +- StorageDead(_7); ++ _6 = Sub(_1, const 0f64); + _5 = opaque::<f64>(move _6) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_6); + StorageDead(_5); + StorageLive(_8); + StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- _9 = Mul(move _10, const 0f64); +- StorageDead(_10); ++ _9 = Mul(_1, const 0f64); + _8 = opaque::<f64>(move _9) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_11); + StorageLive(_12); +- StorageLive(_13); +- _13 = _1; +- _12 = Div(move _13, const 0f64); +- StorageDead(_13); ++ _12 = Div(_1, const 0f64); + _11 = opaque::<f64>(move _12) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; +- _15 = Div(const 0f64, move _16); +- StorageDead(_16); ++ _15 = Div(const 0f64, _1); + _14 = opaque::<f64>(move _15) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_17); + StorageLive(_18); +- StorageLive(_19); +- _19 = _1; +- _18 = Rem(move _19, const 0f64); +- StorageDead(_19); ++ _18 = Rem(_1, const 0f64); + _17 = opaque::<f64>(move _18) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_18); + StorageDead(_17); + StorageLive(_20); + StorageLive(_21); +- StorageLive(_22); +- _22 = _1; +- _21 = Rem(const 0f64, move _22); +- StorageDead(_22); ++ _21 = Rem(const 0f64, _1); + _20 = opaque::<f64>(move _21) -> [return: bb7, unwind unreachable]; + } + + bb7: { + StorageDead(_21); + StorageDead(_20); + StorageLive(_23); + StorageLive(_24); +- StorageLive(_25); +- _25 = _1; +- StorageLive(_26); +- _26 = _1; +- _24 = Eq(move _25, move _26); +- StorageDead(_26); +- StorageDead(_25); ++ _24 = Eq(_1, _1); + _23 = opaque::<bool>(move _24) -> [return: bb8, unwind unreachable]; + } + + bb8: { + StorageDead(_24); + StorageDead(_23); + StorageLive(_27); + StorageLive(_28); +- StorageLive(_29); +- _29 = _1; +- StorageLive(_30); +- _30 = _1; +- _28 = Ne(move _29, move _30); +- StorageDead(_30); +- StorageDead(_29); ++ _28 = Ne(_1, _1); + _27 = opaque::<bool>(move _28) -> [return: bb9, unwind unreachable]; + } + + bb9: { + StorageDead(_28); + StorageDead(_27); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.arithmetic_float.GVN.panic-unwind.diff b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-unwind.diff new file mode 100644 index 00000000000..36c26dc6605 --- /dev/null +++ b/tests/mir-opt/gvn.arithmetic_float.GVN.panic-unwind.diff @@ -0,0 +1,165 @@ +- // MIR for `arithmetic_float` before GVN ++ // MIR for `arithmetic_float` after GVN + + fn arithmetic_float(_1: f64) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: f64; + let mut _4: f64; + let _5: (); + let mut _6: f64; + let mut _7: f64; + let _8: (); + let mut _9: f64; + let mut _10: f64; + let _11: (); + let mut _12: f64; + let mut _13: f64; + let _14: (); + let mut _15: f64; + let mut _16: f64; + let _17: (); + let mut _18: f64; + let mut _19: f64; + let _20: (); + let mut _21: f64; + let mut _22: f64; + let _23: (); + let mut _24: bool; + let mut _25: f64; + let mut _26: f64; + let _27: (); + let mut _28: bool; + let mut _29: f64; + let mut _30: f64; + + bb0: { + StorageLive(_2); + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = Add(move _4, const 0f64); +- StorageDead(_4); ++ _3 = Add(_1, const 0f64); + _2 = opaque::<f64>(move _3) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_5); + StorageLive(_6); +- StorageLive(_7); +- _7 = _1; +- _6 = Sub(move _7, const 0f64); +- StorageDead(_7); ++ _6 = Sub(_1, const 0f64); + _5 = opaque::<f64>(move _6) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_6); + StorageDead(_5); + StorageLive(_8); + StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- _9 = Mul(move _10, const 0f64); +- StorageDead(_10); ++ _9 = Mul(_1, const 0f64); + _8 = opaque::<f64>(move _9) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_11); + StorageLive(_12); +- StorageLive(_13); +- _13 = _1; +- _12 = Div(move _13, const 0f64); +- StorageDead(_13); ++ _12 = Div(_1, const 0f64); + _11 = opaque::<f64>(move _12) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_14); + StorageLive(_15); +- StorageLive(_16); +- _16 = _1; +- _15 = Div(const 0f64, move _16); +- StorageDead(_16); ++ _15 = Div(const 0f64, _1); + _14 = opaque::<f64>(move _15) -> [return: bb5, unwind continue]; + } + + bb5: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_17); + StorageLive(_18); +- StorageLive(_19); +- _19 = _1; +- _18 = Rem(move _19, const 0f64); +- StorageDead(_19); ++ _18 = Rem(_1, const 0f64); + _17 = opaque::<f64>(move _18) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_18); + StorageDead(_17); + StorageLive(_20); + StorageLive(_21); +- StorageLive(_22); +- _22 = _1; +- _21 = Rem(const 0f64, move _22); +- StorageDead(_22); ++ _21 = Rem(const 0f64, _1); + _20 = opaque::<f64>(move _21) -> [return: bb7, unwind continue]; + } + + bb7: { + StorageDead(_21); + StorageDead(_20); + StorageLive(_23); + StorageLive(_24); +- StorageLive(_25); +- _25 = _1; +- StorageLive(_26); +- _26 = _1; +- _24 = Eq(move _25, move _26); +- StorageDead(_26); +- StorageDead(_25); ++ _24 = Eq(_1, _1); + _23 = opaque::<bool>(move _24) -> [return: bb8, unwind continue]; + } + + bb8: { + StorageDead(_24); + StorageDead(_23); + StorageLive(_27); + StorageLive(_28); +- StorageLive(_29); +- _29 = _1; +- StorageLive(_30); +- _30 = _1; +- _28 = Ne(move _29, move _30); +- StorageDead(_30); +- StorageDead(_29); ++ _28 = Ne(_1, _1); + _27 = opaque::<bool>(move _28) -> [return: bb9, unwind continue]; + } + + bb9: { + StorageDead(_28); + StorageDead(_27); + _0 = const (); + return; + } + } + diff --git a/tests/mir-opt/gvn.cast.GVN.panic-abort.diff b/tests/mir-opt/gvn.cast.GVN.panic-abort.diff new file mode 100644 index 00000000000..513fe60b65d --- /dev/null +++ b/tests/mir-opt/gvn.cast.GVN.panic-abort.diff @@ -0,0 +1,501 @@ +- // MIR for `cast` before GVN ++ // MIR for `cast` after GVN + + fn cast() -> () { + let mut _0: (); + let _1: i64; + let _4: (); + let mut _5: u8; + let mut _6: i64; + let _7: (); + let mut _8: u16; + let mut _9: i64; + let _10: (); + let mut _11: u32; + let mut _12: i64; + let _13: (); + let mut _14: u64; + let mut _15: i64; + let _16: (); + let mut _17: i8; + let mut _18: i64; + let _19: (); + let mut _20: i16; + let mut _21: i64; + let _22: (); + let mut _23: i32; + let mut _24: i64; + let _25: (); + let mut _26: i64; + let _27: (); + let mut _28: f32; + let mut _29: i64; + let _30: (); + let mut _31: f64; + let mut _32: i64; + let _33: (); + let mut _34: u8; + let mut _35: u64; + let _36: (); + let mut _37: u16; + let mut _38: u64; + let _39: (); + let mut _40: u32; + let mut _41: u64; + let _42: (); + let mut _43: u64; + let _44: (); + let mut _45: i8; + let mut _46: u64; + let _47: (); + let mut _48: i16; + let mut _49: u64; + let _50: (); + let mut _51: i32; + let mut _52: u64; + let _53: (); + let mut _54: i64; + let mut _55: u64; + let _56: (); + let mut _57: f32; + let mut _58: u64; + let _59: (); + let mut _60: f64; + let mut _61: u64; + let _62: (); + let mut _63: u8; + let mut _64: f64; + let _65: (); + let mut _66: u16; + let mut _67: f64; + let _68: (); + let mut _69: u32; + let mut _70: f64; + let _71: (); + let mut _72: u64; + let mut _73: f64; + let _74: (); + let mut _75: i8; + let mut _76: f64; + let _77: (); + let mut _78: i16; + let mut _79: f64; + let _80: (); + let mut _81: i32; + let mut _82: f64; + let _83: (); + let mut _84: i64; + let mut _85: f64; + let _86: (); + let mut _87: f32; + let mut _88: f64; + let _89: (); + let mut _90: f64; + scope 1 { + debug i => _1; + let _2: u64; + scope 2 { + debug u => _2; + let _3: f64; + scope 3 { + debug f => _3; + } + } + } + + bb0: { +- StorageLive(_1); + _1 = const 1_i64; +- StorageLive(_2); + _2 = const 1_u64; +- StorageLive(_3); + _3 = const 1f64; + StorageLive(_4); + StorageLive(_5); +- StorageLive(_6); +- _6 = _1; +- _5 = move _6 as u8 (IntToInt); +- StorageDead(_6); ++ _5 = const 1_i64 as u8 (IntToInt); + _4 = opaque::<u8>(move _5) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_7); + StorageLive(_8); +- StorageLive(_9); +- _9 = _1; +- _8 = move _9 as u16 (IntToInt); +- StorageDead(_9); ++ _8 = const 1_i64 as u16 (IntToInt); + _7 = opaque::<u16>(move _8) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_8); + StorageDead(_7); + StorageLive(_10); + StorageLive(_11); +- StorageLive(_12); +- _12 = _1; +- _11 = move _12 as u32 (IntToInt); +- StorageDead(_12); ++ _11 = const 1_i64 as u32 (IntToInt); + _10 = opaque::<u32>(move _11) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_13); + StorageLive(_14); +- StorageLive(_15); +- _15 = _1; +- _14 = move _15 as u64 (IntToInt); +- StorageDead(_15); ++ _14 = const 1_i64 as u64 (IntToInt); + _13 = opaque::<u64>(move _14) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_14); + StorageDead(_13); + StorageLive(_16); + StorageLive(_17); +- StorageLive(_18); +- _18 = _1; +- _17 = move _18 as i8 (IntToInt); +- StorageDead(_18); ++ _17 = const 1_i64 as i8 (IntToInt); + _16 = opaque::<i8>(move _17) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_17); + StorageDead(_16); + StorageLive(_19); + StorageLive(_20); +- StorageLive(_21); +- _21 = _1; +- _20 = move _21 as i16 (IntToInt); +- StorageDead(_21); ++ _20 = const 1_i64 as i16 (IntToInt); + _19 = opaque::<i16>(move _20) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_20); + StorageDead(_19); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; +- _23 = move _24 as i32 (IntToInt); +- StorageDead(_24); ++ _23 = const 1_i64 as i32 (IntToInt); + _22 = opaque::<i32>(move _23) -> [return: bb7, unwind unreachable]; + } + + bb7: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_25); +- StorageLive(_26); +- _26 = _1; +- _25 = opaque::<i64>(move _26) -> [return: bb8, unwind unreachable]; ++ _25 = opaque::<i64>(const 1_i64) -> [return: bb8, unwind unreachable]; + } + + bb8: { +- StorageDead(_26); + StorageDead(_25); + StorageLive(_27); + StorageLive(_28); +- StorageLive(_29); +- _29 = _1; +- _28 = move _29 as f32 (IntToFloat); +- StorageDead(_29); ++ _28 = const 1_i64 as f32 (IntToFloat); + _27 = opaque::<f32>(move _28) -> [return: bb9, unwind unreachable]; + } + + bb9: { + StorageDead(_28); + StorageDead(_27); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _31 = move _32 as f64 (IntToFloat); +- StorageDead(_32); ++ _31 = const 1_i64 as f64 (IntToFloat); + _30 = opaque::<f64>(move _31) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_33); + StorageLive(_34); +- StorageLive(_35); +- _35 = _2; +- _34 = move _35 as u8 (IntToInt); +- StorageDead(_35); ++ _34 = const 1_u64 as u8 (IntToInt); + _33 = opaque::<u8>(move _34) -> [return: bb11, unwind unreachable]; + } + + bb11: { + StorageDead(_34); + StorageDead(_33); + StorageLive(_36); + StorageLive(_37); +- StorageLive(_38); +- _38 = _2; +- _37 = move _38 as u16 (IntToInt); +- StorageDead(_38); ++ _37 = const 1_u64 as u16 (IntToInt); + _36 = opaque::<u16>(move _37) -> [return: bb12, unwind unreachable]; + } + + bb12: { + StorageDead(_37); + StorageDead(_36); + StorageLive(_39); + StorageLive(_40); +- StorageLive(_41); +- _41 = _2; +- _40 = move _41 as u32 (IntToInt); +- StorageDead(_41); ++ _40 = const 1_u64 as u32 (IntToInt); + _39 = opaque::<u32>(move _40) -> [return: bb13, unwind unreachable]; + } + + bb13: { + StorageDead(_40); + StorageDead(_39); + StorageLive(_42); +- StorageLive(_43); +- _43 = _2; +- _42 = opaque::<u64>(move _43) -> [return: bb14, unwind unreachable]; ++ _42 = opaque::<u64>(const 1_u64) -> [return: bb14, unwind unreachable]; + } + + bb14: { +- StorageDead(_43); + StorageDead(_42); + StorageLive(_44); + StorageLive(_45); +- StorageLive(_46); +- _46 = _2; +- _45 = move _46 as i8 (IntToInt); +- StorageDead(_46); ++ _45 = const 1_u64 as i8 (IntToInt); + _44 = opaque::<i8>(move _45) -> [return: bb15, unwind unreachable]; + } + + bb15: { + StorageDead(_45); + StorageDead(_44); + StorageLive(_47); + StorageLive(_48); +- StorageLive(_49); +- _49 = _2; +- _48 = move _49 as i16 (IntToInt); +- StorageDead(_49); ++ _48 = const 1_u64 as i16 (IntToInt); + _47 = opaque::<i16>(move _48) -> [return: bb16, unwind unreachable]; + } + + bb16: { + StorageDead(_48); + StorageDead(_47); + StorageLive(_50); + StorageLive(_51); +- StorageLive(_52); +- _52 = _2; +- _51 = move _52 as i32 (IntToInt); +- StorageDead(_52); ++ _51 = const 1_u64 as i32 (IntToInt); + _50 = opaque::<i32>(move _51) -> [return: bb17, unwind unreachable]; + } + + bb17: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_53); + StorageLive(_54); +- StorageLive(_55); +- _55 = _2; +- _54 = move _55 as i64 (IntToInt); +- StorageDead(_55); ++ _54 = const 1_u64 as i64 (IntToInt); + _53 = opaque::<i64>(move _54) -> [return: bb18, unwind unreachable]; + } + + bb18: { + StorageDead(_54); + StorageDead(_53); + StorageLive(_56); + StorageLive(_57); +- StorageLive(_58); +- _58 = _2; +- _57 = move _58 as f32 (IntToFloat); +- StorageDead(_58); ++ _57 = const 1_u64 as f32 (IntToFloat); + _56 = opaque::<f32>(move _57) -> [return: bb19, unwind unreachable]; + } + + bb19: { + StorageDead(_57); + StorageDead(_56); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- _61 = _2; +- _60 = move _61 as f64 (IntToFloat); +- StorageDead(_61); ++ _60 = const 1_u64 as f64 (IntToFloat); + _59 = opaque::<f64>(move _60) -> [return: bb20, unwind unreachable]; + } + + bb20: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_62); + StorageLive(_63); +- StorageLive(_64); +- _64 = _3; +- _63 = move _64 as u8 (FloatToInt); +- StorageDead(_64); ++ _63 = const 1f64 as u8 (FloatToInt); + _62 = opaque::<u8>(move _63) -> [return: bb21, unwind unreachable]; + } + + bb21: { + StorageDead(_63); + StorageDead(_62); + StorageLive(_65); + StorageLive(_66); +- StorageLive(_67); +- _67 = _3; +- _66 = move _67 as u16 (FloatToInt); +- StorageDead(_67); ++ _66 = const 1f64 as u16 (FloatToInt); + _65 = opaque::<u16>(move _66) -> [return: bb22, unwind unreachable]; + } + + bb22: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_68); + StorageLive(_69); +- StorageLive(_70); +- _70 = _3; +- _69 = move _70 as u32 (FloatToInt); +- StorageDead(_70); ++ _69 = const 1f64 as u32 (FloatToInt); + _68 = opaque::<u32>(move _69) -> [return: bb23, unwind unreachable]; + } + + bb23: { + StorageDead(_69); + StorageDead(_68); + StorageLive(_71); + StorageLive(_72); +- StorageLive(_73); +- _73 = _3; +- _72 = move _73 as u64 (FloatToInt); +- StorageDead(_73); ++ _72 = const 1f64 as u64 (FloatToInt); + _71 = opaque::<u64>(move _72) -> [return: bb24, unwind unreachable]; + } + + bb24: { + StorageDead(_72); + StorageDead(_71); + StorageLive(_74); + StorageLive(_75); +- StorageLive(_76); +- _76 = _3; +- _75 = move _76 as i8 (FloatToInt); +- StorageDead(_76); ++ _75 = const 1f64 as i8 (FloatToInt); + _74 = opaque::<i8>(move _75) -> [return: bb25, unwind unreachable]; + } + + bb25: { + StorageDead(_75); + StorageDead(_74); + StorageLive(_77); + StorageLive(_78); +- StorageLive(_79); +- _79 = _3; +- _78 = move _79 as i16 (FloatToInt); +- StorageDead(_79); ++ _78 = const 1f64 as i16 (FloatToInt); + _77 = opaque::<i16>(move _78) -> [return: bb26, unwind unreachable]; + } + + bb26: { + StorageDead(_78); + StorageDead(_77); + StorageLive(_80); + StorageLive(_81); +- StorageLive(_82); +- _82 = _3; +- _81 = move _82 as i32 (FloatToInt); +- StorageDead(_82); ++ _81 = const 1f64 as i32 (FloatToInt); + _80 = opaque::<i32>(move _81) -> [return: bb27, unwind unreachable]; + } + + bb27: { + StorageDead(_81); + StorageDead(_80); + StorageLive(_83); + StorageLive(_84); +- StorageLive(_85); +- _85 = _3; +- _84 = move _85 as i64 (FloatToInt); +- StorageDead(_85); ++ _84 = const 1f64 as i64 (FloatToInt); + _83 = opaque::<i64>(move _84) -> [return: bb28, unwind unreachable]; + } + + bb28: { + StorageDead(_84); + StorageDead(_83); + StorageLive(_86); + StorageLive(_87); +- StorageLive(_88); +- _88 = _3; +- _87 = move _88 as f32 (FloatToFloat); +- StorageDead(_88); ++ _87 = const 1f64 as f32 (FloatToFloat); + _86 = opaque::<f32>(move _87) -> [return: bb29, unwind unreachable]; + } + + bb29: { + StorageDead(_87); + StorageDead(_86); + StorageLive(_89); +- StorageLive(_90); +- _90 = _3; +- _89 = opaque::<f64>(move _90) -> [return: bb30, unwind unreachable]; ++ _89 = opaque::<f64>(const 1f64) -> [return: bb30, unwind unreachable]; + } + + bb30: { +- StorageDead(_90); + StorageDead(_89); + _0 = const (); +- StorageDead(_3); +- StorageDead(_2); +- StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/gvn.cast.GVN.panic-unwind.diff b/tests/mir-opt/gvn.cast.GVN.panic-unwind.diff new file mode 100644 index 00000000000..33192ed8de0 --- /dev/null +++ b/tests/mir-opt/gvn.cast.GVN.panic-unwind.diff @@ -0,0 +1,501 @@ +- // MIR for `cast` before GVN ++ // MIR for `cast` after GVN + + fn cast() -> () { + let mut _0: (); + let _1: i64; + let _4: (); + let mut _5: u8; + let mut _6: i64; + let _7: (); + let mut _8: u16; + let mut _9: i64; + let _10: (); + let mut _11: u32; + let mut _12: i64; + let _13: (); + let mut _14: u64; + let mut _15: i64; + let _16: (); + let mut _17: i8; + let mut _18: i64; + let _19: (); + let mut _20: i16; + let mut _21: i64; + let _22: (); + let mut _23: i32; + let mut _24: i64; + let _25: (); + let mut _26: i64; + let _27: (); + let mut _28: f32; + let mut _29: i64; + let _30: (); + let mut _31: f64; + let mut _32: i64; + let _33: (); + let mut _34: u8; + let mut _35: u64; + let _36: (); + let mut _37: u16; + let mut _38: u64; + let _39: (); + let mut _40: u32; + let mut _41: u64; + let _42: (); + let mut _43: u64; + let _44: (); + let mut _45: i8; + let mut _46: u64; + let _47: (); + let mut _48: i16; + let mut _49: u64; + let _50: (); + let mut _51: i32; + let mut _52: u64; + let _53: (); + let mut _54: i64; + let mut _55: u64; + let _56: (); + let mut _57: f32; + let mut _58: u64; + let _59: (); + let mut _60: f64; + let mut _61: u64; + let _62: (); + let mut _63: u8; + let mut _64: f64; + let _65: (); + let mut _66: u16; + let mut _67: f64; + let _68: (); + let mut _69: u32; + let mut _70: f64; + let _71: (); + let mut _72: u64; + let mut _73: f64; + let _74: (); + let mut _75: i8; + let mut _76: f64; + let _77: (); + let mut _78: i16; + let mut _79: f64; + let _80: (); + let mut _81: i32; + let mut _82: f64; + let _83: (); + let mut _84: i64; + let mut _85: f64; + let _86: (); + let mut _87: f32; + let mut _88: f64; + let _89: (); + let mut _90: f64; + scope 1 { + debug i => _1; + let _2: u64; + scope 2 { + debug u => _2; + let _3: f64; + scope 3 { + debug f => _3; + } + } + } + + bb0: { +- StorageLive(_1); + _1 = const 1_i64; +- StorageLive(_2); + _2 = const 1_u64; +- StorageLive(_3); + _3 = const 1f64; + StorageLive(_4); + StorageLive(_5); +- StorageLive(_6); +- _6 = _1; +- _5 = move _6 as u8 (IntToInt); +- StorageDead(_6); ++ _5 = const 1_i64 as u8 (IntToInt); + _4 = opaque::<u8>(move _5) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_7); + StorageLive(_8); +- StorageLive(_9); +- _9 = _1; +- _8 = move _9 as u16 (IntToInt); +- StorageDead(_9); ++ _8 = const 1_i64 as u16 (IntToInt); + _7 = opaque::<u16>(move _8) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_8); + StorageDead(_7); + StorageLive(_10); + StorageLive(_11); +- StorageLive(_12); +- _12 = _1; +- _11 = move _12 as u32 (IntToInt); +- StorageDead(_12); ++ _11 = const 1_i64 as u32 (IntToInt); + _10 = opaque::<u32>(move _11) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_13); + StorageLive(_14); +- StorageLive(_15); +- _15 = _1; +- _14 = move _15 as u64 (IntToInt); +- StorageDead(_15); ++ _14 = const 1_i64 as u64 (IntToInt); + _13 = opaque::<u64>(move _14) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_14); + StorageDead(_13); + StorageLive(_16); + StorageLive(_17); +- StorageLive(_18); +- _18 = _1; +- _17 = move _18 as i8 (IntToInt); +- StorageDead(_18); ++ _17 = const 1_i64 as i8 (IntToInt); + _16 = opaque::<i8>(move _17) -> [return: bb5, unwind continue]; + } + + bb5: { + StorageDead(_17); + StorageDead(_16); + StorageLive(_19); + StorageLive(_20); +- StorageLive(_21); +- _21 = _1; +- _20 = move _21 as i16 (IntToInt); +- StorageDead(_21); ++ _20 = const 1_i64 as i16 (IntToInt); + _19 = opaque::<i16>(move _20) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_20); + StorageDead(_19); + StorageLive(_22); + StorageLive(_23); +- StorageLive(_24); +- _24 = _1; +- _23 = move _24 as i32 (IntToInt); +- StorageDead(_24); ++ _23 = const 1_i64 as i32 (IntToInt); + _22 = opaque::<i32>(move _23) -> [return: bb7, unwind continue]; + } + + bb7: { + StorageDead(_23); + StorageDead(_22); + StorageLive(_25); +- StorageLive(_26); +- _26 = _1; +- _25 = opaque::<i64>(move _26) -> [return: bb8, unwind continue]; ++ _25 = opaque::<i64>(const 1_i64) -> [return: bb8, unwind continue]; + } + + bb8: { +- StorageDead(_26); + StorageDead(_25); + StorageLive(_27); + StorageLive(_28); +- StorageLive(_29); +- _29 = _1; +- _28 = move _29 as f32 (IntToFloat); +- StorageDead(_29); ++ _28 = const 1_i64 as f32 (IntToFloat); + _27 = opaque::<f32>(move _28) -> [return: bb9, unwind continue]; + } + + bb9: { + StorageDead(_28); + StorageDead(_27); + StorageLive(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- _31 = move _32 as f64 (IntToFloat); +- StorageDead(_32); ++ _31 = const 1_i64 as f64 (IntToFloat); + _30 = opaque::<f64>(move _31) -> [return: bb10, unwind continue]; + } + + bb10: { + StorageDead(_31); + StorageDead(_30); + StorageLive(_33); + StorageLive(_34); +- StorageLive(_35); +- _35 = _2; +- _34 = move _35 as u8 (IntToInt); +- StorageDead(_35); ++ _34 = const 1_u64 as u8 (IntToInt); + _33 = opaque::<u8>(move _34) -> [return: bb11, unwind continue]; + } + + bb11: { + StorageDead(_34); + StorageDead(_33); + StorageLive(_36); + StorageLive(_37); +- StorageLive(_38); +- _38 = _2; +- _37 = move _38 as u16 (IntToInt); +- StorageDead(_38); ++ _37 = const 1_u64 as u16 (IntToInt); + _36 = opaque::<u16>(move _37) -> [return: bb12, unwind continue]; + } + + bb12: { + StorageDead(_37); + StorageDead(_36); + StorageLive(_39); + StorageLive(_40); +- StorageLive(_41); +- _41 = _2; +- _40 = move _41 as u32 (IntToInt); +- StorageDead(_41); ++ _40 = const 1_u64 as u32 (IntToInt); + _39 = opaque::<u32>(move _40) -> [return: bb13, unwind continue]; + } + + bb13: { + StorageDead(_40); + StorageDead(_39); + StorageLive(_42); +- StorageLive(_43); +- _43 = _2; +- _42 = opaque::<u64>(move _43) -> [return: bb14, unwind continue]; ++ _42 = opaque::<u64>(const 1_u64) -> [return: bb14, unwind continue]; + } + + bb14: { +- StorageDead(_43); + StorageDead(_42); + StorageLive(_44); + StorageLive(_45); +- StorageLive(_46); +- _46 = _2; +- _45 = move _46 as i8 (IntToInt); +- StorageDead(_46); ++ _45 = const 1_u64 as i8 (IntToInt); + _44 = opaque::<i8>(move _45) -> [return: bb15, unwind continue]; + } + + bb15: { + StorageDead(_45); + StorageDead(_44); + StorageLive(_47); + StorageLive(_48); +- StorageLive(_49); +- _49 = _2; +- _48 = move _49 as i16 (IntToInt); +- StorageDead(_49); ++ _48 = const 1_u64 as i16 (IntToInt); + _47 = opaque::<i16>(move _48) -> [return: bb16, unwind continue]; + } + + bb16: { + StorageDead(_48); + StorageDead(_47); + StorageLive(_50); + StorageLive(_51); +- StorageLive(_52); +- _52 = _2; +- _51 = move _52 as i32 (IntToInt); +- StorageDead(_52); ++ _51 = const 1_u64 as i32 (IntToInt); + _50 = opaque::<i32>(move _51) -> [return: bb17, unwind continue]; + } + + bb17: { + StorageDead(_51); + StorageDead(_50); + StorageLive(_53); + StorageLive(_54); +- StorageLive(_55); +- _55 = _2; +- _54 = move _55 as i64 (IntToInt); +- StorageDead(_55); ++ _54 = const 1_u64 as i64 (IntToInt); + _53 = opaque::<i64>(move _54) -> [return: bb18, unwind continue]; + } + + bb18: { + StorageDead(_54); + StorageDead(_53); + StorageLive(_56); + StorageLive(_57); +- StorageLive(_58); +- _58 = _2; +- _57 = move _58 as f32 (IntToFloat); +- StorageDead(_58); ++ _57 = const 1_u64 as f32 (IntToFloat); + _56 = opaque::<f32>(move _57) -> [return: bb19, unwind continue]; + } + + bb19: { + StorageDead(_57); + StorageDead(_56); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- _61 = _2; +- _60 = move _61 as f64 (IntToFloat); +- StorageDead(_61); ++ _60 = const 1_u64 as f64 (IntToFloat); + _59 = opaque::<f64>(move _60) -> [return: bb20, unwind continue]; + } + + bb20: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_62); + StorageLive(_63); +- StorageLive(_64); +- _64 = _3; +- _63 = move _64 as u8 (FloatToInt); +- StorageDead(_64); ++ _63 = const 1f64 as u8 (FloatToInt); + _62 = opaque::<u8>(move _63) -> [return: bb21, unwind continue]; + } + + bb21: { + StorageDead(_63); + StorageDead(_62); + StorageLive(_65); + StorageLive(_66); +- StorageLive(_67); +- _67 = _3; +- _66 = move _67 as u16 (FloatToInt); +- StorageDead(_67); ++ _66 = const 1f64 as u16 (FloatToInt); + _65 = opaque::<u16>(move _66) -> [return: bb22, unwind continue]; + } + + bb22: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_68); + StorageLive(_69); +- StorageLive(_70); +- _70 = _3; +- _69 = move _70 as u32 (FloatToInt); +- StorageDead(_70); ++ _69 = const 1f64 as u32 (FloatToInt); + _68 = opaque::<u32>(move _69) -> [return: bb23, unwind continue]; + } + + bb23: { + StorageDead(_69); + StorageDead(_68); + StorageLive(_71); + StorageLive(_72); +- StorageLive(_73); +- _73 = _3; +- _72 = move _73 as u64 (FloatToInt); +- StorageDead(_73); ++ _72 = const 1f64 as u64 (FloatToInt); + _71 = opaque::<u64>(move _72) -> [return: bb24, unwind continue]; + } + + bb24: { + StorageDead(_72); + StorageDead(_71); + StorageLive(_74); + StorageLive(_75); +- StorageLive(_76); +- _76 = _3; +- _75 = move _76 as i8 (FloatToInt); +- StorageDead(_76); ++ _75 = const 1f64 as i8 (FloatToInt); + _74 = opaque::<i8>(move _75) -> [return: bb25, unwind continue]; + } + + bb25: { + StorageDead(_75); + StorageDead(_74); + StorageLive(_77); + StorageLive(_78); +- StorageLive(_79); +- _79 = _3; +- _78 = move _79 as i16 (FloatToInt); +- StorageDead(_79); ++ _78 = const 1f64 as i16 (FloatToInt); + _77 = opaque::<i16>(move _78) -> [return: bb26, unwind continue]; + } + + bb26: { + StorageDead(_78); + StorageDead(_77); + StorageLive(_80); + StorageLive(_81); +- StorageLive(_82); +- _82 = _3; +- _81 = move _82 as i32 (FloatToInt); +- StorageDead(_82); ++ _81 = const 1f64 as i32 (FloatToInt); + _80 = opaque::<i32>(move _81) -> [return: bb27, unwind continue]; + } + + bb27: { + StorageDead(_81); + StorageDead(_80); + StorageLive(_83); + StorageLive(_84); +- StorageLive(_85); +- _85 = _3; +- _84 = move _85 as i64 (FloatToInt); +- StorageDead(_85); ++ _84 = const 1f64 as i64 (FloatToInt); + _83 = opaque::<i64>(move _84) -> [return: bb28, unwind continue]; + } + + bb28: { + StorageDead(_84); + StorageDead(_83); + StorageLive(_86); + StorageLive(_87); +- StorageLive(_88); +- _88 = _3; +- _87 = move _88 as f32 (FloatToFloat); +- StorageDead(_88); ++ _87 = const 1f64 as f32 (FloatToFloat); + _86 = opaque::<f32>(move _87) -> [return: bb29, unwind continue]; + } + + bb29: { + StorageDead(_87); + StorageDead(_86); + StorageLive(_89); +- StorageLive(_90); +- _90 = _3; +- _89 = opaque::<f64>(move _90) -> [return: bb30, unwind continue]; ++ _89 = opaque::<f64>(const 1f64) -> [return: bb30, unwind continue]; + } + + bb30: { +- StorageDead(_90); + StorageDead(_89); + _0 = const (); +- StorageDead(_3); +- StorageDead(_2); +- StorageDead(_1); + return; + } + } + diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff new file mode 100644 index 00000000000..ee320cf6787 --- /dev/null +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-abort.diff @@ -0,0 +1,191 @@ +- // MIR for `dereferences` before GVN ++ // MIR for `dereferences` after GVN + + fn dereferences(_1: &mut u32, _2: &impl Copy, _3: &S<u32>) -> () { + debug t => _1; + debug u => _2; + debug s => _3; + let mut _0: (); + let _4: (); + let mut _5: u32; + let _6: (); + let mut _7: u32; + let _8: *const u32; + let _9: (); + let mut _10: u32; + let _11: (); + let mut _12: u32; + let _14: (); + let mut _15: u32; + let _16: (); + let mut _17: u32; + let _19: (); + let mut _20: u32; + let _21: (); + let mut _22: u32; + let _23: (); + let mut _24: &u32; + let _25: (); + let mut _26: impl Copy; + let _27: (); + let mut _28: impl Copy; + let _29: (); + let mut _30: u32; + let _31: (); + let mut _32: u32; + scope 1 { + debug z => _8; + let _13: *mut u32; + scope 2 { + } + scope 3 { + } + scope 4 { + debug z => _13; + let _18: &u32; + scope 5 { + } + scope 6 { + } + scope 7 { + debug z => _18; + } + } + } + + bb0: { + StorageLive(_4); + StorageLive(_5); + _5 = (*_1); + _4 = opaque::<u32>(move _5) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = (*_1); + _6 = opaque::<u32>(move _7) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + _8 = &raw const (*_1); + StorageLive(_9); + StorageLive(_10); + _10 = (*_8); + _9 = opaque::<u32>(move _10) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_10); + StorageDead(_9); + StorageLive(_11); + StorageLive(_12); + _12 = (*_8); + _11 = opaque::<u32>(move _12) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_13); + _13 = &raw mut (*_1); + StorageLive(_14); + StorageLive(_15); + _15 = (*_13); + _14 = opaque::<u32>(move _15) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + _17 = (*_13); + _16 = opaque::<u32>(move _17) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_17); + StorageDead(_16); + StorageLive(_18); + _18 = &(*_1); + StorageLive(_19); +- StorageLive(_20); + _20 = (*_18); +- _19 = opaque::<u32>(move _20) -> [return: bb7, unwind unreachable]; ++ _19 = opaque::<u32>(_20) -> [return: bb7, unwind unreachable]; + } + + bb7: { +- StorageDead(_20); + StorageDead(_19); + StorageLive(_21); +- StorageLive(_22); +- _22 = (*_18); +- _21 = opaque::<u32>(move _22) -> [return: bb8, unwind unreachable]; ++ _21 = opaque::<u32>(_20) -> [return: bb8, unwind unreachable]; + } + + bb8: { +- StorageDead(_22); + StorageDead(_21); + StorageLive(_23); + StorageLive(_24); + _24 = &(*_18); + _23 = opaque::<&u32>(move _24) -> [return: bb9, unwind unreachable]; + } + + bb9: { + StorageDead(_24); + StorageDead(_23); + StorageLive(_25); + StorageLive(_26); + _26 = (*_2); + _25 = opaque::<impl Copy>(move _26) -> [return: bb10, unwind unreachable]; + } + + bb10: { + StorageDead(_26); + StorageDead(_25); + StorageLive(_27); + StorageLive(_28); + _28 = (*_2); + _27 = opaque::<impl Copy>(move _28) -> [return: bb11, unwind unreachable]; + } + + bb11: { + StorageDead(_28); + StorageDead(_27); + StorageLive(_29); +- StorageLive(_30); + _30 = ((*_3).0: u32); +- _29 = opaque::<u32>(move _30) -> [return: bb12, unwind unreachable]; ++ _29 = opaque::<u32>(_30) -> [return: bb12, unwind unreachable]; + } + + bb12: { +- StorageDead(_30); + StorageDead(_29); + StorageLive(_31); +- StorageLive(_32); +- _32 = ((*_3).0: u32); +- _31 = opaque::<u32>(move _32) -> [return: bb13, unwind unreachable]; ++ _31 = opaque::<u32>(_30) -> [return: bb13, unwind unreachable]; + } + + bb13: { +- StorageDead(_32); + StorageDead(_31); + _0 = const (); + StorageDead(_18); + StorageDead(_13); + StorageDead(_8); + return; + } + } + diff --git a/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff new file mode 100644 index 00000000000..f627b4d5988 --- /dev/null +++ b/tests/mir-opt/gvn.dereferences.GVN.panic-unwind.diff @@ -0,0 +1,191 @@ +- // MIR for `dereferences` before GVN ++ // MIR for `dereferences` after GVN + + fn dereferences(_1: &mut u32, _2: &impl Copy, _3: &S<u32>) -> () { + debug t => _1; + debug u => _2; + debug s => _3; + let mut _0: (); + let _4: (); + let mut _5: u32; + let _6: (); + let mut _7: u32; + let _8: *const u32; + let _9: (); + let mut _10: u32; + let _11: (); + let mut _12: u32; + let _14: (); + let mut _15: u32; + let _16: (); + let mut _17: u32; + let _19: (); + let mut _20: u32; + let _21: (); + let mut _22: u32; + let _23: (); + let mut _24: &u32; + let _25: (); + let mut _26: impl Copy; + let _27: (); + let mut _28: impl Copy; + let _29: (); + let mut _30: u32; + let _31: (); + let mut _32: u32; + scope 1 { + debug z => _8; + let _13: *mut u32; + scope 2 { + } + scope 3 { + } + scope 4 { + debug z => _13; + let _18: &u32; + scope 5 { + } + scope 6 { + } + scope 7 { + debug z => _18; + } + } + } + + bb0: { + StorageLive(_4); + StorageLive(_5); + _5 = (*_1); + _4 = opaque::<u32>(move _5) -> [return: bb1, unwind continue]; + } + + bb1: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = (*_1); + _6 = opaque::<u32>(move _7) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + _8 = &raw const (*_1); + StorageLive(_9); + StorageLive(_10); + _10 = (*_8); + _9 = opaque::<u32>(move _10) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_10); + StorageDead(_9); + StorageLive(_11); + StorageLive(_12); + _12 = (*_8); + _11 = opaque::<u32>(move _12) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_12); + StorageDead(_11); + StorageLive(_13); + _13 = &raw mut (*_1); + StorageLive(_14); + StorageLive(_15); + _15 = (*_13); + _14 = opaque::<u32>(move _15) -> [return: bb5, unwind continue]; + } + + bb5: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + _17 = (*_13); + _16 = opaque::<u32>(move _17) -> [return: bb6, unwind continue]; + } + + bb6: { + StorageDead(_17); + StorageDead(_16); + StorageLive(_18); + _18 = &(*_1); + StorageLive(_19); +- StorageLive(_20); + _20 = (*_18); +- _19 = opaque::<u32>(move _20) -> [return: bb7, unwind continue]; ++ _19 = opaque::<u32>(_20) -> [return: bb7, unwind continue]; + } + + bb7: { +- StorageDead(_20); + StorageDead(_19); + StorageLive(_21); +- StorageLive(_22); +- _22 = (*_18); +- _21 = opaque::<u32>(move _22) -> [return: bb8, unwind continue]; ++ _21 = opaque::<u32>(_20) -> [return: bb8, unwind continue]; + } + + bb8: { +- StorageDead(_22); + StorageDead(_21); + StorageLive(_23); + StorageLive(_24); + _24 = &(*_18); + _23 = opaque::<&u32>(move _24) -> [return: bb9, unwind continue]; + } + + bb9: { + StorageDead(_24); + StorageDead(_23); + StorageLive(_25); + StorageLive(_26); + _26 = (*_2); + _25 = opaque::<impl Copy>(move _26) -> [return: bb10, unwind continue]; + } + + bb10: { + StorageDead(_26); + StorageDead(_25); + StorageLive(_27); + StorageLive(_28); + _28 = (*_2); + _27 = opaque::<impl Copy>(move _28) -> [return: bb11, unwind continue]; + } + + bb11: { + StorageDead(_28); + StorageDead(_27); + StorageLive(_29); +- StorageLive(_30); + _30 = ((*_3).0: u32); +- _29 = opaque::<u32>(move _30) -> [return: bb12, unwind continue]; ++ _29 = opaque::<u32>(_30) -> [return: bb12, unwind continue]; + } + + bb12: { +- StorageDead(_30); + StorageDead(_29); + StorageLive(_31); +- StorageLive(_32); +- _32 = ((*_3).0: u32); +- _31 = opaque::<u32>(move _32) -> [return: bb13, unwind continue]; ++ _31 = opaque::<u32>(_30) -> [return: bb13, unwind continue]; + } + + bb13: { +- StorageDead(_32); + StorageDead(_31); + _0 = const (); + StorageDead(_18); + StorageDead(_13); + StorageDead(_8); + return; + } + } + diff --git a/tests/mir-opt/gvn.multiple_branches.GVN.panic-abort.diff b/tests/mir-opt/gvn.multiple_branches.GVN.panic-abort.diff new file mode 100644 index 00000000000..0a66900283b --- /dev/null +++ b/tests/mir-opt/gvn.multiple_branches.GVN.panic-abort.diff @@ -0,0 +1,198 @@ +- // MIR for `multiple_branches` before GVN ++ // MIR for `multiple_branches` after GVN + + fn multiple_branches(_1: bool, _2: u8, _3: u8) -> () { + debug t => _1; + debug x => _2; + debug y => _3; + let mut _0: (); + let _4: (); + let mut _5: bool; + let _6: (); + let mut _7: u8; + let mut _8: u8; + let mut _9: u8; + let _10: (); + let mut _11: u8; + let mut _12: u8; + let mut _13: u8; + let _14: (); + let mut _15: u8; + let mut _16: u8; + let mut _17: u8; + let _18: (); + let mut _19: u8; + let mut _20: u8; + let mut _21: u8; + let _22: (); + let mut _23: u8; + let mut _24: u8; + let mut _25: u8; + let mut _26: bool; + let _27: (); + let mut _28: u8; + let mut _29: u8; + let mut _30: u8; + let _31: (); + let mut _32: u8; + let mut _33: u8; + let mut _34: u8; + + bb0: { +- StorageLive(_4); +- StorageLive(_5); +- _5 = _1; +- switchInt(move _5) -> [0: bb4, otherwise: bb1]; ++ switchInt(_1) -> [0: bb4, otherwise: bb1]; + } + + bb1: { + StorageLive(_6); +- StorageLive(_7); +- StorageLive(_8); +- _8 = _2; +- StorageLive(_9); +- _9 = _3; +- _7 = Add(move _8, move _9); +- StorageDead(_9); +- StorageDead(_8); +- _6 = opaque::<u8>(move _7) -> [return: bb2, unwind unreachable]; ++ _7 = Add(_2, _3); ++ _6 = opaque::<u8>(_7) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- StorageDead(_7); + StorageDead(_6); + StorageLive(_10); +- StorageLive(_11); +- StorageLive(_12); +- _12 = _2; +- StorageLive(_13); +- _13 = _3; +- _11 = Add(move _12, move _13); +- StorageDead(_13); +- StorageDead(_12); +- _10 = opaque::<u8>(move _11) -> [return: bb3, unwind unreachable]; ++ _10 = opaque::<u8>(_7) -> [return: bb3, unwind unreachable]; + } + + bb3: { +- StorageDead(_11); + StorageDead(_10); +- _4 = const (); + goto -> bb7; + } + + bb4: { + StorageLive(_14); +- StorageLive(_15); +- StorageLive(_16); +- _16 = _2; +- StorageLive(_17); +- _17 = _3; +- _15 = Add(move _16, move _17); +- StorageDead(_17); +- StorageDead(_16); +- _14 = opaque::<u8>(move _15) -> [return: bb5, unwind unreachable]; ++ _15 = Add(_2, _3); ++ _14 = opaque::<u8>(_15) -> [return: bb5, unwind unreachable]; + } + + bb5: { +- StorageDead(_15); + StorageDead(_14); + StorageLive(_18); +- StorageLive(_19); +- StorageLive(_20); +- _20 = _2; +- StorageLive(_21); +- _21 = _3; +- _19 = Add(move _20, move _21); +- StorageDead(_21); +- StorageDead(_20); +- _18 = opaque::<u8>(move _19) -> [return: bb6, unwind unreachable]; ++ _18 = opaque::<u8>(_15) -> [return: bb6, unwind unreachable]; + } + + bb6: { +- StorageDead(_19); + StorageDead(_18); +- _4 = const (); + goto -> bb7; + } + + bb7: { +- StorageDead(_5); +- StorageDead(_4); + StorageLive(_22); +- StorageLive(_23); +- StorageLive(_24); +- _24 = _2; +- StorageLive(_25); +- _25 = _3; +- _23 = Add(move _24, move _25); +- StorageDead(_25); +- StorageDead(_24); +- _22 = opaque::<u8>(move _23) -> [return: bb8, unwind unreachable]; ++ _23 = Add(_2, _3); ++ _22 = opaque::<u8>(_23) -> [return: bb8, unwind unreachable]; + } + + bb8: { +- StorageDead(_23); + StorageDead(_22); +- StorageLive(_26); +- _26 = _1; +- switchInt(move _26) -> [0: bb11, otherwise: bb9]; ++ switchInt(_1) -> [0: bb11, otherwise: bb9]; + } + + bb9: { + StorageLive(_27); +- StorageLive(_28); +- StorageLive(_29); +- _29 = _2; +- StorageLive(_30); +- _30 = _3; +- _28 = Add(move _29, move _30); +- StorageDead(_30); +- StorageDead(_29); +- _27 = opaque::<u8>(move _28) -> [return: bb10, unwind unreachable]; ++ _27 = opaque::<u8>(_23) -> [return: bb10, unwind unreachable]; + } + + bb10: { +- StorageDead(_28); + StorageDead(_27); + _0 = const (); + goto -> bb13; + } + + bb11: { + StorageLive(_31); +- StorageLive(_32); +- StorageLive(_33); +- _33 = _2; +- StorageLive(_34); +- _34 = _3; +- _32 = Add(move _33, move _34); +- StorageDead(_34); +- StorageDead(_33); +- _31 = opaque::<u8>(move _32) -> [return: bb12, unwind unreachable]; ++ _31 = opaque::<u8>(_23) -> [return: bb12, unwind unreachable]; + } + + bb12: { +- StorageDead(_32); + StorageDead(_31); + _0 = const (); + goto -> bb13; + } + + bb13: { +- StorageDead(_26); + return; + } + } + diff --git a/tests/mir-opt/gvn.multiple_branches.GVN.panic-unwind.diff b/tests/mir-opt/gvn.multiple_branches.GVN.panic-unwind.diff new file mode 100644 index 00000000000..0199f2720a9 --- /dev/null +++ b/tests/mir-opt/gvn.multiple_branches.GVN.panic-unwind.diff @@ -0,0 +1,198 @@ +- // MIR for `multiple_branches` before GVN ++ // MIR for `multiple_branches` after GVN + + fn multiple_branches(_1: bool, _2: u8, _3: u8) -> () { + debug t => _1; + debug x => _2; + debug y => _3; + let mut _0: (); + let _4: (); + let mut _5: bool; + let _6: (); + let mut _7: u8; + let mut _8: u8; + let mut _9: u8; + let _10: (); + let mut _11: u8; + let mut _12: u8; + let mut _13: u8; + let _14: (); + let mut _15: u8; + let mut _16: u8; + let mut _17: u8; + let _18: (); + let mut _19: u8; + let mut _20: u8; + let mut _21: u8; + let _22: (); + let mut _23: u8; + let mut _24: u8; + let mut _25: u8; + let mut _26: bool; + let _27: (); + let mut _28: u8; + let mut _29: u8; + let mut _30: u8; + let _31: (); + let mut _32: u8; + let mut _33: u8; + let mut _34: u8; + + bb0: { +- StorageLive(_4); +- StorageLive(_5); +- _5 = _1; +- switchInt(move _5) -> [0: bb4, otherwise: bb1]; ++ switchInt(_1) -> [0: bb4, otherwise: bb1]; + } + + bb1: { + StorageLive(_6); +- StorageLive(_7); +- StorageLive(_8); +- _8 = _2; +- StorageLive(_9); +- _9 = _3; +- _7 = Add(move _8, move _9); +- StorageDead(_9); +- StorageDead(_8); +- _6 = opaque::<u8>(move _7) -> [return: bb2, unwind continue]; ++ _7 = Add(_2, _3); ++ _6 = opaque::<u8>(_7) -> [return: bb2, unwind continue]; + } + + bb2: { +- StorageDead(_7); + StorageDead(_6); + StorageLive(_10); +- StorageLive(_11); +- StorageLive(_12); +- _12 = _2; +- StorageLive(_13); +- _13 = _3; +- _11 = Add(move _12, move _13); +- StorageDead(_13); +- StorageDead(_12); +- _10 = opaque::<u8>(move _11) -> [return: bb3, unwind continue]; ++ _10 = opaque::<u8>(_7) -> [return: bb3, unwind continue]; + } + + bb3: { +- StorageDead(_11); + StorageDead(_10); +- _4 = const (); + goto -> bb7; + } + + bb4: { + StorageLive(_14); +- StorageLive(_15); +- StorageLive(_16); +- _16 = _2; +- StorageLive(_17); +- _17 = _3; +- _15 = Add(move _16, move _17); +- StorageDead(_17); +- StorageDead(_16); +- _14 = opaque::<u8>(move _15) -> [return: bb5, unwind continue]; ++ _15 = Add(_2, _3); ++ _14 = opaque::<u8>(_15) -> [return: bb5, unwind continue]; + } + + bb5: { +- StorageDead(_15); + StorageDead(_14); + StorageLive(_18); +- StorageLive(_19); +- StorageLive(_20); +- _20 = _2; +- StorageLive(_21); +- _21 = _3; +- _19 = Add(move _20, move _21); +- StorageDead(_21); +- StorageDead(_20); +- _18 = opaque::<u8>(move _19) -> [return: bb6, unwind continue]; ++ _18 = opaque::<u8>(_15) -> [return: bb6, unwind continue]; + } + + bb6: { +- StorageDead(_19); + StorageDead(_18); +- _4 = const (); + goto -> bb7; + } + + bb7: { +- StorageDead(_5); +- StorageDead(_4); + StorageLive(_22); +- StorageLive(_23); +- StorageLive(_24); +- _24 = _2; +- StorageLive(_25); +- _25 = _3; +- _23 = Add(move _24, move _25); +- StorageDead(_25); +- StorageDead(_24); +- _22 = opaque::<u8>(move _23) -> [return: bb8, unwind continue]; ++ _23 = Add(_2, _3); ++ _22 = opaque::<u8>(_23) -> [return: bb8, unwind continue]; + } + + bb8: { +- StorageDead(_23); + StorageDead(_22); +- StorageLive(_26); +- _26 = _1; +- switchInt(move _26) -> [0: bb11, otherwise: bb9]; ++ switchInt(_1) -> [0: bb11, otherwise: bb9]; + } + + bb9: { + StorageLive(_27); +- StorageLive(_28); +- StorageLive(_29); +- _29 = _2; +- StorageLive(_30); +- _30 = _3; +- _28 = Add(move _29, move _30); +- StorageDead(_30); +- StorageDead(_29); +- _27 = opaque::<u8>(move _28) -> [return: bb10, unwind continue]; ++ _27 = opaque::<u8>(_23) -> [return: bb10, unwind continue]; + } + + bb10: { +- StorageDead(_28); + StorageDead(_27); + _0 = const (); + goto -> bb13; + } + + bb11: { + StorageLive(_31); +- StorageLive(_32); +- StorageLive(_33); +- _33 = _2; +- StorageLive(_34); +- _34 = _3; +- _32 = Add(move _33, move _34); +- StorageDead(_34); +- StorageDead(_33); +- _31 = opaque::<u8>(move _32) -> [return: bb12, unwind continue]; ++ _31 = opaque::<u8>(_23) -> [return: bb12, unwind continue]; + } + + bb12: { +- StorageDead(_32); + StorageDead(_31); + _0 = const (); + goto -> bb13; + } + + bb13: { +- StorageDead(_26); + return; + } + } + diff --git a/tests/mir-opt/gvn.references.GVN.panic-abort.diff b/tests/mir-opt/gvn.references.GVN.panic-abort.diff new file mode 100644 index 00000000000..b7ad4ab1fd3 --- /dev/null +++ b/tests/mir-opt/gvn.references.GVN.panic-abort.diff @@ -0,0 +1,105 @@ +- // MIR for `references` before GVN ++ // MIR for `references` after GVN + + fn references(_1: impl Sized) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: &impl Sized; + let _4: (); + let mut _5: &impl Sized; + let _6: (); + let mut _7: &mut impl Sized; + let _8: (); + let mut _9: &mut impl Sized; + let _10: (); + let mut _11: *const impl Sized; + let _12: (); + let mut _13: *const impl Sized; + let _14: (); + let mut _15: *mut impl Sized; + let _16: (); + let mut _17: *mut impl Sized; + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = &_1; + _2 = opaque::<&impl Sized>(move _3) -> [return: bb1, unwind unreachable]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_4); + StorageLive(_5); + _5 = &_1; + _4 = opaque::<&impl Sized>(move _5) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = &mut _1; + _6 = opaque::<&mut impl Sized>(move _7) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = &mut _1; + _8 = opaque::<&mut impl Sized>(move _9) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_10); + StorageLive(_11); + _11 = &raw const _1; + _10 = opaque::<*const impl Sized>(move _11) -> [return: bb5, unwind unreachable]; + } + + bb5: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_12); + StorageLive(_13); + _13 = &raw const _1; + _12 = opaque::<*const impl Sized>(move _13) -> [return: bb6, unwind unreachable]; + } + + bb6: { + StorageDead(_13); + StorageDead(_12); + StorageLive(_14); + StorageLive(_15); + _15 = &raw mut _1; + _14 = opaque::<*mut impl Sized>(move _15) -> [return: bb7, unwind unreachable]; + } + + bb7: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + _17 = &raw mut _1; + _16 = opaque::<*mut impl Sized>(move _17) -> [return: bb8, unwind unreachable]; + } + + bb8: { + StorageDead(_17); + StorageDead(_16); + _0 = const (); + drop(_1) -> [return: bb9, unwind unreachable]; + } + + bb9: { + return; + } + } + diff --git a/tests/mir-opt/gvn.references.GVN.panic-unwind.diff b/tests/mir-opt/gvn.references.GVN.panic-unwind.diff new file mode 100644 index 00000000000..08ed4c629a6 --- /dev/null +++ b/tests/mir-opt/gvn.references.GVN.panic-unwind.diff @@ -0,0 +1,113 @@ +- // MIR for `references` before GVN ++ // MIR for `references` after GVN + + fn references(_1: impl Sized) -> () { + debug x => _1; + let mut _0: (); + let _2: (); + let mut _3: &impl Sized; + let _4: (); + let mut _5: &impl Sized; + let _6: (); + let mut _7: &mut impl Sized; + let _8: (); + let mut _9: &mut impl Sized; + let _10: (); + let mut _11: *const impl Sized; + let _12: (); + let mut _13: *const impl Sized; + let _14: (); + let mut _15: *mut impl Sized; + let _16: (); + let mut _17: *mut impl Sized; + + bb0: { + StorageLive(_2); + StorageLive(_3); + _3 = &_1; + _2 = opaque::<&impl Sized>(move _3) -> [return: bb1, unwind: bb10]; + } + + bb1: { + StorageDead(_3); + StorageDead(_2); + StorageLive(_4); + StorageLive(_5); + _5 = &_1; + _4 = opaque::<&impl Sized>(move _5) -> [return: bb2, unwind: bb10]; + } + + bb2: { + StorageDead(_5); + StorageDead(_4); + StorageLive(_6); + StorageLive(_7); + _7 = &mut _1; + _6 = opaque::<&mut impl Sized>(move _7) -> [return: bb3, unwind: bb10]; + } + + bb3: { + StorageDead(_7); + StorageDead(_6); + StorageLive(_8); + StorageLive(_9); + _9 = &mut _1; + _8 = opaque::<&mut impl Sized>(move _9) -> [return: bb4, unwind: bb10]; + } + + bb4: { + StorageDead(_9); + StorageDead(_8); + StorageLive(_10); + StorageLive(_11); + _11 = &raw const _1; + _10 = opaque::<*const impl Sized>(move _11) -> [return: bb5, unwind: bb10]; + } + + bb5: { + StorageDead(_11); + StorageDead(_10); + StorageLive(_12); + StorageLive(_13); + _13 = &raw const _1; + _12 = opaque::<*const impl Sized>(move _13) -> [return: bb6, unwind: bb10]; + } + + bb6: { + StorageDead(_13); + StorageDead(_12); + StorageLive(_14); + StorageLive(_15); + _15 = &raw mut _1; + _14 = opaque::<*mut impl Sized>(move _15) -> [return: bb7, unwind: bb10]; + } + + bb7: { + StorageDead(_15); + StorageDead(_14); + StorageLive(_16); + StorageLive(_17); + _17 = &raw mut _1; + _16 = opaque::<*mut impl Sized>(move _17) -> [return: bb8, unwind: bb10]; + } + + bb8: { + StorageDead(_17); + StorageDead(_16); + _0 = const (); + drop(_1) -> [return: bb9, unwind: bb11]; + } + + bb9: { + return; + } + + bb10 (cleanup): { + drop(_1) -> [return: bb11, unwind terminate(cleanup)]; + } + + bb11 (cleanup): { + resume; + } + } + diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff new file mode 100644 index 00000000000..4c29523d6b2 --- /dev/null +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-abort.diff @@ -0,0 +1,76 @@ +- // MIR for `repeated_index` before GVN ++ // MIR for `repeated_index` after GVN + + fn repeated_index(_1: T, _2: usize) -> () { + debug x => _1; + debug idx => _2; + let mut _0: (); + let _3: [T; N]; + let mut _4: T; + let _5: (); + let mut _6: T; + let _7: usize; + let mut _8: usize; + let mut _9: bool; + let _10: (); + let mut _11: T; + let _12: usize; + let mut _13: usize; + let mut _14: bool; + scope 1 { + debug a => _3; + } + + bb0: { + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = [move _4; N]; +- StorageDead(_4); ++ _3 = [_1; N]; + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + _7 = const 0_usize; + _8 = Len(_3); +- _9 = Lt(_7, _8); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind unreachable]; ++ _9 = Lt(const 0_usize, _8); ++ assert(move _9, "index out of bounds: the length is {} but the index is {}", _8, const 0_usize) -> [success: bb1, unwind unreachable]; + } + + bb1: { + _6 = _3[_7]; + _5 = opaque::<T>(move _6) -> [return: bb2, unwind unreachable]; + } + + bb2: { + StorageDead(_6); + StorageDead(_7); + StorageDead(_5); + StorageLive(_10); + StorageLive(_11); + StorageLive(_12); + _12 = _2; +- _13 = Len(_3); +- _14 = Lt(_12, _13); +- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind unreachable]; ++ _14 = Lt(_2, _8); ++ assert(move _14, "index out of bounds: the length is {} but the index is {}", _8, _2) -> [success: bb3, unwind unreachable]; + } + + bb3: { + _11 = _3[_12]; + _10 = opaque::<T>(move _11) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_11); + StorageDead(_12); + StorageDead(_10); + _0 = const (); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff new file mode 100644 index 00000000000..e44f54cf3cf --- /dev/null +++ b/tests/mir-opt/gvn.repeated_index.GVN.panic-unwind.diff @@ -0,0 +1,76 @@ +- // MIR for `repeated_index` before GVN ++ // MIR for `repeated_index` after GVN + + fn repeated_index(_1: T, _2: usize) -> () { + debug x => _1; + debug idx => _2; + let mut _0: (); + let _3: [T; N]; + let mut _4: T; + let _5: (); + let mut _6: T; + let _7: usize; + let mut _8: usize; + let mut _9: bool; + let _10: (); + let mut _11: T; + let _12: usize; + let mut _13: usize; + let mut _14: bool; + scope 1 { + debug a => _3; + } + + bb0: { + StorageLive(_3); +- StorageLive(_4); +- _4 = _1; +- _3 = [move _4; N]; +- StorageDead(_4); ++ _3 = [_1; N]; + StorageLive(_5); + StorageLive(_6); + StorageLive(_7); + _7 = const 0_usize; + _8 = Len(_3); +- _9 = Lt(_7, _8); +- assert(move _9, "index out of bounds: the length is {} but the index is {}", move _8, _7) -> [success: bb1, unwind continue]; ++ _9 = Lt(const 0_usize, _8); ++ assert(move _9, "index out of bounds: the length is {} but the index is {}", _8, const 0_usize) -> [success: bb1, unwind continue]; + } + + bb1: { + _6 = _3[_7]; + _5 = opaque::<T>(move _6) -> [return: bb2, unwind continue]; + } + + bb2: { + StorageDead(_6); + StorageDead(_7); + StorageDead(_5); + StorageLive(_10); + StorageLive(_11); + StorageLive(_12); + _12 = _2; +- _13 = Len(_3); +- _14 = Lt(_12, _13); +- assert(move _14, "index out of bounds: the length is {} but the index is {}", move _13, _12) -> [success: bb3, unwind continue]; ++ _14 = Lt(_2, _8); ++ assert(move _14, "index out of bounds: the length is {} but the index is {}", _8, _2) -> [success: bb3, unwind continue]; + } + + bb3: { + _11 = _3[_12]; + _10 = opaque::<T>(move _11) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_11); + StorageDead(_12); + StorageDead(_10); + _0 = const (); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/gvn.rs b/tests/mir-opt/gvn.rs new file mode 100644 index 00000000000..a85e2ae368b --- /dev/null +++ b/tests/mir-opt/gvn.rs @@ -0,0 +1,253 @@ +// unit-test: GVN +// EMIT_MIR_FOR_EACH_PANIC_STRATEGY + +#![feature(raw_ref_op)] +#![feature(rustc_attrs)] +#![allow(unconditional_panic)] + +struct S<T>(T); + +fn subexpression_elimination(x: u64, y: u64, mut z: u64) { + opaque(x + y); + opaque(x * y); + opaque(x - y); + opaque(x / y); + opaque(x % y); + opaque(x & y); + opaque(x | y); + opaque(x ^ y); + opaque(x << y); + opaque(x >> y); + opaque(x as u32); + opaque(x as f32); + opaque(S(x)); + opaque(S(x).0); + + // Those are duplicates to substitute somehow. + opaque((x + y) + z); + opaque((x * y) + z); + opaque((x - y) + z); + opaque((x / y) + z); + opaque((x % y) + z); + opaque((x & y) + z); + opaque((x | y) + z); + opaque((x ^ y) + z); + opaque((x << y) + z); + opaque((x >> y) + z); + opaque(S(x)); + opaque(S(x).0); + + // We can substitute through an immutable reference too. + let a = &z; + opaque(*a + x); + opaque(*a + x); + + // But not through a mutable reference or a pointer. + let b = &mut z; + opaque(*b + x); + opaque(*b + x); + unsafe { + let c = &raw const z; + opaque(*c + x); + opaque(*c + x); + let d = &raw mut z; + opaque(*d + x); + opaque(*d + x); + } + + // We can substitute again, but not with the earlier computations. + // Important: `e` is not `a`! + let e = &z; + opaque(*e + x); + opaque(*e + x); + +} + +fn wrap_unwrap<T: Copy>(x: T) -> T { + match Some(x) { + Some(y) => y, + None => panic!(), + } +} + +fn repeated_index<T: Copy, const N: usize>(x: T, idx: usize) { + let a = [x; N]; + opaque(a[0]); + opaque(a[idx]); +} + +fn arithmetic(x: u64) { + opaque(x + 0); + opaque(x - 0); + opaque(x * 0); + opaque(x * 1); + opaque(x / 0); + opaque(x / 1); + opaque(0 / x); + opaque(1 / x); + opaque(x % 0); + opaque(x % 1); + opaque(0 % x); + opaque(1 % x); + opaque(x & 0); + opaque(x | 0); + opaque(x ^ 0); + opaque(x >> 0); + opaque(x << 0); +} + +#[rustc_inherit_overflow_checks] +fn arithmetic_checked(x: u64) { + opaque(x + 0); + opaque(x - 0); + opaque(x * 0); + opaque(x * 1); + opaque(x / 0); + opaque(x / 1); + opaque(0 / x); + opaque(1 / x); + opaque(x % 0); + opaque(x % 1); + opaque(0 % x); + opaque(1 % x); + opaque(x & 0); + opaque(x | 0); + opaque(x ^ 0); + opaque(x >> 0); + opaque(x << 0); +} + +fn arithmetic_float(x: f64) { + opaque(x + 0.); + opaque(x - 0.); + opaque(x * 0.); + opaque(x / 0.); + opaque(0. / x); + opaque(x % 0.); + opaque(0. % x); + // Those are not simplifiable to `true`/`false`, thanks to NaNs. + opaque(x == x); + opaque(x != x); +} + +fn cast() { + let i = 1_i64; + let u = 1_u64; + let f = 1_f64; + opaque(i as u8); + opaque(i as u16); + opaque(i as u32); + opaque(i as u64); + opaque(i as i8); + opaque(i as i16); + opaque(i as i32); + opaque(i as i64); + opaque(i as f32); + opaque(i as f64); + opaque(u as u8); + opaque(u as u16); + opaque(u as u32); + opaque(u as u64); + opaque(u as i8); + opaque(u as i16); + opaque(u as i32); + opaque(u as i64); + opaque(u as f32); + opaque(u as f64); + opaque(f as u8); + opaque(f as u16); + opaque(f as u32); + opaque(f as u64); + opaque(f as i8); + opaque(f as i16); + opaque(f as i32); + opaque(f as i64); + opaque(f as f32); + opaque(f as f64); +} + +fn multiple_branches(t: bool, x: u8, y: u8) { + if t { + opaque(x + y); // a + opaque(x + y); // should reuse a + } else { + opaque(x + y); // b + opaque(x + y); // shoud reuse b + } + opaque(x + y); // c + if t { + opaque(x + y); // should reuse c + } else { + opaque(x + y); // should reuse c + } +} + +fn references(mut x: impl Sized) { + opaque(&x); + opaque(&x); // should not reuse a + opaque(&mut x); + opaque(&mut x); // should not reuse a + opaque(&raw const x); + opaque(&raw const x); // should not reuse a + opaque(&raw mut x); + opaque(&raw mut x); // should not reuse a +} + +fn dereferences(t: &mut u32, u: &impl Copy, s: &S<u32>) { + opaque(*t); + opaque(*t); // this cannot reuse a, as x is &mut. + let z = &raw const *t; + unsafe { opaque(*z) }; + unsafe { opaque(*z) }; // this cannot reuse a, as x is *const. + let z = &raw mut *t; + unsafe { opaque(*z) }; + unsafe { opaque(*z) }; // this cannot reuse a, as x is *mut. + let z = &*t; + opaque(*z); + opaque(*z); // this can reuse, as `z` is immutable ref, Freeze and Copy. + opaque(&*z); // but not for a reborrow. + opaque(*u); + opaque(*u); // this cannot reuse, as `z` is not Freeze. + opaque(s.0); + opaque(s.0); // *s is not Copy, by (*s).0 is, so we can reuse. +} + +fn slices() { + let s = "my favourite slice"; // This is a `Const::Slice` in MIR. + opaque(s); + let t = s; // This should be the same pointer, so cannot be a `Const::Slice`. + opaque(t); + assert_eq!(s.as_ptr(), t.as_ptr()); + let u = unsafe { std::mem::transmute::<&str, &[u8]>(s) }; + opaque(u); + assert_eq!(s.as_ptr(), u.as_ptr()); +} + +fn main() { + subexpression_elimination(2, 4, 5); + wrap_unwrap(5); + repeated_index::<u32, 7>(5, 3); + arithmetic(5); + arithmetic_checked(5); + arithmetic_float(5.); + cast(); + multiple_branches(true, 5, 9); + references(5); + dereferences(&mut 5, &6, &S(7)); + slices(); +} + +#[inline(never)] +fn opaque(_: impl Sized) {} + +// EMIT_MIR gvn.subexpression_elimination.GVN.diff +// EMIT_MIR gvn.wrap_unwrap.GVN.diff +// EMIT_MIR gvn.repeated_index.GVN.diff +// EMIT_MIR gvn.arithmetic.GVN.diff +// EMIT_MIR gvn.arithmetic_checked.GVN.diff +// EMIT_MIR gvn.arithmetic_float.GVN.diff +// EMIT_MIR gvn.cast.GVN.diff +// EMIT_MIR gvn.multiple_branches.GVN.diff +// EMIT_MIR gvn.references.GVN.diff +// EMIT_MIR gvn.dereferences.GVN.diff +// EMIT_MIR gvn.slices.GVN.diff diff --git a/tests/mir-opt/gvn.slices.GVN.panic-abort.diff b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff new file mode 100644 index 00000000000..de3d28d0575 --- /dev/null +++ b/tests/mir-opt/gvn.slices.GVN.panic-abort.diff @@ -0,0 +1,275 @@ +- // MIR for `slices` before GVN ++ // MIR for `slices` after GVN + + fn slices() -> () { + let mut _0: (); + let _1: &str; + let _2: (); + let mut _3: &str; + let _5: (); + let mut _6: &str; + let _7: (); + let mut _8: (&*const u8, &*const u8); + let mut _9: &*const u8; + let _10: *const u8; + let mut _11: &str; + let mut _12: &*const u8; + let _13: *const u8; + let mut _14: &str; + let mut _17: bool; + let mut _18: *const u8; + let mut _19: *const u8; + let mut _20: !; + let _22: !; + let mut _23: core::panicking::AssertKind; + let mut _24: &*const u8; + let _25: &*const u8; + let mut _26: &*const u8; + let _27: &*const u8; + let mut _28: std::option::Option<std::fmt::Arguments<'_>>; + let mut _30: &str; + let _31: (); + let mut _32: &[u8]; + let _33: (); + let mut _34: (&*const u8, &*const u8); + let mut _35: &*const u8; + let _36: *const u8; + let mut _37: &str; + let mut _38: &*const u8; + let _39: *const u8; + let mut _40: &[u8]; + let mut _43: bool; + let mut _44: *const u8; + let mut _45: *const u8; + let mut _46: !; + let _48: !; + let mut _49: core::panicking::AssertKind; + let mut _50: &*const u8; + let _51: &*const u8; + let mut _52: &*const u8; + let _53: &*const u8; + let mut _54: std::option::Option<std::fmt::Arguments<'_>>; + scope 1 { + debug s => _1; + let _4: &str; + scope 2 { + debug t => _4; + let _15: &*const u8; + let _16: &*const u8; + let _29: &[u8]; + scope 3 { + debug left_val => _15; + debug right_val => _16; + let _21: core::panicking::AssertKind; + scope 4 { + debug kind => _21; + } + } + scope 5 { + debug u => _29; + let _41: &*const u8; + let _42: &*const u8; + scope 7 { + debug left_val => _41; + debug right_val => _42; + let _47: core::panicking::AssertKind; + scope 8 { + debug kind => _47; + } + } + } + scope 6 { + } + } + } + + bb0: { +- StorageLive(_1); + _1 = const "my favourite slice"; + StorageLive(_2); +- StorageLive(_3); +- _3 = _1; +- _2 = opaque::<&str>(move _3) -> [return: bb1, unwind unreachable]; ++ _2 = opaque::<&str>(_1) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- StorageDead(_3); + StorageDead(_2); + StorageLive(_4); + _4 = _1; + StorageLive(_5); +- StorageLive(_6); +- _6 = _4; +- _5 = opaque::<&str>(move _6) -> [return: bb2, unwind unreachable]; ++ _5 = opaque::<&str>(_1) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- StorageDead(_6); + StorageDead(_5); +- StorageLive(_7); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = &(*_1); + _10 = core::str::<impl str>::as_ptr(move _11) -> [return: bb3, unwind unreachable]; + } + + bb3: { + StorageDead(_11); + _9 = &_10; + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + _14 = &(*_4); + _13 = core::str::<impl str>::as_ptr(move _14) -> [return: bb4, unwind unreachable]; + } + + bb4: { + StorageDead(_14); + _12 = &_13; + _8 = (move _9, move _12); + StorageDead(_12); + StorageDead(_9); + StorageLive(_15); + _15 = (_8.0: &*const u8); + StorageLive(_16); + _16 = (_8.1: &*const u8); + StorageLive(_17); + StorageLive(_18); + _18 = (*_15); + StorageLive(_19); + _19 = (*_16); + _17 = Eq(move _18, move _19); + switchInt(move _17) -> [0: bb6, otherwise: bb5]; + } + + bb5: { + StorageDead(_19); + StorageDead(_18); +- _7 = const (); + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); + StorageDead(_13); + StorageDead(_10); + StorageDead(_8); +- StorageDead(_7); +- StorageLive(_29); + StorageLive(_30); + _30 = &(*_1); + _29 = move _30 as &[u8] (Transmute); + StorageDead(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _29; +- _31 = opaque::<&[u8]>(move _32) -> [return: bb7, unwind unreachable]; ++ _31 = opaque::<&[u8]>(_29) -> [return: bb7, unwind unreachable]; + } + + bb6: { + StorageDead(_19); + StorageDead(_18); +- StorageLive(_21); + _21 = core::panicking::AssertKind::Eq; + StorageLive(_22); +- StorageLive(_23); +- _23 = move _21; + StorageLive(_24); + StorageLive(_25); + _25 = &(*_15); + _24 = &(*_25); + StorageLive(_26); + StorageLive(_27); + _27 = &(*_16); + _26 = &(*_27); + StorageLive(_28); + _28 = Option::<Arguments<'_>>::None; +- _22 = core::panicking::assert_failed::<*const u8, *const u8>(move _23, move _24, move _26, move _28) -> unwind unreachable; ++ _22 = core::panicking::assert_failed::<*const u8, *const u8>(_21, move _24, move _26, move _28) -> unwind unreachable; + } + + bb7: { +- StorageDead(_32); + StorageDead(_31); +- StorageLive(_33); + StorageLive(_34); + StorageLive(_35); + StorageLive(_36); + StorageLive(_37); + _37 = &(*_1); + _36 = core::str::<impl str>::as_ptr(move _37) -> [return: bb8, unwind unreachable]; + } + + bb8: { + StorageDead(_37); + _35 = &_36; + StorageLive(_38); + StorageLive(_39); + StorageLive(_40); + _40 = &(*_29); + _39 = core::slice::<impl [u8]>::as_ptr(move _40) -> [return: bb9, unwind unreachable]; + } + + bb9: { + StorageDead(_40); + _38 = &_39; + _34 = (move _35, move _38); + StorageDead(_38); + StorageDead(_35); + StorageLive(_41); + _41 = (_34.0: &*const u8); + StorageLive(_42); + _42 = (_34.1: &*const u8); + StorageLive(_43); + StorageLive(_44); + _44 = (*_41); + StorageLive(_45); + _45 = (*_42); + _43 = Eq(move _44, move _45); + switchInt(move _43) -> [0: bb11, otherwise: bb10]; + } + + bb10: { + StorageDead(_45); + StorageDead(_44); +- _33 = const (); + StorageDead(_43); + StorageDead(_42); + StorageDead(_41); + StorageDead(_39); + StorageDead(_36); + StorageDead(_34); +- StorageDead(_33); + _0 = const (); +- StorageDead(_29); + StorageDead(_4); +- StorageDead(_1); + return; + } + + bb11: { + StorageDead(_45); + StorageDead(_44); +- StorageLive(_47); + _47 = core::panicking::AssertKind::Eq; + StorageLive(_48); +- StorageLive(_49); +- _49 = move _47; + StorageLive(_50); + StorageLive(_51); + _51 = &(*_41); + _50 = &(*_51); + StorageLive(_52); + StorageLive(_53); + _53 = &(*_42); + _52 = &(*_53); + StorageLive(_54); + _54 = Option::<Arguments<'_>>::None; +- _48 = core::panicking::assert_failed::<*const u8, *const u8>(move _49, move _50, move _52, move _54) -> unwind unreachable; ++ _48 = core::panicking::assert_failed::<*const u8, *const u8>(_47, move _50, move _52, move _54) -> unwind unreachable; + } + } + diff --git a/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff new file mode 100644 index 00000000000..f22bb25436f --- /dev/null +++ b/tests/mir-opt/gvn.slices.GVN.panic-unwind.diff @@ -0,0 +1,275 @@ +- // MIR for `slices` before GVN ++ // MIR for `slices` after GVN + + fn slices() -> () { + let mut _0: (); + let _1: &str; + let _2: (); + let mut _3: &str; + let _5: (); + let mut _6: &str; + let _7: (); + let mut _8: (&*const u8, &*const u8); + let mut _9: &*const u8; + let _10: *const u8; + let mut _11: &str; + let mut _12: &*const u8; + let _13: *const u8; + let mut _14: &str; + let mut _17: bool; + let mut _18: *const u8; + let mut _19: *const u8; + let mut _20: !; + let _22: !; + let mut _23: core::panicking::AssertKind; + let mut _24: &*const u8; + let _25: &*const u8; + let mut _26: &*const u8; + let _27: &*const u8; + let mut _28: std::option::Option<std::fmt::Arguments<'_>>; + let mut _30: &str; + let _31: (); + let mut _32: &[u8]; + let _33: (); + let mut _34: (&*const u8, &*const u8); + let mut _35: &*const u8; + let _36: *const u8; + let mut _37: &str; + let mut _38: &*const u8; + let _39: *const u8; + let mut _40: &[u8]; + let mut _43: bool; + let mut _44: *const u8; + let mut _45: *const u8; + let mut _46: !; + let _48: !; + let mut _49: core::panicking::AssertKind; + let mut _50: &*const u8; + let _51: &*const u8; + let mut _52: &*const u8; + let _53: &*const u8; + let mut _54: std::option::Option<std::fmt::Arguments<'_>>; + scope 1 { + debug s => _1; + let _4: &str; + scope 2 { + debug t => _4; + let _15: &*const u8; + let _16: &*const u8; + let _29: &[u8]; + scope 3 { + debug left_val => _15; + debug right_val => _16; + let _21: core::panicking::AssertKind; + scope 4 { + debug kind => _21; + } + } + scope 5 { + debug u => _29; + let _41: &*const u8; + let _42: &*const u8; + scope 7 { + debug left_val => _41; + debug right_val => _42; + let _47: core::panicking::AssertKind; + scope 8 { + debug kind => _47; + } + } + } + scope 6 { + } + } + } + + bb0: { +- StorageLive(_1); + _1 = const "my favourite slice"; + StorageLive(_2); +- StorageLive(_3); +- _3 = _1; +- _2 = opaque::<&str>(move _3) -> [return: bb1, unwind continue]; ++ _2 = opaque::<&str>(_1) -> [return: bb1, unwind continue]; + } + + bb1: { +- StorageDead(_3); + StorageDead(_2); + StorageLive(_4); + _4 = _1; + StorageLive(_5); +- StorageLive(_6); +- _6 = _4; +- _5 = opaque::<&str>(move _6) -> [return: bb2, unwind continue]; ++ _5 = opaque::<&str>(_1) -> [return: bb2, unwind continue]; + } + + bb2: { +- StorageDead(_6); + StorageDead(_5); +- StorageLive(_7); + StorageLive(_8); + StorageLive(_9); + StorageLive(_10); + StorageLive(_11); + _11 = &(*_1); + _10 = core::str::<impl str>::as_ptr(move _11) -> [return: bb3, unwind continue]; + } + + bb3: { + StorageDead(_11); + _9 = &_10; + StorageLive(_12); + StorageLive(_13); + StorageLive(_14); + _14 = &(*_4); + _13 = core::str::<impl str>::as_ptr(move _14) -> [return: bb4, unwind continue]; + } + + bb4: { + StorageDead(_14); + _12 = &_13; + _8 = (move _9, move _12); + StorageDead(_12); + StorageDead(_9); + StorageLive(_15); + _15 = (_8.0: &*const u8); + StorageLive(_16); + _16 = (_8.1: &*const u8); + StorageLive(_17); + StorageLive(_18); + _18 = (*_15); + StorageLive(_19); + _19 = (*_16); + _17 = Eq(move _18, move _19); + switchInt(move _17) -> [0: bb6, otherwise: bb5]; + } + + bb5: { + StorageDead(_19); + StorageDead(_18); +- _7 = const (); + StorageDead(_17); + StorageDead(_16); + StorageDead(_15); + StorageDead(_13); + StorageDead(_10); + StorageDead(_8); +- StorageDead(_7); +- StorageLive(_29); + StorageLive(_30); + _30 = &(*_1); + _29 = move _30 as &[u8] (Transmute); + StorageDead(_30); + StorageLive(_31); +- StorageLive(_32); +- _32 = _29; +- _31 = opaque::<&[u8]>(move _32) -> [return: bb7, unwind continue]; ++ _31 = opaque::<&[u8]>(_29) -> [return: bb7, unwind continue]; + } + + bb6: { + StorageDead(_19); + StorageDead(_18); +- StorageLive(_21); + _21 = core::panicking::AssertKind::Eq; + StorageLive(_22); +- StorageLive(_23); +- _23 = move _21; + StorageLive(_24); + StorageLive(_25); + _25 = &(*_15); + _24 = &(*_25); + StorageLive(_26); + StorageLive(_27); + _27 = &(*_16); + _26 = &(*_27); + StorageLive(_28); + _28 = Option::<Arguments<'_>>::None; +- _22 = core::panicking::assert_failed::<*const u8, *const u8>(move _23, move _24, move _26, move _28) -> unwind continue; ++ _22 = core::panicking::assert_failed::<*const u8, *const u8>(_21, move _24, move _26, move _28) -> unwind continue; + } + + bb7: { +- StorageDead(_32); + StorageDead(_31); +- StorageLive(_33); + StorageLive(_34); + StorageLive(_35); + StorageLive(_36); + StorageLive(_37); + _37 = &(*_1); + _36 = core::str::<impl str>::as_ptr(move _37) -> [return: bb8, unwind continue]; + } + + bb8: { + StorageDead(_37); + _35 = &_36; + StorageLive(_38); + StorageLive(_39); + StorageLive(_40); + _40 = &(*_29); + _39 = core::slice::<impl [u8]>::as_ptr(move _40) -> [return: bb9, unwind continue]; + } + + bb9: { + StorageDead(_40); + _38 = &_39; + _34 = (move _35, move _38); + StorageDead(_38); + StorageDead(_35); + StorageLive(_41); + _41 = (_34.0: &*const u8); + StorageLive(_42); + _42 = (_34.1: &*const u8); + StorageLive(_43); + StorageLive(_44); + _44 = (*_41); + StorageLive(_45); + _45 = (*_42); + _43 = Eq(move _44, move _45); + switchInt(move _43) -> [0: bb11, otherwise: bb10]; + } + + bb10: { + StorageDead(_45); + StorageDead(_44); +- _33 = const (); + StorageDead(_43); + StorageDead(_42); + StorageDead(_41); + StorageDead(_39); + StorageDead(_36); + StorageDead(_34); +- StorageDead(_33); + _0 = const (); +- StorageDead(_29); + StorageDead(_4); +- StorageDead(_1); + return; + } + + bb11: { + StorageDead(_45); + StorageDead(_44); +- StorageLive(_47); + _47 = core::panicking::AssertKind::Eq; + StorageLive(_48); +- StorageLive(_49); +- _49 = move _47; + StorageLive(_50); + StorageLive(_51); + _51 = &(*_41); + _50 = &(*_51); + StorageLive(_52); + StorageLive(_53); + _53 = &(*_42); + _52 = &(*_53); + StorageLive(_54); + _54 = Option::<Arguments<'_>>::None; +- _48 = core::panicking::assert_failed::<*const u8, *const u8>(move _49, move _50, move _52, move _54) -> unwind continue; ++ _48 = core::panicking::assert_failed::<*const u8, *const u8>(_47, move _50, move _52, move _54) -> unwind continue; + } + } + diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff new file mode 100644 index 00000000000..bf866e2f4d2 --- /dev/null +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-abort.diff @@ -0,0 +1,883 @@ +- // MIR for `subexpression_elimination` before GVN ++ // MIR for `subexpression_elimination` after GVN + + fn subexpression_elimination(_1: u64, _2: u64, _3: u64) -> () { + debug x => _1; + debug y => _2; + debug z => _3; + let mut _0: (); + let _4: (); + let mut _5: u64; + let mut _6: u64; + let mut _7: u64; + let _8: (); + let mut _9: u64; + let mut _10: u64; + let mut _11: u64; + let _12: (); + let mut _13: u64; + let mut _14: u64; + let mut _15: u64; + let _16: (); + let mut _17: u64; + let mut _18: u64; + let mut _19: u64; + let mut _20: bool; + let _21: (); + let mut _22: u64; + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: u64; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: u64; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: u64; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: u64; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: u64; + let _46: (); + let mut _47: u32; + let mut _48: u64; + let _49: (); + let mut _50: f32; + let mut _51: u64; + let _52: (); + let mut _53: S<u64>; + let mut _54: u64; + let _55: (); + let mut _56: u64; + let mut _57: S<u64>; + let mut _58: u64; + let _59: (); + let mut _60: u64; + let mut _61: u64; + let mut _62: u64; + let mut _63: u64; + let mut _64: u64; + let _65: (); + let mut _66: u64; + let mut _67: u64; + let mut _68: u64; + let mut _69: u64; + let mut _70: u64; + let _71: (); + let mut _72: u64; + let mut _73: u64; + let mut _74: u64; + let mut _75: u64; + let mut _76: u64; + let _77: (); + let mut _78: u64; + let mut _79: u64; + let mut _80: u64; + let mut _81: u64; + let mut _82: bool; + let mut _83: u64; + let _84: (); + let mut _85: u64; + let mut _86: u64; + let mut _87: u64; + let mut _88: u64; + let mut _89: bool; + let mut _90: u64; + let _91: (); + let mut _92: u64; + let mut _93: u64; + let mut _94: u64; + let mut _95: u64; + let mut _96: u64; + let _97: (); + let mut _98: u64; + let mut _99: u64; + let mut _100: u64; + let mut _101: u64; + let mut _102: u64; + let _103: (); + let mut _104: u64; + let mut _105: u64; + let mut _106: u64; + let mut _107: u64; + let mut _108: u64; + let _109: (); + let mut _110: u64; + let mut _111: u64; + let mut _112: u64; + let mut _113: u64; + let mut _114: u64; + let _115: (); + let mut _116: u64; + let mut _117: u64; + let mut _118: u64; + let mut _119: u64; + let mut _120: u64; + let _121: (); + let mut _122: S<u64>; + let mut _123: u64; + let _124: (); + let mut _125: u64; + let mut _126: S<u64>; + let mut _127: u64; + let _128: &u64; + let _129: (); + let mut _130: u64; + let mut _131: u64; + let mut _132: u64; + let _133: (); + let mut _134: u64; + let mut _135: u64; + let mut _136: u64; + let _138: (); + let mut _139: u64; + let mut _140: u64; + let mut _141: u64; + let _142: (); + let mut _143: u64; + let mut _144: u64; + let mut _145: u64; + let _146: (); + let _148: (); + let mut _149: u64; + let mut _150: u64; + let mut _151: u64; + let _152: (); + let mut _153: u64; + let mut _154: u64; + let mut _155: u64; + let _157: (); + let mut _158: u64; + let mut _159: u64; + let mut _160: u64; + let _161: (); + let mut _162: u64; + let mut _163: u64; + let mut _164: u64; + let _166: (); + let mut _167: u64; + let mut _168: u64; + let mut _169: u64; + let _170: (); + let mut _171: u64; + let mut _172: u64; + let mut _173: u64; + scope 1 { + debug a => _128; + let _137: &mut u64; + scope 2 { + debug b => _137; + let _165: &u64; + scope 3 { + let _147: *const u64; + scope 4 { + debug c => _147; + let _156: *mut u64; + scope 5 { + debug d => _156; + } + } + } + scope 6 { + debug e => _165; + } + } + } + + bb0: { + StorageLive(_4); +- StorageLive(_5); +- StorageLive(_6); +- _6 = _1; +- StorageLive(_7); +- _7 = _2; +- _5 = Add(move _6, move _7); +- StorageDead(_7); +- StorageDead(_6); +- _4 = opaque::<u64>(move _5) -> [return: bb1, unwind unreachable]; ++ _5 = Add(_1, _2); ++ _4 = opaque::<u64>(_5) -> [return: bb1, unwind unreachable]; + } + + bb1: { +- StorageDead(_5); + StorageDead(_4); + StorageLive(_8); +- StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- StorageLive(_11); +- _11 = _2; +- _9 = Mul(move _10, move _11); +- StorageDead(_11); +- StorageDead(_10); +- _8 = opaque::<u64>(move _9) -> [return: bb2, unwind unreachable]; ++ _9 = Mul(_1, _2); ++ _8 = opaque::<u64>(_9) -> [return: bb2, unwind unreachable]; + } + + bb2: { +- StorageDead(_9); + StorageDead(_8); + StorageLive(_12); +- StorageLive(_13); +- StorageLive(_14); +- _14 = _1; +- StorageLive(_15); +- _15 = _2; +- _13 = Sub(move _14, move _15); +- StorageDead(_15); +- StorageDead(_14); +- _12 = opaque::<u64>(move _13) -> [return: bb3, unwind unreachable]; ++ _13 = Sub(_1, _2); ++ _12 = opaque::<u64>(_13) -> [return: bb3, unwind unreachable]; + } + + bb3: { +- StorageDead(_13); + StorageDead(_12); + StorageLive(_16); +- StorageLive(_17); +- StorageLive(_18); +- _18 = _1; +- StorageLive(_19); +- _19 = _2; +- _20 = Eq(_19, const 0_u64); +- assert(!move _20, "attempt to divide `{}` by zero", _18) -> [success: bb4, unwind unreachable]; ++ _20 = Eq(_2, const 0_u64); ++ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb4, unwind unreachable]; + } + + bb4: { +- _17 = Div(move _18, move _19); +- StorageDead(_19); +- StorageDead(_18); +- _16 = opaque::<u64>(move _17) -> [return: bb5, unwind unreachable]; ++ _17 = Div(_1, _2); ++ _16 = opaque::<u64>(_17) -> [return: bb5, unwind unreachable]; + } + + bb5: { +- StorageDead(_17); + StorageDead(_16); + StorageLive(_21); +- StorageLive(_22); +- StorageLive(_23); +- _23 = _1; +- StorageLive(_24); +- _24 = _2; +- _25 = Eq(_24, const 0_u64); +- assert(!move _25, "attempt to calculate the remainder of `{}` with a divisor of zero", _23) -> [success: bb6, unwind unreachable]; ++ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb6, unwind unreachable]; + } + + bb6: { +- _22 = Rem(move _23, move _24); +- StorageDead(_24); +- StorageDead(_23); +- _21 = opaque::<u64>(move _22) -> [return: bb7, unwind unreachable]; ++ _22 = Rem(_1, _2); ++ _21 = opaque::<u64>(_22) -> [return: bb7, unwind unreachable]; + } + + bb7: { +- StorageDead(_22); + StorageDead(_21); + StorageLive(_26); +- StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- StorageLive(_29); +- _29 = _2; +- _27 = BitAnd(move _28, move _29); +- StorageDead(_29); +- StorageDead(_28); +- _26 = opaque::<u64>(move _27) -> [return: bb8, unwind unreachable]; ++ _27 = BitAnd(_1, _2); ++ _26 = opaque::<u64>(_27) -> [return: bb8, unwind unreachable]; + } + + bb8: { +- StorageDead(_27); + StorageDead(_26); + StorageLive(_30); +- StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- StorageLive(_33); +- _33 = _2; +- _31 = BitOr(move _32, move _33); +- StorageDead(_33); +- StorageDead(_32); +- _30 = opaque::<u64>(move _31) -> [return: bb9, unwind unreachable]; ++ _31 = BitOr(_1, _2); ++ _30 = opaque::<u64>(_31) -> [return: bb9, unwind unreachable]; + } + + bb9: { +- StorageDead(_31); + StorageDead(_30); + StorageLive(_34); +- StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- StorageLive(_37); +- _37 = _2; +- _35 = BitXor(move _36, move _37); +- StorageDead(_37); +- StorageDead(_36); +- _34 = opaque::<u64>(move _35) -> [return: bb10, unwind unreachable]; ++ _35 = BitXor(_1, _2); ++ _34 = opaque::<u64>(_35) -> [return: bb10, unwind unreachable]; + } + + bb10: { +- StorageDead(_35); + StorageDead(_34); + StorageLive(_38); +- StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- StorageLive(_41); +- _41 = _2; +- _39 = Shl(move _40, move _41); +- StorageDead(_41); +- StorageDead(_40); +- _38 = opaque::<u64>(move _39) -> [return: bb11, unwind unreachable]; ++ _39 = Shl(_1, _2); ++ _38 = opaque::<u64>(_39) -> [return: bb11, unwind unreachable]; + } + + bb11: { +- StorageDead(_39); + StorageDead(_38); + StorageLive(_42); +- StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- StorageLive(_45); +- _45 = _2; +- _43 = Shr(move _44, move _45); +- StorageDead(_45); +- StorageDead(_44); +- _42 = opaque::<u64>(move _43) -> [return: bb12, unwind unreachable]; ++ _43 = Shr(_1, _2); ++ _42 = opaque::<u64>(_43) -> [return: bb12, unwind unreachable]; + } + + bb12: { +- StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _47 = move _48 as u32 (IntToInt); +- StorageDead(_48); ++ _47 = _1 as u32 (IntToInt); + _46 = opaque::<u32>(move _47) -> [return: bb13, unwind unreachable]; + } + + bb13: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_49); + StorageLive(_50); +- StorageLive(_51); +- _51 = _1; +- _50 = move _51 as f32 (IntToFloat); +- StorageDead(_51); ++ _50 = _1 as f32 (IntToFloat); + _49 = opaque::<f32>(move _50) -> [return: bb14, unwind unreachable]; + } + + bb14: { + StorageDead(_50); + StorageDead(_49); + StorageLive(_52); +- StorageLive(_53); +- StorageLive(_54); +- _54 = _1; +- _53 = S::<u64>(move _54); +- StorageDead(_54); +- _52 = opaque::<S<u64>>(move _53) -> [return: bb15, unwind unreachable]; ++ _53 = S::<u64>(_1); ++ _52 = opaque::<S<u64>>(_53) -> [return: bb15, unwind unreachable]; + } + + bb15: { +- StorageDead(_53); + StorageDead(_52); + StorageLive(_55); +- StorageLive(_56); +- StorageLive(_57); +- StorageLive(_58); +- _58 = _1; +- _57 = S::<u64>(move _58); +- StorageDead(_58); +- _56 = (_57.0: u64); +- _55 = opaque::<u64>(move _56) -> [return: bb16, unwind unreachable]; ++ _56 = (_53.0: u64); ++ _55 = opaque::<u64>(_56) -> [return: bb16, unwind unreachable]; + } + + bb16: { +- StorageDead(_56); +- StorageDead(_57); + StorageDead(_55); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- StorageLive(_62); +- _62 = _1; +- StorageLive(_63); +- _63 = _2; +- _61 = Add(move _62, move _63); +- StorageDead(_63); +- StorageDead(_62); + StorageLive(_64); + _64 = _3; +- _60 = Add(move _61, move _64); ++ _60 = Add(_5, move _64); + StorageDead(_64); +- StorageDead(_61); + _59 = opaque::<u64>(move _60) -> [return: bb17, unwind unreachable]; + } + + bb17: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_65); + StorageLive(_66); +- StorageLive(_67); +- StorageLive(_68); +- _68 = _1; +- StorageLive(_69); +- _69 = _2; +- _67 = Mul(move _68, move _69); +- StorageDead(_69); +- StorageDead(_68); + StorageLive(_70); + _70 = _3; +- _66 = Add(move _67, move _70); ++ _66 = Add(_9, move _70); + StorageDead(_70); +- StorageDead(_67); + _65 = opaque::<u64>(move _66) -> [return: bb18, unwind unreachable]; + } + + bb18: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_71); + StorageLive(_72); +- StorageLive(_73); +- StorageLive(_74); +- _74 = _1; +- StorageLive(_75); +- _75 = _2; +- _73 = Sub(move _74, move _75); +- StorageDead(_75); +- StorageDead(_74); + StorageLive(_76); + _76 = _3; +- _72 = Add(move _73, move _76); ++ _72 = Add(_13, move _76); + StorageDead(_76); +- StorageDead(_73); + _71 = opaque::<u64>(move _72) -> [return: bb19, unwind unreachable]; + } + + bb19: { + StorageDead(_72); + StorageDead(_71); + StorageLive(_77); + StorageLive(_78); +- StorageLive(_79); +- StorageLive(_80); +- _80 = _1; +- StorageLive(_81); +- _81 = _2; +- _82 = Eq(_81, const 0_u64); +- assert(!move _82, "attempt to divide `{}` by zero", _80) -> [success: bb20, unwind unreachable]; ++ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb20, unwind unreachable]; + } + + bb20: { +- _79 = Div(move _80, move _81); +- StorageDead(_81); +- StorageDead(_80); + StorageLive(_83); + _83 = _3; +- _78 = Add(move _79, move _83); ++ _78 = Add(_17, move _83); + StorageDead(_83); +- StorageDead(_79); + _77 = opaque::<u64>(move _78) -> [return: bb21, unwind unreachable]; + } + + bb21: { + StorageDead(_78); + StorageDead(_77); + StorageLive(_84); + StorageLive(_85); +- StorageLive(_86); +- StorageLive(_87); +- _87 = _1; +- StorageLive(_88); +- _88 = _2; +- _89 = Eq(_88, const 0_u64); +- assert(!move _89, "attempt to calculate the remainder of `{}` with a divisor of zero", _87) -> [success: bb22, unwind unreachable]; ++ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb22, unwind unreachable]; + } + + bb22: { +- _86 = Rem(move _87, move _88); +- StorageDead(_88); +- StorageDead(_87); + StorageLive(_90); + _90 = _3; +- _85 = Add(move _86, move _90); ++ _85 = Add(_22, move _90); + StorageDead(_90); +- StorageDead(_86); + _84 = opaque::<u64>(move _85) -> [return: bb23, unwind unreachable]; + } + + bb23: { + StorageDead(_85); + StorageDead(_84); + StorageLive(_91); + StorageLive(_92); +- StorageLive(_93); +- StorageLive(_94); +- _94 = _1; +- StorageLive(_95); +- _95 = _2; +- _93 = BitAnd(move _94, move _95); +- StorageDead(_95); +- StorageDead(_94); + StorageLive(_96); + _96 = _3; +- _92 = Add(move _93, move _96); ++ _92 = Add(_27, move _96); + StorageDead(_96); +- StorageDead(_93); + _91 = opaque::<u64>(move _92) -> [return: bb24, unwind unreachable]; + } + + bb24: { + StorageDead(_92); + StorageDead(_91); + StorageLive(_97); + StorageLive(_98); +- StorageLive(_99); +- StorageLive(_100); +- _100 = _1; +- StorageLive(_101); +- _101 = _2; +- _99 = BitOr(move _100, move _101); +- StorageDead(_101); +- StorageDead(_100); + StorageLive(_102); + _102 = _3; +- _98 = Add(move _99, move _102); ++ _98 = Add(_31, move _102); + StorageDead(_102); +- StorageDead(_99); + _97 = opaque::<u64>(move _98) -> [return: bb25, unwind unreachable]; + } + + bb25: { + StorageDead(_98); + StorageDead(_97); + StorageLive(_103); + StorageLive(_104); +- StorageLive(_105); +- StorageLive(_106); +- _106 = _1; +- StorageLive(_107); +- _107 = _2; +- _105 = BitXor(move _106, move _107); +- StorageDead(_107); +- StorageDead(_106); + StorageLive(_108); + _108 = _3; +- _104 = Add(move _105, move _108); ++ _104 = Add(_35, move _108); + StorageDead(_108); +- StorageDead(_105); + _103 = opaque::<u64>(move _104) -> [return: bb26, unwind unreachable]; + } + + bb26: { + StorageDead(_104); + StorageDead(_103); + StorageLive(_109); + StorageLive(_110); +- StorageLive(_111); +- StorageLive(_112); +- _112 = _1; +- StorageLive(_113); +- _113 = _2; +- _111 = Shl(move _112, move _113); +- StorageDead(_113); +- StorageDead(_112); + StorageLive(_114); + _114 = _3; +- _110 = Add(move _111, move _114); ++ _110 = Add(_39, move _114); + StorageDead(_114); +- StorageDead(_111); + _109 = opaque::<u64>(move _110) -> [return: bb27, unwind unreachable]; + } + + bb27: { + StorageDead(_110); + StorageDead(_109); + StorageLive(_115); + StorageLive(_116); +- StorageLive(_117); +- StorageLive(_118); +- _118 = _1; +- StorageLive(_119); +- _119 = _2; +- _117 = Shr(move _118, move _119); +- StorageDead(_119); +- StorageDead(_118); + StorageLive(_120); + _120 = _3; +- _116 = Add(move _117, move _120); ++ _116 = Add(_43, move _120); + StorageDead(_120); +- StorageDead(_117); + _115 = opaque::<u64>(move _116) -> [return: bb28, unwind unreachable]; + } + + bb28: { + StorageDead(_116); + StorageDead(_115); + StorageLive(_121); +- StorageLive(_122); +- StorageLive(_123); +- _123 = _1; +- _122 = S::<u64>(move _123); +- StorageDead(_123); +- _121 = opaque::<S<u64>>(move _122) -> [return: bb29, unwind unreachable]; ++ _121 = opaque::<S<u64>>(_53) -> [return: bb29, unwind unreachable]; + } + + bb29: { +- StorageDead(_122); + StorageDead(_121); + StorageLive(_124); +- StorageLive(_125); +- StorageLive(_126); +- StorageLive(_127); +- _127 = _1; +- _126 = S::<u64>(move _127); +- StorageDead(_127); +- _125 = (_126.0: u64); +- _124 = opaque::<u64>(move _125) -> [return: bb30, unwind unreachable]; ++ _124 = opaque::<u64>(_56) -> [return: bb30, unwind unreachable]; + } + + bb30: { +- StorageDead(_125); +- StorageDead(_126); + StorageDead(_124); + StorageLive(_128); + _128 = &_3; + StorageLive(_129); +- StorageLive(_130); +- StorageLive(_131); + _131 = (*_128); +- StorageLive(_132); +- _132 = _1; +- _130 = Add(move _131, move _132); +- StorageDead(_132); +- StorageDead(_131); +- _129 = opaque::<u64>(move _130) -> [return: bb31, unwind unreachable]; ++ _130 = Add(_131, _1); ++ _129 = opaque::<u64>(_130) -> [return: bb31, unwind unreachable]; + } + + bb31: { +- StorageDead(_130); + StorageDead(_129); + StorageLive(_133); +- StorageLive(_134); +- StorageLive(_135); +- _135 = (*_128); +- StorageLive(_136); +- _136 = _1; +- _134 = Add(move _135, move _136); +- StorageDead(_136); +- StorageDead(_135); +- _133 = opaque::<u64>(move _134) -> [return: bb32, unwind unreachable]; ++ _133 = opaque::<u64>(_130) -> [return: bb32, unwind unreachable]; + } + + bb32: { +- StorageDead(_134); + StorageDead(_133); + StorageLive(_137); + _137 = &mut _3; + StorageLive(_138); + StorageLive(_139); + StorageLive(_140); + _140 = (*_137); +- StorageLive(_141); +- _141 = _1; +- _139 = Add(move _140, move _141); +- StorageDead(_141); ++ _139 = Add(move _140, _1); + StorageDead(_140); + _138 = opaque::<u64>(move _139) -> [return: bb33, unwind unreachable]; + } + + bb33: { + StorageDead(_139); + StorageDead(_138); + StorageLive(_142); + StorageLive(_143); + StorageLive(_144); + _144 = (*_137); +- StorageLive(_145); +- _145 = _1; +- _143 = Add(move _144, move _145); +- StorageDead(_145); ++ _143 = Add(move _144, _1); + StorageDead(_144); + _142 = opaque::<u64>(move _143) -> [return: bb34, unwind unreachable]; + } + + bb34: { + StorageDead(_143); + StorageDead(_142); +- StorageLive(_146); + StorageLive(_147); + _147 = &raw const _3; + StorageLive(_148); + StorageLive(_149); + StorageLive(_150); + _150 = (*_147); +- StorageLive(_151); +- _151 = _1; +- _149 = Add(move _150, move _151); +- StorageDead(_151); ++ _149 = Add(move _150, _1); + StorageDead(_150); + _148 = opaque::<u64>(move _149) -> [return: bb35, unwind unreachable]; + } + + bb35: { + StorageDead(_149); + StorageDead(_148); + StorageLive(_152); + StorageLive(_153); + StorageLive(_154); + _154 = (*_147); +- StorageLive(_155); +- _155 = _1; +- _153 = Add(move _154, move _155); +- StorageDead(_155); ++ _153 = Add(move _154, _1); + StorageDead(_154); + _152 = opaque::<u64>(move _153) -> [return: bb36, unwind unreachable]; + } + + bb36: { + StorageDead(_153); + StorageDead(_152); + StorageLive(_156); + _156 = &raw mut _3; + StorageLive(_157); + StorageLive(_158); + StorageLive(_159); + _159 = (*_156); +- StorageLive(_160); +- _160 = _1; +- _158 = Add(move _159, move _160); +- StorageDead(_160); ++ _158 = Add(move _159, _1); + StorageDead(_159); + _157 = opaque::<u64>(move _158) -> [return: bb37, unwind unreachable]; + } + + bb37: { + StorageDead(_158); + StorageDead(_157); + StorageLive(_161); + StorageLive(_162); + StorageLive(_163); + _163 = (*_156); +- StorageLive(_164); +- _164 = _1; +- _162 = Add(move _163, move _164); +- StorageDead(_164); ++ _162 = Add(move _163, _1); + StorageDead(_163); + _161 = opaque::<u64>(move _162) -> [return: bb38, unwind unreachable]; + } + + bb38: { + StorageDead(_162); + StorageDead(_161); +- _146 = const (); + StorageDead(_156); + StorageDead(_147); +- StorageDead(_146); + StorageLive(_165); + _165 = &_3; + StorageLive(_166); +- StorageLive(_167); +- StorageLive(_168); + _168 = (*_165); +- StorageLive(_169); +- _169 = _1; +- _167 = Add(move _168, move _169); +- StorageDead(_169); +- StorageDead(_168); +- _166 = opaque::<u64>(move _167) -> [return: bb39, unwind unreachable]; ++ _167 = Add(_168, _1); ++ _166 = opaque::<u64>(_167) -> [return: bb39, unwind unreachable]; + } + + bb39: { +- StorageDead(_167); + StorageDead(_166); + StorageLive(_170); +- StorageLive(_171); +- StorageLive(_172); +- _172 = (*_165); +- StorageLive(_173); +- _173 = _1; +- _171 = Add(move _172, move _173); +- StorageDead(_173); +- StorageDead(_172); +- _170 = opaque::<u64>(move _171) -> [return: bb40, unwind unreachable]; ++ _170 = opaque::<u64>(_167) -> [return: bb40, unwind unreachable]; + } + + bb40: { +- StorageDead(_171); + StorageDead(_170); + _0 = const (); + StorageDead(_165); + StorageDead(_137); + StorageDead(_128); + return; + } + } + diff --git a/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff new file mode 100644 index 00000000000..68b05290719 --- /dev/null +++ b/tests/mir-opt/gvn.subexpression_elimination.GVN.panic-unwind.diff @@ -0,0 +1,883 @@ +- // MIR for `subexpression_elimination` before GVN ++ // MIR for `subexpression_elimination` after GVN + + fn subexpression_elimination(_1: u64, _2: u64, _3: u64) -> () { + debug x => _1; + debug y => _2; + debug z => _3; + let mut _0: (); + let _4: (); + let mut _5: u64; + let mut _6: u64; + let mut _7: u64; + let _8: (); + let mut _9: u64; + let mut _10: u64; + let mut _11: u64; + let _12: (); + let mut _13: u64; + let mut _14: u64; + let mut _15: u64; + let _16: (); + let mut _17: u64; + let mut _18: u64; + let mut _19: u64; + let mut _20: bool; + let _21: (); + let mut _22: u64; + let mut _23: u64; + let mut _24: u64; + let mut _25: bool; + let _26: (); + let mut _27: u64; + let mut _28: u64; + let mut _29: u64; + let _30: (); + let mut _31: u64; + let mut _32: u64; + let mut _33: u64; + let _34: (); + let mut _35: u64; + let mut _36: u64; + let mut _37: u64; + let _38: (); + let mut _39: u64; + let mut _40: u64; + let mut _41: u64; + let _42: (); + let mut _43: u64; + let mut _44: u64; + let mut _45: u64; + let _46: (); + let mut _47: u32; + let mut _48: u64; + let _49: (); + let mut _50: f32; + let mut _51: u64; + let _52: (); + let mut _53: S<u64>; + let mut _54: u64; + let _55: (); + let mut _56: u64; + let mut _57: S<u64>; + let mut _58: u64; + let _59: (); + let mut _60: u64; + let mut _61: u64; + let mut _62: u64; + let mut _63: u64; + let mut _64: u64; + let _65: (); + let mut _66: u64; + let mut _67: u64; + let mut _68: u64; + let mut _69: u64; + let mut _70: u64; + let _71: (); + let mut _72: u64; + let mut _73: u64; + let mut _74: u64; + let mut _75: u64; + let mut _76: u64; + let _77: (); + let mut _78: u64; + let mut _79: u64; + let mut _80: u64; + let mut _81: u64; + let mut _82: bool; + let mut _83: u64; + let _84: (); + let mut _85: u64; + let mut _86: u64; + let mut _87: u64; + let mut _88: u64; + let mut _89: bool; + let mut _90: u64; + let _91: (); + let mut _92: u64; + let mut _93: u64; + let mut _94: u64; + let mut _95: u64; + let mut _96: u64; + let _97: (); + let mut _98: u64; + let mut _99: u64; + let mut _100: u64; + let mut _101: u64; + let mut _102: u64; + let _103: (); + let mut _104: u64; + let mut _105: u64; + let mut _106: u64; + let mut _107: u64; + let mut _108: u64; + let _109: (); + let mut _110: u64; + let mut _111: u64; + let mut _112: u64; + let mut _113: u64; + let mut _114: u64; + let _115: (); + let mut _116: u64; + let mut _117: u64; + let mut _118: u64; + let mut _119: u64; + let mut _120: u64; + let _121: (); + let mut _122: S<u64>; + let mut _123: u64; + let _124: (); + let mut _125: u64; + let mut _126: S<u64>; + let mut _127: u64; + let _128: &u64; + let _129: (); + let mut _130: u64; + let mut _131: u64; + let mut _132: u64; + let _133: (); + let mut _134: u64; + let mut _135: u64; + let mut _136: u64; + let _138: (); + let mut _139: u64; + let mut _140: u64; + let mut _141: u64; + let _142: (); + let mut _143: u64; + let mut _144: u64; + let mut _145: u64; + let _146: (); + let _148: (); + let mut _149: u64; + let mut _150: u64; + let mut _151: u64; + let _152: (); + let mut _153: u64; + let mut _154: u64; + let mut _155: u64; + let _157: (); + let mut _158: u64; + let mut _159: u64; + let mut _160: u64; + let _161: (); + let mut _162: u64; + let mut _163: u64; + let mut _164: u64; + let _166: (); + let mut _167: u64; + let mut _168: u64; + let mut _169: u64; + let _170: (); + let mut _171: u64; + let mut _172: u64; + let mut _173: u64; + scope 1 { + debug a => _128; + let _137: &mut u64; + scope 2 { + debug b => _137; + let _165: &u64; + scope 3 { + let _147: *const u64; + scope 4 { + debug c => _147; + let _156: *mut u64; + scope 5 { + debug d => _156; + } + } + } + scope 6 { + debug e => _165; + } + } + } + + bb0: { + StorageLive(_4); +- StorageLive(_5); +- StorageLive(_6); +- _6 = _1; +- StorageLive(_7); +- _7 = _2; +- _5 = Add(move _6, move _7); +- StorageDead(_7); +- StorageDead(_6); +- _4 = opaque::<u64>(move _5) -> [return: bb1, unwind continue]; ++ _5 = Add(_1, _2); ++ _4 = opaque::<u64>(_5) -> [return: bb1, unwind continue]; + } + + bb1: { +- StorageDead(_5); + StorageDead(_4); + StorageLive(_8); +- StorageLive(_9); +- StorageLive(_10); +- _10 = _1; +- StorageLive(_11); +- _11 = _2; +- _9 = Mul(move _10, move _11); +- StorageDead(_11); +- StorageDead(_10); +- _8 = opaque::<u64>(move _9) -> [return: bb2, unwind continue]; ++ _9 = Mul(_1, _2); ++ _8 = opaque::<u64>(_9) -> [return: bb2, unwind continue]; + } + + bb2: { +- StorageDead(_9); + StorageDead(_8); + StorageLive(_12); +- StorageLive(_13); +- StorageLive(_14); +- _14 = _1; +- StorageLive(_15); +- _15 = _2; +- _13 = Sub(move _14, move _15); +- StorageDead(_15); +- StorageDead(_14); +- _12 = opaque::<u64>(move _13) -> [return: bb3, unwind continue]; ++ _13 = Sub(_1, _2); ++ _12 = opaque::<u64>(_13) -> [return: bb3, unwind continue]; + } + + bb3: { +- StorageDead(_13); + StorageDead(_12); + StorageLive(_16); +- StorageLive(_17); +- StorageLive(_18); +- _18 = _1; +- StorageLive(_19); +- _19 = _2; +- _20 = Eq(_19, const 0_u64); +- assert(!move _20, "attempt to divide `{}` by zero", _18) -> [success: bb4, unwind continue]; ++ _20 = Eq(_2, const 0_u64); ++ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb4, unwind continue]; + } + + bb4: { +- _17 = Div(move _18, move _19); +- StorageDead(_19); +- StorageDead(_18); +- _16 = opaque::<u64>(move _17) -> [return: bb5, unwind continue]; ++ _17 = Div(_1, _2); ++ _16 = opaque::<u64>(_17) -> [return: bb5, unwind continue]; + } + + bb5: { +- StorageDead(_17); + StorageDead(_16); + StorageLive(_21); +- StorageLive(_22); +- StorageLive(_23); +- _23 = _1; +- StorageLive(_24); +- _24 = _2; +- _25 = Eq(_24, const 0_u64); +- assert(!move _25, "attempt to calculate the remainder of `{}` with a divisor of zero", _23) -> [success: bb6, unwind continue]; ++ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb6, unwind continue]; + } + + bb6: { +- _22 = Rem(move _23, move _24); +- StorageDead(_24); +- StorageDead(_23); +- _21 = opaque::<u64>(move _22) -> [return: bb7, unwind continue]; ++ _22 = Rem(_1, _2); ++ _21 = opaque::<u64>(_22) -> [return: bb7, unwind continue]; + } + + bb7: { +- StorageDead(_22); + StorageDead(_21); + StorageLive(_26); +- StorageLive(_27); +- StorageLive(_28); +- _28 = _1; +- StorageLive(_29); +- _29 = _2; +- _27 = BitAnd(move _28, move _29); +- StorageDead(_29); +- StorageDead(_28); +- _26 = opaque::<u64>(move _27) -> [return: bb8, unwind continue]; ++ _27 = BitAnd(_1, _2); ++ _26 = opaque::<u64>(_27) -> [return: bb8, unwind continue]; + } + + bb8: { +- StorageDead(_27); + StorageDead(_26); + StorageLive(_30); +- StorageLive(_31); +- StorageLive(_32); +- _32 = _1; +- StorageLive(_33); +- _33 = _2; +- _31 = BitOr(move _32, move _33); +- StorageDead(_33); +- StorageDead(_32); +- _30 = opaque::<u64>(move _31) -> [return: bb9, unwind continue]; ++ _31 = BitOr(_1, _2); ++ _30 = opaque::<u64>(_31) -> [return: bb9, unwind continue]; + } + + bb9: { +- StorageDead(_31); + StorageDead(_30); + StorageLive(_34); +- StorageLive(_35); +- StorageLive(_36); +- _36 = _1; +- StorageLive(_37); +- _37 = _2; +- _35 = BitXor(move _36, move _37); +- StorageDead(_37); +- StorageDead(_36); +- _34 = opaque::<u64>(move _35) -> [return: bb10, unwind continue]; ++ _35 = BitXor(_1, _2); ++ _34 = opaque::<u64>(_35) -> [return: bb10, unwind continue]; + } + + bb10: { +- StorageDead(_35); + StorageDead(_34); + StorageLive(_38); +- StorageLive(_39); +- StorageLive(_40); +- _40 = _1; +- StorageLive(_41); +- _41 = _2; +- _39 = Shl(move _40, move _41); +- StorageDead(_41); +- StorageDead(_40); +- _38 = opaque::<u64>(move _39) -> [return: bb11, unwind continue]; ++ _39 = Shl(_1, _2); ++ _38 = opaque::<u64>(_39) -> [return: bb11, unwind continue]; + } + + bb11: { +- StorageDead(_39); + StorageDead(_38); + StorageLive(_42); +- StorageLive(_43); +- StorageLive(_44); +- _44 = _1; +- StorageLive(_45); +- _45 = _2; +- _43 = Shr(move _44, move _45); +- StorageDead(_45); +- StorageDead(_44); +- _42 = opaque::<u64>(move _43) -> [return: bb12, unwind continue]; ++ _43 = Shr(_1, _2); ++ _42 = opaque::<u64>(_43) -> [return: bb12, unwind continue]; + } + + bb12: { +- StorageDead(_43); + StorageDead(_42); + StorageLive(_46); + StorageLive(_47); +- StorageLive(_48); +- _48 = _1; +- _47 = move _48 as u32 (IntToInt); +- StorageDead(_48); ++ _47 = _1 as u32 (IntToInt); + _46 = opaque::<u32>(move _47) -> [return: bb13, unwind continue]; + } + + bb13: { + StorageDead(_47); + StorageDead(_46); + StorageLive(_49); + StorageLive(_50); +- StorageLive(_51); +- _51 = _1; +- _50 = move _51 as f32 (IntToFloat); +- StorageDead(_51); ++ _50 = _1 as f32 (IntToFloat); + _49 = opaque::<f32>(move _50) -> [return: bb14, unwind continue]; + } + + bb14: { + StorageDead(_50); + StorageDead(_49); + StorageLive(_52); +- StorageLive(_53); +- StorageLive(_54); +- _54 = _1; +- _53 = S::<u64>(move _54); +- StorageDead(_54); +- _52 = opaque::<S<u64>>(move _53) -> [return: bb15, unwind continue]; ++ _53 = S::<u64>(_1); ++ _52 = opaque::<S<u64>>(_53) -> [return: bb15, unwind continue]; + } + + bb15: { +- StorageDead(_53); + StorageDead(_52); + StorageLive(_55); +- StorageLive(_56); +- StorageLive(_57); +- StorageLive(_58); +- _58 = _1; +- _57 = S::<u64>(move _58); +- StorageDead(_58); +- _56 = (_57.0: u64); +- _55 = opaque::<u64>(move _56) -> [return: bb16, unwind continue]; ++ _56 = (_53.0: u64); ++ _55 = opaque::<u64>(_56) -> [return: bb16, unwind continue]; + } + + bb16: { +- StorageDead(_56); +- StorageDead(_57); + StorageDead(_55); + StorageLive(_59); + StorageLive(_60); +- StorageLive(_61); +- StorageLive(_62); +- _62 = _1; +- StorageLive(_63); +- _63 = _2; +- _61 = Add(move _62, move _63); +- StorageDead(_63); +- StorageDead(_62); + StorageLive(_64); + _64 = _3; +- _60 = Add(move _61, move _64); ++ _60 = Add(_5, move _64); + StorageDead(_64); +- StorageDead(_61); + _59 = opaque::<u64>(move _60) -> [return: bb17, unwind continue]; + } + + bb17: { + StorageDead(_60); + StorageDead(_59); + StorageLive(_65); + StorageLive(_66); +- StorageLive(_67); +- StorageLive(_68); +- _68 = _1; +- StorageLive(_69); +- _69 = _2; +- _67 = Mul(move _68, move _69); +- StorageDead(_69); +- StorageDead(_68); + StorageLive(_70); + _70 = _3; +- _66 = Add(move _67, move _70); ++ _66 = Add(_9, move _70); + StorageDead(_70); +- StorageDead(_67); + _65 = opaque::<u64>(move _66) -> [return: bb18, unwind continue]; + } + + bb18: { + StorageDead(_66); + StorageDead(_65); + StorageLive(_71); + StorageLive(_72); +- StorageLive(_73); +- StorageLive(_74); +- _74 = _1; +- StorageLive(_75); +- _75 = _2; +- _73 = Sub(move _74, move _75); +- StorageDead(_75); +- StorageDead(_74); + StorageLive(_76); + _76 = _3; +- _72 = Add(move _73, move _76); ++ _72 = Add(_13, move _76); + StorageDead(_76); +- StorageDead(_73); + _71 = opaque::<u64>(move _72) -> [return: bb19, unwind continue]; + } + + bb19: { + StorageDead(_72); + StorageDead(_71); + StorageLive(_77); + StorageLive(_78); +- StorageLive(_79); +- StorageLive(_80); +- _80 = _1; +- StorageLive(_81); +- _81 = _2; +- _82 = Eq(_81, const 0_u64); +- assert(!move _82, "attempt to divide `{}` by zero", _80) -> [success: bb20, unwind continue]; ++ assert(!_20, "attempt to divide `{}` by zero", _1) -> [success: bb20, unwind continue]; + } + + bb20: { +- _79 = Div(move _80, move _81); +- StorageDead(_81); +- StorageDead(_80); + StorageLive(_83); + _83 = _3; +- _78 = Add(move _79, move _83); ++ _78 = Add(_17, move _83); + StorageDead(_83); +- StorageDead(_79); + _77 = opaque::<u64>(move _78) -> [return: bb21, unwind continue]; + } + + bb21: { + StorageDead(_78); + StorageDead(_77); + StorageLive(_84); + StorageLive(_85); +- StorageLive(_86); +- StorageLive(_87); +- _87 = _1; +- StorageLive(_88); +- _88 = _2; +- _89 = Eq(_88, const 0_u64); +- assert(!move _89, "attempt to calculate the remainder of `{}` with a divisor of zero", _87) -> [success: bb22, unwind continue]; ++ assert(!_20, "attempt to calculate the remainder of `{}` with a divisor of zero", _1) -> [success: bb22, unwind continue]; + } + + bb22: { +- _86 = Rem(move _87, move _88); +- StorageDead(_88); +- StorageDead(_87); + StorageLive(_90); + _90 = _3; +- _85 = Add(move _86, move _90); ++ _85 = Add(_22, move _90); + StorageDead(_90); +- StorageDead(_86); + _84 = opaque::<u64>(move _85) -> [return: bb23, unwind continue]; + } + + bb23: { + StorageDead(_85); + StorageDead(_84); + StorageLive(_91); + StorageLive(_92); +- StorageLive(_93); +- StorageLive(_94); +- _94 = _1; +- StorageLive(_95); +- _95 = _2; +- _93 = BitAnd(move _94, move _95); +- StorageDead(_95); +- StorageDead(_94); + StorageLive(_96); + _96 = _3; +- _92 = Add(move _93, move _96); ++ _92 = Add(_27, move _96); + StorageDead(_96); +- StorageDead(_93); + _91 = opaque::<u64>(move _92) -> [return: bb24, unwind continue]; + } + + bb24: { + StorageDead(_92); + StorageDead(_91); + StorageLive(_97); + StorageLive(_98); +- StorageLive(_99); +- StorageLive(_100); +- _100 = _1; +- StorageLive(_101); +- _101 = _2; +- _99 = BitOr(move _100, move _101); +- StorageDead(_101); +- StorageDead(_100); + StorageLive(_102); + _102 = _3; +- _98 = Add(move _99, move _102); ++ _98 = Add(_31, move _102); + StorageDead(_102); +- StorageDead(_99); + _97 = opaque::<u64>(move _98) -> [return: bb25, unwind continue]; + } + + bb25: { + StorageDead(_98); + StorageDead(_97); + StorageLive(_103); + StorageLive(_104); +- StorageLive(_105); +- StorageLive(_106); +- _106 = _1; +- StorageLive(_107); +- _107 = _2; +- _105 = BitXor(move _106, move _107); +- StorageDead(_107); +- StorageDead(_106); + StorageLive(_108); + _108 = _3; +- _104 = Add(move _105, move _108); ++ _104 = Add(_35, move _108); + StorageDead(_108); +- StorageDead(_105); + _103 = opaque::<u64>(move _104) -> [return: bb26, unwind continue]; + } + + bb26: { + StorageDead(_104); + StorageDead(_103); + StorageLive(_109); + StorageLive(_110); +- StorageLive(_111); +- StorageLive(_112); +- _112 = _1; +- StorageLive(_113); +- _113 = _2; +- _111 = Shl(move _112, move _113); +- StorageDead(_113); +- StorageDead(_112); + StorageLive(_114); + _114 = _3; +- _110 = Add(move _111, move _114); ++ _110 = Add(_39, move _114); + StorageDead(_114); +- StorageDead(_111); + _109 = opaque::<u64>(move _110) -> [return: bb27, unwind continue]; + } + + bb27: { + StorageDead(_110); + StorageDead(_109); + StorageLive(_115); + StorageLive(_116); +- StorageLive(_117); +- StorageLive(_118); +- _118 = _1; +- StorageLive(_119); +- _119 = _2; +- _117 = Shr(move _118, move _119); +- StorageDead(_119); +- StorageDead(_118); + StorageLive(_120); + _120 = _3; +- _116 = Add(move _117, move _120); ++ _116 = Add(_43, move _120); + StorageDead(_120); +- StorageDead(_117); + _115 = opaque::<u64>(move _116) -> [return: bb28, unwind continue]; + } + + bb28: { + StorageDead(_116); + StorageDead(_115); + StorageLive(_121); +- StorageLive(_122); +- StorageLive(_123); +- _123 = _1; +- _122 = S::<u64>(move _123); +- StorageDead(_123); +- _121 = opaque::<S<u64>>(move _122) -> [return: bb29, unwind continue]; ++ _121 = opaque::<S<u64>>(_53) -> [return: bb29, unwind continue]; + } + + bb29: { +- StorageDead(_122); + StorageDead(_121); + StorageLive(_124); +- StorageLive(_125); +- StorageLive(_126); +- StorageLive(_127); +- _127 = _1; +- _126 = S::<u64>(move _127); +- StorageDead(_127); +- _125 = (_126.0: u64); +- _124 = opaque::<u64>(move _125) -> [return: bb30, unwind continue]; ++ _124 = opaque::<u64>(_56) -> [return: bb30, unwind continue]; + } + + bb30: { +- StorageDead(_125); +- StorageDead(_126); + StorageDead(_124); + StorageLive(_128); + _128 = &_3; + StorageLive(_129); +- StorageLive(_130); +- StorageLive(_131); + _131 = (*_128); +- StorageLive(_132); +- _132 = _1; +- _130 = Add(move _131, move _132); +- StorageDead(_132); +- StorageDead(_131); +- _129 = opaque::<u64>(move _130) -> [return: bb31, unwind continue]; ++ _130 = Add(_131, _1); ++ _129 = opaque::<u64>(_130) -> [return: bb31, unwind continue]; + } + + bb31: { +- StorageDead(_130); + StorageDead(_129); + StorageLive(_133); +- StorageLive(_134); +- StorageLive(_135); +- _135 = (*_128); +- StorageLive(_136); +- _136 = _1; +- _134 = Add(move _135, move _136); +- StorageDead(_136); +- StorageDead(_135); +- _133 = opaque::<u64>(move _134) -> [return: bb32, unwind continue]; ++ _133 = opaque::<u64>(_130) -> [return: bb32, unwind continue]; + } + + bb32: { +- StorageDead(_134); + StorageDead(_133); + StorageLive(_137); + _137 = &mut _3; + StorageLive(_138); + StorageLive(_139); + StorageLive(_140); + _140 = (*_137); +- StorageLive(_141); +- _141 = _1; +- _139 = Add(move _140, move _141); +- StorageDead(_141); ++ _139 = Add(move _140, _1); + StorageDead(_140); + _138 = opaque::<u64>(move _139) -> [return: bb33, unwind continue]; + } + + bb33: { + StorageDead(_139); + StorageDead(_138); + StorageLive(_142); + StorageLive(_143); + StorageLive(_144); + _144 = (*_137); +- StorageLive(_145); +- _145 = _1; +- _143 = Add(move _144, move _145); +- StorageDead(_145); ++ _143 = Add(move _144, _1); + StorageDead(_144); + _142 = opaque::<u64>(move _143) -> [return: bb34, unwind continue]; + } + + bb34: { + StorageDead(_143); + StorageDead(_142); +- StorageLive(_146); + StorageLive(_147); + _147 = &raw const _3; + StorageLive(_148); + StorageLive(_149); + StorageLive(_150); + _150 = (*_147); +- StorageLive(_151); +- _151 = _1; +- _149 = Add(move _150, move _151); +- StorageDead(_151); ++ _149 = Add(move _150, _1); + StorageDead(_150); + _148 = opaque::<u64>(move _149) -> [return: bb35, unwind continue]; + } + + bb35: { + StorageDead(_149); + StorageDead(_148); + StorageLive(_152); + StorageLive(_153); + StorageLive(_154); + _154 = (*_147); +- StorageLive(_155); +- _155 = _1; +- _153 = Add(move _154, move _155); +- StorageDead(_155); ++ _153 = Add(move _154, _1); + StorageDead(_154); + _152 = opaque::<u64>(move _153) -> [return: bb36, unwind continue]; + } + + bb36: { + StorageDead(_153); + StorageDead(_152); + StorageLive(_156); + _156 = &raw mut _3; + StorageLive(_157); + StorageLive(_158); + StorageLive(_159); + _159 = (*_156); +- StorageLive(_160); +- _160 = _1; +- _158 = Add(move _159, move _160); +- StorageDead(_160); ++ _158 = Add(move _159, _1); + StorageDead(_159); + _157 = opaque::<u64>(move _158) -> [return: bb37, unwind continue]; + } + + bb37: { + StorageDead(_158); + StorageDead(_157); + StorageLive(_161); + StorageLive(_162); + StorageLive(_163); + _163 = (*_156); +- StorageLive(_164); +- _164 = _1; +- _162 = Add(move _163, move _164); +- StorageDead(_164); ++ _162 = Add(move _163, _1); + StorageDead(_163); + _161 = opaque::<u64>(move _162) -> [return: bb38, unwind continue]; + } + + bb38: { + StorageDead(_162); + StorageDead(_161); +- _146 = const (); + StorageDead(_156); + StorageDead(_147); +- StorageDead(_146); + StorageLive(_165); + _165 = &_3; + StorageLive(_166); +- StorageLive(_167); +- StorageLive(_168); + _168 = (*_165); +- StorageLive(_169); +- _169 = _1; +- _167 = Add(move _168, move _169); +- StorageDead(_169); +- StorageDead(_168); +- _166 = opaque::<u64>(move _167) -> [return: bb39, unwind continue]; ++ _167 = Add(_168, _1); ++ _166 = opaque::<u64>(_167) -> [return: bb39, unwind continue]; + } + + bb39: { +- StorageDead(_167); + StorageDead(_166); + StorageLive(_170); +- StorageLive(_171); +- StorageLive(_172); +- _172 = (*_165); +- StorageLive(_173); +- _173 = _1; +- _171 = Add(move _172, move _173); +- StorageDead(_173); +- StorageDead(_172); +- _170 = opaque::<u64>(move _171) -> [return: bb40, unwind continue]; ++ _170 = opaque::<u64>(_167) -> [return: bb40, unwind continue]; + } + + bb40: { +- StorageDead(_171); + StorageDead(_170); + _0 = const (); + StorageDead(_165); + StorageDead(_137); + StorageDead(_128); + return; + } + } + diff --git a/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-abort.diff b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-abort.diff new file mode 100644 index 00000000000..f33845502ad --- /dev/null +++ b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-abort.diff @@ -0,0 +1,45 @@ +- // MIR for `wrap_unwrap` before GVN ++ // MIR for `wrap_unwrap` after GVN + + fn wrap_unwrap(_1: T) -> T { + debug x => _1; + let mut _0: T; + let mut _2: std::option::Option<T>; + let mut _3: T; + let mut _4: isize; + let _5: T; + let mut _6: !; + scope 1 { + debug y => _5; + } + + bb0: { + StorageLive(_2); +- StorageLive(_3); +- _3 = _1; +- _2 = Option::<T>::Some(move _3); +- StorageDead(_3); ++ _2 = Option::<T>::Some(_1); + _4 = discriminant(_2); + switchInt(move _4) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { + StorageLive(_6); + _6 = begin_panic::<&str>(const "explicit panic") -> unwind unreachable; + } + + bb2: { + unreachable; + } + + bb3: { +- StorageLive(_5); + _5 = ((_2 as Some).0: T); + _0 = _5; +- StorageDead(_5); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-unwind.diff b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-unwind.diff new file mode 100644 index 00000000000..edc05f99fe2 --- /dev/null +++ b/tests/mir-opt/gvn.wrap_unwrap.GVN.panic-unwind.diff @@ -0,0 +1,45 @@ +- // MIR for `wrap_unwrap` before GVN ++ // MIR for `wrap_unwrap` after GVN + + fn wrap_unwrap(_1: T) -> T { + debug x => _1; + let mut _0: T; + let mut _2: std::option::Option<T>; + let mut _3: T; + let mut _4: isize; + let _5: T; + let mut _6: !; + scope 1 { + debug y => _5; + } + + bb0: { + StorageLive(_2); +- StorageLive(_3); +- _3 = _1; +- _2 = Option::<T>::Some(move _3); +- StorageDead(_3); ++ _2 = Option::<T>::Some(_1); + _4 = discriminant(_2); + switchInt(move _4) -> [0: bb1, 1: bb3, otherwise: bb2]; + } + + bb1: { + StorageLive(_6); + _6 = begin_panic::<&str>(const "explicit panic") -> unwind continue; + } + + bb2: { + unreachable; + } + + bb3: { +- StorageLive(_5); + _5 = ((_2 as Some).0: T); + _0 = _5; +- StorageDead(_5); + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir index 549306071ad..721fac27d88 100644 --- a/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir +++ b/tests/mir-opt/inline/inline_closure_captures.foo.Inline.after.mir @@ -42,10 +42,10 @@ fn foo(_1: T, _2: i32) -> (i32, T) { StorageLive(_9); _9 = move (_7.0: i32); StorageLive(_11); - _10 = deref_copy ((*_6).0: &i32); + _10 = ((*_6).0: &i32); _11 = (*_10); StorageLive(_13); - _12 = deref_copy ((*_6).1: &T); + _12 = ((*_6).1: &T); _13 = (*_12); _0 = (move _11, move _13); StorageDead(_13); diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff index 3f093a02dd2..6779003b693 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-abort.diff @@ -26,8 +26,6 @@ + let mut _6: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; + let mut _7: u32; + let mut _8: i32; -+ let mut _9: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; -+ let mut _10: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; + } bb0: { @@ -42,7 +40,7 @@ + StorageDead(_3); + StorageLive(_5); + _5 = const false; -+ _6 = deref_copy (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); ++ _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb3, 1: bb7, 3: bb8, otherwise: bb9]; } @@ -87,8 +85,7 @@ + + bb6: { + _1 = GeneratorState::<i32, bool>::Yielded(move _8); -+ _9 = deref_copy (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); -+ discriminant((*_9)) = 3; ++ discriminant((*_6)) = 3; + goto -> bb1; + } + @@ -100,8 +97,7 @@ + StorageLive(_8); + StorageDead(_8); + _1 = GeneratorState::<i32, bool>::Complete(_5); -+ _10 = deref_copy (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); -+ discriminant((*_10)) = 1; ++ discriminant((*_6)) = 1; + goto -> bb1; + } + diff --git a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff index 3d76262c266..31744be99ec 100644 --- a/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff +++ b/tests/mir-opt/inline/inline_generator.main.Inline.panic-unwind.diff @@ -26,8 +26,6 @@ + let mut _6: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; + let mut _7: u32; + let mut _8: i32; -+ let mut _9: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; -+ let mut _10: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}; + } bb0: { @@ -50,7 +48,7 @@ - _1 = <{generator@$DIR/inline_generator.rs:16:5: 16:8} as Generator<bool>>::resume(move _2, const false) -> [return: bb3, unwind: bb5]; + StorageLive(_5); + _5 = const false; -+ _6 = deref_copy (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); ++ _6 = (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); + _7 = discriminant((*_6)); + switchInt(move _7) -> [0: bb5, 1: bb9, 3: bb10, otherwise: bb11]; } @@ -99,8 +97,7 @@ + + bb8: { + _1 = GeneratorState::<i32, bool>::Yielded(move _8); -+ _9 = deref_copy (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); -+ discriminant((*_9)) = 3; ++ discriminant((*_6)) = 3; + goto -> bb1; + } + @@ -112,8 +109,7 @@ + StorageLive(_8); + StorageDead(_8); + _1 = GeneratorState::<i32, bool>::Complete(_5); -+ _10 = deref_copy (_2.0: &mut {generator@$DIR/inline_generator.rs:16:5: 16:8}); -+ discriminant((*_10)) = 1; ++ discriminant((*_6)) = 1; + goto -> bb1; + } + diff --git a/tests/ui-fulldeps/stable-mir/compilation-result.rs b/tests/ui-fulldeps/stable-mir/compilation-result.rs index 23a9e2a064c..3ec1519fb13 100644 --- a/tests/ui-fulldeps/stable-mir/compilation-result.rs +++ b/tests/ui-fulldeps/stable-mir/compilation-result.rs @@ -11,9 +11,10 @@ extern crate rustc_middle; extern crate rustc_smir; +extern crate stable_mir; use rustc_middle::ty::TyCtxt; -use rustc_smir::{rustc_internal, stable_mir}; +use rustc_smir::rustc_internal; use std::io::Write; use std::ops::ControlFlow; diff --git a/tests/ui-fulldeps/stable-mir/crate-info.rs b/tests/ui-fulldeps/stable-mir/crate-info.rs index a11720c4b55..ce4ee3c2463 100644 --- a/tests/ui-fulldeps/stable-mir/crate-info.rs +++ b/tests/ui-fulldeps/stable-mir/crate-info.rs @@ -13,13 +13,13 @@ extern crate rustc_hir; extern crate rustc_middle; extern crate rustc_smir; +extern crate stable_mir; use rustc_hir::def::DefKind; use rustc_middle::ty::TyCtxt; -use rustc_smir::{ - rustc_internal, - stable_mir::{self, fold::Foldable}, -}; +use rustc_smir::rustc_internal; + +use stable_mir::fold::Foldable; use std::assert_matches::assert_matches; use std::io::Write; use std::ops::ControlFlow; @@ -27,7 +27,7 @@ use std::ops::ControlFlow; 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<'_>) -> ControlFlow<()> { +fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> { // Get the local crate using stable_mir API. let local = stable_mir::local_crate(); assert_eq!(&local.name, CRATE_NAME); @@ -36,12 +36,12 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { // Find items in the local crate. let items = stable_mir::all_local_items(); - assert!(get_item(tcx, &items, (DefKind::Fn, "foo::bar")).is_some()); + assert!(get_item(&items, (DefKind::Fn, "foo::bar")).is_some()); // Find the `std` crate. assert!(stable_mir::find_crate("std").is_some()); - let bar = get_item(tcx, &items, (DefKind::Fn, "bar")).unwrap(); + let bar = get_item(&items, (DefKind::Fn, "bar")).unwrap(); let body = bar.body(); assert_eq!(body.locals.len(), 2); assert_eq!(body.blocks.len(), 1); @@ -56,7 +56,7 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { other => panic!("{other:?}"), } - let foo_bar = get_item(tcx, &items, (DefKind::Fn, "foo_bar")).unwrap(); + let foo_bar = get_item(&items, (DefKind::Fn, "foo_bar")).unwrap(); let body = foo_bar.body(); assert_eq!(body.locals.len(), 7); assert_eq!(body.blocks.len(), 4); @@ -66,7 +66,7 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { other => panic!("{other:?}"), } - let types = get_item(tcx, &items, (DefKind::Fn, "types")).unwrap(); + let types = get_item(&items, (DefKind::Fn, "types")).unwrap(); let body = types.body(); assert_eq!(body.locals.len(), 6); assert_matches!( @@ -96,7 +96,7 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { )) ); - let drop = get_item(tcx, &items, (DefKind::Fn, "drop")).unwrap(); + let drop = get_item(&items, (DefKind::Fn, "drop")).unwrap(); let body = drop.body(); assert_eq!(body.blocks.len(), 2); let block = &body.blocks[0]; @@ -105,7 +105,7 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { other => panic!("{other:?}"), } - let assert = get_item(tcx, &items, (DefKind::Fn, "assert")).unwrap(); + let assert = get_item(&items, (DefKind::Fn, "assert")).unwrap(); let body = assert.body(); assert_eq!(body.blocks.len(), 2); let block = &body.blocks[0]; @@ -114,7 +114,7 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { other => panic!("{other:?}"), } - let monomorphic = get_item(tcx, &items, (DefKind::Fn, "monomorphic")).unwrap(); + let monomorphic = get_item(&items, (DefKind::Fn, "monomorphic")).unwrap(); for block in monomorphic.body().blocks { match &block.terminator { stable_mir::mir::Terminator::Call { func, .. } => match func { @@ -154,7 +154,7 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { } } - let foo_const = get_item(tcx, &items, (DefKind::Const, "FOO")).unwrap(); + let foo_const = get_item(&items, (DefKind::Const, "FOO")).unwrap(); // Ensure we don't panic trying to get the body of a constant. foo_const.body(); @@ -163,13 +163,11 @@ fn test_stable_mir(tcx: TyCtxt<'_>) -> ControlFlow<()> { // Use internal API to find a function in a crate. fn get_item<'a>( - tcx: TyCtxt, items: &'a stable_mir::CrateItems, item: (DefKind, &str), ) -> Option<&'a stable_mir::CrateItem> { items.iter().find(|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 + crate_item.kind().to_string() == format!("{:?}", item.0) && crate_item.name() == item.1 }) } diff --git a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs index 5c59f217be6..99769692342 100644 --- a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs +++ b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs @@ -1,6 +1,5 @@ -// FIXME(inherent_associated_types): This should be `check-pass` -// known-bug: #108491 // compile-flags: --crate-type=lib +// check-pass #![feature(inherent_associated_types)] #![allow(incomplete_features)] @@ -8,11 +7,6 @@ // Bounds on the self type play a major role in the resolution of inherent associated types (*). // As a result of that, if a type alias contains any then its bounds have to be respected and the // lint `type_alias_bounds` should not fire. -// -// FIXME(inherent_associated_types): In the current implementation that is. We might move the -// selection phase of IATs from hir_typeck to trait_selection resulting in us not requiring the -// ParamEnv that early allowing us to ignore bounds on type aliases again. -// Triage this before stabilization. #![deny(type_alias_bounds)] diff --git a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.stderr b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.stderr deleted file mode 100644 index 5e18543fc90..00000000000 --- a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.stderr +++ /dev/null @@ -1,55 +0,0 @@ -error[E0391]: cycle detected when expanding type alias `Alias` - --> $DIR/type-alias-bounds-are-enforced.rs:19:1 - | -LL | pub type Alias<T: Bound> = (Source<T>::Assoc,); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires computing the variances of `Source`... - --> $DIR/type-alias-bounds-are-enforced.rs:21:1 - | -LL | pub struct Source<T>(T); - | ^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires computing the variances for items in this crate... - = note: ...which again requires expanding type alias `Alias`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/type-alias-bounds-are-enforced.rs:5:1 - | -LL | / #![feature(inherent_associated_types)] -LL | | #![allow(incomplete_features)] -LL | | -LL | | // Bounds on the self type play a major role in the resolution of inherent associated types (*). -... | -LL | | pub type Assoc = (); -LL | | } - | |_^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error[E0391]: cycle detected when expanding type alias `Alias` - --> $DIR/type-alias-bounds-are-enforced.rs:19:1 - | -LL | pub type Alias<T: Bound> = (Source<T>::Assoc,); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: ...which requires computing the variances of `Source`... - --> $DIR/type-alias-bounds-are-enforced.rs:21:1 - | -LL | pub struct Source<T>(T); - | ^^^^^^^^^^^^^^^^^^^^ - = note: ...which requires computing the variances for items in this crate... - = note: ...which again requires expanding type alias `Alias`, completing the cycle -note: cycle used when collecting item types in top-level module - --> $DIR/type-alias-bounds-are-enforced.rs:5:1 - | -LL | / #![feature(inherent_associated_types)] -LL | | #![allow(incomplete_features)] -LL | | -LL | | // Bounds on the self type play a major role in the resolution of inherent associated types (*). -... | -LL | | pub type Assoc = (); -LL | | } - | |_^ - = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/async-await/const-async-fn-in-main.rs b/tests/ui/async-await/const-async-fn-in-main.rs new file mode 100644 index 00000000000..5d1aa4d83f3 --- /dev/null +++ b/tests/ui/async-await/const-async-fn-in-main.rs @@ -0,0 +1,7 @@ +// edition:2021 +// Check what happens when a const async fn is in the main function (#102796) + +fn main() { + const async fn a() {} +//~^ ERROR functions cannot be both `const` and `async` +} diff --git a/tests/ui/async-await/const-async-fn-in-main.stderr b/tests/ui/async-await/const-async-fn-in-main.stderr new file mode 100644 index 00000000000..10b15170922 --- /dev/null +++ b/tests/ui/async-await/const-async-fn-in-main.stderr @@ -0,0 +1,11 @@ +error: functions cannot be both `const` and `async` + --> $DIR/const-async-fn-in-main.rs:5:5 + | +LL | const async fn a() {} + | ^^^^^-^^^^^---------- + | | | + | | `async` because of this + | `const` because of this + +error: aborting due to previous error + diff --git a/tests/ui/codegen/issue-79865-llvm-miscompile.rs b/tests/ui/codegen/issue-79865-llvm-miscompile.rs new file mode 100644 index 00000000000..b77f09f8e9a --- /dev/null +++ b/tests/ui/codegen/issue-79865-llvm-miscompile.rs @@ -0,0 +1,38 @@ +// run-pass +// only-x86_64 +// compile-flags: -C opt-level=3 + +// Regression test for issue #79865. +// The assertion will fail when compiled with Rust 1.56..=1.59 +// due to a LLVM miscompilation. + +use std::arch::x86_64::*; + +fn main() { + if is_x86_feature_detected!("avx") { + let res: [f64; 4] = unsafe { std::mem::transmute::<_, _>(first()) }; + assert_eq!(res, [22.0, 44.0, 66.0, 88.0]); + } +} + +#[target_feature(enable = "avx")] +unsafe fn first() -> __m256d { + second() +} + +unsafe fn second() -> __m256d { + let v0 = _mm256_setr_pd(1.0, 2.0, 3.0, 4.0); + let v1 = _mm256_setr_pd(10.0, 20.0, 30.0, 40.0); + + // needs to be called twice to hit the miscompilation + let (add, _) = add_sub(v0, v1); + let (add, _) = add_sub(add, add); + add +} + +#[inline(never)] // needed to hit the miscompilation +unsafe fn add_sub(v1: __m256d, v0: __m256d) -> (__m256d, __m256d) { + let add = _mm256_add_pd(v0, v1); + let sub = _mm256_sub_pd(v0, v1); + (add, sub) +} diff --git a/tests/ui/consts/const_in_pattern/issue-65466.rs b/tests/ui/consts/const_in_pattern/issue-65466.rs index 2b421f4c705..d45c32e170a 100644 --- a/tests/ui/consts/const_in_pattern/issue-65466.rs +++ b/tests/ui/consts/const_in_pattern/issue-65466.rs @@ -15,7 +15,8 @@ const C: &[O<B>] = &[O::None]; fn main() { let x = O::None; match &[x][..] { - C => (), + C => (), //~WARN: the type must implement `PartialEq` + //~| previously accepted _ => (), } } diff --git a/tests/ui/consts/const_in_pattern/issue-65466.stderr b/tests/ui/consts/const_in_pattern/issue-65466.stderr new file mode 100644 index 00000000000..9c80cb3a849 --- /dev/null +++ b/tests/ui/consts/const_in_pattern/issue-65466.stderr @@ -0,0 +1,23 @@ +warning: to use a constant of type `&[O<B>]` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-65466.rs:18:9 + | +LL | C => (), + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 <https://github.com/rust-lang/rust/issues/116122> + = note: `#[warn(const_patterns_without_partial_eq)]` on by default + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `&[O<B>]` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-65466.rs:18:9 + | +LL | C => (), + | ^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 <https://github.com/rust-lang/rust/issues/116122> + = note: `#[warn(const_patterns_without_partial_eq)]` on by default + diff --git a/tests/ui/error-codes/E0094.rs b/tests/ui/error-codes/E0094.rs index a2ec932c124..97ebcff99dc 100644 --- a/tests/ui/error-codes/E0094.rs +++ b/tests/ui/error-codes/E0094.rs @@ -1,4 +1,4 @@ -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] extern "rust-intrinsic" { #[rustc_safe_intrinsic] diff --git a/tests/ui/extern/extern-with-type-bounds.rs b/tests/ui/extern/extern-with-type-bounds.rs index a72aa4171a1..99e9801fd40 100644 --- a/tests/ui/extern/extern-with-type-bounds.rs +++ b/tests/ui/extern/extern-with-type-bounds.rs @@ -1,4 +1,4 @@ -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] extern "rust-intrinsic" { // Real example from libcore diff --git a/tests/ui/impl-trait/in-trait/anonymize-binders-for-refine.rs b/tests/ui/impl-trait/in-trait/anonymize-binders-for-refine.rs new file mode 100644 index 00000000000..e62662f2f07 --- /dev/null +++ b/tests/ui/impl-trait/in-trait/anonymize-binders-for-refine.rs @@ -0,0 +1,13 @@ +// compile-flags: --crate-type=lib +// check-pass + +#![feature(return_position_impl_trait_in_trait)] +#![deny(refining_impl_trait)] + +pub trait Tr<T> { + fn foo() -> impl for<'a> Tr<&'a Self>; +} + +impl<T> Tr<T> for () { + fn foo() -> impl for<'a> Tr<&'a Self> {} +} diff --git a/tests/ui/impl-trait/opaque-cast-field-access-in-future.rs b/tests/ui/impl-trait/opaque-cast-field-access-in-future.rs new file mode 100644 index 00000000000..3e3bc09a62a --- /dev/null +++ b/tests/ui/impl-trait/opaque-cast-field-access-in-future.rs @@ -0,0 +1,27 @@ +// edition: 2021 + +use std::future::Future; + +async fn bop() { + fold(run(), |mut foo| async move { + &mut foo.bar; + }) +} + +fn fold<Fut, F, U>(_: Foo<U>, f: F) +where + F: FnMut(Foo<U>) -> Fut, +{ + loop {} +} + +struct Foo<F> { + bar: Vec<F>, +} + +fn run() -> Foo<impl Future<Output = ()>> { + //~^ ERROR type annotations needed + loop {} +} + +fn main() {} diff --git a/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr new file mode 100644 index 00000000000..ee4343b110f --- /dev/null +++ b/tests/ui/impl-trait/opaque-cast-field-access-in-future.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/opaque-cast-field-access-in-future.rs:22:17 + | +LL | fn run() -> Foo<impl Future<Output = ()>> { + | ^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs b/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs new file mode 100644 index 00000000000..ffaa4d771d9 --- /dev/null +++ b/tests/ui/intrinsics/feature-gate-safe-intrinsic.rs @@ -0,0 +1,6 @@ +#[rustc_safe_intrinsic] +//~^ ERROR the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe +//~| ERROR attribute should be applied to intrinsic functions +fn safe() {} + +fn main() {} diff --git a/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr b/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr new file mode 100644 index 00000000000..8aeb56598ec --- /dev/null +++ b/tests/ui/intrinsics/feature-gate-safe-intrinsic.stderr @@ -0,0 +1,20 @@ +error[E0658]: the `#[rustc_safe_intrinsic]` attribute is used internally to mark intrinsics as safe + --> $DIR/feature-gate-safe-intrinsic.rs:1:1 + | +LL | #[rustc_safe_intrinsic] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(rustc_attrs)]` to the crate attributes to enable + +error: attribute should be applied to intrinsic functions + --> $DIR/feature-gate-safe-intrinsic.rs:1:1 + | +LL | #[rustc_safe_intrinsic] + | ^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn safe() {} + | ------------ not an intrinsic function + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/intrinsics/intrinsic-alignment.rs b/tests/ui/intrinsics/intrinsic-alignment.rs index 30b8a21269a..6f9df64417e 100644 --- a/tests/ui/intrinsics/intrinsic-alignment.rs +++ b/tests/ui/intrinsics/intrinsic-alignment.rs @@ -1,7 +1,7 @@ // run-pass // ignore-wasm32-bare seems not important to test here -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] mod rusti { extern "rust-intrinsic" { diff --git a/tests/ui/issues/issue-27042.stderr b/tests/ui/issues/issue-27042.stderr index 69eedeb8025..01532de999e 100644 --- a/tests/ui/issues/issue-27042.stderr +++ b/tests/ui/issues/issue-27042.stderr @@ -11,8 +11,13 @@ LL | | while true { break }; // but here we cite the whole loop error[E0308]: mismatched types --> $DIR/issue-27042.rs:6:16 | +LL | let _: i32 = + | - expected because of this assignment +LL | 'a: // in this case, the citation is just the `break`: LL | loop { break }; - | ^^^^^ expected `i32`, found `()` + | ---- ^^^^^ expected `i32`, found `()` + | | + | this loop is expected to be of type `i32` | help: give it a value of the expected type | diff --git a/tests/ui/loops/loop-labeled-break-value.stderr b/tests/ui/loops/loop-labeled-break-value.stderr index f233670e8c4..694d6c306f6 100644 --- a/tests/ui/loops/loop-labeled-break-value.stderr +++ b/tests/ui/loops/loop-labeled-break-value.stderr @@ -2,7 +2,10 @@ error[E0308]: mismatched types --> $DIR/loop-labeled-break-value.rs:3:29 | LL | let _: i32 = loop { break }; - | ^^^^^ expected `i32`, found `()` + | - ---- ^^^^^ expected `i32`, found `()` + | | | + | | this loop is expected to be of type `i32` + | expected because of this assignment | help: give it a value of the expected type | @@ -13,7 +16,10 @@ error[E0308]: mismatched types --> $DIR/loop-labeled-break-value.rs:6:37 | LL | let _: i32 = 'inner: loop { break 'inner }; - | ^^^^^^^^^^^^ expected `i32`, found `()` + | - ---- ^^^^^^^^^^^^ expected `i32`, found `()` + | | | + | | this loop is expected to be of type `i32` + | expected because of this assignment | help: give it a value of the expected type | @@ -24,7 +30,10 @@ error[E0308]: mismatched types --> $DIR/loop-labeled-break-value.rs:9:45 | LL | let _: i32 = 'inner2: loop { loop { break 'inner2 } }; - | ^^^^^^^^^^^^^ expected `i32`, found `()` + | - ---- ^^^^^^^^^^^^^ expected `i32`, found `()` + | | | + | | this loop is expected to be of type `i32` + | expected because of this assignment | help: give it a value of the expected type | diff --git a/tests/ui/loops/loop-properly-diverging-2.stderr b/tests/ui/loops/loop-properly-diverging-2.stderr index dc60657ee14..1d1ae60cda1 100644 --- a/tests/ui/loops/loop-properly-diverging-2.stderr +++ b/tests/ui/loops/loop-properly-diverging-2.stderr @@ -2,7 +2,10 @@ error[E0308]: mismatched types --> $DIR/loop-properly-diverging-2.rs:2:23 | LL | let x: i32 = loop { break }; - | ^^^^^ expected `i32`, found `()` + | - ---- ^^^^^ expected `i32`, found `()` + | | | + | | this loop is expected to be of type `i32` + | expected because of this assignment | help: give it a value of the expected type | diff --git a/tests/ui/match/issue-72896.rs b/tests/ui/match/issue-72896-non-partial-eq-const.rs index 3a8b8203731..a3095f0be83 100644 --- a/tests/ui/match/issue-72896.rs +++ b/tests/ui/match/issue-72896-non-partial-eq-const.rs @@ -17,7 +17,8 @@ const CONST_SET: EnumSet<Enum8> = EnumSet { __enumset_underlying: 3 }; fn main() { match CONST_SET { - CONST_SET => { /* ok */ } + CONST_SET => { /* ok */ } //~WARN: must implement `PartialEq` + //~| previously accepted _ => panic!("match fell through?"), } } diff --git a/tests/ui/match/issue-72896-non-partial-eq-const.stderr b/tests/ui/match/issue-72896-non-partial-eq-const.stderr new file mode 100644 index 00000000000..a7fc0cfc054 --- /dev/null +++ b/tests/ui/match/issue-72896-non-partial-eq-const.stderr @@ -0,0 +1,23 @@ +warning: to use a constant of type `EnumSet<Enum8>` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-72896-non-partial-eq-const.rs:20:9 + | +LL | CONST_SET => { /* ok */ } + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 <https://github.com/rust-lang/rust/issues/116122> + = note: `#[warn(const_patterns_without_partial_eq)]` on by default + +warning: 1 warning emitted + +Future incompatibility report: Future breakage diagnostic: +warning: to use a constant of type `EnumSet<Enum8>` in a pattern, the type must implement `PartialEq` + --> $DIR/issue-72896-non-partial-eq-const.rs:20:9 + | +LL | CONST_SET => { /* ok */ } + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #116122 <https://github.com/rust-lang/rust/issues/116122> + = note: `#[warn(const_patterns_without_partial_eq)]` on by default + diff --git a/tests/ui/repr/16-bit-repr-c-enum.rs b/tests/ui/repr/16-bit-repr-c-enum.rs index 2acfde4be46..d4fea2b192b 100644 --- a/tests/ui/repr/16-bit-repr-c-enum.rs +++ b/tests/ui/repr/16-bit-repr-c-enum.rs @@ -5,7 +5,7 @@ // [avr] compile-flags: --target=avr-unknown-gnu-atmega328 --crate-type=rlib // [msp430] needs-llvm-components: msp430 // [msp430] compile-flags: --target=msp430-none-elf --crate-type=rlib -#![feature(no_core, lang_items, intrinsics, staged_api)] +#![feature(no_core, lang_items, intrinsics, staged_api, rustc_attrs)] #![no_core] #![crate_type = "lib"] #![stable(feature = "", since = "")] diff --git a/tests/ui/structs-enums/rec-align-u32.rs b/tests/ui/structs-enums/rec-align-u32.rs index ee704198d19..b3c323d2a29 100644 --- a/tests/ui/structs-enums/rec-align-u32.rs +++ b/tests/ui/structs-enums/rec-align-u32.rs @@ -3,7 +3,7 @@ #![allow(unused_unsafe)] // Issue #2303 -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] use std::mem; diff --git a/tests/ui/structs-enums/rec-align-u64.rs b/tests/ui/structs-enums/rec-align-u64.rs index c3b201fb1c6..de008bcc01d 100644 --- a/tests/ui/structs-enums/rec-align-u64.rs +++ b/tests/ui/structs-enums/rec-align-u64.rs @@ -5,7 +5,7 @@ // Issue #2303 -#![feature(intrinsics)] +#![feature(intrinsics, rustc_attrs)] use std::mem; diff --git a/triagebot.toml b/triagebot.toml index dbced481993..648997ad6f0 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -542,6 +542,10 @@ cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@TaKO8Ki"] message = "This PR changes Stable MIR" cc = ["@oli-obk", "@celinval", "@spastorino"] +[mentions."compiler/stable_mir"] +message = "This PR changes Stable MIR" +cc = ["@oli-obk", "@celinval", "@spastorino"] + [mentions."compiler/rustc_target/src/spec"] message = """ These commits modify **compiler targets**. |
