Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 621e96b

Browse files
committed
Encode one level of cfg_attr in attr_id
1 parent 6872304 commit 621e96b

File tree

11 files changed

+99
-52
lines changed

11 files changed

+99
-52
lines changed

crates/hir-def/src/attr.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ impl AttrSourceMap {
546546
}
547547

548548
fn source_of_id(&self, id: AttrId) -> InFile<&Either<ast::Attr, ast::Comment>> {
549-
let ast_idx = id.ast_index as usize;
549+
let ast_idx = id.ast_index();
550550
let file_id = match self.mod_def_site_file_id {
551551
Some((file_id, def_site_cut)) if def_site_cut <= ast_idx => file_id,
552552
_ => self.file_id,

crates/hir-def/src/child_by_source.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ impl ChildBySource for ItemScope {
117117
let adt = ast_id.to_node(db.upcast());
118118
calls.for_each(|(attr_id, call_id, calls)| {
119119
if let Some(Either::Left(attr)) =
120-
adt.doc_comments_and_attrs().nth(attr_id.ast_index as usize)
120+
adt.doc_comments_and_attrs().nth(attr_id.ast_index())
121121
{
122122
res[keys::DERIVE_MACRO_CALL].insert(attr, (attr_id, call_id, calls.into()));
123123
}

crates/hir-def/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -941,7 +941,7 @@ pub fn macro_id_to_def_id(db: &dyn db::DefDatabase, id: MacroId) -> MacroDefId {
941941
fn derive_macro_as_call_id(
942942
db: &dyn db::DefDatabase,
943943
item_attr: &AstIdWithPath<ast::Adt>,
944-
derive_attr: AttrId,
944+
derive_attr_index: AttrId,
945945
derive_pos: u32,
946946
krate: CrateId,
947947
resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>,
@@ -954,7 +954,7 @@ fn derive_macro_as_call_id(
954954
MacroCallKind::Derive {
955955
ast_id: item_attr.ast_id,
956956
derive_index: derive_pos,
957-
derive_attr_index: derive_attr.ast_index,
957+
derive_attr_index,
958958
},
959959
);
960960
Ok((macro_id, def_id, call_id))
@@ -982,7 +982,7 @@ fn attr_macro_as_call_id(
982982
MacroCallKind::Attr {
983983
ast_id: item_attr.ast_id,
984984
attr_args: Arc::new(arg),
985-
invoc_attr_index: macro_attr.id.ast_index,
985+
invoc_attr_index: macro_attr.id,
986986
is_derive,
987987
},
988988
);

crates/hir-def/src/nameres/collector.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,7 @@ impl DefCollector<'_> {
452452
MacroCallKind::Attr {
453453
ast_id: ast_id.ast_id,
454454
attr_args: Default::default(),
455-
invoc_attr_index: attr.id.ast_index,
455+
invoc_attr_index: attr.id,
456456
is_derive: false,
457457
},
458458
attr.path().clone(),
@@ -1407,7 +1407,7 @@ impl DefCollector<'_> {
14071407
directive.module_id,
14081408
MacroCallKind::Derive {
14091409
ast_id: ast_id.ast_id,
1410-
derive_attr_index: derive_attr.ast_index,
1410+
derive_attr_index: *derive_attr,
14111411
derive_index: *derive_pos as u32,
14121412
},
14131413
ast_id.path.clone(),

crates/hir-def/src/nameres/diagnostics.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ pub enum DefDiagnosticKind {
3131

3232
UnimplementedBuiltinMacro { ast: AstId<ast::Macro> },
3333

34-
InvalidDeriveTarget { ast: AstId<ast::Item>, id: u32 },
34+
InvalidDeriveTarget { ast: AstId<ast::Item>, id: usize },
3535

36-
MalformedDerive { ast: AstId<ast::Adt>, id: u32 },
36+
MalformedDerive { ast: AstId<ast::Adt>, id: usize },
3737
}
3838

3939
#[derive(Debug, PartialEq, Eq)]
@@ -119,7 +119,7 @@ impl DefDiagnostic {
119119
) -> Self {
120120
Self {
121121
in_module: container,
122-
kind: DefDiagnosticKind::InvalidDeriveTarget { ast, id: id.ast_index },
122+
kind: DefDiagnosticKind::InvalidDeriveTarget { ast, id: id.ast_index() },
123123
}
124124
}
125125

@@ -130,7 +130,7 @@ impl DefDiagnostic {
130130
) -> Self {
131131
Self {
132132
in_module: container,
133-
kind: DefDiagnosticKind::MalformedDerive { ast, id: id.ast_index },
133+
kind: DefDiagnosticKind::MalformedDerive { ast, id: id.ast_index() },
134134
}
135135
}
136136
}

crates/hir-expand/src/attrs.rs

Lines changed: 56 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
//! A higher level attributes based on TokenTree, with also some shortcuts.
12
use std::{fmt, ops, sync::Arc};
23

34
use base_db::CrateId;
@@ -65,14 +66,16 @@ impl RawAttrs {
6566
(None, entries @ Some(_)) => Self { entries },
6667
(Some(entries), None) => Self { entries: Some(entries.clone()) },
6768
(Some(a), Some(b)) => {
68-
let last_ast_index = a.last().map_or(0, |it| it.id.ast_index + 1);
69+
let last_ast_index = a.last().map_or(0, |it| it.id.ast_index() + 1) as u32;
6970
Self {
7071
entries: Some(
7172
a.iter()
7273
.cloned()
7374
.chain(b.iter().map(|it| {
7475
let mut it = it.clone();
75-
it.id.ast_index += last_ast_index;
76+
it.id.id = it.id.ast_index() as u32 + last_ast_index
77+
| (it.id.cfg_attr_index().unwrap_or(0) as u32)
78+
<< AttrId::AST_INDEX_BITS;
7679
it
7780
}))
7881
.collect(),
@@ -83,6 +86,7 @@ impl RawAttrs {
8386
}
8487

8588
/// Processes `cfg_attr`s, returning the resulting semantic `Attrs`.
89+
// FIXME: This should return a different type
8690
pub fn filter(self, db: &dyn AstDatabase, krate: CrateId) -> RawAttrs {
8791
let has_cfg_attrs = self
8892
.iter()
@@ -106,27 +110,22 @@ impl RawAttrs {
106110
_ => return smallvec![attr.clone()],
107111
};
108112

109-
// Input subtree is: `(cfg, $(attr),+)`
110-
// Split it up into a `cfg` subtree and the `attr` subtrees.
111-
// FIXME: There should be a common API for this.
112-
let mut parts = subtree.token_trees.split(|tt| {
113-
matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. })))
114-
});
115-
let cfg = match parts.next() {
113+
let (cfg, parts) = match parse_cfg_attr_input(subtree) {
116114
Some(it) => it,
117-
None => return smallvec![],
115+
None => return smallvec![attr.clone()],
118116
};
119-
let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
120-
let cfg = CfgExpr::parse(&cfg);
121117
let index = attr.id;
122-
let attrs = parts.filter(|a| !a.is_empty()).filter_map(|attr| {
123-
let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
124-
// FIXME hygiene
125-
let hygiene = Hygiene::new_unhygienic();
126-
Attr::from_tt(db, &tree, &hygiene, index)
127-
});
118+
let attrs =
119+
parts.enumerate().take(1 << AttrId::CFG_ATTR_BITS).filter_map(|(idx, attr)| {
120+
let tree = Subtree { delimiter: None, token_trees: attr.to_vec() };
121+
// FIXME hygiene
122+
let hygiene = Hygiene::new_unhygienic();
123+
Attr::from_tt(db, &tree, &hygiene, index.with_cfg_attr(idx))
124+
});
128125

129126
let cfg_options = &crate_graph[krate].cfg_options;
127+
let cfg = Subtree { delimiter: subtree.delimiter, token_trees: cfg.to_vec() };
128+
let cfg = CfgExpr::parse(&cfg);
130129
if cfg_options.check(&cfg) == Some(false) {
131130
smallvec![]
132131
} else {
@@ -143,7 +142,32 @@ impl RawAttrs {
143142

144143
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
145144
pub struct AttrId {
146-
pub ast_index: u32,
145+
id: u32,
146+
}
147+
148+
// FIXME: This only handles a single level of cfg_attr nesting
149+
// that is `#[cfg_attr(all(), cfg_attr(all(), cfg(any())))]` breaks again
150+
impl AttrId {
151+
const CFG_ATTR_BITS: usize = 7;
152+
const AST_INDEX_MASK: usize = 0x00FF_FFFF;
153+
const AST_INDEX_BITS: usize = Self::AST_INDEX_MASK.count_ones() as usize;
154+
const CFG_ATTR_SET_BITS: u32 = 1 << 31;
155+
156+
pub fn ast_index(&self) -> usize {
157+
self.id as usize & Self::AST_INDEX_MASK
158+
}
159+
160+
pub fn cfg_attr_index(&self) -> Option<usize> {
161+
if self.id & Self::CFG_ATTR_SET_BITS == 0 {
162+
None
163+
} else {
164+
Some(self.id as usize >> Self::AST_INDEX_BITS)
165+
}
166+
}
167+
168+
pub fn with_cfg_attr(self, idx: usize) -> AttrId {
169+
AttrId { id: self.id | (idx as u32) << Self::AST_INDEX_BITS | Self::CFG_ATTR_SET_BITS }
170+
}
147171
}
148172

149173
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -272,10 +296,7 @@ pub fn collect_attrs(
272296
Either::Left(attr) => attr.kind().is_outer(),
273297
Either::Right(comment) => comment.is_outer(),
274298
});
275-
outer_attrs
276-
.chain(inner_attrs)
277-
.enumerate()
278-
.map(|(id, attr)| (AttrId { ast_index: id as u32 }, attr))
299+
outer_attrs.chain(inner_attrs).enumerate().map(|(id, attr)| (AttrId { id: id as u32 }, attr))
279300
}
280301

281302
fn inner_attributes(
@@ -311,3 +332,15 @@ fn inner_attributes(
311332
});
312333
Some(attrs)
313334
}
335+
336+
// Input subtree is: `(cfg, $(attr),+)`
337+
// Split it up into a `cfg` subtree and the `attr` subtrees.
338+
pub fn parse_cfg_attr_input(
339+
subtree: &Subtree,
340+
) -> Option<(&[tt::TokenTree], impl Iterator<Item = &[tt::TokenTree]>)> {
341+
let mut parts = subtree
342+
.token_trees
343+
.split(|tt| matches!(tt, tt::TokenTree::Leaf(tt::Leaf::Punct(Punct { char: ',', .. }))));
344+
let cfg = parts.next()?;
345+
Some((cfg, parts.filter(|it| !it.is_empty())))
346+
}

crates/hir-expand/src/db.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,9 @@ pub fn expand_speculative(
168168
// Attributes may have an input token tree, build the subtree and map for this as well
169169
// then try finding a token id for our token if it is inside this input subtree.
170170
let item = ast::Item::cast(speculative_args.clone())?;
171-
item.doc_comments_and_attrs().nth(invoc_attr_index as usize).and_then(Either::left)
171+
item.doc_comments_and_attrs()
172+
.nth(invoc_attr_index.ast_index())
173+
.and_then(Either::left)
172174
}?;
173175
match attr.token_tree() {
174176
Some(token_tree) => {
@@ -321,14 +323,15 @@ fn macro_arg(
321323
}
322324

323325
fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<SyntaxNode> {
326+
// FIXME: handle `cfg_attr`
324327
(|| {
325328
let censor = match loc.kind {
326329
MacroCallKind::FnLike { .. } => return None,
327330
MacroCallKind::Derive { derive_attr_index, .. } => {
328331
cov_mark::hit!(derive_censoring);
329332
ast::Item::cast(node.clone())?
330333
.attrs()
331-
.take(derive_attr_index as usize + 1)
334+
.take(derive_attr_index.ast_index() + 1)
332335
// FIXME, this resolution should not be done syntactically
333336
// derive is a proper macro now, no longer builtin
334337
// But we do not have resolution at this stage, this means
@@ -343,7 +346,7 @@ fn censor_for_macro_input(loc: &MacroCallLoc, node: &SyntaxNode) -> FxHashSet<Sy
343346
cov_mark::hit!(attribute_macro_attr_censoring);
344347
ast::Item::cast(node.clone())?
345348
.doc_comments_and_attrs()
346-
.nth(invoc_attr_index as usize)
349+
.nth(invoc_attr_index.ast_index())
347350
.and_then(Either::left)
348351
.map(|attr| attr.syntax().clone())
349352
.into_iter()

crates/hir-expand/src/hygiene.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ fn make_hygiene_info(
191191
let tt = ast_id
192192
.to_node(db)
193193
.doc_comments_and_attrs()
194-
.nth(invoc_attr_index as usize)
194+
.nth(invoc_attr_index.ast_index())
195195
.and_then(Either::left)?
196196
.token_tree()?;
197197
Some(InFile::new(ast_id.file_id, tt))

crates/hir-expand/src/lib.rs

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ use syntax::{
3838

3939
use crate::{
4040
ast_id_map::FileAstId,
41+
attrs::AttrId,
4142
builtin_attr_macro::BuiltinAttrExpander,
4243
builtin_derive_macro::BuiltinDeriveExpander,
4344
builtin_fn_macro::{BuiltinFnLikeExpander, EagerExpander},
@@ -146,7 +147,7 @@ pub enum MacroCallKind {
146147
///
147148
/// Outer attributes are counted first, then inner attributes. This does not support
148149
/// out-of-line modules, which may have attributes spread across 2 files!
149-
derive_attr_index: u32,
150+
derive_attr_index: AttrId,
150151
/// Index of the derive macro in the derive attribute
151152
derive_index: u32,
152153
},
@@ -157,7 +158,7 @@ pub enum MacroCallKind {
157158
///
158159
/// Outer attributes are counted first, then inner attributes. This does not support
159160
/// out-of-line modules, which may have attributes spread across 2 files!
160-
invoc_attr_index: u32,
161+
invoc_attr_index: AttrId,
161162
/// Whether this attribute is the `#[derive]` attribute.
162163
is_derive: bool,
163164
},
@@ -262,10 +263,11 @@ impl HirFileId {
262263
});
263264
let attr_input_or_mac_def = def.or_else(|| match loc.kind {
264265
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => {
266+
// FIXME: handle `cfg_attr`
265267
let tt = ast_id
266268
.to_node(db)
267269
.doc_comments_and_attrs()
268-
.nth(invoc_attr_index as usize)
270+
.nth(invoc_attr_index.ast_index())
269271
.and_then(Either::left)?
270272
.token_tree()?;
271273
Some(InFile::new(ast_id.file_id, tt))
@@ -398,8 +400,7 @@ impl MacroDefId {
398400
}
399401
}
400402

401-
// FIXME: attribute indices do not account for `cfg_attr`, which means that we'll strip the whole
402-
// `cfg_attr` instead of just one of the attributes it expands to
403+
// FIXME: attribute indices do not account for nested `cfg_attr`
403404

404405
impl MacroCallKind {
405406
/// Returns the file containing the macro invocation.
@@ -420,7 +421,7 @@ impl MacroCallKind {
420421
// FIXME: handle `cfg_attr`
421422
ast_id.with_value(ast_id.to_node(db)).map(|it| {
422423
it.doc_comments_and_attrs()
423-
.nth(*derive_attr_index as usize)
424+
.nth(derive_attr_index.ast_index())
424425
.and_then(|it| match it {
425426
Either::Left(attr) => Some(attr.syntax().clone()),
426427
Either::Right(_) => None,
@@ -432,7 +433,7 @@ impl MacroCallKind {
432433
// FIXME: handle `cfg_attr`
433434
ast_id.with_value(ast_id.to_node(db)).map(|it| {
434435
it.doc_comments_and_attrs()
435-
.nth(*invoc_attr_index as usize)
436+
.nth(invoc_attr_index.ast_index())
436437
.and_then(|it| match it {
437438
Either::Left(attr) => Some(attr.syntax().clone()),
438439
Either::Right(_) => None,
@@ -489,19 +490,21 @@ impl MacroCallKind {
489490
MacroCallKind::FnLike { ast_id, .. } => ast_id.to_node(db).syntax().text_range(),
490491
MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
491492
// FIXME: should be the range of the macro name, not the whole derive
493+
// FIXME: handle `cfg_attr`
492494
ast_id
493495
.to_node(db)
494496
.doc_comments_and_attrs()
495-
.nth(derive_attr_index as usize)
497+
.nth(derive_attr_index.ast_index())
496498
.expect("missing derive")
497499
.expect_left("derive is a doc comment?")
498500
.syntax()
499501
.text_range()
500502
}
503+
// FIXME: handle `cfg_attr`
501504
MacroCallKind::Attr { ast_id, invoc_attr_index, .. } => ast_id
502505
.to_node(db)
503506
.doc_comments_and_attrs()
504-
.nth(invoc_attr_index as usize)
507+
.nth(invoc_attr_index.ast_index())
505508
.expect("missing attribute")
506509
.expect_left("attribute macro is a doc comment?")
507510
.syntax()
@@ -593,9 +596,10 @@ impl ExpansionInfo {
593596
let token_range = token.value.text_range();
594597
match &loc.kind {
595598
MacroCallKind::Attr { attr_args, invoc_attr_index, is_derive, .. } => {
599+
// FIXME: handle `cfg_attr`
596600
let attr = item
597601
.doc_comments_and_attrs()
598-
.nth(*invoc_attr_index as usize)
602+
.nth(invoc_attr_index.ast_index())
599603
.and_then(Either::left)?;
600604
match attr.token_tree() {
601605
Some(token_tree)

crates/hir/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -785,7 +785,7 @@ fn precise_macro_call_location(
785785
let token = (|| {
786786
let derive_attr = node
787787
.doc_comments_and_attrs()
788-
.nth(*derive_attr_index as usize)
788+
.nth(derive_attr_index.ast_index())
789789
.and_then(Either::left)?;
790790
let token_tree = derive_attr.meta()?.token_tree()?;
791791
let group_by = token_tree
@@ -813,9 +813,11 @@ fn precise_macro_call_location(
813813
let node = ast_id.to_node(db.upcast());
814814
let attr = node
815815
.doc_comments_and_attrs()
816-
.nth((*invoc_attr_index) as usize)
816+
.nth(invoc_attr_index.ast_index())
817817
.and_then(Either::left)
818-
.unwrap_or_else(|| panic!("cannot find attribute #{invoc_attr_index}"));
818+
.unwrap_or_else(|| {
819+
panic!("cannot find attribute #{}", invoc_attr_index.ast_index())
820+
});
819821

820822
(
821823
ast_id.with_value(SyntaxNodePtr::from(AstPtr::new(&attr))),

0 commit comments

Comments
 (0)