From 8e256b19d529ebf9021030e17791e23a1212ff1e Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sat, 18 Apr 2020 21:26:10 +0300 Subject: [PATCH 1/9] parser: Break float tokens into parts in tuple field positions --- src/librustc_parse/parser/expr.rs | 119 ++++--- src/test/ui/parser/float-field.rs | 62 ++++ src/test/ui/parser/float-field.stderr | 349 +++++++++++++++++++++ src/test/ui/tuple/tuple-float-index.fixed | 5 - src/test/ui/tuple/tuple-float-index.rs | 5 - src/test/ui/tuple/tuple-float-index.stderr | 11 - 6 files changed, 492 insertions(+), 59 deletions(-) create mode 100644 src/test/ui/parser/float-field.rs create mode 100644 src/test/ui/parser/float-field.stderr delete mode 100644 src/test/ui/tuple/tuple-float-index.fixed delete mode 100644 src/test/ui/tuple/tuple-float-index.rs delete mode 100644 src/test/ui/tuple/tuple-float-index.stderr diff --git a/src/librustc_parse/parser/expr.rs b/src/librustc_parse/parser/expr.rs index abb444933536f..d52cea74520bd 100644 --- a/src/librustc_parse/parser/expr.rs +++ b/src/librustc_parse/parser/expr.rs @@ -770,10 +770,10 @@ impl<'a> Parser<'a> { match self.token.uninterpolate().kind { token::Ident(..) => self.parse_dot_suffix(base, lo), token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) => { - Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix)) + Ok(self.parse_tuple_field_access_expr(lo, base, symbol, suffix, None)) } - token::Literal(token::Lit { kind: token::Float, symbol, .. }) => { - self.recover_field_access_by_float_lit(lo, base, symbol) + token::Literal(token::Lit { kind: token::Float, symbol, suffix }) => { + Ok(self.parse_tuple_field_access_expr_float(lo, base, symbol, suffix)) } _ => { self.error_unexpected_after_dot(); @@ -788,45 +788,84 @@ impl<'a> Parser<'a> { self.struct_span_err(self.token.span, &format!("unexpected token: `{}`", actual)).emit(); } - fn recover_field_access_by_float_lit( + // We need and identifier or integer, but the next token is a float. + // Break the float into components to extract the identifier or integer. + // FIXME: With current `TokenCursor` it's hard to break tokens into more than 2 + // parts unless those parts are processed immediately. `TokenCursor` should either + // support pushing "future tokens" (would be also helpful to `break_and_eat`), or + // we should break everything including floats into more basic proc-macro style + // tokens in the lexer (probably preferable). + fn parse_tuple_field_access_expr_float( &mut self, lo: Span, base: P, - sym: Symbol, - ) -> PResult<'a, P> { - self.bump(); - - let fstr = sym.as_str(); - let msg = format!("unexpected token: `{}`", sym); - - let mut err = self.struct_span_err(self.prev_token.span, &msg); - err.span_label(self.prev_token.span, "unexpected token"); - - if fstr.chars().all(|x| "0123456789.".contains(x)) { - let float = match fstr.parse::() { - Ok(f) => f, - Err(_) => { - err.emit(); - return Ok(base); + float: Symbol, + suffix: Option, + ) -> P { + #[derive(Debug)] + enum FloatComponent { + IdentLike(String), + Punct(char), + } + use FloatComponent::*; + + let mut components = Vec::new(); + let mut ident_like = String::new(); + for c in float.as_str().chars() { + if c == '_' || c.is_ascii_alphanumeric() { + ident_like.push(c); + } else if matches!(c, '.' | '+' | '-') { + if !ident_like.is_empty() { + components.push(IdentLike(mem::take(&mut ident_like))); } - }; - let sugg = pprust::to_string(|s| { - s.popen(); - s.print_expr(&base); - s.s.word("."); - s.print_usize(float.trunc() as usize); - s.pclose(); - s.s.word("."); - s.s.word(fstr.splitn(2, '.').last().unwrap().to_string()) - }); - err.span_suggestion( - lo.to(self.prev_token.span), - "try parenthesizing the first index", - sugg, - Applicability::MachineApplicable, - ); + components.push(Punct(c)); + } else { + panic!("unexpected character in a float token: {:?}", c) + } + } + if !ident_like.is_empty() { + components.push(IdentLike(ident_like)); + } + + // FIXME: Make the span more precise. + let span = self.token.span; + match &*components { + // 1e2 + [IdentLike(i)] => { + self.parse_tuple_field_access_expr(lo, base, Symbol::intern(&i), suffix, None) + } + // 1. + [IdentLike(i), Punct('.')] => { + assert!(suffix.is_none()); + let symbol = Symbol::intern(&i); + self.token = Token::new(token::Ident(symbol, false), span); + let next_token = Token::new(token::Dot, span); + self.parse_tuple_field_access_expr(lo, base, symbol, None, Some(next_token)) + } + // 1.2 | 1.2e3 + [IdentLike(i1), Punct('.'), IdentLike(i2)] => { + let symbol1 = Symbol::intern(&i1); + self.token = Token::new(token::Ident(symbol1, false), span); + let next_token1 = Token::new(token::Dot, span); + let base1 = + self.parse_tuple_field_access_expr(lo, base, symbol1, None, Some(next_token1)); + let symbol2 = Symbol::intern(&i2); + let next_token2 = Token::new(token::Ident(symbol2, false), span); + self.bump_with(next_token2); // `.` + self.parse_tuple_field_access_expr(lo, base1, symbol2, suffix, None) + } + // 1e+ | 1e- (recovered) + [IdentLike(_), Punct('+' | '-')] | + // 1e+2 | 1e-2 + [IdentLike(_), Punct('+' | '-'), IdentLike(_)] | + // 1.2e+3 | 1.2e-3 + [IdentLike(_), Punct('.'), IdentLike(_), Punct('+' | '-'), IdentLike(_)] => { + // See the FIXME about `TokenCursor` above. + self.error_unexpected_after_dot(); + base + } + _ => panic!("unexpected components in a float token: {:?}", components), } - Err(err) } fn parse_tuple_field_access_expr( @@ -835,8 +874,12 @@ impl<'a> Parser<'a> { base: P, field: Symbol, suffix: Option, + next_token: Option, ) -> P { - self.bump(); + match next_token { + Some(next_token) => self.bump_with(next_token), + None => self.bump(), + } let span = self.prev_token.span; let field = ExprKind::Field(base, Ident::new(field, span)); self.expect_no_suffix(span, "a tuple index", suffix); diff --git a/src/test/ui/parser/float-field.rs b/src/test/ui/parser/float-field.rs new file mode 100644 index 0000000000000..eaa7465dc4d06 --- /dev/null +++ b/src/test/ui/parser/float-field.rs @@ -0,0 +1,62 @@ +struct S(u8, (u8, u8)); + +fn main() { + let s = S(0, (0, 0)); + + s.1e1; //~ ERROR no field `1e1` on type `S` + s.1.; //~ ERROR unexpected token: `;` + s.1.1; + s.1.1e1; //~ ERROR no field `1e1` on type `(u8, u8)` + { s.1e+; } //~ ERROR unexpected token: `1e+` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+` + //~| ERROR expected at least one digit in exponent + { s.1e-; } //~ ERROR unexpected token: `1e-` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-` + //~| ERROR expected at least one digit in exponent + { s.1e+1; } //~ ERROR unexpected token: `1e+1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1` + { s.1e-1; } //~ ERROR unexpected token: `1e-1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1` + { s.1.1e+1; } //~ ERROR unexpected token: `1.1e+1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1` + { s.1.1e-1; } //~ ERROR unexpected token: `1.1e-1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1` + s.0x1e1; //~ ERROR no field `0x1e1` on type `S` + s.0x1.; //~ ERROR no field `0x1` on type `S` + //~| ERROR hexadecimal float literal is not supported + //~| ERROR unexpected token: `;` + s.0x1.1; //~ ERROR no field `0x1` on type `S` + //~| ERROR hexadecimal float literal is not supported + s.0x1.1e1; //~ ERROR no field `0x1` on type `S` + //~| ERROR hexadecimal float literal is not supported + { s.0x1e+; } //~ ERROR expected expression, found `;` + { s.0x1e-; } //~ ERROR expected expression, found `;` + s.0x1e+1; //~ ERROR no field `0x1e` on type `S` + s.0x1e-1; //~ ERROR no field `0x1e` on type `S` + { s.0x1.1e+1; } //~ ERROR unexpected token: `0x1.1e+1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e+1` + //~| ERROR hexadecimal float literal is not supported + { s.0x1.1e-1; } //~ ERROR unexpected token: `0x1.1e-1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e-1` + //~| ERROR hexadecimal float literal is not supported + s.1e1f32; //~ ERROR no field `1e1` on type `S` + //~| ERROR suffixes on a tuple index are invalid + s.1.f32; //~ ERROR no field `f32` on type `(u8, u8)` + s.1.1f32; //~ ERROR suffixes on a tuple index are invalid + s.1.1e1f32; //~ ERROR no field `1e1` on type `(u8, u8)` + //~| ERROR suffixes on a tuple index are invalid + { s.1e+f32; } //~ ERROR unexpected token: `1e+f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+f32` + //~| ERROR expected at least one digit in exponent + { s.1e-f32; } //~ ERROR unexpected token: `1e-f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-f32` + //~| ERROR expected at least one digit in exponent + { s.1e+1f32; } //~ ERROR unexpected token: `1e+1f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1f32` + { s.1e-1f32; } //~ ERROR unexpected token: `1e-1f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1f32` + { s.1.1e+1f32; } //~ ERROR unexpected token: `1.1e+1f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1f32` + { s.1.1e-1f32; } //~ ERROR unexpected token: `1.1e-1f32` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1f32` +} diff --git a/src/test/ui/parser/float-field.stderr b/src/test/ui/parser/float-field.stderr new file mode 100644 index 0000000000000..62202b999648d --- /dev/null +++ b/src/test/ui/parser/float-field.stderr @@ -0,0 +1,349 @@ +error: expected at least one digit in exponent + --> $DIR/float-field.rs:10:9 + | +LL | { s.1e+; } + | ^^^ + +error: expected at least one digit in exponent + --> $DIR/float-field.rs:13:9 + | +LL | { s.1e-; } + | ^^^ + +error: hexadecimal float literal is not supported + --> $DIR/float-field.rs:25:7 + | +LL | s.0x1.; + | ^^^^ + +error: hexadecimal float literal is not supported + --> $DIR/float-field.rs:28:7 + | +LL | s.0x1.1; + | ^^^^^ + +error: hexadecimal float literal is not supported + --> $DIR/float-field.rs:30:7 + | +LL | s.0x1.1e1; + | ^^^^^^^ + +error: hexadecimal float literal is not supported + --> $DIR/float-field.rs:36:9 + | +LL | { s.0x1.1e+1; } + | ^^^^^^^^ + +error: hexadecimal float literal is not supported + --> $DIR/float-field.rs:39:9 + | +LL | { s.0x1.1e-1; } + | ^^^^^^^^ + +error: expected at least one digit in exponent + --> $DIR/float-field.rs:48:9 + | +LL | { s.1e+f32; } + | ^^^^^^ + +error: expected at least one digit in exponent + --> $DIR/float-field.rs:51:9 + | +LL | { s.1e-f32; } + | ^^^^^^ + +error: unexpected token: `;` + --> $DIR/float-field.rs:7:9 + | +LL | s.1.; + | ^ + +error: unexpected token: `1e+` + --> $DIR/float-field.rs:10:9 + | +LL | { s.1e+; } + | ^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+` + --> $DIR/float-field.rs:10:9 + | +LL | { s.1e+; } + | ^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e-` + --> $DIR/float-field.rs:13:9 + | +LL | { s.1e-; } + | ^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-` + --> $DIR/float-field.rs:13:9 + | +LL | { s.1e-; } + | ^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e+1` + --> $DIR/float-field.rs:16:9 + | +LL | { s.1e+1; } + | ^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1` + --> $DIR/float-field.rs:16:9 + | +LL | { s.1e+1; } + | ^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e-1` + --> $DIR/float-field.rs:18:9 + | +LL | { s.1e-1; } + | ^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1` + --> $DIR/float-field.rs:18:9 + | +LL | { s.1e-1; } + | ^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1.1e+1` + --> $DIR/float-field.rs:20:9 + | +LL | { s.1.1e+1; } + | ^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1` + --> $DIR/float-field.rs:20:9 + | +LL | { s.1.1e+1; } + | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1.1e-1` + --> $DIR/float-field.rs:22:9 + | +LL | { s.1.1e-1; } + | ^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1` + --> $DIR/float-field.rs:22:9 + | +LL | { s.1.1e-1; } + | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `;` + --> $DIR/float-field.rs:25:11 + | +LL | s.0x1.; + | ^ + +error: expected expression, found `;` + --> $DIR/float-field.rs:32:14 + | +LL | { s.0x1e+; } + | ^ expected expression + +error: expected expression, found `;` + --> $DIR/float-field.rs:33:14 + | +LL | { s.0x1e-; } + | ^ expected expression + +error: unexpected token: `0x1.1e+1` + --> $DIR/float-field.rs:36:9 + | +LL | { s.0x1.1e+1; } + | ^^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e+1` + --> $DIR/float-field.rs:36:9 + | +LL | { s.0x1.1e+1; } + | ^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `0x1.1e-1` + --> $DIR/float-field.rs:39:9 + | +LL | { s.0x1.1e-1; } + | ^^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e-1` + --> $DIR/float-field.rs:39:9 + | +LL | { s.0x1.1e-1; } + | ^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: suffixes on a tuple index are invalid + --> $DIR/float-field.rs:42:7 + | +LL | s.1e1f32; + | ^^^^^^ invalid suffix `f32` + +error: suffixes on a tuple index are invalid + --> $DIR/float-field.rs:45:7 + | +LL | s.1.1f32; + | ^^^^^^ invalid suffix `f32` + +error: suffixes on a tuple index are invalid + --> $DIR/float-field.rs:46:7 + | +LL | s.1.1e1f32; + | ^^^^^^^^ invalid suffix `f32` + +error: unexpected token: `1e+f32` + --> $DIR/float-field.rs:48:9 + | +LL | { s.1e+f32; } + | ^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+f32` + --> $DIR/float-field.rs:48:9 + | +LL | { s.1e+f32; } + | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e-f32` + --> $DIR/float-field.rs:51:9 + | +LL | { s.1e-f32; } + | ^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-f32` + --> $DIR/float-field.rs:51:9 + | +LL | { s.1e-f32; } + | ^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e+1f32` + --> $DIR/float-field.rs:54:9 + | +LL | { s.1e+1f32; } + | ^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1f32` + --> $DIR/float-field.rs:54:9 + | +LL | { s.1e+1f32; } + | ^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1e-1f32` + --> $DIR/float-field.rs:56:9 + | +LL | { s.1e-1f32; } + | ^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1f32` + --> $DIR/float-field.rs:56:9 + | +LL | { s.1e-1f32; } + | ^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1.1e+1f32` + --> $DIR/float-field.rs:58:9 + | +LL | { s.1.1e+1f32; } + | ^^^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1f32` + --> $DIR/float-field.rs:58:9 + | +LL | { s.1.1e+1f32; } + | ^^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: unexpected token: `1.1e-1f32` + --> $DIR/float-field.rs:60:9 + | +LL | { s.1.1e-1f32; } + | ^^^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1f32` + --> $DIR/float-field.rs:60:9 + | +LL | { s.1.1e-1f32; } + | ^^^^^^^^^ expected one of `.`, `;`, `?`, `}`, or an operator + +error[E0609]: no field `1e1` on type `S` + --> $DIR/float-field.rs:6:7 + | +LL | s.1e1; + | ^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `1e1` on type `(u8, u8)` + --> $DIR/float-field.rs:9:7 + | +LL | s.1.1e1; + | ^^^^^ + +error[E0609]: no field `0x1e1` on type `S` + --> $DIR/float-field.rs:24:7 + | +LL | s.0x1e1; + | ^^^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `0x1` on type `S` + --> $DIR/float-field.rs:25:7 + | +LL | s.0x1.; + | ^^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `0x1` on type `S` + --> $DIR/float-field.rs:28:7 + | +LL | s.0x1.1; + | ^^^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `0x1` on type `S` + --> $DIR/float-field.rs:30:7 + | +LL | s.0x1.1e1; + | ^^^^^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `0x1e` on type `S` + --> $DIR/float-field.rs:34:7 + | +LL | s.0x1e+1; + | ^^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `0x1e` on type `S` + --> $DIR/float-field.rs:35:7 + | +LL | s.0x1e-1; + | ^^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `1e1` on type `S` + --> $DIR/float-field.rs:42:7 + | +LL | s.1e1f32; + | ^^^^^^ unknown field + | + = note: available fields are: `0`, `1` + +error[E0609]: no field `f32` on type `(u8, u8)` + --> $DIR/float-field.rs:44:9 + | +LL | s.1.f32; + | ^^^ + +error[E0609]: no field `1e1` on type `(u8, u8)` + --> $DIR/float-field.rs:46:7 + | +LL | s.1.1e1f32; + | ^^^^^^^^ + +error: aborting due to 55 previous errors + +For more information about this error, try `rustc --explain E0609`. diff --git a/src/test/ui/tuple/tuple-float-index.fixed b/src/test/ui/tuple/tuple-float-index.fixed deleted file mode 100644 index cd1a85a9d2442..0000000000000 --- a/src/test/ui/tuple/tuple-float-index.fixed +++ /dev/null @@ -1,5 +0,0 @@ -// run-rustfix - -fn main () { - ((1, (2, 3)).1).1; //~ ERROR unexpected token: `1.1` -} diff --git a/src/test/ui/tuple/tuple-float-index.rs b/src/test/ui/tuple/tuple-float-index.rs deleted file mode 100644 index 1faabac2bcdac..0000000000000 --- a/src/test/ui/tuple/tuple-float-index.rs +++ /dev/null @@ -1,5 +0,0 @@ -// run-rustfix - -fn main () { - (1, (2, 3)).1.1; //~ ERROR unexpected token: `1.1` -} diff --git a/src/test/ui/tuple/tuple-float-index.stderr b/src/test/ui/tuple/tuple-float-index.stderr deleted file mode 100644 index a0ea0e0a30a72..0000000000000 --- a/src/test/ui/tuple/tuple-float-index.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: unexpected token: `1.1` - --> $DIR/tuple-float-index.rs:4:17 - | -LL | (1, (2, 3)).1.1; - | ------------^^^ - | | | - | | unexpected token - | help: try parenthesizing the first index: `((1, (2, 3)).1).1` - -error: aborting due to previous error - From 40a21707b4c0e7e5a8cb5a03ddebecdd59ab705c Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 26 Mar 2020 00:17:41 -0700 Subject: [PATCH 2/9] Add test of tuple nested indexing --- src/test/ui/tuple/nested-index.rs | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 src/test/ui/tuple/nested-index.rs diff --git a/src/test/ui/tuple/nested-index.rs b/src/test/ui/tuple/nested-index.rs new file mode 100644 index 0000000000000..e498db8cb88ca --- /dev/null +++ b/src/test/ui/tuple/nested-index.rs @@ -0,0 +1,6 @@ +// run-pass + +fn main () { + let n = (1, (2, 3)).1.1; + assert_eq!(n, 3); +} From 0432f63acf5b08c23ad206a87e3ad4a2a171cf7f Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 26 Mar 2020 00:57:39 -0700 Subject: [PATCH 3/9] Test even deeper nested indexing --- src/test/ui/tuple/nested-index.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/ui/tuple/nested-index.rs b/src/test/ui/tuple/nested-index.rs index e498db8cb88ca..b88f876d858eb 100644 --- a/src/test/ui/tuple/nested-index.rs +++ b/src/test/ui/tuple/nested-index.rs @@ -3,4 +3,7 @@ fn main () { let n = (1, (2, 3)).1.1; assert_eq!(n, 3); + + let n = (1, (2, (3, 4))).1.1.1; + assert_eq!(n, 4); } From 776deb6b9f326f5ba5984e4d55cb5010a17ce559 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 26 Mar 2020 00:59:47 -0700 Subject: [PATCH 4/9] Test a range, which is not nested indexing --- src/test/ui/tuple/nested-index.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/test/ui/tuple/nested-index.rs b/src/test/ui/tuple/nested-index.rs index b88f876d858eb..a3232d6fc361e 100644 --- a/src/test/ui/tuple/nested-index.rs +++ b/src/test/ui/tuple/nested-index.rs @@ -6,4 +6,7 @@ fn main () { let n = (1, (2, (3, 4))).1.1.1; assert_eq!(n, 4); + + // This is a range expression, not nested indexing. + let _ = 0.0..1.1; } From 6dfa549fb5719034b829955384e1e198f4d66c04 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 26 Mar 2020 09:36:05 -0700 Subject: [PATCH 5/9] Add tests in which the token really is a float --- src/test/ui/tuple/index-float.rs | 7 +++++++ src/test/ui/tuple/index-float.stderr | 14 ++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 src/test/ui/tuple/index-float.rs create mode 100644 src/test/ui/tuple/index-float.stderr diff --git a/src/test/ui/tuple/index-float.rs b/src/test/ui/tuple/index-float.rs new file mode 100644 index 0000000000000..673d32e4d4351 --- /dev/null +++ b/src/test/ui/tuple/index-float.rs @@ -0,0 +1,7 @@ +fn main() { + let tuple = (((),),); + + let _ = tuple. 0.0; //~ ERROR unexpected token: `0.0` + + let _ = tuple./*special cases*/0.0; //~ ERROR unexpected token: `0.0` +} diff --git a/src/test/ui/tuple/index-float.stderr b/src/test/ui/tuple/index-float.stderr new file mode 100644 index 0000000000000..505b91e5bbba5 --- /dev/null +++ b/src/test/ui/tuple/index-float.stderr @@ -0,0 +1,14 @@ +error: unexpected token: `0.0` + --> $DIR/index-float.rs:4:20 + | +LL | let _ = tuple. 0.0; + | ^^^ + +error: unexpected token: `0.0` + --> $DIR/index-float.rs:6:36 + | +LL | let _ = tuple./*special cases*/0.0; + | ^^^ + +error: aborting due to 2 previous errors + From 3814eec087c6e5695c92956b7a738f4c2ffd7649 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 26 Mar 2020 09:40:05 -0700 Subject: [PATCH 6/9] Add test for tuple indexed with float in macro input --- src/test/ui/tuple/indexing-in-macro.rs | 9 +++++++++ src/test/ui/tuple/indexing-in-macro.stderr | 11 +++++++++++ 2 files changed, 20 insertions(+) create mode 100644 src/test/ui/tuple/indexing-in-macro.rs create mode 100644 src/test/ui/tuple/indexing-in-macro.stderr diff --git a/src/test/ui/tuple/indexing-in-macro.rs b/src/test/ui/tuple/indexing-in-macro.rs new file mode 100644 index 0000000000000..89696cd7fcf44 --- /dev/null +++ b/src/test/ui/tuple/indexing-in-macro.rs @@ -0,0 +1,9 @@ +// Broken by https://github.com/rust-lang/rust/pull/70420. + +macro_rules! m { + (.$l:literal) => {}; +} + +m!(.0.0); //~ ERROR no rules expected the token `.` + +fn main() {} diff --git a/src/test/ui/tuple/indexing-in-macro.stderr b/src/test/ui/tuple/indexing-in-macro.stderr new file mode 100644 index 0000000000000..78879262b0177 --- /dev/null +++ b/src/test/ui/tuple/indexing-in-macro.stderr @@ -0,0 +1,11 @@ +error: no rules expected the token `.` + --> $DIR/indexing-in-macro.rs:7:6 + | +LL | macro_rules! m { + | -------------- when calling this macro +... +LL | m!(.0.0); + | ^ no rules expected this token in macro call + +error: aborting due to previous error + From 63f95a4858bbe8cef9a6e1b0e7e5273255d60926 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Thu, 26 Mar 2020 09:46:47 -0700 Subject: [PATCH 7/9] Add test for errors triggered on parts of decomposed index --- src/test/ui/tuple/index-invalid.rs | 7 +++++++ src/test/ui/tuple/index-invalid.stderr | 21 +++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/test/ui/tuple/index-invalid.rs create mode 100644 src/test/ui/tuple/index-invalid.stderr diff --git a/src/test/ui/tuple/index-invalid.rs b/src/test/ui/tuple/index-invalid.rs new file mode 100644 index 0000000000000..d36f6cfe3df7f --- /dev/null +++ b/src/test/ui/tuple/index-invalid.rs @@ -0,0 +1,7 @@ +fn main() { + let _ = (((),),).1.0; //~ ERROR no field `1` on type `(((),),)` + + let _ = (((),),).0.1; //~ ERROR no field `1` on type `((),)` + + let _ = (((),),).000.000; //~ ERROR no field `000` on type `(((),),)` +} diff --git a/src/test/ui/tuple/index-invalid.stderr b/src/test/ui/tuple/index-invalid.stderr new file mode 100644 index 0000000000000..8d22f458a6c6e --- /dev/null +++ b/src/test/ui/tuple/index-invalid.stderr @@ -0,0 +1,21 @@ +error[E0609]: no field `1` on type `(((),),)` + --> $DIR/index-invalid.rs:2:22 + | +LL | let _ = (((),),).1.0; + | ^ + +error[E0609]: no field `1` on type `((),)` + --> $DIR/index-invalid.rs:4:24 + | +LL | let _ = (((),),).0.1; + | ^ + +error[E0609]: no field `000` on type `(((),),)` + --> $DIR/index-invalid.rs:6:22 + | +LL | let _ = (((),),).000.000; + | ^^^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0609`. From 64a88db762bc13b37508d44e09731a3b8349110a Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Sun, 19 Apr 2020 15:30:34 +0300 Subject: [PATCH 8/9] Update dtolnay's tests that now work --- src/test/ui/tuple/index-float.rs | 6 ++++-- src/test/ui/tuple/index-float.stderr | 14 -------------- src/test/ui/tuple/index-invalid.stderr | 8 ++++---- src/test/ui/tuple/indexing-in-macro.rs | 4 ++-- src/test/ui/tuple/indexing-in-macro.stderr | 11 ----------- 5 files changed, 10 insertions(+), 33 deletions(-) delete mode 100644 src/test/ui/tuple/index-float.stderr delete mode 100644 src/test/ui/tuple/indexing-in-macro.stderr diff --git a/src/test/ui/tuple/index-float.rs b/src/test/ui/tuple/index-float.rs index 673d32e4d4351..85b088d664da1 100644 --- a/src/test/ui/tuple/index-float.rs +++ b/src/test/ui/tuple/index-float.rs @@ -1,7 +1,9 @@ +// check-pass + fn main() { let tuple = (((),),); - let _ = tuple. 0.0; //~ ERROR unexpected token: `0.0` + let _ = tuple. 0.0; // OK, whitespace - let _ = tuple./*special cases*/0.0; //~ ERROR unexpected token: `0.0` + let _ = tuple./*special cases*/0.0; // OK, comment } diff --git a/src/test/ui/tuple/index-float.stderr b/src/test/ui/tuple/index-float.stderr deleted file mode 100644 index 505b91e5bbba5..0000000000000 --- a/src/test/ui/tuple/index-float.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error: unexpected token: `0.0` - --> $DIR/index-float.rs:4:20 - | -LL | let _ = tuple. 0.0; - | ^^^ - -error: unexpected token: `0.0` - --> $DIR/index-float.rs:6:36 - | -LL | let _ = tuple./*special cases*/0.0; - | ^^^ - -error: aborting due to 2 previous errors - diff --git a/src/test/ui/tuple/index-invalid.stderr b/src/test/ui/tuple/index-invalid.stderr index 8d22f458a6c6e..800b5a31d98ab 100644 --- a/src/test/ui/tuple/index-invalid.stderr +++ b/src/test/ui/tuple/index-invalid.stderr @@ -2,19 +2,19 @@ error[E0609]: no field `1` on type `(((),),)` --> $DIR/index-invalid.rs:2:22 | LL | let _ = (((),),).1.0; - | ^ + | ^^^ error[E0609]: no field `1` on type `((),)` - --> $DIR/index-invalid.rs:4:24 + --> $DIR/index-invalid.rs:4:22 | LL | let _ = (((),),).0.1; - | ^ + | ^^^ error[E0609]: no field `000` on type `(((),),)` --> $DIR/index-invalid.rs:6:22 | LL | let _ = (((),),).000.000; - | ^^^ + | ^^^^^^^ error: aborting due to 3 previous errors diff --git a/src/test/ui/tuple/indexing-in-macro.rs b/src/test/ui/tuple/indexing-in-macro.rs index 89696cd7fcf44..bef4a69ab23c9 100644 --- a/src/test/ui/tuple/indexing-in-macro.rs +++ b/src/test/ui/tuple/indexing-in-macro.rs @@ -1,9 +1,9 @@ -// Broken by https://github.com/rust-lang/rust/pull/70420. +// check-pass macro_rules! m { (.$l:literal) => {}; } -m!(.0.0); //~ ERROR no rules expected the token `.` +m!(.0.0); // OK, `0.0` after a dot is still a float token. fn main() {} diff --git a/src/test/ui/tuple/indexing-in-macro.stderr b/src/test/ui/tuple/indexing-in-macro.stderr deleted file mode 100644 index 78879262b0177..0000000000000 --- a/src/test/ui/tuple/indexing-in-macro.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error: no rules expected the token `.` - --> $DIR/indexing-in-macro.rs:7:6 - | -LL | macro_rules! m { - | -------------- when calling this macro -... -LL | m!(.0.0); - | ^ no rules expected this token in macro call - -error: aborting due to previous error - From 52bdaaa0edb2824af1610b67664f06580335fd78 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Wed, 1 Jul 2020 14:12:49 +0300 Subject: [PATCH 9/9] Add some requested tests --- .../ui/parser/float-field-interpolated.rs | 17 +++++++ .../ui/parser/float-field-interpolated.stderr | 46 +++++++++++++++++++ src/test/ui/tuple/index-float.rs | 1 + 3 files changed, 64 insertions(+) create mode 100644 src/test/ui/parser/float-field-interpolated.rs create mode 100644 src/test/ui/parser/float-field-interpolated.stderr diff --git a/src/test/ui/parser/float-field-interpolated.rs b/src/test/ui/parser/float-field-interpolated.rs new file mode 100644 index 0000000000000..a30532035365b --- /dev/null +++ b/src/test/ui/parser/float-field-interpolated.rs @@ -0,0 +1,17 @@ +struct S(u8, (u8, u8)); + +macro_rules! generate_field_accesses { + ($a:tt, $b:literal, $c:expr) => { + let s = S(0, (0, 0)); + + s.$a; // OK + { s.$b; } //~ ERROR unexpected token: `1.1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` + { s.$c; } //~ ERROR unexpected token: `1.1` + //~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` + }; +} + +fn main() { + generate_field_accesses!(1.1, 1.1, 1.1); +} diff --git a/src/test/ui/parser/float-field-interpolated.stderr b/src/test/ui/parser/float-field-interpolated.stderr new file mode 100644 index 0000000000000..fb974f085cbf1 --- /dev/null +++ b/src/test/ui/parser/float-field-interpolated.stderr @@ -0,0 +1,46 @@ +error: unexpected token: `1.1` + --> $DIR/float-field-interpolated.rs:8:13 + | +LL | { s.$b; } + | ^^ +... +LL | generate_field_accesses!(1.1, 1.1, 1.1); + | ---------------------------------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` + --> $DIR/float-field-interpolated.rs:8:13 + | +LL | { s.$b; } + | ^^ expected one of `.`, `;`, `?`, `}`, or an operator +... +LL | generate_field_accesses!(1.1, 1.1, 1.1); + | ---------------------------------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: unexpected token: `1.1` + --> $DIR/float-field-interpolated.rs:10:13 + | +LL | { s.$c; } + | ^^ +... +LL | generate_field_accesses!(1.1, 1.1, 1.1); + | ---------------------------------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1` + --> $DIR/float-field-interpolated.rs:10:13 + | +LL | { s.$c; } + | ^^ expected one of `.`, `;`, `?`, `}`, or an operator +... +LL | generate_field_accesses!(1.1, 1.1, 1.1); + | ---------------------------------------- in this macro invocation + | + = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 4 previous errors + diff --git a/src/test/ui/tuple/index-float.rs b/src/test/ui/tuple/index-float.rs index 85b088d664da1..eda2bf48581a0 100644 --- a/src/test/ui/tuple/index-float.rs +++ b/src/test/ui/tuple/index-float.rs @@ -4,6 +4,7 @@ fn main() { let tuple = (((),),); let _ = tuple. 0.0; // OK, whitespace + let _ = tuple.0. 0; // OK, whitespace let _ = tuple./*special cases*/0.0; // OK, comment }