Port #[cfg_attr] to the new attribute parsing infrastructure
Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
This commit is contained in:
@@ -4,6 +4,8 @@ attr_parsing_as_needed_compatibility =
|
|||||||
attr_parsing_bundle_needs_static =
|
attr_parsing_bundle_needs_static =
|
||||||
linking modifier `bundle` is only compatible with `static` linking kind
|
linking modifier `bundle` is only compatible with `static` linking kind
|
||||||
|
|
||||||
|
attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
|
||||||
|
|
||||||
attr_parsing_cfg_predicate_identifier =
|
attr_parsing_cfg_predicate_identifier =
|
||||||
`cfg` predicate key must be an identifier
|
`cfg` predicate key must be an identifier
|
||||||
|
|
||||||
@@ -264,13 +266,3 @@ attr_parsing_unused_multiple =
|
|||||||
|
|
||||||
attr_parsing_whole_archive_needs_static =
|
attr_parsing_whole_archive_needs_static =
|
||||||
linking modifier `whole-archive` is only compatible with `static` linking kind
|
linking modifier `whole-archive` is only compatible with `static` linking kind
|
||||||
|
|
||||||
attr_parsing_limit_invalid =
|
|
||||||
`limit` must be a non-negative integer
|
|
||||||
.label = {$error_str}
|
|
||||||
|
|
||||||
attr_parsing_cfg_attr_bad_delim = wrong `cfg_attr` delimiters
|
|
||||||
|
|
||||||
attr_parsing_malformed_cfg_attr = malformed `cfg_attr` attribute input
|
|
||||||
.suggestion = missing condition and attribute
|
|
||||||
.note = for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
use rustc_ast::token::Delimiter;
|
use rustc_ast::token::Delimiter;
|
||||||
use rustc_ast::tokenstream::DelimSpan;
|
use rustc_ast::tokenstream::DelimSpan;
|
||||||
use rustc_ast::{AttrItem, Attribute, LitKind, MetaItemInner, NodeId, ast, token};
|
use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, NodeId, ast, token};
|
||||||
use rustc_errors::PResult;
|
use rustc_errors::{Applicability, PResult};
|
||||||
use rustc_feature::{AttributeTemplate, Features, template};
|
use rustc_feature::{AttributeTemplate, Features, template};
|
||||||
use rustc_hir::RustcVersion;
|
|
||||||
use rustc_hir::attrs::CfgEntry;
|
use rustc_hir::attrs::CfgEntry;
|
||||||
|
use rustc_hir::{AttrPath, RustcVersion};
|
||||||
use rustc_parse::parser::{ForceCollect, Parser};
|
use rustc_parse::parser::{ForceCollect, Parser};
|
||||||
use rustc_parse::{exp, parse_in};
|
use rustc_parse::{exp, parse_in};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
@@ -17,9 +17,12 @@ use thin_vec::ThinVec;
|
|||||||
|
|
||||||
use crate::context::{AcceptContext, ShouldEmit, Stage};
|
use crate::context::{AcceptContext, ShouldEmit, Stage};
|
||||||
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser};
|
use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, NameValueParser};
|
||||||
use crate::session_diagnostics::{CfgAttrBadDelim, MalformedCfgAttr, MetaBadDelimSugg};
|
use crate::session_diagnostics::{
|
||||||
|
AttributeParseError, AttributeParseErrorReason, CfgAttrBadDelim, MetaBadDelimSugg,
|
||||||
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics, try_gate_cfg,
|
AttributeParser, CfgMatchesLintEmitter, fluent_generated, parse_version, session_diagnostics,
|
||||||
|
try_gate_cfg,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const CFG_TEMPLATE: AttributeTemplate = template!(
|
pub const CFG_TEMPLATE: AttributeTemplate = template!(
|
||||||
@@ -27,6 +30,11 @@ pub const CFG_TEMPLATE: AttributeTemplate = template!(
|
|||||||
"https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute"
|
"https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const CFG_ATTR_TEMPLATE: AttributeTemplate = template!(
|
||||||
|
List: &["predicate, attr1, attr2, ..."],
|
||||||
|
"https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute"
|
||||||
|
);
|
||||||
|
|
||||||
pub fn parse_cfg<'c, S: Stage>(
|
pub fn parse_cfg<'c, S: Stage>(
|
||||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||||
args: &'c ArgParser<'_>,
|
args: &'c ArgParser<'_>,
|
||||||
@@ -76,9 +84,7 @@ pub(crate) fn parse_cfg_entry<S: Stage>(
|
|||||||
},
|
},
|
||||||
a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
|
a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
|
||||||
let Some(name) = meta.path().word_sym() else {
|
let Some(name) = meta.path().word_sym() else {
|
||||||
cx.emit_err(session_diagnostics::CfgPredicateIdentifier {
|
cx.expected_identifier(meta.path().span());
|
||||||
span: meta.path().span(),
|
|
||||||
});
|
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
parse_name_value(name, meta.path().span(), a.name_value(), meta.span(), cx)?
|
parse_name_value(name, meta.path().span(), a.name_value(), meta.span(), cx)?
|
||||||
@@ -87,7 +93,7 @@ pub(crate) fn parse_cfg_entry<S: Stage>(
|
|||||||
MetaItemOrLitParser::Lit(lit) => match lit.kind {
|
MetaItemOrLitParser::Lit(lit) => match lit.kind {
|
||||||
LitKind::Bool(b) => CfgEntry::Bool(b, lit.span),
|
LitKind::Bool(b) => CfgEntry::Bool(b, lit.span),
|
||||||
_ => {
|
_ => {
|
||||||
cx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: lit.span });
|
cx.expected_identifier(lit.span);
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -155,9 +161,7 @@ fn parse_cfg_entry_target<S: Stage>(
|
|||||||
|
|
||||||
// Then, parse it as a name-value item
|
// Then, parse it as a name-value item
|
||||||
let Some(name) = sub_item.path().word_sym() else {
|
let Some(name) = sub_item.path().word_sym() else {
|
||||||
cx.emit_err(session_diagnostics::CfgPredicateIdentifier {
|
cx.expected_identifier(sub_item.path().span());
|
||||||
span: sub_item.path().span(),
|
|
||||||
});
|
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let name = Symbol::intern(&format!("target_{name}"));
|
let name = Symbol::intern(&format!("target_{name}"));
|
||||||
@@ -309,32 +313,51 @@ impl EvalConfigResult {
|
|||||||
|
|
||||||
pub fn parse_cfg_attr(
|
pub fn parse_cfg_attr(
|
||||||
cfg_attr: &Attribute,
|
cfg_attr: &Attribute,
|
||||||
psess: &ParseSess,
|
sess: &Session,
|
||||||
) -> Option<(MetaItemInner, Vec<(AttrItem, Span)>)> {
|
features: Option<&Features>,
|
||||||
const CFG_ATTR_GRAMMAR_HELP: &str = "#[cfg_attr(condition, attribute, other_attribute, ...)]";
|
) -> Option<(CfgEntry, Vec<(AttrItem, Span)>)> {
|
||||||
const CFG_ATTR_NOTE_REF: &str = "for more information, visit \
|
|
||||||
<https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg_attr-attribute>";
|
|
||||||
|
|
||||||
match cfg_attr.get_normal_item().args {
|
match cfg_attr.get_normal_item().args {
|
||||||
ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens })
|
ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens })
|
||||||
if !tokens.is_empty() =>
|
if !tokens.is_empty() =>
|
||||||
{
|
{
|
||||||
check_cfg_attr_bad_delim(psess, dspan, delim);
|
check_cfg_attr_bad_delim(&sess.psess, dspan, delim);
|
||||||
match parse_in(psess, tokens.clone(), "`cfg_attr` input", |p| {
|
match parse_in(&sess.psess, tokens.clone(), "`cfg_attr` input", |p| {
|
||||||
parse_cfg_attr_internal(p)
|
parse_cfg_attr_internal(p, sess, features, cfg_attr)
|
||||||
}) {
|
}) {
|
||||||
Ok(r) => return Some(r),
|
Ok(r) => return Some(r),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
e.with_help(format!("the valid syntax is `{CFG_ATTR_GRAMMAR_HELP}`"))
|
let suggestions = CFG_ATTR_TEMPLATE.suggestions(cfg_attr.style, sym::cfg_attr);
|
||||||
.with_note(CFG_ATTR_NOTE_REF)
|
e.with_span_suggestions(
|
||||||
.emit();
|
cfg_attr.span,
|
||||||
|
"must be of the form",
|
||||||
|
suggestions,
|
||||||
|
Applicability::HasPlaceholders,
|
||||||
|
)
|
||||||
|
.with_note(format!(
|
||||||
|
"for more information, visit <{}>",
|
||||||
|
CFG_ATTR_TEMPLATE.docs.expect("cfg_attr has docs")
|
||||||
|
))
|
||||||
|
.emit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
psess
|
let (span, reason) = if let ast::AttrArgs::Delimited(ast::DelimArgs { dspan, .. }) =
|
||||||
.dcx()
|
cfg_attr.get_normal_item().args
|
||||||
.emit_err(MalformedCfgAttr { span: cfg_attr.span, sugg: CFG_ATTR_GRAMMAR_HELP });
|
{
|
||||||
|
(dspan.entire(), AttributeParseErrorReason::ExpectedAtLeastOneArgument)
|
||||||
|
} else {
|
||||||
|
(cfg_attr.span, AttributeParseErrorReason::ExpectedList)
|
||||||
|
};
|
||||||
|
|
||||||
|
sess.dcx().emit_err(AttributeParseError {
|
||||||
|
span,
|
||||||
|
attr_span: cfg_attr.span,
|
||||||
|
template: CFG_ATTR_TEMPLATE,
|
||||||
|
attribute: AttrPath::from_ast(&cfg_attr.get_normal_item().path),
|
||||||
|
reason,
|
||||||
|
attr_style: cfg_attr.style,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
@@ -353,8 +376,42 @@ fn check_cfg_attr_bad_delim(psess: &ParseSess, span: DelimSpan, delim: Delimiter
|
|||||||
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
|
/// Parses `cfg_attr(pred, attr_item_list)` where `attr_item_list` is comma-delimited.
|
||||||
fn parse_cfg_attr_internal<'a>(
|
fn parse_cfg_attr_internal<'a>(
|
||||||
parser: &mut Parser<'a>,
|
parser: &mut Parser<'a>,
|
||||||
) -> PResult<'a, (ast::MetaItemInner, Vec<(ast::AttrItem, Span)>)> {
|
sess: &'a Session,
|
||||||
let cfg_predicate = parser.parse_meta_item_inner()?;
|
features: Option<&Features>,
|
||||||
|
attribute: &Attribute,
|
||||||
|
) -> PResult<'a, (CfgEntry, Vec<(ast::AttrItem, Span)>)> {
|
||||||
|
// Parse cfg predicate
|
||||||
|
let pred_start = parser.token.span;
|
||||||
|
let meta = MetaItemOrLitParser::parse_single(parser, ShouldEmit::ErrorsAndLints)?;
|
||||||
|
let pred_span = pred_start.with_hi(parser.token.span.hi());
|
||||||
|
|
||||||
|
let cfg_predicate = AttributeParser::parse_single_args(
|
||||||
|
sess,
|
||||||
|
attribute.span,
|
||||||
|
attribute.style,
|
||||||
|
AttrPath {
|
||||||
|
segments: attribute
|
||||||
|
.ident_path()
|
||||||
|
.expect("cfg_attr is not a doc comment")
|
||||||
|
.into_boxed_slice(),
|
||||||
|
span: attribute.span,
|
||||||
|
},
|
||||||
|
pred_span,
|
||||||
|
CRATE_NODE_ID,
|
||||||
|
features,
|
||||||
|
ShouldEmit::ErrorsAndLints,
|
||||||
|
&meta,
|
||||||
|
parse_cfg_entry,
|
||||||
|
&CFG_ATTR_TEMPLATE,
|
||||||
|
)
|
||||||
|
.ok_or_else(|| {
|
||||||
|
let mut diag = sess.dcx().struct_err(
|
||||||
|
"cfg_entry parsing failing with `ShouldEmit::ErrorsAndLints` should emit a error.",
|
||||||
|
);
|
||||||
|
diag.downgrade_to_delayed_bug();
|
||||||
|
diag
|
||||||
|
})?;
|
||||||
|
|
||||||
parser.expect(exp!(Comma))?;
|
parser.expect(exp!(Comma))?;
|
||||||
|
|
||||||
// Presumably, the majority of the time there will only be one attr.
|
// Presumably, the majority of the time there will only be one attr.
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use rustc_ast as ast;
|
use rustc_ast as ast;
|
||||||
use rustc_ast::NodeId;
|
use rustc_ast::{AttrStyle, NodeId};
|
||||||
use rustc_errors::DiagCtxtHandle;
|
use rustc_errors::DiagCtxtHandle;
|
||||||
use rustc_feature::{AttributeTemplate, Features};
|
use rustc_feature::{AttributeTemplate, Features};
|
||||||
use rustc_hir::attrs::AttributeKind;
|
use rustc_hir::attrs::AttributeKind;
|
||||||
@@ -62,7 +62,8 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Usually you want `parse_limited`, which defaults to no errors.
|
/// This does the same as `parse_limited`, except it has a `should_emit` parameter which allows it to emit errors.
|
||||||
|
/// Usually you want `parse_limited`, which emits no errors.
|
||||||
pub fn parse_limited_should_emit(
|
pub fn parse_limited_should_emit(
|
||||||
sess: &'sess Session,
|
sess: &'sess Session,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[ast::Attribute],
|
||||||
@@ -86,6 +87,13 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||||||
parsed.pop()
|
parsed.pop()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This method allows you to parse a list of attributes *before* `rustc_ast_lowering`.
|
||||||
|
/// This can be used for attributes that would be removed before `rustc_ast_lowering`, such as attributes on macro calls.
|
||||||
|
///
|
||||||
|
/// Try to use this as little as possible. Attributes *should* be lowered during
|
||||||
|
/// `rustc_ast_lowering`. Some attributes require access to features to parse, which would
|
||||||
|
/// crash if you tried to do so through [`parse_limited_all`](Self::parse_limited_all).
|
||||||
|
/// Therefore, if `parse_only` is None, then features *must* be provided.
|
||||||
pub fn parse_limited_all(
|
pub fn parse_limited_all(
|
||||||
sess: &'sess Session,
|
sess: &'sess Session,
|
||||||
attrs: &[ast::Attribute],
|
attrs: &[ast::Attribute],
|
||||||
@@ -111,6 +119,8 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// This method parses a single attribute, using `parse_fn`.
|
||||||
|
/// This is useful if you already know what exact attribute this is, and want to parse it.
|
||||||
pub fn parse_single<T>(
|
pub fn parse_single<T>(
|
||||||
sess: &'sess Session,
|
sess: &'sess Session,
|
||||||
attr: &ast::Attribute,
|
attr: &ast::Attribute,
|
||||||
@@ -121,13 +131,6 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||||||
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> Option<T>,
|
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> Option<T>,
|
||||||
template: &AttributeTemplate,
|
template: &AttributeTemplate,
|
||||||
) -> Option<T> {
|
) -> Option<T> {
|
||||||
let mut parser = Self {
|
|
||||||
features,
|
|
||||||
tools: Vec::new(),
|
|
||||||
parse_only: None,
|
|
||||||
sess,
|
|
||||||
stage: Early { emit_errors },
|
|
||||||
};
|
|
||||||
let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
|
let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
|
||||||
panic!("parse_single called on a doc attr")
|
panic!("parse_single called on a doc attr")
|
||||||
};
|
};
|
||||||
@@ -136,6 +139,43 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||||||
let meta_parser = MetaItemParser::from_attr(normal_attr, &parts, &sess.psess, emit_errors)?;
|
let meta_parser = MetaItemParser::from_attr(normal_attr, &parts, &sess.psess, emit_errors)?;
|
||||||
let path = meta_parser.path();
|
let path = meta_parser.path();
|
||||||
let args = meta_parser.args();
|
let args = meta_parser.args();
|
||||||
|
Self::parse_single_args(
|
||||||
|
sess,
|
||||||
|
attr.span,
|
||||||
|
attr.style,
|
||||||
|
path.get_attribute_path(),
|
||||||
|
target_span,
|
||||||
|
target_node_id,
|
||||||
|
features,
|
||||||
|
emit_errors,
|
||||||
|
args,
|
||||||
|
parse_fn,
|
||||||
|
template,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This method is equivalent to `parse_single`, but parses arguments using `parse_fn` using manually created `args`.
|
||||||
|
/// This is useful when you want to parse other things than attributes using attribute parsers.
|
||||||
|
pub fn parse_single_args<T, I>(
|
||||||
|
sess: &'sess Session,
|
||||||
|
attr_span: Span,
|
||||||
|
attr_style: AttrStyle,
|
||||||
|
attr_path: AttrPath,
|
||||||
|
target_span: Span,
|
||||||
|
target_node_id: NodeId,
|
||||||
|
features: Option<&'sess Features>,
|
||||||
|
emit_errors: ShouldEmit,
|
||||||
|
args: &I,
|
||||||
|
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> Option<T>,
|
||||||
|
template: &AttributeTemplate,
|
||||||
|
) -> Option<T> {
|
||||||
|
let mut parser = Self {
|
||||||
|
features,
|
||||||
|
tools: Vec::new(),
|
||||||
|
parse_only: None,
|
||||||
|
sess,
|
||||||
|
stage: Early { emit_errors },
|
||||||
|
};
|
||||||
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
|
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
|
||||||
shared: SharedContext {
|
shared: SharedContext {
|
||||||
cx: &mut parser,
|
cx: &mut parser,
|
||||||
@@ -145,10 +185,10 @@ impl<'sess> AttributeParser<'sess, Early> {
|
|||||||
crate::lints::emit_attribute_lint(&lint, sess);
|
crate::lints::emit_attribute_lint(&lint, sess);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
attr_span: attr.span,
|
attr_span,
|
||||||
attr_style: attr.style,
|
attr_style,
|
||||||
template,
|
template,
|
||||||
attr_path: path.get_attribute_path(),
|
attr_path,
|
||||||
};
|
};
|
||||||
parse_fn(&mut cx, args)
|
parse_fn(&mut cx, args)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::fmt::{Debug, Display};
|
|||||||
|
|
||||||
use rustc_ast::token::{self, Delimiter, MetaVarKind};
|
use rustc_ast::token::{self, Delimiter, MetaVarKind};
|
||||||
use rustc_ast::tokenstream::TokenStream;
|
use rustc_ast::tokenstream::TokenStream;
|
||||||
use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path};
|
use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path};
|
||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_errors::{Diag, PResult};
|
use rustc_errors::{Diag, PResult};
|
||||||
use rustc_hir::{self as hir, AttrPath};
|
use rustc_hir::{self as hir, AttrPath};
|
||||||
@@ -124,7 +124,11 @@ impl<'a> ArgParser<'a> {
|
|||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Self::List(MetaItemListParser::new(args, psess, should_emit)?)
|
Self::List(
|
||||||
|
MetaItemListParser::new(&args.tokens, args.dspan.entire(), psess, should_emit)
|
||||||
|
.map_err(|e| should_emit.emit_err(e))
|
||||||
|
.ok()?,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser {
|
AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser {
|
||||||
eq_span: *eq_span,
|
eq_span: *eq_span,
|
||||||
@@ -186,7 +190,15 @@ pub enum MetaItemOrLitParser<'a> {
|
|||||||
Err(Span, ErrorGuaranteed),
|
Err(Span, ErrorGuaranteed),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MetaItemOrLitParser<'a> {
|
impl<'sess> MetaItemOrLitParser<'sess> {
|
||||||
|
pub fn parse_single(
|
||||||
|
parser: &mut Parser<'sess>,
|
||||||
|
should_emit: ShouldEmit,
|
||||||
|
) -> PResult<'sess, MetaItemOrLitParser<'static>> {
|
||||||
|
let mut this = MetaItemListParserContext { parser, should_emit };
|
||||||
|
this.parse_meta_item_inner()
|
||||||
|
}
|
||||||
|
|
||||||
pub fn span(&self) -> Span {
|
pub fn span(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
MetaItemOrLitParser::MetaItemParser(generic_meta_item_parser) => {
|
MetaItemOrLitParser::MetaItemParser(generic_meta_item_parser) => {
|
||||||
@@ -204,7 +216,7 @@ impl<'a> MetaItemOrLitParser<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn meta_item(&self) -> Option<&MetaItemParser<'a>> {
|
pub fn meta_item(&self) -> Option<&MetaItemParser<'sess>> {
|
||||||
match self {
|
match self {
|
||||||
MetaItemOrLitParser::MetaItemParser(parser) => Some(parser),
|
MetaItemOrLitParser::MetaItemParser(parser) => Some(parser),
|
||||||
_ => None,
|
_ => None,
|
||||||
@@ -542,23 +554,13 @@ pub struct MetaItemListParser<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MetaItemListParser<'a> {
|
impl<'a> MetaItemListParser<'a> {
|
||||||
fn new<'sess>(
|
pub(crate) fn new<'sess>(
|
||||||
delim: &'a DelimArgs,
|
tokens: &'a TokenStream,
|
||||||
|
span: Span,
|
||||||
psess: &'sess ParseSess,
|
psess: &'sess ParseSess,
|
||||||
should_emit: ShouldEmit,
|
should_emit: ShouldEmit,
|
||||||
) -> Option<Self> {
|
) -> Result<Self, Diag<'sess>> {
|
||||||
match MetaItemListParserContext::parse(
|
MetaItemListParserContext::parse(tokens.clone(), psess, span, should_emit)
|
||||||
delim.tokens.clone(),
|
|
||||||
psess,
|
|
||||||
delim.dspan.entire(),
|
|
||||||
should_emit,
|
|
||||||
) {
|
|
||||||
Ok(s) => Some(s),
|
|
||||||
Err(e) => {
|
|
||||||
should_emit.emit_err(e);
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Lets you pick and choose as what you want to parse each element in the list
|
/// Lets you pick and choose as what you want to parse each element in the list
|
||||||
|
|||||||
@@ -980,13 +980,3 @@ pub(crate) struct CfgAttrBadDelim {
|
|||||||
#[subdiagnostic]
|
#[subdiagnostic]
|
||||||
pub sugg: MetaBadDelimSugg,
|
pub sugg: MetaBadDelimSugg,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
|
||||||
#[diag(attr_parsing_malformed_cfg_attr)]
|
|
||||||
#[note]
|
|
||||||
pub(crate) struct MalformedCfgAttr {
|
|
||||||
#[primary_span]
|
|
||||||
#[suggestion(style = "verbose", code = "{sugg}")]
|
|
||||||
pub span: Span,
|
|
||||||
pub sugg: &'static str,
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||||||
let trace_attr = attr_into_trace(cfg_attr.clone(), sym::cfg_attr_trace);
|
let trace_attr = attr_into_trace(cfg_attr.clone(), sym::cfg_attr_trace);
|
||||||
|
|
||||||
let Some((cfg_predicate, expanded_attrs)) =
|
let Some((cfg_predicate, expanded_attrs)) =
|
||||||
rustc_attr_parsing::parse_cfg_attr(cfg_attr, &self.sess.psess)
|
rustc_attr_parsing::parse_cfg_attr(cfg_attr, &self.sess, self.features)
|
||||||
else {
|
else {
|
||||||
return vec![trace_attr];
|
return vec![trace_attr];
|
||||||
};
|
};
|
||||||
@@ -318,7 +318,15 @@ impl<'a> StripUnconfigured<'a> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if !attr::cfg_matches(&cfg_predicate, &self.sess, self.lint_node_id, self.features) {
|
if !attr::eval_config_entry(
|
||||||
|
self.sess,
|
||||||
|
&cfg_predicate,
|
||||||
|
ast::CRATE_NODE_ID,
|
||||||
|
self.features,
|
||||||
|
ShouldEmit::ErrorsAndLints,
|
||||||
|
)
|
||||||
|
.as_bool()
|
||||||
|
{
|
||||||
return vec![trace_attr];
|
return vec![trace_attr];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user