Skip to content

Commit 956aa91

Browse files
committed
WIP: deny path-segment kw in cfg
1 parent b2be57d commit 956aa91

File tree

10 files changed

+129
-296
lines changed

10 files changed

+129
-296
lines changed

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ pub(crate) fn parse_cfg_entry<S: Stage>(
6969
}
7070
},
7171
a @ (ArgParser::NoArgs | ArgParser::NameValue(_)) => {
72-
let Some(name) = meta.path().word_sym().filter(|s| !s.is_path_segment_keyword())
73-
else {
72+
let Some(name) = meta.path().word_sym() else {
7473
cx.emit_err(session_diagnostics::CfgPredicateIdentifier {
7574
span: meta.path().span(),
7675
});
@@ -149,7 +148,7 @@ fn parse_cfg_entry_target<S: Stage>(
149148
};
150149

151150
// Then, parse it as a name-value item
152-
let Some(name) = sub_item.path().word_sym().filter(|s| !s.is_path_segment_keyword()) else {
151+
let Some(name) = sub_item.path().word_sym() else {
153152
cx.emit_err(session_diagnostics::CfgPredicateIdentifier {
154153
span: sub_item.path().span(),
155154
});

compiler/rustc_attr_parsing/src/attributes/cfg_old.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,7 @@ pub fn eval_condition(
220220
}
221221
}
222222
}
223-
MetaItemKind::Word | MetaItemKind::NameValue(..)
224-
if cfg.path.segments.len() != 1
225-
|| cfg.path.segments[0].ident.is_path_segment_keyword() =>
226-
{
223+
MetaItemKind::Word | MetaItemKind::NameValue(..) if cfg.path.segments.len() != 1 => {
227224
dcx.emit_err(session_diagnostics::CfgPredicateIdentifier { span: cfg.path.span });
228225
true
229226
}

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ impl<'sess> AttributeParser<'sess, Early> {
118118
target_node_id: NodeId,
119119
features: Option<&'sess Features>,
120120
emit_errors: ShouldEmit,
121+
accept_ident_only: bool,
121122
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> Option<T>,
122123
template: &AttributeTemplate,
123124
) -> Option<T> {
@@ -133,7 +134,13 @@ impl<'sess> AttributeParser<'sess, Early> {
133134
};
134135
let parts =
135136
normal_attr.item.path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>();
136-
let meta_parser = MetaItemParser::from_attr(normal_attr, &parts, &sess.psess, emit_errors)?;
137+
let meta_parser = MetaItemParser::from_attr(
138+
normal_attr,
139+
&parts,
140+
&sess.psess,
141+
emit_errors,
142+
accept_ident_only,
143+
)?;
137144
let path = meta_parser.path();
138145
let args = meta_parser.args();
139146
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
@@ -251,6 +258,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
251258
&parts,
252259
&self.sess.psess,
253260
self.stage.should_emit(),
261+
false,
254262
) else {
255263
continue;
256264
};

compiler/rustc_attr_parsing/src/parser.rs

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ impl<'a> ArgParser<'a> {
104104
parts: &[Symbol],
105105
psess: &'sess ParseSess,
106106
should_emit: ShouldEmit,
107+
accept_ident_only: bool,
107108
) -> Option<Self> {
108109
Some(match value {
109110
AttrArgs::Empty => Self::NoArgs,
@@ -124,7 +125,7 @@ impl<'a> ArgParser<'a> {
124125
return None;
125126
}
126127

127-
Self::List(MetaItemListParser::new(args, psess, should_emit)?)
128+
Self::List(MetaItemListParser::new(args, psess, should_emit, accept_ident_only)?)
128129
}
129130
AttrArgs::Eq { eq_span, expr } => Self::NameValue(NameValueParser {
130131
eq_span: *eq_span,
@@ -248,10 +249,17 @@ impl<'a> MetaItemParser<'a> {
248249
parts: &[Symbol],
249250
psess: &'sess ParseSess,
250251
should_emit: ShouldEmit,
252+
accept_ident_only: bool,
251253
) -> Option<Self> {
252254
Some(Self {
253255
path: PathParser(Cow::Borrowed(&attr.item.path)),
254-
args: ArgParser::from_attr_args(&attr.item.args, parts, psess, should_emit)?,
256+
args: ArgParser::from_attr_args(
257+
&attr.item.args,
258+
parts,
259+
psess,
260+
should_emit,
261+
accept_ident_only,
262+
)?,
255263
})
256264
}
257265
}
@@ -375,6 +383,7 @@ fn expr_to_lit(
375383
struct MetaItemListParserContext<'a, 'sess> {
376384
parser: &'a mut Parser<'sess>,
377385
should_emit: ShouldEmit,
386+
accept_ident_only: bool,
378387
}
379388

380389
impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
@@ -415,8 +424,12 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
415424
let attr_item = self
416425
.parser
417426
.eat_metavar_seq(MetaVarKind::Meta { has_meta_form: true }, |this| {
418-
MetaItemListParserContext { parser: this, should_emit: self.should_emit }
419-
.parse_attr_item()
427+
MetaItemListParserContext {
428+
parser: this,
429+
should_emit: self.should_emit,
430+
accept_ident_only: self.accept_ident_only,
431+
}
432+
.parse_attr_item()
420433
})
421434
.unwrap();
422435
Ok(attr_item)
@@ -425,14 +438,22 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
425438
};
426439
}
427440

428-
let path = self.parser.parse_path(PathStyle::Mod)?;
441+
let path = if self.accept_ident_only {
442+
Path::from_ident(self.parser.parse_ident()?)
443+
} else {
444+
self.parser.parse_path(PathStyle::Mod)?
445+
};
429446

430447
// Check style of arguments that this meta item has
431448
let args = if self.parser.check(exp!(OpenParen)) {
432449
let start = self.parser.token.span;
433450
let (sub_parsers, _) = self.parser.parse_paren_comma_seq(|parser| {
434-
MetaItemListParserContext { parser, should_emit: self.should_emit }
435-
.parse_meta_item_inner()
451+
MetaItemListParserContext {
452+
parser,
453+
should_emit: self.should_emit,
454+
accept_ident_only: self.accept_ident_only,
455+
}
456+
.parse_meta_item_inner()
436457
})?;
437458
let end = self.parser.prev_token.span;
438459
ArgParser::List(MetaItemListParser { sub_parsers, span: start.with_hi(end.hi()) })
@@ -513,9 +534,11 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
513534
psess: &'sess ParseSess,
514535
span: Span,
515536
should_emit: ShouldEmit,
537+
accept_ident_only: bool,
516538
) -> PResult<'sess, MetaItemListParser<'static>> {
517539
let mut parser = Parser::new(psess, tokens, None);
518-
let mut this = MetaItemListParserContext { parser: &mut parser, should_emit };
540+
let mut this =
541+
MetaItemListParserContext { parser: &mut parser, should_emit, accept_ident_only };
519542

520543
// Presumably, the majority of the time there will only be one attr.
521544
let mut sub_parsers = ThinVec::with_capacity(1);
@@ -546,12 +569,14 @@ impl<'a> MetaItemListParser<'a> {
546569
delim: &'a DelimArgs,
547570
psess: &'sess ParseSess,
548571
should_emit: ShouldEmit,
572+
accept_ident_only: bool,
549573
) -> Option<Self> {
550574
match MetaItemListParserContext::parse(
551575
delim.tokens.clone(),
552576
psess,
553577
delim.dspan.entire(),
554578
should_emit,
579+
accept_ident_only,
555580
) {
556581
Ok(s) => Some(s),
557582
Err(e) => {

compiler/rustc_errors/src/emitter.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -548,7 +548,7 @@ impl Emitter for FatalOnlyEmitter {
548548
}
549549

550550
fn emit_diagnostic(&mut self, mut diag: DiagInner, registry: &Registry) {
551-
if diag.level == Level::Fatal {
551+
if diag.level.is_error() {
552552
if let Some(fatal_note) = &self.fatal_note {
553553
diag.sub(Level::Note, fatal_note.clone(), MultiSpan::new());
554554
}

compiler/rustc_errors/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1998,6 +1998,10 @@ impl Level {
19981998
matches!(*self, FailureNote)
19991999
}
20002000

2001+
pub fn is_error(&self) -> bool {
2002+
matches!(*self, Bug | DelayedBug | Fatal | Error)
2003+
}
2004+
20012005
// Can this level be used in a subdiagnostic message?
20022006
fn can_be_subdiag(&self) -> bool {
20032007
match self {

compiler/rustc_expand/src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,7 @@ impl<'a> StripUnconfigured<'a> {
428428
node,
429429
self.features,
430430
emit_errors,
431+
true,
431432
parse_cfg_attr,
432433
&CFG_TEMPLATE,
433434
) else {

compiler/rustc_span/src/symbol.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3034,7 +3034,9 @@ impl Symbol {
30343034

30353035
/// Returns `true` if this symbol can be a raw identifier.
30363036
pub fn can_be_raw(self) -> bool {
3037-
self != sym::empty && self != kw::Underscore && !self.is_path_segment_keyword()
3037+
self != sym::empty
3038+
&& self != kw::Underscore
3039+
&& !matches!(self, kw::PathRoot | kw::DollarCrate)
30383040
}
30393041

30403042
/// Was this symbol index predefined in the compiler's `symbols!` macro?

tests/ui/cfg/path-kw-as-pred.rs

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,76 @@
11
//@ edition: 2024
22

3+
#![allow(unexpected_cfgs)]
4+
35
macro_rules! foo {
46
() => {
5-
#[cfg($crate)] //~ ERROR `cfg` predicate key must be an identifier
6-
#[cfg_attr($crate, path = "foo")] //~ ERROR `cfg` predicate key must be an identifier
7-
mod _x {}
7+
#[cfg($crate)] //~ ERROR expected identifier, found reserved identifier `$crate`
8+
mod _cfg_dollar_crate {}
9+
#[cfg_attr($crate, path = "foo")] //~ ERROR expected identifier, found reserved identifier `$crate`
10+
mod _cfg_attr_dollar_crate {}
811

912
cfg!($crate); //~ ERROR `cfg` predicate key must be an identifier
1013
};
1114
}
1215

13-
#[cfg(crate)] //~ ERROR `cfg` predicate key must be an identifier
14-
#[cfg(super)] //~ ERROR `cfg` predicate key must be an identifier
15-
#[cfg(self)] //~ ERROR `cfg` predicate key must be an identifier
16-
#[cfg(Self)] //~ ERROR `cfg` predicate key must be an identifier
17-
#[cfg_attr(crate, path = "foo")] //~ ERROR `cfg` predicate key must be an identifier
18-
#[cfg_attr(super, path = "foo")] //~ ERROR `cfg` predicate key must be an identifier
19-
#[cfg_attr(self, path = "foo")] //~ ERROR `cfg` predicate key must be an identifier
20-
#[cfg_attr(Self, path = "foo")] //~ ERROR `cfg` predicate key must be an identifier
21-
mod _path_kw {}
16+
#[cfg(crate)] //~ ERROR expected identifier, found keyword `crate`
17+
mod _cfg_crate {}
18+
#[cfg(super)] //~ ERROR expected identifier, found keyword `super`
19+
mod _cfg_super {}
20+
#[cfg(self)] //~ ERROR expected identifier, found keyword `self`
21+
mod _cfg_self_lower {}
22+
#[cfg(Self)] //~ ERROR expected identifier, found keyword `Self`
23+
mod _cfg_self_upper {}
24+
#[cfg_attr(crate, path = "foo")] //~ ERROR expected identifier, found keyword `crate`
25+
mod _cfg_attr_crate {}
26+
#[cfg_attr(super, path = "foo")] //~ ERROR expected identifier, found keyword `super`
27+
mod _cfg_attr_super {}
28+
#[cfg_attr(self, path = "foo")] //~ ERROR expected identifier, found keyword `self`
29+
mod _cfg_attr_self_lower {}
30+
#[cfg_attr(Self, path = "foo")] //~ ERROR expected identifier, found keyword `Self`
31+
mod _cfg_attr_self_upper {}
2232

2333
#[cfg(struct)] //~ ERROR expected identifier, found keyword
24-
//~^ WARNING unexpected `cfg` condition name
25-
mod _non_path_kw1 {}
34+
mod _cfg_struct {}
2635
#[cfg(enum)] //~ ERROR expected identifier, found keyword
27-
//~^ WARNING unexpected `cfg` condition name
28-
mod _non_path_kw2 {}
36+
mod _cfg_enum {}
2937
#[cfg(async)] //~ ERROR expected identifier, found keyword
30-
//~^ WARNING unexpected `cfg` condition name
31-
mod _non_path_kw3 {}
38+
mod _cfg_async {}
3239
#[cfg(impl)] //~ ERROR expected identifier, found keyword
33-
//~^ WARNING unexpected `cfg` condition name
34-
mod _non_path_kw4 {}
40+
mod _cfg_impl {}
3541
#[cfg(trait)] //~ ERROR expected identifier, found keyword
36-
//~^ WARNING unexpected `cfg` condition name
37-
mod _non_path_kw5 {}
42+
mod _cfg_trait {}
3843
#[cfg_attr(struct, path = "foo")] //~ ERROR expected identifier, found keyword
39-
//~^ WARNING unexpected `cfg` condition name
40-
mod _non_path_kw6 {}
44+
mod _cfg_attr_struct {}
4145
#[cfg_attr(enum, path = "foo")] //~ ERROR expected identifier, found keyword
42-
//~^ WARNING unexpected `cfg` condition name
43-
mod _non_path_kw7 {}
46+
mod _cfg_attr_enum {}
4447
#[cfg_attr(async, path = "foo")] //~ ERROR expected identifier, found keyword
45-
//~^ WARNING unexpected `cfg` condition name
46-
mod _non_path_kw8 {}
48+
mod _cfg_attr_async {}
4749
#[cfg_attr(impl, path = "foo")] //~ ERROR expected identifier, found keyword
48-
//~^ WARNING unexpected `cfg` condition name
49-
mod _non_path_kw9 {}
50+
mod _cfg_attr_impl {}
5051
#[cfg_attr(trait, path = "foo")] //~ ERROR expected identifier, found keyword
51-
//~^ WARNING unexpected `cfg` condition name
52-
mod _non_path_kw10 {}
52+
mod _cfg_attr_trait {}
5353

5454
fn main() {
5555
foo!();
5656

57-
cfg!(crate); //~ ERROR `cfg` predicate key must be an identifier
58-
cfg!(super); //~ ERROR `cfg` predicate key must be an identifier
59-
cfg!(self); //~ ERROR `cfg` predicate key must be an identifier
60-
cfg!(Self); //~ ERROR `cfg` predicate key must be an identifier
57+
cfg!(crate); //~ ERROR expected identifier, found keyword `crate`
58+
cfg!(super); //~ ERROR expected identifier, found keyword `super`
59+
cfg!(self); //~ ERROR expected identifier, found keyword `self`
60+
cfg!(Self); //~ ERROR expected identifier, found keyword `Self`
6161

6262
cfg!(struct); //~ ERROR expected identifier, found keyword
63-
//~^ WARNING unexpected `cfg` condition name
6463
cfg!(enum); //~ ERROR expected identifier, found keyword
65-
//~^ WARNING unexpected `cfg` condition name
6664
cfg!(async); //~ ERROR expected identifier, found keyword
67-
//~^ WARNING unexpected `cfg` condition name
6865
cfg!(impl); //~ ERROR expected identifier, found keyword
69-
//~^ WARNING unexpected `cfg` condition name
7066
cfg!(trait); //~ ERROR expected identifier, found keyword
71-
//~^ WARNING unexpected `cfg` condition name
7267
}
68+
69+
#[cfg(r#crate)] // Ok
70+
mod _cfg_r_crate {}
71+
#[cfg(r#super)] // Ok
72+
mod _cfg_r_super {}
73+
#[cfg(r#self)] // Ok
74+
mod _cfg_r_self_lower {}
75+
#[cfg(r#Self)] // Ok
76+
mod _cfg_r_self_upper {}

0 commit comments

Comments
 (0)