From 0952856e6c78ec00fd2bc1bfc3a162d883446f50 Mon Sep 17 00:00:00 2001 From: Esteban Küber Date: Mon, 26 Nov 2018 10:11:46 -0800 Subject: Suggest an appropriate token when encountering `pub Ident<'a>` --- src/libsyntax/parse/parser.rs | 39 ++++++++++++++++------ src/test/ui/pub/pub-ident-fn-with-lifetime.rs | 6 ++++ src/test/ui/pub/pub-ident-fn-with-lifetime.stderr | 12 +++++++ src/test/ui/pub/pub-ident-struct-with-lifetime.rs | 4 +++ .../ui/pub/pub-ident-struct-with-lifetime.stderr | 12 +++++++ .../ui/pub/pub-ident-with-lifetime-incomplete.rs | 5 +++ .../pub/pub-ident-with-lifetime-incomplete.stderr | 8 +++++ 7 files changed, 75 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/pub/pub-ident-fn-with-lifetime.rs create mode 100644 src/test/ui/pub/pub-ident-fn-with-lifetime.stderr create mode 100644 src/test/ui/pub/pub-ident-struct-with-lifetime.rs create mode 100644 src/test/ui/pub/pub-ident-struct-with-lifetime.stderr create mode 100644 src/test/ui/pub/pub-ident-with-lifetime-incomplete.rs create mode 100644 src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr (limited to 'src') diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 506199b60ad..5257fc44934 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -5802,20 +5802,14 @@ impl<'a> Parser<'a> { } fn complain_if_pub_macro(&mut self, vis: &VisibilityKind, 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: &VisibilityKind, sp: Span) -> PResult<'a, ()> { match *vis { - VisibilityKind::Inherited => Ok(()), + VisibilityKind::Inherited => {} _ => { let is_macro_rules: bool = match self.token { token::Ident(sid, _) => sid.name == Symbol::intern("macro_rules"), _ => false, }; - if is_macro_rules { + let mut err = if is_macro_rules { let mut err = self.diagnostic() .struct_span_err(sp, "can't qualify macro_rules invocation with `pub`"); err.span_suggestion_with_applicability( @@ -5824,13 +5818,14 @@ impl<'a> Parser<'a> { "#[macro_export]".to_owned(), Applicability::MaybeIncorrect // speculative ); - Err(err) + err } else { 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) - } + err + }; + err.emit(); } } } @@ -7439,6 +7434,28 @@ impl<'a> Parser<'a> { } } return Err(err); + } else if self.look_ahead(1, |t| *t == token::Lt) { + let ident = self.parse_ident().unwrap(); + self.eat_to_tokens(&[&token::Gt]); + self.bump(); + let (kw, kw_name, ambiguous) = if self.check(&token::OpenDelim(token::Paren)) { + ("fn", "method", false) + } else if self.check(&token::OpenDelim(token::Brace)) { + ("struct", "struct", false) + } else { + ("fn` or `struct", "method or struct", true) + }; + let msg = format!("missing `{}` for {} definition", kw, kw_name); + let mut err = self.diagnostic().struct_span_err(sp, &msg); + if !ambiguous { + err.span_suggestion_short_with_applicability( + sp, + &format!("add `{}` here to parse `{}` as a public {}", kw, ident, kw_name), + format!(" {} ", kw), + Applicability::MachineApplicable, + ); + } + return Err(err); } } self.parse_macro_use_or_failure(attrs, macros_allowed, attributes_allowed, lo, visibility) diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime.rs b/src/test/ui/pub/pub-ident-fn-with-lifetime.rs new file mode 100644 index 00000000000..973bb924684 --- /dev/null +++ b/src/test/ui/pub/pub-ident-fn-with-lifetime.rs @@ -0,0 +1,6 @@ +pub foo<'a>(_s: &'a usize) -> bool { true } +//~^ ERROR missing `fn` for method definition + +fn main() { + foo(2); +} diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime.stderr b/src/test/ui/pub/pub-ident-fn-with-lifetime.stderr new file mode 100644 index 00000000000..aa609d2cbc6 --- /dev/null +++ b/src/test/ui/pub/pub-ident-fn-with-lifetime.stderr @@ -0,0 +1,12 @@ +error: missing `fn` for method definition + --> $DIR/pub-ident-fn-with-lifetime.rs:1:4 + | +LL | pub foo<'a>(_s: &'a usize) -> bool { true } + | ^^^ +help: add `fn` here to parse `foo` as a public method + | +LL | pub fn foo<'a>(_s: &'a usize) -> bool { true } + | ^^ + +error: aborting due to previous error + diff --git a/src/test/ui/pub/pub-ident-struct-with-lifetime.rs b/src/test/ui/pub/pub-ident-struct-with-lifetime.rs new file mode 100644 index 00000000000..2feb0266070 --- /dev/null +++ b/src/test/ui/pub/pub-ident-struct-with-lifetime.rs @@ -0,0 +1,4 @@ +pub S<'a> { +//~^ ERROR missing `struct` for struct definition +} +fn main() {} diff --git a/src/test/ui/pub/pub-ident-struct-with-lifetime.stderr b/src/test/ui/pub/pub-ident-struct-with-lifetime.stderr new file mode 100644 index 00000000000..2bbcf5dfff0 --- /dev/null +++ b/src/test/ui/pub/pub-ident-struct-with-lifetime.stderr @@ -0,0 +1,12 @@ +error: missing `struct` for struct definition + --> $DIR/pub-ident-struct-with-lifetime.rs:1:4 + | +LL | pub S<'a> { + | ^ +help: add `struct` here to parse `S` as a public struct + | +LL | pub struct S<'a> { + | ^^^^^^ + +error: aborting due to previous error + diff --git a/src/test/ui/pub/pub-ident-with-lifetime-incomplete.rs b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.rs new file mode 100644 index 00000000000..55b1b746bc8 --- /dev/null +++ b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.rs @@ -0,0 +1,5 @@ +fn main() { +} + +pub foo<'a> +//~^ ERROR missing `fn` or `struct` for method or struct definition diff --git a/src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr new file mode 100644 index 00000000000..a55c06f72df --- /dev/null +++ b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr @@ -0,0 +1,8 @@ +error: missing `fn` or `struct` for method or struct definition + --> $DIR/pub-ident-with-lifetime-incomplete.rs:4:4 + | +LL | pub foo<'a> + | ^^^ + +error: aborting due to previous error + -- cgit 1.4.1-3-g733a5