diff --git a/RELEASES.md b/RELEASES.md
index 6aba476103e..29c872eb448 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -112,6 +112,14 @@ tools.
- [Add a Rust-for Linux `auto` CI job to check kernel builds.](https://github.com/rust-lang/rust/pull/125209/)
+Version 1.80.1 (2024-08-08)
+===========================
+
+
+
+- [Fix miscompilation in the jump threading MIR optimization when comparing floats](https://github.com/rust-lang/rust/pull/128271)
+- [Revert changes to the `dead_code` lint from 1.80.0](https://github.com/rust-lang/rust/pull/128618)
+
Version 1.80.0 (2024-07-25)
==========================
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`
// and suggest `Trait0`.
+ // 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` 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`
+ // suggestion.
+ let suggestion = if borrowed {
+ vec![(ty.span, format!("Box"))]
+ } else {
vec![
(ty.span.shrink_to_lo(), "Box".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> = {
- 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::();
- 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 {
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 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> {
&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>>,
}
-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;
-/// Just like `MirPass`, except it cannot mutate `Body`.
-pub trait MirLint<'tcx> {
+thread_local! {
+ static PASS_NAMES: RefCell> = {
+ 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::();
+ 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`, 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::();
- 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(pub T);
+pub(super) struct Lint(pub T);
impl<'tcx, T> MirPass<'tcx> for Lint
where
@@ -49,7 +129,7 @@ where
}
}
-pub struct WithMinOptLevel(pub u32, pub T);
+pub(super) struct WithMinOptLevel(pub u32, pub T);
impl<'tcx, T> MirPass<'tcx> for WithMinOptLevel
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>>,
}
-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 {
@@ -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>(
+ fn consider_coherence_unknowable_candidate>(
&mut self,
goal: Goal,
- candidates: &mut Vec>,
- ) {
- 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, 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,
- /// 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,
/// Direct or use GOT indirect to reference external data symbols
pub direct_access_external_data: Option,
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 = self
.iter()
- .filter_map(|p| match p.name {
+ .filter_map(|param| match param.name {
hir::ParamName::Plain(ident) => Some(ident.name),
_ => None,
})
- .collect::>();
+ .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 inspect::ProbeKind::TraitCandidate {
+ source: CandidateSource::CoherenceUnknowable,
+ result: Ok(_),
+ } = cand.kind()
+ else {
+ return;
+ };
- 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 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,
diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md
index 12b7817c382..0e06a820a22 100644
--- a/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md
+++ b/src/doc/rustc/src/platform-support/wasm32-unknown-unknown.md
@@ -195,3 +195,120 @@ conditionally compile code instead. This is notably different to the way native
platforms such as x86\_64 work, and this is due to the fact that WebAssembly
binaries must only contain code the engine understands. Native binaries work so
long as the CPU doesn't execute unknown code dynamically at runtime.
+
+## Broken `extern "C"` ABI
+
+This target has what is considered a broken `extern "C"` ABI implementation at
+this time. Notably the same signature in Rust and C will compile to different
+WebAssembly functions and be incompatible. This is considered a bug and it will
+be fixed in a future version of Rust.
+
+For example this Rust code:
+
+```rust,ignore (does-not-link)
+#[repr(C)]
+struct MyPair {
+ a: u32,
+ b: u32,
+}
+
+extern "C" {
+ fn take_my_pair(pair: MyPair) -> u32;
+}
+
+#[no_mangle]
+pub unsafe extern "C" fn call_c() -> u32 {
+ take_my_pair(MyPair { a: 1, b: 2 })
+}
+```
+
+compiles to a WebAssembly module that looks like:
+
+```wasm
+(module
+ (import "env" "take_my_pair" (func $take_my_pair (param i32 i32) (result i32)))
+ (func $call_c
+ i32.const 1
+ i32.const 2
+ call $take_my_pair
+ )
+)
+```
+
+The function when defined in C, however, looks like
+
+```c
+struct my_pair {
+ unsigned a;
+ unsigned b;
+};
+
+unsigned take_my_pair(struct my_pair pair) {
+ return pair.a + pair.b;
+}
+```
+
+```wasm
+(module
+ (import "env" "__linear_memory" (memory 0))
+ (func $take_my_pair (param i32) (result i32)
+ local.get 0
+ i32.load offset=4
+ local.get 0
+ i32.load
+ i32.add
+ )
+)
+```
+
+Notice how Rust thinks `take_my_pair` takes two `i32` parameters but C thinks it
+only takes one.
+
+The correct definition of the `extern "C"` ABI for WebAssembly is located in the
+[WebAssembly/tool-conventions](https://github.com/WebAssembly/tool-conventions/blob/main/BasicCABI.md)
+repository. The `wasm32-unknown-unknown` target (and only this target, not other
+WebAssembly targets Rust support) does not correctly follow this document.
+
+Example issues in the Rust repository about this bug are:
+
+* [#115666](https://github.com/rust-lang/rust/issues/115666)
+* [#129486](https://github.com/rust-lang/rust/issues/129486)
+
+This current state of the `wasm32-unknown-unknown` backend is due to an
+unfortunate accident which got relied on. The `wasm-bindgen` project prior to
+0.2.89 was incompatible with the "correct" definition of `extern "C"` and it was
+seen as not worth the tradeoff of breaking `wasm-bindgen` historically to fix
+this issue in the compiler.
+
+Thanks to the heroic efforts of many involved in this, however, `wasm-bindgen`
+0.2.89 and later are compatible with the correct definition of `extern "C"` and
+the nightly compiler currently supports a `-Zwasm-c-abi` implemented in
+[#117919](https://github.com/rust-lang/rust/pull/117919). This nightly-only flag
+can be used to indicate whether the spec-defined version of `extern "C"` should
+be used instead of the "legacy" version of
+whatever-the-Rust-target-originally-implemented. For example using the above
+code you can see (lightly edited for clarity):
+
+```shell
+$ rustc +nightly -Zwasm-c-abi=spec foo.rs --target wasm32-unknown-unknown --crate-type lib --emit obj -O
+$ wasm-tools print foo.o
+(module
+ (import "env" "take_my_pair" (func $take_my_pair (param i32) (result i32)))
+ (func $call_c (result i32)
+ ;; ...
+ )
+ ;; ...
+)
+```
+
+which shows that the C and Rust definitions of the same function now agree like
+they should.
+
+The `-Zwasm-c-abi` compiler flag is tracked in
+[#122532](https://github.com/rust-lang/rust/issues/122532) and a lint was
+implemented in [#117918](https://github.com/rust-lang/rust/issues/117918) to
+help warn users about the transition if they're using `wasm-bindgen` 0.2.88 or
+prior. The current plan is to, in the future, switch `-Zwasm-c-api=spec` to
+being the default. Some time after that the `-Zwasm-c-abi` flag and the
+"legacy" implementation will all be removed. During this process users on a
+sufficiently updated version of `wasm-bindgen` should not experience breakage.
diff --git a/tests/ui/coherence/normalize-for-errors.next.stderr b/tests/ui/coherence/normalize-for-errors.next.stderr
index 634a10b7a14..44952dc1944 100644
--- a/tests/ui/coherence/normalize-for-errors.next.stderr
+++ b/tests/ui/coherence/normalize-for-errors.next.stderr
@@ -7,7 +7,7 @@ LL |
LL | impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `(Box<(MyType,)>, <_ as Iterator>::Item)`
|
- = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions
+ = note: upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions
= note: upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
error: aborting due to 1 previous error
diff --git a/tests/ui/coherence/normalize-for-errors.rs b/tests/ui/coherence/normalize-for-errors.rs
index 4188389a3ad..c17bb766b5b 100644
--- a/tests/ui/coherence/normalize-for-errors.rs
+++ b/tests/ui/coherence/normalize-for-errors.rs
@@ -18,6 +18,6 @@ impl MyTrait for (Box<<(MyType,) as Mirror>::Assoc>, S::Item) {}
//~^ ERROR conflicting implementations of trait `MyTrait<_>` for type `(Box<(MyType,)>,
//~| NOTE conflicting implementation for `(Box<(MyType,)>,
//~| NOTE upstream crates may add a new impl of trait `std::marker::Copy` for type `std::boxed::Box<(MyType,)>` in future versions
-//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `(MyType,)` in future versions
+//[next]~| NOTE upstream crates may add a new impl of trait `std::clone::Clone` for type `std::boxed::Box<(MyType,)>` in future versions
fn main() {}
diff --git a/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr
index b39689afd1c..52ee6c81ab7 100644
--- a/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr
+++ b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr
@@ -4,7 +4,15 @@ error[E0782]: trait objects must include the `dyn` keyword
LL | fn function(x: &SomeTrait, y: Box) {
| ^^^^^^^^^
|
-help: add `dyn` keyword before this trait
+help: use a new generic type parameter, constrained by `SomeTrait`
+ |
+LL | fn function(x: &T, y: Box) {
+ | ++++++++++++++ ~
+help: 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
+ |
+LL | fn function(x: &impl SomeTrait, y: Box) {
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `SomeTrait`, accessing its methods at runtime using dynamic dispatch
|
LL | fn function(x: &dyn SomeTrait, y: Box) {
| +++
diff --git a/tests/ui/inline-const/break-inside-inline-const-issue-128604.rs b/tests/ui/inline-const/break-inside-inline-const-issue-128604.rs
new file mode 100644
index 00000000000..a9795d1569c
--- /dev/null
+++ b/tests/ui/inline-const/break-inside-inline-const-issue-128604.rs
@@ -0,0 +1,25 @@
+fn main() {
+ let _ = ['a'; { break 2; 1 }];
+ //~^ ERROR `break` outside of a loop or labeled block
+ //~| HELP consider labeling this block to be able to break within it
+
+ const {
+ {
+ //~^ HELP consider labeling this block to be able to break within it
+ break;
+ //~^ ERROR `break` outside of a loop or labeled block
+ }
+ };
+
+ const {
+ break;
+ //~^ ERROR `break` outside of a loop or labeled block
+ };
+
+ {
+ const {
+ break;
+ //~^ ERROR `break` outside of a loop or labeled block
+ }
+ }
+}
diff --git a/tests/ui/inline-const/break-inside-inline-const-issue-128604.stderr b/tests/ui/inline-const/break-inside-inline-const-issue-128604.stderr
new file mode 100644
index 00000000000..300cd45ad69
--- /dev/null
+++ b/tests/ui/inline-const/break-inside-inline-const-issue-128604.stderr
@@ -0,0 +1,39 @@
+error[E0268]: `break` outside of a loop or labeled block
+ --> $DIR/break-inside-inline-const-issue-128604.rs:15:9
+ |
+LL | break;
+ | ^^^^^ cannot `break` outside of a loop or labeled block
+
+error[E0268]: `break` outside of a loop or labeled block
+ --> $DIR/break-inside-inline-const-issue-128604.rs:21:13
+ |
+LL | break;
+ | ^^^^^ cannot `break` outside of a loop or labeled block
+
+error[E0268]: `break` outside of a loop or labeled block
+ --> $DIR/break-inside-inline-const-issue-128604.rs:2:21
+ |
+LL | let _ = ['a'; { break 2; 1 }];
+ | ^^^^^^^ cannot `break` outside of a loop or labeled block
+ |
+help: consider labeling this block to be able to break within it
+ |
+LL | let _ = ['a'; 'block: { break 'block 2; 1 }];
+ | +++++++ ++++++
+
+error[E0268]: `break` outside of a loop or labeled block
+ --> $DIR/break-inside-inline-const-issue-128604.rs:9:13
+ |
+LL | break;
+ | ^^^^^ cannot `break` outside of a loop or labeled block
+ |
+help: consider labeling this block to be able to break within it
+ |
+LL ~ 'block: {
+LL |
+LL ~ break 'block;
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0268`.
diff --git a/tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs b/tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs
new file mode 100644
index 00000000000..dabaa309c16
--- /dev/null
+++ b/tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs
@@ -0,0 +1,142 @@
+//@ edition:2021
+
+trait Trait {}
+
+struct IceCream;
+
+impl IceCream {
+ fn foo(_: &Trait) {}
+ //~^ ERROR: trait objects must include the `dyn` keyword
+
+ fn bar(self, _: &'a Trait) {}
+ //~^ ERROR: trait objects must include the `dyn` keyword
+ //~| ERROR: use of undeclared lifetime name
+
+ fn alice<'a>(&self, _: &Trait) {}
+ //~^ ERROR: trait objects must include the `dyn` keyword
+
+ fn bob<'a>(_: &'a Trait) {}
+ //~^ ERROR: trait objects must include the `dyn` keyword
+
+ fn cat() -> &Trait {
+ //~^ ERROR: missing lifetime specifier
+ //~| ERROR: trait objects must include the `dyn` keyword
+ &Type
+ }
+
+ fn dog<'a>() -> &Trait {
+ //~^ ERROR: missing lifetime specifier
+ //~| ERROR: trait objects must include the `dyn` keyword
+ &Type
+ }
+
+ fn kitten() -> &'a Trait {
+ //~^ ERROR: use of undeclared lifetime name
+ //~| ERROR: trait objects must include the `dyn` keyword
+ &Type
+ }
+
+ fn puppy<'a>() -> &'a Trait {
+ //~^ ERROR: trait objects must include the `dyn` keyword
+ &Type
+ }
+
+ fn parrot() -> &mut Trait {
+ //~^ ERROR: missing lifetime specifier
+ //~| ERROR: trait objects must include the `dyn` keyword
+ &mut Type
+ //~^ ERROR: cannot return reference to temporary value
+ }
+}
+
+trait Sing {
+ fn foo(_: &Trait);
+ //~^ ERROR: trait objects must include the `dyn` keyword
+
+ fn bar(_: &'a Trait);
+ //~^ ERROR: trait objects must include the `dyn` keyword
+ //~| ERROR: use of undeclared lifetime name
+
+ fn alice<'a>(_: &Trait);
+ //~^ ERROR: trait objects must include the `dyn` keyword
+
+ fn bob<'a>(_: &'a Trait);
+ //~^ ERROR: trait objects must include the `dyn` keyword
+
+ fn cat() -> &Trait;
+ //~^ ERROR: missing lifetime specifier
+ //~| ERROR: trait objects must include the `dyn` keyword
+
+ fn dog<'a>() -> &Trait {
+ //~^ ERROR: missing lifetime specifier
+ //~| ERROR: trait objects must include the `dyn` keyword
+ &Type
+ }
+
+ fn kitten() -> &'a Trait {
+ //~^ ERROR: use of undeclared lifetime name
+ //~| ERROR: trait objects must include the `dyn` keyword
+ &Type
+ }
+
+ fn puppy<'a>() -> &'a Trait {
+ //~^ ERROR: trait objects must include the `dyn` keyword
+ &Type
+ }
+
+ fn parrot() -> &mut Trait {
+ //~^ ERROR: missing lifetime specifier
+ //~| ERROR: trait objects must include the `dyn` keyword
+ &mut Type
+ //~^ ERROR: cannot return reference to temporary value
+ }
+}
+
+fn foo(_: &Trait) {}
+//~^ ERROR: trait objects must include the `dyn` keyword
+
+fn bar(_: &'a Trait) {}
+//~^ ERROR: trait objects must include the `dyn` keyword
+//~| ERROR: use of undeclared lifetime name
+
+fn alice<'a>(_: &Trait) {}
+//~^ ERROR: trait objects must include the `dyn` keyword
+
+fn bob<'a>(_: &'a Trait) {}
+//~^ ERROR: trait objects must include the `dyn` keyword
+
+struct Type;
+
+impl Trait for Type {}
+
+fn cat() -> &Trait {
+//~^ ERROR: missing lifetime specifier
+//~| ERROR: trait objects must include the `dyn` keyword
+ &Type
+}
+
+fn dog<'a>() -> &Trait {
+//~^ ERROR: missing lifetime specifier
+//~| ERROR: trait objects must include the `dyn` keyword
+ &Type
+}
+
+fn kitten() -> &'a Trait {
+//~^ ERROR: use of undeclared lifetime name
+//~| ERROR: trait objects must include the `dyn` keyword
+ &Type
+}
+
+fn puppy<'a>() -> &'a Trait {
+//~^ ERROR: trait objects must include the `dyn` keyword
+ &Type
+}
+
+fn parrot() -> &mut Trait {
+ //~^ ERROR: missing lifetime specifier
+ //~| ERROR: trait objects must include the `dyn` keyword
+ &mut Type
+ //~^ ERROR: cannot return reference to temporary value
+}
+
+fn main() {}
diff --git a/tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr b/tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr
new file mode 100644
index 00000000000..8bdfea7766e
--- /dev/null
+++ b/tests/ui/object-safety/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.stderr
@@ -0,0 +1,673 @@
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:11:22
+ |
+LL | fn bar(self, _: &'a Trait) {}
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn bar<'a>(self, _: &'a Trait) {}
+ | ++++
+help: consider introducing lifetime `'a` here
+ |
+LL | impl<'a> IceCream {
+ | ++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:21:17
+ |
+LL | fn cat() -> &Trait {
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+ |
+LL | fn cat() -> &'static Trait {
+ | +++++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:27:21
+ |
+LL | fn dog<'a>() -> &Trait {
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'a` lifetime
+ |
+LL | fn dog<'a>() -> &'a Trait {
+ | ++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:33:21
+ |
+LL | fn kitten() -> &'a Trait {
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn kitten<'a>() -> &'a Trait {
+ | ++++
+help: consider introducing lifetime `'a` here
+ |
+LL | impl<'a> IceCream {
+ | ++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:44:20
+ |
+LL | fn parrot() -> &mut Trait {
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+ |
+LL | fn parrot() -> &'static mut Trait {
+ | +++++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:56:16
+ |
+LL | fn bar(_: &'a Trait);
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn bar<'a>(_: &'a Trait);
+ | ++++
+help: consider introducing lifetime `'a` here
+ |
+LL | trait Sing<'a> {
+ | ++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:66:17
+ |
+LL | fn cat() -> &Trait;
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+ |
+LL | fn cat() -> &'static Trait;
+ | +++++++
+help: instead, you are more likely to want to return an owned value
+ |
+LL - fn cat() -> &Trait;
+LL + fn cat() -> Trait;
+ |
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:70:21
+ |
+LL | fn dog<'a>() -> &Trait {
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'a` lifetime
+ |
+LL | fn dog<'a>() -> &'a Trait {
+ | ++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:76:21
+ |
+LL | fn kitten() -> &'a Trait {
+ | ^^ undeclared lifetime
+ |
+help: consider introducing lifetime `'a` here
+ |
+LL | fn kitten<'a>() -> &'a Trait {
+ | ++++
+help: consider introducing lifetime `'a` here
+ |
+LL | trait Sing<'a> {
+ | ++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:87:20
+ |
+LL | fn parrot() -> &mut Trait {
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+ |
+LL | fn parrot() -> &'static mut Trait {
+ | +++++++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:98:12
+ |
+LL | fn bar(_: &'a Trait) {}
+ | - ^^ undeclared lifetime
+ | |
+ | help: consider introducing lifetime `'a` here: `<'a>`
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:112:13
+ |
+LL | fn cat() -> &Trait {
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+ |
+LL | fn cat() -> &'static Trait {
+ | +++++++
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:118:17
+ |
+LL | fn dog<'a>() -> &Trait {
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'a` lifetime
+ |
+LL | fn dog<'a>() -> &'a Trait {
+ | ++
+
+error[E0261]: use of undeclared lifetime name `'a`
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:124:17
+ |
+LL | fn kitten() -> &'a Trait {
+ | - ^^ undeclared lifetime
+ | |
+ | help: consider introducing lifetime `'a` here: `<'a>`
+
+error[E0106]: missing lifetime specifier
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:135:16
+ |
+LL | fn parrot() -> &mut Trait {
+ | ^ expected named lifetime parameter
+ |
+ = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from
+help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`
+ |
+LL | fn parrot() -> &'static mut Trait {
+ | +++++++
+
+error[E0515]: cannot return reference to temporary value
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:47:9
+ |
+LL | &mut Type
+ | ^^^^^----
+ | | |
+ | | temporary value created here
+ | returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:90:9
+ |
+LL | &mut Type
+ | ^^^^^----
+ | | |
+ | | temporary value created here
+ | returns a reference to data owned by the current function
+
+error[E0515]: cannot return reference to temporary value
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:138:5
+ |
+LL | &mut Type
+ | ^^^^^----
+ | | |
+ | | temporary value created here
+ | returns a reference to data owned by the current function
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:53:16
+ |
+LL | fn foo(_: &Trait);
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn foo(_: &T);
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn foo(_: &impl Trait);
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn foo(_: &dyn Trait);
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:56:19
+ |
+LL | fn bar(_: &'a Trait);
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn bar(_: &'a T);
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn bar(_: &'a impl Trait);
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn bar(_: &'a dyn Trait);
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:60:22
+ |
+LL | fn alice<'a>(_: &Trait);
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn alice<'a, T: Trait>(_: &T);
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn alice<'a>(_: &impl Trait);
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn alice<'a>(_: &dyn Trait);
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:63:23
+ |
+LL | fn bob<'a>(_: &'a Trait);
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn bob<'a, T: Trait>(_: &'a T);
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn bob<'a>(_: &'a impl Trait);
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn bob<'a>(_: &'a dyn Trait);
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:66:18
+ |
+LL | fn cat() -> &Trait;
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn cat() -> &impl Trait;
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn cat() -> Box;
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:70:22
+ |
+LL | fn dog<'a>() -> &Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn dog<'a>() -> &impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn dog<'a>() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:76:24
+ |
+LL | fn kitten() -> &'a Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn kitten() -> &'a impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn kitten() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:82:27
+ |
+LL | fn puppy<'a>() -> &'a Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn puppy<'a>() -> &'a impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn puppy<'a>() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:87:25
+ |
+LL | fn parrot() -> &mut Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn parrot() -> &mut impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn parrot() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:95:12
+ |
+LL | fn foo(_: &Trait) {}
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn foo(_: &T) {}
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn foo(_: &impl Trait) {}
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn foo(_: &dyn Trait) {}
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:98:15
+ |
+LL | fn bar(_: &'a Trait) {}
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn bar(_: &'a T) {}
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn bar(_: &'a impl Trait) {}
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn bar(_: &'a dyn Trait) {}
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:102:18
+ |
+LL | fn alice<'a>(_: &Trait) {}
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn alice<'a, T: Trait>(_: &T) {}
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn alice<'a>(_: &impl Trait) {}
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn alice<'a>(_: &dyn Trait) {}
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:105:19
+ |
+LL | fn bob<'a>(_: &'a Trait) {}
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn bob<'a, T: Trait>(_: &'a T) {}
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn bob<'a>(_: &'a impl Trait) {}
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn bob<'a>(_: &'a dyn Trait) {}
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:112:14
+ |
+LL | fn cat() -> &Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn cat() -> &impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn cat() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:118:18
+ |
+LL | fn dog<'a>() -> &Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn dog<'a>() -> &impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn dog<'a>() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:124:20
+ |
+LL | fn kitten() -> &'a Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn kitten() -> &'a impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn kitten() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:130:23
+ |
+LL | fn puppy<'a>() -> &'a Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn puppy<'a>() -> &'a impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn puppy<'a>() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:135:21
+ |
+LL | fn parrot() -> &mut Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn parrot() -> &mut impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn parrot() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:8:16
+ |
+LL | fn foo(_: &Trait) {}
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn foo(_: &T) {}
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn foo(_: &impl Trait) {}
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn foo(_: &dyn Trait) {}
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:11:25
+ |
+LL | fn bar(self, _: &'a Trait) {}
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn bar(self, _: &'a T) {}
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn bar(self, _: &'a impl Trait) {}
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn bar(self, _: &'a dyn Trait) {}
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:15:29
+ |
+LL | fn alice<'a>(&self, _: &Trait) {}
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn alice<'a, T: Trait>(&self, _: &T) {}
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn alice<'a>(&self, _: &impl Trait) {}
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn alice<'a>(&self, _: &dyn Trait) {}
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:18:23
+ |
+LL | fn bob<'a>(_: &'a Trait) {}
+ | ^^^^^
+ |
+help: use a new generic type parameter, constrained by `Trait`
+ |
+LL | fn bob<'a, T: Trait>(_: &'a T) {}
+ | ++++++++++ ~
+help: 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
+ |
+LL | fn bob<'a>(_: &'a impl Trait) {}
+ | ++++
+help: alternatively, use a trait object to accept any type that implements `Trait`, accessing its methods at runtime using dynamic dispatch
+ |
+LL | fn bob<'a>(_: &'a dyn Trait) {}
+ | +++
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:21:18
+ |
+LL | fn cat() -> &Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn cat() -> &impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn cat() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:27:22
+ |
+LL | fn dog<'a>() -> &Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn dog<'a>() -> &impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn dog<'a>() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:33:24
+ |
+LL | fn kitten() -> &'a Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn kitten() -> &'a impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn kitten() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:39:27
+ |
+LL | fn puppy<'a>() -> &'a Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn puppy<'a>() -> &'a impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn puppy<'a>() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error[E0782]: trait objects must include the `dyn` keyword
+ --> $DIR/reference-to-bare-trait-in-fn-inputs-and-outputs-issue-125139.rs:44:25
+ |
+LL | fn parrot() -> &mut Trait {
+ | ^^^^^
+ |
+help: use `impl Trait` to return an opaque type, as long as you return a single underlying type
+ |
+LL | fn parrot() -> &mut impl Trait {
+ | ++++
+help: alternatively, you can return an owned trait object
+ |
+LL | fn parrot() -> Box {
+ | ~~~~~~~~~~~~~~
+
+error: aborting due to 45 previous errors
+
+Some errors have detailed explanations: E0106, E0261, E0515, E0782.
+For more information about an error, try `rustc --explain E0106`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs
index a2735d4cbfb..e1799761b69 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/auxiliary/uninhabited.rs
@@ -7,11 +7,17 @@ pub enum UninhabitedEnum {
#[non_exhaustive]
pub struct UninhabitedStruct {
- _priv: !,
+ pub never: !,
+ _priv: (),
}
#[non_exhaustive]
-pub struct UninhabitedTupleStruct(!);
+pub struct PrivatelyUninhabitedStruct {
+ never: !,
+}
+
+#[non_exhaustive]
+pub struct UninhabitedTupleStruct(pub !);
pub enum UninhabitedVariants {
#[non_exhaustive] Tuple(!),
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
index 66e93291c72..f332e6deeb8 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match.stderr
@@ -5,7 +5,7 @@ LL | match x {}
| ^
|
note: `IndirectUninhabitedEnum` defined here
- --> $DIR/auxiliary/uninhabited.rs:26:1
+ --> $DIR/auxiliary/uninhabited.rs:32:1
|
LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL | match x {}
| ^
|
note: `IndirectUninhabitedStruct` defined here
- --> $DIR/auxiliary/uninhabited.rs:28:1
+ --> $DIR/auxiliary/uninhabited.rs:34:1
|
LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,7 +43,7 @@ LL | match x {}
| ^
|
note: `IndirectUninhabitedTupleStruct` defined here
- --> $DIR/auxiliary/uninhabited.rs:30:1
+ --> $DIR/auxiliary/uninhabited.rs:36:1
|
LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +62,7 @@ LL | match x {}
| ^
|
note: `IndirectUninhabitedVariants` defined here
- --> $DIR/auxiliary/uninhabited.rs:32:1
+ --> $DIR/auxiliary/uninhabited.rs:38:1
|
LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr
index 745b196a0e3..48f3857bfa7 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/indirect_match_with_exhaustive_patterns.stderr
@@ -5,7 +5,7 @@ LL | match x {}
| ^
|
note: `IndirectUninhabitedEnum` defined here
- --> $DIR/auxiliary/uninhabited.rs:26:1
+ --> $DIR/auxiliary/uninhabited.rs:32:1
|
LL | pub struct IndirectUninhabitedEnum(UninhabitedEnum);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +24,7 @@ LL | match x {}
| ^
|
note: `IndirectUninhabitedStruct` defined here
- --> $DIR/auxiliary/uninhabited.rs:28:1
+ --> $DIR/auxiliary/uninhabited.rs:34:1
|
LL | pub struct IndirectUninhabitedStruct(UninhabitedStruct);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -43,7 +43,7 @@ LL | match x {}
| ^
|
note: `IndirectUninhabitedTupleStruct` defined here
- --> $DIR/auxiliary/uninhabited.rs:30:1
+ --> $DIR/auxiliary/uninhabited.rs:36:1
|
LL | pub struct IndirectUninhabitedTupleStruct(UninhabitedTupleStruct);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -62,7 +62,7 @@ LL | match x {}
| ^
|
note: `IndirectUninhabitedVariants` defined here
- --> $DIR/auxiliary/uninhabited.rs:32:1
+ --> $DIR/auxiliary/uninhabited.rs:38:1
|
LL | pub struct IndirectUninhabitedVariants(UninhabitedVariants);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs
index fd77fab8738..6bee019e897 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.rs
@@ -11,11 +11,12 @@ use uninhabited::PartiallyInhabitedVariants;
pub fn foo(x: PartiallyInhabitedVariants) {
match x {
- PartiallyInhabitedVariants::Struct { .. } => {},
- PartiallyInhabitedVariants::Struct { .. } => {},
+ PartiallyInhabitedVariants::Struct { .. } => {}
//~^ ERROR unreachable pattern
- _ => {},
+ PartiallyInhabitedVariants::Struct { .. } => {}
+ //~^ ERROR unreachable pattern
+ _ => {}
}
}
-fn main() { }
+fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
index 956725fc10e..4fa53101a55 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/issue-65157-repeated-match-arm.stderr
@@ -1,16 +1,23 @@
error: unreachable pattern
- --> $DIR/issue-65157-repeated-match-arm.rs:15:9
+ --> $DIR/issue-65157-repeated-match-arm.rs:14:9
|
-LL | PartiallyInhabitedVariants::Struct { .. } => {},
- | ----------------------------------------- matches all the relevant values
-LL | PartiallyInhabitedVariants::Struct { .. } => {},
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
+LL | PartiallyInhabitedVariants::Struct { .. } => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `PartiallyInhabitedVariants` is uninhabited
|
+ = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
note: the lint level is defined here
--> $DIR/issue-65157-repeated-match-arm.rs:2:9
|
LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
-error: aborting due to 1 previous error
+error: unreachable pattern
+ --> $DIR/issue-65157-repeated-match-arm.rs:16:9
+ |
+LL | PartiallyInhabitedVariants::Struct { .. } => {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `PartiallyInhabitedVariants` is uninhabited
+ |
+ = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
+
+error: aborting due to 2 previous errors
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs
index c330f3aa05c..58d7bbd2c17 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.rs
@@ -3,12 +3,7 @@
extern crate uninhabited;
-use uninhabited::{
- UninhabitedEnum,
- UninhabitedStruct,
- UninhabitedTupleStruct,
- UninhabitedVariants,
-};
+use uninhabited::*;
struct A;
@@ -19,16 +14,20 @@ fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
match x {} //~ ERROR non-exhaustive patterns
}
-fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+fn empty_match_on_empty_struct(x: UninhabitedStruct) -> A {
+ match x {}
+}
+
+fn cannot_empty_match_on_privately_empty_struct(x: PrivatelyUninhabitedStruct) -> A {
match x {} //~ ERROR non-exhaustive patterns
}
-fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+fn empty_match_on_empty_tuple_struct(x: UninhabitedTupleStruct) -> A {
+ match x {}
}
-fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+fn empty_match_on_enum_with_empty_variants_struct(x: UninhabitedVariants) -> A {
+ match x {}
}
fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr
index c125756a646..0232e7106aa 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match.stderr
@@ -1,15 +1,15 @@
-error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty
- --> $DIR/match.rs:19:11
+error[E0004]: non-exhaustive patterns: type `uninhabited::UninhabitedEnum` is non-empty
+ --> $DIR/match.rs:14:11
|
LL | match x {}
| ^
|
-note: `UninhabitedEnum` defined here
+note: `uninhabited::UninhabitedEnum` defined here
--> $DIR/auxiliary/uninhabited.rs:5:1
|
LL | pub enum UninhabitedEnum {
| ^^^^^^^^^^^^^^^^^^^^^^^^
- = note: the matched value is of type `UninhabitedEnum`, which is marked as non-exhaustive
+ = note: the matched value is of type `uninhabited::UninhabitedEnum`, which is marked as non-exhaustive
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match x {
@@ -17,18 +17,18 @@ LL + _ => todo!(),
LL ~ }
|
-error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
- --> $DIR/match.rs:23:11
+error[E0004]: non-exhaustive patterns: type `uninhabited::PrivatelyUninhabitedStruct` is non-empty
+ --> $DIR/match.rs:22:11
|
LL | match x {}
| ^
|
-note: `UninhabitedStruct` defined here
- --> $DIR/auxiliary/uninhabited.rs:9:1
+note: `uninhabited::PrivatelyUninhabitedStruct` defined here
+ --> $DIR/auxiliary/uninhabited.rs:15:1
|
-LL | pub struct UninhabitedStruct {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: the matched value is of type `UninhabitedStruct`
+LL | pub struct PrivatelyUninhabitedStruct {
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ = note: the matched value is of type `uninhabited::PrivatelyUninhabitedStruct`
help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
|
LL ~ match x {
@@ -36,48 +36,6 @@ LL + _ => todo!(),
LL ~ }
|
-error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
- --> $DIR/match.rs:27:11
- |
-LL | match x {}
- | ^
- |
-note: `UninhabitedTupleStruct` defined here
- --> $DIR/auxiliary/uninhabited.rs:14:1
- |
-LL | pub struct UninhabitedTupleStruct(!);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: the matched value is of type `UninhabitedTupleStruct`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match x {
-LL + _ => todo!(),
-LL ~ }
- |
-
-error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
- --> $DIR/match.rs:31:11
- |
-LL | match x {}
- | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
- |
-note: `UninhabitedVariants` defined here
- --> $DIR/auxiliary/uninhabited.rs:16:1
- |
-LL | pub enum UninhabitedVariants {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL | #[non_exhaustive] Tuple(!),
- | ----- not covered
-LL | #[non_exhaustive] Struct { x: ! }
- | ------ not covered
- = note: the matched value is of type `UninhabitedVariants`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
- |
-LL ~ match x {
-LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(),
-LL ~ }
- |
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs
index 108cac7099e..c214581549c 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.rs
@@ -5,32 +5,28 @@
extern crate uninhabited;
use uninhabited::{
- UninhabitedEnum,
- UninhabitedStruct,
- UninhabitedTupleStruct,
- UninhabitedVariants,
+ UninhabitedEnum, UninhabitedStruct, UninhabitedTupleStruct, UninhabitedVariants,
};
struct A;
-// This test checks that an empty match on a non-exhaustive uninhabited type from an extern crate
-// will not compile. In particular, this enables the `exhaustive_patterns` feature as this can
-// change the branch used in the compiler to determine this.
-
-fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+// This test checks that non-exhaustive enums are never considered uninhabited outside their
+// defining crate, and non-exhaustive structs are considered uninhabited the same way as normal
+// ones.
+fn cannot_empty_match_on_non_exhaustive_empty_enum(x: UninhabitedEnum) -> A {
match x {} //~ ERROR non-exhaustive patterns
}
-fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+fn empty_match_on_empty_struct(x: UninhabitedStruct) -> A {
+ match x {}
}
-fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+fn empty_match_on_empty_tuple_struct(x: UninhabitedTupleStruct) -> A {
+ match x {}
}
-fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
- match x {} //~ ERROR non-exhaustive patterns
+fn empty_match_on_enum_with_empty_variants_struct(x: UninhabitedVariants) -> A {
+ match x {}
}
fn main() {}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
index 0c8b14ab69d..d6f0bc724a9 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns.stderr
@@ -1,5 +1,5 @@
error[E0004]: non-exhaustive patterns: type `UninhabitedEnum` is non-empty
- --> $DIR/match_with_exhaustive_patterns.rs:21:11
+ --> $DIR/match_with_exhaustive_patterns.rs:17:11
|
LL | match x {}
| ^
@@ -17,67 +17,6 @@ LL + _ => todo!(),
LL ~ }
|
-error[E0004]: non-exhaustive patterns: type `UninhabitedStruct` is non-empty
- --> $DIR/match_with_exhaustive_patterns.rs:25:11
- |
-LL | match x {}
- | ^
- |
-note: `UninhabitedStruct` defined here
- --> $DIR/auxiliary/uninhabited.rs:9:1
- |
-LL | pub struct UninhabitedStruct {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: the matched value is of type `UninhabitedStruct`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match x {
-LL + _ => todo!(),
-LL ~ }
- |
-
-error[E0004]: non-exhaustive patterns: type `UninhabitedTupleStruct` is non-empty
- --> $DIR/match_with_exhaustive_patterns.rs:29:11
- |
-LL | match x {}
- | ^
- |
-note: `UninhabitedTupleStruct` defined here
- --> $DIR/auxiliary/uninhabited.rs:14:1
- |
-LL | pub struct UninhabitedTupleStruct(!);
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- = note: the matched value is of type `UninhabitedTupleStruct`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
- |
-LL ~ match x {
-LL + _ => todo!(),
-LL ~ }
- |
-
-error[E0004]: non-exhaustive patterns: `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
- --> $DIR/match_with_exhaustive_patterns.rs:33:11
- |
-LL | match x {}
- | ^ patterns `UninhabitedVariants::Tuple(_)` and `UninhabitedVariants::Struct { .. }` not covered
- |
-note: `UninhabitedVariants` defined here
- --> $DIR/auxiliary/uninhabited.rs:16:1
- |
-LL | pub enum UninhabitedVariants {
- | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-LL | #[non_exhaustive] Tuple(!),
- | ----- not covered
-LL | #[non_exhaustive] Struct { x: ! }
- | ------ not covered
- = note: the matched value is of type `UninhabitedVariants`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
- |
-LL ~ match x {
-LL + UninhabitedVariants::Tuple(_) | UninhabitedVariants::Struct { .. } => todo!(),
-LL ~ }
- |
-
-error: aborting due to 4 previous errors
+error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs
index 468703c78e0..96620162212 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/match_with_exhaustive_patterns_same_crate.rs
@@ -1,5 +1,4 @@
//@ check-pass
-
#![deny(unreachable_patterns)]
#![feature(never_type)]
@@ -9,11 +8,12 @@ pub enum UninhabitedEnum {
#[non_exhaustive]
pub struct UninhabitedStruct {
- _priv: !,
+ pub never: !,
+ _priv: (),
}
#[non_exhaustive]
-pub struct UninhabitedTupleStruct(!);
+pub struct UninhabitedTupleStruct(pub !);
pub enum UninhabitedVariants {
#[non_exhaustive] Tuple(!),
@@ -22,24 +22,21 @@ pub enum UninhabitedVariants {
struct A;
-// This test checks that an empty match on a non-exhaustive uninhabited type from the defining crate
-// will compile. In particular, this enables the `exhaustive_patterns` feature as this can
-// change the branch used in the compiler to determine this.
-// Codegen is skipped because tests with long names can cause issues on Windows CI, see #60648.
-
-fn cannot_empty_match_on_empty_enum_to_anything(x: UninhabitedEnum) -> A {
+// This checks that `non_exhaustive` annotations do not affect exhaustiveness checking within the
+// defining crate.
+fn empty_match_on_empty_enum(x: UninhabitedEnum) -> A {
match x {}
}
-fn cannot_empty_match_on_empty_struct_to_anything(x: UninhabitedStruct) -> A {
+fn empty_match_on_empty_struct(x: UninhabitedStruct) -> A {
match x {}
}
-fn cannot_empty_match_on_empty_tuple_struct_to_anything(x: UninhabitedTupleStruct) -> A {
+fn empty_match_on_empty_tuple_struct(x: UninhabitedTupleStruct) -> A {
match x {}
}
-fn cannot_empty_match_on_enum_with_empty_variants_struct_to_anything(x: UninhabitedVariants) -> A {
+fn empty_match_on_enum_with_empty_variants_struct(x: UninhabitedVariants) -> A {
match x {}
}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs
index be55ad51578..edc588777eb 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.rs
@@ -1,14 +1,10 @@
//@ aux-build:uninhabited.rs
-//@ build-pass (FIXME(62277): could be check-pass?)
#![deny(unreachable_patterns)]
extern crate uninhabited;
use uninhabited::{
- PartiallyInhabitedVariants,
- UninhabitedEnum,
- UninhabitedStruct,
- UninhabitedTupleStruct,
+ PartiallyInhabitedVariants, UninhabitedEnum, UninhabitedStruct, UninhabitedTupleStruct,
UninhabitedVariants,
};
@@ -32,27 +28,26 @@ fn uninhabited_tuple_struct() -> Option {
None
}
-// This test checks that non-exhaustive types that would normally be considered uninhabited within
-// the defining crate are not considered uninhabited from extern crates.
-
+// This test checks that non-exhaustive enums are never considered uninhabited outside their
+// defining crate, and non-exhaustive structs are considered uninhabited the same way as normal
+// ones.
fn main() {
match uninhabited_enum() {
- Some(_x) => (), // This line would normally error.
+ Some(_x) => (), // This would error without `non_exhaustive`
None => (),
}
match uninhabited_variant() {
- Some(_x) => (), // This line would normally error.
+ Some(_x) => (), //~ ERROR unreachable
None => (),
}
// This line would normally error.
- while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() {
+ while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() {} //~ ERROR unreachable
+
+ while let Some(_x) = uninhabited_struct() { //~ ERROR unreachable
}
- while let Some(_x) = uninhabited_struct() { // This line would normally error.
- }
-
- while let Some(_x) = uninhabited_tuple_struct() { // This line would normally error.
+ while let Some(_x) = uninhabited_tuple_struct() { //~ ERROR unreachable
}
}
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr
new file mode 100644
index 00000000000..deaa2ffd927
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns.stderr
@@ -0,0 +1,39 @@
+error: unreachable pattern
+ --> $DIR/patterns.rs:41:9
+ |
+LL | Some(_x) => (),
+ | ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited
+ |
+ = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
+note: the lint level is defined here
+ --> $DIR/patterns.rs:2:9
+ |
+LL | #![deny(unreachable_patterns)]
+ | ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+ --> $DIR/patterns.rs:46:15
+ |
+LL | while let PartiallyInhabitedVariants::Struct { x, .. } = partially_inhabited_variant() {}
+ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `!` is uninhabited
+ |
+ = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
+
+error: unreachable pattern
+ --> $DIR/patterns.rs:48:15
+ |
+LL | while let Some(_x) = uninhabited_struct() {
+ | ^^^^^^^^ matches no values because `UninhabitedStruct` is uninhabited
+ |
+ = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
+
+error: unreachable pattern
+ --> $DIR/patterns.rs:51:15
+ |
+LL | while let Some(_x) = uninhabited_tuple_struct() {
+ | ^^^^^^^^ matches no values because `UninhabitedTupleStruct` is uninhabited
+ |
+ = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs
index 1194d7b858d..58cced3d23d 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.rs
@@ -6,11 +6,12 @@ pub enum UninhabitedEnum {
}
#[non_exhaustive]
-pub struct UninhabitedTupleStruct(!);
+pub struct UninhabitedTupleStruct(pub !);
#[non_exhaustive]
pub struct UninhabitedStruct {
- _priv: !,
+ pub never: !,
+ _priv: (),
}
pub enum UninhabitedVariants {
diff --git a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
index 7e7dc802e7f..38524bf5b95 100644
--- a/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
+++ b/tests/ui/rfcs/rfc-2008-non-exhaustive/uninhabited/patterns_same_crate.stderr
@@ -1,5 +1,5 @@
error: unreachable pattern
- --> $DIR/patterns_same_crate.rs:51:9
+ --> $DIR/patterns_same_crate.rs:52:9
|
LL | Some(_x) => (),
| ^^^^^^^^ matches no values because `UninhabitedEnum` is uninhabited
@@ -12,7 +12,7 @@ LL | #![deny(unreachable_patterns)]
| ^^^^^^^^^^^^^^^^^^^^
error: unreachable pattern
- --> $DIR/patterns_same_crate.rs:56:9
+ --> $DIR/patterns_same_crate.rs:57:9
|
LL | Some(_x) => (),
| ^^^^^^^^ matches no values because `UninhabitedVariants` is uninhabited
@@ -20,7 +20,7 @@ LL | Some(_x) => (),
= note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
error: unreachable pattern
- --> $DIR/patterns_same_crate.rs:60:15
+ --> $DIR/patterns_same_crate.rs:61:15
|
LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabited_variant() {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ matches no values because `!` is uninhabited
@@ -28,7 +28,7 @@ LL | while let PartiallyInhabitedVariants::Struct { x } = partially_inhabite
= note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
error: unreachable pattern
- --> $DIR/patterns_same_crate.rs:64:15
+ --> $DIR/patterns_same_crate.rs:65:15
|
LL | while let Some(_x) = uninhabited_struct() {
| ^^^^^^^^ matches no values because `UninhabitedStruct` is uninhabited
@@ -36,7 +36,7 @@ LL | while let Some(_x) = uninhabited_struct() {
= note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
error: unreachable pattern
- --> $DIR/patterns_same_crate.rs:67:15
+ --> $DIR/patterns_same_crate.rs:68:15
|
LL | while let Some(_x) = uninhabited_tuple_struct() {
| ^^^^^^^^ matches no values because `UninhabitedTupleStruct` is uninhabited
diff --git a/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.rs b/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.rs
new file mode 100644
index 00000000000..a83141f0e4e
--- /dev/null
+++ b/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.rs
@@ -0,0 +1,34 @@
+fn main() {
+ let a = ["_"; unsafe { break; 1 + 2 }];
+ //~^ ERROR `break` outside of a loop or labeled block
+
+ unsafe {
+ {
+ //~^ HELP consider labeling this block to be able to break within it
+ break;
+ //~^ ERROR `break` outside of a loop or labeled block
+ }
+ }
+
+ unsafe {
+ break;
+ //~^ ERROR `break` outside of a loop or labeled block
+ }
+
+ {
+ //~^ HELP consider labeling this block to be able to break within it
+ unsafe {
+ break;
+ //~^ ERROR `break` outside of a loop or labeled block
+ }
+ }
+
+ while 2 > 1 {
+ unsafe {
+ if true || false {
+ break;
+ }
+ }
+ }
+
+}
diff --git a/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.stderr b/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.stderr
new file mode 100644
index 00000000000..b7cbe1a5cf4
--- /dev/null
+++ b/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.stderr
@@ -0,0 +1,42 @@
+error[E0268]: `break` outside of a loop or labeled block
+ --> $DIR/break-inside-unsafe-block-issue-128604.rs:2:28
+ |
+LL | let a = ["_"; unsafe { break; 1 + 2 }];
+ | ^^^^^ cannot `break` outside of a loop or labeled block
+
+error[E0268]: `break` outside of a loop or labeled block
+ --> $DIR/break-inside-unsafe-block-issue-128604.rs:14:9
+ |
+LL | break;
+ | ^^^^^ cannot `break` outside of a loop or labeled block
+
+error[E0268]: `break` outside of a loop or labeled block
+ --> $DIR/break-inside-unsafe-block-issue-128604.rs:8:13
+ |
+LL | break;
+ | ^^^^^ cannot `break` outside of a loop or labeled block
+ |
+help: consider labeling this block to be able to break within it
+ |
+LL ~ 'block: {
+LL |
+LL ~ break 'block;
+ |
+
+error[E0268]: `break` outside of a loop or labeled block
+ --> $DIR/break-inside-unsafe-block-issue-128604.rs:21:13
+ |
+LL | break;
+ | ^^^^^ cannot `break` outside of a loop or labeled block
+ |
+help: consider labeling this block to be able to break within it
+ |
+LL ~ 'block: {
+LL |
+LL | unsafe {
+LL ~ break 'block;
+ |
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0268`.