about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-12-08 09:56:32 +0000
committerbors <bors@rust-lang.org>2018-12-08 09:56:32 +0000
commit9772d02774534aa4ccd0b328364403d5b6cda1d0 (patch)
tree2772335186306e975aa4d8f4156cabefd5949b6f
parent1ccb5b219d50b1bc96dbb85e82a8473f16422582 (diff)
parenta8cc9166d47afebea15e6079d033fa37ecda3f7d (diff)
downloadrust-9772d02774534aa4ccd0b328364403d5b6cda1d0.tar.gz
rust-9772d02774534aa4ccd0b328364403d5b6cda1d0.zip
Auto merge of #56623 - Centril:rollup, r=Centril
Rollup of 6 pull requests

Successful merges:

 - #56248 (Suggest an appropriate token when encountering `pub Ident<'a>`)
 - #56597 (Improve the usage message for `-Z dump-mir`.)
 - #56599 (codegen: Fix va_list - aarch64 iOS/Windows)
 - #56602 (Fix the just-introduced ptr::hash docs)
 - #56620 (resolve: Reduce some clutter in import ambiguity errors)
 - #56621 (Add missing comma in Generators)

Failed merges:

r? @ghost
-rw-r--r--src/doc/unstable-book/src/language-features/generators.md2
-rw-r--r--src/libcore/ffi.rs2
-rw-r--r--src/libcore/ptr.rs7
-rw-r--r--src/librustc/session/config.rs8
-rw-r--r--src/librustc_codegen_llvm/va_arg.rs36
-rw-r--r--src/librustc_resolve/resolve_imports.rs42
-rw-r--r--src/libsyntax/parse/parser.rs68
-rw-r--r--src/test/ui/imports/issue-56125.rs2
-rw-r--r--src/test/ui/imports/issue-56125.stderr26
-rw-r--r--src/test/ui/pub/pub-ident-fn-2.rs2
-rw-r--r--src/test/ui/pub/pub-ident-fn-2.stderr4
-rw-r--r--src/test/ui/pub/pub-ident-fn-or-struct-2.rs2
-rw-r--r--src/test/ui/pub/pub-ident-fn-or-struct-2.stderr2
-rw-r--r--src/test/ui/pub/pub-ident-fn-or-struct.rs2
-rw-r--r--src/test/ui/pub/pub-ident-fn-or-struct.stderr2
-rw-r--r--src/test/ui/pub/pub-ident-fn-with-lifetime-2.rs6
-rw-r--r--src/test/ui/pub/pub-ident-fn-with-lifetime-2.stderr12
-rw-r--r--src/test/ui/pub/pub-ident-fn-with-lifetime.rs6
-rw-r--r--src/test/ui/pub/pub-ident-fn-with-lifetime.stderr12
-rw-r--r--src/test/ui/pub/pub-ident-fn.fixed2
-rw-r--r--src/test/ui/pub/pub-ident-fn.rs2
-rw-r--r--src/test/ui/pub/pub-ident-fn.stderr4
-rw-r--r--src/test/ui/pub/pub-ident-struct-with-lifetime.rs4
-rw-r--r--src/test/ui/pub/pub-ident-struct-with-lifetime.stderr12
-rw-r--r--src/test/ui/pub/pub-ident-with-lifetime-incomplete.rs5
-rw-r--r--src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr8
26 files changed, 195 insertions, 85 deletions
diff --git a/src/doc/unstable-book/src/language-features/generators.md b/src/doc/unstable-book/src/language-features/generators.md
index 8e888de90a9..968534e58bd 100644
--- a/src/doc/unstable-book/src/language-features/generators.md
+++ b/src/doc/unstable-book/src/language-features/generators.md
@@ -149,7 +149,7 @@ closure-like semantics. Namely:
 * Whenever a generator is dropped it will drop all captured environment
   variables.
 
-Note that unlike closures generators at this time cannot take any arguments.
+Note that unlike closures, generators at this time cannot take any arguments.
 That is, generators must always look like `|| { ... }`. This restriction may be
 lifted at a future date, the design is ongoing!
 
diff --git a/src/libcore/ffi.rs b/src/libcore/ffi.rs
index 1dbf03923e1..d7a112eb90d 100644
--- a/src/libcore/ffi.rs
+++ b/src/libcore/ffi.rs
@@ -45,6 +45,7 @@ impl fmt::Debug for c_void {
 /// Basic implementation of a `va_list`.
 #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
               not(target_arch = "x86_64")),
+          all(target_arch = "aarch4", target_os = "ios"),
           windows))]
 #[unstable(feature = "c_variadic",
            reason = "the `c_variadic` feature has not been properly tested on \
@@ -192,6 +193,7 @@ impl<'a> VaList<'a> {
             where F: for<'copy> FnOnce(VaList<'copy>) -> R {
         #[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
                       not(target_arch = "x86_64")),
+                  all(target_arch = "aarch4", target_os = "ios"),
                   windows))]
         let mut ap = va_copy(self);
         #[cfg(all(any(target_arch = "aarch64", target_arch = "powerpc", target_arch = "x86_64"),
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index a2d32e9d68f..b11ae303272 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2516,8 +2516,11 @@ pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
     a == b
 }
 
-/// Hash the raw pointer address behind a reference, rather than the value
-/// it points to.
+/// Hash a raw pointer.
+///
+/// This can be used to hash a `&T` reference (which coerces to `*const T` implicitly)
+/// by its address rather than the value it points to
+/// (which is what the `Hash for &T` implementation does).
 ///
 /// # Examples
 ///
diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs
index 51855ff6cc8..750b7f151f5 100644
--- a/src/librustc/session/config.rs
+++ b/src/librustc/session/config.rs
@@ -1272,7 +1272,13 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
     arg_align_attributes: bool = (false, parse_bool, [TRACKED],
         "emit align metadata for reference arguments"),
     dump_mir: Option<String> = (None, parse_opt_string, [UNTRACKED],
-        "dump MIR state at various points in transforms"),
+        "dump MIR state to file.
+        `val` is used to select which passes and functions to dump. For example:
+        `all` matches all passes and functions,
+        `foo` matches all passes for functions whose name contains 'foo',
+        `foo & ConstProp` only the 'ConstProp' pass for function names containing 'foo',
+        `foo | bar` all passes for function names containing 'foo' or 'bar'."),
+
     dump_mir_dir: String = (String::from("mir_dump"), parse_string, [UNTRACKED],
         "the directory the MIR is dumped into"),
     dump_mir_graphviz: bool = (false, parse_bool, [UNTRACKED],
diff --git a/src/librustc_codegen_llvm/va_arg.rs b/src/librustc_codegen_llvm/va_arg.rs
index fbc3e6f06d1..1e5bb03ddb1 100644
--- a/src/librustc_codegen_llvm/va_arg.rs
+++ b/src/librustc_codegen_llvm/va_arg.rs
@@ -105,13 +105,30 @@ pub(super) fn emit_va_arg(
 ) -> &'ll Value {
     // Determine the va_arg implementation to use. The LLVM va_arg instruction
     // is lacking in some instances, so we should only use it as a fallback.
+    let target = &bx.cx.tcx.sess.target.target;
     let arch = &bx.cx.tcx.sess.target.target.arch;
-    match (&**arch,
-           bx.cx.tcx.sess.target.target.options.is_like_windows) {
+    match (&**arch, target.options.is_like_windows) {
+        // Windows x86
         ("x86", true) => {
             emit_ptr_va_arg(bx, addr, target_ty, false,
                             Align::from_bytes(4).unwrap(), false)
         }
+        // Generic x86
+        ("x86", _) => {
+            emit_ptr_va_arg(bx, addr, target_ty, false,
+                            Align::from_bytes(4).unwrap(), true)
+        }
+        // Windows Aarch64
+        ("aarch4", true) => {
+            emit_ptr_va_arg(bx, addr, target_ty, false,
+                            Align::from_bytes(8).unwrap(), false)
+        }
+        // iOS Aarch64
+        ("aarch4", _) if target.target_os == "ios" => {
+            emit_ptr_va_arg(bx, addr, target_ty, false,
+                            Align::from_bytes(8).unwrap(), true)
+        }
+        // Windows x86_64
         ("x86_64", true) => {
             let target_ty_size = bx.cx.size_of(target_ty).bytes();
             let indirect = if target_ty_size > 8 || !target_ty_size.is_power_of_two() {
@@ -122,15 +139,14 @@ pub(super) fn emit_va_arg(
             emit_ptr_va_arg(bx, addr, target_ty, indirect,
                             Align::from_bytes(8).unwrap(), false)
         }
-        ("x86", false) => {
-            emit_ptr_va_arg(bx, addr, target_ty, false,
-                            Align::from_bytes(4).unwrap(), true)
-        }
+        // For all other architecture/OS combinations fall back to using
+        // the LLVM va_arg instruction.
+        // https://llvm.org/docs/LangRef.html#va-arg-instruction
         _ => {
-            let va_list = if (bx.tcx().sess.target.target.arch == "aarch64" ||
-                              bx.tcx().sess.target.target.arch == "x86_64" ||
-                              bx.tcx().sess.target.target.arch == "powerpc") &&
-                             !bx.tcx().sess.target.target.options.is_like_windows {
+            let va_list = if (target.arch == "aarch64" ||
+                              target.arch == "x86_64" ||
+                              target.arch == "powerpc") &&
+                             !target.options.is_like_windows {
                 bx.load(addr.immediate(), bx.tcx().data_layout.pointer_align.abi)
             } else {
                 addr.immediate()
diff --git a/src/librustc_resolve/resolve_imports.rs b/src/librustc_resolve/resolve_imports.rs
index f130895e236..015cd31ac1d 100644
--- a/src/librustc_resolve/resolve_imports.rs
+++ b/src/librustc_resolve/resolve_imports.rs
@@ -843,14 +843,16 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
         self.current_module = directive.parent_scope.module;
 
         let orig_vis = directive.vis.replace(ty::Visibility::Invisible);
+        let prev_ambiguity_errors_len = self.ambiguity_errors.len();
         let path_res = self.resolve_path(&directive.module_path, None, &directive.parent_scope,
                                          true, directive.span, directive.crate_lint());
+        let no_ambiguity = self.ambiguity_errors.len() == prev_ambiguity_errors_len;
         directive.vis.set(orig_vis);
         let module = match path_res {
             PathResult::Module(module) => {
                 // Consistency checks, analogous to `finalize_current_module_macro_resolutions`.
                 if let Some(initial_module) = directive.imported_module.get() {
-                    if module != initial_module && self.ambiguity_errors.is_empty() {
+                    if module != initial_module && no_ambiguity {
                         span_bug!(directive.span, "inconsistent resolution for an import");
                     }
                 } else {
@@ -864,30 +866,32 @@ impl<'a, 'b:'a, 'c: 'b> ImportResolver<'a, 'b, 'c> {
                 module
             }
             PathResult::Failed(span, msg, false) => {
-                assert!(!self.ambiguity_errors.is_empty() ||
-                        directive.imported_module.get().is_none());
-                resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
+                if no_ambiguity {
+                    assert!(directive.imported_module.get().is_none());
+                    resolve_error(self, span, ResolutionError::FailedToResolve(&msg));
+                }
                 return None;
             }
             PathResult::Failed(span, msg, true) => {
-                assert!(!self.ambiguity_errors.is_empty() ||
-                        directive.imported_module.get().is_none());
-                return if let Some((suggested_path, note)) = self.make_path_suggestion(
-                    span, directive.module_path.clone(), &directive.parent_scope
-                ) {
-                    Some((
-                        span,
-                        format!("did you mean `{}`?", Segment::names_to_string(&suggested_path)),
-                        note,
-                    ))
-                } else {
-                    Some((span, msg, None))
-                };
+                if no_ambiguity {
+                    assert!(directive.imported_module.get().is_none());
+                    return Some(match self.make_path_suggestion(span, directive.module_path.clone(),
+                                                                &directive.parent_scope) {
+                        Some((suggestion, note)) => (
+                            span,
+                            format!("did you mean `{}`?", Segment::names_to_string(&suggestion)),
+                            note,
+                        ),
+                        None => (span, msg, None),
+                    });
+                }
+                return None;
             }
             PathResult::NonModule(path_res) if path_res.base_def() == Def::Err => {
+                if no_ambiguity {
+                    assert!(directive.imported_module.get().is_none());
+                }
                 // The error was already reported earlier.
-                assert!(!self.ambiguity_errors.is_empty() ||
-                        directive.imported_module.get().is_none());
                 return None;
             }
             PathResult::Indeterminate | PathResult::NonModule(..) => unreachable!(),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 9a9b615233b..e3a3454de49 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -5811,20 +5811,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(
@@ -5833,13 +5827,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();
             }
         }
     }
@@ -6148,9 +6143,6 @@ impl<'a> Parser<'a> {
 
     fn consume_block(&mut self, delim: token::DelimToken) {
         let mut brace_depth = 0;
-        if !self.eat(&token::OpenDelim(delim)) {
-            return;
-        }
         loop {
             if self.eat(&token::OpenDelim(delim)) {
                 brace_depth += 1;
@@ -6161,7 +6153,7 @@ impl<'a> Parser<'a> {
                     brace_depth -= 1;
                     continue;
                 }
-            } else if self.eat(&token::Eof) || self.eat(&token::CloseDelim(token::NoDelim)) {
+            } else if self.token == token::Eof || self.eat(&token::CloseDelim(token::NoDelim)) {
                 return;
             } else {
                 self.bump();
@@ -7410,17 +7402,27 @@ impl<'a> Parser<'a> {
                 return Err(err);
             } else if self.look_ahead(1, |t| *t == token::OpenDelim(token::Paren)) {
                 let ident = self.parse_ident().unwrap();
+                self.bump();  // `(`
+                let kw_name = if let Ok(Some(_)) = self.parse_self_arg() {
+                    "method"
+                } else {
+                    "function"
+                };
                 self.consume_block(token::Paren);
-                let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) ||
-                    self.check(&token::OpenDelim(token::Brace))
-                {
-                    ("fn", "method", false)
+                let (kw, kw_name, ambiguous) = if self.check(&token::RArrow) {
+                    self.eat_to_tokens(&[&token::OpenDelim(token::Brace)]);
+                    self.bump();  // `{`
+                    ("fn", kw_name, false)
+                } else if self.check(&token::OpenDelim(token::Brace)) {
+                    self.bump();  // `{`
+                    ("fn", kw_name, false)
                 } else if self.check(&token::Colon) {
                     let kw = "struct";
                     (kw, kw, false)
                 } else {
-                    ("fn` or `struct", "method or struct", true)
+                    ("fn` or `struct", "function or struct", true)
                 };
+                self.consume_block(token::Brace);
 
                 let msg = format!("missing `{}` for {} definition", kw, kw_name);
                 let mut err = self.diagnostic().struct_span_err(sp, &msg);
@@ -7447,6 +7449,32 @@ 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.eat(&token::OpenDelim(token::Paren)) {
+                    if let Ok(Some(_)) = self.parse_self_arg() {
+                        ("fn", "method", false)
+                    } else {
+                        ("fn", "function", false)
+                    }
+                } else if self.check(&token::OpenDelim(token::Brace)) {
+                    ("struct", "struct", false)
+                } else {
+                    ("fn` or `struct", "function 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/imports/issue-56125.rs b/src/test/ui/imports/issue-56125.rs
index 843b52f1843..0327522e4b8 100644
--- a/src/test/ui/imports/issue-56125.rs
+++ b/src/test/ui/imports/issue-56125.rs
@@ -7,13 +7,11 @@
 mod m1 {
     use issue_56125::last_segment::*;
     //~^ ERROR `issue_56125` is ambiguous
-    //~| ERROR unresolved import `issue_56125::last_segment`
 }
 
 mod m2 {
     use issue_56125::non_last_segment::non_last_segment::*;
     //~^ ERROR `issue_56125` is ambiguous
-    //~| ERROR failed to resolve: could not find `non_last_segment` in `issue_56125`
 }
 
 mod m3 {
diff --git a/src/test/ui/imports/issue-56125.stderr b/src/test/ui/imports/issue-56125.stderr
index b1292ef8f78..559979e5d51 100644
--- a/src/test/ui/imports/issue-56125.stderr
+++ b/src/test/ui/imports/issue-56125.stderr
@@ -1,17 +1,5 @@
-error[E0433]: failed to resolve: could not find `non_last_segment` in `issue_56125`
-  --> $DIR/issue-56125.rs:14:22
-   |
-LL |     use issue_56125::non_last_segment::non_last_segment::*;
-   |                      ^^^^^^^^^^^^^^^^ could not find `non_last_segment` in `issue_56125`
-
-error[E0432]: unresolved import `issue_56125::last_segment`
-  --> $DIR/issue-56125.rs:8:22
-   |
-LL |     use issue_56125::last_segment::*;
-   |                      ^^^^^^^^^^^^ could not find `last_segment` in `issue_56125`
-
 error[E0432]: unresolved import `empty::issue_56125`
-  --> $DIR/issue-56125.rs:21:9
+  --> $DIR/issue-56125.rs:19:9
    |
 LL |     use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125`
    |         ^^^^^^^^^^^^^^^^^^ no `issue_56125` in `m3::empty`
@@ -32,7 +20,7 @@ LL |     use issue_56125::last_segment::*;
    = help: use `self::issue_56125` to refer to this module unambiguously
 
 error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution)
-  --> $DIR/issue-56125.rs:14:9
+  --> $DIR/issue-56125.rs:13:9
    |
 LL |     use issue_56125::non_last_segment::non_last_segment::*;
    |         ^^^^^^^^^^^ ambiguous name
@@ -40,14 +28,14 @@ LL |     use issue_56125::non_last_segment::non_last_segment::*;
    = note: `issue_56125` could refer to an extern crate passed with `--extern`
    = help: use `::issue_56125` to refer to this extern crate unambiguously
 note: `issue_56125` could also refer to the module imported here
-  --> $DIR/issue-56125.rs:14:9
+  --> $DIR/issue-56125.rs:13:9
    |
 LL |     use issue_56125::non_last_segment::non_last_segment::*;
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = help: use `self::issue_56125` to refer to this module unambiguously
 
 error[E0659]: `issue_56125` is ambiguous (name vs any other name during import resolution)
-  --> $DIR/issue-56125.rs:22:9
+  --> $DIR/issue-56125.rs:20:9
    |
 LL |     use issue_56125::*; //~ ERROR `issue_56125` is ambiguous
    |         ^^^^^^^^^^^ ambiguous name
@@ -55,13 +43,13 @@ LL |     use issue_56125::*; //~ ERROR `issue_56125` is ambiguous
    = note: `issue_56125` could refer to an extern crate passed with `--extern`
    = help: use `::issue_56125` to refer to this extern crate unambiguously
 note: `issue_56125` could also refer to the unresolved item imported here
-  --> $DIR/issue-56125.rs:21:9
+  --> $DIR/issue-56125.rs:19:9
    |
 LL |     use empty::issue_56125; //~ ERROR unresolved import `empty::issue_56125`
    |         ^^^^^^^^^^^^^^^^^^
    = help: use `self::issue_56125` to refer to this unresolved item unambiguously
 
-error: aborting due to 6 previous errors
+error: aborting due to 4 previous errors
 
-Some errors occurred: E0432, E0433, E0659.
+Some errors occurred: E0432, E0659.
 For more information about an error, try `rustc --explain E0432`.
diff --git a/src/test/ui/pub/pub-ident-fn-2.rs b/src/test/ui/pub/pub-ident-fn-2.rs
index 44884bfcdfd..648b1067add 100644
--- a/src/test/ui/pub/pub-ident-fn-2.rs
+++ b/src/test/ui/pub/pub-ident-fn-2.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 pub foo(s: usize) { bar() }
-//~^ ERROR missing `fn` for method definition
+//~^ ERROR missing `fn` for function definition
 
 fn main() {
     foo(2);
diff --git a/src/test/ui/pub/pub-ident-fn-2.stderr b/src/test/ui/pub/pub-ident-fn-2.stderr
index bbbb3df8769..ed7430fd394 100644
--- a/src/test/ui/pub/pub-ident-fn-2.stderr
+++ b/src/test/ui/pub/pub-ident-fn-2.stderr
@@ -1,9 +1,9 @@
-error: missing `fn` for method definition
+error: missing `fn` for function definition
   --> $DIR/pub-ident-fn-2.rs:11:4
    |
 LL | pub foo(s: usize) { bar() }
    |    ^
-help: add `fn` here to parse `foo` as a public method
+help: add `fn` here to parse `foo` as a public function
    |
 LL | pub fn foo(s: usize) { bar() }
    |     ^^
diff --git a/src/test/ui/pub/pub-ident-fn-or-struct-2.rs b/src/test/ui/pub/pub-ident-fn-or-struct-2.rs
index 1ccadc8a40b..e528e86fbc6 100644
--- a/src/test/ui/pub/pub-ident-fn-or-struct-2.rs
+++ b/src/test/ui/pub/pub-ident-fn-or-struct-2.rs
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 pub S();
-//~^ ERROR missing `fn` or `struct` for method or struct definition
+//~^ ERROR missing `fn` or `struct` for function or struct definition
 
 fn main() {}
diff --git a/src/test/ui/pub/pub-ident-fn-or-struct-2.stderr b/src/test/ui/pub/pub-ident-fn-or-struct-2.stderr
index e492a8c4756..d423b838f05 100644
--- a/src/test/ui/pub/pub-ident-fn-or-struct-2.stderr
+++ b/src/test/ui/pub/pub-ident-fn-or-struct-2.stderr
@@ -1,4 +1,4 @@
-error: missing `fn` or `struct` for method or struct definition
+error: missing `fn` or `struct` for function or struct definition
   --> $DIR/pub-ident-fn-or-struct-2.rs:11:4
    |
 LL | pub S();
diff --git a/src/test/ui/pub/pub-ident-fn-or-struct.rs b/src/test/ui/pub/pub-ident-fn-or-struct.rs
index 0664918945b..d5254bf2066 100644
--- a/src/test/ui/pub/pub-ident-fn-or-struct.rs
+++ b/src/test/ui/pub/pub-ident-fn-or-struct.rs
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 pub S (foo) bar
-//~^ ERROR missing `fn` or `struct` for method or struct definition
+//~^ ERROR missing `fn` or `struct` for function or struct definition
 
 fn main() {}
diff --git a/src/test/ui/pub/pub-ident-fn-or-struct.stderr b/src/test/ui/pub/pub-ident-fn-or-struct.stderr
index c1bff34cec3..b8b5e8a4bbf 100644
--- a/src/test/ui/pub/pub-ident-fn-or-struct.stderr
+++ b/src/test/ui/pub/pub-ident-fn-or-struct.stderr
@@ -1,4 +1,4 @@
-error: missing `fn` or `struct` for method or struct definition
+error: missing `fn` or `struct` for function or struct definition
   --> $DIR/pub-ident-fn-or-struct.rs:11:4
    |
 LL | pub S (foo) bar
diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime-2.rs b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.rs
new file mode 100644
index 00000000000..1ee8c84f13b
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.rs
@@ -0,0 +1,6 @@
+pub   bar<'a>(&self, _s: &'a usize) -> bool { true }
+//~^ ERROR missing `fn` for method definition
+
+fn main() {
+    bar(2);
+}
diff --git a/src/test/ui/pub/pub-ident-fn-with-lifetime-2.stderr b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.stderr
new file mode 100644
index 00000000000..c403774df8e
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-with-lifetime-2.stderr
@@ -0,0 +1,12 @@
+error: missing `fn` for method definition
+  --> $DIR/pub-ident-fn-with-lifetime-2.rs:1:4
+   |
+LL | pub   bar<'a>(&self, _s: &'a usize) -> bool { true }
+   |    ^^^
+help: add `fn` here to parse `bar` as a public method
+   |
+LL | pub fn bar<'a>(&self, _s: &'a usize) -> bool { true }
+   |     ^^
+
+error: aborting due to previous error
+
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..84f7bdc1fb1
--- /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 function 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..85823809640
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-fn-with-lifetime.stderr
@@ -0,0 +1,12 @@
+error: missing `fn` for function 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 function
+   |
+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-fn.fixed b/src/test/ui/pub/pub-ident-fn.fixed
index f2d0c6c3e1d..667e02114a1 100644
--- a/src/test/ui/pub/pub-ident-fn.fixed
+++ b/src/test/ui/pub/pub-ident-fn.fixed
@@ -11,7 +11,7 @@
 // run-rustfix
 
 pub fn foo(_s: usize) -> bool { true }
-//~^ ERROR missing `fn` for method definition
+//~^ ERROR missing `fn` for function definition
 
 fn main() {
     foo(2);
diff --git a/src/test/ui/pub/pub-ident-fn.rs b/src/test/ui/pub/pub-ident-fn.rs
index 82c32f57eea..91bbf58fe77 100644
--- a/src/test/ui/pub/pub-ident-fn.rs
+++ b/src/test/ui/pub/pub-ident-fn.rs
@@ -11,7 +11,7 @@
 // run-rustfix
 
 pub   foo(_s: usize) -> bool { true }
-//~^ ERROR missing `fn` for method definition
+//~^ ERROR missing `fn` for function definition
 
 fn main() {
     foo(2);
diff --git a/src/test/ui/pub/pub-ident-fn.stderr b/src/test/ui/pub/pub-ident-fn.stderr
index f7c96b8b9f4..1df6dd85ffe 100644
--- a/src/test/ui/pub/pub-ident-fn.stderr
+++ b/src/test/ui/pub/pub-ident-fn.stderr
@@ -1,9 +1,9 @@
-error: missing `fn` for method definition
+error: missing `fn` for function definition
   --> $DIR/pub-ident-fn.rs:13:4
    |
 LL | pub   foo(_s: usize) -> bool { true }
    |    ^^^
-help: add `fn` here to parse `foo` as a public method
+help: add `fn` here to parse `foo` as a public function
    |
 LL | pub fn foo(_s: usize) -> bool { true }
    |     ^^
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..c86a9f2fdd6
--- /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 function 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..0e0b127054d
--- /dev/null
+++ b/src/test/ui/pub/pub-ident-with-lifetime-incomplete.stderr
@@ -0,0 +1,8 @@
+error: missing `fn` or `struct` for function or struct definition
+  --> $DIR/pub-ident-with-lifetime-incomplete.rs:4:4
+   |
+LL | pub   foo<'a>
+   |    ^^^
+
+error: aborting due to previous error
+