Skip to content

Commit 97cd2c7

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

File tree

13 files changed

+179
-289
lines changed

13 files changed

+179
-289
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: 4 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+
parsing_cfg: bool,
121122
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> Option<T>,
122123
template: &AttributeTemplate,
123124
) -> Option<T> {
@@ -133,7 +134,8 @@ 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 =
138+
MetaItemParser::from_attr(normal_attr, &parts, &sess.psess, emit_errors, parsing_cfg)?;
137139
let path = meta_parser.path();
138140
let args = meta_parser.args();
139141
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
@@ -251,6 +253,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
251253
&parts,
252254
&self.sess.psess,
253255
self.stage.should_emit(),
256+
false,
254257
) else {
255258
continue;
256259
};

compiler/rustc_attr_parsing/src/parser.rs

Lines changed: 21 additions & 3 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+
parsing_cfg: 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, parsing_cfg)?)
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+
parsing_cfg: 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+
parsing_cfg,
262+
)?,
255263
})
256264
}
257265
}
@@ -425,7 +433,12 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
425433
};
426434
}
427435

428-
let path = self.parser.parse_path(PathStyle::Mod)?;
436+
let path = if self.parser.parse_cfg_pred {
437+
self.parser.parse_cfg_pred = false;
438+
Path::from_ident(self.parser.parse_ident()?)
439+
} else {
440+
self.parser.parse_path(PathStyle::Mod)?
441+
};
429442

430443
// Check style of arguments that this meta item has
431444
let args = if self.parser.check(exp!(OpenParen)) {
@@ -513,8 +526,11 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
513526
psess: &'sess ParseSess,
514527
span: Span,
515528
should_emit: ShouldEmit,
529+
parsing_cfg: bool,
516530
) -> PResult<'sess, MetaItemListParser<'static>> {
517531
let mut parser = Parser::new(psess, tokens, None);
532+
parser.parse_cfg_pred = parsing_cfg;
533+
518534
let mut this = MetaItemListParserContext { parser: &mut parser, should_emit };
519535

520536
// Presumably, the majority of the time there will only be one attr.
@@ -546,12 +562,14 @@ impl<'a> MetaItemListParser<'a> {
546562
delim: &'a DelimArgs,
547563
psess: &'sess ParseSess,
548564
should_emit: ShouldEmit,
565+
parsing_cfg: bool,
549566
) -> Option<Self> {
550567
match MetaItemListParserContext::parse(
551568
delim.tokens.clone(),
552569
psess,
553570
delim.dspan.entire(),
554571
should_emit,
572+
parsing_cfg,
555573
) {
556574
Ok(s) => Some(s),
557575
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_interface/src/interface.rs

Lines changed: 21 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -71,27 +71,31 @@ pub(crate) fn parse_cfg(dcx: DiagCtxtHandle<'_>, cfgs: Vec<String>) -> Cfg {
7171

7272
match new_parser_from_source_str(&psess, filename, s.to_string(), StripTokens::Nothing)
7373
{
74-
Ok(mut parser) => match parser.parse_meta_item(AllowLeadingUnsafe::No) {
75-
Ok(meta_item) if parser.token == token::Eof => {
76-
if meta_item.path.segments.len() != 1 {
77-
error!("argument key must be an identifier");
78-
}
79-
match &meta_item.kind {
80-
MetaItemKind::List(..) => {}
81-
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
82-
error!("argument value must be a string");
74+
Ok(mut parser) => {
75+
parser.parse_cfg_pred = true;
76+
77+
match parser.parse_meta_item(AllowLeadingUnsafe::No) {
78+
Ok(meta_item) if parser.token == token::Eof => {
79+
if meta_item.path.segments.len() != 1 {
80+
error!("argument key must be an identifier");
8381
}
84-
MetaItemKind::NameValue(..) | MetaItemKind::Word => {
85-
let ident = meta_item.ident().expect("multi-segment cfg key");
86-
return (ident.name, meta_item.value_str());
82+
match &meta_item.kind {
83+
MetaItemKind::List(..) => {}
84+
MetaItemKind::NameValue(lit) if !lit.kind.is_str() => {
85+
error!("argument value must be a string");
86+
}
87+
MetaItemKind::NameValue(..) | MetaItemKind::Word => {
88+
let ident = meta_item.ident().expect("multi-segment cfg key");
89+
return (ident.name, meta_item.value_str());
90+
}
8791
}
8892
}
93+
Ok(..) => {}
94+
Err(err) => err.cancel(),
8995
}
90-
Ok(..) => {}
91-
Err(err) => err.cancel(),
92-
},
96+
}
9397
Err(errs) => errs.into_iter().for_each(|err| err.cancel()),
94-
}
98+
};
9599

96100
// If the user tried to use a key="value" flag, but is missing the quotes, provide
97101
// a hint about how to resolve this.
@@ -177,6 +181,7 @@ pub(crate) fn parse_check_cfg(dcx: DiagCtxtHandle<'_>, specs: Vec<String>) -> Ch
177181
expected_error();
178182
}
179183
};
184+
parser.parse_cfg_pred = true;
180185

181186
let meta_item = match parser.parse_meta_item(AllowLeadingUnsafe::No) {
182187
Ok(meta_item) if parser.token == token::Eof => meta_item,

compiler/rustc_parse/src/parser/attr.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use rustc_ast as ast;
22
use rustc_ast::token::{self, MetaVarKind};
33
use rustc_ast::tokenstream::ParserRange;
4-
use rustc_ast::{Attribute, attr};
4+
use rustc_ast::{Attribute, Path, attr};
55
use rustc_errors::codes::*;
66
use rustc_errors::{Diag, PResult};
77
use rustc_span::{BytePos, Span};
@@ -381,6 +381,7 @@ impl<'a> Parser<'a> {
381381
pub fn parse_cfg_attr(
382382
&mut self,
383383
) -> PResult<'a, (ast::MetaItemInner, Vec<(ast::AttrItem, Span)>)> {
384+
self.parse_cfg_pred = true;
384385
let cfg_predicate = self.parse_meta_item_inner()?;
385386
self.expect(exp!(Comma))?;
386387

@@ -449,7 +450,13 @@ impl<'a> Parser<'a> {
449450
ast::Safety::Default
450451
};
451452

452-
let path = self.parse_path(PathStyle::Mod)?;
453+
let path = if self.parse_cfg_pred {
454+
self.parse_cfg_pred = false;
455+
Path::from_ident(self.parse_ident()?)
456+
} else {
457+
self.parse_path(PathStyle::Mod)?
458+
};
459+
453460
let kind = self.parse_meta_item_kind()?;
454461
if is_unsafe {
455462
self.expect(exp!(CloseParen))?;

compiler/rustc_parse/src/parser/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ pub struct Parser<'a> {
181181
/// The previous token.
182182
pub prev_token: Token,
183183
pub capture_cfg: bool,
184+
pub parse_cfg_pred: bool,
184185
restrictions: Restrictions,
185186
expected_token_types: TokenTypeSet,
186187
token_cursor: TokenCursor,
@@ -372,6 +373,7 @@ impl<'a> Parser<'a> {
372373
},
373374
current_closure: None,
374375
recovery: Recovery::Allowed,
376+
parse_cfg_pred: false,
375377
};
376378

377379
// Make parser point to the first token.

0 commit comments

Comments
 (0)