From 57009caabd2a45a6efa4d36149feec39ab0a0658 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Fri, 24 Mar 2017 23:00:21 -0700 Subject: Identify missing item category in `impl`s ```rust struct S; impl S { pub hello_method(&self) { println!("Hello"); } } fn main() { S.hello_method(); } ``` ```rust error: can't qualify macro invocation with `pub` --> file.rs:3:4 | 3 | pub hello_method(&self) { | ^^^- - expected `!` here for a macro invocation | | | did you mean to write `fn` here for a method declaration? | = help: try adjusting the macro to put `pub` inside the invocation ``` --- src/libsyntax/parse/parser.rs | 62 ++++++++++++++++++++++++++++++++----------- 1 file changed, 47 insertions(+), 15 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index df4ccc94c04..a19339f8cc1 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4660,25 +4660,30 @@ impl<'a> Parser<'a> { }) } - fn complain_if_pub_macro(&mut self, visa: &Visibility, span: Span) { - match *visa { - Visibility::Inherited => (), + fn complain_if_pub_macro(&mut self, vis: &Visibility, sp: Span) { + if let Err(mut err) = self.complain_if_pub_macro_diag(vis, sp) { + err.emit(); + } + } + + fn complain_if_pub_macro_diag(&mut self, vis: &Visibility, sp: Span) -> PResult<'a, ()> { + match *vis { + Visibility::Inherited => Ok(()), _ => { let is_macro_rules: bool = match self.token { token::Ident(sid) => sid.name == Symbol::intern("macro_rules"), _ => false, }; if is_macro_rules { - self.diagnostic().struct_span_err(span, "can't qualify macro_rules \ - invocation with `pub`") - .help("did you mean #[macro_export]?") - .emit(); + let mut err = self.diagnostic() + .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); + err.help("did you mean #[macro_export]?"); + Err(err) } else { - self.diagnostic().struct_span_err(span, "can't qualify macro \ - invocation with `pub`") - .help("try adjusting the macro to put `pub` \ - inside the invocation") - .emit(); + let mut err = self.diagnostic() + .struct_span_err(sp, "can't qualify macro invocation with `pub`"); + err.help("try adjusting the macro to put `pub` inside the invocation"); + Err(err) } } } @@ -4689,14 +4694,41 @@ impl<'a> Parser<'a> { -> PResult<'a, (Ident, Vec, ast::ImplItemKind)> { // code copied from parse_macro_use_or_failure... abstraction! if self.token.is_path_start() { - // method macro. + // Method macro. let prev_span = self.prev_span; - self.complain_if_pub_macro(&vis, prev_span); + // Before complaining about trying to set a macro as `pub`, + // check if `!` comes after the path. + let err = self.complain_if_pub_macro_diag(&vis, prev_span); let lo = self.span.lo; let pth = self.parse_path(PathStyle::Mod)?; - self.expect(&token::Not)?; + let bang_err = self.expect(&token::Not); + if let Err(mut err) = err { + if let Err(mut bang_err) = bang_err { + // Given this code `pub path(`, it seems like this is not setting the + // visibility of a macro invocation, but rather a mistyped method declaration. + // Keep the macro diagnostic, but also provide a hint that `fn` might be + // missing. Don't complain about the missing `!` as a separate diagnostic, add + // label in the appropriate place as part of one unified diagnostic. + // + // x | pub path(&self) { + // | ^^^- - expected `!` here for a macro invocation + // | | + // | did you mean to write `fn` here for a method declaration? + + bang_err.cancel(); + err.span_label(self.span, &"expected `!` here for a macro invocation"); + // pub path( + // ^^ `sp` below will point to this + let sp = mk_sp(prev_span.hi, self.prev_span.lo); + err.span_label(sp, + &"did you mean to write `fn` here for a method declaration?"); + } + return Err(err); + } else if let Err(bang_err) = bang_err { + return Err(bang_err); + } // eat a matched-delimiter token tree: let (delim, tts) = self.expect_delimited_token_tree()?; -- cgit 1.4.1-3-g733a5 From 03eca713816ee00ecacde27cc655dc199c6bff40 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Fri, 24 Mar 2017 19:14:58 -0700 Subject: Point at last valid token on failed `expect_one_of` ```rust error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` --> $DIR/token-error-correct-3.rs:29:9 | 25 | foo() | - expected one of `.`, `;`, `?`, `}`, or an operator after this ... 29 | } else { | ^ unexpected token ``` --- src/libsyntax/parse/parser.rs | 28 ++++++++++++------------ src/test/compile-fail/issue-10636-2.rs | 2 ++ src/test/compile-fail/macro-incomplete-parse.rs | 2 ++ src/test/parse-fail/bounds-obj-parens.rs | 4 +++- src/test/parse-fail/match-refactor-to-expr.rs | 4 +++- src/test/parse-fail/trailing-plus-in-bounds.rs | 4 +++- src/test/ui/resolve/token-error-correct-3.stderr | 9 ++++++-- src/test/ui/resolve/token-error-correct.stderr | 4 +++- 8 files changed, 37 insertions(+), 20 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index df4ccc94c04..6379015055b 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -548,20 +548,20 @@ impl<'a> Parser<'a> { expected.dedup(); let expect = tokens_to_string(&expected[..]); let actual = self.this_token_to_string(); - Err(self.fatal( - &(if expected.len() > 1 { - (format!("expected one of {}, found `{}`", - expect, - actual)) - } else if expected.is_empty() { - (format!("unexpected token: `{}`", - actual)) - } else { - (format!("expected {}, found `{}`", - expect, - actual)) - })[..] - )) + let (msg_exp, label_exp) = if expected.len() > 1 { + (format!("expected one of {}, found `{}`", expect, actual), + format!("expected one of {} after this", expect)) + } else if expected.is_empty() { + (format!("unexpected token: `{}`", actual), + "unexpected token after this".to_string()) + } else { + (format!("expected {}, found `{}`", expect, actual), + format!("expected {} after this", expect)) + }; + let mut err = self.fatal(&msg_exp); + err.span_label(self.prev_span, &label_exp); + err.span_label(self.span, &"unexpected token"); + Err(err) } } diff --git a/src/test/compile-fail/issue-10636-2.rs b/src/test/compile-fail/issue-10636-2.rs index beaf9e5059f..93759123618 100644 --- a/src/test/compile-fail/issue-10636-2.rs +++ b/src/test/compile-fail/issue-10636-2.rs @@ -14,5 +14,7 @@ pub fn trace_option(option: Option) { option.map(|some| 42; //~ NOTE: unclosed delimiter //~^ ERROR: expected one of + //~| NOTE: expected one of + //~| NOTE: unexpected token } //~ ERROR: incorrect close delimiter //~^ ERROR: expected expression, found `)` diff --git a/src/test/compile-fail/macro-incomplete-parse.rs b/src/test/compile-fail/macro-incomplete-parse.rs index c2ac99d1f6a..682664df981 100644 --- a/src/test/compile-fail/macro-incomplete-parse.rs +++ b/src/test/compile-fail/macro-incomplete-parse.rs @@ -20,6 +20,8 @@ macro_rules! ignored_item { macro_rules! ignored_expr { () => ( 1, //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + //~^ NOTE expected one of `.`, `;`, `?`, `}`, or an operator after this + //~| NOTE unexpected token 2 ) } diff --git a/src/test/parse-fail/bounds-obj-parens.rs b/src/test/parse-fail/bounds-obj-parens.rs index ad59d4a52d7..02c119cf727 100644 --- a/src/test/parse-fail/bounds-obj-parens.rs +++ b/src/test/parse-fail/bounds-obj-parens.rs @@ -12,4 +12,6 @@ type A = Box<(Fn(D::Error) -> E) + 'static + Send + Sync>; // OK (but see #39318) -FAIL //~ ERROR +FAIL +//~^ ERROR +//~| ERROR diff --git a/src/test/parse-fail/match-refactor-to-expr.rs b/src/test/parse-fail/match-refactor-to-expr.rs index 37b66601e70..7bb1c40118a 100644 --- a/src/test/parse-fail/match-refactor-to-expr.rs +++ b/src/test/parse-fail/match-refactor-to-expr.rs @@ -14,7 +14,9 @@ fn main() { let foo = match //~ NOTE did you mean to remove this `match` keyword? Some(4).unwrap_or_else(5) - ; //~ ERROR expected one of `.`, `?`, `{`, or an operator, found `;` + //~^ NOTE expected one of `.`, `?`, `{`, or an operator after this + ; //~ NOTE unexpected token + //~^ ERROR expected one of `.`, `?`, `{`, or an operator, found `;` println!("{}", foo) } diff --git a/src/test/parse-fail/trailing-plus-in-bounds.rs b/src/test/parse-fail/trailing-plus-in-bounds.rs index 4a2e6d5bdcd..2bb2c97790c 100644 --- a/src/test/parse-fail/trailing-plus-in-bounds.rs +++ b/src/test/parse-fail/trailing-plus-in-bounds.rs @@ -16,4 +16,6 @@ fn main() { let x: Box = box 3 as Box; // Trailing `+` is OK } -FAIL //~ ERROR +FAIL +//~^ ERROR +//~| ERROR diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index 56e36889575..2e0edf0c4b8 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -14,13 +14,18 @@ error: expected one of `,`, `.`, `?`, or an operator, found `;` --> $DIR/token-error-correct-3.rs:23:35 | 23 | callback(path.as_ref(); //~ NOTE: unclosed delimiter - | ^ + | -^ unexpected token + | | + | expected one of `,`, `.`, `?`, or an operator after this error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` --> $DIR/token-error-correct-3.rs:29:9 | +25 | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types + | - expected one of `.`, `;`, `?`, `}`, or an operator after this +... 29 | } else { //~ ERROR: incorrect close delimiter: `}` - | ^ + | ^ unexpected token error[E0425]: cannot find function `is_directory` in this scope --> $DIR/token-error-correct-3.rs:21:13 diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr index 248a923efaf..36f298a456a 100644 --- a/src/test/ui/resolve/token-error-correct.stderr +++ b/src/test/ui/resolve/token-error-correct.stderr @@ -32,7 +32,9 @@ error: expected one of `)`, `,`, `.`, `<`, `?`, `break`, `continue`, `false`, `f --> $DIR/token-error-correct.rs:14:13 | 14 | foo(bar(; - | ^ + | -^ unexpected token + | | + | expected one of `)`, `,`, `.`, `<`, `?`, `break`, `continue`, `false`, `for`, `if`, `loop`, `match`, `move`, `return`, `true`, `unsafe`, `while`, or an operator after this error: expected expression, found `)` --> $DIR/token-error-correct.rs:23:1 -- cgit 1.4.1-3-g733a5 From 78ae8feebbf9a2c70d42780d0c646cbbc1f2cdbc Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Sat, 25 Mar 2017 15:36:59 -0700 Subject: Improve wording and spans for unexpected token * Point at where the token was expected instead of the last token successfuly parsed. * Only show `unexpected token` if the next char and the unexpected token don't have the same span. * Change some cfail and pfail tests to ui test. * Don't show all possible tokens in span label if they are more than 6. --- src/libsyntax/parse/parser.rs | 25 +++++++++++---- src/libsyntax_pos/lib.rs | 6 ++++ src/test/compile-fail/issue-10636-2.rs | 20 ------------ src/test/compile-fail/macro-incomplete-parse.rs | 40 ------------------------ src/test/parse-fail/bounds-obj-parens.rs | 17 ---------- src/test/parse-fail/match-refactor-to-expr.rs | 2 +- src/test/parse-fail/trailing-plus-in-bounds.rs | 21 ------------- src/test/ui/resolve/token-error-correct-3.stderr | 6 ++-- src/test/ui/resolve/token-error-correct.stderr | 4 +-- src/test/ui/token/bounds-obj-parens.rs | 17 ++++++++++ src/test/ui/token/bounds-obj-parens.stderr | 7 +++++ src/test/ui/token/issue-10636-2.rs | 20 ++++++++++++ src/test/ui/token/issue-10636-2.stderr | 27 ++++++++++++++++ src/test/ui/token/macro-incomplete-parse.rs | 40 ++++++++++++++++++++++++ src/test/ui/token/macro-incomplete-parse.stderr | 31 ++++++++++++++++++ src/test/ui/token/trailing-plus-in-bounds.rs | 21 +++++++++++++ src/test/ui/token/trailing-plus-in-bounds.stderr | 7 +++++ 17 files changed, 199 insertions(+), 112 deletions(-) delete mode 100644 src/test/compile-fail/issue-10636-2.rs delete mode 100644 src/test/compile-fail/macro-incomplete-parse.rs delete mode 100644 src/test/parse-fail/bounds-obj-parens.rs delete mode 100644 src/test/parse-fail/trailing-plus-in-bounds.rs create mode 100644 src/test/ui/token/bounds-obj-parens.rs create mode 100644 src/test/ui/token/bounds-obj-parens.stderr create mode 100644 src/test/ui/token/issue-10636-2.rs create mode 100644 src/test/ui/token/issue-10636-2.stderr create mode 100644 src/test/ui/token/macro-incomplete-parse.rs create mode 100644 src/test/ui/token/macro-incomplete-parse.stderr create mode 100644 src/test/ui/token/trailing-plus-in-bounds.rs create mode 100644 src/test/ui/token/trailing-plus-in-bounds.stderr (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 6379015055b..4076368c180 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -548,19 +548,32 @@ impl<'a> Parser<'a> { expected.dedup(); let expect = tokens_to_string(&expected[..]); let actual = self.this_token_to_string(); - let (msg_exp, label_exp) = if expected.len() > 1 { + let (msg_exp, (label_sp, label_exp)) = if expected.len() > 1 { + let short_expect = if expected.len() > 6 { + format!("{} possible tokens", expected.len()) + } else { + expect.clone() + }; (format!("expected one of {}, found `{}`", expect, actual), - format!("expected one of {} after this", expect)) + (self.prev_span.next_point(), format!("expected one of {} here", short_expect))) } else if expected.is_empty() { (format!("unexpected token: `{}`", actual), - "unexpected token after this".to_string()) + (self.prev_span, "unexpected token after this".to_string())) } else { (format!("expected {}, found `{}`", expect, actual), - format!("expected {} after this", expect)) + (self.prev_span.next_point(), format!("expected {} here", expect))) }; let mut err = self.fatal(&msg_exp); - err.span_label(self.prev_span, &label_exp); - err.span_label(self.span, &"unexpected token"); + let sp = if self.token == token::Token::Eof { + // This is EOF, don't want to point at the following char, but rather the last token + self.prev_span + } else { + label_sp + }; + err.span_label(sp, &label_exp); + if label_sp != self.span { + err.span_label(self.span, &"unexpected token"); + } Err(err) } } diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 3808923e772..07494ff904e 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -79,6 +79,12 @@ impl Span { Span { lo: BytePos(lo), hi: self.hi, expn_id: self.expn_id} } + /// Returns a new span representing the next character after the end-point of this span + pub fn next_point(self) -> Span { + let lo = BytePos(cmp::max(self.hi.0, self.lo.0 + 1)); + Span { lo: lo, hi: lo, expn_id: self.expn_id} + } + /// Returns `self` if `self` is not the dummy span, and `other` otherwise. pub fn substitute_dummy(self, other: Span) -> Span { if self.source_equal(&DUMMY_SP) { other } else { self } diff --git a/src/test/compile-fail/issue-10636-2.rs b/src/test/compile-fail/issue-10636-2.rs deleted file mode 100644 index 93759123618..00000000000 --- a/src/test/compile-fail/issue-10636-2.rs +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013-2016 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// FIXME(31528) we emit a bunch of silly errors here due to continuing past the -// first one. This would be easy-ish to address by better recovery in tokenisation. - -pub fn trace_option(option: Option) { - option.map(|some| 42; //~ NOTE: unclosed delimiter - //~^ ERROR: expected one of - //~| NOTE: expected one of - //~| NOTE: unexpected token -} //~ ERROR: incorrect close delimiter -//~^ ERROR: expected expression, found `)` diff --git a/src/test/compile-fail/macro-incomplete-parse.rs b/src/test/compile-fail/macro-incomplete-parse.rs deleted file mode 100644 index 682664df981..00000000000 --- a/src/test/compile-fail/macro-incomplete-parse.rs +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2013 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z continue-parse-after-error - -macro_rules! ignored_item { - () => { - fn foo() {} - fn bar() {} - , //~ ERROR macro expansion ignores token `,` - } -} - -macro_rules! ignored_expr { - () => ( 1, //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `,` - //~^ NOTE expected one of `.`, `;`, `?`, `}`, or an operator after this - //~| NOTE unexpected token - 2 ) -} - -macro_rules! ignored_pat { - () => ( 1, 2 ) //~ ERROR macro expansion ignores token `,` -} - -ignored_item!(); //~ NOTE caused by the macro expansion here - -fn main() { - ignored_expr!(); - match 1 { - ignored_pat!() => (), //~ NOTE caused by the macro expansion here - _ => (), - } -} diff --git a/src/test/parse-fail/bounds-obj-parens.rs b/src/test/parse-fail/bounds-obj-parens.rs deleted file mode 100644 index 02c119cf727..00000000000 --- a/src/test/parse-fail/bounds-obj-parens.rs +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z parse-only - -type A = Box<(Fn(D::Error) -> E) + 'static + Send + Sync>; // OK (but see #39318) - -FAIL -//~^ ERROR -//~| ERROR diff --git a/src/test/parse-fail/match-refactor-to-expr.rs b/src/test/parse-fail/match-refactor-to-expr.rs index 7bb1c40118a..e2fee1d1895 100644 --- a/src/test/parse-fail/match-refactor-to-expr.rs +++ b/src/test/parse-fail/match-refactor-to-expr.rs @@ -14,7 +14,7 @@ fn main() { let foo = match //~ NOTE did you mean to remove this `match` keyword? Some(4).unwrap_or_else(5) - //~^ NOTE expected one of `.`, `?`, `{`, or an operator after this + //~^ NOTE expected one of `.`, `?`, `{`, or an operator here ; //~ NOTE unexpected token //~^ ERROR expected one of `.`, `?`, `{`, or an operator, found `;` diff --git a/src/test/parse-fail/trailing-plus-in-bounds.rs b/src/test/parse-fail/trailing-plus-in-bounds.rs deleted file mode 100644 index 2bb2c97790c..00000000000 --- a/src/test/parse-fail/trailing-plus-in-bounds.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// compile-flags: -Z parse-only -Z continue-parse-after-error - -use std::fmt::Debug; - -fn main() { - let x: Box = box 3 as Box; // Trailing `+` is OK -} - -FAIL -//~^ ERROR -//~| ERROR diff --git a/src/test/ui/resolve/token-error-correct-3.stderr b/src/test/ui/resolve/token-error-correct-3.stderr index 2e0edf0c4b8..bf7db67e728 100644 --- a/src/test/ui/resolve/token-error-correct-3.stderr +++ b/src/test/ui/resolve/token-error-correct-3.stderr @@ -14,15 +14,13 @@ error: expected one of `,`, `.`, `?`, or an operator, found `;` --> $DIR/token-error-correct-3.rs:23:35 | 23 | callback(path.as_ref(); //~ NOTE: unclosed delimiter - | -^ unexpected token - | | - | expected one of `,`, `.`, `?`, or an operator after this + | ^ expected one of `,`, `.`, `?`, or an operator here error: expected one of `.`, `;`, `?`, `}`, or an operator, found `)` --> $DIR/token-error-correct-3.rs:29:9 | 25 | fs::create_dir_all(path.as_ref()).map(|()| true) //~ ERROR: mismatched types - | - expected one of `.`, `;`, `?`, `}`, or an operator after this + | - expected one of `.`, `;`, `?`, `}`, or an operator here ... 29 | } else { //~ ERROR: incorrect close delimiter: `}` | ^ unexpected token diff --git a/src/test/ui/resolve/token-error-correct.stderr b/src/test/ui/resolve/token-error-correct.stderr index 36f298a456a..226fa6469bc 100644 --- a/src/test/ui/resolve/token-error-correct.stderr +++ b/src/test/ui/resolve/token-error-correct.stderr @@ -32,9 +32,7 @@ error: expected one of `)`, `,`, `.`, `<`, `?`, `break`, `continue`, `false`, `f --> $DIR/token-error-correct.rs:14:13 | 14 | foo(bar(; - | -^ unexpected token - | | - | expected one of `)`, `,`, `.`, `<`, `?`, `break`, `continue`, `false`, `for`, `if`, `loop`, `match`, `move`, `return`, `true`, `unsafe`, `while`, or an operator after this + | ^ expected one of 18 possible tokens here error: expected expression, found `)` --> $DIR/token-error-correct.rs:23:1 diff --git a/src/test/ui/token/bounds-obj-parens.rs b/src/test/ui/token/bounds-obj-parens.rs new file mode 100644 index 00000000000..02c119cf727 --- /dev/null +++ b/src/test/ui/token/bounds-obj-parens.rs @@ -0,0 +1,17 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only + +type A = Box<(Fn(D::Error) -> E) + 'static + Send + Sync>; // OK (but see #39318) + +FAIL +//~^ ERROR +//~| ERROR diff --git a/src/test/ui/token/bounds-obj-parens.stderr b/src/test/ui/token/bounds-obj-parens.stderr new file mode 100644 index 00000000000..ebee363f278 --- /dev/null +++ b/src/test/ui/token/bounds-obj-parens.stderr @@ -0,0 +1,7 @@ +error: expected one of `!` or `::`, found `` + --> $DIR/bounds-obj-parens.rs:15:1 + | +15 | FAIL + | ^^^^ expected one of `!` or `::` here + +error: aborting due to previous error diff --git a/src/test/ui/token/issue-10636-2.rs b/src/test/ui/token/issue-10636-2.rs new file mode 100644 index 00000000000..93759123618 --- /dev/null +++ b/src/test/ui/token/issue-10636-2.rs @@ -0,0 +1,20 @@ +// Copyright 2013-2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// FIXME(31528) we emit a bunch of silly errors here due to continuing past the +// first one. This would be easy-ish to address by better recovery in tokenisation. + +pub fn trace_option(option: Option) { + option.map(|some| 42; //~ NOTE: unclosed delimiter + //~^ ERROR: expected one of + //~| NOTE: expected one of + //~| NOTE: unexpected token +} //~ ERROR: incorrect close delimiter +//~^ ERROR: expected expression, found `)` diff --git a/src/test/ui/token/issue-10636-2.stderr b/src/test/ui/token/issue-10636-2.stderr new file mode 100644 index 00000000000..183ad30c4ef --- /dev/null +++ b/src/test/ui/token/issue-10636-2.stderr @@ -0,0 +1,27 @@ +error: incorrect close delimiter: `}` + --> $DIR/issue-10636-2.rs:19:1 + | +19 | } //~ ERROR: incorrect close delimiter + | ^ + | +note: unclosed delimiter + --> $DIR/issue-10636-2.rs:15:15 + | +15 | option.map(|some| 42; //~ NOTE: unclosed delimiter + | ^ + +error: expected one of `,`, `.`, `?`, or an operator, found `;` + --> $DIR/issue-10636-2.rs:15:25 + | +15 | option.map(|some| 42; //~ NOTE: unclosed delimiter + | ^ expected one of `,`, `.`, `?`, or an operator here + +error: expected expression, found `)` + --> $DIR/issue-10636-2.rs:19:1 + | +19 | } //~ ERROR: incorrect close delimiter + | ^ + +error: main function not found + +error: aborting due to 4 previous errors diff --git a/src/test/ui/token/macro-incomplete-parse.rs b/src/test/ui/token/macro-incomplete-parse.rs new file mode 100644 index 00000000000..47374fc3c60 --- /dev/null +++ b/src/test/ui/token/macro-incomplete-parse.rs @@ -0,0 +1,40 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z continue-parse-after-error + +macro_rules! ignored_item { + () => { + fn foo() {} + fn bar() {} + , //~ ERROR macro expansion ignores token `,` + } +} + +macro_rules! ignored_expr { + () => ( 1, //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + //~^ NOTE expected one of `.`, `;`, `?`, `}`, or an operator here + //~| NOTE unexpected token + 2 ) +} + +macro_rules! ignored_pat { + () => ( 1, 2 ) //~ ERROR macro expansion ignores token `,` +} + +ignored_item!(); //~ NOTE caused by the macro expansion here + +fn main() { + ignored_expr!(); + match 1 { + ignored_pat!() => (), //~ NOTE caused by the macro expansion here + _ => (), + } +} diff --git a/src/test/ui/token/macro-incomplete-parse.stderr b/src/test/ui/token/macro-incomplete-parse.stderr new file mode 100644 index 00000000000..bea00a6444c --- /dev/null +++ b/src/test/ui/token/macro-incomplete-parse.stderr @@ -0,0 +1,31 @@ +error: macro expansion ignores token `,` and any following + --> $DIR/macro-incomplete-parse.rs:17:9 + | +17 | , //~ ERROR macro expansion ignores token `,` + | ^ + | +note: caused by the macro expansion here; the usage of `ignored_item!` is likely invalid in item context + --> $DIR/macro-incomplete-parse.rs:32:1 + | +32 | ignored_item!(); //~ NOTE caused by the macro expansion here + | ^^^^^^^^^^^^^^^^ + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/macro-incomplete-parse.rs:22:14 + | +22 | () => ( 1, //~ ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + | ^ expected one of `.`, `;`, `?`, `}`, or an operator here + +error: macro expansion ignores token `,` and any following + --> $DIR/macro-incomplete-parse.rs:29:14 + | +29 | () => ( 1, 2 ) //~ ERROR macro expansion ignores token `,` + | ^ + | +note: caused by the macro expansion here; the usage of `ignored_pat!` is likely invalid in pattern context + --> $DIR/macro-incomplete-parse.rs:37:9 + | +37 | ignored_pat!() => (), //~ NOTE caused by the macro expansion here + | ^^^^^^^^^^^^^^ + +error: aborting due to 3 previous errors diff --git a/src/test/ui/token/trailing-plus-in-bounds.rs b/src/test/ui/token/trailing-plus-in-bounds.rs new file mode 100644 index 00000000000..2bb2c97790c --- /dev/null +++ b/src/test/ui/token/trailing-plus-in-bounds.rs @@ -0,0 +1,21 @@ +// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -Z parse-only -Z continue-parse-after-error + +use std::fmt::Debug; + +fn main() { + let x: Box = box 3 as Box; // Trailing `+` is OK +} + +FAIL +//~^ ERROR +//~| ERROR diff --git a/src/test/ui/token/trailing-plus-in-bounds.stderr b/src/test/ui/token/trailing-plus-in-bounds.stderr new file mode 100644 index 00000000000..74caf8f5c2b --- /dev/null +++ b/src/test/ui/token/trailing-plus-in-bounds.stderr @@ -0,0 +1,7 @@ +error: expected one of `!` or `::`, found `` + --> ../../src/test/ui/token/trailing-plus-in-bounds.rs:19:1 + | +19 | FAIL + | ^^^^ expected one of `!` or `::` here + +error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From c963d613a2275d5c9b31cd7124dda2f2af61deb6 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Mon, 27 Mar 2017 17:15:16 -0700 Subject: Simplify error output --- src/libsyntax/parse/parser.rs | 17 ++++++----------- src/test/ui/did_you_mean/issue-40006.stderr | 10 +++------- 2 files changed, 9 insertions(+), 18 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index a19339f8cc1..2603b3302c6 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -4708,26 +4708,21 @@ impl<'a> Parser<'a> { if let Err(mut bang_err) = bang_err { // Given this code `pub path(`, it seems like this is not setting the // visibility of a macro invocation, but rather a mistyped method declaration. - // Keep the macro diagnostic, but also provide a hint that `fn` might be - // missing. Don't complain about the missing `!` as a separate diagnostic, add - // label in the appropriate place as part of one unified diagnostic. + // Create a diagnostic pointing out that `fn` is missing. // // x | pub path(&self) { - // | ^^^- - expected `!` here for a macro invocation - // | | - // | did you mean to write `fn` here for a method declaration? + // | ^ missing `fn` for method declaration + err.cancel(); bang_err.cancel(); - err.span_label(self.span, &"expected `!` here for a macro invocation"); // pub path( // ^^ `sp` below will point to this let sp = mk_sp(prev_span.hi, self.prev_span.lo); - err.span_label(sp, - &"did you mean to write `fn` here for a method declaration?"); + err = self.diagnostic() + .struct_span_err(sp, "missing `fn` for method declaration"); + err.span_label(sp, &"missing `fn`"); } return Err(err); - } else if let Err(bang_err) = bang_err { - return Err(bang_err); } // eat a matched-delimiter token tree: diff --git a/src/test/ui/did_you_mean/issue-40006.stderr b/src/test/ui/did_you_mean/issue-40006.stderr index 93a0c58f91a..460958027ad 100644 --- a/src/test/ui/did_you_mean/issue-40006.stderr +++ b/src/test/ui/did_you_mean/issue-40006.stderr @@ -1,12 +1,8 @@ -error: can't qualify macro invocation with `pub` - --> $DIR/issue-40006.rs:14:5 +error: missing `fn` for method declaration + --> $DIR/issue-40006.rs:14:8 | 14 | pub hello_method(&self) { - | ^^^- - expected `!` here for a macro invocation - | | - | did you mean to write `fn` here for a method declaration? - | - = help: try adjusting the macro to put `pub` inside the invocation + | ^ missing `fn` error: aborting due to previous error -- cgit 1.4.1-3-g733a5 From b477682dca3343eb89a467f0d3c73986a53d49d9 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Sat, 25 Mar 2017 19:06:19 -0700 Subject: Fix unittests --- src/libsyntax/parse/parser.rs | 2 +- src/libsyntax_pos/lib.rs | 4 ++-- src/test/ui/token/bounds-obj-parens.stderr | 1 + src/test/ui/token/issue-10636-2.stderr | 1 + src/test/ui/token/macro-incomplete-parse.stderr | 1 + src/test/ui/token/trailing-plus-in-bounds.stderr | 3 ++- 6 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 4076368c180..8177d738dc8 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -571,7 +571,7 @@ impl<'a> Parser<'a> { label_sp }; err.span_label(sp, &label_exp); - if label_sp != self.span { + if !sp.source_equal(&self.span) { err.span_label(self.span, &"unexpected token"); } Err(err) diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index 07494ff904e..0662c1c9cfd 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -81,8 +81,8 @@ impl Span { /// Returns a new span representing the next character after the end-point of this span pub fn next_point(self) -> Span { - let lo = BytePos(cmp::max(self.hi.0, self.lo.0 + 1)); - Span { lo: lo, hi: lo, expn_id: self.expn_id} + let lo = cmp::max(self.hi.0, self.lo.0 + 1); + Span { lo: BytePos(lo), hi: BytePos(lo + 1), expn_id: self.expn_id} } /// Returns `self` if `self` is not the dummy span, and `other` otherwise. diff --git a/src/test/ui/token/bounds-obj-parens.stderr b/src/test/ui/token/bounds-obj-parens.stderr index ebee363f278..4d60be15eca 100644 --- a/src/test/ui/token/bounds-obj-parens.stderr +++ b/src/test/ui/token/bounds-obj-parens.stderr @@ -5,3 +5,4 @@ error: expected one of `!` or `::`, found `` | ^^^^ expected one of `!` or `::` here error: aborting due to previous error + diff --git a/src/test/ui/token/issue-10636-2.stderr b/src/test/ui/token/issue-10636-2.stderr index 183ad30c4ef..b0bae1248b9 100644 --- a/src/test/ui/token/issue-10636-2.stderr +++ b/src/test/ui/token/issue-10636-2.stderr @@ -25,3 +25,4 @@ error: expected expression, found `)` error: main function not found error: aborting due to 4 previous errors + diff --git a/src/test/ui/token/macro-incomplete-parse.stderr b/src/test/ui/token/macro-incomplete-parse.stderr index bea00a6444c..f23d97586b8 100644 --- a/src/test/ui/token/macro-incomplete-parse.stderr +++ b/src/test/ui/token/macro-incomplete-parse.stderr @@ -29,3 +29,4 @@ note: caused by the macro expansion here; the usage of `ignored_pat!` is likely | ^^^^^^^^^^^^^^ error: aborting due to 3 previous errors + diff --git a/src/test/ui/token/trailing-plus-in-bounds.stderr b/src/test/ui/token/trailing-plus-in-bounds.stderr index 74caf8f5c2b..c765a434b8a 100644 --- a/src/test/ui/token/trailing-plus-in-bounds.stderr +++ b/src/test/ui/token/trailing-plus-in-bounds.stderr @@ -1,7 +1,8 @@ error: expected one of `!` or `::`, found `` - --> ../../src/test/ui/token/trailing-plus-in-bounds.rs:19:1 + --> $DIR/trailing-plus-in-bounds.rs:19:1 | 19 | FAIL | ^^^^ expected one of `!` or `::` here error: aborting due to previous error + -- cgit 1.4.1-3-g733a5 From 6a9448b523b95dbc850e856508342644fc17db45 Mon Sep 17 00:00:00 2001 From: Jeffrey Seyfried Date: Mon, 3 Apr 2017 22:23:32 +0000 Subject: Fix bug parsing `#[derive]` macro invocations. --- src/librustc_resolve/macros.rs | 6 ++++-- src/libsyntax/ext/derive.rs | 3 ++- src/libsyntax/parse/parser.rs | 20 ++++++++++++++++++++ src/test/run-pass/issue-40962.rs | 20 ++++++++++++++++++++ 4 files changed, 46 insertions(+), 3 deletions(-) create mode 100644 src/test/run-pass/issue-40962.rs (limited to 'src/libsyntax/parse') diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs index 05f30f039c8..966cb7ee8d8 100644 --- a/src/librustc_resolve/macros.rs +++ b/src/librustc_resolve/macros.rs @@ -222,8 +222,10 @@ impl<'a> base::Resolver for Resolver<'a> { let name = unwrap_or!(attrs[i].name(), continue); if name == "derive" { - let result = attrs[i].parse_list(&self.session.parse_sess, - |parser| parser.parse_path(PathStyle::Mod)); + let result = attrs[i].parse_list(&self.session.parse_sess, |parser| { + parser.parse_path_allowing_meta(PathStyle::Mod) + }); + let mut traits = match result { Ok(traits) => traits, Err(mut e) => { diff --git a/src/libsyntax/ext/derive.rs b/src/libsyntax/ext/derive.rs index c79040424f6..e7c5d8278d9 100644 --- a/src/libsyntax/ext/derive.rs +++ b/src/libsyntax/ext/derive.rs @@ -26,7 +26,8 @@ pub fn collect_derives(cx: &mut ExtCtxt, attrs: &mut Vec) -> Vec return true; } - match attr.parse_list(cx.parse_sess, |parser| parser.parse_path(PathStyle::Mod)) { + match attr.parse_list(cx.parse_sess, + |parser| parser.parse_path_allowing_meta(PathStyle::Mod)) { Ok(ref traits) if traits.is_empty() => { cx.span_warn(attr.span, "empty trait list in `derive`"); false diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index c2c3e5a6855..a89811d8abb 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -1754,6 +1754,26 @@ impl<'a> Parser<'a> { }) } + /// Like `parse_path`, but also supports parsing `Word` meta items into paths for back-compat. + /// This is used when parsing derive macro paths in `#[derive]` attributes. + pub fn parse_path_allowing_meta(&mut self, mode: PathStyle) -> PResult<'a, ast::Path> { + let meta_ident = match self.token { + token::Interpolated(ref nt) => match **nt { + token::NtMeta(ref meta) => match meta.node { + ast::MetaItemKind::Word => Some(ast::Ident::with_empty_ctxt(meta.name)), + _ => None, + }, + _ => None, + }, + _ => None, + }; + if let Some(ident) = meta_ident { + self.bump(); + return Ok(ast::Path::from_ident(self.prev_span, ident)); + } + self.parse_path(mode) + } + /// Examples: /// - `a::b::c` /// - `a::b::c(V) -> W` diff --git a/src/test/run-pass/issue-40962.rs b/src/test/run-pass/issue-40962.rs new file mode 100644 index 00000000000..b35cfa12eab --- /dev/null +++ b/src/test/run-pass/issue-40962.rs @@ -0,0 +1,20 @@ +// Copyright 2017 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +macro_rules! m { + ($i:meta) => { + #[derive($i)] + struct S; + } +} + +m!(Clone); + +fn main() {} -- cgit 1.4.1-3-g733a5