Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Negative LitFloat seems to parse incorrectly in procedural macro #1085

Closed
sagacity opened this issue Oct 20, 2021 · 3 comments · Fixed by rust-lang/rust#90297
Closed

Negative LitFloat seems to parse incorrectly in procedural macro #1085

sagacity opened this issue Oct 20, 2021 · 3 comments · Fixed by rust-lang/rust#90297

Comments

@sagacity
Copy link

sagacity commented Oct 20, 2021

I have come across a weird issue in my procedural macro:

I parse a float, like so:

let float = syn::Lit::Float(syn::LitFloat::new("-10.0", Span::call_site()));

I would expect float to be: Float(LitFloat { token: - 10.0 }). However, it is Float(LitFloat { token: - 10 }) instead. This causes the code generated by my macro to miscompile, since -10 is not interpreted as a float.

Weirdly, this only happens when the parsing is done inside a procedural macro. If I do the parsing in a regular binary it works fine. I have no idea what is different about executing in a procedural macro that could cause this, and it also makes it quite hard to debug.

I have a reproduction case here. Run it with cargo run --example example and it will panic with the parsed float showing as: Float(LitFloat { token: - 10 }). I would have expected Float(LitFloat { token: - 10.0 }) instead.

I've tried this both on Rust 1.55.0 and the currently nightly, on MacOS.

@dtolnay
Copy link
Owner

dtolnay commented Oct 26, 2021

I believe this is a bug in the compiler's proc_macro implementation, which is why you only saw it affecting procedural macros and not regular binaries. I've put up a fix in rust-lang/rust#90297.

@sagacity
Copy link
Author

Great, thanks so much!

@dtolnay
Copy link
Owner

dtolnay commented Oct 26, 2021

The compiler fix is still needed but I implemented a workaround in #1087 + #1088 as long as the compiler being used is 1.56+.

  = help: message: float is parsed as: Float(LitFloat { token: -10.0 })

@dtolnay dtolnay closed this as completed Oct 26, 2021
bors added a commit to rust-lang-ci/rust that referenced this issue Nov 6, 2021
Append .0 to unsuffixed float if it would otherwise become int token

Previously the unsuffixed f32/f64 constructors of `proc_macro::Literal` would create literal tokens that are definitely not a float:

```rust
Literal::f32_unsuffixed(10.0)  // 10
Literal::f32_suffixed(10.0)    // 10f32
Literal::f64_unsuffixed(10.0)  // 10
Literal::f64_suffixed(10.0)    // 10f64
```

Notice that the `10` are actually integer tokens if you were to reparse them, not float tokens.

This diff updates `Literal::f32_unsuffixed` and `Literal::f64_unsuffixed` to produce tokens that unambiguously parse as a float. This matches longstanding behavior of the proc-macro2 crate's implementation of these APIs dating back at least 3.5 years, so it's likely an unobjectionable behavior.

```rust
Literal::f32_unsuffixed(10.0)  // 10.0
Literal::f32_suffixed(10.0)    // 10f32
Literal::f64_unsuffixed(10.0)  // 10.0
Literal::f64_suffixed(10.0)    // 10f64
```

Fixes dtolnay/syn#1085.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants