Skip to content

Commit ed1fb29

Browse files
Auto merge of #150310 - JonathanBrouwer:cfg_trace2, r=<try>
Cfg trace attributes, attempt 2
2 parents 0bd13c3 + 76b5987 commit ed1fb29

File tree

36 files changed

+415
-566
lines changed

36 files changed

+415
-566
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ use rustc_span::source_map::{Spanned, respan};
3434
use rustc_span::{ByteSymbol, DUMMY_SP, ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
3535
use thin_vec::{ThinVec, thin_vec};
3636

37+
use crate::attr::data_structures::CfgEntry;
3738
pub use crate::format::*;
3839
use crate::token::{self, CommentKind, Delimiter};
3940
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
@@ -3390,7 +3391,7 @@ impl NormalAttr {
33903391
item: AttrItem {
33913392
unsafety: Safety::Default,
33923393
path: Path::from_ident(ident),
3393-
args: AttrArgs::Empty,
3394+
args: AttrItemKind::Unparsed(AttrArgs::Empty),
33943395
tokens: None,
33953396
},
33963397
tokens: None,
@@ -3402,11 +3403,46 @@ impl NormalAttr {
34023403
pub struct AttrItem {
34033404
pub unsafety: Safety,
34043405
pub path: Path,
3405-
pub args: AttrArgs,
3406+
pub args: AttrItemKind,
34063407
// Tokens for the meta item, e.g. just the `foo` within `#[foo]` or `#![foo]`.
34073408
pub tokens: Option<LazyAttrTokenStream>,
34083409
}
34093410

3411+
#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
3412+
pub enum AttrItemKind {
3413+
Parsed(EarlyParsedAttribute),
3414+
Unparsed(AttrArgs),
3415+
}
3416+
3417+
impl AttrItemKind {
3418+
pub fn unparsed(self) -> Option<AttrArgs> {
3419+
match self {
3420+
AttrItemKind::Unparsed(args) => Some(args),
3421+
AttrItemKind::Parsed(_) => None,
3422+
}
3423+
}
3424+
3425+
pub fn unparsed_ref(&self) -> Option<&AttrArgs> {
3426+
match self {
3427+
AttrItemKind::Unparsed(args) => Some(args),
3428+
AttrItemKind::Parsed(_) => None,
3429+
}
3430+
}
3431+
3432+
pub fn span(&self) -> Option<Span> {
3433+
match self {
3434+
AttrItemKind::Unparsed(args) => args.span(),
3435+
AttrItemKind::Parsed(_) => None,
3436+
}
3437+
}
3438+
}
3439+
3440+
#[derive(Clone, Encodable, Decodable, Debug, HashStable_Generic)]
3441+
pub enum EarlyParsedAttribute {
3442+
CfgTrace(CfgEntry),
3443+
CfgAttrTrace,
3444+
}
3445+
34103446
impl AttrItem {
34113447
pub fn is_valid_for_outer_style(&self) -> bool {
34123448
self.path == sym::cfg_attr
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use std::fmt;
2+
3+
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
4+
use rustc_span::{Span, Symbol};
5+
use thin_vec::ThinVec;
6+
7+
use crate::attr::version::RustcVersion;
8+
9+
#[derive(Encodable, Decodable, Clone, Debug, PartialEq, Eq, Hash)]
10+
#[derive(HashStable_Generic)]
11+
pub enum CfgEntry {
12+
All(ThinVec<CfgEntry>, Span),
13+
Any(ThinVec<CfgEntry>, Span),
14+
Not(Box<CfgEntry>, Span),
15+
Bool(bool, Span),
16+
NameValue { name: Symbol, value: Option<Symbol>, span: Span },
17+
Version(Option<RustcVersion>, Span),
18+
}
19+
20+
impl CfgEntry {
21+
pub fn span(&self) -> Span {
22+
let (Self::All(_, span)
23+
| Self::Any(_, span)
24+
| Self::Not(_, span)
25+
| Self::Bool(_, span)
26+
| Self::NameValue { span, .. }
27+
| Self::Version(_, span)) = self;
28+
*span
29+
}
30+
31+
/// Same as `PartialEq` but doesn't check spans and ignore order of cfgs.
32+
pub fn is_equivalent_to(&self, other: &Self) -> bool {
33+
match (self, other) {
34+
(Self::All(a, _), Self::All(b, _)) | (Self::Any(a, _), Self::Any(b, _)) => {
35+
a.len() == b.len() && a.iter().all(|a| b.iter().any(|b| a.is_equivalent_to(b)))
36+
}
37+
(Self::Not(a, _), Self::Not(b, _)) => a.is_equivalent_to(b),
38+
(Self::Bool(a, _), Self::Bool(b, _)) => a == b,
39+
(
40+
Self::NameValue { name: name1, value: value1, .. },
41+
Self::NameValue { name: name2, value: value2, .. },
42+
) => name1 == name2 && value1 == value2,
43+
(Self::Version(a, _), Self::Version(b, _)) => a == b,
44+
_ => false,
45+
}
46+
}
47+
}
48+
49+
impl fmt::Display for CfgEntry {
50+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51+
fn write_entries(
52+
name: &str,
53+
entries: &[CfgEntry],
54+
f: &mut fmt::Formatter<'_>,
55+
) -> fmt::Result {
56+
write!(f, "{name}(")?;
57+
for (nb, entry) in entries.iter().enumerate() {
58+
if nb != 0 {
59+
f.write_str(", ")?;
60+
}
61+
entry.fmt(f)?;
62+
}
63+
f.write_str(")")
64+
}
65+
match self {
66+
Self::All(entries, _) => write_entries("all", entries, f),
67+
Self::Any(entries, _) => write_entries("any", entries, f),
68+
Self::Not(entry, _) => write!(f, "not({entry})"),
69+
Self::Bool(value, _) => write!(f, "{value}"),
70+
Self::NameValue { name, value, .. } => {
71+
match value {
72+
// We use `as_str` and debug display to have characters escaped and `"`
73+
// characters surrounding the string.
74+
Some(value) => write!(f, "{name} = {:?}", value.as_str()),
75+
None => write!(f, "{name}"),
76+
}
77+
}
78+
Self::Version(version, _) => match version {
79+
Some(version) => write!(f, "{version}"),
80+
None => Ok(()),
81+
},
82+
}
83+
}
84+
}

compiler/rustc_ast/src/attr/mod.rs

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
//! Functions dealing with attributes and meta items.
22
3+
pub mod data_structures;
4+
pub mod version;
5+
36
use std::fmt::Debug;
47
use std::sync::atomic::{AtomicU32, Ordering};
58

@@ -8,6 +11,7 @@ use rustc_span::{Ident, Span, Symbol, sym};
811
use smallvec::{SmallVec, smallvec};
912
use thin_vec::{ThinVec, thin_vec};
1013

14+
use crate::AttrItemKind;
1115
use crate::ast::{
1216
AttrArgs, AttrId, AttrItem, AttrKind, AttrStyle, AttrVec, Attribute, DUMMY_NODE_ID, DelimArgs,
1317
Expr, ExprKind, LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, NormalAttr, Path,
@@ -62,6 +66,13 @@ impl Attribute {
6266
}
6367
}
6468

69+
pub fn get_mut_normal_item(&mut self) -> &mut AttrItem {
70+
match &mut self.kind {
71+
AttrKind::Normal(normal) => &mut normal.item,
72+
AttrKind::DocComment(..) => panic!("unexpected doc comment"),
73+
}
74+
}
75+
6576
pub fn unwrap_normal_item(self) -> AttrItem {
6677
match self.kind {
6778
AttrKind::Normal(normal) => normal.item,
@@ -77,7 +88,7 @@ impl AttributeExt for Attribute {
7788

7889
fn value_span(&self) -> Option<Span> {
7990
match &self.kind {
80-
AttrKind::Normal(normal) => match &normal.item.args {
91+
AttrKind::Normal(normal) => match &normal.item.args.unparsed_ref()? {
8192
AttrArgs::Eq { expr, .. } => Some(expr.span),
8293
_ => None,
8394
},
@@ -138,7 +149,7 @@ impl AttributeExt for Attribute {
138149

139150
fn is_word(&self) -> bool {
140151
if let AttrKind::Normal(normal) = &self.kind {
141-
matches!(normal.item.args, AttrArgs::Empty)
152+
matches!(normal.item.args, AttrItemKind::Unparsed(AttrArgs::Empty))
142153
} else {
143154
false
144155
}
@@ -294,7 +305,7 @@ impl AttrItem {
294305
}
295306

296307
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
297-
match &self.args {
308+
match &self.args.unparsed_ref()? {
298309
AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => {
299310
MetaItemKind::list_from_tokens(args.tokens.clone())
300311
}
@@ -315,7 +326,7 @@ impl AttrItem {
315326
/// #[attr("value")]
316327
/// ```
317328
fn value_str(&self) -> Option<Symbol> {
318-
match &self.args {
329+
match &self.args.unparsed_ref()? {
319330
AttrArgs::Eq { expr, .. } => match expr.kind {
320331
ExprKind::Lit(token_lit) => {
321332
LitKind::from_token_lit(token_lit).ok().and_then(|lit| lit.str())
@@ -339,7 +350,7 @@ impl AttrItem {
339350
/// #[attr("value")]
340351
/// ```
341352
fn value_span(&self) -> Option<Span> {
342-
match &self.args {
353+
match &self.args.unparsed_ref()? {
343354
AttrArgs::Eq { expr, .. } => Some(expr.span),
344355
AttrArgs::Delimited(_) | AttrArgs::Empty => None,
345356
}
@@ -355,7 +366,7 @@ impl AttrItem {
355366
}
356367

357368
pub fn meta_kind(&self) -> Option<MetaItemKind> {
358-
MetaItemKind::from_attr_args(&self.args)
369+
MetaItemKind::from_attr_args(self.args.unparsed_ref()?)
359370
}
360371
}
361372

@@ -690,7 +701,13 @@ fn mk_attr(
690701
args: AttrArgs,
691702
span: Span,
692703
) -> Attribute {
693-
mk_attr_from_item(g, AttrItem { unsafety, path, args, tokens: None }, None, style, span)
704+
mk_attr_from_item(
705+
g,
706+
AttrItem { unsafety, path, args: AttrItemKind::Unparsed(args), tokens: None },
707+
None,
708+
style,
709+
span,
710+
)
694711
}
695712

696713
pub fn mk_attr_from_item(
Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,10 @@
1-
use std::borrow::Cow;
21
use std::fmt::{self, Display};
32
use std::sync::OnceLock;
43

5-
use rustc_error_messages::{DiagArgValue, IntoDiagArg};
6-
use rustc_macros::{
7-
BlobDecodable, Encodable, HashStable_Generic, PrintAttribute, current_rustc_version,
8-
};
9-
10-
use crate::attrs::PrintAttribute;
4+
use rustc_macros::{BlobDecodable, Encodable, HashStable_Generic, current_rustc_version};
115

126
#[derive(Encodable, BlobDecodable, Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
13-
#[derive(HashStable_Generic, PrintAttribute)]
7+
#[derive(HashStable_Generic)]
148
pub struct RustcVersion {
159
pub major: u16,
1610
pub minor: u16,
@@ -47,9 +41,3 @@ impl Display for RustcVersion {
4741
write!(formatter, "{}.{}.{}", self.major, self.minor, self.patch)
4842
}
4943
}
50-
51-
impl IntoDiagArg for RustcVersion {
52-
fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
53-
DiagArgValue::Str(Cow::Owned(self.to_string()))
54-
}
55-
}

compiler/rustc_ast/src/visit.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,7 @@ macro_rules! common_visitor_and_walkers {
366366
crate::token::LitKind,
367367
crate::tokenstream::LazyAttrTokenStream,
368368
crate::tokenstream::TokenStream,
369+
EarlyParsedAttribute,
369370
Movability,
370371
Mutability,
371372
Pinnedness,
@@ -457,6 +458,7 @@ macro_rules! common_visitor_and_walkers {
457458
ModSpans,
458459
MutTy,
459460
NormalAttr,
461+
AttrItemKind,
460462
Parens,
461463
ParenthesizedArgs,
462464
PatFieldsRest,

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};
@@ -209,6 +209,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
209209
tcx.features(),
210210
registered_tools,
211211
Late,
212+
ShouldEmit::ErrorsAndLints,
212213
),
213214
delayed_lints: Vec::new(),
214215
}

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
694694
}
695695
ast::Safety::Default | ast::Safety::Safe(_) => {}
696696
}
697-
match &item.args {
697+
match &item.args.unparsed_ref().unwrap() {
698698
AttrArgs::Delimited(DelimArgs { dspan: _, delim, tokens }) => self.print_mac_common(
699699
Some(MacHeader::Path(&item.path)),
700700
false,

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 14 additions & 12 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,
@@ -294,11 +295,9 @@ pub fn parse_cfg_attr(
294295
sess: &Session,
295296
features: Option<&Features>,
296297
) -> Option<(CfgEntry, Vec<(AttrItem, Span)>)> {
297-
match cfg_attr.get_normal_item().args {
298-
ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, ref tokens })
299-
if !tokens.is_empty() =>
300-
{
301-
check_cfg_attr_bad_delim(&sess.psess, dspan, delim);
298+
match cfg_attr.get_normal_item().args.unparsed_ref().unwrap() {
299+
ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, tokens }) if !tokens.is_empty() => {
300+
check_cfg_attr_bad_delim(&sess.psess, *dspan, *delim);
302301
match parse_in(&sess.psess, tokens.clone(), "`cfg_attr` input", |p| {
303302
parse_cfg_attr_internal(p, sess, features, cfg_attr)
304303
}) {
@@ -322,7 +321,7 @@ pub fn parse_cfg_attr(
322321
}
323322
_ => {
324323
let (span, reason) = if let ast::AttrArgs::Delimited(ast::DelimArgs { dspan, .. }) =
325-
cfg_attr.get_normal_item().args
324+
cfg_attr.get_normal_item().args.unparsed_ref()?
326325
{
327326
(dspan.entire(), AttributeParseErrorReason::ExpectedAtLeastOneArgument)
328327
} else {
@@ -413,10 +412,13 @@ fn parse_cfg_attr_internal<'a>(
413412
Ok((cfg_predicate, expanded_attrs))
414413
}
415414

416-
fn try_gate_cfg(name: Symbol, span: Span, sess: &Session, features: Option<&Features>) {
415+
fn try_gate_cfg<S: Stage>(name: Symbol, span: Span, cx: &mut AcceptContext<'_, '_, S>) {
416+
if let ShouldEmit::Nothing = cx.should_emit {
417+
return;
418+
}
417419
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);
420+
if let (Some(feats), Some(gated_cfg)) = (cx.features, gate) {
421+
gate_cfg(gated_cfg, span, cx.sess, feats);
420422
}
421423
}
422424

0 commit comments

Comments
 (0)