diff options
| author | bors <bors@rust-lang.org> | 2024-09-04 22:58:51 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-09-04 22:58:51 +0000 |
| commit | 009e73825af0e59ad4fc603562e038b3dbd6593a (patch) | |
| tree | 5015384a0ad20ed06a185717c3155722515a218d /compiler | |
| parent | 4ac7bcbaad8d6fd7a51bdf1b696cbc3ba4c796cf (diff) | |
| parent | 2e005112fdd15af33f76eb2fd839c4f7f646d3ac (diff) | |
| download | rust-009e73825af0e59ad4fc603562e038b3dbd6593a.tar.gz rust-009e73825af0e59ad4fc603562e038b3dbd6593a.zip | |
Auto merge of #129936 - matthiaskrgr:rollup-0s8xycb, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #127692 (Suggest `impl Trait` for References to Bare Trait in Function Header) - #128701 (Don't Suggest Labeling `const` and `unsafe` Blocks ) - #128934 (Non-exhaustive structs may be empty) - #129630 (Document the broken C ABI of `wasm32-unknown-unknown`) - #129863 (update comment regarding TargetOptions.features) - #129896 (do not attempt to prove unknowable goals) - #129926 (Move `SanityCheck` and `MirPass`) - #129928 (rustc_driver_impl: remove some old dead logic) - #129930 (include 1.80.1 release notes on master) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
69 files changed, 400 insertions, 384 deletions
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index e49ae60e890..cb2fa6e9d74 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -61,7 +61,6 @@ use rustc_session::lint::{Lint, LintId}; use rustc_session::output::collect_crate_types; use rustc_session::{config, filesearch, EarlyDiagCtxt, Session}; use rustc_span::source_map::FileLoader; -use rustc_span::symbol::sym; use rustc_span::FileName; use rustc_target::json::ToJson; use rustc_target::spec::{Target, TargetTriple}; @@ -777,16 +776,8 @@ fn print_crate_info( .config .iter() .filter_map(|&(name, value)| { - // Note that crt-static is a specially recognized cfg - // directive that's printed out here as part of - // rust-lang/rust#37406, but in general the - // `target_feature` cfg is gated under - // rust-lang/rust#29717. For now this is just - // specifically allowing the crt-static cfg and that's - // it, this is intended to get into Cargo and then go - // through to build scripts. - if (name != sym::target_feature || value != Some(sym::crt_dash_static)) - && !sess.is_nightly_build() + // On stable, exclude unstable flags. + if !sess.is_nightly_build() && find_gated_cfg(|cfg_sym| cfg_sym == name).is_some() { return None; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 7be45463f15..149bc6d2698 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -133,9 +133,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return; }; let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &impl_trait_name); - if sugg.is_empty() { - return; - }; diag.multipart_suggestion( format!( "alternatively use a blanket implementation to implement `{of_trait_name}` for \ @@ -170,6 +167,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let parent_id = tcx.hir().get_parent_item(self_ty.hir_id).def_id; // FIXME: If `type_alias_impl_trait` is enabled, also look for `Trait0<Ty = Trait1>` // and suggest `Trait0<Ty = impl Trait1>`. + // Functions are found in three different contexts. + // 1. Independent functions + // 2. Functions inside trait blocks + // 3. Functions inside impl blocks let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => { (sig, generics, None) @@ -180,6 +181,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { owner_id, .. }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + hir::Node::ImplItem(hir::ImplItem { + kind: hir::ImplItemKind::Fn(sig, _), + generics, + owner_id, + .. + }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), _ => return false, }; let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { @@ -187,6 +194,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }; let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; let mut is_downgradable = true; + + // Check if trait object is safe for suggesting dynamic dispatch. let is_object_safe = match self_ty.kind { hir::TyKind::TraitObject(objects, ..) => { objects.iter().all(|(o, _)| match o.trait_ref.path.res { @@ -202,8 +211,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } _ => false, }; + + let borrowed = matches!( + tcx.parent_hir_node(self_ty.hir_id), + hir::Node::Ty(hir::Ty { kind: hir::TyKind::Ref(..), .. }) + ); + + // Suggestions for function return type. if let hir::FnRetTy::Return(ty) = sig.decl.output - && ty.hir_id == self_ty.hir_id + && ty.peel_refs().hir_id == self_ty.hir_id { let pre = if !is_object_safe { format!("`{trait_name}` is not object safe, ") @@ -214,14 +230,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { "{pre}use `impl {trait_name}` to return an opaque type, as long as you return a \ single underlying type", ); + diag.multipart_suggestion_verbose(msg, impl_sugg, Applicability::MachineApplicable); + + // Suggest `Box<dyn Trait>` for return type if is_object_safe { - diag.multipart_suggestion_verbose( - "alternatively, you can return an owned trait object", + // If the return type is `&Trait`, we don't want + // the ampersand to be displayed in the `Box<dyn Trait>` + // suggestion. + let suggestion = if borrowed { + vec![(ty.span, format!("Box<dyn {trait_name}>"))] + } else { vec![ (ty.span.shrink_to_lo(), "Box<dyn ".to_string()), (ty.span.shrink_to_hi(), ">".to_string()), - ], + ] + }; + + diag.multipart_suggestion_verbose( + "alternatively, you can return an owned trait object", + suggestion, Applicability::MachineApplicable, ); } else if is_downgradable { @@ -230,24 +258,24 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } return true; } + + // Suggestions for function parameters. for ty in sig.decl.inputs { - if ty.hir_id != self_ty.hir_id { + if ty.peel_refs().hir_id != self_ty.hir_id { continue; } let sugg = self.add_generic_param_suggestion(generics, self_ty.span, &trait_name); - if !sugg.is_empty() { - diag.multipart_suggestion_verbose( - format!("use a new generic type parameter, constrained by `{trait_name}`"), - sugg, - Applicability::MachineApplicable, - ); - diag.multipart_suggestion_verbose( - "you can also use an opaque type, but users won't be able to specify the type \ - parameter when calling the `fn`, having to rely exclusively on type inference", - impl_sugg, - Applicability::MachineApplicable, - ); - } + diag.multipart_suggestion_verbose( + format!("use a new generic type parameter, constrained by `{trait_name}`"), + sugg, + Applicability::MachineApplicable, + ); + diag.multipart_suggestion_verbose( + "you can also use an opaque type, but users won't be able to specify the type \ + parameter when calling the `fn`, having to rely exclusively on type inference", + impl_sugg, + Applicability::MachineApplicable, + ); if !is_object_safe { diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`")); if is_downgradable { @@ -255,14 +283,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { diag.downgrade_to_delayed_bug(); } } else { + // No ampersand in suggestion if it's borrowed already + let (dyn_str, paren_dyn_str) = + if borrowed { ("dyn ", "(dyn ") } else { ("&dyn ", "&(dyn ") }; + let sugg = if let hir::TyKind::TraitObject([_, _, ..], _, _) = self_ty.kind { // There are more than one trait bound, we need surrounding parentheses. vec![ - (self_ty.span.shrink_to_lo(), "&(dyn ".to_string()), + (self_ty.span.shrink_to_lo(), paren_dyn_str.to_string()), (self_ty.span.shrink_to_hi(), ")".to_string()), ] } else { - vec![(self_ty.span.shrink_to_lo(), "&dyn ".to_string())] + vec![(self_ty.span.shrink_to_lo(), dyn_str.to_string())] }; diag.multipart_suggestion_verbose( format!( diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 7b901915037..081a23b6ff3 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -3,8 +3,6 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/mir/index.html use std::borrow::Cow; -use std::cell::RefCell; -use std::collections::hash_map::Entry; use std::fmt::{self, Debug, Formatter}; use std::ops::{Index, IndexMut}; use std::{iter, mem}; @@ -26,7 +24,6 @@ use rustc_index::bit_set::BitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::{HashStable, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_serialize::{Decodable, Encodable}; -use rustc_session::Session; use rustc_span::source_map::Spanned; use rustc_span::symbol::Symbol; use rustc_span::{Span, DUMMY_SP}; @@ -106,65 +103,6 @@ impl<'tcx> HasLocalDecls<'tcx> for Body<'tcx> { } } -thread_local! { - static PASS_NAMES: RefCell<FxHashMap<&'static str, &'static str>> = { - RefCell::new(FxHashMap::default()) - }; -} - -/// Converts a MIR pass name into a snake case form to match the profiling naming style. -fn to_profiler_name(type_name: &'static str) -> &'static str { - PASS_NAMES.with(|names| match names.borrow_mut().entry(type_name) { - Entry::Occupied(e) => *e.get(), - Entry::Vacant(e) => { - let snake_case: String = type_name - .chars() - .flat_map(|c| { - if c.is_ascii_uppercase() { - vec!['_', c.to_ascii_lowercase()] - } else if c == '-' { - vec!['_'] - } else { - vec![c] - } - }) - .collect(); - let result = &*String::leak(format!("mir_pass{}", snake_case)); - e.insert(result); - result - } - }) -} - -/// A streamlined trait that you can implement to create a pass; the -/// pass will be named after the type, and it will consist of a main -/// loop that goes over each available MIR and applies `run_pass`. -pub trait MirPass<'tcx> { - fn name(&self) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. - // See copypaste in `MirLint` - const { - let name = std::any::type_name::<Self>(); - crate::util::common::c_name(name) - } - } - - fn profiler_name(&self) -> &'static str { - to_profiler_name(self.name()) - } - - /// Returns `true` if this pass is enabled with the current combination of compiler flags. - fn is_enabled(&self, _sess: &Session) -> bool { - true - } - - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); - - fn is_mir_dump_enabled(&self) -> bool { - true - } -} - impl MirPhase { /// Gets the index of the current MirPhase within the set of all `MirPhase`s. /// diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 698104b0462..dd00db8635f 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -81,10 +81,6 @@ impl<'tcx> VariantDef { adt: ty::AdtDef<'_>, ) -> InhabitedPredicate<'tcx> { debug_assert!(!adt.is_union()); - if self.is_field_list_non_exhaustive() && !self.def_id.is_local() { - // Non-exhaustive variants from other crates are always considered inhabited. - return InhabitedPredicate::True; - } InhabitedPredicate::all( tcx, self.fields.iter().map(|field| { diff --git a/compiler/rustc_middle/src/util/common.rs b/compiler/rustc_middle/src/util/common.rs index 2038d3f8448..223b2b3bfe4 100644 --- a/compiler/rustc_middle/src/util/common.rs +++ b/compiler/rustc_middle/src/util/common.rs @@ -20,19 +20,3 @@ pub fn to_readable_str(mut val: usize) -> String { groups.join("_") } - -// const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }` -pub const fn c_name(name: &'static str) -> &'static str { - // FIXME Simplify the implementation once more `str` methods get const-stable. - // and inline into call site - let bytes = name.as_bytes(); - let mut i = bytes.len(); - while i > 0 && bytes[i - 1] != b':' { - i = i - 1; - } - let (_, bytes) = bytes.split_at(i); - match std::str::from_utf8(bytes) { - Ok(name) => name, - Err(_) => name, - } -} diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 0171cc85918..8c3e6f49b16 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -1,7 +1,7 @@ use rustc_ast::MetaItem; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; -use rustc_middle::mir::{self, Body, Local, Location, MirPass}; +use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::symbol::{sym, Symbol}; use rustc_span::Span; @@ -18,8 +18,6 @@ use crate::impls::{ use crate::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex}; use crate::{Analysis, JoinSemiLattice, ResultsCursor}; -pub struct SanityCheck; - fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option<MetaItem> { for attr in tcx.get_attrs(def_id, sym::rustc_mir) { let items = attr.meta_item_list(); @@ -33,53 +31,50 @@ fn has_rustc_mir_with(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol) -> Option<Me None } -// FIXME: This should be a `MirLint`, but it needs to be moved back to `rustc_mir_transform` first. -impl<'tcx> MirPass<'tcx> for SanityCheck { - fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { - let def_id = body.source.def_id(); - if !tcx.has_attr(def_id, sym::rustc_mir) { - debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); - return; - } else { - debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); - } +pub fn sanity_check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { + let def_id = body.source.def_id(); + if !tcx.has_attr(def_id, sym::rustc_mir) { + debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); + return; + } else { + debug!("running rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); + } - let param_env = tcx.param_env(def_id); - let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true); + let param_env = tcx.param_env(def_id); + let move_data = MoveData::gather_moves(body, tcx, param_env, |_| true); - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { - let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) - .into_engine(tcx, body) - .iterate_to_fixpoint(); + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_init).is_some() { + let flow_inits = MaybeInitializedPlaces::new(tcx, body, &move_data) + .into_engine(tcx, body) + .iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, flow_inits.into_results_cursor(body)); - } + sanity_check_via_rustc_peek(tcx, flow_inits.into_results_cursor(body)); + } - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() { - let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) - .into_engine(tcx, body) - .iterate_to_fixpoint(); + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_maybe_uninit).is_some() { + let flow_uninits = MaybeUninitializedPlaces::new(tcx, body, &move_data) + .into_engine(tcx, body) + .iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, flow_uninits.into_results_cursor(body)); - } + sanity_check_via_rustc_peek(tcx, flow_uninits.into_results_cursor(body)); + } - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() { - let flow_def_inits = DefinitelyInitializedPlaces::new(body, &move_data) - .into_engine(tcx, body) - .iterate_to_fixpoint(); + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_definite_init).is_some() { + let flow_def_inits = DefinitelyInitializedPlaces::new(body, &move_data) + .into_engine(tcx, body) + .iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, flow_def_inits.into_results_cursor(body)); - } + sanity_check_via_rustc_peek(tcx, flow_def_inits.into_results_cursor(body)); + } - if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() { - let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint(); + if has_rustc_mir_with(tcx, def_id, sym::rustc_peek_liveness).is_some() { + let flow_liveness = MaybeLiveLocals.into_engine(tcx, body).iterate_to_fixpoint(); - sanity_check_via_rustc_peek(tcx, flow_liveness.into_results_cursor(body)); - } + sanity_check_via_rustc_peek(tcx, flow_liveness.into_results_cursor(body)); + } - if has_rustc_mir_with(tcx, def_id, sym::stop_after_dataflow).is_some() { - tcx.dcx().emit_fatal(StopAfterDataFlowEndedCompilation); - } + if has_rustc_mir_with(tcx, def_id, sym::stop_after_dataflow).is_some() { + tcx.dcx().emit_fatal(StopAfterDataFlowEndedCompilation); } } diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs index edb6bc4fbea..e4bc6b3efe4 100644 --- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs +++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs @@ -22,7 +22,7 @@ use rustc_target::spec::PanicStrategy; #[derive(PartialEq)] pub struct AbortUnwindingCalls; -impl<'tcx> MirPass<'tcx> for AbortUnwindingCalls { +impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let def_id = body.source.def_id(); let kind = tcx.def_kind(def_id); diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index df5312d155c..78e850de3c7 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -30,7 +30,7 @@ pub use self::AddCallGuards::*; * */ -impl<'tcx> MirPass<'tcx> for AddCallGuards { +impl<'tcx> crate::MirPass<'tcx> for AddCallGuards { fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { self.add_call_guards(body); } diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index e503119a349..4a8196aeff5 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -37,7 +37,7 @@ use crate::util; /// blowup. pub struct AddMovesForPackedDrops; -impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops { +impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span); add_moves_for_packed_drops(tcx, body); diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs index 79bc21cab14..2e12064fe73 100644 --- a/compiler/rustc_mir_transform/src/add_retag.rs +++ b/compiler/rustc_mir_transform/src/add_retag.rs @@ -48,7 +48,7 @@ fn may_contain_reference<'tcx>(ty: Ty<'tcx>, depth: u32, tcx: TyCtxt<'tcx>) -> b } } -impl<'tcx> MirPass<'tcx> for AddRetag { +impl<'tcx> crate::MirPass<'tcx> for AddRetag { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.opts.unstable_opts.mir_emit_retag } diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs index 04204c68f7b..369f6c60084 100644 --- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs +++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs @@ -62,7 +62,7 @@ pub fn subtype_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { checker.patcher.apply(body); } -impl<'tcx> MirPass<'tcx> for Subtyper { +impl<'tcx> crate::MirPass<'tcx> for Subtyper { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { subtype_finder(tcx, body); } diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index ad362f22ce1..2e072aa262a 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -9,7 +9,7 @@ use tracing::{debug, trace}; pub struct CheckAlignment; -impl<'tcx> MirPass<'tcx> for CheckAlignment { +impl<'tcx> crate::MirPass<'tcx> for CheckAlignment { fn is_enabled(&self, sess: &Session) -> bool { // FIXME(#112480) MSVC and rustc disagree on minimum stack alignment on x86 Windows if sess.target.llvm_target == "i686-pc-windows-msvc" { diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index 1f615c9d8d1..fb03323e37e 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -6,11 +6,11 @@ use rustc_session::lint::builtin::CONST_ITEM_MUTATION; use rustc_span::def_id::DefId; use rustc_span::Span; -use crate::{errors, MirLint}; +use crate::errors; pub struct CheckConstItemMutation; -impl<'tcx> MirLint<'tcx> for CheckConstItemMutation { +impl<'tcx> crate::MirLint<'tcx> for CheckConstItemMutation { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let mut checker = ConstMutationChecker { body, tcx, target_local: None }; checker.visit_body(body); diff --git a/compiler/rustc_mir_transform/src/check_packed_ref.rs b/compiler/rustc_mir_transform/src/check_packed_ref.rs index eb76a39be57..2f957de7e78 100644 --- a/compiler/rustc_mir_transform/src/check_packed_ref.rs +++ b/compiler/rustc_mir_transform/src/check_packed_ref.rs @@ -3,11 +3,11 @@ use rustc_middle::mir::*; use rustc_middle::span_bug; use rustc_middle::ty::{self, TyCtxt}; -use crate::{errors, util, MirLint}; +use crate::{errors, util}; pub struct CheckPackedRef; -impl<'tcx> MirLint<'tcx> for CheckPackedRef { +impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let param_env = tcx.param_env(body.source.def_id()); let source_info = SourceInfo::outermost(body.span); diff --git a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs index 08c9f9f08e6..2f3be1e425d 100644 --- a/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir_transform/src/cleanup_post_borrowck.rs @@ -21,11 +21,9 @@ use rustc_middle::mir::{Body, BorrowKind, CastKind, Rvalue, StatementKind, Termi use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::TyCtxt; -use crate::MirPass; - pub struct CleanupPostBorrowck; -impl<'tcx> MirPass<'tcx> for CleanupPostBorrowck { +impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck { fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { for basic_block in body.basic_blocks.as_mut() { for statement in basic_block.statements.iter_mut() { diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs index 5c267f85378..85d25ca2231 100644 --- a/compiler/rustc_mir_transform/src/copy_prop.rs +++ b/compiler/rustc_mir_transform/src/copy_prop.rs @@ -19,7 +19,7 @@ use crate::ssa::SsaLocals; /// We want to replace all those locals by `_a`, either copied or moved. pub struct CopyProp; -impl<'tcx> MirPass<'tcx> for CopyProp { +impl<'tcx> crate::MirPass<'tcx> for CopyProp { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 1 } diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 80ba1c42668..eefb748e49d 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1535,7 +1535,7 @@ fn check_field_tys_sized<'tcx>( } } -impl<'tcx> MirPass<'tcx> for StateTransform { +impl<'tcx> crate::MirPass<'tcx> for StateTransform { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let Some(old_yield_ty) = body.yield_ty() else { // This only applies to coroutines diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index bba354d2936..4edba61fdec 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -28,14 +28,13 @@ use tracing::{debug, debug_span, instrument, trace}; use crate::coverage::counters::{CounterIncrementSite, CoverageCounters}; use crate::coverage::graph::CoverageGraph; use crate::coverage::mappings::ExtractedMappings; -use crate::MirPass; /// Inserts `StatementKind::Coverage` statements that either instrument the binary with injected /// counters, via intrinsic `llvm.instrprof.increment`, and/or inject metadata used during codegen /// to construct the coverage map. pub struct InstrumentCoverage; -impl<'tcx> MirPass<'tcx> for InstrumentCoverage { +impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.instrument_coverage() } diff --git a/compiler/rustc_mir_transform/src/ctfe_limit.rs b/compiler/rustc_mir_transform/src/ctfe_limit.rs index bf522fd5ef4..ea473b64ce5 100644 --- a/compiler/rustc_mir_transform/src/ctfe_limit.rs +++ b/compiler/rustc_mir_transform/src/ctfe_limit.rs @@ -8,11 +8,9 @@ use rustc_middle::mir::{ use rustc_middle::ty::TyCtxt; use tracing::instrument; -use crate::MirPass; - pub struct CtfeLimit; -impl<'tcx> MirPass<'tcx> for CtfeLimit { +impl<'tcx> crate::MirPass<'tcx> for CtfeLimit { #[instrument(skip(self, _tcx, body))] fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let doms = body.basic_blocks.dominators(); diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index b16d25c93bb..46f7408ef80 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -28,7 +28,7 @@ const PLACE_LIMIT: usize = 100; pub struct DataflowConstProp; -impl<'tcx> MirPass<'tcx> for DataflowConstProp { +impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 3 } diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 39c8db184a5..9081a2e2e30 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -132,7 +132,7 @@ pub enum DeadStoreElimination { Final, } -impl<'tcx> MirPass<'tcx> for DeadStoreElimination { +impl<'tcx> crate::MirPass<'tcx> for DeadStoreElimination { fn name(&self) -> &'static str { match self { DeadStoreElimination::Initial => "DeadStoreElimination-initial", diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs index b38f4a4a823..be50c1da8a4 100644 --- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs +++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs @@ -15,7 +15,7 @@ use super::simplify::simplify_cfg; pub struct DeduplicateBlocks; -impl<'tcx> MirPass<'tcx> for DeduplicateBlocks { +impl<'tcx> crate::MirPass<'tcx> for DeduplicateBlocks { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 4 } diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs index 0e2fccc85da..a878f777448 100644 --- a/compiler/rustc_mir_transform/src/deref_separator.rs +++ b/compiler/rustc_mir_transform/src/deref_separator.rs @@ -78,7 +78,7 @@ pub fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { checker.patcher.apply(body); } -impl<'tcx> MirPass<'tcx> for Derefer { +impl<'tcx> crate::MirPass<'tcx> for Derefer { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { deref_finder(tcx, body); } diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs index a6d626d3f8f..8940a21d7fa 100644 --- a/compiler/rustc_mir_transform/src/dest_prop.rs +++ b/compiler/rustc_mir_transform/src/dest_prop.rs @@ -146,11 +146,9 @@ use rustc_mir_dataflow::points::{save_as_intervals, DenseLocationMap, PointIndex use rustc_mir_dataflow::Analysis; use tracing::{debug, trace}; -use crate::MirPass; - pub struct DestinationPropagation; -impl<'tcx> MirPass<'tcx> for DestinationPropagation { +impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { // For now, only run at MIR opt level 3. Two things need to be changed before this can be // turned on by default: diff --git a/compiler/rustc_mir_transform/src/dump_mir.rs b/compiler/rustc_mir_transform/src/dump_mir.rs index 29db45f9450..06ae1b490d7 100644 --- a/compiler/rustc_mir_transform/src/dump_mir.rs +++ b/compiler/rustc_mir_transform/src/dump_mir.rs @@ -7,11 +7,9 @@ use rustc_middle::mir::{write_mir_pretty, Body}; use rustc_middle::ty::TyCtxt; use rustc_session::config::{OutFileName, OutputType}; -use crate::MirPass; - pub struct Marker(pub &'static str); -impl<'tcx> MirPass<'tcx> for Marker { +impl<'tcx> crate::MirPass<'tcx> for Marker { fn name(&self) -> &'static str { self.0 } diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index 67b81efd614..1c54cd70023 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -92,7 +92,7 @@ use super::simplify::simplify_cfg; /// ``` pub struct EarlyOtherwiseBranch; -impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { +impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs index e5778f8a05d..5dd82f40163 100644 --- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs +++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs @@ -88,7 +88,7 @@ impl<'tcx, 'a> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'tcx, 'a> { pub struct ElaborateBoxDerefs; -impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs { +impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if let Some(def_id) = tcx.lang_items().owned_box() { let unique_did = tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did; diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs index d0809d9388d..f4a951ebde6 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drops.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs @@ -49,7 +49,7 @@ use crate::deref_separator::deref_finder; /// ``` pub struct ElaborateDrops; -impl<'tcx> MirPass<'tcx> for ElaborateDrops { +impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops { #[instrument(level = "trace", skip(self, tcx, body))] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("elaborate_drops({:?} @ {:?})", body.source, body.span); diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs index b7873e73c18..199fd0f10ee 100644 --- a/compiler/rustc_mir_transform/src/function_item_references.rs +++ b/compiler/rustc_mir_transform/src/function_item_references.rs @@ -9,11 +9,11 @@ use rustc_span::symbol::sym; use rustc_span::Span; use rustc_target::spec::abi::Abi; -use crate::{errors, MirLint}; +use crate::errors; pub struct FunctionItemReferences; -impl<'tcx> MirLint<'tcx> for FunctionItemReferences { +impl<'tcx> crate::MirLint<'tcx> for FunctionItemReferences { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let mut checker = FunctionItemRefChecker { tcx, body }; checker.visit_body(body); diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index fb9baeeb3ed..df0fcc42e59 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -111,7 +111,7 @@ use crate::ssa::{AssignedValue, SsaLocals}; pub struct GVN; -impl<'tcx> MirPass<'tcx> for GVN { +impl<'tcx> crate::MirPass<'tcx> for GVN { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 4482801826a..6cc7e0ee1e4 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -42,7 +42,7 @@ struct CallSite<'tcx> { source_info: SourceInfo, } -impl<'tcx> MirPass<'tcx> for Inline { +impl<'tcx> crate::MirPass<'tcx> for Inline { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { // FIXME(#127234): Coverage instrumentation currently doesn't handle inlined // MIR correctly when Modified Condition/Decision Coverage is enabled. diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 3ec553d0ba0..4fbfa744e67 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -27,7 +27,7 @@ impl InstSimplify { } } -impl<'tcx> MirPass<'tcx> for InstSimplify { +impl<'tcx> crate::MirPass<'tcx> for InstSimplify { fn name(&self) -> &'static str { self.name() } diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index 435b6a01163..02dd56e1b4f 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -61,7 +61,7 @@ const MAX_BACKTRACK: usize = 5; const MAX_COST: usize = 100; const MAX_PLACES: usize = 100; -impl<'tcx> MirPass<'tcx> for JumpThreading { +impl<'tcx> crate::MirPass<'tcx> for JumpThreading { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 15d71ee2ac8..61405fb25c6 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -25,11 +25,10 @@ use rustc_target::abi::{Abi, FieldIdx, HasDataLayout, Size, TargetDataLayout, Va use tracing::{debug, instrument, trace}; use crate::errors::{AssertLint, AssertLintKind}; -use crate::MirLint; pub struct KnownPanicsLint; -impl<'tcx> MirLint<'tcx> for KnownPanicsLint { +impl<'tcx> crate::MirLint<'tcx> for KnownPanicsLint { fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { if body.tainted_by_errors.is_some() { return; diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs index cbc3169f2f1..f02ba71ddc6 100644 --- a/compiler/rustc_mir_transform/src/large_enums.rs +++ b/compiler/rustc_mir_transform/src/large_enums.rs @@ -27,7 +27,7 @@ pub struct EnumSizeOpt { pub(crate) discrepancy: u64, } -impl<'tcx> MirPass<'tcx> for EnumSizeOpt { +impl<'tcx> crate::MirPass<'tcx> for EnumSizeOpt { fn is_enabled(&self, sess: &Session) -> bool { // There are some differences in behavior on wasm and ARM that are not properly // understood, so we conservatively treat this optimization as unsound: diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 9e460a725ee..62e73ba2c8e 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -26,13 +26,12 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_index::IndexVec; use rustc_middle::mir::{ AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs, LocalDecl, - MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, + MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, Statement, StatementKind, TerminatorKind, START_BLOCK, }; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_middle::util::Providers; use rustc_middle::{bug, query, span_bug}; -use rustc_mir_dataflow::rustc_peek; use rustc_span::source_map::Spanned; use rustc_span::{sym, DUMMY_SP}; use rustc_trait_selection::traits; @@ -41,7 +40,7 @@ use tracing::{debug, trace}; #[macro_use] mod pass_manager; -use pass_manager::{self as pm, Lint, MirLint, WithMinOptLevel}; +use pass_manager::{self as pm, Lint, MirLint, MirPass, WithMinOptLevel}; mod abort_unwinding_calls; mod add_call_guards; @@ -96,6 +95,7 @@ mod remove_unneeded_drops; mod remove_zsts; mod required_consts; mod reveal_all; +mod sanity_check; mod shim; mod ssa; // This pass is public to allow external drivers to perform MIR cleanup @@ -288,7 +288,7 @@ fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> { &Lint(function_item_references::FunctionItemReferences), // What we need to do constant evaluation. &simplify::SimplifyCfg::Initial, - &rustc_peek::SanityCheck, // Just a lint + &Lint(sanity_check::SanityCheck), ], None, ); diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs index a9bdff95fe5..55eec332306 100644 --- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs +++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs @@ -9,7 +9,7 @@ use crate::take_array; pub struct LowerIntrinsics; -impl<'tcx> MirPass<'tcx> for LowerIntrinsics { +impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let local_decls = &body.local_decls; for block in body.basic_blocks.as_mut() { diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs index 77a7f4f47dd..555309a7750 100644 --- a/compiler/rustc_mir_transform/src/lower_slice_len.rs +++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs @@ -7,7 +7,7 @@ use rustc_middle::ty::TyCtxt; pub struct LowerSliceLenCalls; -impl<'tcx> MirPass<'tcx> for LowerSliceLenCalls { +impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs index 5240f1c887c..233b39fb47a 100644 --- a/compiler/rustc_mir_transform/src/match_branches.rs +++ b/compiler/rustc_mir_transform/src/match_branches.rs @@ -12,7 +12,7 @@ use super::simplify::simplify_cfg; pub struct MatchBranchSimplification; -impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { +impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 1 } diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs index 32c8064ebca..41ce03caf08 100644 --- a/compiler/rustc_mir_transform/src/mentioned_items.rs +++ b/compiler/rustc_mir_transform/src/mentioned_items.rs @@ -1,5 +1,5 @@ use rustc_middle::mir::visit::Visitor; -use rustc_middle::mir::{self, Location, MentionedItem, MirPass}; +use rustc_middle::mir::{self, Location, MentionedItem}; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::Session; @@ -13,7 +13,7 @@ struct MentionedItemsVisitor<'a, 'tcx> { mentioned_items: &'a mut Vec<Spanned<MentionedItem<'tcx>>>, } -impl<'tcx> MirPass<'tcx> for MentionedItems { +impl<'tcx> crate::MirPass<'tcx> for MentionedItems { fn is_enabled(&self, _sess: &Session) -> bool { // If this pass is skipped the collector assume that nothing got mentioned! We could // potentially skip it in opt-level 0 if we are sure that opt-level will never *remove* uses diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs index 1e87a0e01d9..1b4972d487e 100644 --- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs +++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs @@ -9,7 +9,7 @@ use crate::simplify; pub struct MultipleReturnTerminators; -impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { +impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 4 } diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs index dd1875f2a78..94573a9d89b 100644 --- a/compiler/rustc_mir_transform/src/nrvo.rs +++ b/compiler/rustc_mir_transform/src/nrvo.rs @@ -8,8 +8,6 @@ use rustc_middle::mir::{self, BasicBlock, Local, Location}; use rustc_middle::ty::TyCtxt; use tracing::{debug, trace}; -use crate::MirPass; - /// This pass looks for MIR that always copies the same local into the return place and eliminates /// the copy by renaming all uses of that local to `_0`. /// @@ -34,7 +32,7 @@ use crate::MirPass; /// [#71003]: https://github.com/rust-lang/rust/pull/71003 pub struct RenameReturnPlace; -impl<'tcx> MirPass<'tcx> for RenameReturnPlace { +impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { // unsound: #111005 sess.mir_opt_level() > 0 && sess.opts.unstable_opts.unsound_mir_opts diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 51e27600404..28d4e1a1c91 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -1,19 +1,99 @@ +use std::cell::RefCell; +use std::collections::hash_map::Entry; + +use rustc_data_structures::fx::FxHashMap; use rustc_middle::mir::{self, Body, MirPhase, RuntimePhase}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use tracing::trace; use crate::lint::lint_body; -use crate::{validate, MirPass}; +use crate::validate; + +thread_local! { + static PASS_NAMES: RefCell<FxHashMap<&'static str, &'static str>> = { + RefCell::new(FxHashMap::default()) + }; +} + +/// Converts a MIR pass name into a snake case form to match the profiling naming style. +fn to_profiler_name(type_name: &'static str) -> &'static str { + PASS_NAMES.with(|names| match names.borrow_mut().entry(type_name) { + Entry::Occupied(e) => *e.get(), + Entry::Vacant(e) => { + let snake_case: String = type_name + .chars() + .flat_map(|c| { + if c.is_ascii_uppercase() { + vec!['_', c.to_ascii_lowercase()] + } else if c == '-' { + vec!['_'] + } else { + vec![c] + } + }) + .collect(); + let result = &*String::leak(format!("mir_pass{}", snake_case)); + e.insert(result); + result + } + }) +} + +// const wrapper for `if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }` +const fn c_name(name: &'static str) -> &'static str { + // FIXME Simplify the implementation once more `str` methods get const-stable. + // and inline into call site + let bytes = name.as_bytes(); + let mut i = bytes.len(); + while i > 0 && bytes[i - 1] != b':' { + i = i - 1; + } + let (_, bytes) = bytes.split_at(i); + match std::str::from_utf8(bytes) { + Ok(name) => name, + Err(_) => name, + } +} + +/// A streamlined trait that you can implement to create a pass; the +/// pass will be named after the type, and it will consist of a main +/// loop that goes over each available MIR and applies `run_pass`. +pub(super) trait MirPass<'tcx> { + fn name(&self) -> &'static str { + // FIXME Simplify the implementation once more `str` methods get const-stable. + // See copypaste in `MirLint` + const { + let name = std::any::type_name::<Self>(); + c_name(name) + } + } + + fn profiler_name(&self) -> &'static str { + to_profiler_name(self.name()) + } + + /// Returns `true` if this pass is enabled with the current combination of compiler flags. + fn is_enabled(&self, _sess: &Session) -> bool { + true + } + + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); + + fn is_mir_dump_enabled(&self) -> bool { + true + } +} -/// Just like `MirPass`, except it cannot mutate `Body`. -pub trait MirLint<'tcx> { +/// Just like `MirPass`, except it cannot mutate `Body`, and MIR dumping is +/// disabled (via the `Lint` adapter). +pub(super) trait MirLint<'tcx> { fn name(&self) -> &'static str { // FIXME Simplify the implementation once more `str` methods get const-stable. // See copypaste in `MirPass` const { let name = std::any::type_name::<Self>(); - rustc_middle::util::common::c_name(name) + c_name(name) } } @@ -26,7 +106,7 @@ pub trait MirLint<'tcx> { /// An adapter for `MirLint`s that implements `MirPass`. #[derive(Debug, Clone)] -pub struct Lint<T>(pub T); +pub(super) struct Lint<T>(pub T); impl<'tcx, T> MirPass<'tcx> for Lint<T> where @@ -49,7 +129,7 @@ where } } -pub struct WithMinOptLevel<T>(pub u32, pub T); +pub(super) struct WithMinOptLevel<T>(pub u32, pub T); impl<'tcx, T> MirPass<'tcx> for WithMinOptLevel<T> where @@ -70,7 +150,7 @@ where /// Run the sequence of passes without validating the MIR after each pass. The MIR is still /// validated at the end. -pub fn run_passes_no_validate<'tcx>( +pub(super) fn run_passes_no_validate<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>], @@ -80,7 +160,7 @@ pub fn run_passes_no_validate<'tcx>( } /// The optional `phase_change` is applied after executing all the passes, if present -pub fn run_passes<'tcx>( +pub(super) fn run_passes<'tcx>( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, passes: &[&dyn MirPass<'tcx>], @@ -89,7 +169,7 @@ pub fn run_passes<'tcx>( run_passes_inner(tcx, body, passes, phase_change, true); } -pub fn should_run_pass<'tcx, P>(tcx: TyCtxt<'tcx>, pass: &P) -> bool +pub(super) fn should_run_pass<'tcx, P>(tcx: TyCtxt<'tcx>, pass: &P) -> bool where P: MirPass<'tcx> + ?Sized, { @@ -185,11 +265,11 @@ fn run_passes_inner<'tcx>( } } -pub fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { +pub(super) fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when: String) { validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body); } -pub fn dump_mir_for_pass<'tcx>( +pub(super) fn dump_mir_for_pass<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, pass_name: &str, @@ -205,7 +285,7 @@ pub fn dump_mir_for_pass<'tcx>( ); } -pub fn dump_mir_for_phase_change<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { +pub(super) fn dump_mir_for_phase_change<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { assert_eq!(body.pass_count, 0); mir::dump_mir(tcx, true, body.phase.name(), &"after", body, |_, _| Ok(())) } diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs index 14dd0c6f61e..ad71c622660 100644 --- a/compiler/rustc_mir_transform/src/prettify.rs +++ b/compiler/rustc_mir_transform/src/prettify.rs @@ -17,7 +17,7 @@ use rustc_session::Session; /// `IndexVec`, unless that successor is a back-edge (such as from a loop). pub struct ReorderBasicBlocks; -impl<'tcx> MirPass<'tcx> for ReorderBasicBlocks { +impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks { fn is_enabled(&self, _session: &Session) -> bool { false } @@ -45,7 +45,7 @@ impl<'tcx> MirPass<'tcx> for ReorderBasicBlocks { /// (Does not reorder arguments nor the [`RETURN_PLACE`].) pub struct ReorderLocals; -impl<'tcx> MirPass<'tcx> for ReorderLocals { +impl<'tcx> crate::MirPass<'tcx> for ReorderLocals { fn is_enabled(&self, _session: &Session) -> bool { false } diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 0c940bac13c..cf0a569ffa4 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -41,7 +41,7 @@ pub struct PromoteTemps<'tcx> { pub promoted_fragments: Cell<IndexVec<Promoted, Body<'tcx>>>, } -impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { +impl<'tcx> crate::MirPass<'tcx> for PromoteTemps<'tcx> { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. // diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs index 8d0b47cb34a..4a447d24cce 100644 --- a/compiler/rustc_mir_transform/src/ref_prop.rs +++ b/compiler/rustc_mir_transform/src/ref_prop.rs @@ -72,7 +72,7 @@ use crate::ssa::{SsaLocals, StorageLiveLocals}; /// so we perform all the possible instantiations without removing the `_1 = &_2` statement. pub struct ReferencePropagation; -impl<'tcx> MirPass<'tcx> for ReferencePropagation { +impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs index 33c7d1695c0..ccba8d015e3 100644 --- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs @@ -10,7 +10,7 @@ use tracing::debug; /// terrible code for these. pub struct RemoveNoopLandingPads; -impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { +impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.panic_strategy() != PanicStrategy::Abort } diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs index 6c0b50fafdb..5801fdedceb 100644 --- a/compiler/rustc_mir_transform/src/remove_place_mention.rs +++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs @@ -6,7 +6,7 @@ use tracing::trace; pub struct RemovePlaceMention; -impl<'tcx> MirPass<'tcx> for RemovePlaceMention { +impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { !sess.opts.unstable_opts.mir_keep_place_mention } diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs index af89395dddd..329b30d3890 100644 --- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs +++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs @@ -6,7 +6,7 @@ use tracing::trace; pub struct RemoveStorageMarkers; -impl<'tcx> MirPass<'tcx> for RemoveStorageMarkers { +impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 && !sess.emit_lifetime_markers() } diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs index fae1cb5f7d8..aafe971311d 100644 --- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs @@ -6,8 +6,6 @@ use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use rustc_mir_dataflow::{move_path_children_matching, Analysis, MaybeReachable}; use rustc_target::abi::FieldIdx; -use crate::MirPass; - /// Removes `Drop` terminators whose target is known to be uninitialized at /// that point. /// @@ -18,7 +16,7 @@ use crate::MirPass; /// [#90770]: https://github.com/rust-lang/rust/issues/90770 pub struct RemoveUninitDrops; -impl<'tcx> MirPass<'tcx> for RemoveUninitDrops { +impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env(body.source.def_id()); let move_data = diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs index 9adcb5a38fd..43109aae0fb 100644 --- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs +++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs @@ -12,7 +12,7 @@ use super::simplify::simplify_cfg; pub struct RemoveUnneededDrops; -impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { +impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { trace!("Running RemoveUnneededDrops on {:?}", body.source); diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 9a94cae3382..9aa46bd4fba 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct RemoveZsts; -impl<'tcx> MirPass<'tcx> for RemoveZsts { +impl<'tcx> crate::MirPass<'tcx> for RemoveZsts { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs index 5eaa024f846..29312a99cbc 100644 --- a/compiler/rustc_mir_transform/src/reveal_all.rs +++ b/compiler/rustc_mir_transform/src/reveal_all.rs @@ -6,7 +6,7 @@ use rustc_middle::ty::{self, Ty, TyCtxt}; pub struct RevealAll; -impl<'tcx> MirPass<'tcx> for RevealAll { +impl<'tcx> crate::MirPass<'tcx> for RevealAll { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env_reveal_all_normalized(body.source.def_id()); RevealAllVisitor { tcx, param_env }.visit_body_preserves_cfg(body); diff --git a/compiler/rustc_mir_transform/src/sanity_check.rs b/compiler/rustc_mir_transform/src/sanity_check.rs new file mode 100644 index 00000000000..c9445d18162 --- /dev/null +++ b/compiler/rustc_mir_transform/src/sanity_check.rs @@ -0,0 +1,11 @@ +use rustc_middle::mir::Body; +use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::rustc_peek::sanity_check; + +pub(super) struct SanityCheck; + +impl<'tcx> crate::MirLint<'tcx> for SanityCheck { + fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { + sanity_check(tcx, body); + } +} diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs index d1c2c91e00f..1478b86d3c7 100644 --- a/compiler/rustc_mir_transform/src/simplify.rs +++ b/compiler/rustc_mir_transform/src/simplify.rs @@ -74,7 +74,7 @@ pub(crate) fn simplify_cfg(body: &mut Body<'_>) { body.basic_blocks_mut().raw.shrink_to_fit(); } -impl<'tcx> MirPass<'tcx> for SimplifyCfg { +impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg { fn name(&self) -> &'static str { self.name() } @@ -366,7 +366,7 @@ pub enum SimplifyLocals { Final, } -impl<'tcx> MirPass<'tcx> for SimplifyLocals { +impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals { fn name(&self) -> &'static str { match &self { SimplifyLocals::BeforeConstProp => "SimplifyLocals-before-const-prop", diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs index 7c8a686d007..5a014bb7346 100644 --- a/compiler/rustc_mir_transform/src/simplify_branches.rs +++ b/compiler/rustc_mir_transform/src/simplify_branches.rs @@ -7,7 +7,7 @@ pub enum SimplifyConstCondition { Final, } /// A pass that replaces a branch with a goto when its condition is known. -impl<'tcx> MirPass<'tcx> for SimplifyConstCondition { +impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition { fn name(&self) -> &'static str { match self { SimplifyConstCondition::AfterConstProp => "SimplifyConstCondition-after-const-prop", diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs index ac892adebec..bd30ecc59b3 100644 --- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs +++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs @@ -9,8 +9,6 @@ use rustc_middle::mir::{ use rustc_middle::ty::{Ty, TyCtxt}; use tracing::trace; -use super::MirPass; - /// Pass to convert `if` conditions on integrals into switches on the integral. /// For an example, it turns something like /// @@ -27,7 +25,7 @@ use super::MirPass; /// ``` pub struct SimplifyComparisonIntegral; -impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { +impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs index 35cb6872fe9..64a92872830 100644 --- a/compiler/rustc_mir_transform/src/single_use_consts.rs +++ b/compiler/rustc_mir_transform/src/single_use_consts.rs @@ -21,7 +21,7 @@ use rustc_middle::ty::TyCtxt; /// needed to do that too, including updating the debug info. pub struct SingleUseConsts; -impl<'tcx> MirPass<'tcx> for SingleUseConsts { +impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 906e2c23f3b..3c5ccc0c99a 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -13,7 +13,7 @@ use tracing::{debug, instrument}; pub struct ScalarReplacementOfAggregates; -impl<'tcx> MirPass<'tcx> for ScalarReplacementOfAggregates { +impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() >= 2 } diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs index 2427fbac5ee..51a322628ee 100644 --- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs +++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs @@ -12,8 +12,6 @@ use rustc_middle::ty::{Ty, TyCtxt}; use rustc_target::abi::{Abi, Variants}; use tracing::trace; -use crate::MirPass; - pub struct UnreachableEnumBranching; fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option<Local> { @@ -74,7 +72,7 @@ fn variant_discriminants<'tcx>( } } -impl<'tcx> MirPass<'tcx> for UnreachableEnumBranching { +impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching { fn is_enabled(&self, sess: &rustc_session::Session) -> bool { sess.mir_opt_level() > 0 } diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs index a6c3c3b189e..b8da86f1a8d 100644 --- a/compiler/rustc_mir_transform/src/unreachable_prop.rs +++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs @@ -12,7 +12,7 @@ use rustc_target::abi::Size; pub struct UnreachablePropagation; -impl MirPass<'_> for UnreachablePropagation { +impl crate::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 diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index 99e06f59dd0..69e2592e82c 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -36,7 +36,7 @@ pub struct Validator { pub mir_phase: MirPhase, } -impl<'tcx> MirPass<'tcx> for Validator { +impl<'tcx> crate::MirPass<'tcx> for Validator { fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // FIXME(JakobDegen): These bodies never instantiated in codegend anyway, so it's not // terribly important that they pass the validator. However, I think other passes might diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index bb05eb4c256..6c9a6011144 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -304,6 +304,11 @@ where let mut candidates = vec![]; + if self.solver_mode() == SolverMode::Coherence { + if let Ok(candidate) = self.consider_coherence_unknowable_candidate(goal) { + return vec![candidate]; + } + } self.assemble_impl_candidates(goal, &mut candidates); self.assemble_builtin_impl_candidates(goal, &mut candidates); @@ -314,11 +319,8 @@ where self.assemble_param_env_candidates(goal, &mut candidates); - match self.solver_mode() { - SolverMode::Normal => self.discard_impls_shadowed_by_env(goal, &mut candidates), - SolverMode::Coherence => { - self.assemble_coherence_unknowable_candidates(goal, &mut candidates) - } + if self.solver_mode() == SolverMode::Normal { + self.discard_impls_shadowed_by_env(goal, &mut candidates); } candidates @@ -682,38 +684,34 @@ where /// also consider impls which may get added in a downstream or sibling crate /// or which an upstream impl may add in a minor release. /// - /// To do so we add an ambiguous candidate in case such an unknown impl could - /// apply to the current goal. + /// To do so we return a single ambiguous candidate in case such an unknown + /// impl could apply to the current goal. #[instrument(level = "trace", skip_all)] - fn assemble_coherence_unknowable_candidates<G: GoalKind<D>>( + fn consider_coherence_unknowable_candidate<G: GoalKind<D>>( &mut self, goal: Goal<I, G>, - candidates: &mut Vec<Candidate<I>>, - ) { - let cx = self.cx(); - - candidates.extend(self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter( - |ecx| { - let trait_ref = goal.predicate.trait_ref(cx); - if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? { - Err(NoSolution) - } else { - // While the trait bound itself may be unknowable, we may be able to - // prove that a super trait is not implemented. For this, we recursively - // prove the super trait bounds of the current goal. - // - // We skip the goal itself as that one would cycle. - let predicate: I::Predicate = trait_ref.upcast(cx); - ecx.add_goals( - GoalSource::Misc, - elaborate::elaborate(cx, [predicate]) - .skip(1) - .map(|predicate| goal.with(cx, predicate)), - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) - } - }, - )) + ) -> Result<Candidate<I>, NoSolution> { + self.probe_trait_candidate(CandidateSource::CoherenceUnknowable).enter(|ecx| { + let cx = ecx.cx(); + let trait_ref = goal.predicate.trait_ref(cx); + if ecx.trait_ref_is_knowable(goal.param_env, trait_ref)? { + Err(NoSolution) + } else { + // While the trait bound itself may be unknowable, we may be able to + // prove that a super trait is not implemented. For this, we recursively + // prove the super trait bounds of the current goal. + // + // We skip the goal itself as that one would cycle. + let predicate: I::Predicate = trait_ref.upcast(cx); + ecx.add_goals( + GoalSource::Misc, + elaborate::elaborate(cx, [predicate]) + .skip(1) + .map(|predicate| goal.with(cx, predicate)), + ); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) + } + }) } /// If there's a where-bound for the current goal, do not use any impl candidates diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 25115c5cafd..c11562ae39e 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -19,17 +19,25 @@ use crate::errors::{ OutsideLoopSuggestion, UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock, }; +/// The context in which a block is encountered. #[derive(Clone, Copy, Debug, PartialEq)] enum Context { Normal, Fn, Loop(hir::LoopSource), Closure(Span), - Coroutine { coroutine_span: Span, kind: hir::CoroutineDesugaring, source: hir::CoroutineSource }, + Coroutine { + coroutine_span: Span, + kind: hir::CoroutineDesugaring, + source: hir::CoroutineSource, + }, UnlabeledBlock(Span), UnlabeledIfBlock(Span), LabeledBlock, - Constant, + /// E.g. The labeled block inside `['_'; 'block: { break 'block 1 + 2; }]`. + AnonConst, + /// E.g. `const { ... }`. + ConstBlock, } #[derive(Clone)] @@ -90,11 +98,11 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { } fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) { - self.with_context(Constant, |v| intravisit::walk_anon_const(v, c)); + self.with_context(AnonConst, |v| intravisit::walk_anon_const(v, c)); } fn visit_inline_const(&mut self, c: &'hir hir::ConstBlock) { - self.with_context(Constant, |v| intravisit::walk_inline_const(v, c)); + self.with_context(ConstBlock, |v| intravisit::walk_inline_const(v, c)); } fn visit_fn( @@ -128,7 +136,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { && matches!( ck_loop.cx_stack.last(), Some(&Normal) - | Some(&Constant) + | Some(&AnonConst) | Some(&UnlabeledBlock(_)) | Some(&UnlabeledIfBlock(_)) ) @@ -175,14 +183,18 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { hir::ExprKind::Block(ref b, Some(_label)) => { self.with_context(LabeledBlock, |v| v.visit_block(b)); } - hir::ExprKind::Block(ref b, None) if matches!(self.cx_stack.last(), Some(&Fn)) => { + hir::ExprKind::Block(ref b, None) + if matches!(self.cx_stack.last(), Some(&Fn) | Some(&ConstBlock)) => + { self.with_context(Normal, |v| v.visit_block(b)); } - hir::ExprKind::Block(ref b, None) - if matches!( - self.cx_stack.last(), - Some(&Normal) | Some(&Constant) | Some(&UnlabeledBlock(_)) - ) => + hir::ExprKind::Block( + ref b @ hir::Block { rules: hir::BlockCheckMode::DefaultBlock, .. }, + None, + ) if matches!( + self.cx_stack.last(), + Some(&Normal) | Some(&AnonConst) | Some(&UnlabeledBlock(_)) + ) => { self.with_context(UnlabeledBlock(b.span.shrink_to_lo()), |v| v.visit_block(b)); } @@ -353,7 +365,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { UnlabeledIfBlock(_) if br_cx_kind == BreakContextKind::Break => { self.require_break_cx(br_cx_kind, span, break_span, cx_pos - 1); } - Normal | Constant | Fn | UnlabeledBlock(_) | UnlabeledIfBlock(_) => { + Normal | AnonConst | Fn | UnlabeledBlock(_) | UnlabeledIfBlock(_) | ConstBlock => { self.sess.dcx().emit_err(OutsideLoop { spans: vec![span], name: &br_cx_kind.to_string(), @@ -365,7 +377,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { } fn require_label_in_labeled_block( - &mut self, + &self, span: Span, label: &Destination, cf_type: &str, @@ -380,7 +392,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { false } - fn report_outside_loop_error(&mut self) { + fn report_outside_loop_error(&self) { for (s, block) in &self.block_breaks { self.sess.dcx().emit_err(OutsideLoop { spans: block.spans.clone(), diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index d7885e05a2f..6c09f97bfe7 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -229,17 +229,11 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> { } else { let variant = &adt.variant(RustcPatCtxt::variant_index_for_adt(&ctor, *adt)); - - // In the cases of either a `#[non_exhaustive]` field list or a non-public - // field, we skip uninhabited fields in order not to reveal the - // uninhabitedness of the whole variant. - let is_non_exhaustive = - variant.is_field_list_non_exhaustive() && !adt.did().is_local(); let tys = cx.variant_sub_tys(ty, variant).map(|(field, ty)| { let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); let is_uninhabited = cx.is_uninhabited(*ty); - let skip = is_uninhabited && (!is_visible || is_non_exhaustive); + let skip = is_uninhabited && !is_visible; (ty, PrivateUninhabitedField(skip)) }); cx.dropless_arena.alloc_from_iter(tys) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index f992ddf8417..e6b00c84254 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2097,9 +2097,10 @@ pub struct TargetOptions { /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults /// to "generic". pub cpu: StaticCow<str>, - /// Default target features to pass to LLVM. These features will *always* be - /// passed, and cannot be disabled even via `-C`. Corresponds to `llc - /// -mattr=$features`. + /// Default target features to pass to LLVM. These features overwrite + /// `-Ctarget-cpu` but can be overwritten with `-Ctarget-features`. + /// Corresponds to `llc -mattr=$features`. + /// Note that these are LLVM feature names, not Rust feature names! pub features: StaticCow<str>, /// Direct or use GOT indirect to reference external data symbols pub direct_access_external_data: Option<bool>, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 5c663e0bf4b..45e157b1080 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -5023,24 +5023,32 @@ impl<'v> Visitor<'v> for AwaitsVisitor { } } +/// Suggest a new type parameter name for diagnostic purposes. +/// +/// `name` is the preferred name you'd like to suggest if it's not in use already. pub trait NextTypeParamName { fn next_type_param_name(&self, name: Option<&str>) -> String; } impl NextTypeParamName for &[hir::GenericParam<'_>] { fn next_type_param_name(&self, name: Option<&str>) -> String { - // This is the list of possible parameter names that we might suggest. + // Type names are usually single letters in uppercase. So convert the first letter of input string to uppercase. let name = name.and_then(|n| n.chars().next()).map(|c| c.to_uppercase().to_string()); let name = name.as_deref(); + + // This is the list of possible parameter names that we might suggest. let possible_names = [name.unwrap_or("T"), "T", "U", "V", "X", "Y", "Z", "A", "B", "C"]; - let used_names = self + + // Filter out used names based on `filter_fn`. + let used_names: Vec<Symbol> = self .iter() - .filter_map(|p| match p.name { + .filter_map(|param| match param.name { hir::ParamName::Plain(ident) => Some(ident.name), _ => None, }) - .collect::<Vec<_>>(); + .collect(); + // Find a name from `possible_names` that is not in `used_names`. possible_names .iter() .find(|n| !used_names.contains(&Symbol::intern(n))) diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 8558520897b..8b55f84bccc 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -29,6 +29,7 @@ use crate::infer::outlives::env::OutlivesEnvironment; use crate::infer::InferOk; use crate::solve::inspect::{InspectGoal, ProofTreeInferCtxtExt, ProofTreeVisitor}; use crate::solve::{deeply_normalize_for_diagnostics, inspect}; +use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{ util, FulfillmentErrorCode, NormalizeExt, Obligation, ObligationCause, PredicateObligation, @@ -624,14 +625,13 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { // at ambiguous goals, as for others the coherence unknowable candidate // was irrelevant. match goal.result() { - Ok(Certainty::Maybe(_)) => {} Ok(Certainty::Yes) | Err(NoSolution) => return, + Ok(Certainty::Maybe(_)) => {} } - let Goal { param_env, predicate } = goal.goal(); - // For bound predicates we simply call `infcx.enter_forall` // and then prove the resulting predicate as a nested goal. + let Goal { param_env, predicate } = goal.goal(); let trait_ref = match predicate.kind().no_bound_vars() { Some(ty::PredicateKind::Clause(ty::ClauseKind::Trait(tr))) => tr.trait_ref, Some(ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj))) @@ -645,7 +645,11 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { _ => return, }; - // Add ambiguity causes for reservation impls. + if trait_ref.references_error() { + return; + } + + let mut candidates = goal.candidates(); for cand in goal.candidates() { if let inspect::ProbeKind::TraitCandidate { source: CandidateSource::Impl(def_id), @@ -664,78 +668,68 @@ impl<'a, 'tcx> ProofTreeVisitor<'tcx> for AmbiguityCausesVisitor<'a, 'tcx> { } } - // Add ambiguity causes for unknowable goals. - let mut ambiguity_cause = None; - for cand in goal.candidates() { - if let inspect::ProbeKind::TraitCandidate { - source: CandidateSource::CoherenceUnknowable, - result: Ok(_), - } = cand.kind() - { - let lazily_normalize_ty = |mut ty: Ty<'tcx>| { - if matches!(ty.kind(), ty::Alias(..)) { - let ocx = ObligationCtxt::new(infcx); - ty = ocx - .structurally_normalize(&ObligationCause::dummy(), param_env, ty) - .map_err(|_| ())?; - if !ocx.select_where_possible().is_empty() { - return Err(()); - } - } - Ok(ty) - }; + // We also look for unknowable candidates. In case a goal is unknowable, there's + // always exactly 1 candidate. + let Some(cand) = candidates.pop() else { + return; + }; - infcx.probe(|_| { - match trait_ref_is_knowable(infcx, trait_ref, lazily_normalize_ty) { - Err(()) => {} - Ok(Ok(())) => warn!("expected an unknowable trait ref: {trait_ref:?}"), - Ok(Err(conflict)) => { - if !trait_ref.references_error() { - // Normalize the trait ref for diagnostics, ignoring any errors if this fails. - let trait_ref = - deeply_normalize_for_diagnostics(infcx, param_env, trait_ref); - - let self_ty = trait_ref.self_ty(); - let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty); - ambiguity_cause = Some(match conflict { - Conflict::Upstream => { - IntercrateAmbiguityCause::UpstreamCrateUpdate { - trait_ref, - self_ty, - } - } - Conflict::Downstream => { - IntercrateAmbiguityCause::DownstreamCrate { - trait_ref, - self_ty, - } - } - }); - } - } - } - }) - } else { - match cand.result() { - // We only add an ambiguity cause if the goal would otherwise - // result in an error. - // - // FIXME: While this matches the behavior of the - // old solver, it is not the only way in which the unknowable - // candidates *weaken* coherence, they can also force otherwise - // successful normalization to be ambiguous. - Ok(Certainty::Maybe(_) | Certainty::Yes) => { - ambiguity_cause = None; - break; - } - Err(NoSolution) => continue, + let inspect::ProbeKind::TraitCandidate { + source: CandidateSource::CoherenceUnknowable, + result: Ok(_), + } = cand.kind() + else { + return; + }; + + let lazily_normalize_ty = |mut ty: Ty<'tcx>| { + if matches!(ty.kind(), ty::Alias(..)) { + let ocx = ObligationCtxt::new(infcx); + ty = ocx + .structurally_normalize(&ObligationCause::dummy(), param_env, ty) + .map_err(|_| ())?; + if !ocx.select_where_possible().is_empty() { + return Err(()); } } - } + Ok(ty) + }; - if let Some(ambiguity_cause) = ambiguity_cause { - self.causes.insert(ambiguity_cause); - } + infcx.probe(|_| { + let conflict = match trait_ref_is_knowable(infcx, trait_ref, lazily_normalize_ty) { + Err(()) => return, + Ok(Ok(())) => { + warn!("expected an unknowable trait ref: {trait_ref:?}"); + return; + } + Ok(Err(conflict)) => conflict, + }; + + // It is only relevant that a goal is unknowable if it would have otherwise + // failed. + let non_intercrate_infcx = infcx.fork_with_intercrate(false); + if non_intercrate_infcx.predicate_may_hold(&Obligation::new( + infcx.tcx, + ObligationCause::dummy(), + param_env, + predicate, + )) { + return; + } + + // Normalize the trait ref for diagnostics, ignoring any errors if this fails. + let trait_ref = deeply_normalize_for_diagnostics(infcx, param_env, trait_ref); + let self_ty = trait_ref.self_ty(); + let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty); + self.causes.insert(match conflict { + Conflict::Upstream => { + IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_ref, self_ty } + } + Conflict::Downstream => { + IntercrateAmbiguityCause::DownstreamCrate { trait_ref, self_ty } + } + }); + }); } } diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 96c939a898b..96998d2ec9f 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -58,7 +58,7 @@ pub enum Reveal { All, } -#[derive(Debug, Clone, Copy)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum SolverMode { /// Ordinary trait solving, using everywhere except for coherence. Normal, |
