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.
This commit is contained in:
est31 2023-06-02 18:53:04 +02:00
parent d74ec96e8d
commit 1b90f5efaf
4 changed files with 344 additions and 21 deletions

View File

@ -1852,10 +1852,53 @@ pub(crate) fn parse_expr_offset_of(&mut self, lo: Span) -> PResult<'a, P<Expr>>
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.

View File

@ -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));
}

View File

@ -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 `)`
}

View File

@ -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
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 | 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[E0609]: no field `_0` on type `(u8, u8)`
--> $DIR/offset-of-tuple.rs:5:37
error: expected identifier, found `)`
--> $DIR/offset-of-tuple.rs:14:5
|
LL | core::mem::offset_of!((u8, u8), _0);
| ^^
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:8:35
--> $DIR/offset-of-tuple.rs:7:26
|
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: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`.