diff options
| author | est31 <MTest31@outlook.com> | 2023-06-02 18:53:04 +0200 |
|---|---|---|
| committer | est31 <MTest31@outlook.com> | 2023-06-08 23:42:58 +0200 |
| commit | 1b90f5efaf46073a7da509a895a0688e1c6300c3 (patch) | |
| tree | 1dfa03e86f163a72e16a6d62df81f0aead4684c6 | |
| parent | d74ec96e8d334c765e35707f7b7f3c6499a1b43c (diff) | |
| download | rust-1b90f5efaf46073a7da509a895a0688e1c6300c3.tar.gz rust-1b90f5efaf46073a7da509a895a0688e1c6300c3.zip | |
Support float-like tuple indices in offset_of!()
The tokenizer gives us whole float literal tokens, we have to split them up in order to be able to create field access from them.
| -rw-r--r-- | compiler/rustc_parse/src/parser/expr.rs | 47 | ||||
| -rw-r--r-- | tests/ui/offset-of/offset-of-tuple-nested.rs | 32 | ||||
| -rw-r--r-- | tests/ui/offset-of/offset-of-tuple.rs | 52 | ||||
| -rw-r--r-- | tests/ui/offset-of/offset-of-tuple.stderr | 232 |
4 files changed, 343 insertions, 20 deletions
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9e5f85dc7dc..df06115ef3b 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1852,10 +1852,53 @@ impl<'a> Parser<'a> { let (fields, _trailing, _recovered) = self.parse_seq_to_before_end( &TokenKind::CloseDelim(Delimiter::Parenthesis), seq_sep, - Parser::parse_field_name, + |this| { + let token::Literal(token::Lit { kind: token::Float, symbol, suffix }) = this.token.kind + else { + return Ok(thin_vec![this.parse_field_name()?]); + }; + let res = match this.break_up_float(symbol) { + // 1e2 + DestructuredFloat::Single(sym, sp) => { + this.bump(); + thin_vec![Ident::new(sym, sp)] + } + // 1. + DestructuredFloat::TrailingDot(sym, sym_span, dot_span) => { + assert!(suffix.is_none()); + // Analogous to Self::break_and_eat + this.token_cursor.break_last_token = true; + // This might work, in cases like `1. 2.3`, and might not, + // in cases like `offset_of!(Ty, 1.)`. + this.token = Token::new(token::Ident(sym, false), sym_span); + this.bump_with((Token::new(token::Dot, dot_span), this.token_spacing)); + thin_vec![Ident::new(sym, sym_span)] + } + // 1.2 | 1.2e3 + DestructuredFloat::MiddleDot( + symbol1, + ident1_span, + _dot_span, + symbol2, + ident2_span, + ) => { + this.bump(); + thin_vec![ + Ident::new(symbol1, ident1_span), + Ident::new(symbol2, ident2_span) + ] + } + DestructuredFloat::Error => { + this.bump(); + thin_vec![Ident::new(symbol, this.prev_token.span)] + } + }; + Ok(res) + }, )?; + let fields = fields.into_iter().flatten().collect::<Vec<_>>(); let span = lo.to(self.token.span); - Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields.to_vec().into()))) + Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields.into()))) } /// Returns a string literal if the next token is a string literal. diff --git a/tests/ui/offset-of/offset-of-tuple-nested.rs b/tests/ui/offset-of/offset-of-tuple-nested.rs new file mode 100644 index 00000000000..00fbb6bf8f4 --- /dev/null +++ b/tests/ui/offset-of/offset-of-tuple-nested.rs @@ -0,0 +1,32 @@ +// run-pass +// Test for issue #112204 -- make sure this goes through the entire compilation pipeline, +// similar to why `offset-of-unsized.rs` is also build-pass + +#![feature(offset_of)] +#![feature(builtin_syntax)] + +use std::mem::offset_of; + +type ComplexTup = ((u8, (u8, (u8, u16), u8)), (u8, u32, u16)); + +fn main() { + println!("{}", offset_of!(((u8, u8), u8), 0)); + println!("{}", offset_of!(((u8, u8), u8), 1)); + println!("{}", offset_of!(((u8, (u8, u8)), (u8, u8, u8)), 0.1.0)); + + // Complex case: do all combinations of spacings because the spacing determines what gets + // sent to the lexer. + println!("{}", offset_of!(ComplexTup, 0.1.1.1)); + println!("{}", builtin # offset_of(ComplexTup, 0. 1.1.1)); + println!("{}", offset_of!(ComplexTup, 0 . 1.1.1)); + println!("{}", offset_of!(ComplexTup, 0 .1.1.1)); + println!("{}", offset_of!(ComplexTup, 0.1 .1.1)); + println!("{}", offset_of!(ComplexTup, 0.1 . 1.1)); + println!("{}", offset_of!(ComplexTup, 0.1. 1.1)); + println!("{}", builtin # offset_of(ComplexTup, 0.1.1. 1)); + println!("{}", offset_of!(ComplexTup, 0.1.1 . 1)); + println!("{}", offset_of!(ComplexTup, 0.1.1 .1)); + + println!("{}", offset_of!(((u8, u16), (u32, u16, u8)), 0.0)); + println!("{}", offset_of!(((u8, u16), (u32, u16, u8)), 1.2)); +} diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs index 4077538b77f..e31b037ee3e 100644 --- a/tests/ui/offset-of/offset-of-tuple.rs +++ b/tests/ui/offset-of/offset-of-tuple.rs @@ -1,10 +1,54 @@ #![feature(offset_of)] #![feature(builtin_syntax)] +use std::mem::offset_of; + fn main() { - core::mem::offset_of!((u8, u8), _0); //~ ERROR no field `_0` - core::mem::offset_of!((u8, u8), +1); //~ ERROR no rules expected - core::mem::offset_of!((u8, u8), -1); //~ ERROR no rules expected + offset_of!((u8, u8), _0); //~ ERROR no field `_0` + offset_of!((u8, u8), 01); //~ ERROR no field `01` + offset_of!((u8, u8), 1e2); //~ ERROR no field `1e2` + offset_of!((u8, u8), 1_u8); //~ ERROR no field `1_` + //~| ERROR suffixes on a tuple index + offset_of!((u8, u8), +1); //~ ERROR no rules expected + offset_of!((u8, u8), -1); //~ ERROR no rules expected + offset_of!((u8, u8), 1.); //~ ERROR expected identifier, found `)` + offset_of!((u8, u8), 1 .); //~ ERROR unexpected end of macro + builtin # offset_of((u8, u8), 1e2); //~ ERROR no field `1e2` builtin # offset_of((u8, u8), _0); //~ ERROR no field `_0` - builtin # offset_of((u8, u8), +1); //~ ERROR expected identifier + builtin # offset_of((u8, u8), 01); //~ ERROR no field `01` + builtin # offset_of((u8, u8), 1_u8); //~ ERROR no field `1_` + //~| ERROR suffixes on a tuple index + // We need to put these into curly braces, otherwise only one of the + // errors will be emitted and the others suppressed. + { builtin # offset_of((u8, u8), +1) }; //~ ERROR expected identifier, found `+` + { builtin # offset_of((u8, u8), 1.) }; //~ ERROR expected identifier, found `)` + { builtin # offset_of((u8, u8), 1 .) }; //~ ERROR expected identifier, found `)` +} + +type ComplexTup = ((u8, (u8, u8)), u8); + +fn nested() { + offset_of!(((u8, u16), (u32, u16, u8)), 0.2); //~ ERROR no field `2` + offset_of!(((u8, u16), (u32, u16, u8)), 1.2); + offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); //~ ERROR no field `0` + + // All combinations of spaces (this sends different tokens to the parser) + offset_of!(ComplexTup, 0.0.1.); //~ ERROR expected identifier + offset_of!(ComplexTup, 0 .0.1.); //~ ERROR unexpected end of macro + offset_of!(ComplexTup, 0 . 0.1.); //~ ERROR unexpected end of macro + offset_of!(ComplexTup, 0. 0.1.); //~ ERROR no rules expected + offset_of!(ComplexTup, 0.0 .1.); //~ ERROR expected identifier, found `)` + offset_of!(ComplexTup, 0.0 . 1.); //~ ERROR expected identifier, found `)` + offset_of!(ComplexTup, 0.0. 1.); //~ ERROR expected identifier, found `)` + + // Test for builtin too to ensure that the builtin syntax can also handle these cases + // We need to put these into curly braces, otherwise only one of the + // errors will be emitted and the others suppressed. + { builtin # offset_of(ComplexTup, 0.0.1.) }; //~ ERROR expected identifier, found `)` + { builtin # offset_of(ComplexTup, 0 .0.1.) }; //~ ERROR expected identifier, found `)` + { builtin # offset_of(ComplexTup, 0 . 0.1.) }; //~ ERROR expected identifier, found `)` + { builtin # offset_of(ComplexTup, 0. 0.1.) }; //~ ERROR expected identifier, found `)` + { builtin # offset_of(ComplexTup, 0.0 .1.) }; //~ ERROR expected identifier, found `)` + { builtin # offset_of(ComplexTup, 0.0 . 1.) }; //~ ERROR expected identifier, found `)` + { builtin # offset_of(ComplexTup, 0.0. 1.) }; //~ ERROR expected identifier, found `)` } diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr index cc9ce0f3455..954515f80a6 100644 --- a/tests/ui/offset-of/offset-of-tuple.stderr +++ b/tests/ui/offset-of/offset-of-tuple.stderr @@ -1,37 +1,241 @@ +error: suffixes on a tuple index are invalid + --> $DIR/offset-of-tuple.rs:19:35 + | +LL | builtin # offset_of((u8, u8), 1_u8); + | ^^^^ invalid suffix `u8` + error: expected identifier, found `+` - --> $DIR/offset-of-tuple.rs:9:35 + --> $DIR/offset-of-tuple.rs:23:37 + | +LL | { builtin # offset_of((u8, u8), +1) }; + | ^ expected identifier + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:24:39 + | +LL | { builtin # offset_of((u8, u8), 1.) }; + | ^ expected identifier + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:25:40 + | +LL | { builtin # offset_of((u8, u8), 1 .) }; + | ^ expected identifier + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:47:45 + | +LL | { builtin # offset_of(ComplexTup, 0.0.1.) }; + | ^ expected identifier + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:48:46 + | +LL | { builtin # offset_of(ComplexTup, 0 .0.1.) }; + | ^ expected identifier + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:49:47 + | +LL | { builtin # offset_of(ComplexTup, 0 . 0.1.) }; + | ^ expected identifier + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:50:46 + | +LL | { builtin # offset_of(ComplexTup, 0. 0.1.) }; + | ^ expected identifier + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:51:46 + | +LL | { builtin # offset_of(ComplexTup, 0.0 .1.) }; + | ^ expected identifier + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:52:47 + | +LL | { builtin # offset_of(ComplexTup, 0.0 . 1.) }; + | ^ expected identifier + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:53:46 + | +LL | { builtin # offset_of(ComplexTup, 0.0. 1.) }; + | ^ expected identifier + +error: suffixes on a tuple index are invalid + --> $DIR/offset-of-tuple.rs:10:26 | -LL | builtin # offset_of((u8, u8), +1); - | ^ expected identifier +LL | offset_of!((u8, u8), 1_u8); + | ^^^^ invalid suffix `u8` error: no rules expected the token `1` - --> $DIR/offset-of-tuple.rs:6:38 + --> $DIR/offset-of-tuple.rs:12:27 | -LL | core::mem::offset_of!((u8, u8), +1); - | ^ no rules expected this token in macro call +LL | offset_of!((u8, u8), +1); + | ^ no rules expected this token in macro call | = note: while trying to match sequence start error: no rules expected the token `1` - --> $DIR/offset-of-tuple.rs:7:38 + --> $DIR/offset-of-tuple.rs:13:27 | -LL | core::mem::offset_of!((u8, u8), -1); - | ^ no rules expected this token in macro call +LL | offset_of!((u8, u8), -1); + | ^ no rules expected this token in macro call | = note: while trying to match sequence start +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:14:5 + | +LL | offset_of!((u8, u8), 1.); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected identifier + | in this macro invocation + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unexpected end of macro invocation + --> $DIR/offset-of-tuple.rs:15:29 + | +LL | offset_of!((u8, u8), 1 .); + | ^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$fields:tt` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:36:5 + | +LL | offset_of!(ComplexTup, 0.0.1.); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected identifier + | in this macro invocation + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unexpected end of macro invocation + --> $DIR/offset-of-tuple.rs:37:35 + | +LL | offset_of!(ComplexTup, 0 .0.1.); + | ^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$fields:tt` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + +error: unexpected end of macro invocation + --> $DIR/offset-of-tuple.rs:38:36 + | +LL | offset_of!(ComplexTup, 0 . 0.1.); + | ^ missing tokens in macro arguments + | +note: while trying to match meta-variable `$fields:tt` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL + +error: no rules expected the token `0.1` + --> $DIR/offset-of-tuple.rs:39:31 + | +LL | offset_of!(ComplexTup, 0. 0.1.); + | ^^^ no rules expected this token in macro call + | + = note: while trying to match sequence start + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:40:5 + | +LL | offset_of!(ComplexTup, 0.0 .1.); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected identifier + | in this macro invocation + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:41:5 + | +LL | offset_of!(ComplexTup, 0.0 . 1.); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected identifier + | in this macro invocation + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected identifier, found `)` + --> $DIR/offset-of-tuple.rs:42:5 + | +LL | offset_of!(ComplexTup, 0.0. 1.); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected identifier + | in this macro invocation + | + = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info) + error[E0609]: no field `_0` on type `(u8, u8)` - --> $DIR/offset-of-tuple.rs:5:37 + --> $DIR/offset-of-tuple.rs:7:26 | -LL | core::mem::offset_of!((u8, u8), _0); - | ^^ +LL | offset_of!((u8, u8), _0); + | ^^ + +error[E0609]: no field `01` on type `(u8, u8)` + --> $DIR/offset-of-tuple.rs:8:26 + | +LL | offset_of!((u8, u8), 01); + | ^^ + +error[E0609]: no field `1e2` on type `(u8, u8)` + --> $DIR/offset-of-tuple.rs:9:26 + | +LL | offset_of!((u8, u8), 1e2); + | ^^^ + +error[E0609]: no field `1_` on type `(u8, u8)` + --> $DIR/offset-of-tuple.rs:10:26 + | +LL | offset_of!((u8, u8), 1_u8); + | ^^^^ + +error[E0609]: no field `1e2` on type `(u8, u8)` + --> $DIR/offset-of-tuple.rs:16:35 + | +LL | builtin # offset_of((u8, u8), 1e2); + | ^^^ error[E0609]: no field `_0` on type `(u8, u8)` - --> $DIR/offset-of-tuple.rs:8:35 + --> $DIR/offset-of-tuple.rs:17:35 | LL | builtin # offset_of((u8, u8), _0); | ^^ -error: aborting due to 5 previous errors +error[E0609]: no field `01` on type `(u8, u8)` + --> $DIR/offset-of-tuple.rs:18:35 + | +LL | builtin # offset_of((u8, u8), 01); + | ^^ + +error[E0609]: no field `1_` on type `(u8, u8)` + --> $DIR/offset-of-tuple.rs:19:35 + | +LL | builtin # offset_of((u8, u8), 1_u8); + | ^^^^ + +error[E0609]: no field `2` on type `(u8, u16)` + --> $DIR/offset-of-tuple.rs:31:47 + | +LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); + | ^ + +error[E0609]: no field `0` on type `u8` + --> $DIR/offset-of-tuple.rs:33:49 + | +LL | offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); + | ^ + +error: aborting due to 33 previous errors For more information about this error, try `rustc --explain E0609`. |
