diff --git a/.travis.yml b/.travis.yml
index 148b59e8c64eb..83e837e2d7690 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -133,13 +133,14 @@ before_script:
 script:
   - >
       if [ "$ALLOW_PR" = "" ] && [ "$TRAVIS_BRANCH" != "auto" ]; then
-          echo skipping, not a full build;
-      elif [ "$TRAVIS_OS_NAME" = "osx" ]; then
-          travis_retry stamp sh -c 'git submodule deinit -f . && git submodule update --init' &&
-          stamp src/ci/run.sh;
+          echo skipping, not a full build
       else
-          travis_retry stamp sh -c 'git submodule deinit -f . && git submodule update --init' &&
-          stamp src/ci/docker/run.sh $IMAGE;
+          stamp src/ci/init_repo.sh . "$HOME/rustsrc" &&
+          if [ "$TRAVIS_OS_NAME" = "osx" ]; then
+              stamp src/ci/run.sh;
+          else
+              stamp src/ci/docker/run.sh $IMAGE;
+          fi
       fi
 
 after_success:
@@ -169,13 +170,21 @@ after_failure:
   - dmesg | grep -i kill
 
 # Save tagged docker images we created and load them if they're available
+# Travis saves caches whether the build failed or not, nuke rustsrc if
+# the failure was while updating it (as it may be in an bad state)
+# https://github.com/travis-ci/travis-ci/issues/4472
 before_cache:
   - docker history -q rust-ci |
     grep -v missing |
     xargs docker save |
     gzip > $HOME/docker/rust-ci.tar.gz
+  - if [ ! -f $HOME/rustsrc/cache_valid1 ]; then
+        echo "WARNING rustsrc cache was invalid when saving";
+        rm -rf $HOME/rustsrc && mkdir $HOME/rustsrc;
+    fi
 before_install:
   - zcat $HOME/docker/rust-ci.tar.gz | docker load || true
+  - mkdir -p $HOME/rustsrc
 
 notifications:
   email: false
@@ -183,6 +192,7 @@ notifications:
 cache:
   directories:
     - $HOME/docker
+    - $HOME/rustsrc
 
 before_deploy:
   - mkdir -p deploy/$TRAVIS_COMMIT
diff --git a/appveyor.yml b/appveyor.yml
index 68b2a239aff1b..fa599a00c4de3 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -141,7 +141,8 @@ install:
   - set SCCACHE_ERROR_LOG=%CD%/sccache.log
 
 test_script:
-  - appveyor-retry sh -c 'git submodule deinit -f . && git submodule update --init'
+  - mkdir C:\cache\rustsrc
+  - sh src/ci/init_repo.sh . /c/cache/rustsrc
   - set SRC=.
   - set NO_CCACHE=1
   - sh src/ci/run.sh
@@ -150,6 +151,7 @@ on_failure:
   - cat %CD%/sccache.log
 
 cache:
+  - C:\cache\rustsrc
   - "build/i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
   - "build/x86_64-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
   - "i686-pc-windows-msvc/llvm -> src/rustllvm/llvm-rebuild-trigger"
diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh
index c418d427b15b3..71a4bfae3caf9 100755
--- a/src/ci/docker/run.sh
+++ b/src/ci/docker/run.sh
@@ -57,6 +57,7 @@ exec docker \
   --env DEPLOY_ALT=$DEPLOY_ALT \
   --env LOCAL_USER_ID=`id -u` \
   --volume "$HOME/.cargo:/cargo" \
+  --volume "$HOME/rustsrc:$HOME/rustsrc" \
   --privileged \
   --rm \
   rust-ci \
diff --git a/src/ci/init_repo.sh b/src/ci/init_repo.sh
new file mode 100755
index 0000000000000..4e22907d9794c
--- /dev/null
+++ b/src/ci/init_repo.sh
@@ -0,0 +1,71 @@
+#!/bin/bash
+# Copyright 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 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+set -o errexit
+set -o pipefail
+set -o nounset
+
+set -o xtrace
+
+ci_dir=$(cd $(dirname $0) && pwd)
+. "$ci_dir/shared.sh"
+
+REPO_DIR="$1"
+CACHE_DIR="$2"
+
+cache_src_dir="$CACHE_DIR/src"
+# If the layout of the cache directory changes, bump the number here
+# (and anywhere else this file is referenced) so the cache is wiped
+cache_valid_file="$CACHE_DIR/cache_valid1"
+
+if [ ! -d "$REPO_DIR" -o ! -d "$REPO_DIR/.git" ]; then
+    echo "Error: $REPO_DIR does not exist or is not a git repo"
+    exit 1
+fi
+cd $REPO_DIR
+if [ ! -d "$CACHE_DIR" ]; then
+    echo "Error: $CACHE_DIR does not exist or is not an absolute path"
+    exit 1
+fi
+
+# Wipe the cache if it's not valid, or mark it as invalid while we update it
+if [ ! -f "$cache_valid_file" ]; then
+    rm -rf "$CACHE_DIR" && mkdir "$CACHE_DIR"
+else
+    rm "$cache_valid_file"
+fi
+
+# Update the cache (a pristine copy of the rust source master)
+if [ ! -d "$cache_src_dir/.git" ]; then
+    retry sh -c "rm -rf $cache_src_dir && mkdir -p $cache_src_dir && \
+        git clone https://github.com/rust-lang/rust.git $cache_src_dir"
+fi
+retry sh -c "cd $cache_src_dir && git reset --hard && git pull"
+retry sh -c "cd $cache_src_dir && \
+    git submodule deinit -f . && git submodule sync && git submodule update --init"
+
+# Cache was updated without errors, mark it as valid
+touch "$cache_valid_file"
+
+# Update the submodules of the repo we're in, using the pristine repo as
+# a cache for any object files
+# No, `git submodule foreach` won't work:
+# http://stackoverflow.com/questions/12641469/list-submodules-in-a-git-repository
+modules="$(git config --file .gitmodules --get-regexp '\.path$' | cut -d' ' -f2)"
+for module in $modules; do
+    if [ ! -d "$cache_src_dir/$module" ]; then
+        echo "WARNING: $module not found in pristine repo"
+        retry sh -c "git submodule deinit -f $module && git submodule update --init $module"
+        continue
+    fi
+    retry sh -c "git submodule deinit -f $module && \
+        git submodule update --init --reference $cache_src_dir/$module $module"
+done
diff --git a/src/ci/shared.sh b/src/ci/shared.sh
index ecd9b7e98a482..f2e13fc73ae47 100644
--- a/src/ci/shared.sh
+++ b/src/ci/shared.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/false
 # Copyright 2016 The Rust Project Developers. See the COPYRIGHT
 # file at the top-level directory of this distribution and at
 # http://rust-lang.org/COPYRIGHT.
@@ -9,13 +9,16 @@
 # option. This file may not be copied, modified, or distributed
 # except according to those terms.
 
+# This file is intended to be sourced with `. shared.sh` or
+# `source shared.sh`, hence the invalid shebang and not being
+# marked as an executable file in git.
+
 # See http://unix.stackexchange.com/questions/82598
 function retry {
+  echo "Attempting with retry:" "$@"
   local n=1
   local max=5
-  local delay=15
   while true; do
-    echo "Attempting:" "$@"
     "$@" && break || {
       if [[ $n -lt $max ]]; then
         ((n++))
diff --git a/src/doc/rust.md b/src/doc/rust.md
index 7f02260cd2cd4..5008b228c5c85 100644
--- a/src/doc/rust.md
+++ b/src/doc/rust.md
@@ -1,3 +1,3 @@
 % The Rust Reference Manual
 
-The manual has moved, and is now called [the reference](reference.html).
+The manual has moved, and is now called [the reference](reference/index.html).
diff --git a/src/libcore/slice/sort.rs b/src/libcore/slice/sort.rs
index 3612ee65bca0d..7065fdb79fc40 100644
--- a/src/libcore/slice/sort.rs
+++ b/src/libcore/slice/sort.rs
@@ -527,7 +527,9 @@ fn break_patterns<T>(v: &mut [T]) {
             // we first take it modulo a power of two, and then decrease by `len` until it fits
             // into the range `[0, len - 1]`.
             let mut other = gen_usize() & (modulus - 1);
-            while other >= len {
+
+            // `other` is guaranteed to be less than `2 * len`.
+            if other >= len {
                 other -= len;
             }
 
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 0d66d0e93aa85..857eeb26af078 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -327,7 +327,9 @@ unsafe fn from_raw_parts_mut<'a>(p: *mut u8, len: usize) -> &'a mut str {
 ///
 /// This function is unsafe because it does not check that the bytes passed to
 /// it are valid UTF-8. If this constraint is violated, undefined behavior
-/// results, as the rest of Rust assumes that `&str`s are valid UTF-8.
+/// results, as the rest of Rust assumes that [`&str`]s are valid UTF-8.
+///
+/// [`&str`]: ../../std/primitive.str.html
 ///
 /// # Examples
 ///
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 6ce50d91124d4..67ee7ef586530 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -197,18 +197,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                     let field_ty = field.ty(tcx, substs);
 
                                     if self.is_fn_ty(&field_ty, span) {
-                                        err.span_note(span,
-                                                      &format!("use `({0}.{1})(...)` if you \
-                                                                meant to call the function \
-                                                                stored in the `{1}` field",
-                                                               expr_string,
-                                                               item_name));
+                                        err.help(&format!("use `({0}.{1})(...)` if you \
+                                                           meant to call the function \
+                                                           stored in the `{1}` field",
+                                                          expr_string,
+                                                          item_name));
                                     } else {
-                                        err.span_note(span,
-                                                      &format!("did you mean to write `{0}.{1}`?",
-                                                               expr_string,
-                                                               item_name));
+                                        err.help(&format!("did you mean to write `{0}.{1}` \
+                                                           instead of `{0}.{1}(...)`?",
+                                                          expr_string,
+                                                          item_name));
                                     }
+                                    err.span_label(span, &"field, not a method");
                                     break;
                                 }
                             }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 2793307697852..c89ec5bbe15bd 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -21,7 +21,7 @@ use syntax_pos::Span;
 
 use rustc::hir::map as hir_map;
 use rustc::hir::def::Def;
-use rustc::hir::def_id::LOCAL_CRATE;
+use rustc::hir::def_id::{DefId, LOCAL_CRATE};
 use rustc::middle::cstore::LoadedMacro;
 use rustc::middle::privacy::AccessLevel;
 use rustc::util::nodemap::FxHashSet;
@@ -48,6 +48,7 @@ pub struct RustdocVisitor<'a, 'tcx: 'a> {
     inlining: bool,
     /// Is the current module and all of its parents public?
     inside_public_path: bool,
+    reexported_macros: FxHashSet<DefId>,
 }
 
 impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
@@ -62,6 +63,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             view_item_stack: stack,
             inlining: false,
             inside_public_path: true,
+            reexported_macros: FxHashSet(),
         }
     }
 
@@ -201,9 +203,10 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         if let Some(exports) = self.cx.tcx.export_map.get(&id) {
             for export in exports {
                 if let Def::Macro(def_id, ..) = export.def {
-                    if def_id.krate == LOCAL_CRATE {
+                    if def_id.krate == LOCAL_CRATE || self.reexported_macros.contains(&def_id) {
                         continue // These are `krate.exported_macros`, handled in `self.visit()`.
                     }
+
                     let imported_from = self.cx.sess().cstore.original_crate_name(def_id.krate);
                     let def = match self.cx.sess().cstore.load_macro(def_id, self.cx.sess()) {
                         LoadedMacro::MacroDef(macro_def) => macro_def,
@@ -217,6 +220,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                     } else {
                         unreachable!()
                     };
+
                     om.macros.push(Macro {
                         def_id: def_id,
                         attrs: def.attrs.clone().into(),
@@ -263,6 +267,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             false
         }
 
+        debug!("maybe_inline_local def: {:?}", def);
+
         let tcx = self.cx.tcx;
         if def == Def::Err {
             return false;
@@ -274,6 +280,17 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
         let is_no_inline = use_attrs.lists("doc").has_word("no_inline") ||
                            use_attrs.lists("doc").has_word("hidden");
 
+        // Memoize the non-inlined `pub use`'d macros so we don't push an extra
+        // declaration in `visit_mod_contents()`
+        if !def_did.is_local() {
+            if let Def::Macro(did, _) = def {
+                if please_inline { return true }
+                debug!("memoizing non-inlined macro export: {:?}", def);
+                self.reexported_macros.insert(did);
+                return false;
+            }
+        }
+
         // For cross-crate impl inlining we need to know whether items are
         // reachable in documentation - a previously nonreachable item can be
         // made reachable by cross-crate inlining which we're checking here.
@@ -294,6 +311,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 },
                 _ => {},
             }
+
             return false
         }
 
diff --git a/src/test/rustdoc/auxiliary/pub-use-extern-macros.rs b/src/test/rustdoc/auxiliary/pub-use-extern-macros.rs
new file mode 100644
index 0000000000000..70d174a149daa
--- /dev/null
+++ b/src/test/rustdoc/auxiliary/pub-use-extern-macros.rs
@@ -0,0 +1,30 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![crate_name="macros"]
+
+#[macro_export]
+macro_rules! foo {
+    () => {};
+}
+
+#[macro_export]
+macro_rules! bar {
+    () => {};
+}
+
+#[macro_export]
+macro_rules! baz {
+    () => {};
+}
+
+#[macro_export]
+macro_rules! quux {
+    () => {};
+}
diff --git a/src/test/rustdoc/pub-use-extern-macros.rs b/src/test/rustdoc/pub-use-extern-macros.rs
new file mode 100644
index 0000000000000..3f8f6f9544e80
--- /dev/null
+++ b/src/test/rustdoc/pub-use-extern-macros.rs
@@ -0,0 +1,31 @@
+// 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 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:pub-use-extern-macros.rs
+
+#![feature(use_extern_macros, macro_reexport)]
+
+// @has pub_use_extern_macros/macro.foo.html
+// @!has pub_use_extern_macros/index.html 'pub use macros::foo;'
+#[macro_reexport(foo)] extern crate macros;
+
+// @has pub_use_extern_macros/index.html 'pub use macros::bar;'
+// @!has pub_use_extern_macros/macro.bar.html
+pub use macros::bar;
+
+// @has pub_use_extern_macros/macro.baz.html
+// @!has pub_use_extern_macros/index.html 'pub use macros::baz;'
+#[doc(inline)]
+pub use macros::baz;
+
+// @!has pub_use_extern_macros/macro.quux.html
+// @!has pub_use_extern_macros/index.html 'pub use macros::quux;'
+#[doc(hidden)]
+pub use macros::quux;
diff --git a/src/test/compile-fail/issue-18343.rs b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.rs
similarity index 79%
rename from src/test/compile-fail/issue-18343.rs
rename to src/test/ui/suggestions/confuse-field-and-method/issue-18343.rs
index 4601db9dba0fc..fc3c58e5223a3 100644
--- a/src/test/compile-fail/issue-18343.rs
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.rs
@@ -14,6 +14,8 @@ struct Obj<F> where F: FnMut() -> u32 {
 
 fn main() {
     let o = Obj { closure: || 42 };
-    o.closure(); //~ ERROR no method named `closure` found
-    //~^ NOTE use `(o.closure)(...)` if you meant to call the function stored in the `closure` field
+    o.closure();
+    //~^ ERROR no method named `closure` found
+    //~| HELP use `(o.closure)(...)` if you meant to call the function stored in the `closure` field
+    //~| NOTE field, not a method
 }
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr
new file mode 100644
index 0000000000000..9e5e4adb180d5
--- /dev/null
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-18343.stderr
@@ -0,0 +1,10 @@
+error: no method named `closure` found for type `Obj<[closure@$DIR/issue-18343.rs:16:28: 16:33]>` in the current scope
+  --> $DIR/issue-18343.rs:17:7
+   |
+17 |     o.closure();
+   |       ^^^^^^^ field, not a method
+   |
+   = help: use `(o.closure)(...)` if you meant to call the function stored in the `closure` field
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/issue-2392.rs b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.rs
similarity index 64%
rename from src/test/compile-fail/issue-2392.rs
rename to src/test/ui/suggestions/confuse-field-and-method/issue-2392.rs
index 805725dd749f5..f84f35ce84bf9 100644
--- a/src/test/compile-fail/issue-2392.rs
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.rs
@@ -48,45 +48,58 @@ fn main() {
 
     let o_closure = Obj { closure: || 42, not_closure: 42 };
     o_closure.closure(); //~ ERROR no method named `closure` found
-    //~^ NOTE use `(o_closure.closure)(...)` if you meant to call the function stored
+    //~^ HELP use `(o_closure.closure)(...)` if you meant to call the function stored
+    //~| NOTE field, not a method
 
-    o_closure.not_closure(); //~ ERROR no method named `not_closure` found
-    //~^ NOTE did you mean to write `o_closure.not_closure`?
+    o_closure.not_closure();
+    //~^ ERROR no method named `not_closure` found
+    //~| NOTE field, not a method
+    //~| HELP did you mean to write `o_closure.not_closure` instead of `o_closure.not_closure(...)`?
 
     let o_func = Obj { closure: func, not_closure: 5 };
     o_func.closure(); //~ ERROR no method named `closure` found
-    //~^ NOTE use `(o_func.closure)(...)` if you meant to call the function stored
+    //~^ HELP use `(o_func.closure)(...)` if you meant to call the function stored
+    //~| NOTE field, not a method
 
     let boxed_fn = BoxedObj { boxed_closure: Box::new(func) };
     boxed_fn.boxed_closure();//~ ERROR no method named `boxed_closure` found
-    //~^ NOTE use `(boxed_fn.boxed_closure)(...)` if you meant to call the function stored
+    //~^ HELP use `(boxed_fn.boxed_closure)(...)` if you meant to call the function stored
+    //~| NOTE field, not a method
 
     let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box<FnBox() -> u32> };
     boxed_closure.boxed_closure();//~ ERROR no method named `boxed_closure` found
-    //~^ NOTE use `(boxed_closure.boxed_closure)(...)` if you meant to call the function stored
+    //~^ HELP use `(boxed_closure.boxed_closure)(...)` if you meant to call the function stored
+    //~| NOTE field, not a method
 
     // test expression writing in the notes
 
     let w = Wrapper { wrap: o_func };
     w.wrap.closure();//~ ERROR no method named `closure` found
-    //~^ NOTE use `(w.wrap.closure)(...)` if you meant to call the function stored
+    //~^ HELP use `(w.wrap.closure)(...)` if you meant to call the function stored
+    //~| NOTE field, not a method
 
-    w.wrap.not_closure();//~ ERROR no method named `not_closure` found
-    //~^ NOTE did you mean to write `w.wrap.not_closure`?
+    w.wrap.not_closure();
+    //~^ ERROR no method named `not_closure` found
+    //~| NOTE field, not a method
+    //~| HELP did you mean to write `w.wrap.not_closure` instead of `w.wrap.not_closure(...)`?
 
     check_expression().closure();//~ ERROR no method named `closure` found
-    //~^ NOTE use `(check_expression().closure)(...)` if you meant to call the function stored
+    //~^ HELP use `(check_expression().closure)(...)` if you meant to call the function stored
+    //~| NOTE field, not a method
 }
 
 impl FuncContainerOuter {
     fn run(&self) {
         unsafe {
             (*self.container).f1(1); //~ ERROR no method named `f1` found
-            //~^ NOTE use `((*self.container).f1)(...)`
+            //~^ HELP use `((*self.container).f1)(...)`
+            //~| NOTE field, not a method
             (*self.container).f2(1); //~ ERROR no method named `f2` found
-            //~^ NOTE use `((*self.container).f2)(...)`
+            //~^ HELP use `((*self.container).f2)(...)`
+            //~| NOTE field, not a method
             (*self.container).f3(1); //~ ERROR no method named `f3` found
-            //~^ NOTE use `((*self.container).f3)(...)`
+            //~^ HELP use `((*self.container).f3)(...)`
+            //~| NOTE field, not a method
         }
     }
 }
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr
new file mode 100644
index 0000000000000..56e1060bdb95a
--- /dev/null
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-2392.stderr
@@ -0,0 +1,90 @@
+error: no method named `closure` found for type `Obj<[closure@$DIR/issue-2392.rs:49:36: 49:41]>` in the current scope
+  --> $DIR/issue-2392.rs:50:15
+   |
+50 |     o_closure.closure(); //~ ERROR no method named `closure` found
+   |               ^^^^^^^ field, not a method
+   |
+   = help: use `(o_closure.closure)(...)` if you meant to call the function stored in the `closure` field
+
+error: no method named `not_closure` found for type `Obj<[closure@$DIR/issue-2392.rs:49:36: 49:41]>` in the current scope
+  --> $DIR/issue-2392.rs:54:15
+   |
+54 |     o_closure.not_closure();
+   |               ^^^^^^^^^^^ field, not a method
+   |
+   = help: did you mean to write `o_closure.not_closure` instead of `o_closure.not_closure(...)`?
+
+error: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+  --> $DIR/issue-2392.rs:60:12
+   |
+60 |     o_func.closure(); //~ ERROR no method named `closure` found
+   |            ^^^^^^^ field, not a method
+   |
+   = help: use `(o_func.closure)(...)` if you meant to call the function stored in the `closure` field
+
+error: no method named `boxed_closure` found for type `BoxedObj` in the current scope
+  --> $DIR/issue-2392.rs:65:14
+   |
+65 |     boxed_fn.boxed_closure();//~ ERROR no method named `boxed_closure` found
+   |              ^^^^^^^^^^^^^ field, not a method
+   |
+   = help: use `(boxed_fn.boxed_closure)(...)` if you meant to call the function stored in the `boxed_closure` field
+
+error: no method named `boxed_closure` found for type `BoxedObj` in the current scope
+  --> $DIR/issue-2392.rs:70:19
+   |
+70 |     boxed_closure.boxed_closure();//~ ERROR no method named `boxed_closure` found
+   |                   ^^^^^^^^^^^^^ field, not a method
+   |
+   = help: use `(boxed_closure.boxed_closure)(...)` if you meant to call the function stored in the `boxed_closure` field
+
+error: no method named `closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+  --> $DIR/issue-2392.rs:77:12
+   |
+77 |     w.wrap.closure();//~ ERROR no method named `closure` found
+   |            ^^^^^^^ field, not a method
+   |
+   = help: use `(w.wrap.closure)(...)` if you meant to call the function stored in the `closure` field
+
+error: no method named `not_closure` found for type `Obj<fn() -> u32 {func}>` in the current scope
+  --> $DIR/issue-2392.rs:81:12
+   |
+81 |     w.wrap.not_closure();
+   |            ^^^^^^^^^^^ field, not a method
+   |
+   = help: did you mean to write `w.wrap.not_closure` instead of `w.wrap.not_closure(...)`?
+
+error: no method named `closure` found for type `Obj<std::boxed::Box<std::boxed::FnBox<(), Output=u32> + 'static>>` in the current scope
+  --> $DIR/issue-2392.rs:86:24
+   |
+86 |     check_expression().closure();//~ ERROR no method named `closure` found
+   |                        ^^^^^^^ field, not a method
+   |
+   = help: use `(check_expression().closure)(...)` if you meant to call the function stored in the `closure` field
+
+error: no method named `f1` found for type `FuncContainer` in the current scope
+  --> $DIR/issue-2392.rs:94:31
+   |
+94 |             (*self.container).f1(1); //~ ERROR no method named `f1` found
+   |                               ^^ field, not a method
+   |
+   = help: use `((*self.container).f1)(...)` if you meant to call the function stored in the `f1` field
+
+error: no method named `f2` found for type `FuncContainer` in the current scope
+  --> $DIR/issue-2392.rs:97:31
+   |
+97 |             (*self.container).f2(1); //~ ERROR no method named `f2` found
+   |                               ^^ field, not a method
+   |
+   = help: use `((*self.container).f2)(...)` if you meant to call the function stored in the `f2` field
+
+error: no method named `f3` found for type `FuncContainer` in the current scope
+   --> $DIR/issue-2392.rs:100:31
+    |
+100 |             (*self.container).f3(1); //~ ERROR no method named `f3` found
+    |                               ^^ field, not a method
+    |
+    = help: use `((*self.container).f3)(...)` if you meant to call the function stored in the `f3` field
+
+error: aborting due to 11 previous errors
+
diff --git a/src/test/compile-fail/issue-32128.rs b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.rs
similarity index 82%
rename from src/test/compile-fail/issue-32128.rs
rename to src/test/ui/suggestions/confuse-field-and-method/issue-32128.rs
index fe7e66a2116eb..2fd7dc246c206 100644
--- a/src/test/compile-fail/issue-32128.rs
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.rs
@@ -19,7 +19,9 @@ fn main() {
         })
     };
 
-    demo.example(1);    //~ ERROR no method named `example`
-                        //~^ NOTE use `(demo.example)(...)`
+    demo.example(1);
+    //~^ ERROR no method named `example`
+    //~| HELP use `(demo.example)(...)`
+    //~| NOTE field, not a method
     // (demo.example)(1);
 }
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr
new file mode 100644
index 0000000000000..0d2a895bad16d
--- /dev/null
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-32128.stderr
@@ -0,0 +1,10 @@
+error: no method named `example` found for type `Example` in the current scope
+  --> $DIR/issue-32128.rs:22:10
+   |
+22 |     demo.example(1);
+   |          ^^^^^^^ field, not a method
+   |
+   = help: use `(demo.example)(...)` if you meant to call the function stored in the `example` field
+
+error: aborting due to previous error
+
diff --git a/src/test/compile-fail/issue-33784.rs b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.rs
similarity index 74%
rename from src/test/compile-fail/issue-33784.rs
rename to src/test/ui/suggestions/confuse-field-and-method/issue-33784.rs
index 4229be29473db..03c84fc57befe 100644
--- a/src/test/compile-fail/issue-33784.rs
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.rs
@@ -35,12 +35,15 @@ fn main() {
     let o = Obj { fn_ptr: empty, closure: || 42 };
     let p = &o;
     p.closure(); //~ ERROR no method named `closure` found
-    //~^ NOTE use `(p.closure)(...)` if you meant to call the function stored in the `closure` field
+    //~^ HELP use `(p.closure)(...)` if you meant to call the function stored in the `closure` field
+    //~| NOTE `closure` is a field storing a function, not a method
     let q = &p;
     q.fn_ptr(); //~ ERROR no method named `fn_ptr` found
-    //~^ NOTE use `(q.fn_ptr)(...)` if you meant to call the function stored in the `fn_ptr` field
+    //~^ HELP use `(q.fn_ptr)(...)` if you meant to call the function stored in the `fn_ptr` field
+    //~| NOTE `fn_ptr` is a field storing a function, not a method
     let r = D(C { c_fn_ptr: empty });
     let s = &r;
     s.c_fn_ptr(); //~ ERROR no method named `c_fn_ptr` found
-    //~^ NOTE use `(s.c_fn_ptr)(...)` if you meant to call the function stored in the `c_fn_ptr`
+    //~^ HELP use `(s.c_fn_ptr)(...)` if you meant to call the function stored in the `c_fn_ptr`
+    //~| NOTE `c_fn_ptr` is a field storing a function, not a method
 }
diff --git a/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr
new file mode 100644
index 0000000000000..70d64e3ffa331
--- /dev/null
+++ b/src/test/ui/suggestions/confuse-field-and-method/issue-33784.stderr
@@ -0,0 +1,26 @@
+error: no method named `closure` found for type `&Obj<[closure@$DIR/issue-33784.rs:35:43: 35:48]>` in the current scope
+  --> $DIR/issue-33784.rs:37:7
+   |
+37 |     p.closure(); //~ ERROR no method named `closure` found
+   |       ^^^^^^^ field, not a method
+   |
+   = help: use `(p.closure)(...)` if you meant to call the function stored in the `closure` field
+
+error: no method named `fn_ptr` found for type `&&Obj<[closure@$DIR/issue-33784.rs:35:43: 35:48]>` in the current scope
+  --> $DIR/issue-33784.rs:41:7
+   |
+41 |     q.fn_ptr(); //~ ERROR no method named `fn_ptr` found
+   |       ^^^^^^ field, not a method
+   |
+   = help: use `(q.fn_ptr)(...)` if you meant to call the function stored in the `fn_ptr` field
+
+error: no method named `c_fn_ptr` found for type `&D` in the current scope
+  --> $DIR/issue-33784.rs:46:7
+   |
+46 |     s.c_fn_ptr(); //~ ERROR no method named `c_fn_ptr` found
+   |       ^^^^^^^^ field, not a method
+   |
+   = help: use `(s.c_fn_ptr)(...)` if you meant to call the function stored in the `c_fn_ptr` field
+
+error: aborting due to 3 previous errors
+