Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,7 @@ fn parse_cfg_attr_internal<'a>(
let meta = MetaItemOrLitParser::parse_single(
parser,
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
true,
Comment thread
Jules-Bertholet marked this conversation as resolved.
Outdated
)?;
let pred_span = pred_start.with_hi(parser.token.span.hi());

Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/cfg_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub fn parse_cfg_select(
let meta = MetaItemOrLitParser::parse_single(
p,
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
true,
)
.map_err(|diag| diag.emit())?;
let cfg_span = meta.span();
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_attr_parsing/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ impl<'sess> AttributeParser<'sess, Early> {
emit_errors: ShouldEmit,
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser) -> Option<T>,
template: &AttributeTemplate,
allow_expr_metavar: bool,
) -> Option<T> {
let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
panic!("parse_single called on a doc attr")
Expand All @@ -152,6 +153,7 @@ impl<'sess> AttributeParser<'sess, Early> {
&parts,
&sess.psess,
emit_errors,
allow_expr_metavar,
)?;
Self::parse_single_args(
sess,
Expand Down Expand Up @@ -333,6 +335,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
&parts,
&self.sess.psess,
self.stage.should_emit(),
false,
) else {
continue;
};
Expand Down
87 changes: 67 additions & 20 deletions compiler/rustc_attr_parsing/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ impl ArgParser {
parts: &[Symbol],
psess: &'sess ParseSess,
should_emit: ShouldEmit,
allow_expr_metavar: bool,
) -> Option<Self> {
Some(match value {
AttrArgs::Empty => Self::NoArgs,
Expand All @@ -122,6 +123,7 @@ impl ArgParser {
args.dspan.entire(),
psess,
ShouldEmit::ErrorsAndLints { recovery: Recovery::Forbidden },
allow_expr_metavar,
) {
Ok(p) => return Some(ArgParser::List(p)),
Err(e) => {
Expand All @@ -147,9 +149,15 @@ impl ArgParser {
}

Self::List(
MetaItemListParser::new(&args.tokens, args.dspan.entire(), psess, should_emit)
.map_err(|e| should_emit.emit_err(e))
.ok()?,
MetaItemListParser::new(
&args.tokens,
args.dspan.entire(),
psess,
should_emit,
allow_expr_metavar,
)
.map_err(|e| should_emit.emit_err(e))
.ok()?,
)
}
AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser {
Expand Down Expand Up @@ -217,8 +225,9 @@ impl MetaItemOrLitParser {
pub fn parse_single<'sess>(
parser: &mut Parser<'sess>,
should_emit: ShouldEmit,
allow_expr_metavar: bool,
) -> PResult<'sess, MetaItemOrLitParser> {
let mut this = MetaItemListParserContext { parser, should_emit };
let mut this = MetaItemListParserContext { parser, should_emit, allow_expr_metavar };
this.parse_meta_item_inner()
}

Expand Down Expand Up @@ -407,6 +416,7 @@ fn expr_to_lit<'sess>(
struct MetaItemListParserContext<'a, 'sess> {
parser: &'a mut Parser<'sess>,
should_emit: ShouldEmit,
allow_expr_metavar: bool,
}

impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
Expand Down Expand Up @@ -448,19 +458,43 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
}

fn parse_attr_item(&mut self) -> PResult<'sess, MetaItemParser> {
Comment thread
Jules-Bertholet marked this conversation as resolved.
Outdated
if let Some(MetaVarKind::Meta { has_meta_form }) = self.parser.token.is_metavar_seq() {
return if has_meta_form {
let attr_item = self
.parser
.eat_metavar_seq(MetaVarKind::Meta { has_meta_form: true }, |this| {
MetaItemListParserContext { parser: this, should_emit: self.should_emit }
if let Some(metavar) = self.parser.token.is_metavar_seq() {
match metavar {
kind @ MetaVarKind::Expr { .. } if self.allow_expr_metavar => {
return self
.parser
.eat_metavar_seq(kind, |this| {
MetaItemListParserContext {
parser: this,
should_emit: self.should_emit,
allow_expr_metavar: true,
}
.parse_attr_item()
})
.unwrap();
Ok(attr_item)
} else {
self.parser.unexpected_any()
};
})
.ok_or_else(|| {
self.parser.unexpected_any::<core::convert::Infallible>().unwrap_err()
});
}
MetaVarKind::Meta { has_meta_form } => {
return if has_meta_form {
let attr_item = self
.parser
.eat_metavar_seq(MetaVarKind::Meta { has_meta_form: true }, |this| {
MetaItemListParserContext {
parser: this,
should_emit: self.should_emit,
allow_expr_metavar: self.allow_expr_metavar,
}
.parse_attr_item()
})
.unwrap();
Ok(attr_item)
} else {
self.parser.unexpected_any()
};
}
_ => {}
}
}

let path = self.parser.parse_path(PathStyle::Mod)?;
Expand All @@ -469,8 +503,12 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
let args = if self.parser.check(exp!(OpenParen)) {
let start = self.parser.token.span;
let (sub_parsers, _) = self.parser.parse_paren_comma_seq(|parser| {
MetaItemListParserContext { parser, should_emit: self.should_emit }
.parse_meta_item_inner()
MetaItemListParserContext {
parser,
should_emit: self.should_emit,
allow_expr_metavar: self.allow_expr_metavar,
}
.parse_meta_item_inner()
})?;
let end = self.parser.prev_token.span;
ArgParser::List(MetaItemListParser { sub_parsers, span: start.with_hi(end.hi()) })
Expand Down Expand Up @@ -580,13 +618,15 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
psess: &'sess ParseSess,
span: Span,
should_emit: ShouldEmit,
allow_expr_metavar: bool,
) -> 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 };
let mut this =
MetaItemListParserContext { parser: &mut parser, should_emit, allow_expr_metavar };

// Presumably, the majority of the time there will only be one attr.
let mut sub_parsers = ThinVec::with_capacity(1);
Expand Down Expand Up @@ -618,8 +658,15 @@ impl MetaItemListParser {
span: Span,
psess: &'sess ParseSess,
should_emit: ShouldEmit,
allow_expr_metavar: bool,
) -> Result<Self, Diag<'sess>> {
MetaItemListParserContext::parse(tokens.clone(), psess, span, should_emit)
MetaItemListParserContext::parse(
tokens.clone(),
psess,
span,
should_emit,
allow_expr_metavar,
)
}

/// Lets you pick and choose as what you want to parse each element in the list
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_builtin_macros/src/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result<CfgEntry,
let meta = MetaItemOrLitParser::parse_single(
&mut parser,
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
true,
)
.map_err(|diag| diag.emit())?;
let cfg = AttributeParser::parse_single_args(
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,7 @@ impl<'a> StripUnconfigured<'a> {
emit_errors,
parse_cfg,
&CFG_TEMPLATE,
true,
) else {
// Cfg attribute was not parsable, give up
return EvalConfigResult::True;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2224,6 +2224,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
parse_cfg,
&CFG_TEMPLATE,
true,
) else {
// Cfg attribute was not parsable, give up
return EvalConfigResult::True;
Expand Down
20 changes: 1 addition & 19 deletions library/std/src/sys/thread_local/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,25 +62,7 @@ pub macro thread_local_inner {
// by translating it into a `cfg`ed block and recursing.
// https://doc.rust-lang.org/reference/conditional-compilation.html#railroad-ConfigurationPredicate

(@align $final_align:ident, cfg_attr(true, $($cfg_rhs:tt)*) $(, $($attr_rest:tt)+)?) => {
#[cfg(true)]
{
$crate::thread::local_impl::thread_local_inner!(@align $final_align, $($cfg_rhs)*);
}

$($crate::thread::local_impl::thread_local_inner!(@align $final_align, $($attr_rest)+);)?
},

(@align $final_align:ident, cfg_attr(false, $($cfg_rhs:tt)*) $(, $($attr_rest:tt)+)?) => {
#[cfg(false)]
{
$crate::thread::local_impl::thread_local_inner!(@align $final_align, $($cfg_rhs)*);
}

$($crate::thread::local_impl::thread_local_inner!(@align $final_align, $($attr_rest)+);)?
},

(@align $final_align:ident, cfg_attr($cfg_pred:meta, $($cfg_rhs:tt)*) $(, $($attr_rest:tt)+)?) => {
(@align $final_align:ident, cfg_attr($cfg_pred:expr, $($cfg_rhs:tt)*) $(, $($attr_rest:tt)+)?) => {
#[cfg($cfg_pred)]
{
$crate::thread::local_impl::thread_local_inner!(@align $final_align, $($cfg_rhs)*);
Expand Down
55 changes: 2 additions & 53 deletions library/std/src/thread/local.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,41 +198,10 @@ pub macro thread_local_process_attrs {
);
),

// it's a nested `cfg_attr(true, ...)`; recurse into RHS
(
[$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
@processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [cfg_attr(true, $($cfg_rhs:tt)*) $(, $($attr_rhs:tt)*)?] };
$($rest:tt)*
) => (
$crate::thread::local_impl::thread_local_process_attrs!(
[] [];
@processing_cfg_attr { pred: (true), rhs: [$($cfg_rhs)*] };
[$($prev_align_attrs)*] [$($prev_other_attrs)*];
@processing_cfg_attr { pred: ($($predicate)*), rhs: [$($($attr_rhs)*)?] };
$($rest)*
);
),

// it's a nested `cfg_attr(false, ...)`; recurse into RHS
(
[$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
@processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [cfg_attr(false, $($cfg_rhs:tt)*) $(, $($attr_rhs:tt)*)?] };
$($rest:tt)*
) => (
$crate::thread::local_impl::thread_local_process_attrs!(
[] [];
@processing_cfg_attr { pred: (false), rhs: [$($cfg_rhs)*] };
[$($prev_align_attrs)*] [$($prev_other_attrs)*];
@processing_cfg_attr { pred: ($($predicate)*), rhs: [$($($attr_rhs)*)?] };
$($rest)*
);
),


// it's a nested `cfg_attr(..., ...)`; recurse into RHS
(
[$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*];
@processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [cfg_attr($cfg_lhs:meta, $($cfg_rhs:tt)*) $(, $($attr_rhs:tt)*)?] };
@processing_cfg_attr { pred: ($($predicate:tt)*), rhs: [cfg_attr($cfg_lhs:expr, $($cfg_rhs:tt)*) $(, $($attr_rhs:tt)*)?] };
$($rest:tt)*
) => (
$crate::thread::local_impl::thread_local_process_attrs!(
Expand Down Expand Up @@ -268,28 +237,8 @@ pub macro thread_local_process_attrs {
);
),

// `cfg_attr(true, ...)` attribute; parse it
([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[cfg_attr(true, $($cfg_rhs:tt)*)] $($rest:tt)*) => (
$crate::thread::local_impl::thread_local_process_attrs!(
[] [];
@processing_cfg_attr { pred: (true), rhs: [$($cfg_rhs)*] };
[$($prev_align_attrs)*] [$($prev_other_attrs)*];
$($rest)*
);
),

// `cfg_attr(false, ...)` attribute; parse it
([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[cfg_attr(false, $($cfg_rhs:tt)*)] $($rest:tt)*) => (
$crate::thread::local_impl::thread_local_process_attrs!(
[] [];
@processing_cfg_attr { pred: (false), rhs: [$($cfg_rhs)*] };
[$($prev_align_attrs)*] [$($prev_other_attrs)*];
$($rest)*
);
),

// `cfg_attr(..., ...)` attribute; parse it
([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[cfg_attr($cfg_pred:meta, $($cfg_rhs:tt)*)] $($rest:tt)*) => (
([$($prev_align_attrs:tt)*] [$($prev_other_attrs:tt)*]; #[cfg_attr($cfg_pred:expr, $($cfg_rhs:tt)*)] $($rest:tt)*) => (
$crate::thread::local_impl::thread_local_process_attrs!(
[] [];
@processing_cfg_attr { pred: ($cfg_pred), rhs: [$($cfg_rhs)*] };
Expand Down
9 changes: 9 additions & 0 deletions tests/ui/macros/attr-expr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
macro_rules! foo {
($e:expr) => {
#[$e]
//~^ ERROR expected identifier, found metavariable
fn foo() {}
}
}
foo!(inline);
fn main() {}
13 changes: 13 additions & 0 deletions tests/ui/macros/attr-expr.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error: expected identifier, found metavariable
--> $DIR/attr-expr.rs:3:11
|
LL | #[$e]
| ^^ expected identifier, found metavariable
...
LL | foo!(inline);
| ------------ in this macro invocation
|
= note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to 1 previous error

44 changes: 44 additions & 0 deletions tests/ui/macros/cfg-expr.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//@ run-pass
macro_rules! foo {
($e:expr, $n:ident) => {
#[cfg($e)]
macro_rules! $n {
() => {}
}

#[cfg_attr($e, allow(non_snake_case))]
#[cfg($e)]
fn $n() {
#[cfg($e)]
$n!();
}

#[cfg_attr(not($e), allow(unused))]
#[cfg(not($e))]
fn $n() {
panic!()
}
}
}
foo!(true, BAR);
foo!(any(true, unix, target_pointer_width = "64"), baz);
foo!(target_pointer_width = "64", quux);
foo!(false, haha);

fn main() {
BAR();
BAR!();
baz();
baz!();
#[cfg(target_pointer_width = "64")]
quux();
#[cfg(target_pointer_width = "64")]
quux!();
#[cfg(panic = "unwind")]
{
let result = std::panic::catch_unwind(|| {
haha();
});
assert!(result.is_err());
}
}
Loading
Loading