From 09bb07e38f5bfba4fa3e9ac3113e6b7e542e7c67 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Tue, 2 Jan 2024 22:12:35 +0000 Subject: [PATCH 1/2] Make offset_of field parsing use metavariable which handles any spacing --- compiler/rustc_parse/messages.ftl | 4 + compiler/rustc_parse/src/errors.rs | 8 + compiler/rustc_parse/src/parser/expr.rs | 164 +++++++++++++----- library/core/src/mem/mod.rs | 10 ++ tests/ui/offset-of/offset-of-arg-count.rs | 8 +- tests/ui/offset-of/offset-of-arg-count.stderr | 29 ++-- tests/ui/offset-of/offset-of-builtin.rs | 24 +-- tests/ui/offset-of/offset-of-builtin.stderr | 67 +++---- tests/ui/offset-of/offset-of-self.rs | 11 +- tests/ui/offset-of/offset-of-self.stderr | 38 +--- tests/ui/offset-of/offset-of-tuple-nested.rs | 5 +- tests/ui/offset-of/offset-of-tuple.rs | 42 ++--- tests/ui/offset-of/offset-of-tuple.stderr | 146 ++++++++-------- 13 files changed, 293 insertions(+), 263 deletions(-) diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl index c6bddbfacd6ec..9a76872a383bd 100644 --- a/compiler/rustc_parse/messages.ftl +++ b/compiler/rustc_parse/messages.ftl @@ -10,6 +10,8 @@ parse_ambiguous_range_pattern = the range pattern here has ambiguous interpretat parse_array_brackets_instead_of_braces = this is a block expression, not an array .suggestion = to make an array, use square brackets instead of curly braces +parse_array_index_offset_of = array indexing not supported in offset_of + parse_assignment_else_not_allowed = ... else {"{"} ... {"}"} is not allowed parse_assoc_lifetime = associated lifetimes are not supported @@ -405,6 +407,8 @@ parse_invalid_logical_operator = `{$incorrect}` is not a logical operator parse_invalid_meta_item = expected unsuffixed literal or identifier, found `{$token}` +parse_invalid_offset_of = offset_of expects dot-separated field and variant names + parse_invalid_unicode_escape = invalid unicode character escape .label = invalid escape .help = unicode escape must {$surrogate -> diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index e276b34ca37af..04d70872d78cb 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -2887,3 +2887,11 @@ pub(crate) struct TransposeDynOrImplSugg<'a> { pub insertion_span: Span, pub kw: &'a str, } + +#[derive(Diagnostic)] +#[diag(parse_array_index_offset_of)] +pub(crate) struct ArrayIndexInOffsetOf(#[primary_span] pub Span); + +#[derive(Diagnostic)] +#[diag(parse_invalid_offset_of)] +pub(crate) struct InvalidOffsetOf(#[primary_span] pub Span); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index bf6151b64d3f1..739d7384fdac2 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1023,7 +1023,7 @@ impl<'a> Parser<'a> { // we should break everything including floats into more basic proc-macro style // tokens in the lexer (probably preferable). // See also `TokenKind::break_two_token_op` which does similar splitting of `>>` into `>`. - fn break_up_float(&mut self, float: Symbol) -> DestructuredFloat { + fn break_up_float(&self, float: Symbol, span: Span) -> DestructuredFloat { #[derive(Debug)] enum FloatComponent { IdentLike(String), @@ -1053,7 +1053,6 @@ impl<'a> Parser<'a> { // With proc macros the span can refer to anything, the source may be too short, // or too long, or non-ASCII. It only makes sense to break our span into components // if its underlying text is identical to our float literal. - let span = self.token.span; let can_take_span_apart = || self.span_to_snippet(span).as_deref() == Ok(float_str).as_deref(); @@ -1115,7 +1114,7 @@ impl<'a> Parser<'a> { float: Symbol, suffix: Option, ) -> P { - match self.break_up_float(float) { + match self.break_up_float(float, self.token.span) { // 1e2 DestructuredFloat::Single(sym, _sp) => { self.parse_expr_tuple_field_access(lo, base, sym, suffix, None) @@ -1143,40 +1142,105 @@ impl<'a> Parser<'a> { } } - fn parse_field_name_maybe_tuple(&mut self) -> PResult<'a, ThinVec> { - let token::Literal(token::Lit { kind: token::Float, symbol, suffix }) = self.token.kind - else { - return Ok(thin_vec![self.parse_field_name()?]); - }; - Ok(match self.break_up_float(symbol) { - // 1e2 - DestructuredFloat::Single(sym, sp) => { - self.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` - self.break_last_token = true; - // This might work, in cases like `1. 2`, and might not, - // in cases like `offset_of!(Ty, 1.)`. It depends on what comes - // after the float-like token, and therefore we have to make - // the other parts of the parser think that there is a dot literal. - self.token = Token::new(token::Ident(sym, false), sym_span); - self.bump_with((Token::new(token::Dot, dot_span), self.token_spacing)); - thin_vec![Ident::new(sym, sym_span)] - } - // 1.2 | 1.2e3 - DestructuredFloat::MiddleDot(symbol1, ident1_span, _dot_span, symbol2, ident2_span) => { - self.bump(); - thin_vec![Ident::new(symbol1, ident1_span), Ident::new(symbol2, ident2_span)] + /// Parse the field access used in offset_of, matched by `$(e:expr)+`. + /// Currently returns a list of idents. However, it should be possible in + /// future to also do array indices, which might be arbitrary expressions. + fn parse_floating_field_access(&mut self) -> PResult<'a, P<[Ident]>> { + let mut fields = Vec::new(); + let mut trailing_dot = None; + + loop { + // This is expected to use a metavariable $(args:expr)+, but the builtin syntax + // could be called directly. Calling `parse_expr` allows this function to only + // consider `Expr`s. + let expr = self.parse_expr()?; + let mut current = &expr; + let start_idx = fields.len(); + loop { + match current.kind { + ExprKind::Field(ref left, right) => { + // Field access is read right-to-left. + fields.insert(start_idx, right); + trailing_dot = None; + current = left; + } + // Parse this both to give helpful error messages and to + // verify it can be done with this parser setup. + ExprKind::Index(ref left, ref _right, span) => { + self.sess.emit_err(errors::ArrayIndexInOffsetOf(span)); + current = left; + } + ExprKind::Lit(token::Lit { + kind: token::Float | token::Integer, + symbol, + suffix, + }) => { + if let Some(suffix) = suffix { + self.expect_no_tuple_index_suffix(current.span, suffix); + } + match self.break_up_float(symbol, current.span) { + // 1e2 + DestructuredFloat::Single(sym, sp) => { + trailing_dot = None; + fields.insert(start_idx, Ident::new(sym, sp)); + } + // 1. + DestructuredFloat::TrailingDot(sym, sym_span, dot_span) => { + assert!(suffix.is_none()); + trailing_dot = Some(dot_span); + fields.insert(start_idx, Ident::new(sym, sym_span)); + } + // 1.2 | 1.2e3 + DestructuredFloat::MiddleDot( + symbol1, + span1, + _dot_span, + symbol2, + span2, + ) => { + trailing_dot = None; + fields.insert(start_idx, Ident::new(symbol2, span2)); + fields.insert(start_idx, Ident::new(symbol1, span1)); + } + DestructuredFloat::Error => { + trailing_dot = None; + fields.insert(start_idx, Ident::new(symbol, self.prev_token.span)); + } + } + break; + } + ExprKind::Path(None, Path { ref segments, .. }) => { + match &segments[..] { + [PathSegment { ident, args: None, .. }] => { + trailing_dot = None; + fields.insert(start_idx, *ident) + } + _ => { + self.sess.emit_err(errors::InvalidOffsetOf(current.span)); + break; + } + } + break; + } + _ => { + self.sess.emit_err(errors::InvalidOffsetOf(current.span)); + break; + } + } } - DestructuredFloat::Error => { - self.bump(); - thin_vec![Ident::new(symbol, self.prev_token.span)] + + if matches!(self.token.kind, token::CloseDelim(..) | token::Comma) { + break; + } else if trailing_dot.is_none() { + // This loop should only repeat if there is a trailing dot. + self.sess.emit_err(errors::InvalidOffsetOf(self.token.span)); + break; } - }) + } + if let Some(dot) = trailing_dot { + self.sess.emit_err(errors::InvalidOffsetOf(dot)); + } + Ok(fields.into_iter().collect()) } fn parse_expr_tuple_field_access( @@ -1907,15 +1971,29 @@ impl<'a> Parser<'a> { let container = self.parse_ty()?; self.expect(&TokenKind::Comma)?; - let seq_sep = SeqSep { sep: Some(token::Dot), trailing_sep_allowed: false }; - let (fields, _trailing, _recovered) = self.parse_seq_to_before_end( - &TokenKind::CloseDelim(Delimiter::Parenthesis), - seq_sep, - Parser::parse_field_name_maybe_tuple, - )?; - let fields = fields.into_iter().flatten().collect::>(); + let fields = self.parse_floating_field_access()?; + let trailing_comma = self.eat_noexpect(&TokenKind::Comma); + + if let Err(mut e) = + self.expect_one_of(&[], &[TokenKind::CloseDelim(Delimiter::Parenthesis)]) + { + if trailing_comma { + e.note("unexpected third argument to offset_of"); + } else { + e.note("offset_of expects dot-separated field and variant names"); + } + e.emit(); + } + + // Eat tokens until the macro call ends. + if self.may_recover() { + while !matches!(self.token.kind, token::CloseDelim(..) | token::Eof) { + self.bump(); + } + } + let span = lo.to(self.token.span); - Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields.into()))) + Ok(self.mk_expr(span, ExprKind::OffsetOf(container, fields))) } /// Returns a string literal if the next token is a string literal. diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index c1687abb7cb9c..407954001e4ce 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1395,8 +1395,18 @@ impl SizedTypeProperties for T {} /// /// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); /// ``` +#[cfg(not(bootstrap))] #[unstable(feature = "offset_of", issue = "106655")] #[allow_internal_unstable(builtin_syntax, hint_must_use)] +pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { + // The `{}` is for better error messages + crate::hint::must_use({builtin # offset_of($Container, $($fields)+)}) +} + +#[cfg(bootstrap)] +#[unstable(feature = "offset_of", issue = "106655")] +#[allow_internal_unstable(builtin_syntax, hint_must_use)] +#[allow(missing_docs)] pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) { // The `{}` is for better error messages crate::hint::must_use({builtin # offset_of($Container, $($fields).+)}) diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs index 31de45bc7567f..7b92698c25e8a 100644 --- a/tests/ui/offset-of/offset-of-arg-count.rs +++ b/tests/ui/offset-of/offset-of-arg-count.rs @@ -8,10 +8,10 @@ fn main() { offset_of!(Container, field, too many arguments); //~ ERROR no rules expected the token `too` offset_of!(S, f); // compiles fine offset_of!(S, f,); // also compiles fine - offset_of!(S, f.); //~ ERROR unexpected end of macro invocation - offset_of!(S, f.,); //~ ERROR expected identifier - offset_of!(S, f..); //~ ERROR no rules expected the token - offset_of!(S, f..,); //~ ERROR no rules expected the token + offset_of!(S, f.); //~ ERROR unexpected token: `)` + offset_of!(S, f.,); //~ ERROR unexpected token: `,` + offset_of!(S, f..); //~ ERROR offset_of expects dot-separated field and variant names + offset_of!(S, f..,); //~ ERROR offset_of expects dot-separated field and variant names offset_of!(Lt<'static>, bar); // issue #111657 offset_of!(Lt<'_>, bar); // issue #111678 } diff --git a/tests/ui/offset-of/offset-of-arg-count.stderr b/tests/ui/offset-of/offset-of-arg-count.stderr index 4275a89545f50..af0d42de30d60 100644 --- a/tests/ui/offset-of/offset-of-arg-count.stderr +++ b/tests/ui/offset-of/offset-of-arg-count.stderr @@ -13,7 +13,7 @@ error: unexpected end of macro invocation LL | offset_of!(NotEnoughArgumentsWithAComma, ); | ^ missing tokens in macro arguments | -note: while trying to match meta-variable `$fields:tt` +note: while trying to match meta-variable `$fields:expr` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL error: no rules expected the token `too` @@ -24,36 +24,29 @@ LL | offset_of!(Container, field, too many arguments); | = note: while trying to match sequence end -error: unexpected end of macro invocation +error: unexpected token: `)` --> $DIR/offset-of-arg-count.rs:11:21 | LL | offset_of!(S, f.); - | ^ 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 `,` +error: unexpected token: `,` --> $DIR/offset-of-arg-count.rs:12:21 | LL | offset_of!(S, f.,); - | ^ expected identifier + | ^ -error: no rules expected the token `..` - --> $DIR/offset-of-arg-count.rs:13:20 +error: offset_of expects dot-separated field and variant names + --> $DIR/offset-of-arg-count.rs:13:19 | LL | offset_of!(S, f..); - | ^^ no rules expected this token in macro call - | - = note: while trying to match sequence start + | ^^^ -error: no rules expected the token `..` - --> $DIR/offset-of-arg-count.rs:14:20 +error: offset_of expects dot-separated field and variant names + --> $DIR/offset-of-arg-count.rs:14:19 | LL | offset_of!(S, f..,); - | ^^ no rules expected this token in macro call - | - = note: while trying to match sequence start + | ^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/offset-of/offset-of-builtin.rs b/tests/ui/offset-of/offset-of-builtin.rs index 1be9899887b4a..6664c10f905ef 100644 --- a/tests/ui/offset-of/offset-of-builtin.rs +++ b/tests/ui/offset-of/offset-of-builtin.rs @@ -8,37 +8,25 @@ fn main() { builtin # offset_of(NotEnoughArguments); //~ ERROR expected one of } fn t1() { - // Already errored upon at the macro level. Yielding an error would require - // extra effort. - builtin # offset_of(NotEnoughArgumentsWithAComma, ); + builtin # offset_of(NotEnoughArgumentsWithAComma, ); //~ ERROR expected expression } fn t2() { - builtin # offset_of(Container, field, too many arguments); //~ ERROR expected identifier, found - //~| ERROR found `,` - //~| ERROR found `many` - //~| ERROR found `arguments` + builtin # offset_of(S, f, too many arguments); //~ ERROR expected `)`, found `too` } fn t3() { builtin # offset_of(S, f); // compiles fine } fn t4() { - // Already errored upon at the macro level. Yielding an error would require - // extra effort. - builtin # offset_of(S, f); + builtin # offset_of(S, f.); //~ ERROR unexpected token } fn t5() { - builtin # offset_of(S, f.); //~ ERROR expected identifier + builtin # offset_of(S, f.,); //~ ERROR unexpected token } fn t6() { - builtin # offset_of(S, f.,); //~ ERROR expected identifier + builtin # offset_of(S, f..); //~ ERROR offset_of expects dot-separated field and variant names } fn t7() { - builtin # offset_of(S, f..); //~ ERROR expected one of -} -fn t8() { - // Already errored upon at the macro level. Yielding an error would require - // extra effort. - builtin # offset_of(S, f..,); + builtin # offset_of(S, f..,); //~ ERROR offset_of expects dot-separated field and variant names } struct S { f: u8, } diff --git a/tests/ui/offset-of/offset-of-builtin.stderr b/tests/ui/offset-of/offset-of-builtin.stderr index 1a1f33cc613a7..5917ee2936361 100644 --- a/tests/ui/offset-of/offset-of-builtin.stderr +++ b/tests/ui/offset-of/offset-of-builtin.stderr @@ -4,62 +4,43 @@ error: expected one of `!`, `(`, `+`, `,`, `::`, or `<`, found `)` LL | builtin # offset_of(NotEnoughArguments); | ^ expected one of `!`, `(`, `+`, `,`, `::`, or `<` -error: expected identifier, found `,` - --> $DIR/offset-of-builtin.rs:16:41 +error: expected expression, found `)` + --> $DIR/offset-of-builtin.rs:11:55 | -LL | builtin # offset_of(Container, field, too many arguments); - | ^ - | | - | expected identifier - | help: remove this comma +LL | builtin # offset_of(NotEnoughArgumentsWithAComma, ); + | ^ expected expression -error: expected one of `)` or `.`, found `,` - --> $DIR/offset-of-builtin.rs:16:41 +error: expected `)`, found `too` + --> $DIR/offset-of-builtin.rs:14:31 | -LL | builtin # offset_of(Container, field, too many arguments); - | ^ - | | - | expected one of `)` or `.` - | help: missing `.` - -error: expected one of `)` or `.`, found `many` - --> $DIR/offset-of-builtin.rs:16:47 - | -LL | builtin # offset_of(Container, field, too many arguments); - | -^^^^ expected one of `)` or `.` - | | - | help: missing `.` - -error: expected one of `)` or `.`, found `arguments` - --> $DIR/offset-of-builtin.rs:16:52 +LL | builtin # offset_of(S, f, too many arguments); + | ^^^ expected `)` | -LL | builtin # offset_of(Container, field, too many arguments); - | -^^^^^^^^^ expected one of `)` or `.` - | | - | help: missing `.` + = note: unexpected third argument to offset_of -error: expected identifier, found `)` - --> $DIR/offset-of-builtin.rs:30:30 +error: unexpected token: `)` + --> $DIR/offset-of-builtin.rs:20:30 | LL | builtin # offset_of(S, f.); - | ^ expected identifier + | ^ -error: expected identifier, found `,` - --> $DIR/offset-of-builtin.rs:33:30 +error: unexpected token: `,` + --> $DIR/offset-of-builtin.rs:23:30 | LL | builtin # offset_of(S, f.,); - | ^ expected identifier + | ^ -error: expected one of `)` or `.`, found `..` - --> $DIR/offset-of-builtin.rs:36:29 +error: offset_of expects dot-separated field and variant names + --> $DIR/offset-of-builtin.rs:26:28 | LL | builtin # offset_of(S, f..); - | ^^ expected one of `)` or `.` - | -help: if you meant to bind the contents of the rest of the array pattern into `f`, use `@` + | ^^^ + +error: offset_of expects dot-separated field and variant names + --> $DIR/offset-of-builtin.rs:29:28 | -LL | builtin # offset_of(S, f @ ..); - | + +LL | builtin # offset_of(S, f..,); + | ^^^ -error: aborting due to 8 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs index dbeef0e74dc37..04dcaf7c0a6b6 100644 --- a/tests/ui/offset-of/offset-of-self.rs +++ b/tests/ui/offset-of/offset-of-self.rs @@ -17,9 +17,8 @@ impl S { offset_of!(Self, v) } fn v_offs_wrong_syntax() { - offset_of!(Self, Self::v); //~ ERROR no rules expected the token `::` - offset_of!(S, Self); //~ ERROR expected identifier, found keyword `Self` - //~| no field `Self` on type `S` + offset_of!(Self, Self::v); //~ offset_of expects dot-separated field and variant names + offset_of!(S, Self); //~ no field `Self` on type `S` } fn offs_in_c() -> usize { offset_of!(C, w) @@ -51,8 +50,6 @@ fn main() { offset_of!(self::S, v); offset_of!(Self, v); //~ ERROR cannot find type `Self` in this scope - offset_of!(S, self); //~ ERROR expected identifier, found keyword `self` - //~| no field `self` on type `S` - offset_of!(S, v.self); //~ ERROR expected identifier, found keyword `self` - //~| no field `self` on type `u8` + offset_of!(S, self); //~ no field `self` on type `S` + offset_of!(S, v.self); //~ no field `self` on type `u8` } diff --git a/tests/ui/offset-of/offset-of-self.stderr b/tests/ui/offset-of/offset-of-self.stderr index 2dc17189a702e..7c7576e066b6f 100644 --- a/tests/ui/offset-of/offset-of-self.stderr +++ b/tests/ui/offset-of/offset-of-self.stderr @@ -1,31 +1,11 @@ -error: no rules expected the token `::` - --> $DIR/offset-of-self.rs:20:30 +error: offset_of expects dot-separated field and variant names + --> $DIR/offset-of-self.rs:20:26 | LL | offset_of!(Self, Self::v); - | ^^ no rules expected this token in macro call - | - = note: while trying to match sequence start - -error: expected identifier, found keyword `Self` - --> $DIR/offset-of-self.rs:21:23 - | -LL | offset_of!(S, Self); - | ^^^^ expected identifier, found keyword - -error: expected identifier, found keyword `self` - --> $DIR/offset-of-self.rs:54:19 - | -LL | offset_of!(S, self); - | ^^^^ expected identifier, found keyword - -error: expected identifier, found keyword `self` - --> $DIR/offset-of-self.rs:56:21 - | -LL | offset_of!(S, v.self); - | ^^^^ expected identifier, found keyword + | ^^^^^^^ error[E0412]: cannot find type `S` in module `self` - --> $DIR/offset-of-self.rs:35:26 + --> $DIR/offset-of-self.rs:34:26 | LL | offset_of!(self::S, v); | ^ not found in `self` @@ -41,7 +21,7 @@ LL + offset_of!(S, v); | error[E0411]: cannot find type `Self` in this scope - --> $DIR/offset-of-self.rs:52:16 + --> $DIR/offset-of-self.rs:51:16 | LL | fn main() { | ---- `Self` not allowed in a function @@ -58,13 +38,13 @@ LL | offset_of!(S, Self); = note: available fields are: `v`, `w` error[E0616]: field `v` of struct `T` is private - --> $DIR/offset-of-self.rs:41:30 + --> $DIR/offset-of-self.rs:40:30 | LL | offset_of!(Self, v) | ^ private field error[E0609]: no field `self` on type `S` - --> $DIR/offset-of-self.rs:54:19 + --> $DIR/offset-of-self.rs:53:19 | LL | offset_of!(S, self); | ^^^^ @@ -72,12 +52,12 @@ LL | offset_of!(S, self); = note: available fields are: `v`, `w` error[E0609]: no field `self` on type `u8` - --> $DIR/offset-of-self.rs:56:21 + --> $DIR/offset-of-self.rs:54:21 | LL | offset_of!(S, v.self); | ^^^^ -error: aborting due to 10 previous errors +error: aborting due to 7 previous errors Some errors have detailed explanations: E0411, E0412, E0609, E0616. For more information about an error, try `rustc --explain E0411`. diff --git a/tests/ui/offset-of/offset-of-tuple-nested.rs b/tests/ui/offset-of/offset-of-tuple-nested.rs index 00fbb6bf8f407..59b02e3c5c433 100644 --- a/tests/ui/offset-of/offset-of-tuple-nested.rs +++ b/tests/ui/offset-of/offset-of-tuple-nested.rs @@ -3,7 +3,6 @@ // similar to why `offset-of-unsized.rs` is also build-pass #![feature(offset_of)] -#![feature(builtin_syntax)] use std::mem::offset_of; @@ -17,13 +16,13 @@ fn main() { // 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!("{}", 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)); diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs index e31b037ee3e01..b6fc1e32229a1 100644 --- a/tests/ui/offset-of/offset-of-tuple.rs +++ b/tests/ui/offset-of/offset-of-tuple.rs @@ -10,9 +10,9 @@ fn main() { 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 + offset_of!((u8, u8), -1); //~ ERROR offset_of expects dot-separated field and variant names + offset_of!((u8, u8), 1.); //~ ERROR offset_of expects dot-separated field and variant names + offset_of!((u8, u8), 1 .); //~ unexpected token: `)` 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), 01); //~ ERROR no field `01` @@ -20,12 +20,12 @@ fn main() { //~| 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 `)` + { builtin # offset_of((u8, u8), +1) }; //~ ERROR leading `+` is not supported + { builtin # offset_of((u8, u8), 1.) }; //~ ERROR offset_of expects dot-separated field and variant names + { builtin # offset_of((u8, u8), 1 .) }; //~ ERROR unexpected token: `)` } -type ComplexTup = ((u8, (u8, u8)), u8); +type ComplexTup = (((u8, u8), u8), u8); fn nested() { offset_of!(((u8, u16), (u32, u16, u8)), 0.2); //~ ERROR no field `2` @@ -33,22 +33,22 @@ fn nested() { 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 `)` + offset_of!(ComplexTup, 0.0.1.); //~ ERROR unexpected token: `)` + offset_of!(ComplexTup, 0 .0.1.); //~ ERROR unexpected token: `)` + offset_of!(ComplexTup, 0 . 0.1.); //~ ERROR unexpected token: `)` + offset_of!(ComplexTup, 0. 0.1.); //~ ERROR unexpected token: `)` + offset_of!(ComplexTup, 0.0 .1.); //~ ERROR unexpected token: `)` + offset_of!(ComplexTup, 0.0 . 1.); //~ ERROR unexpected token: `)` + offset_of!(ComplexTup, 0.0. 1.); //~ ERROR unexpected token: `)` // 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 `)` + { builtin # offset_of(ComplexTup, 0.0.1.) }; //~ ERROR unexpected token: `)` + { builtin # offset_of(ComplexTup, 0 .0.1.) }; //~ ERROR unexpected token: `)` + { builtin # offset_of(ComplexTup, 0 . 0.1.) }; //~ ERROR unexpected token: `)` + { builtin # offset_of(ComplexTup, 0. 0.1.) }; //~ ERROR unexpected token: `)` + { builtin # offset_of(ComplexTup, 0.0 .1.) }; //~ ERROR unexpected token: `)` + { builtin # offset_of(ComplexTup, 0.0 . 1.) }; //~ ERROR unexpected token: `)` + { builtin # offset_of(ComplexTup, 0.0. 1.) }; //~ ERROR unexpected token: `)` } diff --git a/tests/ui/offset-of/offset-of-tuple.stderr b/tests/ui/offset-of/offset-of-tuple.stderr index ed9523458063d..e9aa495becdfa 100644 --- a/tests/ui/offset-of/offset-of-tuple.stderr +++ b/tests/ui/offset-of/offset-of-tuple.stderr @@ -4,65 +4,71 @@ error: suffixes on a tuple index are invalid LL | builtin # offset_of((u8, u8), 1_u8); | ^^^^ invalid suffix `u8` -error: expected identifier, found `+` +error: leading `+` is not supported --> $DIR/offset-of-tuple.rs:23:37 | LL | { builtin # offset_of((u8, u8), +1) }; - | ^ expected identifier + | ^ unexpected `+` + | +help: try removing the `+` + | +LL - { builtin # offset_of((u8, u8), +1) }; +LL + { builtin # offset_of((u8, u8), 1) }; + | -error: expected identifier, found `)` - --> $DIR/offset-of-tuple.rs:24:39 +error: offset_of expects dot-separated field and variant names + --> $DIR/offset-of-tuple.rs:24:38 | LL | { builtin # offset_of((u8, u8), 1.) }; - | ^ expected identifier + | ^ -error: expected identifier, found `)` +error: unexpected token: `)` --> $DIR/offset-of-tuple.rs:25:40 | LL | { builtin # offset_of((u8, u8), 1 .) }; - | ^ expected identifier + | ^ -error: expected identifier, found `)` +error: unexpected token: `)` --> $DIR/offset-of-tuple.rs:47:45 | LL | { builtin # offset_of(ComplexTup, 0.0.1.) }; - | ^ expected identifier + | ^ -error: expected identifier, found `)` +error: unexpected token: `)` --> $DIR/offset-of-tuple.rs:48:46 | LL | { builtin # offset_of(ComplexTup, 0 .0.1.) }; - | ^ expected identifier + | ^ -error: expected identifier, found `)` +error: unexpected token: `)` --> $DIR/offset-of-tuple.rs:49:47 | LL | { builtin # offset_of(ComplexTup, 0 . 0.1.) }; - | ^ expected identifier + | ^ -error: expected identifier, found `)` +error: unexpected token: `)` --> $DIR/offset-of-tuple.rs:50:46 | LL | { builtin # offset_of(ComplexTup, 0. 0.1.) }; - | ^ expected identifier + | ^ -error: expected identifier, found `)` +error: unexpected token: `)` --> $DIR/offset-of-tuple.rs:51:46 | LL | { builtin # offset_of(ComplexTup, 0.0 .1.) }; - | ^ expected identifier + | ^ -error: expected identifier, found `)` +error: unexpected token: `)` --> $DIR/offset-of-tuple.rs:52:47 | LL | { builtin # offset_of(ComplexTup, 0.0 . 1.) }; - | ^ expected identifier + | ^ -error: expected identifier, found `)` +error: unexpected token: `)` --> $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 @@ -70,96 +76,74 @@ error: suffixes on a tuple index are invalid LL | offset_of!((u8, u8), 1_u8); | ^^^^ invalid suffix `u8` -error: no rules expected the token `1` - --> $DIR/offset-of-tuple.rs:12:27 +error: no rules expected the token `+` + --> $DIR/offset-of-tuple.rs:12:26 | LL | offset_of!((u8, u8), +1); - | ^ no rules expected this token in macro call + | ^ no rules expected this token in macro call | - = note: while trying to match sequence start +note: while trying to match meta-variable `$fields:expr` + --> $SRC_DIR/core/src/mem/mod.rs:LL:COL -error: no rules expected the token `1` - --> $DIR/offset-of-tuple.rs:13:27 +error: offset_of expects dot-separated field and variant names + --> $DIR/offset-of-tuple.rs:13:26 | 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 +error: offset_of expects dot-separated field and variant names + --> $DIR/offset-of-tuple.rs:14:27 | LL | offset_of!((u8, u8), 1.); - | ^^^^^^^^^^^^^^^^^^^^^^^^ expected identifier - | - = 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 +error: unexpected token: `)` --> $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 +error: unexpected token: `)` + --> $DIR/offset-of-tuple.rs:36:34 | LL | offset_of!(ComplexTup, 0.0.1.); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected identifier - | - = 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 +error: unexpected token: `)` --> $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 +error: unexpected token: `)` --> $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 +error: unexpected token: `)` + --> $DIR/offset-of-tuple.rs:39:35 | 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 +error: unexpected token: `)` + --> $DIR/offset-of-tuple.rs:40:35 | LL | offset_of!(ComplexTup, 0.0 .1.); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected identifier - | - = 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 +error: unexpected token: `)` + --> $DIR/offset-of-tuple.rs:41:36 | LL | offset_of!(ComplexTup, 0.0 . 1.); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected identifier - | - = 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 +error: unexpected token: `)` + --> $DIR/offset-of-tuple.rs:42:35 | LL | offset_of!(ComplexTup, 0.0. 1.); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected identifier - | - = 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:7:26 @@ -212,8 +196,16 @@ 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); - | ^ +LL | offset_of!(((u8, u16), (u32, u16, u8)), 0.2); + | _____------------------------------------------^- + | | | + | | in this macro invocation +LL | | offset_of!(((u8, u16), (u32, u16, u8)), 1.2); +LL | | offset_of!(((u8, u16), (u32, u16, u8)), 1.2.0); +LL | | +... | + | + = 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` --> $DIR/offset-of-tuple.rs:33:49 From f0c0a498b86313468f20f0aa42ffc4fc685cacd2 Mon Sep 17 00:00:00 2001 From: George Bateman Date: Tue, 2 Jan 2024 23:13:08 +0000 Subject: [PATCH 2/2] Update after rebase --- compiler/rustc_parse/src/parser/expr.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 739d7384fdac2..0b24e78412635 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1167,7 +1167,7 @@ impl<'a> Parser<'a> { // Parse this both to give helpful error messages and to // verify it can be done with this parser setup. ExprKind::Index(ref left, ref _right, span) => { - self.sess.emit_err(errors::ArrayIndexInOffsetOf(span)); + self.dcx().emit_err(errors::ArrayIndexInOffsetOf(span)); current = left; } ExprKind::Lit(token::Lit { @@ -1216,14 +1216,14 @@ impl<'a> Parser<'a> { fields.insert(start_idx, *ident) } _ => { - self.sess.emit_err(errors::InvalidOffsetOf(current.span)); + self.dcx().emit_err(errors::InvalidOffsetOf(current.span)); break; } } break; } _ => { - self.sess.emit_err(errors::InvalidOffsetOf(current.span)); + self.dcx().emit_err(errors::InvalidOffsetOf(current.span)); break; } } @@ -1233,12 +1233,12 @@ impl<'a> Parser<'a> { break; } else if trailing_dot.is_none() { // This loop should only repeat if there is a trailing dot. - self.sess.emit_err(errors::InvalidOffsetOf(self.token.span)); + self.dcx().emit_err(errors::InvalidOffsetOf(self.token.span)); break; } } if let Some(dot) = trailing_dot { - self.sess.emit_err(errors::InvalidOffsetOf(dot)); + self.dcx().emit_err(errors::InvalidOffsetOf(dot)); } Ok(fields.into_iter().collect()) }