Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
806b443
add check for typo in let chains
Kivooeo Oct 21, 2025
b92ed4e
reflect that type and const parameter can be intermixed
tshepang Oct 29, 2025
73515c7
fix: Only special case single line item attribute suggestions
Muscraft Oct 22, 2025
d472d91
address review
Kivooeo Oct 31, 2025
516a273
Suggest making binding `mut` on `&mut` reborrow
estebank Sep 29, 2025
93fef45
Fix `wasm_import_module` attribute cross-crate
alexcrichton Nov 1, 2025
ba2600e
Suggest appropriate type instead of `Self` in E0401
estebank Nov 3, 2025
4af32ca
Add test
estebank Nov 3, 2025
48dde00
Use more accurate span in `resolve_ident_in_lexical_scope`
estebank Nov 3, 2025
14646ec
Add note to E0401
estebank Nov 3, 2025
001be2f
Make `parse_cfg_entry` output `ErrorGuaranteed` on failure
JonathanBrouwer Oct 21, 2025
b78800f
Port `cfg!()` macro to the new attribute parsing system
JonathanBrouwer Oct 21, 2025
a628e71
Add `ParsedDescription` to the attribute parsers
JonathanBrouwer Oct 29, 2025
549846e
Rollup merge of #147141 - estebank:issue-81059, r=jackh726
matthiaskrgr Nov 3, 2025
049092a
Rollup merge of #147945 - JonathanBrouwer:cfg_macro, r=jdonszelmann
matthiaskrgr Nov 3, 2025
3de72f6
Rollup merge of #147951 - Kivooeo:plus-equal-let-chains, r=davidtwco
matthiaskrgr Nov 3, 2025
e3dbcdf
Rollup merge of #148004 - Muscraft:only-single-line-item-attributes, …
matthiaskrgr Nov 3, 2025
d116eba
Rollup merge of #148264 - tshepang:patch-4, r=jackh726
matthiaskrgr Nov 3, 2025
b93b0d2
Rollup merge of #148363 - alexcrichton:fix-wasm-link-name, r=jackh726
matthiaskrgr Nov 3, 2025
bcf227a
Rollup merge of #148447 - estebank:outer-param-2, r=jackh726
matthiaskrgr Nov 3, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 37 additions & 36 deletions compiler/rustc_attr_parsing/src/attributes/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ use rustc_session::config::ExpectedValues;
use rustc_session::lint::BuiltinLintDiag;
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
use rustc_session::parse::{ParseSess, feature_err};
use rustc_span::{Span, Symbol, sym};
use rustc_span::{ErrorGuaranteed, Span, Symbol, sym};
use thin_vec::ThinVec;

use crate::context::{AcceptContext, ShouldEmit, Stage};
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser};
use crate::session_diagnostics::{
AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg,
ParsedDescription,
};
use crate::{
AttributeParser, CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics,
Expand Down Expand Up @@ -47,20 +48,19 @@ pub fn parse_cfg<'c, S: Stage>(
cx.expected_single_argument(list.span);
return None;
};
parse_cfg_entry(cx, single)
parse_cfg_entry(cx, single).ok()
}

pub(crate) fn parse_cfg_entry<S: Stage>(
pub fn parse_cfg_entry<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
item: &MetaItemOrLitParser<'_>,
) -> Option<CfgEntry> {
Some(match item {
) -> Result<CfgEntry, ErrorGuaranteed> {
Ok(match item {
MetaItemOrLitParser::MetaItemParser(meta) => match meta.args() {
ArgParser::List(list) => match meta.path().word_sym() {
Some(sym::not) => {
let Some(single) = list.single() else {
cx.expected_single_argument(list.span);
return None;
return Err(cx.expected_single_argument(list.span));
};
CfgEntry::Not(Box::new(parse_cfg_entry(cx, single)?), list.span)
}
Expand All @@ -75,49 +75,47 @@ pub(crate) fn parse_cfg_entry<S: Stage>(
Some(sym::target) => parse_cfg_entry_target(cx, list, meta.span())?,
Some(sym::version) => parse_cfg_entry_version(cx, list, meta.span())?,
_ => {
cx.emit_err(session_diagnostics::InvalidPredicate {
return Err(cx.emit_err(session_diagnostics::InvalidPredicate {
span: meta.span(),
predicate: meta.path().to_string(),
});
return None;
}));
}
},
a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
let Some(name) = meta.path().word_sym() else {
cx.expected_identifier(meta.path().span());
return None;
return Err(cx.expected_identifier(meta.path().span()));
};
parse_name_value(name, meta.path().span(), a.name_value(), meta.span(), cx)?
}
},
MetaItemOrLitParser::Lit(lit) => match lit.kind {
LitKind::Bool(b) => CfgEntry::Bool(b, lit.span),
_ => {
cx.expected_identifier(lit.span);
return None;
}
_ => return Err(cx.expected_identifier(lit.span)),
},
MetaItemOrLitParser::Err(_, _) => return None,
MetaItemOrLitParser::Err(_, err) => return Err(*err),
})
}

fn parse_cfg_entry_version<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
list: &MetaItemListParser<'_>,
meta_span: Span,
) -> Option<CfgEntry> {
) -> Result<CfgEntry, ErrorGuaranteed> {
try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option());
let Some(version) = list.single() else {
cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span });
return None;
return Err(
cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span })
);
};
let Some(version_lit) = version.lit() else {
cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version.span() });
return None;
return Err(
cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version.span() })
);
};
let Some(version_str) = version_lit.value_str() else {
cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version_lit.span });
return None;
return Err(
cx.emit_err(session_diagnostics::ExpectedVersionLiteral { span: version_lit.span })
);
};

let min_version = parse_version(version_str).or_else(|| {
Expand All @@ -127,14 +125,14 @@ fn parse_cfg_entry_version<S: Stage>(
None
});

Some(CfgEntry::Version(min_version, list.span))
Ok(CfgEntry::Version(min_version, list.span))
}

fn parse_cfg_entry_target<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
list: &MetaItemListParser<'_>,
meta_span: Span,
) -> Option<CfgEntry> {
) -> Result<CfgEntry, ErrorGuaranteed> {
if let Some(features) = cx.features_option()
&& !features.cfg_target_compact()
{
Expand All @@ -161,17 +159,16 @@ fn parse_cfg_entry_target<S: Stage>(

// Then, parse it as a name-value item
let Some(name) = sub_item.path().word_sym() else {
cx.expected_identifier(sub_item.path().span());
return None;
return Err(cx.expected_identifier(sub_item.path().span()));
};
let name = Symbol::intern(&format!("target_{name}"));
if let Some(cfg) =
if let Ok(cfg) =
parse_name_value(name, sub_item.path().span(), Some(nv), sub_item.span(), cx)
{
result.push(cfg);
}
}
Some(CfgEntry::All(result, list.span))
Ok(CfgEntry::All(result, list.span))
}

fn parse_name_value<S: Stage>(
Expand All @@ -180,21 +177,22 @@ fn parse_name_value<S: Stage>(
value: Option<&NameValueParser>,
span: Span,
cx: &mut AcceptContext<'_, '_, S>,
) -> Option<CfgEntry> {
) -> Result<CfgEntry, ErrorGuaranteed> {
try_gate_cfg(name, span, cx.sess(), cx.features_option());

let value = match value {
None => None,
Some(value) => {
let Some(value_str) = value.value_as_str() else {
cx.expected_string_literal(value.value_span, Some(value.value_as_lit()));
return None;
return Err(
cx.expected_string_literal(value.value_span, Some(value.value_as_lit()))
);
};
Some((value_str, value.value_span))
}
};

Some(CfgEntry::NameValue { name, name_span, value, span })
Ok(CfgEntry::NameValue { name, name_span, value, span })
}

pub fn eval_config_entry(
Expand Down Expand Up @@ -355,7 +353,8 @@ pub fn parse_cfg_attr(
span,
attr_span: cfg_attr.span,
template: CFG_ATTR_TEMPLATE,
attribute: AttrPath::from_ast(&cfg_attr.get_normal_item().path),
path: AttrPath::from_ast(&cfg_attr.get_normal_item().path),
description: ParsedDescription::Attribute,
reason,
suggestions: CFG_ATTR_TEMPLATE.suggestions(Some(cfg_attr.style), sym::cfg_attr),
});
Expand Down Expand Up @@ -398,6 +397,7 @@ fn parse_cfg_attr_internal<'a>(
.into_boxed_slice(),
span: attribute.span,
},
ParsedDescription::Attribute,
pred_span,
CRATE_NODE_ID,
features,
Expand All @@ -406,7 +406,8 @@ fn parse_cfg_attr_internal<'a>(
parse_cfg_entry,
&CFG_ATTR_TEMPLATE,
)
.ok_or_else(|| {
.map_err(|_err: ErrorGuaranteed| {
// We have an `ErrorGuaranteed` so this delayed bug cannot fail, but we need a `Diag` for the `PResult` so we make one anyways
let mut diag = sess.dcx().struct_err(
"cfg_entry parsing failing with `ShouldEmit::ErrorsAndLints` should emit a error.",
);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -396,7 +396,7 @@ impl LinkParser {
)
.emit();
}
*cfg = parse_cfg_entry(cx, link_cfg);
*cfg = parse_cfg_entry(cx, link_cfg).ok();
true
}

Expand Down
47 changes: 33 additions & 14 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ use crate::attributes::traits::{
use crate::attributes::transparency::TransparencyParser;
use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
use crate::parser::{ArgParser, PathParser};
use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
use crate::session_diagnostics::{
AttributeParseError, AttributeParseErrorReason, ParsedDescription, UnknownMetaItem,
};
use crate::target_checking::AllowedTargets;

type GroupType<S> = LazyLock<GroupTypeInner<S>>;
Expand Down Expand Up @@ -353,6 +355,10 @@ pub struct AcceptContext<'f, 'sess, S: Stage> {
/// Whether it is an inner or outer attribute
pub(crate) attr_style: AttrStyle,

/// A description of the thing we are parsing using this attribute parser
/// We are not only using these parsers for attributes, but also for macros such as the `cfg!()` macro.
pub(crate) parsed_description: ParsedDescription,

/// The expected structure of the attribute.
///
/// Used in reporting errors to give a hint to users what the attribute *should* look like.
Expand Down Expand Up @@ -431,7 +437,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedStringLiteral {
byte_string: actual_literal.and_then(|i| {
i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))
Expand All @@ -446,7 +453,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedIntegerLiteral,
suggestions: self.suggestions(),
})
Expand All @@ -457,7 +465,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedList,
suggestions: self.suggestions(),
})
Expand All @@ -468,7 +477,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span: args_span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedNoArgs,
suggestions: self.suggestions(),
})
Expand All @@ -480,7 +490,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedIdentifier,
suggestions: self.suggestions(),
})
Expand All @@ -493,7 +504,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedNameValue(name),
suggestions: self.suggestions(),
})
Expand All @@ -505,7 +517,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::DuplicateKey(key),
suggestions: self.suggestions(),
})
Expand All @@ -518,7 +531,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::UnexpectedLiteral,
suggestions: self.suggestions(),
})
Expand All @@ -529,7 +543,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedSingleArgument,
suggestions: self.suggestions(),
})
Expand All @@ -540,7 +555,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedAtLeastOneArgument,
suggestions: self.suggestions(),
})
Expand All @@ -556,7 +572,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
possibilities,
strings: false,
Expand All @@ -577,7 +594,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
possibilities,
strings: false,
Expand All @@ -597,7 +615,8 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> {
span,
attr_span: self.attr_span,
template: self.template.clone(),
attribute: self.attr_path.clone(),
path: self.attr_path.clone(),
description: self.parsed_description,
reason: AttributeParseErrorReason::ExpectedSpecificArgument {
possibilities,
strings: true,
Expand Down
Loading
Loading