Rollup merge of #151999 - mejrs:ignore_nonmeta_v2, r=JonathanBrouwer

attribute parsing: pass recovery mode to Parser.

Fixes https://github.com/rust-lang/rust/issues/151996
This commit is contained in:
Jacob Pratt
2026-02-02 23:12:08 -05:00
committed by GitHub
10 changed files with 48 additions and 29 deletions
@@ -10,7 +10,7 @@
use rustc_hir::attrs::CfgEntry;
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{AttrPath, RustcVersion, Target};
use rustc_parse::parser::{ForceCollect, Parser};
use rustc_parse::parser::{ForceCollect, Parser, Recovery};
use rustc_parse::{exp, parse_in};
use rustc_session::Session;
use rustc_session::config::ExpectedValues;
@@ -360,8 +360,10 @@ fn parse_cfg_attr_internal<'a>(
) -> PResult<'a, (CfgEntry, Vec<(ast::AttrItem, Span)>)> {
// Parse cfg predicate
let pred_start = parser.token.span;
let meta =
MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints { recover: true })?;
let meta = MetaItemOrLitParser::parse_single(
parser,
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
)?;
let pred_span = pred_start.with_hi(parser.token.span.hi());
let cfg_predicate = AttributeParser::parse_single_args(
@@ -376,7 +378,7 @@ fn parse_cfg_attr_internal<'a>(
CRATE_NODE_ID,
Target::Crate,
features,
ShouldEmit::ErrorsAndLints { recover: true },
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
&meta,
parse_cfg_entry,
&CFG_ATTR_TEMPLATE,
@@ -5,7 +5,7 @@
use rustc_hir::attrs::CfgEntry;
use rustc_hir::{AttrPath, Target};
use rustc_parse::exp;
use rustc_parse::parser::Parser;
use rustc_parse::parser::{Parser, Recovery};
use rustc_session::Session;
use rustc_span::{ErrorGuaranteed, Span, sym};
@@ -78,9 +78,11 @@ pub fn parse_cfg_select(
}
}
} else {
let meta =
MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints { recover: true })
.map_err(|diag| diag.emit())?;
let meta = MetaItemOrLitParser::parse_single(
p,
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
)
.map_err(|diag| diag.emit())?;
let cfg_span = meta.span();
let cfg = AttributeParser::parse_single_args(
sess,
@@ -95,7 +97,7 @@ pub fn parse_cfg_select(
// Doesn't matter what the target actually is here.
Target::Crate,
features,
ShouldEmit::ErrorsAndLints { recover: true },
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
&meta,
parse_cfg_entry,
&AttributeTemplate::default(),
+6 -5
View File
@@ -10,6 +10,7 @@
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{AttrPath, HirId};
use rustc_parse::parser::Recovery;
use rustc_session::Session;
use rustc_session::lint::{Lint, LintId};
use rustc_span::{ErrorGuaranteed, Span, Symbol};
@@ -383,7 +384,7 @@ fn emit_err<'sess>(
}
fn should_emit(&self) -> ShouldEmit {
ShouldEmit::ErrorsAndLints { recover: true }
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }
}
}
@@ -770,10 +771,10 @@ pub enum ShouldEmit {
ErrorsAndLints {
/// Whether [`ArgParser`] will attempt to recover from errors.
///
/// If true, it will attempt to recover from bad input (like an invalid literal). Setting
/// this to false will instead return early, and not raise errors except at the top level
/// (in [`ArgParser::from_attr_args`]).
recover: bool,
/// Whether it is allowed to recover from bad input (like an invalid literal). Setting
/// this to `Forbidden` will instead return early, and not raise errors except at the top
/// level (in [`ArgParser::from_attr_args`]).
recovery: Recovery,
},
/// The operation will *not* emit errors and lints.
///
+14 -4
View File
@@ -15,7 +15,7 @@
use rustc_errors::{Diag, PResult};
use rustc_hir::{self as hir, AttrPath};
use rustc_parse::exp;
use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr};
use rustc_parse::parser::{ForceCollect, Parser, PathStyle, Recovery, token_descr};
use rustc_session::errors::create_lit_error;
use rustc_session::parse::ParseSess;
use rustc_span::{Ident, Span, Symbol, sym};
@@ -121,7 +121,7 @@ pub fn from_attr_args<'sess>(
&args.tokens,
args.dspan.entire(),
psess,
ShouldEmit::ErrorsAndLints { recover: false },
ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden },
) {
Ok(p) => return Some(ArgParser::List(p)),
Err(e) => {
@@ -373,7 +373,10 @@ fn expr_to_lit<'sess>(
}
Err(err) => {
let err = create_lit_error(psess, err, token_lit, expr.span);
if matches!(should_emit, ShouldEmit::ErrorsAndLints { recover: false }) {
if matches!(
should_emit,
ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden }
) {
Err(err)
} else {
let lit = MetaItemLit {
@@ -431,7 +434,10 @@ fn unsuffixed_meta_item_from_lit(
if !lit.kind.is_unsuffixed() {
// Emit error and continue, we can still parse the attribute as if the suffix isn't there
let err = self.parser.dcx().create_err(SuffixedLiteralInAttribute { span: lit.span });
if matches!(self.should_emit, ShouldEmit::ErrorsAndLints { recover: false }) {
if matches!(
self.should_emit,
ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden }
) {
return Err(err);
} else {
self.should_emit.emit_err(err)
@@ -569,6 +575,10 @@ fn parse(
should_emit: ShouldEmit,
) -> PResult<'sess, MetaItemListParser> {
let mut parser = Parser::new(psess, tokens, None);
if let ShouldEmit::ErrorsAndLints { recovery } = should_emit {
parser = parser.recovery(recovery);
}
let mut this = MetaItemListParserContext { parser: &mut parser, should_emit };
// Presumably, the majority of the time there will only be one attr.
+3 -2
View File
@@ -13,6 +13,7 @@
use rustc_hir::attrs::CfgEntry;
use rustc_hir::{AttrPath, Target};
use rustc_parse::exp;
use rustc_parse::parser::Recovery;
use rustc_span::{ErrorGuaranteed, Span, sym};
use crate::errors;
@@ -42,7 +43,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry,
let meta = MetaItemOrLitParser::parse_single(
&mut parser,
ShouldEmit::ErrorsAndLints { recover: true },
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
)
.map_err(|diag| diag.emit())?;
let cfg = AttributeParser::parse_single_args(
@@ -58,7 +59,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry,
// Doesn't matter what the target actually is here.
Target::Crate,
Some(cx.ecfg.features),
ShouldEmit::ErrorsAndLints { recover: true },
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
&meta,
parse_cfg_entry,
&CFG_TEMPLATE,
+4 -1
View File
@@ -20,6 +20,7 @@
UNSTABLE_LANG_FEATURES,
};
use rustc_hir::Target;
use rustc_parse::parser::Recovery;
use rustc_session::Session;
use rustc_session::parse::feature_err;
use rustc_span::{STDLIB_STABLE_CRATES, Span, Symbol, sym};
@@ -395,7 +396,9 @@ fn expand_cfg_attr_item(
fn in_cfg(&self, attrs: &[Attribute]) -> bool {
attrs.iter().all(|attr| {
!is_cfg(attr)
|| self.cfg_true(attr, ShouldEmit::ErrorsAndLints { recover: true }).as_bool()
|| self
.cfg_true(attr, ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed })
.as_bool()
})
}
+3 -3
View File
@@ -26,7 +26,7 @@
use rustc_hir::limit::Limit;
use rustc_parse::parser::{
AllowConstBlockItems, AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser,
RecoverColon, RecoverComma, token_descr,
RecoverColon, RecoverComma, Recovery, token_descr,
};
use rustc_session::Session;
use rustc_session::lint::builtin::{UNUSED_ATTRIBUTES, UNUSED_DOC_COMMENTS};
@@ -2170,7 +2170,7 @@ fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) {
call.span(),
self.cx.current_expansion.lint_node_id,
Some(self.cx.ecfg.features),
ShouldEmit::ErrorsAndLints { recover: true },
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
);
let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
@@ -2220,7 +2220,7 @@ fn expand_cfg_true(
// Target doesn't matter for `cfg` parsing.
Target::Crate,
self.cfg().features,
ShouldEmit::ErrorsAndLints { recover: true },
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
parse_cfg,
&CFG_TEMPLATE,
) else {
@@ -1,8 +1,8 @@
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
--> $DIR/does_not_acccept_args.rs:12:1
|
LL | #[diagnostic::do_not_recommend(not_accepted)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | #[diagnostic::do_not_recommend(if, crate, do yeet, false, dyn, abstract, gen, not_accepted)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
@@ -1,8 +1,8 @@
warning: `#[diagnostic::do_not_recommend]` does not expect any arguments
--> $DIR/does_not_acccept_args.rs:12:1
|
LL | #[diagnostic::do_not_recommend(not_accepted)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
LL | #[diagnostic::do_not_recommend(if, crate, do yeet, false, dyn, abstract, gen, not_accepted)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default
@@ -9,7 +9,7 @@ trait Bar {}
trait Baz {}
trait Boo {}
#[diagnostic::do_not_recommend(not_accepted)]
#[diagnostic::do_not_recommend(if, crate, do yeet, false, dyn, abstract, gen, not_accepted)]
//~^ WARNING `#[diagnostic::do_not_recommend]` does not expect any arguments
impl<T> Foo for T where T: Send {}