diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 345464c666425..898c8c64d1128 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1714,11 +1714,10 @@ impl<'a> Parser<'a> { } else if self.eat_keyword(keywords::Const) { Mutability::Immutable } else { - let span = self.prev_span; - self.span_err(span, - "expected mut or const in raw pointer type (use \ - `*mut T` or `*const T` as appropriate)"); - Mutability::Immutable + let mut err = self.fatal("expected mut or const in raw pointer type (use \ + `*mut T` or `*const T` as appropriate)"); + err.span_label(self.prev_span, "expected mut or const"); + return Err(err); }; let t = self.parse_ty_no_plus()?; Ok(MutTy { ty: t, mutbl: mutbl }) @@ -2022,20 +2021,39 @@ impl<'a> Parser<'a> { -> PResult<'a, PathSegment> { let ident = self.parse_path_segment_ident()?; - let is_args_start = |token: &token::Token| match *token { - token::Lt | token::BinOp(token::Shl) | token::OpenDelim(token::Paren) => true, + let is_args_start = |token: &token::Token, include_paren: bool| match *token { + token::Lt | token::BinOp(token::Shl) => true, + token::OpenDelim(token::Paren) => include_paren, _ => false, }; - let check_args_start = |this: &mut Self| { - this.expected_tokens.extend_from_slice( - &[TokenType::Token(token::Lt), TokenType::Token(token::OpenDelim(token::Paren))] - ); - is_args_start(&this.token) + let check_args_start = |this: &mut Self, include_paren: bool| { + this.expected_tokens.push(TokenType::Token(token::Lt)); + if include_paren { + this.expected_tokens.push(TokenType::Token(token::OpenDelim(token::Paren))); + } + is_args_start(&this.token, include_paren) }; - Ok(if style == PathStyle::Type && check_args_start(self) || - style != PathStyle::Mod && self.check(&token::ModSep) - && self.look_ahead(1, |t| is_args_start(t)) { + let mut parser_snapshot_before_generics = None; + + Ok(if style == PathStyle::Type && check_args_start(self, true) + || style != PathStyle::Mod && self.check(&token::ModSep) + && self.look_ahead(1, |t| is_args_start(t, true)) + && { + if style == PathStyle::Expr { + // Simulate every occurrence of `::<>` actually being `<>`. + self.eat(&token::ModSep); + parser_snapshot_before_generics = Some(self.clone()); + } + true + } + || style == PathStyle::Expr && check_args_start(self, false) && { + // Check for generic arguments in an expression without a disambiguating `::`. + // We have to save a snapshot, because it could end up being an expression + // instead. + parser_snapshot_before_generics = Some(self.clone()); + true + } { // Generic arguments are found - `<`, `(`, `::<` or `::(`. let lo = self.span; if self.eat(&token::ModSep) && style == PathStyle::Type && enable_warning { @@ -2045,10 +2063,26 @@ impl<'a> Parser<'a> { let args = if self.eat_lt() { // `<'a, T, A = U>` - let (args, bindings) = self.parse_generic_args()?; - self.expect_gt()?; - let span = lo.to(self.prev_span); - AngleBracketedArgs { args, bindings, span }.into() + let args: PResult<_> = do catch { + let (args, bindings) = self.parse_generic_args()?; + self.expect_gt()?; + let span = lo.to(self.prev_span); + AngleBracketedArgs { args, bindings, span } + }; + + match args { + Err(mut err) => { + if let Some(snapshot) = parser_snapshot_before_generics { + err.cancel(); + mem::replace(self, snapshot); + return Ok(PathSegment::from_ident(ident)); + } + return Err(err); + } + _ => { + args?.into() + } + } } else { // `(T, U) -> R` self.bump(); // `(` diff --git a/src/libsyntax/parse/token.rs b/src/libsyntax/parse/token.rs index 1d0c6b5317a38..7e586d03234b2 100644 --- a/src/libsyntax/parse/token.rs +++ b/src/libsyntax/parse/token.rs @@ -167,7 +167,7 @@ pub enum Token { Comma, Semi, Colon, - ModSep, + ModSep, // `::` RArrow, LArrow, FatArrow, diff --git a/src/test/parse-fail/pat-ranges-2.rs b/src/test/parse-fail/pat-ranges-2.rs index 64c749333cf4a..fd76e794cd8d0 100644 --- a/src/test/parse-fail/pat-ranges-2.rs +++ b/src/test/parse-fail/pat-ranges-2.rs @@ -11,5 +11,5 @@ // Parsing of range patterns fn main() { - let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, or `=`, found `!` + let 10 ..= makropulos!() = 12; //~ error: expected one of `::`, `:`, `;`, `<`, or `=`, found `!` } diff --git a/src/test/parse-fail/require-parens-for-chained-comparison.rs b/src/test/parse-fail/require-parens-for-chained-comparison.rs index 1ee6996ce9c84..c330c17804ba1 100644 --- a/src/test/parse-fail/require-parens-for-chained-comparison.rs +++ b/src/test/parse-fail/require-parens-for-chained-comparison.rs @@ -18,9 +18,4 @@ fn main() { false == 0 < 2; //~^ ERROR: chained comparison operators require parentheses - - f(); - //~^ ERROR: chained comparison operators require parentheses - //~| HELP: use `::<...>` instead of `<...>` - //~| HELP: or use `(...)` } diff --git a/src/test/ui/did_you_mean/issue-40396.rs b/src/test/ui/did_you_mean/issue-40396.rs index eb62dc5408494..0f6758d9fd681 100644 --- a/src/test/ui/did_you_mean/issue-40396.rs +++ b/src/test/ui/did_you_mean/issue-40396.rs @@ -9,16 +9,16 @@ // except according to those terms. fn foo() { - println!("{:?}", (0..13).collect>()); //~ ERROR chained comparison + println!("{:?}", (0..13).collect>()); // ok } fn bar() { - println!("{:?}", Vec::new()); //~ ERROR chained comparison + println!("{:?}", Vec::new()); // ok } fn qux() { - println!("{:?}", (0..13).collect()); //~ ERROR chained comparison - //~^ ERROR chained comparison + println!("{:?}", (0..13).collect()); //~ ERROR expected function, found struct `Vec` + //~^ ERROR attempted to take value of method `collect` } fn main() {} diff --git a/src/test/ui/did_you_mean/issue-40396.stderr b/src/test/ui/did_you_mean/issue-40396.stderr index 219fd45665a94..4669a105270bd 100644 --- a/src/test/ui/did_you_mean/issue-40396.stderr +++ b/src/test/ui/did_you_mean/issue-40396.stderr @@ -1,38 +1,18 @@ -error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:12:37 +error[E0423]: expected function, found struct `Vec` + --> $DIR/issue-40396.rs:20:38 | -LL | println!("{:?}", (0..13).collect>()); //~ ERROR chained comparison - | ^^^^^^^^ - | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments - -error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:16:25 - | -LL | println!("{:?}", Vec::new()); //~ ERROR chained comparison - | ^^^^^^^ - | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments - -error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:20:37 - | -LL | println!("{:?}", (0..13).collect()); //~ ERROR chained comparison - | ^^^^^^^^ - | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments +LL | println!("{:?}", (0..13).collect()); //~ ERROR expected function, found struct `Vec` + | ^^^^^^^^ did you mean `Vec { /* fields */ }`? -error: chained comparison operators require parentheses - --> $DIR/issue-40396.rs:20:41 +error[E0615]: attempted to take value of method `collect` on type `std::ops::Range<{integer}>` + --> $DIR/issue-40396.rs:20:30 | -LL | println!("{:?}", (0..13).collect()); //~ ERROR chained comparison - | ^^^^^^ +LL | println!("{:?}", (0..13).collect()); //~ ERROR expected function, found struct `Vec` + | ^^^^^^^ | - = help: use `::<...>` instead of `<...>` if you meant to specify type arguments - = help: or use `(...)` if you meant to specify fn arguments + = help: maybe a `()` to call it is missing? -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors +Some errors occurred: E0423, E0615. +For more information about an error, try `rustc --explain E0423`. diff --git a/src/test/ui/issues/issue-6596-2.stderr b/src/test/ui/issues/issue-6596-2.stderr index f2ed17f35e697..c34b053653649 100644 --- a/src/test/ui/issues/issue-6596-2.stderr +++ b/src/test/ui/issues/issue-6596-2.stderr @@ -7,11 +7,11 @@ LL | { $inp $nonexistent } LL | g!(foo); | -------- in this macro invocation -error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `nonexistent` +error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `nonexistent` --> $DIR/issue-6596-2.rs:15:16 | LL | { $inp $nonexistent } - | ^^^^^^^^^^^^ expected one of 8 possible tokens here + | ^^^^^^^^^^^^ expected one of 9 possible tokens here ... LL | g!(foo); | -------- in this macro invocation diff --git a/src/test/ui/macro_backtrace/main.stderr b/src/test/ui/macro_backtrace/main.stderr index 10eabca63538d..54dfd35121d3b 100644 --- a/src/test/ui/macro_backtrace/main.stderr +++ b/src/test/ui/macro_backtrace/main.stderr @@ -1,21 +1,21 @@ -error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` +error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `error` --> $DIR/main.rs:19:20 | LL | / macro_rules! pong { LL | | () => { syntax error }; - | | ^^^^^ expected one of 8 possible tokens here + | | ^^^^^ expected one of 9 possible tokens here LL | | } | |_- in this expansion of `pong!` ... LL | pong!(); | -------- in this macro invocation -error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` +error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `error` --> $DIR/main.rs:19:20 | LL | / macro_rules! pong { LL | | () => { syntax error }; - | | ^^^^^ expected one of 8 possible tokens here + | | ^^^^^ expected one of 9 possible tokens here LL | | } | |_- in this expansion of `pong!` ... @@ -30,12 +30,12 @@ LL | ( ) => { pong ! ( ) ; } | | in this macro invocation | in this expansion of `ping!` -error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` +error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `error` --> $DIR/main.rs:19:20 | LL | / macro_rules! pong { LL | | () => { syntax error }; - | | ^^^^^ expected one of 8 possible tokens here + | | ^^^^^ expected one of 9 possible tokens here LL | | } | |_- in this expansion of `pong!` (#5) ... diff --git a/src/test/ui/raw/raw-literal-keywords.stderr b/src/test/ui/raw/raw-literal-keywords.stderr index 022f80ae8a4ec..143ef7cc03ba6 100644 --- a/src/test/ui/raw/raw-literal-keywords.stderr +++ b/src/test/ui/raw/raw-literal-keywords.stderr @@ -1,20 +1,20 @@ -error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `true` +error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `true` --> $DIR/raw-literal-keywords.rs:16:10 | LL | r#if true { } //~ ERROR found `true` - | ^^^^ expected one of 8 possible tokens here + | ^^^^ expected one of 9 possible tokens here -error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test` +error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `Test` --> $DIR/raw-literal-keywords.rs:20:14 | LL | r#struct Test; //~ ERROR found `Test` - | ^^^^ expected one of 8 possible tokens here + | ^^^^ expected one of 9 possible tokens here -error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `Test` +error: expected one of `!`, `.`, `::`, `;`, `<`, `?`, `{`, `}`, or an operator, found `Test` --> $DIR/raw-literal-keywords.rs:24:13 | LL | r#union Test; //~ ERROR found `Test` - | ^^^^ expected one of 8 possible tokens here + | ^^^^ expected one of 9 possible tokens here error: aborting due to 3 previous errors