Skip to content

Commit faddea9

Browse files
bors[bot]cutsoy
andauthored
Merge #6158
6158: Fix for negative literals in macros r=matklad a=cutsoy _This pull request fixes #6028._ When writing `-42.0f32` in Rust, it is usually parsed as two different tokens (a minus operator and a float literal). But a procedural macro can also generate new tokens, including negative [float literals](https://doc.rust-lang.org/stable/proc_macro/struct.Literal.html#method.f32_suffixed): ```rust #[proc_macro] fn example_verbose(input: TokenStream) -> TokenStream { let literal = Literal::f32_suffixed(-42.0); quote! { #literal } } ``` or even shorter ```rust #[proc_macro] fn example(input: TokenStream) -> TokenStream { let literal = -42.0f32; quote! { #literal } } ``` Unfortunately, these currently cause RA to crash: ``` thread '<unnamed>' panicked at 'Fail to convert given literal Literal { text: "-42.0f32", id: TokenId( 4294967295, ), }', crates/mbe/src/subtree_source.rs:161:28 ``` This pull request contains both a fix 8cf9362 and a unit test 27798ee. In addition, I installed the patched server with `cargo xtask install --server` and verified in VSCode that it no longer crashes when a procedural macro returns a negative number literal. Co-authored-by: Tim <tim@glacyr.com>
2 parents a184c83 + 27798ee commit faddea9

File tree

1 file changed

+33
-5
lines changed

1 file changed

+33
-5
lines changed

crates/mbe/src/subtree_source.rs

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
33
use parser::{Token, TokenSource};
44
use std::cell::{Cell, Ref, RefCell};
5-
use syntax::{lex_single_syntax_kind, SmolStr, SyntaxKind, SyntaxKind::*, T};
5+
use syntax::{tokenize, SmolStr, SyntaxKind, SyntaxKind::*, T};
66
use tt::buffer::{Cursor, TokenBuffer};
77

88
#[derive(Debug, Clone, Eq, PartialEq)]
@@ -155,10 +155,17 @@ fn convert_delim(d: Option<tt::DelimiterKind>, closing: bool) -> TtToken {
155155
}
156156

157157
fn convert_literal(l: &tt::Literal) -> TtToken {
158-
let kind = lex_single_syntax_kind(&l.text)
159-
.map(|(kind, _error)| kind)
160-
.filter(|kind| kind.is_literal())
161-
.unwrap_or_else(|| panic!("Fail to convert given literal {:#?}", &l));
158+
let mut kinds = tokenize(&l.text).0.into_iter().map(|token| token.kind);
159+
160+
let kind = match kinds.next() {
161+
Some(kind) if kind.is_literal() => Some(kind),
162+
Some(SyntaxKind::MINUS) => match kinds.next() {
163+
Some(kind) if kind.is_literal() => Some(kind),
164+
_ => None,
165+
},
166+
_ => None,
167+
}
168+
.unwrap_or_else(|| panic!("Fail to convert given literal {:#?}", &l));
162169

163170
TtToken { kind, is_joint_to_next: false, text: l.text.clone() }
164171
}
@@ -195,3 +202,24 @@ fn convert_leaf(leaf: &tt::Leaf) -> TtToken {
195202
tt::Leaf::Punct(punct) => convert_punct(*punct),
196203
}
197204
}
205+
206+
#[cfg(test)]
207+
mod tests {
208+
use super::{convert_literal, TtToken};
209+
use syntax::{SmolStr, SyntaxKind};
210+
211+
#[test]
212+
fn test_negative_literal() {
213+
assert_eq!(
214+
convert_literal(&tt::Literal {
215+
id: tt::TokenId::unspecified(),
216+
text: SmolStr::new("-42.0")
217+
}),
218+
TtToken {
219+
kind: SyntaxKind::FLOAT_NUMBER,
220+
is_joint_to_next: false,
221+
text: SmolStr::new("-42.0")
222+
}
223+
);
224+
}
225+
}

0 commit comments

Comments
 (0)