Skip to content

Commit 3c234ba

Browse files
Auto merge of #150092 - JonathanBrouwer:cfg_trace, r=<try>
[DON'T MERGE] Port `#[cfg]` and `#[cfg_attr]` trace attributes to the new attribute parsers
2 parents 58b270b + e8833aa commit 3c234ba

File tree

18 files changed

+157
-119
lines changed

18 files changed

+157
-119
lines changed

compiler/rustc_ast/src/attr/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ impl Attribute {
6262
}
6363
}
6464

65+
pub fn get_mut_normal_item(&mut self) -> &mut AttrItem {
66+
match &mut self.kind {
67+
AttrKind::Normal(normal) => &mut normal.item,
68+
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
69+
}
70+
}
71+
6572
pub fn unwrap_normal_item(self) -> AttrItem {
6673
match self.kind {
6774
AttrKind::Normal(normal) => normal.item,

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use std::sync::Arc;
4040

4141
use rustc_ast::node_id::NodeMap;
4242
use rustc_ast::{self as ast, *};
43-
use rustc_attr_parsing::{AttributeParser, Late, OmitDoc};
43+
use rustc_attr_parsing::{AttributeParser, Late, OmitDoc, ShouldEmit};
4444
use rustc_data_structures::fingerprint::Fingerprint;
4545
use rustc_data_structures::sorted_map::SortedMap;
4646
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@@ -208,6 +208,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
208208
tcx.features(),
209209
registered_tools,
210210
Late,
211+
ShouldEmit::ErrorsAndLints,
211212
),
212213
delayed_lints: Vec::new(),
213214
}

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ fn parse_cfg_entry_version<S: Stage>(
103103
list: &MetaItemListParser,
104104
meta_span: Span,
105105
) -> Result<CfgEntry, ErrorGuaranteed> {
106-
try_gate_cfg(sym::version, meta_span, cx.sess(), cx.features_option());
106+
try_gate_cfg(sym::version, meta_span, cx);
107107
let Some(version) = list.single() else {
108108
return Err(
109109
cx.emit_err(session_diagnostics::ExpectedSingleVersionLiteral { span: list.span })
@@ -135,7 +135,8 @@ fn parse_cfg_entry_target<S: Stage>(
135135
list: &MetaItemListParser,
136136
meta_span: Span,
137137
) -> Result<CfgEntry, ErrorGuaranteed> {
138-
if let Some(features) = cx.features_option()
138+
if let ShouldEmit::ErrorsAndLints = cx.should_emit
139+
&& let Some(features) = cx.features_option()
139140
&& !features.cfg_target_compact()
140141
{
141142
feature_err(
@@ -180,7 +181,7 @@ pub(crate) fn parse_name_value<S: Stage>(
180181
span: Span,
181182
cx: &mut AcceptContext<'_, '_, S>,
182183
) -> Result<CfgEntry, ErrorGuaranteed> {
183-
try_gate_cfg(name, span, cx.sess(), cx.features_option());
184+
try_gate_cfg(name, span, cx);
184185

185186
let value = match value {
186187
None => None,
@@ -413,10 +414,13 @@ fn parse_cfg_attr_internal<'a>(
413414
Ok((cfg_predicate, expanded_attrs))
414415
}
415416

416-
fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
417+
fn try_gate_cfg<S: Stage>(name: Symbol, span: Span, cx: &mut AcceptContext<'_, '_, S>) {
418+
if let ShouldEmit::Nothing = cx.should_emit {
419+
return;
420+
}
417421
let gate = find_gated_cfg(|sym| sym == name);
418-
if let (Some(feats), Some(gated_cfg)) = (features, gate) {
419-
gate_cfg(gated_cfg, span, sess, feats);
422+
if let (Some(feats), Some(gated_cfg)) = (cx.features, gate) {
423+
gate_cfg(gated_cfg, span, cx.sess, feats);
420424
}
421425
}
422426

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use rustc_feature::AttributeTemplate;
2+
use rustc_hir::attrs::{AttributeKind, CfgEntry};
3+
use rustc_span::{Symbol, sym};
4+
5+
use crate::attributes::{CombineAttributeParser, ConvertFn};
6+
use crate::context::{AcceptContext, Stage};
7+
use crate::parser::ArgParser;
8+
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
9+
use crate::{CFG_TEMPLATE, parse_cfg_entry};
10+
11+
pub(crate) struct CfgTraceParser;
12+
13+
impl<S: Stage> CombineAttributeParser<S> for CfgTraceParser {
14+
const PATH: &[Symbol] = &[sym::cfg_trace];
15+
type Item = CfgEntry;
16+
const CONVERT: ConvertFn<Self::Item> = AttributeKind::CfgTrace;
17+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
18+
const TEMPLATE: AttributeTemplate = CFG_TEMPLATE;
19+
20+
fn extend(
21+
cx: &mut AcceptContext<'_, '_, S>,
22+
args: &ArgParser,
23+
) -> impl IntoIterator<Item = Self::Item> {
24+
let Some(list) = args.list() else {
25+
return None;
26+
};
27+
let Some(entry) = list.single() else {
28+
return None;
29+
};
30+
31+
parse_cfg_entry(cx, entry).ok()
32+
}
33+
}
34+
35+
pub(crate) struct CfgAttrTraceParser;
36+
37+
impl<S: Stage> CombineAttributeParser<S> for CfgAttrTraceParser {
38+
const PATH: &[Symbol] = &[sym::cfg_attr_trace];
39+
type Item = ();
40+
const CONVERT: ConvertFn<Self::Item> = AttributeKind::CfgAttrTrace;
41+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
42+
const TEMPLATE: AttributeTemplate = CFG_TEMPLATE;
43+
44+
fn extend(
45+
_cx: &mut AcceptContext<'_, '_, S>,
46+
_args: &ArgParser,
47+
) -> impl IntoIterator<Item = Self::Item> {
48+
Some(())
49+
}
50+
}

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pub(crate) mod allow_unstable;
3333
pub(crate) mod body;
3434
pub(crate) mod cfg;
3535
pub(crate) mod cfg_select;
36+
pub(crate) mod cfg_trace;
3637
pub(crate) mod codegen_attrs;
3738
pub(crate) mod confusables;
3839
pub(crate) mod crate_level;

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 7 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,11 @@ use std::sync::LazyLock;
55

66
use private::Sealed;
77
use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
8-
use rustc_errors::{Diag, Diagnostic, Level};
8+
use rustc_errors::{Diag, Level};
99
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate};
1010
use rustc_hir::attrs::AttributeKind;
1111
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
1212
use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
13-
use rustc_session::Session;
1413
use rustc_session::lint::{Lint, LintId};
1514
use rustc_span::{ErrorGuaranteed, Span, Symbol};
1615

@@ -19,6 +18,7 @@ use crate::attributes::allow_unstable::{
1918
AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
2019
};
2120
use crate::attributes::body::CoroutineParser;
21+
use crate::attributes::cfg_trace::{CfgAttrTraceParser, CfgTraceParser};
2222
use crate::attributes::codegen_attrs::{
2323
ColdParser, CoverageParser, EiiExternItemParser, ExportNameParser, ForceTargetFeatureParser,
2424
NakedParser, NoMangleParser, ObjcClassParser, ObjcSelectorParser, OptimizeParser,
@@ -175,6 +175,8 @@ attribute_parsers!(
175175
// tidy-alphabetical-start
176176
Combine<AllowConstFnUnstableParser>,
177177
Combine<AllowInternalUnstableParser>,
178+
Combine<CfgAttrTraceParser>,
179+
Combine<CfgTraceParser>,
178180
Combine<DebuggerViualizerParser>,
179181
Combine<ForceTargetFeatureParser>,
180182
Combine<LinkParser>,
@@ -279,14 +281,6 @@ pub trait Stage: Sized + 'static + Sealed {
279281

280282
fn parsers() -> &'static GroupType<Self>;
281283

282-
fn emit_err<'sess>(
283-
&self,
284-
sess: &'sess Session,
285-
diag: impl for<'x> Diagnostic<'x>,
286-
) -> ErrorGuaranteed;
287-
288-
fn should_emit(&self) -> ShouldEmit;
289-
290284
fn id_is_crate_root(id: Self::Id) -> bool;
291285
}
292286

@@ -298,17 +292,6 @@ impl Stage for Early {
298292
fn parsers() -> &'static GroupType<Self> {
299293
&early::ATTRIBUTE_PARSERS
300294
}
301-
fn emit_err<'sess>(
302-
&self,
303-
sess: &'sess Session,
304-
diag: impl for<'x> Diagnostic<'x>,
305-
) -> ErrorGuaranteed {
306-
self.should_emit().emit_err(sess.dcx().create_err(diag))
307-
}
308-
309-
fn should_emit(&self) -> ShouldEmit {
310-
self.emit_errors
311-
}
312295

313296
fn id_is_crate_root(id: Self::Id) -> bool {
314297
id == CRATE_NODE_ID
@@ -323,30 +306,15 @@ impl Stage for Late {
323306
fn parsers() -> &'static GroupType<Self> {
324307
&late::ATTRIBUTE_PARSERS
325308
}
326-
fn emit_err<'sess>(
327-
&self,
328-
tcx: &'sess Session,
329-
diag: impl for<'x> Diagnostic<'x>,
330-
) -> ErrorGuaranteed {
331-
tcx.dcx().emit_err(diag)
332-
}
333-
334-
fn should_emit(&self) -> ShouldEmit {
335-
ShouldEmit::ErrorsAndLints
336-
}
337309

338310
fn id_is_crate_root(id: Self::Id) -> bool {
339311
id == CRATE_HIR_ID
340312
}
341313
}
342314

343315
/// used when parsing attributes for miscellaneous things *before* ast lowering
344-
pub struct Early {
345-
/// Whether to emit errors or delay them as a bug
346-
/// For most attributes, the attribute will be parsed again in the `Late` stage and in this case the errors should be delayed
347-
/// But for some, such as `cfg`, the attribute will be removed before the `Late` stage so errors must be emitted
348-
pub emit_errors: ShouldEmit,
349-
}
316+
pub struct Early;
317+
350318
/// used when parsing attributes during ast lowering
351319
pub struct Late;
352320

@@ -383,16 +351,12 @@ pub struct AcceptContext<'f, 'sess, S: Stage> {
383351
}
384352

385353
impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
386-
pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
387-
self.stage.emit_err(&self.sess, diag)
388-
}
389-
390354
/// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing
391355
/// must be delayed until after HIR is built. This method will take care of the details of
392356
/// that.
393357
pub(crate) fn emit_lint(&mut self, lint: &'static Lint, kind: AttributeLintKind, span: Span) {
394358
if !matches!(
395-
self.stage.should_emit(),
359+
self.should_emit,
396360
ShouldEmit::ErrorsAndLints | ShouldEmit::EarlyFatal { also_emit_lints: true }
397361
) {
398362
return;

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ use std::convert::identity;
33
use rustc_ast as ast;
44
use rustc_ast::token::DocFragmentKind;
55
use rustc_ast::{AttrStyle, NodeId, Safety};
6-
use rustc_errors::DiagCtxtHandle;
6+
use rustc_errors::{DiagCtxtHandle, Diagnostic};
77
use rustc_feature::{AttributeTemplate, Features};
88
use rustc_hir::attrs::AttributeKind;
99
use rustc_hir::lints::AttributeLint;
1010
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, Target};
1111
use rustc_session::Session;
1212
use rustc_session::lint::BuiltinLintDiag;
13-
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
13+
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
1414

1515
use crate::context::{AcceptContext, FinalizeContext, SharedContext, Stage};
1616
use crate::parser::{ArgParser, PathParser, RefPathParser};
@@ -23,7 +23,8 @@ pub struct AttributeParser<'sess, S: Stage = Late> {
2323
pub(crate) tools: Vec<Symbol>,
2424
pub(crate) features: Option<&'sess Features>,
2525
pub(crate) sess: &'sess Session,
26-
pub(crate) stage: S,
26+
pub(crate) _stage: S,
27+
pub(crate) should_emit: ShouldEmit,
2728

2829
/// *Only* parse attributes with this symbol.
2930
///
@@ -105,10 +106,10 @@ impl<'sess> AttributeParser<'sess, Early> {
105106
target_span: Span,
106107
target_node_id: NodeId,
107108
features: Option<&'sess Features>,
108-
emit_errors: ShouldEmit,
109+
should_emit: ShouldEmit,
109110
) -> Vec<Attribute> {
110111
let mut p =
111-
Self { features, tools: Vec::new(), parse_only, sess, stage: Early { emit_errors } };
112+
Self { features, tools: Vec::new(), parse_only, sess, _stage: Early, should_emit };
112113
p.parse_attribute_list(
113114
attrs,
114115
target_span,
@@ -179,7 +180,7 @@ impl<'sess> AttributeParser<'sess, Early> {
179180
target_span: Span,
180181
target_node_id: NodeId,
181182
features: Option<&'sess Features>,
182-
emit_errors: ShouldEmit,
183+
should_emit: ShouldEmit,
183184
args: &I,
184185
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> T,
185186
template: &AttributeTemplate,
@@ -189,7 +190,8 @@ impl<'sess> AttributeParser<'sess, Early> {
189190
tools: Vec::new(),
190191
parse_only: None,
191192
sess,
192-
stage: Early { emit_errors },
193+
_stage: Early,
194+
should_emit,
193195
};
194196
let mut emit_lint = |lint: AttributeLint<NodeId>| {
195197
sess.psess.buffer_lint(
@@ -232,8 +234,9 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
232234
features: &'sess Features,
233235
tools: Vec<Symbol>,
234236
stage: S,
237+
should_emit: ShouldEmit,
235238
) -> Self {
236-
Self { features: Some(features), tools, parse_only: None, sess, stage }
239+
Self { features: Some(features), tools, parse_only: None, sess, _stage: stage, should_emit }
237240
}
238241

239242
pub(crate) fn sess(&self) -> &'sess Session {
@@ -252,6 +255,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
252255
self.sess().dcx()
253256
}
254257

258+
pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {
259+
self.should_emit.emit_err(self.dcx().create_err(diag))
260+
}
261+
255262
/// Parse a list of attributes.
256263
///
257264
/// `target_span` is the span of the thing this list of attributes is applied to,
@@ -263,14 +270,16 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
263270
target_id: S::Id,
264271
target: Target,
265272
omit_doc: OmitDoc,
266-
267273
lower_span: impl Copy + Fn(Span) -> Span,
268274
mut emit_lint: impl FnMut(AttributeLint<S::Id>),
269275
) -> Vec<Attribute> {
270276
let mut attributes = Vec::new();
271277
let mut attr_paths: Vec<RefPathParser<'_>> = Vec::new();
278+
let old_should_emit = self.should_emit;
272279

273280
for attr in attrs {
281+
self.should_emit = old_should_emit; //FIXME ugly solution
282+
274283
// If we're only looking for a single attribute, skip all the ones we don't care about.
275284
if let Some(expected) = self.parse_only {
276285
if !attr.has_name(expected) {
@@ -305,6 +314,11 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
305314
attr_paths.push(PathParser(&n.item.path));
306315
let attr_path = AttrPath::from_ast(&n.item.path, lower_span);
307316

317+
// Don't emit anything for trace attributes
318+
if attr.has_any_name(&[sym::cfg_trace, sym::cfg_attr_trace]) {
319+
self.should_emit = ShouldEmit::Nothing;
320+
}
321+
308322
self.check_attribute_safety(
309323
&attr_path,
310324
lower_span(n.item.span()),
@@ -321,7 +335,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
321335
&n.item.args,
322336
&parts,
323337
&self.sess.psess,
324-
self.stage.should_emit(),
338+
self.should_emit,
325339
) else {
326340
continue;
327341
};
@@ -374,9 +388,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
374388
};
375389

376390
(accept.accept_fn)(&mut cx, &args);
377-
if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
378-
Self::check_target(&accept.allowed_targets, target, &mut cx);
379-
}
391+
Self::check_target(&accept.allowed_targets, target, &mut cx);
380392
}
381393
} else {
382394
// If we're here, we must be compiling a tool attribute... Or someone

compiler/rustc_attr_parsing/src/parser.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,10 @@ impl ArgParser {
120120
}
121121

122122
if args.delim != Delimiter::Parenthesis {
123-
psess.dcx().emit_err(MetaBadDelim {
123+
should_emit.emit_err(psess.dcx().create_err(MetaBadDelim {
124124
span: args.dspan.entire(),
125125
sugg: MetaBadDelimSugg { open: args.dspan.open, close: args.dspan.close },
126-
});
126+
}));
127127
return None;
128128
}
129129

0 commit comments

Comments
 (0)