-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Macros 2.0: Negative numbers as a single token #48889
Comments
Looks like upstream in rust-lang/rust negative integers are represented as two tokens instead of one token (and it looks like proc_macro may erroneously (?) accept negative integers as literals, see rust-lang/rust#48889). As a result tweak the `ToTokens` impls for signed integers to maybe put a `-` token out in front. Similar treatment is applied to f32/f64 as well. Special treatment is required, however, for the `iNN::min_value()` constants. The actual integral portion isn't actually representable as a positive integer literal (as it'd overflow back to negative) so to handle this case everything is just represented as a u64 literal cast to the right type.
I opened dtolnay/quote#65 as a workaround for the Given that information I think I'd propose the following change:
I think with that change we should be able to put all integers into literals (with suffixes) and we'd also be able to be clear that the negative tokens don't go into the literal but rather need to get emitted as a separate token. |
Looks like upstream in rust-lang/rust negative integers are represented as two tokens instead of one token (and it looks like proc_macro may erroneously (?) accept negative integers as literals, see rust-lang/rust#48889). As a result tweak the `ToTokens` impls for signed integers to maybe put a `-` token out in front. Similar treatment is applied to f32/f64 as well. Special treatment is required, however, for the `iNN::min_value()` constants. The actual integral portion isn't actually representable as a positive integer literal (as it'd overflow back to negative) so to handle this case everything is just represented as a u64 literal cast to the right type.
This commit tweaks the public api of the `proc_macro::Literal` structure to solve rust-lang#48889, an issue about negative integers and their representation in `proc_macro` tokens. Currently the compiler assumes that all integer tokens are *positive* integers rather than embedding a negative sign. The negative sign is a separate token from the integer itself. Currently there's a function like: impl Literal { pub fn i32(i: i32) -> Literal; } but unfortunately this doesn't work for negative integers. When called with negative integers weird errors end up getting thrown later during the parsing process. This function tweaks the definitions to instead use: impl Literal { pub fn i32(i: u32) -> Literal; } This construction makes it more clear that negative arguments are not supported. This additionally allows literals like `-128i8` where `128`, the positive integer part of this literal, isn't representable in `i8`. By taking an unsigned number in each constructor we can allow constructing the minimum literal for each signed type as well. The final tweak of this commit is to panic in `Literal::{f32, f64}` if the input number is negative. This is similar to how infinite/nan literals are handled today (they panic) and constructing a literal should be possible by negating a float and then separately passing in a literal. Closes rust-lang#48889
iirc, we do quite a few 'tricks' with tokens, that is the way we lex source code is not necessarily how the parser treats the tokens. The interpolated tokens from macros are an obvious example which can't be written, only produced from code. I think This is a long-way of saying that perhaps the |
👍 for what I think Nick is saying which is |
+1 Even if |
proc_macro: Tweak doc comments and negative literals This commit tweaks the tokenization of a doc comment to use `#[doc = "..."]` like `macro_rules!` does (instead of treating it as a `Literal` token). Additionally it fixes treatment of negative literals in the compiler, for exapmle `Literal::i32(-1)`. The current fix is a bit of a hack around the current compiler implementation, providing a fix at the proc-macro layer rather than the libsyntax layer. Closes #48889
@ngg ran into some weird bugs and made an awesome reduction which boils down to:
It turns out that when expanding this rustc will print out:
Originating from here I think that this is actually a misdiagnosed error in the sense that the parse is failing because the string is
"-1"
which isn't parseable as au128
, but the current code assumes that it can only fail due to overflow. Generally this is correct because the parser never feeds minus signs to this function!So the broader issue here I believe is that
Literal::i32
can't actually exist. Our parser, as-is today, (and tokenizer?) dictates that the source string-1
is lexed as two tokens, the minus and then the1
. This means thatLiteral::i32
pretending it can only be one token isn't actually right!Should we remove
Literal::i32
and all other signed functions? If so should we also panic on negative floats? If not, should we refactor the AST to support literal tokens with negative integers?cc @jseyfried, @dtolnay, @nrc
The text was updated successfully, but these errors were encountered: