From f5b285906e45d0fd031a1433cdb7ab3c7be92650 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 17 Jul 2019 11:40:36 -0700 Subject: [PATCH 1/2] Handle more cases of typos misinterpreted as type ascription --- src/libsyntax/parse/diagnostics.rs | 91 ++++++++++--------- src/libsyntax/parse/parser.rs | 45 +++++---- src/libsyntax_ext/format.rs | 5 +- .../ui/codemap_tests/bad-format-args.stderr | 4 +- src/test/ui/issues/issue-22644.stderr | 11 +-- src/test/ui/issues/issue-34255-1.stderr | 11 +-- src/test/ui/issues/issue-39616.stderr | 2 +- src/test/ui/issues/issue-44406.stderr | 5 +- .../ui/lifetime_starts_expressions.stderr | 11 +-- src/test/ui/macros/missing-comma.stderr | 2 +- src/test/ui/parser/issue-33262.stderr | 2 +- .../macro/trait-object-macro-matcher.stderr | 2 +- src/test/ui/parser/recover-enum2.stderr | 2 +- .../ui/parser/recover-from-bad-variant.stderr | 11 +-- .../parser/removed-syntax-mut-vec-ty.stderr | 2 +- .../ui/parser/removed-syntax-record.stderr | 2 +- .../trait-object-lifetime-parens.stderr | 2 +- .../type-ascription-instead-of-method.stderr | 7 +- .../type-ascription-instead-of-variant.stderr | 7 +- src/test/ui/type/ascription/issue-34255-1.rs | 15 +++ .../ui/type/ascription/issue-34255-1.stderr | 30 ++++++ src/test/ui/type/ascription/issue-47666.rs | 5 + .../ui/type/ascription/issue-47666.stderr | 13 +++ src/test/ui/type/ascription/issue-54516.rs | 6 ++ .../ui/type/ascription/issue-54516.stderr | 13 +++ src/test/ui/type/ascription/issue-60933.rs | 4 + .../ui/type/ascription/issue-60933.stderr | 13 +++ ...e-ascription-instead-of-initializer.stderr | 2 +- ...ascription-instead-of-statement-end.stderr | 16 ++-- 29 files changed, 227 insertions(+), 114 deletions(-) create mode 100644 src/test/ui/type/ascription/issue-34255-1.rs create mode 100644 src/test/ui/type/ascription/issue-34255-1.stderr create mode 100644 src/test/ui/type/ascription/issue-47666.rs create mode 100644 src/test/ui/type/ascription/issue-47666.stderr create mode 100644 src/test/ui/type/ascription/issue-54516.rs create mode 100644 src/test/ui/type/ascription/issue-54516.stderr create mode 100644 src/test/ui/type/ascription/issue-60933.rs create mode 100644 src/test/ui/type/ascription/issue-60933.stderr diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 0e88a0ee28937..190672acfcf77 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -2,6 +2,7 @@ use crate::ast::{ self, Arg, BinOpKind, BindingMode, BlockCheckMode, Expr, ExprKind, Ident, Item, ItemKind, Mutability, Pat, PatKind, PathSegment, QSelf, Ty, TyKind, VariantData, }; +use crate::feature_gate::{feature_err, UnstableFeatures}; use crate::parse::{SeqSep, PResult, Parser, ParseSess}; use crate::parse::parser::{BlockMode, PathStyle, SemiColonMode, TokenType, TokenExpectType}; use crate::parse::token::{self, TokenKind}; @@ -365,9 +366,53 @@ impl<'a> Parser<'a> { err.span_label(self.token.span, "unexpected token"); } } + self.maybe_annotate_with_ascription(&mut err, false); Err(err) } + pub fn maybe_annotate_with_ascription( + &self, + err: &mut DiagnosticBuilder<'_>, + maybe_expected_semicolon: bool, + ) { + if let Some((sp, likely_path)) = self.last_type_ascription { + let cm = self.sess.source_map(); + let next_pos = cm.lookup_char_pos(self.token.span.lo()); + let op_pos = cm.lookup_char_pos(sp.hi()); + + if likely_path { + err.span_suggestion( + sp, + "maybe write a path separator here", + "::".to_string(), + match self.sess.unstable_features { + UnstableFeatures::Disallow => Applicability::MachineApplicable, + _ => Applicability::MaybeIncorrect, + }, + ); + } else if op_pos.line != next_pos.line && maybe_expected_semicolon { + err.span_suggestion( + sp, + "try using a semicolon", + ";".to_string(), + Applicability::MaybeIncorrect, + ); + } else if let UnstableFeatures::Disallow = self.sess.unstable_features { + err.span_label(sp, "tried to parse a type due to this"); + } else { + err.span_label(sp, "tried to parse a type due to this type ascription"); + } + if let UnstableFeatures::Disallow = self.sess.unstable_features { + // Give extra information about type ascription only if it's a nightly compiler. + } else { + err.note("`#![feature(type_ascription)]` lets you annotate an expression with a \ + type: `: `"); + err.note("for more information, see \ + https://github.com/rust-lang/rust/issues/23416"); + } + } + } + /// Eats and discards tokens until one of `kets` is encountered. Respects token trees, /// passes through any errors encountered. Used for error recovery. crate fn eat_to_tokens(&mut self, kets: &[&TokenKind]) { @@ -556,7 +601,7 @@ impl<'a> Parser<'a> { .collect::>(); if !discriminant_spans.is_empty() && has_fields { - let mut err = crate::feature_gate::feature_err( + let mut err = feature_err( sess, sym::arbitrary_enum_discriminant, discriminant_spans.clone(), @@ -887,47 +932,9 @@ impl<'a> Parser<'a> { self.look_ahead(2, |t| t.is_ident()) || self.look_ahead(1, |t| t == &token::Colon) && // `foo:bar:baz` self.look_ahead(2, |t| t.is_ident()) || - self.look_ahead(1, |t| t == &token::ModSep) && // `foo:bar::baz` - self.look_ahead(2, |t| t.is_ident()) - } - - crate fn bad_type_ascription( - &self, - err: &mut DiagnosticBuilder<'a>, - lhs_span: Span, - cur_op_span: Span, - next_sp: Span, - maybe_path: bool, - ) { - err.span_label(self.token.span, "expecting a type here because of type ascription"); - let cm = self.sess.source_map(); - let next_pos = cm.lookup_char_pos(next_sp.lo()); - let op_pos = cm.lookup_char_pos(cur_op_span.hi()); - if op_pos.line != next_pos.line { - err.span_suggestion( - cur_op_span, - "try using a semicolon", - ";".to_string(), - Applicability::MaybeIncorrect, - ); - } else { - if maybe_path { - err.span_suggestion( - cur_op_span, - "maybe you meant to write a path separator here", - "::".to_string(), - Applicability::MaybeIncorrect, - ); - } else { - err.note("`#![feature(type_ascription)]` lets you annotate an \ - expression with a type: `: `") - .span_note( - lhs_span, - "this expression expects an ascribed type after the colon", - ) - .help("this might be indicative of a syntax error elsewhere"); - } - } + self.look_ahead(1, |t| t == &token::ModSep) && + (self.look_ahead(2, |t| t.is_ident()) || // `foo:bar::baz` + self.look_ahead(2, |t| t == &token::Lt)) // `foo:bar::` } crate fn recover_seq_parse_error( diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 1d4d02c732582..41cfb5bece3b8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -239,6 +239,7 @@ pub struct Parser<'a> { /// error. crate unclosed_delims: Vec, crate last_unexpected_token_span: Option, + crate last_type_ascription: Option<(Span, bool /* likely path typo */)>, /// If present, this `Parser` is not parsing Rust code but rather a macro call. crate subparser_name: Option<&'static str>, } @@ -502,6 +503,7 @@ impl<'a> Parser<'a> { max_angle_bracket_count: 0, unclosed_delims: Vec::new(), last_unexpected_token_span: None, + last_type_ascription: None, subparser_name, }; @@ -1422,7 +1424,10 @@ impl<'a> Parser<'a> { } } else { let msg = format!("expected type, found {}", self.this_token_descr()); - return Err(self.fatal(&msg)); + let mut err = self.fatal(&msg); + err.span_label(self.token.span, "expected type"); + self.maybe_annotate_with_ascription(&mut err, true); + return Err(err); }; let span = lo.to(self.prev_span); @@ -2823,10 +2828,11 @@ impl<'a> Parser<'a> { } /// Parses an associative expression with operators of at least `min_prec` precedence. - fn parse_assoc_expr_with(&mut self, - min_prec: usize, - lhs: LhsExpr) - -> PResult<'a, P> { + fn parse_assoc_expr_with( + &mut self, + min_prec: usize, + lhs: LhsExpr, + ) -> PResult<'a, P> { let mut lhs = if let LhsExpr::AlreadyParsed(expr) = lhs { expr } else { @@ -2840,9 +2846,13 @@ impl<'a> Parser<'a> { self.parse_prefix_expr(attrs)? } }; + let last_type_ascription_set = self.last_type_ascription.is_some(); match (self.expr_is_complete(&lhs), AssocOp::from_token(&self.token)) { (true, None) => { + if last_type_ascription_set { + self.last_type_ascription = None; + } // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 return Ok(lhs); } @@ -2857,12 +2867,18 @@ impl<'a> Parser<'a> { // If the next token is a keyword, then the tokens above *are* unambiguously incorrect: // `if x { a } else { b } && if y { c } else { d }` if !self.look_ahead(1, |t| t.is_reserved_ident()) => { + if last_type_ascription_set { + self.last_type_ascription = None; + } // These cases are ambiguous and can't be identified in the parser alone let sp = self.sess.source_map().start_point(self.token.span); self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); return Ok(lhs); } (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => { + if last_type_ascription_set { + self.last_type_ascription = None; + } return Ok(lhs); } (true, Some(_)) => { @@ -2921,21 +2937,9 @@ impl<'a> Parser<'a> { continue } else if op == AssocOp::Colon { let maybe_path = self.could_ascription_be_path(&lhs.node); - let next_sp = self.token.span; + self.last_type_ascription = Some((self.prev_span, maybe_path)); - lhs = match self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type) { - Ok(lhs) => lhs, - Err(mut err) => { - self.bad_type_ascription( - &mut err, - lhs_span, - cur_op_span, - next_sp, - maybe_path, - ); - return Err(err); - } - }; + lhs = self.parse_assoc_op_cast(lhs, lhs_span, ExprKind::Type)?; continue } else if op == AssocOp::DotDot || op == AssocOp::DotDotEq { // If we didn’t have to handle `x..`/`x..=`, it would be pretty easy to @@ -3020,6 +3024,9 @@ impl<'a> Parser<'a> { if let Fixity::None = fixity { break } } + if last_type_ascription_set { + self.last_type_ascription = None; + } Ok(lhs) } diff --git a/src/libsyntax_ext/format.rs b/src/libsyntax_ext/format.rs index c3dbd48cc6e4e..b9e83de43bb0c 100644 --- a/src/libsyntax_ext/format.rs +++ b/src/libsyntax_ext/format.rs @@ -141,7 +141,10 @@ fn parse_args<'a>( while p.token != token::Eof { if !p.eat(&token::Comma) { - return Err(ecx.struct_span_err(p.token.span, "expected token: `,`")); + let mut err = ecx.struct_span_err(p.token.span, "expected token: `,`"); + err.span_label(p.token.span, "expected `,`"); + p.maybe_annotate_with_ascription(&mut err, false); + return Err(err); } if p.token == token::Eof { break; diff --git a/src/test/ui/codemap_tests/bad-format-args.stderr b/src/test/ui/codemap_tests/bad-format-args.stderr index c424eb08a7a98..5b01314d8ad4f 100644 --- a/src/test/ui/codemap_tests/bad-format-args.stderr +++ b/src/test/ui/codemap_tests/bad-format-args.stderr @@ -10,13 +10,13 @@ error: expected token: `,` --> $DIR/bad-format-args.rs:3:16 | LL | format!("" 1); - | ^ + | ^ expected `,` error: expected token: `,` --> $DIR/bad-format-args.rs:4:19 | LL | format!("", 1 1); - | ^ + | ^ expected `,` error: aborting due to 3 previous errors diff --git a/src/test/ui/issues/issue-22644.stderr b/src/test/ui/issues/issue-22644.stderr index 4f0dc0a488765..0fe167963c3f4 100644 --- a/src/test/ui/issues/issue-22644.stderr +++ b/src/test/ui/issues/issue-22644.stderr @@ -87,15 +87,12 @@ error: expected type, found `4` --> $DIR/issue-22644.rs:34:28 | LL | println!("{}", a: &mut 4); - | ^ expecting a type here because of type ascription + | - ^ expected type + | | + | tried to parse a type due to this type ascription | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` -note: this expression expects an ascribed type after the colon - --> $DIR/issue-22644.rs:34:20 - | -LL | println!("{}", a: &mut 4); - | ^ - = help: this might be indicative of a syntax error elsewhere + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 error: aborting due to 9 previous errors diff --git a/src/test/ui/issues/issue-34255-1.stderr b/src/test/ui/issues/issue-34255-1.stderr index 0218a7abeaa4c..acb093b51428b 100644 --- a/src/test/ui/issues/issue-34255-1.stderr +++ b/src/test/ui/issues/issue-34255-1.stderr @@ -2,15 +2,12 @@ error: expected type, found `42` --> $DIR/issue-34255-1.rs:8:24 | LL | Test::Drill(field: 42); - | ^^ expecting a type here because of type ascription + | - ^^ expected type + | | + | tried to parse a type due to this type ascription | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` -note: this expression expects an ascribed type after the colon - --> $DIR/issue-34255-1.rs:8:17 - | -LL | Test::Drill(field: 42); - | ^^^^^ - = help: this might be indicative of a syntax error elsewhere + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 error: aborting due to previous error diff --git a/src/test/ui/issues/issue-39616.stderr b/src/test/ui/issues/issue-39616.stderr index e24ffcdb0d990..75eb55fa50bb3 100644 --- a/src/test/ui/issues/issue-39616.stderr +++ b/src/test/ui/issues/issue-39616.stderr @@ -2,7 +2,7 @@ error: expected type, found `0` --> $DIR/issue-39616.rs:1:12 | LL | fn foo(a: [0; 1]) {} - | ^ + | ^ expected type error: expected one of `)`, `,`, `->`, `where`, or `{`, found `]` --> $DIR/issue-39616.rs:1:16 diff --git a/src/test/ui/issues/issue-44406.stderr b/src/test/ui/issues/issue-44406.stderr index 14b3b8cc5c85d..108542c9b6f13 100644 --- a/src/test/ui/issues/issue-44406.stderr +++ b/src/test/ui/issues/issue-44406.stderr @@ -15,7 +15,10 @@ LL | bar(baz: $rest) | - help: try using a semicolon: `;` ... LL | foo!(true); - | ^^^^ expecting a type here because of type ascription + | ^^^^ expected type + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 error: aborting due to 2 previous errors diff --git a/src/test/ui/lifetime_starts_expressions.stderr b/src/test/ui/lifetime_starts_expressions.stderr index 84e4c87ebc4da..bacba10b55fba 100644 --- a/src/test/ui/lifetime_starts_expressions.stderr +++ b/src/test/ui/lifetime_starts_expressions.stderr @@ -12,15 +12,12 @@ error: expected type, found keyword `loop` --> $DIR/lifetime_starts_expressions.rs:6:26 | LL | loop { break 'label: loop { break 'label 42; }; } - | ^^^^ expecting a type here because of type ascription + | - ^^^^ expected type + | | + | tried to parse a type due to this type ascription | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` -note: this expression expects an ascribed type after the colon - --> $DIR/lifetime_starts_expressions.rs:6:12 - | -LL | loop { break 'label: loop { break 'label 42; }; } - | ^^^^^^^^^^^^ - = help: this might be indicative of a syntax error elsewhere + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 error: aborting due to 2 previous errors diff --git a/src/test/ui/macros/missing-comma.stderr b/src/test/ui/macros/missing-comma.stderr index d5b6d86b20ff1..f96848f8239f7 100644 --- a/src/test/ui/macros/missing-comma.stderr +++ b/src/test/ui/macros/missing-comma.stderr @@ -2,7 +2,7 @@ error: expected token: `,` --> $DIR/missing-comma.rs:19:19 | LL | println!("{}" a); - | ^ + | ^ expected `,` error: no rules expected the token `b` --> $DIR/missing-comma.rs:21:12 diff --git a/src/test/ui/parser/issue-33262.stderr b/src/test/ui/parser/issue-33262.stderr index c2491df903b76..2aff328393538 100644 --- a/src/test/ui/parser/issue-33262.stderr +++ b/src/test/ui/parser/issue-33262.stderr @@ -2,7 +2,7 @@ error: expected type, found `{` --> $DIR/issue-33262.rs:4:22 | LL | for i in 0..a as { } - | ^ + | ^ expected type error: aborting due to previous error diff --git a/src/test/ui/parser/macro/trait-object-macro-matcher.stderr b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr index 19c5c82f82cd2..f02f60e4bfb1d 100644 --- a/src/test/ui/parser/macro/trait-object-macro-matcher.stderr +++ b/src/test/ui/parser/macro/trait-object-macro-matcher.stderr @@ -2,7 +2,7 @@ error: expected type, found `'static` --> $DIR/trait-object-macro-matcher.rs:9:8 | LL | m!('static); - | ^^^^^^^ + | ^^^^^^^ expected type error: aborting due to previous error diff --git a/src/test/ui/parser/recover-enum2.stderr b/src/test/ui/parser/recover-enum2.stderr index 9ed2e6f5eb6c4..2311887a6fb36 100644 --- a/src/test/ui/parser/recover-enum2.stderr +++ b/src/test/ui/parser/recover-enum2.stderr @@ -2,7 +2,7 @@ error: expected type, found `{` --> $DIR/recover-enum2.rs:6:18 | LL | abc: {}, - | ^ + | ^ expected type error: expected one of `!`, `(`, `)`, `+`, `,`, `::`, or `<`, found `{` --> $DIR/recover-enum2.rs:25:22 diff --git a/src/test/ui/parser/recover-from-bad-variant.stderr b/src/test/ui/parser/recover-from-bad-variant.stderr index d525bd3f4c6e5..b46d3ca9c233c 100644 --- a/src/test/ui/parser/recover-from-bad-variant.stderr +++ b/src/test/ui/parser/recover-from-bad-variant.stderr @@ -2,15 +2,12 @@ error: expected type, found `3` --> $DIR/recover-from-bad-variant.rs:7:26 | LL | let x = Enum::Foo(a: 3, b: 4); - | ^ expecting a type here because of type ascription + | - ^ expected type + | | + | tried to parse a type due to this type ascription | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` -note: this expression expects an ascribed type after the colon - --> $DIR/recover-from-bad-variant.rs:7:23 - | -LL | let x = Enum::Foo(a: 3, b: 4); - | ^ - = help: this might be indicative of a syntax error elsewhere + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 error[E0532]: expected tuple struct/variant, found struct variant `Enum::Foo` --> $DIR/recover-from-bad-variant.rs:10:9 diff --git a/src/test/ui/parser/removed-syntax-mut-vec-ty.stderr b/src/test/ui/parser/removed-syntax-mut-vec-ty.stderr index a759716b5a963..02b518e251678 100644 --- a/src/test/ui/parser/removed-syntax-mut-vec-ty.stderr +++ b/src/test/ui/parser/removed-syntax-mut-vec-ty.stderr @@ -2,7 +2,7 @@ error: expected type, found keyword `mut` --> $DIR/removed-syntax-mut-vec-ty.rs:1:11 | LL | type v = [mut isize]; - | ^^^ + | ^^^ expected type error: aborting due to previous error diff --git a/src/test/ui/parser/removed-syntax-record.stderr b/src/test/ui/parser/removed-syntax-record.stderr index 730d5e2712b96..0a1655840b550 100644 --- a/src/test/ui/parser/removed-syntax-record.stderr +++ b/src/test/ui/parser/removed-syntax-record.stderr @@ -2,7 +2,7 @@ error: expected type, found `{` --> $DIR/removed-syntax-record.rs:1:10 | LL | type t = { f: () }; - | ^ + | ^ expected type error: aborting due to previous error diff --git a/src/test/ui/parser/trait-object-lifetime-parens.stderr b/src/test/ui/parser/trait-object-lifetime-parens.stderr index a31b7aea8fee6..7ffc26e9edead 100644 --- a/src/test/ui/parser/trait-object-lifetime-parens.stderr +++ b/src/test/ui/parser/trait-object-lifetime-parens.stderr @@ -29,7 +29,7 @@ error: expected type, found `'a` --> $DIR/trait-object-lifetime-parens.rs:9:17 | LL | let _: Box<('a) + Trait>; - | - ^^ + | - ^^ expected type | | | while parsing the type for `_` diff --git a/src/test/ui/suggestions/type-ascription-instead-of-method.stderr b/src/test/ui/suggestions/type-ascription-instead-of-method.stderr index 15ec087b1cc01..4a8d2f57d89d3 100644 --- a/src/test/ui/suggestions/type-ascription-instead-of-method.stderr +++ b/src/test/ui/suggestions/type-ascription-instead-of-method.stderr @@ -2,9 +2,12 @@ error: expected type, found `"foo"` --> $DIR/type-ascription-instead-of-method.rs:2:13 | LL | Box:new("foo".to_string()) - | - ^^^^^ expecting a type here because of type ascription + | - ^^^^^ expected type | | - | help: maybe you meant to write a path separator here: `::` + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 error: aborting due to previous error diff --git a/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr b/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr index 5719a667a8415..7e9a31c06c8b2 100644 --- a/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr +++ b/src/test/ui/suggestions/type-ascription-instead-of-variant.stderr @@ -2,9 +2,12 @@ error: expected type, found `""` --> $DIR/type-ascription-instead-of-variant.rs:2:25 | LL | let _ = Option:Some(""); - | - ^^ expecting a type here because of type ascription + | - ^^ expected type | | - | help: maybe you meant to write a path separator here: `::` + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 error: aborting due to previous error diff --git a/src/test/ui/type/ascription/issue-34255-1.rs b/src/test/ui/type/ascription/issue-34255-1.rs new file mode 100644 index 0000000000000..c11a248d3c7d1 --- /dev/null +++ b/src/test/ui/type/ascription/issue-34255-1.rs @@ -0,0 +1,15 @@ +struct Reactor { + input_cells: Vec, +} + +impl Reactor { + pub fn new() -> Self { + input_cells: Vec::new() + //~^ ERROR cannot find value `input_cells` in this scope + //~| ERROR parenthesized type parameters may only be used with a `Fn` trait + //~| ERROR wrong number of type arguments: expected 1, found 0 + //~| WARNING this was previously accepted by the compiler but is being phased out + } +} + +// This case isn't currently being handled gracefully, including for completeness. diff --git a/src/test/ui/type/ascription/issue-34255-1.stderr b/src/test/ui/type/ascription/issue-34255-1.stderr new file mode 100644 index 0000000000000..531455b82b424 --- /dev/null +++ b/src/test/ui/type/ascription/issue-34255-1.stderr @@ -0,0 +1,30 @@ +error[E0425]: cannot find value `input_cells` in this scope + --> $DIR/issue-34255-1.rs:7:9 + | +LL | input_cells: Vec::new() + | ^^^^^^^^^^^ a field by this name exists in `Self` + +error: parenthesized type parameters may only be used with a `Fn` trait + --> $DIR/issue-34255-1.rs:7:30 + | +LL | input_cells: Vec::new() + | ^^ + | + = note: `#[deny(parenthesized_params_in_types_and_modules)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42238 + +error[E0601]: `main` function not found in crate `issue_34255_1` + | + = note: consider adding a `main` function to `$DIR/issue-34255-1.rs` + +error[E0107]: wrong number of type arguments: expected 1, found 0 + --> $DIR/issue-34255-1.rs:7:22 + | +LL | input_cells: Vec::new() + | ^^^^^^^^^^ expected 1 type argument + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0107, E0425, E0601. +For more information about an error, try `rustc --explain E0107`. diff --git a/src/test/ui/type/ascription/issue-47666.rs b/src/test/ui/type/ascription/issue-47666.rs new file mode 100644 index 0000000000000..ceb1dd89daea9 --- /dev/null +++ b/src/test/ui/type/ascription/issue-47666.rs @@ -0,0 +1,5 @@ +fn main() { + let _ = Option:Some(vec![0, 1]); //~ ERROR expected type, found +} + +// This case isn't currently being handled gracefully due to the macro invocation. diff --git a/src/test/ui/type/ascription/issue-47666.stderr b/src/test/ui/type/ascription/issue-47666.stderr new file mode 100644 index 0000000000000..7aa899f795c7d --- /dev/null +++ b/src/test/ui/type/ascription/issue-47666.stderr @@ -0,0 +1,13 @@ +error: expected type, found reserved keyword `box` + --> $DIR/issue-47666.rs:2:25 + | +LL | let _ = Option:Some(vec![0, 1]); + | ^^^^^^^^^^ + | | + | expected type + | in this macro invocation + | + = note: this warning originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info) + +error: aborting due to previous error + diff --git a/src/test/ui/type/ascription/issue-54516.rs b/src/test/ui/type/ascription/issue-54516.rs new file mode 100644 index 0000000000000..6d65760e299b5 --- /dev/null +++ b/src/test/ui/type/ascription/issue-54516.rs @@ -0,0 +1,6 @@ +use std::collections::BTreeMap; + +fn main() { + println!("{}", std::mem:size_of::>()); + //~^ ERROR expected token: `,` +} diff --git a/src/test/ui/type/ascription/issue-54516.stderr b/src/test/ui/type/ascription/issue-54516.stderr new file mode 100644 index 0000000000000..a846f3bc320e6 --- /dev/null +++ b/src/test/ui/type/ascription/issue-54516.stderr @@ -0,0 +1,13 @@ +error: expected token: `,` + --> $DIR/issue-54516.rs:4:58 + | +LL | println!("{}", std::mem:size_of::>()); + | - ^ expected `,` + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 + +error: aborting due to previous error + diff --git a/src/test/ui/type/ascription/issue-60933.rs b/src/test/ui/type/ascription/issue-60933.rs new file mode 100644 index 0000000000000..8fb06c887bd3e --- /dev/null +++ b/src/test/ui/type/ascription/issue-60933.rs @@ -0,0 +1,4 @@ +fn main() { + let u: usize = std::mem:size_of::(); + //~^ ERROR expected one of +} diff --git a/src/test/ui/type/ascription/issue-60933.stderr b/src/test/ui/type/ascription/issue-60933.stderr new file mode 100644 index 0000000000000..c2fc7bbcfc865 --- /dev/null +++ b/src/test/ui/type/ascription/issue-60933.stderr @@ -0,0 +1,13 @@ +error: expected one of `!`, `::`, or `;`, found `(` + --> $DIR/issue-60933.rs:2:43 + | +LL | let u: usize = std::mem:size_of::(); + | - ^ expected one of `!`, `::`, or `;` here + | | + | help: maybe write a path separator here: `::` + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 + +error: aborting due to previous error + diff --git a/src/test/ui/type/type-ascription-instead-of-initializer.stderr b/src/test/ui/type/type-ascription-instead-of-initializer.stderr index a22d25697d8bd..3fe676de59dab 100644 --- a/src/test/ui/type/type-ascription-instead-of-initializer.stderr +++ b/src/test/ui/type/type-ascription-instead-of-initializer.stderr @@ -2,7 +2,7 @@ error: expected type, found `10` --> $DIR/type-ascription-instead-of-initializer.rs:2:31 | LL | let x: Vec::with_capacity(10, 20); - | -- ^^ + | -- ^^ expected type | || | |help: use `=` if you meant to assign | while parsing the type for `x` diff --git a/src/test/ui/type/type-ascription-instead-of-statement-end.stderr b/src/test/ui/type/type-ascription-instead-of-statement-end.stderr index 1f8989db81412..8fbcb3969a79a 100644 --- a/src/test/ui/type/type-ascription-instead-of-statement-end.stderr +++ b/src/test/ui/type/type-ascription-instead-of-statement-end.stderr @@ -4,21 +4,21 @@ error: expected type, found `0` LL | println!("test"): | - help: try using a semicolon: `;` LL | 0; - | ^ expecting a type here because of type ascription + | ^ expected type + | + = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 error: expected type, found `0` --> $DIR/type-ascription-instead-of-statement-end.rs:9:23 | LL | println!("test"): 0; - | ^ expecting a type here because of type ascription + | - ^ expected type + | | + | tried to parse a type due to this type ascription | = note: `#![feature(type_ascription)]` lets you annotate an expression with a type: `: ` -note: this expression expects an ascribed type after the colon - --> $DIR/type-ascription-instead-of-statement-end.rs:9:5 - | -LL | println!("test"): 0; - | ^^^^^^^^^^^^^^^^ - = help: this might be indicative of a syntax error elsewhere + = note: for more information, see https://github.com/rust-lang/rust/issues/23416 error: aborting due to 2 previous errors From 9dbe2e77b34f5321976ee3b26ca008ad8d574faf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 19 Jul 2019 10:59:02 -0700 Subject: [PATCH 2/2] review comments --- src/libsyntax/parse/diagnostics.rs | 14 +++++++------- src/libsyntax/parse/parser.rs | 12 +++--------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/libsyntax/parse/diagnostics.rs b/src/libsyntax/parse/diagnostics.rs index 190672acfcf77..f4fc87506f357 100644 --- a/src/libsyntax/parse/diagnostics.rs +++ b/src/libsyntax/parse/diagnostics.rs @@ -327,8 +327,8 @@ impl<'a> Parser<'a> { self.token.is_keyword(kw::Return) || self.token.is_keyword(kw::While) ); - let cm = self.sess.source_map(); - match (cm.lookup_line(self.token.span.lo()), cm.lookup_line(sp.lo())) { + let sm = self.sess.source_map(); + match (sm.lookup_line(self.token.span.lo()), sm.lookup_line(sp.lo())) { (Ok(ref a), Ok(ref b)) if a.line != b.line && is_semi_suggestable => { // The spans are in different lines, expected `;` and found `let` or `return`. // High likelihood that it is only a missing `;`. @@ -376,9 +376,9 @@ impl<'a> Parser<'a> { maybe_expected_semicolon: bool, ) { if let Some((sp, likely_path)) = self.last_type_ascription { - let cm = self.sess.source_map(); - let next_pos = cm.lookup_char_pos(self.token.span.lo()); - let op_pos = cm.lookup_char_pos(sp.hi()); + let sm = self.sess.source_map(); + let next_pos = sm.lookup_char_pos(self.token.span.lo()); + let op_pos = sm.lookup_char_pos(sp.hi()); if likely_path { err.span_suggestion( @@ -814,8 +814,8 @@ impl<'a> Parser<'a> { return Ok(recovered); } } - let cm = self.sess.source_map(); - match (cm.lookup_line(prev_sp.lo()), cm.lookup_line(sp.lo())) { + let sm = self.sess.source_map(); + match (sm.lookup_line(prev_sp.lo()), sm.lookup_line(sp.lo())) { (Ok(ref a), Ok(ref b)) if a.line == b.line => { // When the spans are in the same line, it means that the only content // between them is whitespace, point only at the found token. diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 41cfb5bece3b8..da38869463737 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2850,9 +2850,7 @@ impl<'a> Parser<'a> { match (self.expr_is_complete(&lhs), AssocOp::from_token(&self.token)) { (true, None) => { - if last_type_ascription_set { - self.last_type_ascription = None; - } + self.last_type_ascription = None; // Semi-statement forms are odd. See https://github.com/rust-lang/rust/issues/29071 return Ok(lhs); } @@ -2867,18 +2865,14 @@ impl<'a> Parser<'a> { // If the next token is a keyword, then the tokens above *are* unambiguously incorrect: // `if x { a } else { b } && if y { c } else { d }` if !self.look_ahead(1, |t| t.is_reserved_ident()) => { - if last_type_ascription_set { - self.last_type_ascription = None; - } + self.last_type_ascription = None; // These cases are ambiguous and can't be identified in the parser alone let sp = self.sess.source_map().start_point(self.token.span); self.sess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); return Ok(lhs); } (true, Some(ref op)) if !op.can_continue_expr_unambiguously() => { - if last_type_ascription_set { - self.last_type_ascription = None; - } + self.last_type_ascription = None; return Ok(lhs); } (true, Some(_)) => {