From 0d72821ae57d5d67e94fce5e9f496c3729e21a9c Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Fri, 19 Jun 2026 17:11:42 +0300 Subject: [PATCH 1/2] Remove redundant check for `#[loop_match]` remove `check_loop_match` from `check_attr.rs` as it only verifies that the target is a loop, which is already enforced by `check_target` in `target_checking.rs` via `ALLOWED_TARGETS`, and its `LoopMatchAttr` diagnostic. --- compiler/rustc_passes/src/check_attr.rs | 16 +--------------- compiler/rustc_passes/src/diagnostics.rs | 9 --------- tests/ui/loop-match/invalid-attribute.rs | 1 - tests/ui/loop-match/invalid-attribute.stderr | 13 ++----------- 4 files changed, 3 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index dd950cce42103..51cd7667235c1 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -193,9 +193,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::Inline(kind, attr_span) => { self.check_inline(hir_id, *attr_span, kind, target) } - AttributeKind::LoopMatch(attr_span) => { - self.check_loop_match(hir_id, *attr_span, target) - } AttributeKind::ConstContinue(attr_span) => { self.check_const_continue(hir_id, *attr_span, target) } @@ -286,6 +283,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::LinkOrdinal { .. } => (), AttributeKind::LinkSection { .. } => (), AttributeKind::Linkage(..) => (), + AttributeKind::LoopMatch(..) => {} AttributeKind::MacroEscape => (), AttributeKind::MacroUse { .. } => (), AttributeKind::Marker => (), @@ -1663,18 +1661,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_loop_match(&self, hir_id: HirId, attr_span: Span, target: Target) { - let node_span = self.tcx.hir_span(hir_id); - - if !matches!(target, Target::Expression) { - return; // Handled in target checking during attr parse - } - - if !matches!(self.tcx.hir_expect_expr(hir_id).kind, hir::ExprKind::Loop(..)) { - self.dcx().emit_err(diagnostics::LoopMatchAttr { attr_span, node_span }); - }; - } - fn check_const_continue(&self, hir_id: HirId, attr_span: Span, target: Target) { let node_span = self.tcx.hir_span(hir_id); diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 7c00d9d2e1bcb..723a90f033031 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -13,15 +13,6 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol}; use crate::check_attr::ProcMacroKind; use crate::lang_items::Duplicate; -#[derive(Diagnostic)] -#[diag("`#[loop_match]` should be applied to a loop")] -pub(crate) struct LoopMatchAttr { - #[primary_span] - pub attr_span: Span, - #[label("not a loop")] - pub node_span: Span, -} - #[derive(Diagnostic)] #[diag("`#[const_continue]` should be applied to a break expression")] pub(crate) struct ConstContinueAttr { diff --git a/tests/ui/loop-match/invalid-attribute.rs b/tests/ui/loop-match/invalid-attribute.rs index 4e4fe41c6ecb9..8c83f802c2b35 100644 --- a/tests/ui/loop-match/invalid-attribute.rs +++ b/tests/ui/loop-match/invalid-attribute.rs @@ -37,7 +37,6 @@ fn main() { { #[loop_match] //~ ERROR attribute cannot be used on - //~^ ERROR `#[loop_match]` should be applied to a loop #[const_continue] //~ ERROR should be applied to a break expression 5 }; diff --git a/tests/ui/loop-match/invalid-attribute.stderr b/tests/ui/loop-match/invalid-attribute.stderr index 4db75e1e57b04..4cbb58149e4c9 100644 --- a/tests/ui/loop-match/invalid-attribute.stderr +++ b/tests/ui/loop-match/invalid-attribute.stderr @@ -102,22 +102,13 @@ LL | #[loop_match] | = help: `#[loop_match]` can only be applied to loops -error: `#[loop_match]` should be applied to a loop - --> $DIR/invalid-attribute.rs:39:9 - | -LL | #[loop_match] - | ^^^^^^^^^^^^^ -... -LL | 5 - | - not a loop - error: `#[const_continue]` should be applied to a break expression - --> $DIR/invalid-attribute.rs:41:9 + --> $DIR/invalid-attribute.rs:40:9 | LL | #[const_continue] | ^^^^^^^^^^^^^^^^^ LL | 5 | - not a break expression -error: aborting due to 15 previous errors +error: aborting due to 14 previous errors From 620bf09346ca85ac4613f7dd7b0258acbd314b85 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Fri, 19 Jun 2026 18:12:40 +0300 Subject: [PATCH 2/2] Remove redundant check for `#[const_continue]` remove `check_const_continue` from `check_attr.rs` as it only verifies that the target is a break, which is already enforced by `check_target` in `target_checking.rs` via `ALLOWED_TARGETS`, and it's's `ConstContinueAttr` diagnostic. --- .../src/attributes/loop_match.rs | 2 +- .../rustc_attr_parsing/src/target_checking.rs | 1 + compiler/rustc_hir/src/target.rs | 7 ++++++- compiler/rustc_passes/src/check_attr.rs | 21 ++++--------------- compiler/rustc_passes/src/diagnostics.rs | 9 -------- tests/ui/loop-match/invalid-attribute.rs | 3 ++- tests/ui/loop-match/invalid-attribute.stderr | 18 ++++++++-------- 7 files changed, 23 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs index 0a04742bdfe58..06c3cd286a06e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/loop_match.rs +++ b/compiler/rustc_attr_parsing/src/attributes/loop_match.rs @@ -13,7 +13,7 @@ impl NoArgsAttributeParser for LoopMatchParser { pub(crate) struct ConstContinueParser; impl NoArgsAttributeParser for ConstContinueParser { const PATH: &[Symbol] = &[sym::const_continue]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Expression)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Break)]); const STABILITY: AttributeStability = unstable!(loop_match); const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstContinue; } diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index e60938aacdcc6..9345c0f5183df 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -527,5 +527,6 @@ pub(crate) const ALL_TARGETS: &'static [Policy] = { Allow(Target::Loop), Allow(Target::ForLoop), Allow(Target::While), + Allow(Target::Break), ] }; diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs index 2c5615a13f402..a59b30ebf2748 100644 --- a/compiler/rustc_hir/src/target.rs +++ b/compiler/rustc_hir/src/target.rs @@ -70,6 +70,7 @@ pub enum Target { ForLoop, While, Loop, + Break, } impl Display for Target { @@ -119,7 +120,8 @@ impl Target { | Target::Delegation { .. } | Target::Loop | Target::While - | Target::ForLoop => false, + | Target::ForLoop + | Target::Break => false, } } @@ -265,6 +267,7 @@ impl Target { ast::ExprKind::ForLoop { .. } => Self::ForLoop, ast::ExprKind::Loop(..) => Self::Loop, ast::ExprKind::While(..) => Self::While, + ast::ExprKind::Break(..) => Self::Break, _ => Self::Expression, } } @@ -319,6 +322,7 @@ impl Target { Target::Loop => "loop", Target::ForLoop => "for loop", Target::While => "while loop", + Target::Break => "break expression", } } @@ -373,6 +377,7 @@ impl Target { Target::ForLoop => "for loops", Target::Loop => "loops", Target::While => "while loops", + Target::Break => "break expressions", } } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 51cd7667235c1..079fdd923ac0d 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -193,9 +193,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::Inline(kind, attr_span) => { self.check_inline(hir_id, *attr_span, kind, target) } - AttributeKind::ConstContinue(attr_span) => { - self.check_const_continue(hir_id, *attr_span, target) - } AttributeKind::AllowInternalUnsafe(attr_span) | AttributeKind::AllowInternalUnstable(.., attr_span) => { self.check_macro_only_attr(*attr_span, span, target, attrs) @@ -215,7 +212,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { &AttributeKind::RustcPubTransparent(attr_span) => { self.check_rustc_pub_transparent(attr_span, span, attrs) } - AttributeKind::RustcAlign { .. } => {} AttributeKind::Naked(..) => self.check_naked(hir_id, target), AttributeKind::TrackCaller(attr_span) => { self.check_track_caller(hir_id, *attr_span, attrs, target) @@ -259,6 +255,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::Cold => (), AttributeKind::CollapseDebugInfo(..) => (), AttributeKind::CompilerBuiltins => (), + AttributeKind::ConstContinue(..) => {} AttributeKind::Coroutine => (), AttributeKind::Coverage(..) => (), AttributeKind::CrateName { .. } => (), @@ -315,6 +312,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // handled below this loop and elsewhere AttributeKind::Repr { .. } => (), AttributeKind::RustcAbi { .. } => (), + AttributeKind::RustcAlign { .. } => {} AttributeKind::RustcAllocator => (), AttributeKind::RustcAllocatorZeroed => (), AttributeKind::RustcAllocatorZeroedVariant { .. } => (), @@ -889,7 +887,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | Target::Delegation { .. } | Target::Loop | Target::ForLoop - | Target::While => None, + | Target::While + | Target::Break => None, } { self.tcx.dcx().emit_err(diagnostics::DocAliasBadLocation { span, location }); return; @@ -1660,18 +1659,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { .emit_err(diagnostics::BothOptimizeNoneAndInline { optimize_span, inline_span }); } } - - fn check_const_continue(&self, hir_id: HirId, attr_span: Span, target: Target) { - let node_span = self.tcx.hir_span(hir_id); - - if !matches!(target, Target::Expression) { - return; // Handled in target checking during attr parse - } - - if !matches!(self.tcx.hir_expect_expr(hir_id).kind, hir::ExprKind::Break(..)) { - self.dcx().emit_err(diagnostics::ConstContinueAttr { attr_span, node_span }); - }; - } } impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 723a90f033031..f6c4b0cf77d12 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -13,15 +13,6 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol}; use crate::check_attr::ProcMacroKind; use crate::lang_items::Duplicate; -#[derive(Diagnostic)] -#[diag("`#[const_continue]` should be applied to a break expression")] -pub(crate) struct ConstContinueAttr { - #[primary_span] - pub attr_span: Span, - #[label("not a break expression")] - pub node_span: Span, -} - #[derive(Diagnostic)] #[diag("`{$no_mangle_attr}` attribute may not be used in combination with `{$export_name_attr}`")] pub(crate) struct MixedExportNameAndNoMangle { diff --git a/tests/ui/loop-match/invalid-attribute.rs b/tests/ui/loop-match/invalid-attribute.rs index 8c83f802c2b35..2953df6373e69 100644 --- a/tests/ui/loop-match/invalid-attribute.rs +++ b/tests/ui/loop-match/invalid-attribute.rs @@ -37,7 +37,8 @@ fn main() { { #[loop_match] //~ ERROR attribute cannot be used on - #[const_continue] //~ ERROR should be applied to a break expression + #[const_continue] + //~^ ERROR `#[const_continue]` attribute cannot be used on expressions 5 }; } diff --git a/tests/ui/loop-match/invalid-attribute.stderr b/tests/ui/loop-match/invalid-attribute.stderr index 4cbb58149e4c9..ce291d6d446a6 100644 --- a/tests/ui/loop-match/invalid-attribute.stderr +++ b/tests/ui/loop-match/invalid-attribute.stderr @@ -12,7 +12,7 @@ error: `#[const_continue]` attribute cannot be used on crates LL | #![const_continue] | ^^^^^^^^^^^^^^^^^^ | - = help: `#[const_continue]` can be applied to + = help: `#[const_continue]` can only be applied to break expressions error: `#[loop_match]` attribute cannot be used on foreign functions --> $DIR/invalid-attribute.rs:10:5 @@ -28,7 +28,7 @@ error: `#[const_continue]` attribute cannot be used on foreign functions LL | #[const_continue] | ^^^^^^^^^^^^^^^^^ | - = help: `#[const_continue]` can be applied to + = help: `#[const_continue]` can only be applied to break expressions error: `#[loop_match]` attribute cannot be used on structs --> $DIR/invalid-attribute.rs:15:1 @@ -44,7 +44,7 @@ error: `#[const_continue]` attribute cannot be used on structs LL | #[const_continue] | ^^^^^^^^^^^^^^^^^ | - = help: `#[const_continue]` can be applied to + = help: `#[const_continue]` can only be applied to break expressions error: `#[loop_match]` attribute cannot be used on required trait methods --> $DIR/invalid-attribute.rs:24:5 @@ -60,7 +60,7 @@ error: `#[const_continue]` attribute cannot be used on required trait methods LL | #[const_continue] | ^^^^^^^^^^^^^^^^^ | - = help: `#[const_continue]` can be applied to + = help: `#[const_continue]` can only be applied to break expressions error: `#[loop_match]` attribute cannot be used on functions --> $DIR/invalid-attribute.rs:29:1 @@ -76,7 +76,7 @@ error: `#[const_continue]` attribute cannot be used on functions LL | #[const_continue] | ^^^^^^^^^^^^^^^^^ | - = help: `#[const_continue]` can be applied to + = help: `#[const_continue]` can only be applied to break expressions error: `#[loop_match]` attribute cannot be used on closures --> $DIR/invalid-attribute.rs:34:5 @@ -92,7 +92,7 @@ error: `#[const_continue]` attribute cannot be used on closures LL | #[const_continue] | ^^^^^^^^^^^^^^^^^ | - = help: `#[const_continue]` can be applied to + = help: `#[const_continue]` can only be applied to break expressions error: `#[loop_match]` attribute cannot be used on expressions --> $DIR/invalid-attribute.rs:39:9 @@ -102,13 +102,13 @@ LL | #[loop_match] | = help: `#[loop_match]` can only be applied to loops -error: `#[const_continue]` should be applied to a break expression +error: `#[const_continue]` attribute cannot be used on expressions --> $DIR/invalid-attribute.rs:40:9 | LL | #[const_continue] | ^^^^^^^^^^^^^^^^^ -LL | 5 - | - not a break expression + | + = help: `#[const_continue]` can only be applied to break expressions error: aborting due to 14 previous errors