Skip to content

Commit 957b4bb

Browse files
committed
Auto merge of #13717 - lowr:fix/proc-macro-ident-is-raw, r=Veykril
Handle raw identifiers in proc macro server Fixes #13706 When proc macros create `proc_macro::Ident`s, they pass an identifier text without "r#" prefix and a flag `is_raw` to proc macro server. Our `tt::Ident` currently stores the text *with* "r#" so we need to adjust them somewhere. Rather than following rustc and adding `is_raw` field to our `tt::Ident`, I opted for adjusting the representation of identifiers in proc macro server, because we don't need the field outside it. It's hard to write regression test for this, but at least I: - ran `cargo +nightly t --features sysroot-abi` and all the tests passed - built proc macro server with `cargo +nightly b -r --bin rust-analyzer-proc-macro-srv --features sysroot-abi` and made sure #13706 resolved - For the record, the nightly versions used are `rustc 1.67.0-nightly (32e613bba 2022-12-02)` and `cargo 1.67.0-nightly (e027c4b5d 2022-11-25)`.
2 parents 04a2ac2 + de591f0 commit 957b4bb

File tree

5 files changed

+27
-12
lines changed

5 files changed

+27
-12
lines changed

crates/proc-macro-srv/src/abis/abi_1_58/ra_server.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -471,8 +471,12 @@ impl server::Punct for RustAnalyzer {
471471
}
472472

473473
impl server::Ident for RustAnalyzer {
474-
fn new(&mut self, string: &str, span: Self::Span, _is_raw: bool) -> Self::Ident {
475-
IdentId(self.ident_interner.intern(&IdentData(tt::Ident { text: string.into(), id: span })))
474+
fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
475+
IdentId(self.ident_interner.intern(&IdentData(tt::Ident::new_with_is_raw(
476+
string.into(),
477+
span,
478+
is_raw,
479+
))))
476480
}
477481

478482
fn span(&mut self, ident: Self::Ident) -> Self::Span {

crates/proc-macro-srv/src/abis/abi_1_63/ra_server.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -486,8 +486,12 @@ impl server::Punct for RustAnalyzer {
486486
}
487487

488488
impl server::Ident for RustAnalyzer {
489-
fn new(&mut self, string: &str, span: Self::Span, _is_raw: bool) -> Self::Ident {
490-
IdentId(self.ident_interner.intern(&IdentData(tt::Ident { text: string.into(), id: span })))
489+
fn new(&mut self, string: &str, span: Self::Span, is_raw: bool) -> Self::Ident {
490+
IdentId(self.ident_interner.intern(&IdentData(tt::Ident::new_with_is_raw(
491+
string.into(),
492+
span,
493+
is_raw,
494+
))))
491495
}
492496

493497
fn span(&mut self, ident: Self::Ident) -> Self::Span {

crates/proc-macro-srv/src/abis/abi_sysroot/ra_server.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -107,8 +107,8 @@ impl server::TokenStream for RustAnalyzer {
107107
}
108108

109109
bridge::TokenTree::Ident(ident) => {
110-
// FIXME: handle raw idents
111110
let text = ident.sym.text();
111+
let text = if ident.is_raw { tt::SmolStr::from_iter(["r#", &text]) } else { text };
112112
let ident: tt::Ident = tt::Ident { text, id: ident.span };
113113
let leaf = tt::Leaf::from(ident);
114114
let tree = TokenTree::from(leaf);
@@ -182,9 +182,8 @@ impl server::TokenStream for RustAnalyzer {
182182
.map(|tree| match tree {
183183
tt::TokenTree::Leaf(tt::Leaf::Ident(ident)) => {
184184
bridge::TokenTree::Ident(bridge::Ident {
185-
sym: Symbol::intern(&ident.text),
186-
// FIXME: handle raw idents
187-
is_raw: false,
185+
sym: Symbol::intern(&ident.text.trim_start_matches("r#")),
186+
is_raw: ident.text.starts_with("r#"),
188187
span: ident.id,
189188
})
190189
}

crates/proc-macro-srv/src/tests/mod.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ fn test_fn_like_macro_clone_raw_ident() {
6363
"r#async",
6464
expect![[r#"
6565
SUBTREE $
66-
IDENT async 4294967295"#]],
66+
IDENT r#async 4294967295"#]],
6767
);
6868
}
6969

@@ -86,15 +86,13 @@ fn test_fn_like_mk_literals() {
8686

8787
#[test]
8888
fn test_fn_like_mk_idents() {
89-
// FIXME: this test is wrong: raw should be 'r#raw' but ABIs 1.64 and below
90-
// simply ignore `is_raw` when implementing the `Ident` interface.
9189
assert_expand(
9290
"fn_like_mk_idents",
9391
r#""#,
9492
expect![[r#"
9593
SUBTREE $
9694
IDENT standard 4294967295
97-
IDENT raw 4294967295"#]],
95+
IDENT r#raw 4294967295"#]],
9896
);
9997
}
10098

crates/tt/src/lib.rs

+10
Original file line numberDiff line numberDiff line change
@@ -86,10 +86,20 @@ pub enum Spacing {
8686

8787
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
8888
pub struct Ident {
89+
/// Identifier or keyword. Unlike rustc, we keep "r#" prefix when it represents a raw identifier.
8990
pub text: SmolStr,
9091
pub id: TokenId,
9192
}
9293

94+
impl Ident {
95+
/// Constructor intended to be used only by proc macro server. `text` should not contain raw
96+
/// identifier prefix.
97+
pub fn new_with_is_raw(text: SmolStr, id: TokenId, is_raw: bool) -> Self {
98+
let text = if is_raw { SmolStr::from_iter(["r#", &text]) } else { text };
99+
Ident { text, id }
100+
}
101+
}
102+
93103
impl Leaf {
94104
pub fn id(&self) -> TokenId {
95105
match self {

0 commit comments

Comments
 (0)