Skip to content

Commit 89adbae

Browse files
committed
Fix float-split hack not setting up spans correctly
1 parent 604a945 commit 89adbae

File tree

15 files changed

+197
-58
lines changed

15 files changed

+197
-58
lines changed

crates/base-db/src/span.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ pub type SpanData = tt::SpanData<SpanAnchor, SyntaxContextId>;
1616
pub struct SyntaxContextId(InternId);
1717
crate::impl_intern_key!(SyntaxContextId);
1818

19+
impl fmt::Display for SyntaxContextId {
20+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
21+
write!(f, "{}", self.0.as_u32())
22+
}
23+
}
24+
1925
impl SyntaxContext for SyntaxContextId {
2026
const DUMMY: Self = Self::ROOT;
2127
// veykril(HACK): salsa doesn't allow us fetching the id of the current input to be allocated so

crates/hir-def/src/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,6 +1322,7 @@ fn derive_macro_as_call_id(
13221322
item_attr: &AstIdWithPath<ast::Adt>,
13231323
derive_attr_index: AttrId,
13241324
derive_pos: u32,
1325+
call_site: SyntaxContextId,
13251326
krate: CrateId,
13261327
resolver: impl Fn(path::ModPath) -> Option<(MacroId, MacroDefId)>,
13271328
) -> Result<(MacroId, MacroDefId, MacroCallId), UnresolvedMacro> {
@@ -1336,8 +1337,7 @@ fn derive_macro_as_call_id(
13361337
derive_index: derive_pos,
13371338
derive_attr_index,
13381339
},
1339-
//FIXME
1340-
SyntaxContextId::ROOT,
1340+
call_site,
13411341
);
13421342
Ok((macro_id, def_id, call_id))
13431343
}
@@ -1367,8 +1367,7 @@ fn attr_macro_as_call_id(
13671367
attr_args: Arc::new(arg),
13681368
invoc_attr_index: macro_attr.id,
13691369
},
1370-
//FIXME
1371-
SyntaxContextId::ROOT,
1370+
macro_attr.ctxt,
13721371
)
13731372
}
13741373
intern::impl_internable!(

crates/hir-def/src/macro_expansion_tests/mbe.rs

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,12 @@ macro_rules! f {
2323
};
2424
}
2525
26-
// +tokenids
26+
// +spans
2727
f!(struct MyTraitMap2);
2828
"#,
29-
// FIXME: #SpanAnchor(FileId(0), 1)@91..92 why is there whitespace annotated with a span here?
29+
// FIXME: #SpanAnchor(FileId(0), 1)@91..92\2# why is there whitespace annotated with a span
30+
// here? Presumably because the leading `::` is getting two spans instead of one? Sounds
31+
// liek glueing might be failing here
3032
expect![[r#"
3133
macro_rules! f {
3234
( struct $ident:ident ) => {
@@ -36,9 +38,9 @@ macro_rules! f {
3638
};
3739
}
3840
39-
struct#SpanAnchor(FileId(0), 1)@58..64 MyTraitMap2#SpanAnchor(FileId(0), 2)@23..34 {#SpanAnchor(FileId(0), 1)@72..73
40-
map#SpanAnchor(FileId(0), 1)@86..89:#SpanAnchor(FileId(0), 1)@89..90 #SpanAnchor(FileId(0), 1)@91..92::#SpanAnchor(FileId(0), 1)@92..93std#SpanAnchor(FileId(0), 1)@93..96::#SpanAnchor(FileId(0), 1)@97..98collections#SpanAnchor(FileId(0), 1)@98..109::#SpanAnchor(FileId(0), 1)@110..111HashSet#SpanAnchor(FileId(0), 1)@111..118<#SpanAnchor(FileId(0), 1)@118..119(#SpanAnchor(FileId(0), 1)@119..120)#SpanAnchor(FileId(0), 1)@120..121>#SpanAnchor(FileId(0), 1)@121..122,#SpanAnchor(FileId(0), 1)@122..123
41-
}#SpanAnchor(FileId(0), 1)@132..133
41+
struct#FileId(0):1@58..64\2# MyTraitMap2#FileId(0):[email protected]\0# {#FileId(0):1@72..73\2#
42+
map#FileId(0):1@86..89\2#:#FileId(0):1@89..90\2# #FileId(0):1@91..92\2#::#FileId(0):1@92..93\2#std#FileId(0):1@93..96\2#::#FileId(0):1@97..98\2#collections#FileId(0):1@98..109\2#::#FileId(0):1@110..111\2#HashSet#FileId(0):1@111..118\2#<#FileId(0):1@118..119\2#(#FileId(0):1@119..120\2#)#FileId(0):1@120..121\2#>#FileId(0):1@121..122\2#,#FileId(0):1@122..123\2#
43+
}#FileId(0):1@132..133\2#
4244
"#]],
4345
);
4446
}
@@ -49,37 +51,39 @@ fn token_mapping_floats() {
4951
// (and related issues)
5052
check(
5153
r#"
52-
// +tokenids
54+
// +spans
5355
macro_rules! f {
5456
($($tt:tt)*) => {
5557
$($tt)*
5658
};
5759
}
5860
59-
// +tokenids
61+
// +spans
6062
f! {
6163
fn main() {
6264
1;
6365
1.0;
66+
((1,),).0.0;
6467
let x = 1;
6568
}
6669
}
6770
6871
6972
"#,
7073
expect![[r#"
71-
// +tokenids
74+
// +spans
7275
macro_rules! f {
7376
($($tt:tt)*) => {
7477
$($tt)*
7578
};
7679
}
7780
78-
fn#SpanAnchor(FileId(0), 2)@22..24 main#SpanAnchor(FileId(0), 2)@25..29(#SpanAnchor(FileId(0), 2)@29..30)#SpanAnchor(FileId(0), 2)@30..31 {#SpanAnchor(FileId(0), 2)@32..33
79-
1#SpanAnchor(FileId(0), 2)@42..43;#SpanAnchor(FileId(0), 2)@43..44
80-
1.0#SpanAnchor(FileId(0), 2)@53..56;#SpanAnchor(FileId(0), 2)@56..57
81-
let#SpanAnchor(FileId(0), 2)@66..69 x#SpanAnchor(FileId(0), 2)@70..71 =#SpanAnchor(FileId(0), 2)@72..73 1#SpanAnchor(FileId(0), 2)@74..75;#SpanAnchor(FileId(0), 2)@75..76
82-
}#SpanAnchor(FileId(0), 2)@81..82
81+
fn#FileId(0):[email protected]\0# main#FileId(0):[email protected]\0#(#FileId(0):[email protected]\0#)#FileId(0):[email protected]\0# {#FileId(0):[email protected]\0#
82+
1#FileId(0):[email protected]\0#;#FileId(0):[email protected]\0#
83+
1.0#FileId(0):[email protected]\0#;#FileId(0):[email protected]\0#
84+
(#FileId(0):[email protected]\0#(#FileId(0):[email protected]\0#1#FileId(0):[email protected]\0#,#FileId(0):[email protected]\0# )#FileId(0):[email protected]\0#,#FileId(0):[email protected]\0# )#FileId(0):[email protected]\0#.#FileId(0):[email protected]\0#0#FileId(0):[email protected]\0#.#FileId(0):[email protected]\0#0#FileId(0):[email protected]\0#;#FileId(0):[email protected]\0#
85+
let#FileId(0):[email protected]\0# x#FileId(0):[email protected]\0# =#FileId(0):[email protected]\0# 1#FileId(0):[email protected]\0#;#FileId(0):[email protected]\0#
86+
}#FileId(0):[email protected]\0#
8387
8488
8589
"#]],
@@ -123,7 +127,7 @@ macro_rules! identity {
123127
}
124128
125129
fn main(foo: ()) {
126-
format_args/*+tokenids*/!("{} {} {}", format_args!("{}", 0), foo, identity!(10), "bar")
130+
format_args/*+spans*/!("{} {} {}", format_args!("{}", 0), foo, identity!(10), "bar")
127131
}
128132
129133
"#,
@@ -137,13 +141,36 @@ macro_rules! identity {
137141
}
138142
139143
fn main(foo: ()) {
140-
builtin#SpanAnchor(FileId(0), 0)@0..0 ##SpanAnchor(FileId(0), 0)@0..0format_args#SpanAnchor(FileId(0), 0)@0..0 (#SpanAnchor(FileId(0), 6)@25..26"{} {} {}"#SpanAnchor(FileId(0), 6)@26..36,#SpanAnchor(FileId(0), 6)@36..37 format_args#SpanAnchor(FileId(0), 6)@38..49!#SpanAnchor(FileId(0), 6)@49..50(#SpanAnchor(FileId(0), 6)@50..51"{}"#SpanAnchor(FileId(0), 6)@51..55,#SpanAnchor(FileId(0), 6)@55..56 0#SpanAnchor(FileId(0), 6)@57..58)#SpanAnchor(FileId(0), 6)@58..59,#SpanAnchor(FileId(0), 6)@59..60 foo#SpanAnchor(FileId(0), 6)@61..64,#SpanAnchor(FileId(0), 6)@64..65 identity#SpanAnchor(FileId(0), 6)@66..74!#SpanAnchor(FileId(0), 6)@74..75(#SpanAnchor(FileId(0), 6)@75..7610#SpanAnchor(FileId(0), 6)@76..78)#SpanAnchor(FileId(0), 6)@78..79,#SpanAnchor(FileId(0), 6)@79..80 "bar"#SpanAnchor(FileId(0), 6)@81..86)#SpanAnchor(FileId(0), 6)@86..87
144+
builtin#FileId(0):0@0..0\0# ##FileId(0):0@0..0\0#format_args#FileId(0):0@0..0\0# (#FileId(0):[email protected]\0#"{} {} {}"#FileId(0):[email protected]\0#,#FileId(0):[email protected]\0# format_args#FileId(0):[email protected]\0#!#FileId(0):[email protected]\0#(#FileId(0):[email protected]\0#"{}"#FileId(0):[email protected]\0#,#FileId(0):[email protected]\0# 0#FileId(0):[email protected]\0#)#FileId(0):[email protected]\0#,#FileId(0):[email protected]\0# foo#FileId(0):[email protected]\0#,#FileId(0):[email protected]\0# identity#FileId(0):[email protected]\0#!#FileId(0):[email protected]\0#(#FileId(0):[email protected]\0#10#FileId(0):[email protected]\0#)#FileId(0):[email protected]\0#,#FileId(0):[email protected]\0# "bar"#FileId(0):[email protected]\0#)#FileId(0):[email protected]\0#
141145
}
142146
143147
"##]],
144148
);
145149
}
146150

151+
#[test]
152+
fn token_mapping_across_files() {
153+
check(
154+
r#"
155+
//- /lib.rs
156+
#[macro_use]
157+
mod foo;
158+
159+
mk_struct/*+spans*/!(Foo with u32);
160+
//- /foo.rs
161+
macro_rules! mk_struct {
162+
($foo:ident with $ty:ty) => { struct $foo($ty); }
163+
}
164+
"#,
165+
expect![[r#"
166+
#[macro_use]
167+
mod foo;
168+
169+
struct#FileId(1):[email protected]\2# Foo#FileId(0):[email protected]\0#(#FileId(1):[email protected]\2#u32#FileId(0):[email protected]\0#)#FileId(1):[email protected]\2#;#FileId(1):[email protected]\2#
170+
"#]],
171+
);
172+
}
173+
147174
#[test]
148175
fn float_field_access_macro_input() {
149176
check(

crates/hir-def/src/macro_expansion_tests/mod.rs

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,11 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
103103
for (call, exp) in expansions.into_iter().rev() {
104104
let mut tree = false;
105105
let mut expect_errors = false;
106-
let mut show_token_ids = false;
106+
let mut show_spans = false;
107107
for comment in call.syntax().children_with_tokens().filter(|it| it.kind() == COMMENT) {
108108
tree |= comment.to_string().contains("+tree");
109109
expect_errors |= comment.to_string().contains("+errors");
110-
show_token_ids |= comment.to_string().contains("+tokenids");
110+
show_spans |= comment.to_string().contains("+spans");
111111
}
112112

113113
let mut expn_text = String::new();
@@ -128,10 +128,8 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
128128
parse.syntax_node(),
129129
);
130130
}
131-
let pp = pretty_print_macro_expansion(
132-
parse.syntax_node(),
133-
show_token_ids.then_some(&*token_map),
134-
);
131+
let pp =
132+
pretty_print_macro_expansion(parse.syntax_node(), show_spans.then_some(&*token_map));
135133
let indent = IndentLevel::from_node(call.syntax());
136134
let pp = reindent(indent, pp);
137135
format_to!(expn_text, "{}", pp);
@@ -166,9 +164,18 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
166164
}
167165
_ => None,
168166
};
167+
169168
if let Some(src) = src {
170169
if src.file_id.is_attr_macro(&db) || src.file_id.is_custom_derive(&db) {
171-
let pp = pretty_print_macro_expansion(src.value, None);
170+
let call = src.file_id.call_node(&db).expect("macro file");
171+
let mut show_spans = false;
172+
for comment in call.value.children_with_tokens().filter(|it| it.kind() == COMMENT) {
173+
show_spans |= comment.to_string().contains("+spans");
174+
}
175+
let pp = pretty_print_macro_expansion(
176+
src.value,
177+
show_spans.then_some(&db.span_map(src.file_id)),
178+
);
172179
format_to!(expanded_text, "\n{}", pp)
173180
}
174181
}
@@ -250,7 +257,14 @@ fn pretty_print_macro_expansion(expn: SyntaxNode, map: Option<&SpanMap>) -> Stri
250257
format_to!(res, "{}", token);
251258
if let Some(map) = map {
252259
if let Some(span) = map.span_for_range(token.text_range()) {
253-
format_to!(res, "#{:?}@{:?}", span.anchor, span.range);
260+
format_to!(
261+
res,
262+
"#{:?}:{:?}@{:?}\\{}#",
263+
span.anchor.file_id,
264+
span.anchor.ast_id.into_raw(),
265+
span.range,
266+
span.ctx
267+
);
254268
}
255269
}
256270
}

crates/hir-def/src/macro_expansion_tests/proc_macros.rs

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,41 @@ fn foo() {
9393
);
9494
}
9595

96+
#[test]
97+
fn macro_rules_in_attr() {
98+
// Regression test for https://github.com/rust-lang/rust-analyzer/issues/12211
99+
check(
100+
r#"
101+
//- proc_macros: identity
102+
macro_rules! id {
103+
($($t:tt)*) => {
104+
$($t)*
105+
};
106+
}
107+
id! {
108+
#[proc_macros::identity]
109+
impl Foo for WrapBj {
110+
async fn foo(&self) {
111+
self.id().await;
112+
}
113+
}
114+
}
115+
"#,
116+
expect![[r#"
117+
macro_rules! id {
118+
($($t:tt)*) => {
119+
$($t)*
120+
};
121+
}
122+
#[proc_macros::identity] impl Foo for WrapBj {
123+
async fn foo(&self ) {
124+
self .id().await ;
125+
}
126+
}
127+
"#]],
128+
);
129+
}
130+
96131
#[test]
97132
fn float_parsing_panic() {
98133
// Regression test for https://github.com/rust-lang/rust-analyzer/issues/12211
@@ -127,3 +162,27 @@ macro_rules! id {
127162
"#]],
128163
);
129164
}
165+
166+
#[test]
167+
fn float_attribute_mapping() {
168+
check(
169+
r#"
170+
//- proc_macros: identity
171+
//+spans
172+
#[proc_macros::identity]
173+
fn foo(&self) {
174+
self.0. 1;
175+
}
176+
"#,
177+
expect![[r#"
178+
//+spans
179+
#[proc_macros::identity]
180+
fn foo(&self) {
181+
self.0. 1;
182+
}
183+
184+
fn#FileId(0):[email protected]\0# foo#FileId(0):[email protected]\0#(#FileId(0):[email protected]\0#&#FileId(0):[email protected]\0#self#FileId(0):[email protected]\0# )#FileId(0):[email protected]\0# {#FileId(0):[email protected]\0#
185+
self#FileId(0):[email protected]\0# .#FileId(0):[email protected]\0#0#FileId(0):[email protected]\0#.#FileId(0):[email protected]\0#1#FileId(0):[email protected]\0#;#FileId(0):[email protected]\0#
186+
}#FileId(0):[email protected]\0#"#]],
187+
);
188+
}

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ enum MacroDirectiveKind {
219219
ast_id: AstIdWithPath<ast::Adt>,
220220
derive_attr: AttrId,
221221
derive_pos: usize,
222+
call_site: SyntaxContextId,
222223
},
223224
Attr {
224225
ast_id: AstIdWithPath<ast::Item>,
@@ -324,7 +325,7 @@ impl DefCollector<'_> {
324325
.parse_path_comma_token_tree(self.db.upcast())
325326
.into_iter()
326327
.flatten()
327-
.filter_map(|feat| match feat.segments() {
328+
.filter_map(|(feat, _)| match feat.segments() {
328329
[name] => Some(name.to_smol_str()),
329330
_ => None,
330331
});
@@ -1139,12 +1140,13 @@ impl DefCollector<'_> {
11391140
return false;
11401141
}
11411142
}
1142-
MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
1143+
MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos, call_site } => {
11431144
let id = derive_macro_as_call_id(
11441145
self.db,
11451146
ast_id,
11461147
*derive_attr,
11471148
*derive_pos as u32,
1149+
*call_site,
11481150
self.def_map.krate,
11491151
resolver,
11501152
);
@@ -1242,7 +1244,7 @@ impl DefCollector<'_> {
12421244
match attr.parse_path_comma_token_tree(self.db.upcast()) {
12431245
Some(derive_macros) => {
12441246
let mut len = 0;
1245-
for (idx, path) in derive_macros.enumerate() {
1247+
for (idx, (path, call_site)) in derive_macros.enumerate() {
12461248
let ast_id = AstIdWithPath::new(file_id, ast_id.value, path);
12471249
self.unresolved_macros.push(MacroDirective {
12481250
module_id: directive.module_id,
@@ -1251,6 +1253,7 @@ impl DefCollector<'_> {
12511253
ast_id,
12521254
derive_attr: attr.id,
12531255
derive_pos: idx,
1256+
call_site,
12541257
},
12551258
container: directive.container,
12561259
});
@@ -1438,7 +1441,7 @@ impl DefCollector<'_> {
14381441
));
14391442
}
14401443
}
1441-
MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos } => {
1444+
MacroDirectiveKind::Derive { ast_id, derive_attr, derive_pos, call_site: _ } => {
14421445
self.def_map.diagnostics.push(DefDiagnostic::unresolved_macro_call(
14431446
directive.module_id,
14441447
MacroCallKind::Derive {
@@ -1828,7 +1831,7 @@ impl ModCollector<'_, '_> {
18281831
);
18291832
return;
18301833
};
1831-
for path in paths {
1834+
for (path, _) in paths {
18321835
if let Some(name) = path.as_ident() {
18331836
single_imports.push(name.clone());
18341837
}

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

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ use base_db::{fixture::WithFixture, SourceDatabase};
88
use expect_test::{expect, Expect};
99
use triomphe::Arc;
1010

11-
use crate::{db::DefDatabase, test_db::TestDB};
12-
13-
use super::DefMap;
11+
use crate::{db::DefDatabase, nameres::DefMap, test_db::TestDB};
1412

1513
fn compute_crate_def_map(ra_fixture: &str) -> Arc<DefMap> {
1614
let db = TestDB::with_files(ra_fixture);

crates/hir-def/src/test_db.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use base_db::{
77
AnchoredPath, CrateId, FileId, FileLoader, FileLoaderDelegate, FilePosition, SourceDatabase,
88
Upcast,
99
};
10-
use hir_expand::{db::ExpandDatabase, hygiene::SyntaxContextData, InFile};
10+
use hir_expand::{db::ExpandDatabase, InFile};
1111
use rustc_hash::FxHashSet;
1212
use syntax::{algo, ast, AstNode};
1313
use triomphe::Arc;
@@ -34,7 +34,7 @@ pub(crate) struct TestDB {
3434
impl Default for TestDB {
3535
fn default() -> Self {
3636
let mut this = Self { storage: Default::default(), events: Default::default() };
37-
this.intern_syntax_context(SyntaxContextData::root());
37+
this.setup_syntax_context_root();
3838
this.set_expand_proc_attr_macros_with_durability(true, Durability::HIGH);
3939
this
4040
}

0 commit comments

Comments
 (0)