about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLukas Wirth <lukastw97@gmail.com>2025-05-05 13:56:24 +0200
committerLukas Wirth <lukastw97@gmail.com>2025-05-05 14:10:42 +0200
commit4f0c28e1dcc07052c1f8ddce686628c1c8f959c8 (patch)
tree57c8dfaa10151a756a8e833e8563fafddd73bac1
parent53881efacb7af06677c1632523d43c5c173dd2dd (diff)
downloadrust-4f0c28e1dcc07052c1f8ddce686628c1c8f959c8.tar.gz
rust-4f0c28e1dcc07052c1f8ddce686628c1c8f959c8.zip
fix: Fix proc-macro API creating malformed negative literals
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs42
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs42
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs5
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs25
4 files changed, 85 insertions, 29 deletions
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
index 47555a5db2f..64b40e7b943 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/rust_analyzer_span.rs
@@ -168,16 +168,38 @@ impl server::TokenStream for RaSpanServer {
             }
 
             bridge::TokenTree::Literal(literal) => {
-                let literal = tt::Literal {
-                    symbol: literal.symbol,
-                    suffix: literal.suffix,
-                    span: literal.span,
-                    kind: literal_kind_to_internal(literal.kind),
-                };
-
-                let leaf: tt::Leaf = tt::Leaf::from(literal);
-                let tree = tt::TokenTree::from(leaf);
-                TokenStream { token_trees: vec![tree] }
+                let token_trees =
+                    if let Some((_minus, symbol)) = literal.symbol.as_str().split_once('-') {
+                        let punct = tt::Punct {
+                            spacing: tt::Spacing::Alone,
+                            span: literal.span,
+                            char: '-' as char,
+                        };
+                        let leaf: tt::Leaf = tt::Leaf::from(punct);
+                        let minus_tree = tt::TokenTree::from(leaf);
+
+                        let literal = tt::Literal {
+                            symbol: Symbol::intern(symbol),
+                            suffix: literal.suffix,
+                            span: literal.span,
+                            kind: literal_kind_to_internal(literal.kind),
+                        };
+                        let leaf: tt::Leaf = tt::Leaf::from(literal);
+                        let tree = tt::TokenTree::from(leaf);
+                        vec![minus_tree, tree]
+                    } else {
+                        let literal = tt::Literal {
+                            symbol: literal.symbol,
+                            suffix: literal.suffix,
+                            span: literal.span,
+                            kind: literal_kind_to_internal(literal.kind),
+                        };
+
+                        let leaf: tt::Leaf = tt::Leaf::from(literal);
+                        let tree = tt::TokenTree::from(leaf);
+                        vec![tree]
+                    };
+                TokenStream { token_trees }
             }
 
             bridge::TokenTree::Punct(p) => {
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
index c002be4be6f..24a67bf45c8 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_id.rs
@@ -153,16 +153,38 @@ impl server::TokenStream for TokenIdServer {
             }
 
             bridge::TokenTree::Literal(literal) => {
-                let literal = Literal {
-                    symbol: literal.symbol,
-                    suffix: literal.suffix,
-                    span: literal.span,
-                    kind: literal_kind_to_internal(literal.kind),
-                };
-
-                let leaf = tt::Leaf::from(literal);
-                let tree = TokenTree::from(leaf);
-                TokenStream { token_trees: vec![tree] }
+                let token_trees =
+                    if let Some((_minus, symbol)) = literal.symbol.as_str().split_once('-') {
+                        let punct = tt::Punct {
+                            spacing: tt::Spacing::Alone,
+                            span: literal.span,
+                            char: '-' as char,
+                        };
+                        let leaf: tt::Leaf = tt::Leaf::from(punct);
+                        let minus_tree = tt::TokenTree::from(leaf);
+
+                        let literal = Literal {
+                            symbol: Symbol::intern(symbol),
+                            suffix: literal.suffix,
+                            span: literal.span,
+                            kind: literal_kind_to_internal(literal.kind),
+                        };
+                        let leaf: tt::Leaf = tt::Leaf::from(literal);
+                        let tree = tt::TokenTree::from(leaf);
+                        vec![minus_tree, tree]
+                    } else {
+                        let literal = Literal {
+                            symbol: literal.symbol,
+                            suffix: literal.suffix,
+                            span: literal.span,
+                            kind: literal_kind_to_internal(literal.kind),
+                        };
+
+                        let leaf: tt::Leaf = tt::Leaf::from(literal);
+                        let tree = tt::TokenTree::from(leaf);
+                        vec![tree]
+                    };
+                TokenStream { token_trees }
             }
 
             bridge::TokenTree::Punct(p) => {
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
index 4946a4f2a62..072557913c2 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/server_impl/token_stream.rs
@@ -68,6 +68,11 @@ impl<S: Copy> TokenStream<S> {
                         span: ident.span,
                     }))
                 }
+                // Note, we do not have to assemble our `-` punct and literal split into a single
+                // negative bridge literal here. As the proc-macro docs state
+                // > Literals created from negative numbers might not survive round-trips through
+                // > TokenStream or strings and may be broken into two tokens (- and positive
+                // > literal).
                 tt::TokenTree::Leaf(tt::Leaf::Literal(lit)) => {
                     result.push(bridge::TokenTree::Literal(bridge::Literal {
                         span: lit.span,
diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
index 7a0ac01c50d..36cd675b9a6 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs
@@ -248,13 +248,17 @@ fn test_fn_like_mk_literals() {
               LITERAL Str string 1
               LITERAL CStr cstring 1
               LITERAL Float 3.14f64 1
-              LITERAL Float -3.14f64 1
+              PUNCH   - [alone] 1
+              LITERAL Float 3.14f64 1
+              LITERAL Float 3.14 1
+              PUNCH   - [alone] 1
               LITERAL Float 3.14 1
-              LITERAL Float -3.14 1
               LITERAL Integer 123i64 1
-              LITERAL Integer -123i64 1
+              PUNCH   - [alone] 1
+              LITERAL Integer 123i64 1
               LITERAL Integer 123 1
-              LITERAL Integer -123 1"#]],
+              PUNCH   - [alone] 1
+              LITERAL Integer 123 1"#]],
         expect![[r#"
             SUBTREE $$ 42:2@0..100#ROOT2024 42:2@0..100#ROOT2024
 
@@ -266,13 +270,17 @@ fn test_fn_like_mk_literals() {
               LITERAL Str string 42:2@0..100#ROOT2024
               LITERAL CStr cstring 42:2@0..100#ROOT2024
               LITERAL Float 3.14f64 42:2@0..100#ROOT2024
-              LITERAL Float -3.14f64 42:2@0..100#ROOT2024
+              PUNCH   - [alone] 42:2@0..100#ROOT2024
+              LITERAL Float 3.14f64 42:2@0..100#ROOT2024
+              LITERAL Float 3.14 42:2@0..100#ROOT2024
+              PUNCH   - [alone] 42:2@0..100#ROOT2024
               LITERAL Float 3.14 42:2@0..100#ROOT2024
-              LITERAL Float -3.14 42:2@0..100#ROOT2024
               LITERAL Integer 123i64 42:2@0..100#ROOT2024
-              LITERAL Integer -123i64 42:2@0..100#ROOT2024
+              PUNCH   - [alone] 42:2@0..100#ROOT2024
+              LITERAL Integer 123i64 42:2@0..100#ROOT2024
               LITERAL Integer 123 42:2@0..100#ROOT2024
-              LITERAL Integer -123 42:2@0..100#ROOT2024"#]],
+              PUNCH   - [alone] 42:2@0..100#ROOT2024
+              LITERAL Integer 123 42:2@0..100#ROOT2024"#]],
     );
 }
 
@@ -400,7 +408,6 @@ fn test_fn_like_macro_clone_literals() {
     );
 }
 
-
 #[test]
 fn test_fn_like_macro_negative_literals() {
     assert_expand(