>,
patch: MirPatch<'tcx>,
}
-impl<'b, 'mir, 'tcx> ElaborateDropsCtxt<'b, 'mir, 'tcx> {
- fn move_data(&self) -> &'b MoveData<'tcx> {
+impl fmt::Debug for ElaborateDropsCtxt<'_, '_> {
+ fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ Ok(())
+ }
+}
+
+impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
+ fn move_data(&self) -> &'a MoveData<'tcx> {
&self.env.move_data
}
@@ -370,15 +366,7 @@ impl<'b, 'mir, 'tcx> ElaborateDropsCtxt<'b, 'mir, 'tcx> {
}
};
self.init_data.seek_before(self.body.terminator_loc(bb));
- elaborate_drop(
- &mut Elaborator { ctxt: self },
- terminator.source_info,
- place,
- path,
- target,
- unwind,
- bb,
- )
+ elaborate_drop(self, terminator.source_info, place, path, target, unwind, bb)
}
LookupResult::Parent(None) => {}
LookupResult::Parent(Some(_)) => {
diff --git a/compiler/rustc_mir_transform/src/errors.rs b/compiler/rustc_mir_transform/src/errors.rs
index 2703dc57cdad..9a93c3a72b1c 100644
--- a/compiler/rustc_mir_transform/src/errors.rs
+++ b/compiler/rustc_mir_transform/src/errors.rs
@@ -64,7 +64,7 @@ impl<'a, P: std::fmt::Debug> LintDiagnostic<'a, ()> for AssertLint {
}
impl AssertLintKind {
- pub fn lint(&self) -> &'static Lint {
+ pub(crate) fn lint(&self) -> &'static Lint {
match self {
AssertLintKind::ArithmeticOverflow => lint::builtin::ARITHMETIC_OVERFLOW,
AssertLintKind::UnconditionalPanic => lint::builtin::UNCONDITIONAL_PANIC,
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 199fd0f10ee2..0efaa172e0c6 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -11,7 +11,7 @@ use rustc_target::spec::abi::Abi;
use crate::errors;
-pub struct FunctionItemReferences;
+pub(super) struct FunctionItemReferences;
impl<'tcx> crate::MirLint<'tcx> for FunctionItemReferences {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index df0fcc42e592..e5d2b13efd8f 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -109,7 +109,7 @@ use tracing::{debug, instrument, trace};
use crate::ssa::{AssignedValue, SsaLocals};
-pub struct GVN;
+pub(super) struct GVN;
impl<'tcx> crate::MirPass<'tcx> for GVN {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 6cc7e0ee1e4b..03ef808efecb 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -32,9 +32,11 @@ pub(crate) mod cycle;
const TOP_DOWN_DEPTH_LIMIT: usize = 5;
+// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
+// by custom rustc drivers, running all the steps by themselves. See #114628.
pub struct Inline;
-#[derive(Copy, Clone, Debug)]
+#[derive(Clone, Debug)]
struct CallSite<'tcx> {
callee: Instance<'tcx>,
fn_sig: ty::PolyFnSig<'tcx>,
@@ -156,7 +158,6 @@ impl<'tcx> Inliner<'tcx> {
match self.try_inlining(caller_body, &callsite) {
Err(reason) => {
debug!("not-inlined {} [{}]", callsite.callee, reason);
- continue;
}
Ok(new_blocks) => {
debug!("inlined {}", callsite.callee);
@@ -638,7 +639,7 @@ impl<'tcx> Inliner<'tcx> {
);
let dest_ty = dest.ty(caller_body, self.tcx);
let temp =
- Place::from(self.new_call_temp(caller_body, &callsite, dest_ty, return_block));
+ Place::from(self.new_call_temp(caller_body, callsite, dest_ty, return_block));
caller_body[callsite.block].statements.push(Statement {
source_info: callsite.source_info,
kind: StatementKind::Assign(Box::new((temp, dest))),
@@ -657,7 +658,7 @@ impl<'tcx> Inliner<'tcx> {
true,
self.new_call_temp(
caller_body,
- &callsite,
+ callsite,
destination.ty(caller_body, self.tcx).ty,
return_block,
),
@@ -665,7 +666,7 @@ impl<'tcx> Inliner<'tcx> {
};
// Copy the arguments if needed.
- let args = self.make_call_args(args, &callsite, caller_body, &callee_body, return_block);
+ let args = self.make_call_args(args, callsite, caller_body, &callee_body, return_block);
let mut integrator = Integrator {
args: &args,
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 4fbfa744e673..a9591bf39848 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -13,13 +13,13 @@ use rustc_target::spec::abi::Abi;
use crate::simplify::simplify_duplicate_switch_targets;
use crate::take_array;
-pub enum InstSimplify {
+pub(super) enum InstSimplify {
BeforeInline,
AfterSimplifyCfg,
}
impl InstSimplify {
- pub fn name(&self) -> &'static str {
+ fn name(&self) -> &'static str {
match self {
InstSimplify::BeforeInline => "InstSimplify-before-inline",
InstSimplify::AfterSimplifyCfg => "InstSimplify-after-simplifycfg",
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index 02dd56e1b4fd..e950c2cb72ab 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -55,7 +55,7 @@ use tracing::{debug, instrument, trace};
use crate::cost_checker::CostChecker;
-pub struct JumpThreading;
+pub(super) struct JumpThreading;
const MAX_BACKTRACK: usize = 5;
const MAX_COST: usize = 100;
diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs
index 61405fb25c6f..e964310c5429 100644
--- a/compiler/rustc_mir_transform/src/known_panics_lint.rs
+++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs
@@ -26,7 +26,7 @@ use tracing::{debug, instrument, trace};
use crate::errors::{AssertLint, AssertLintKind};
-pub struct KnownPanicsLint;
+pub(super) struct KnownPanicsLint;
impl<'tcx> crate::MirLint<'tcx> for KnownPanicsLint {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
@@ -852,7 +852,7 @@ const MAX_ALLOC_LIMIT: u64 = 1024;
/// The mode that `ConstProp` is allowed to run in for a given `Local`.
#[derive(Clone, Copy, Debug, PartialEq)]
-pub enum ConstPropMode {
+enum ConstPropMode {
/// The `Local` can be propagated into and reads of this `Local` can also be propagated.
FullConstProp,
/// The `Local` can only be propagated into and from its own block.
@@ -864,7 +864,7 @@ pub enum ConstPropMode {
/// A visitor that determines locals in a MIR body
/// that can be const propagated
-pub struct CanConstProp {
+struct CanConstProp {
can_const_prop: IndexVec,
// False at the beginning. Once set, no more assignments are allowed to that local.
found_assignment: BitSet,
@@ -872,7 +872,7 @@ pub struct CanConstProp {
impl CanConstProp {
/// Returns true if `local` can be propagated
- pub fn check<'tcx>(
+ fn check<'tcx>(
tcx: TyCtxt<'tcx>,
param_env: ParamEnv<'tcx>,
body: &Body<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index f02ba71ddc64..f61cf236f77c 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -23,7 +23,7 @@ use rustc_target::abi::{HasDataLayout, Size, TagEncoding, Variants};
/// In summary, what this does is at runtime determine which enum variant is active,
/// and instead of copying all the bytes of the largest possible variant,
/// copy only the bytes for the currently active variant.
-pub struct EnumSizeOpt {
+pub(super) struct EnumSizeOpt {
pub(crate) discrepancy: u64,
}
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 62e73ba2c8e2..0bbbf047f634 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -11,6 +11,7 @@
#![feature(round_char_boundary)]
#![feature(try_blocks)]
#![feature(yeet_expr)]
+#![warn(unreachable_pub)]
// tidy-alphabetical-end
use hir::ConstContext;
@@ -72,6 +73,8 @@ mod errors;
mod ffi_unwind_calls;
mod function_item_references;
mod gvn;
+// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
+// by custom rustc drivers, running all the steps by themselves. See #114628.
pub mod inline;
mod instsimplify;
mod jump_threading;
@@ -459,8 +462,8 @@ fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &
tcx.alloc_steal_mir(body)
}
-// Made public such that `mir_drops_elaborated_and_const_checked` can be overridden
-// by custom rustc drivers, running all the steps by themselves.
+// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
+// by custom rustc drivers, running all the steps by themselves. See #114628.
pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
assert!(body.phase == MirPhase::Analysis(AnalysisPhase::Initial));
let did = body.source.def_id();
diff --git a/compiler/rustc_mir_transform/src/lint.rs b/compiler/rustc_mir_transform/src/lint.rs
index 746068064b8f..23733994a8b4 100644
--- a/compiler/rustc_mir_transform/src/lint.rs
+++ b/compiler/rustc_mir_transform/src/lint.rs
@@ -13,7 +13,7 @@ use rustc_mir_dataflow::impls::{MaybeStorageDead, MaybeStorageLive};
use rustc_mir_dataflow::storage::always_storage_live_locals;
use rustc_mir_dataflow::{Analysis, ResultsCursor};
-pub fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
+pub(super) fn lint_body<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, when: String) {
let always_live_locals = &always_storage_live_locals(body);
let maybe_storage_live = MaybeStorageLive::new(Cow::Borrowed(always_live_locals))
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 55eec3323061..6d635606687a 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -7,7 +7,7 @@ use rustc_span::symbol::sym;
use crate::take_array;
-pub struct LowerIntrinsics;
+pub(super) struct LowerIntrinsics;
impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -35,20 +35,19 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
terminator.kind = TerminatorKind::Goto { target };
}
sym::forget => {
- if let Some(target) = *target {
- block.statements.push(Statement {
- source_info: terminator.source_info,
- kind: StatementKind::Assign(Box::new((
- *destination,
- Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
- span: terminator.source_info.span,
- user_ty: None,
- const_: Const::zero_sized(tcx.types.unit),
- }))),
- ))),
- });
- terminator.kind = TerminatorKind::Goto { target };
- }
+ let target = target.unwrap();
+ block.statements.push(Statement {
+ source_info: terminator.source_info,
+ kind: StatementKind::Assign(Box::new((
+ *destination,
+ Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
+ span: terminator.source_info.span,
+ user_ty: None,
+ const_: Const::zero_sized(tcx.types.unit),
+ }))),
+ ))),
+ });
+ terminator.kind = TerminatorKind::Goto { target };
}
sym::copy_nonoverlapping => {
let target = target.unwrap();
@@ -121,43 +120,41 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
terminator.kind = TerminatorKind::Goto { target };
}
sym::add_with_overflow | sym::sub_with_overflow | sym::mul_with_overflow => {
- if let Some(target) = *target {
- let Ok([lhs, rhs]) = take_array(args) else {
- bug!("Wrong arguments for {} intrinsic", intrinsic.name);
- };
- let bin_op = match intrinsic.name {
- sym::add_with_overflow => BinOp::AddWithOverflow,
- sym::sub_with_overflow => BinOp::SubWithOverflow,
- sym::mul_with_overflow => BinOp::MulWithOverflow,
- _ => bug!("unexpected intrinsic"),
- };
- block.statements.push(Statement {
- source_info: terminator.source_info,
- kind: StatementKind::Assign(Box::new((
- *destination,
- Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
- ))),
- });
- terminator.kind = TerminatorKind::Goto { target };
- }
+ let target = target.unwrap();
+ let Ok([lhs, rhs]) = take_array(args) else {
+ bug!("Wrong arguments for {} intrinsic", intrinsic.name);
+ };
+ let bin_op = match intrinsic.name {
+ sym::add_with_overflow => BinOp::AddWithOverflow,
+ sym::sub_with_overflow => BinOp::SubWithOverflow,
+ sym::mul_with_overflow => BinOp::MulWithOverflow,
+ _ => bug!("unexpected intrinsic"),
+ };
+ block.statements.push(Statement {
+ source_info: terminator.source_info,
+ kind: StatementKind::Assign(Box::new((
+ *destination,
+ Rvalue::BinaryOp(bin_op, Box::new((lhs.node, rhs.node))),
+ ))),
+ });
+ terminator.kind = TerminatorKind::Goto { target };
}
sym::size_of | sym::min_align_of => {
- if let Some(target) = *target {
- let tp_ty = generic_args.type_at(0);
- let null_op = match intrinsic.name {
- sym::size_of => NullOp::SizeOf,
- sym::min_align_of => NullOp::AlignOf,
- _ => bug!("unexpected intrinsic"),
- };
- block.statements.push(Statement {
- source_info: terminator.source_info,
- kind: StatementKind::Assign(Box::new((
- *destination,
- Rvalue::NullaryOp(null_op, tp_ty),
- ))),
- });
- terminator.kind = TerminatorKind::Goto { target };
- }
+ let target = target.unwrap();
+ let tp_ty = generic_args.type_at(0);
+ let null_op = match intrinsic.name {
+ sym::size_of => NullOp::SizeOf,
+ sym::min_align_of => NullOp::AlignOf,
+ _ => bug!("unexpected intrinsic"),
+ };
+ block.statements.push(Statement {
+ source_info: terminator.source_info,
+ kind: StatementKind::Assign(Box::new((
+ *destination,
+ Rvalue::NullaryOp(null_op, tp_ty),
+ ))),
+ });
+ terminator.kind = TerminatorKind::Goto { target };
}
sym::read_via_copy => {
let Ok([arg]) = take_array(args) else {
@@ -219,17 +216,23 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
terminator.kind = TerminatorKind::Goto { target };
}
sym::discriminant_value => {
- if let (Some(target), Some(arg)) = (*target, args[0].node.place()) {
- let arg = tcx.mk_place_deref(arg);
- block.statements.push(Statement {
- source_info: terminator.source_info,
- kind: StatementKind::Assign(Box::new((
- *destination,
- Rvalue::Discriminant(arg),
- ))),
- });
- terminator.kind = TerminatorKind::Goto { target };
- }
+ let target = target.unwrap();
+ let Ok([arg]) = take_array(args) else {
+ span_bug!(
+ terminator.source_info.span,
+ "Wrong arguments for discriminant_value intrinsic"
+ );
+ };
+ let arg = arg.node.place().unwrap();
+ let arg = tcx.mk_place_deref(arg);
+ block.statements.push(Statement {
+ source_info: terminator.source_info,
+ kind: StatementKind::Assign(Box::new((
+ *destination,
+ Rvalue::Discriminant(arg),
+ ))),
+ });
+ terminator.kind = TerminatorKind::Goto { target };
}
sym::offset => {
let target = target.unwrap();
@@ -267,7 +270,6 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
Rvalue::Cast(CastKind::Transmute, arg.node, dst_ty),
))),
});
-
if let Some(target) = *target {
terminator.kind = TerminatorKind::Goto { target };
} else {
@@ -299,7 +301,6 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
Rvalue::Aggregate(Box::new(kind), fields.into()),
))),
});
-
terminator.kind = TerminatorKind::Goto { target };
}
sym::ptr_metadata => {
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index 555309a77500..ca59d4d12aca 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -5,7 +5,7 @@ use rustc_hir::def_id::DefId;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
-pub struct LowerSliceLenCalls;
+pub(super) struct LowerSliceLenCalls;
impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
@@ -17,7 +17,7 @@ impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls {
}
}
-pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
+fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let language_items = tcx.lang_items();
let Some(slice_len_fn_item_def_id) = language_items.slice_len_fn() else {
// there is no lang item to compare to :)
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 233b39fb47a4..2a2616b20a6d 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -10,7 +10,7 @@ use rustc_type_ir::TyKind::*;
use super::simplify::simplify_cfg;
-pub struct MatchBranchSimplification;
+pub(super) struct MatchBranchSimplification;
impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/mentioned_items.rs b/compiler/rustc_mir_transform/src/mentioned_items.rs
index 41ce03caf087..7f9d0a5b6985 100644
--- a/compiler/rustc_mir_transform/src/mentioned_items.rs
+++ b/compiler/rustc_mir_transform/src/mentioned_items.rs
@@ -5,7 +5,7 @@ use rustc_middle::ty::{self, TyCtxt};
use rustc_session::Session;
use rustc_span::source_map::Spanned;
-pub struct MentionedItems;
+pub(super) struct MentionedItems;
struct MentionedItemsVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
index 1b4972d487ee..b6d6ef5de1da 100644
--- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
+++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
@@ -7,7 +7,7 @@ use rustc_middle::ty::TyCtxt;
use crate::simplify;
-pub struct MultipleReturnTerminators;
+pub(super) struct MultipleReturnTerminators;
impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/nrvo.rs b/compiler/rustc_mir_transform/src/nrvo.rs
index 94573a9d89bf..98fa149e2bc7 100644
--- a/compiler/rustc_mir_transform/src/nrvo.rs
+++ b/compiler/rustc_mir_transform/src/nrvo.rs
@@ -30,7 +30,7 @@ use tracing::{debug, trace};
///
/// [#47954]: https://github.com/rust-lang/rust/pull/47954
/// [#71003]: https://github.com/rust-lang/rust/pull/71003
-pub struct RenameReturnPlace;
+pub(super) struct RenameReturnPlace;
impl<'tcx> crate::MirPass<'tcx> for RenameReturnPlace {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index 28d4e1a1c918..60ece5e7db97 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -269,12 +269,7 @@ pub(super) fn validate_body<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, when
validate::Validator { when, mir_phase: body.phase }.run_pass(tcx, body);
}
-pub(super) fn dump_mir_for_pass<'tcx>(
- tcx: TyCtxt<'tcx>,
- body: &Body<'tcx>,
- pass_name: &str,
- is_after: bool,
-) {
+fn dump_mir_for_pass<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, pass_name: &str, is_after: bool) {
mir::dump_mir(
tcx,
true,
diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs
index ad71c6226601..ef011d230c27 100644
--- a/compiler/rustc_mir_transform/src/prettify.rs
+++ b/compiler/rustc_mir_transform/src/prettify.rs
@@ -15,7 +15,7 @@ use rustc_session::Session;
///
/// Thus after this pass, all the successors of a block are later than it in the
/// `IndexVec`, unless that successor is a back-edge (such as from a loop).
-pub struct ReorderBasicBlocks;
+pub(super) struct ReorderBasicBlocks;
impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks {
fn is_enabled(&self, _session: &Session) -> bool {
@@ -43,7 +43,7 @@ impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks {
/// assigned or referenced will have a smaller number.
///
/// (Does not reorder arguments nor the [`RETURN_PLACE`].)
-pub struct ReorderLocals;
+pub(super) struct ReorderLocals;
impl<'tcx> crate::MirPass<'tcx> for ReorderLocals {
fn is_enabled(&self, _session: &Session) -> bool {
@@ -135,8 +135,8 @@ impl<'tcx> Visitor<'tcx> for LocalFinder {
}
struct LocalUpdater<'tcx> {
- pub map: IndexVec,
- pub tcx: TyCtxt<'tcx>,
+ map: IndexVec,
+ tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs
index cf0a569ffa49..65309f63d593 100644
--- a/compiler/rustc_mir_transform/src/promote_consts.rs
+++ b/compiler/rustc_mir_transform/src/promote_consts.rs
@@ -37,7 +37,7 @@ use tracing::{debug, instrument};
/// After this pass is run, `promoted_fragments` will hold the MIR body corresponding to each
/// newly created `Constant`.
#[derive(Default)]
-pub struct PromoteTemps<'tcx> {
+pub(super) struct PromoteTemps<'tcx> {
pub promoted_fragments: Cell>>,
}
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index 4a447d24ccec..25b98786c66b 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -70,7 +70,7 @@ use crate::ssa::{SsaLocals, StorageLiveLocals};
///
/// For immutable borrows, we do not need to preserve such uniqueness property,
/// so we perform all the possible instantiations without removing the `_1 = &_2` statement.
-pub struct ReferencePropagation;
+pub(super) struct ReferencePropagation;
impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
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 ccba8d015e3a..37197c3f573d 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -8,7 +8,7 @@ use tracing::debug;
/// A pass that removes noop landing pads and replaces jumps to them with
/// `UnwindAction::Continue`. This is important because otherwise LLVM generates
/// terrible code for these.
-pub struct RemoveNoopLandingPads;
+pub(super) struct RemoveNoopLandingPads;
impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs
index 5801fdedcebb..71399eb72f00 100644
--- a/compiler/rustc_mir_transform/src/remove_place_mention.rs
+++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs
@@ -4,7 +4,7 @@ use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::trace;
-pub struct RemovePlaceMention;
+pub(super) struct RemovePlaceMention;
impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
index 329b30d3890a..3ecb4a8994f5 100644
--- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs
+++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
@@ -4,7 +4,7 @@ use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::trace;
-pub struct RemoveStorageMarkers;
+pub(super) struct RemoveStorageMarkers;
impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index aafe971311d3..c58f492655a8 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -14,7 +14,7 @@ use rustc_target::abi::FieldIdx;
/// like [#90770].
///
/// [#90770]: https://github.com/rust-lang/rust/issues/90770
-pub struct RemoveUninitDrops;
+pub(super) struct RemoveUninitDrops;
impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
index 43109aae0fb6..28925ba1beb1 100644
--- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
@@ -10,7 +10,7 @@ use tracing::{debug, trace};
use super::simplify::simplify_cfg;
-pub struct RemoveUnneededDrops;
+pub(super) struct RemoveUnneededDrops;
impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index 9aa46bd4fbae..f13bb1c5993d 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -4,7 +4,7 @@ use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
-pub struct RemoveZsts;
+pub(super) struct RemoveZsts;
impl<'tcx> crate::MirPass<'tcx> for RemoveZsts {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/required_consts.rs b/compiler/rustc_mir_transform/src/required_consts.rs
index 50637e2ac03b..ebcf5b5d27b8 100644
--- a/compiler/rustc_mir_transform/src/required_consts.rs
+++ b/compiler/rustc_mir_transform/src/required_consts.rs
@@ -1,7 +1,7 @@
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{traversal, Body, ConstOperand, Location};
-pub struct RequiredConstsVisitor<'a, 'tcx> {
+pub(super) struct RequiredConstsVisitor<'a, 'tcx> {
required_consts: &'a mut Vec>,
}
@@ -10,7 +10,7 @@ impl<'a, 'tcx> RequiredConstsVisitor<'a, 'tcx> {
RequiredConstsVisitor { required_consts }
}
- pub fn compute_required_consts(body: &mut Body<'tcx>) {
+ pub(super) fn compute_required_consts(body: &mut Body<'tcx>) {
let mut required_consts = Vec::new();
let mut required_consts_visitor = RequiredConstsVisitor::new(&mut required_consts);
for (bb, bb_data) in traversal::reverse_postorder(&body) {
diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs
index 29312a99cbc0..3db962bd94ae 100644
--- a/compiler/rustc_mir_transform/src/reveal_all.rs
+++ b/compiler/rustc_mir_transform/src/reveal_all.rs
@@ -4,7 +4,7 @@ use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
-pub struct RevealAll;
+pub(super) struct RevealAll;
impl<'tcx> crate::MirPass<'tcx> for RevealAll {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 8c70e4291185..cf8ef580b272 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -26,7 +26,7 @@ use crate::{
mod async_destructor_ctor;
-pub fn provide(providers: &mut Providers) {
+pub(super) fn provide(providers: &mut Providers) {
providers.mir_shims = make_shim;
}
@@ -331,7 +331,7 @@ fn new_body<'tcx>(
body
}
-pub struct DropShimElaborator<'a, 'tcx> {
+pub(super) struct DropShimElaborator<'a, 'tcx> {
pub body: &'a Body<'tcx>,
pub patch: MirPatch<'tcx>,
pub tcx: TyCtxt<'tcx>,
@@ -913,7 +913,7 @@ fn build_call_shim<'tcx>(
body
}
-pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
+pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
debug_assert!(tcx.is_constructor(ctor_id));
let param_env = tcx.param_env_reveal_all_normalized(ctor_id);
diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
index 50810f23113f..c88953a1d1a2 100644
--- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
+++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs
@@ -23,7 +23,7 @@ use tracing::debug;
use super::{local_decls_for_sig, new_body};
-pub fn build_async_destructor_ctor_shim<'tcx>(
+pub(super) fn build_async_destructor_ctor_shim<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
ty: Option>,
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 1478b86d3c76..cb8e1dfda98b 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -35,7 +35,7 @@ use rustc_span::DUMMY_SP;
use smallvec::SmallVec;
use tracing::{debug, trace};
-pub enum SimplifyCfg {
+pub(super) enum SimplifyCfg {
Initial,
PromoteConsts,
RemoveFalseEdges,
@@ -50,7 +50,7 @@ pub enum SimplifyCfg {
}
impl SimplifyCfg {
- pub fn name(&self) -> &'static str {
+ fn name(&self) -> &'static str {
match self {
SimplifyCfg::Initial => "SimplifyCfg-initial",
SimplifyCfg::PromoteConsts => "SimplifyCfg-promote-consts",
@@ -66,7 +66,7 @@ impl SimplifyCfg {
}
}
-pub(crate) fn simplify_cfg(body: &mut Body<'_>) {
+pub(super) fn simplify_cfg(body: &mut Body<'_>) {
CfgSimplifier::new(body).simplify();
remove_dead_blocks(body);
@@ -85,13 +85,13 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg {
}
}
-pub struct CfgSimplifier<'a, 'tcx> {
+struct CfgSimplifier<'a, 'tcx> {
basic_blocks: &'a mut IndexSlice>,
pred_count: IndexVec,
}
impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
- pub fn new(body: &'a mut Body<'tcx>) -> Self {
+ fn new(body: &'a mut Body<'tcx>) -> Self {
let mut pred_count = IndexVec::from_elem(0u32, &body.basic_blocks);
// we can't use mir.predecessors() here because that counts
@@ -111,7 +111,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
CfgSimplifier { basic_blocks, pred_count }
}
- pub fn simplify(mut self) {
+ fn simplify(mut self) {
self.strip_nops();
// Vec of the blocks that should be merged. We store the indices here, instead of the
@@ -280,7 +280,7 @@ impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
}
}
-pub fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
+pub(super) fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
if let TerminatorKind::SwitchInt { targets, .. } = &mut terminator.kind {
let otherwise = targets.otherwise();
if targets.iter().any(|t| t.1 == otherwise) {
@@ -292,7 +292,7 @@ pub fn simplify_duplicate_switch_targets(terminator: &mut Terminator<'_>) {
}
}
-pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
+pub(super) fn remove_dead_blocks(body: &mut Body<'_>) {
let should_deduplicate_unreachable = |bbdata: &BasicBlockData<'_>| {
// CfgSimplifier::simplify leaves behind some unreachable basic blocks without a
// terminator. Those blocks will be deleted by remove_dead_blocks, but we run just
@@ -360,7 +360,7 @@ pub(crate) fn remove_dead_blocks(body: &mut Body<'_>) {
}
}
-pub enum SimplifyLocals {
+pub(super) enum SimplifyLocals {
BeforeConstProp,
AfterGVN,
Final,
@@ -385,7 +385,7 @@ impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
}
}
-pub fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
+pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
// First, we're going to get a count of *actual* uses for every `Local`.
let mut used_locals = UsedLocals::new(body);
@@ -397,7 +397,7 @@ pub fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
remove_unused_definitions_helper(&mut used_locals, body);
}
-pub fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
+fn simplify_locals<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>) {
// First, we're going to get a count of *actual* uses for every `Local`.
let mut used_locals = UsedLocals::new(body);
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index 5a014bb73468..e83b4727c485 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -2,10 +2,11 @@ use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::trace;
-pub enum SimplifyConstCondition {
+pub(super) enum SimplifyConstCondition {
AfterConstProp,
Final,
}
+
/// A pass that replaces a branch with a goto when its condition is known.
impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
fn name(&self) -> &'static str {
diff --git a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
index bd30ecc59b3d..644bcb58d567 100644
--- a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
+++ b/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs
@@ -23,7 +23,7 @@ use tracing::trace;
/// ```ignore (MIR)
/// switchInt(_4) -> [43i32: bb3, otherwise: bb2];
/// ```
-pub struct SimplifyComparisonIntegral;
+pub(super) struct SimplifyComparisonIntegral;
impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/single_use_consts.rs b/compiler/rustc_mir_transform/src/single_use_consts.rs
index 64a928728307..26059268c37d 100644
--- a/compiler/rustc_mir_transform/src/single_use_consts.rs
+++ b/compiler/rustc_mir_transform/src/single_use_consts.rs
@@ -19,7 +19,7 @@ use rustc_middle::ty::TyCtxt;
///
/// It also removes *never*-used constants, since it had all the information
/// needed to do that too, including updating the debug info.
-pub struct SingleUseConsts;
+pub(super) struct SingleUseConsts;
impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index 3c5ccc0c99a8..e6dd2cfd862d 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -11,7 +11,7 @@ use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields};
use rustc_target::abi::{FieldIdx, FIRST_VARIANT};
use tracing::{debug, instrument};
-pub struct ScalarReplacementOfAggregates;
+pub(super) struct ScalarReplacementOfAggregates;
impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/ssa.rs b/compiler/rustc_mir_transform/src/ssa.rs
index c1254766f0a9..cf8622cadd1f 100644
--- a/compiler/rustc_mir_transform/src/ssa.rs
+++ b/compiler/rustc_mir_transform/src/ssa.rs
@@ -16,7 +16,7 @@ use rustc_middle::mir::*;
use rustc_middle::ty::{ParamEnv, TyCtxt};
use tracing::{debug, instrument, trace};
-pub struct SsaLocals {
+pub(super) struct SsaLocals {
/// Assignments to each local. This defines whether the local is SSA.
assignments: IndexVec>,
/// We visit the body in reverse postorder, to ensure each local is assigned before it is used.
@@ -32,14 +32,18 @@ pub struct SsaLocals {
borrowed_locals: BitSet,
}
-pub enum AssignedValue<'a, 'tcx> {
+pub(super) enum AssignedValue<'a, 'tcx> {
Arg,
Rvalue(&'a mut Rvalue<'tcx>),
Terminator,
}
impl SsaLocals {
- pub fn new<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, param_env: ParamEnv<'tcx>) -> SsaLocals {
+ pub(super) fn new<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ body: &Body<'tcx>,
+ param_env: ParamEnv<'tcx>,
+ ) -> SsaLocals {
let assignment_order = Vec::with_capacity(body.local_decls.len());
let assignments = IndexVec::from_elem(Set1::Empty, &body.local_decls);
@@ -101,25 +105,25 @@ impl SsaLocals {
ssa
}
- pub fn num_locals(&self) -> usize {
+ pub(super) fn num_locals(&self) -> usize {
self.assignments.len()
}
- pub fn locals(&self) -> impl Iterator- {
+ pub(super) fn locals(&self) -> impl Iterator
- {
self.assignments.indices()
}
- pub fn is_ssa(&self, local: Local) -> bool {
+ pub(super) fn is_ssa(&self, local: Local) -> bool {
matches!(self.assignments[local], Set1::One(_))
}
/// Return the number of uses if a local that are not "Deref".
- pub fn num_direct_uses(&self, local: Local) -> u32 {
+ pub(super) fn num_direct_uses(&self, local: Local) -> u32 {
self.direct_uses[local]
}
#[inline]
- pub fn assignment_dominates(
+ pub(super) fn assignment_dominates(
&self,
dominators: &Dominators,
local: Local,
@@ -131,7 +135,7 @@ impl SsaLocals {
}
}
- pub fn assignments<'a, 'tcx>(
+ pub(super) fn assignments<'a, 'tcx>(
&'a self,
body: &'a Body<'tcx>,
) -> impl Iterator
- , Location)> + 'a {
@@ -148,7 +152,7 @@ impl SsaLocals {
})
}
- pub fn for_each_assignment_mut<'tcx>(
+ pub(super) fn for_each_assignment_mut<'tcx>(
&self,
basic_blocks: &mut IndexSlice>,
mut f: impl FnMut(Local, AssignedValue<'_, 'tcx>, Location),
@@ -194,17 +198,17 @@ impl SsaLocals {
/// _d => _a // transitively through _c
///
/// Exception: we do not see through the return place, as it cannot be instantiated.
- pub fn copy_classes(&self) -> &IndexSlice {
+ pub(super) fn copy_classes(&self) -> &IndexSlice {
&self.copy_classes
}
/// Set of SSA locals that are immutably borrowed.
- pub fn borrowed_locals(&self) -> &BitSet {
+ pub(super) fn borrowed_locals(&self) -> &BitSet {
&self.borrowed_locals
}
/// Make a property uniform on a copy equivalence class by removing elements.
- pub fn meet_copy_equivalence(&self, property: &mut BitSet) {
+ pub(super) fn meet_copy_equivalence(&self, property: &mut BitSet) {
// Consolidate to have a local iff all its copies are.
//
// `copy_classes` defines equivalence classes between locals. The `local`s that recursively
diff --git a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
index 51a322628ee6..6957394ed104 100644
--- a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs
@@ -12,7 +12,7 @@ use rustc_middle::ty::{Ty, TyCtxt};
use rustc_target::abi::{Abi, Variants};
use tracing::trace;
-pub struct UnreachableEnumBranching;
+pub(super) struct UnreachableEnumBranching;
fn get_discriminant_local(terminator: &TerminatorKind<'_>) -> Option {
if let TerminatorKind::SwitchInt { discr: Operand::Move(p), .. } = terminator {
diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index b8da86f1a8dd..c60cbae21422 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
use rustc_target::abi::Size;
-pub struct UnreachablePropagation;
+pub(super) struct UnreachablePropagation;
impl crate::MirPass<'_> for UnreachablePropagation {
fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index 69e2592e82c7..18865c73f75b 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -1,6 +1,7 @@
//! Validates the MIR to ensure that invariants are upheld.
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_hir as hir;
use rustc_hir::LangItem;
use rustc_index::bit_set::BitSet;
use rustc_index::IndexVec;
@@ -25,7 +26,7 @@ enum EdgeKind {
Normal,
}
-pub struct Validator {
+pub(super) struct Validator {
/// Describes at which point in the pipeline this validation is happening.
pub when: String,
/// The phase for which we are upholding the dialect. If the given phase forbids a specific
@@ -530,7 +531,7 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
///
/// `caller_body` is used to detect cycles in MIR inlining and MIR validation before
/// `optimized_mir` is available.
-pub fn validate_types<'tcx>(
+pub(super) fn validate_types<'tcx>(
tcx: TyCtxt<'tcx>,
mir_phase: MirPhase,
param_env: ty::ParamEnv<'tcx>,
@@ -714,7 +715,17 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
// since we may be in the process of computing this MIR in the
// first place.
let layout = if def_id == self.caller_body.source.def_id() {
- // FIXME: This is not right for async closures.
+ self.caller_body.coroutine_layout_raw()
+ } else if let Some(hir::CoroutineKind::Desugared(
+ _,
+ hir::CoroutineSource::Closure,
+ )) = self.tcx.coroutine_kind(def_id)
+ && let ty::ClosureKind::FnOnce =
+ args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap()
+ && self.caller_body.source.def_id()
+ == self.tcx.coroutine_by_move_body_def_id(def_id)
+ {
+ // Same if this is the by-move body of a coroutine-closure.
self.caller_body.coroutine_layout_raw()
} else {
self.tcx.coroutine_layout(def_id, args.as_coroutine().kind_ty())
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 8515ab45de21..093697a290c0 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -1041,8 +1041,11 @@ fn find_vtable_types_for_unsizing<'tcx>(
match (source_ty.kind(), target_ty.kind()) {
(&ty::Ref(_, a, _), &ty::Ref(_, b, _) | &ty::RawPtr(b, _))
| (&ty::RawPtr(a, _), &ty::RawPtr(b, _)) => ptr_vtable(a, b),
- (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) if def_a.is_box() && def_b.is_box() => {
- ptr_vtable(source_ty.boxed_ty(), target_ty.boxed_ty())
+ (_, _)
+ if let Some(source_boxed) = source_ty.boxed_ty()
+ && let Some(target_boxed) = target_ty.boxed_ty() =>
+ {
+ ptr_vtable(source_boxed, target_boxed)
}
// T as dyn* Trait
diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs
index b22e8e30465e..91101ddd5902 100644
--- a/compiler/rustc_monomorphize/src/lib.rs
+++ b/compiler/rustc_monomorphize/src/lib.rs
@@ -1,5 +1,7 @@
// tidy-alphabetical-start
#![feature(array_windows)]
+#![feature(if_let_guard)]
+#![feature(let_chains)]
#![warn(unreachable_pub)]
// tidy-alphabetical-end
diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
index c7a9846cd97f..17b6ec7e2bb2 100644
--- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs
@@ -3,7 +3,7 @@ mod inherent;
mod opaque_types;
mod weak_types;
-use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::{self as ty, Interner, NormalizesTo, Upcast as _};
@@ -106,6 +106,12 @@ where
if let Some(projection_pred) = assumption.as_projection_clause() {
if projection_pred.projection_def_id() == goal.predicate.def_id() {
let cx = ecx.cx();
+ if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
+ goal.predicate.alias.args,
+ projection_pred.skip_binder().projection_term.args,
+ ) {
+ return Err(NoSolution);
+ }
ecx.probe_trait_candidate(source).enter(|ecx| {
let assumption_projection_pred =
ecx.instantiate_binder_with_infer(projection_pred);
@@ -144,7 +150,7 @@ where
let goal_trait_ref = goal.predicate.alias.trait_ref(cx);
let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
- if !DeepRejectCtxt::new(ecx.cx(), TreatParams::ForLookup).args_may_unify(
+ if !DeepRejectCtxt::relate_rigid_infer(ecx.cx()).args_may_unify(
goal.predicate.alias.trait_ref(cx).args,
impl_trait_ref.skip_binder().args,
) {
diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
index 67b001d0cced..683d8dab3b2a 100644
--- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
@@ -2,7 +2,7 @@
use rustc_ast_ir::Movability;
use rustc_type_ir::data_structures::IndexSet;
-use rustc_type_ir::fast_reject::{DeepRejectCtxt, TreatParams};
+use rustc_type_ir::fast_reject::DeepRejectCtxt;
use rustc_type_ir::inherent::*;
use rustc_type_ir::lang_items::TraitSolverLangItem;
use rustc_type_ir::visit::TypeVisitableExt as _;
@@ -47,7 +47,7 @@ where
let cx = ecx.cx();
let impl_trait_ref = cx.impl_trait_ref(impl_def_id);
- if !DeepRejectCtxt::new(ecx.cx(), TreatParams::ForLookup)
+ if !DeepRejectCtxt::relate_rigid_infer(ecx.cx())
.args_may_unify(goal.predicate.trait_ref.args, impl_trait_ref.skip_binder().args)
{
return Err(NoSolution);
@@ -124,6 +124,13 @@ where
if trait_clause.def_id() == goal.predicate.def_id()
&& trait_clause.polarity() == goal.predicate.polarity
{
+ if !DeepRejectCtxt::relate_rigid_rigid(ecx.cx()).args_may_unify(
+ goal.predicate.trait_ref.args,
+ trait_clause.skip_binder().trait_ref.args,
+ ) {
+ return Err(NoSolution);
+ }
+
ecx.probe_trait_candidate(source).enter(|ecx| {
let assumption_trait_pred = ecx.instantiate_binder_with_infer(trait_clause);
ecx.eq(
diff --git a/compiler/rustc_parse/Cargo.toml b/compiler/rustc_parse/Cargo.toml
index b33896154f23..c59ae48a07d0 100644
--- a/compiler/rustc_parse/Cargo.toml
+++ b/compiler/rustc_parse/Cargo.toml
@@ -12,6 +12,7 @@ rustc_data_structures = { path = "../rustc_data_structures" }
rustc_errors = { path = "../rustc_errors" }
rustc_feature = { path = "../rustc_feature" }
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
+rustc_index = { path = "../rustc_index" }
rustc_lexer = { path = "../rustc_lexer" }
rustc_macros = { path = "../rustc_macros" }
rustc_session = { path = "../rustc_session" }
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 8e8d91ce4d03..ec9a676ea313 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -381,6 +381,7 @@ parse_invalid_char_in_escape_msg = invalid character in {$is_hex ->
*[false] unicode
} escape
+
parse_invalid_comparison_operator = invalid comparison operator `{$invalid}`
.use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}`
.spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
@@ -581,6 +582,11 @@ parse_missing_trait_in_trait_impl = missing trait in a trait impl
.suggestion_add_trait = add a trait here
.suggestion_remove_for = for an inherent impl, drop this `for`
+parse_misspelled_kw = {$is_incorrect_case ->
+ [true] write keyword `{$similar_kw}` in lowercase
+ *[false] there is a keyword `{$similar_kw}` with a similar name
+}
+
parse_modifier_lifetime = `{$modifier}` may only modify trait bounds, not lifetime bounds
.suggestion = remove the `{$modifier}`
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index f30939093c2e..b7232ff21ca0 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -13,7 +13,6 @@ use rustc_session::lint::builtin::{
};
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::parse::ParseSess;
-use rustc_span::edition::Edition;
use rustc_span::symbol::Symbol;
use rustc_span::{BytePos, Pos, Span};
use tracing::debug;
@@ -188,9 +187,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
preceded_by_whitespace = true;
continue;
}
- rustc_lexer::TokenKind::Ident => {
- self.ident(start)
- }
+ rustc_lexer::TokenKind::Ident => self.ident(start),
rustc_lexer::TokenKind::RawIdent => {
let sym = nfc_normalize(self.str_from(start + BytePos(2)));
let span = self.mk_sp(start, self.pos);
@@ -205,20 +202,31 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
self.report_unknown_prefix(start);
self.ident(start)
}
- rustc_lexer::TokenKind::InvalidIdent
- | rustc_lexer::TokenKind::InvalidPrefix
+ rustc_lexer::TokenKind::UnknownPrefixLifetime => {
+ self.report_unknown_prefix(start);
+ // Include the leading `'` in the real identifier, for macro
+ // expansion purposes. See #12512 for the gory details of why
+ // this is necessary.
+ let lifetime_name = self.str_from(start);
+ self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
+ let ident = Symbol::intern(lifetime_name);
+ token::Lifetime(ident, IdentIsRaw::No)
+ }
+ rustc_lexer::TokenKind::InvalidIdent | rustc_lexer::TokenKind::InvalidPrefix
// Do not recover an identifier with emoji if the codepoint is a confusable
// with a recoverable substitution token, like `➖`.
- if !UNICODE_ARRAY
- .iter()
- .any(|&(c, _, _)| {
- let sym = self.str_from(start);
- sym.chars().count() == 1 && c == sym.chars().next().unwrap()
- }) =>
+ if !UNICODE_ARRAY.iter().any(|&(c, _, _)| {
+ let sym = self.str_from(start);
+ sym.chars().count() == 1 && c == sym.chars().next().unwrap()
+ }) =>
{
let sym = nfc_normalize(self.str_from(start));
let span = self.mk_sp(start, self.pos);
- self.psess.bad_unicode_identifiers.borrow_mut().entry(sym).or_default()
+ self.psess
+ .bad_unicode_identifiers
+ .borrow_mut()
+ .entry(sym)
+ .or_default()
.push(span);
token::Ident(sym, IdentIsRaw::No)
}
@@ -249,9 +257,9 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
let suffix = if suffix_start < self.pos {
let string = self.str_from(suffix_start);
if string == "_" {
- self
- .dcx()
- .emit_err(errors::UnderscoreLiteralSuffix { span: self.mk_sp(suffix_start, self.pos) });
+ self.dcx().emit_err(errors::UnderscoreLiteralSuffix {
+ span: self.mk_sp(suffix_start, self.pos),
+ });
None
} else {
Some(Symbol::intern(string))
@@ -269,12 +277,47 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
if starts_with_number {
let span = self.mk_sp(start, self.pos);
- self.dcx().struct_err("lifetimes cannot start with a number")
+ self.dcx()
+ .struct_err("lifetimes cannot start with a number")
.with_span(span)
.stash(span, StashKey::LifetimeIsChar);
}
let ident = Symbol::intern(lifetime_name);
- token::Lifetime(ident)
+ token::Lifetime(ident, IdentIsRaw::No)
+ }
+ rustc_lexer::TokenKind::RawLifetime => {
+ self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1)));
+
+ let ident_start = start + BytePos(3);
+ let prefix_span = self.mk_sp(start, ident_start);
+
+ if prefix_span.at_least_rust_2021() {
+ let lifetime_name_without_tick = self.str_from(ident_start);
+ // Put the `'` back onto the lifetime name.
+ let mut lifetime_name = String::with_capacity(lifetime_name_without_tick.len() + 1);
+ lifetime_name.push('\'');
+ lifetime_name += lifetime_name_without_tick;
+ let sym = Symbol::intern(&lifetime_name);
+
+ token::Lifetime(sym, IdentIsRaw::Yes)
+ } else {
+ // Otherwise, this should be parsed like `'r`. Warn about it though.
+ self.psess.buffer_lint(
+ RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX,
+ prefix_span,
+ ast::CRATE_NODE_ID,
+ BuiltinLintDiag::RawPrefix(prefix_span),
+ );
+
+ // Reset the state so we just lex the `'r`.
+ let lt_start = start + BytePos(2);
+ self.pos = lt_start;
+ self.cursor = Cursor::new(&str_before[2 as usize..]);
+
+ let lifetime_name = self.str_from(start);
+ let ident = Symbol::intern(lifetime_name);
+ token::Lifetime(ident, IdentIsRaw::No)
+ }
}
rustc_lexer::TokenKind::Semi => token::Semi,
rustc_lexer::TokenKind::Comma => token::Comma,
@@ -331,16 +374,19 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
// first remove compound tokens like `<<` from `rustc_lexer`, and then add
// fancier error recovery to it, as there will be less overall work to do this
// way.
- let (token, sugg) = unicode_chars::check_for_substitution(self, start, c, repeats+1);
+ let (token, sugg) =
+ unicode_chars::check_for_substitution(self, start, c, repeats + 1);
self.dcx().emit_err(errors::UnknownTokenStart {
span: self.mk_sp(start, self.pos + Pos::from_usize(repeats * c.len_utf8())),
escaped: escaped_char(c),
sugg,
- null: if c == '\x00' {Some(errors::UnknownTokenNull)} else {None},
+ null: if c == '\x00' { Some(errors::UnknownTokenNull) } else { None },
repeat: if repeats > 0 {
swallow_next_invalid = repeats;
Some(errors::UnknownTokenRepeat { repeats })
- } else {None}
+ } else {
+ None
+ },
});
if let Some(token) = token {
@@ -699,7 +745,7 @@ impl<'psess, 'src> StringReader<'psess, 'src> {
let expn_data = prefix_span.ctxt().outer_expn_data();
- if expn_data.edition >= Edition::Edition2021 {
+ if expn_data.edition.at_least_rust_2021() {
// In Rust 2021, this is a hard error.
let sugg = if prefix == "rb" {
Some(errors::UnknownPrefixSugg::UseBr(prefix_span))
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 49df2811d525..205cca830b2e 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -1,3 +1,4 @@
+use std::borrow::Cow;
use std::{iter, mem};
use rustc_ast::token::{Delimiter, Token, TokenKind};
@@ -6,6 +7,7 @@ use rustc_ast::tokenstream::{
Spacing, ToAttrTokenStream,
};
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, HasTokens};
+use rustc_data_structures::fx::FxHashSet;
use rustc_errors::PResult;
use rustc_session::parse::ParseSess;
use rustc_span::{sym, Span, DUMMY_SP};
@@ -134,9 +136,8 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
node_replacements.array_windows()
{
assert!(
- node_range.0.end <= next_node_range.0.start
- || node_range.0.end >= next_node_range.0.end,
- "Node ranges should be disjoint or nested: ({:?}, {:?}) ({:?}, {:?})",
+ node_range.0.end <= next_node_range.0.start,
+ "Node ranges should be disjoint: ({:?}, {:?}) ({:?}, {:?})",
node_range,
tokens,
next_node_range,
@@ -144,20 +145,8 @@ impl ToAttrTokenStream for LazyAttrTokenStreamImpl {
);
}
- // Process the replace ranges, starting from the highest start
- // position and working our way back. If have tokens like:
- //
- // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
- //
- // Then we will generate replace ranges for both
- // the `#[cfg(FALSE)] field: bool` and the entire
- // `#[cfg(FALSE)] struct Foo { #[cfg(FALSE)] field: bool }`
- //
- // By starting processing from the replace range with the greatest
- // start position, we ensure that any (outer) replace range which
- // encloses another (inner) replace range will fully overwrite the
- // inner range's replacement.
- for (node_range, target) in node_replacements.into_iter().rev() {
+ // Process the replace ranges.
+ for (node_range, target) in node_replacements.into_iter() {
assert!(
!node_range.0.is_empty(),
"Cannot replace an empty node range: {:?}",
@@ -234,6 +223,8 @@ impl<'a> Parser<'a> {
force_collect: ForceCollect,
f: impl FnOnce(&mut Self, AttrVec) -> PResult<'a, (R, Trailing, UsePreAttrPos)>,
) -> PResult<'a, R> {
+ let possible_capture_mode = self.capture_cfg;
+
// We must collect if anything could observe the collected tokens, i.e.
// if any of the following conditions hold.
// - We are force collecting tokens (because force collection requires
@@ -244,9 +235,9 @@ impl<'a> Parser<'a> {
// - Our target supports custom inner attributes (custom
// inner attribute invocation might require token capturing).
|| R::SUPPORTS_CUSTOM_INNER_ATTRS
- // - We are in `capture_cfg` mode (which requires tokens if
+ // - We are in "possible capture mode" (which requires tokens if
// the parsed node has `#[cfg]` or `#[cfg_attr]` attributes).
- || self.capture_cfg;
+ || possible_capture_mode;
if !needs_collection {
return Ok(f(self, attrs.attrs)?.0);
}
@@ -267,18 +258,48 @@ impl<'a> Parser<'a> {
res?
};
- // When we're not in `capture_cfg` mode, then skip collecting and
- // return early if either of the following conditions hold.
// - `None`: Our target doesn't support tokens at all (e.g. `NtIdent`).
+ // - `Some(None)`: Our target supports tokens and has none.
// - `Some(Some(_))`: Our target already has tokens set (e.g. we've
- // parsed something like `#[my_attr] $item`). The actual parsing code
- // takes care of prepending any attributes to the nonterminal, so we
- // don't need to modify the already captured tokens.
+ // parsed something like `#[my_attr] $item`).
+ let ret_can_hold_tokens = matches!(ret.tokens_mut(), Some(None));
+
+ // Ignore any attributes we've previously processed. This happens when
+ // an inner call to `collect_tokens` returns an AST node and then an
+ // outer call ends up with the same AST node without any additional
+ // wrapping layer.
+ let mut seen_indices = FxHashSet::default();
+ for (i, attr) in ret.attrs().iter().enumerate() {
+ let is_unseen = self.capture_state.seen_attrs.insert(attr.id);
+ if !is_unseen {
+ seen_indices.insert(i);
+ }
+ }
+ let ret_attrs: Cow<'_, [Attribute]> =
+ if seen_indices.is_empty() {
+ Cow::Borrowed(ret.attrs())
+ } else {
+ let ret_attrs =
+ ret.attrs()
+ .iter()
+ .enumerate()
+ .filter_map(|(i, attr)| {
+ if seen_indices.contains(&i) { None } else { Some(attr.clone()) }
+ })
+ .collect();
+ Cow::Owned(ret_attrs)
+ };
+
+ // When we're not in "definite capture mode", then skip collecting and
+ // return early if `ret` doesn't support tokens or already has some.
//
// Note that this check is independent of `force_collect`. There's no
// need to collect tokens when we don't support tokens or already have
// tokens.
- if !self.capture_cfg && matches!(ret.tokens_mut(), None | Some(Some(_))) {
+ let definite_capture_mode = self.capture_cfg
+ && matches!(self.capture_state.capturing, Capturing::Yes)
+ && has_cfg_or_cfg_attr(&ret_attrs);
+ if !definite_capture_mode && !ret_can_hold_tokens {
return Ok(ret);
}
@@ -297,12 +318,12 @@ impl<'a> Parser<'a> {
// outer and inner attributes. So this check is more precise than
// the earlier `needs_tokens` check, and we don't need to
// check `R::SUPPORTS_CUSTOM_INNER_ATTRS`.)
- || needs_tokens(ret.attrs())
- // - We are in `capture_cfg` mode and there are `#[cfg]` or
- // `#[cfg_attr]` attributes. (During normal non-`capture_cfg`
- // parsing, we don't need any special capturing for those
- // attributes, because they're builtin.)
- || (self.capture_cfg && has_cfg_or_cfg_attr(ret.attrs()));
+ || needs_tokens(&ret_attrs)
+ // - We are in "definite capture mode", which requires that there
+ // are `#[cfg]` or `#[cfg_attr]` attributes. (During normal
+ // non-`capture_cfg` parsing, we don't need any special capturing
+ // for those attributes, because they're builtin.)
+ || definite_capture_mode;
if !needs_collection {
return Ok(ret);
}
@@ -336,7 +357,7 @@ impl<'a> Parser<'a> {
// `Parser::parse_inner_attributes`, and pair them in a `ParserReplacement` with `None`,
// which means the relevant tokens will be removed. (More details below.)
let mut inner_attr_parser_replacements = Vec::new();
- for attr in ret.attrs() {
+ for attr in ret_attrs.iter() {
if attr.style == ast::AttrStyle::Inner {
if let Some(inner_attr_parser_range) =
self.capture_state.inner_attr_parser_ranges.remove(&attr.id)
@@ -359,11 +380,10 @@ impl<'a> Parser<'a> {
// from `ParserRange` form to `NodeRange` form. We will perform the actual
// replacement only when we convert the `LazyAttrTokenStream` to an
// `AttrTokenStream`.
- self.capture_state.parser_replacements
- [parser_replacements_start..parser_replacements_end]
- .iter()
- .cloned()
- .chain(inner_attr_parser_replacements.iter().cloned())
+ self.capture_state
+ .parser_replacements
+ .drain(parser_replacements_start..parser_replacements_end)
+ .chain(inner_attr_parser_replacements.into_iter())
.map(|(parser_range, data)| {
(NodeRange::new(parser_range, collect_pos.start_pos), data)
})
@@ -399,20 +419,12 @@ impl<'a> Parser<'a> {
break_last_token: self.break_last_token,
node_replacements,
});
+ let mut tokens_used = false;
- // If we support tokens and don't already have them, store the newly captured tokens.
- if let Some(target_tokens @ None) = ret.tokens_mut() {
- *target_tokens = Some(tokens.clone());
- }
-
- // If `capture_cfg` is set and we're inside a recursive call to
- // `collect_tokens`, then we need to register a replace range if we
- // have `#[cfg]` or `#[cfg_attr]`. This allows us to run eager
- // cfg-expansion on the captured token stream.
- if self.capture_cfg
- && matches!(self.capture_state.capturing, Capturing::Yes)
- && has_cfg_or_cfg_attr(ret.attrs())
- {
+ // If in "definite capture mode" we need to register a replace range
+ // for the `#[cfg]` and/or `#[cfg_attr]` attrs. This allows us to run
+ // eager cfg-expansion on the captured token stream.
+ if definite_capture_mode {
assert!(!self.break_last_token, "Should not have unglued last token with cfg attr");
// What is the status here when parsing the example code at the top of this method?
@@ -429,7 +441,9 @@ impl<'a> Parser<'a> {
// cfg-expand this AST node.
let start_pos =
if has_outer_attrs { attrs.start_pos.unwrap() } else { collect_pos.start_pos };
- let target = AttrsTarget { attrs: ret.attrs().iter().cloned().collect(), tokens };
+ let target =
+ AttrsTarget { attrs: ret_attrs.iter().cloned().collect(), tokens: tokens.clone() };
+ tokens_used = true;
self.capture_state
.parser_replacements
.push((ParserRange(start_pos..end_pos), Some(target)));
@@ -438,7 +452,16 @@ impl<'a> Parser<'a> {
// the outermost call to this method.
self.capture_state.parser_replacements.clear();
self.capture_state.inner_attr_parser_ranges.clear();
+ self.capture_state.seen_attrs.clear();
}
+
+ // If we support tokens and don't already have them, store the newly captured tokens.
+ if let Some(target_tokens @ None) = ret.tokens_mut() {
+ tokens_used = true;
+ *target_tokens = Some(tokens);
+ }
+
+ assert!(tokens_used); // check we didn't create `tokens` unnecessarily
Ok(ret)
}
}
@@ -510,9 +533,11 @@ fn make_attr_token_stream(
}
/// Tokens are needed if:
-/// - any non-single-segment attributes (other than doc comments) are present; or
-/// - any `cfg_attr` attributes are present;
-/// - any single-segment, non-builtin attributes are present.
+/// - any non-single-segment attributes (other than doc comments) are present,
+/// e.g. `rustfmt::skip`; or
+/// - any `cfg_attr` attributes are present; or
+/// - any single-segment, non-builtin attributes are present, e.g. `derive`,
+/// `test`, `global_allocator`.
fn needs_tokens(attrs: &[ast::Attribute]) -> bool {
attrs.iter().any(|attr| match attr.ident() {
None => !attr.is_doc_comment(),
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index fcdc10c0837e..f6f66821df7f 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -19,8 +19,9 @@ use rustc_errors::{
Subdiagnostic,
};
use rustc_session::errors::ExprParenthesesNeeded;
+use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::source_map::Spanned;
-use rustc_span::symbol::{kw, sym, Ident};
+use rustc_span::symbol::{kw, sym, AllKeywords, Ident};
use rustc_span::{BytePos, Span, SpanSnippetError, Symbol, DUMMY_SP};
use thin_vec::{thin_vec, ThinVec};
use tracing::{debug, trace};
@@ -203,6 +204,37 @@ impl std::fmt::Display for UnaryFixity {
}
}
+#[derive(Debug, rustc_macros::Subdiagnostic)]
+#[suggestion(
+ parse_misspelled_kw,
+ applicability = "machine-applicable",
+ code = "{similar_kw}",
+ style = "verbose"
+)]
+struct MisspelledKw {
+ similar_kw: String,
+ #[primary_span]
+ span: Span,
+ is_incorrect_case: bool,
+}
+
+/// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`.
+fn find_similar_kw(lookup: Ident, candidates: &[Symbol]) -> Option {
+ let lowercase = lookup.name.as_str().to_lowercase();
+ let lowercase_sym = Symbol::intern(&lowercase);
+ if candidates.contains(&lowercase_sym) {
+ Some(MisspelledKw { similar_kw: lowercase, span: lookup.span, is_incorrect_case: true })
+ } else if let Some(similar_sym) = find_best_match_for_name(candidates, lookup.name, None) {
+ Some(MisspelledKw {
+ similar_kw: similar_sym.to_string(),
+ span: lookup.span,
+ is_incorrect_case: false,
+ })
+ } else {
+ None
+ }
+}
+
struct MultiSugg {
msg: String,
patches: Vec<(Span, String)>,
@@ -638,9 +670,9 @@ impl<'a> Parser<'a> {
let concat = Symbol::intern(&format!("{prev}{cur}"));
let ident = Ident::new(concat, DUMMY_SP);
if ident.is_used_keyword() || ident.is_reserved() || ident.is_raw_guess() {
- let span = self.prev_token.span.to(self.token.span);
+ let concat_span = self.prev_token.span.to(self.token.span);
err.span_suggestion_verbose(
- span,
+ concat_span,
format!("consider removing the space to spell keyword `{concat}`"),
concat,
Applicability::MachineApplicable,
@@ -741,9 +773,55 @@ impl<'a> Parser<'a> {
err.span_label(sp, label_exp);
err.span_label(self.token.span, "unexpected token");
}
+
+ // Check for misspelled keywords if there are no suggestions added to the diagnostic.
+ if err.suggestions.as_ref().is_ok_and(|code_suggestions| code_suggestions.is_empty()) {
+ self.check_for_misspelled_kw(&mut err, &expected);
+ }
Err(err)
}
+ /// Checks if the current token or the previous token are misspelled keywords
+ /// and adds a helpful suggestion.
+ fn check_for_misspelled_kw(&self, err: &mut Diag<'_>, expected: &[TokenType]) {
+ let Some((curr_ident, _)) = self.token.ident() else {
+ return;
+ };
+ let expected_tokens: &[TokenType] =
+ expected.len().checked_sub(10).map_or(&expected, |index| &expected[index..]);
+ let expected_keywords: Vec = expected_tokens
+ .iter()
+ .filter_map(|token| if let TokenType::Keyword(kw) = token { Some(*kw) } else { None })
+ .collect();
+
+ // When there are a few keywords in the last ten elements of `self.expected_tokens` and the current
+ // token is an identifier, it's probably a misspelled keyword.
+ // This handles code like `async Move {}`, misspelled `if` in match guard, misspelled `else` in `if`-`else`
+ // and mispelled `where` in a where clause.
+ if !expected_keywords.is_empty()
+ && !curr_ident.is_used_keyword()
+ && let Some(misspelled_kw) = find_similar_kw(curr_ident, &expected_keywords)
+ {
+ err.subdiagnostic(misspelled_kw);
+ } else if let Some((prev_ident, _)) = self.prev_token.ident()
+ && !prev_ident.is_used_keyword()
+ {
+ // We generate a list of all keywords at runtime rather than at compile time
+ // so that it gets generated only when the diagnostic needs it.
+ // Also, it is unlikely that this list is generated multiple times because the
+ // parser halts after execution hits this path.
+ let all_keywords = AllKeywords::new().collect_used(|| prev_ident.span.edition());
+
+ // Otherwise, check the previous token with all the keywords as possible candidates.
+ // This handles code like `Struct Human;` and `While a < b {}`.
+ // We check the previous token only when the current token is an identifier to avoid false
+ // positives like suggesting keyword `for` for `extern crate foo {}`.
+ if let Some(misspelled_kw) = find_similar_kw(prev_ident, &all_keywords) {
+ err.subdiagnostic(misspelled_kw);
+ }
+ }
+ }
+
/// The user has written `#[attr] expr` which is unsupported. (#106020)
pub(super) fn attr_on_non_tail_expr(&self, expr: &Expr) -> ErrorGuaranteed {
// Missing semicolon typo error.
@@ -846,6 +924,7 @@ impl<'a> Parser<'a> {
);
}
}
+
err.emit()
}
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 84684e808d94..ecc4cd96fafb 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2050,7 +2050,7 @@ impl<'a> Parser<'a> {
};
// On an error path, eagerly consider a lifetime to be an unclosed character lit, if that
// makes sense.
- if let Some(ident) = self.token.lifetime()
+ if let Some((ident, IdentIsRaw::No)) = self.token.lifetime()
&& could_be_unclosed_char_literal(ident)
{
let lt = self.expect_lifetime();
@@ -2925,9 +2925,9 @@ impl<'a> Parser<'a> {
}
pub(crate) fn eat_label(&mut self) -> Option