about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-09-04 02:59:45 +0000
committerbors <bors@rust-lang.org>2022-09-04 02:59:45 +0000
commit5fecdb7c0ab4fb26f37df7c5e6afb4981e0fc71b (patch)
treeb25dc752c766fdd89b5f95c7c559053d157fa849
parent84f0c3f79a85329dd79a54694ff8a7f427c842e9 (diff)
parenta3dda514389a688ac04de3bd4535fe1362983706 (diff)
downloadrust-5fecdb7c0ab4fb26f37df7c5e6afb4981e0fc71b.tar.gz
rust-5fecdb7c0ab4fb26f37df7c5e6afb4981e0fc71b.zip
Auto merge of #101396 - matthiaskrgr:rollup-9n0257m, r=matthiaskrgr
Rollup of 4 pull requests

Successful merges:

 - #100302 (Suggest associated method on deref types when path syntax method fails)
 - #100647 ( Make trait bound not satisfied specify kind)
 - #101349 (rustdoc: remove `.impl-items { flex-basis }` CSS, not in flex container)
 - #101369 (Fix `global_asm` macro pretty printing)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs37
-rw-r--r--compiler/rustc_typeck/src/check/method/suggest.rs62
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css4
-rw-r--r--src/test/ui/asm/unpretty-expanded.rs3
-rw-r--r--src/test/ui/asm/unpretty-expanded.stdout9
-rw-r--r--src/test/ui/async-await/issues/issue-62009-1.stderr2
-rw-r--r--src/test/ui/binop/issue-77910-1.stderr2
-rw-r--r--src/test/ui/closures/coerce-unsafe-to-closure.stderr2
-rw-r--r--src/test/ui/extern/extern-wrong-value-type.stderr2
-rw-r--r--src/test/ui/intrinsics/const-eval-select-bad.stderr2
-rw-r--r--src/test/ui/issues/issue-59488.stderr4
-rw-r--r--src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr2
-rw-r--r--src/test/ui/issues/issue-99875.rs16
-rw-r--r--src/test/ui/issues/issue-99875.stderr33
-rw-r--r--src/test/ui/namespace/namespace-mix.stderr8
-rw-r--r--src/test/ui/proc-macro/signature.stderr2
-rw-r--r--src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr12
-rw-r--r--src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr4
-rw-r--r--src/test/ui/suggestions/deref-path-method.rs6
-rw-r--r--src/test/ui/suggestions/deref-path-method.stderr14
-rw-r--r--src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr6
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr6
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr6
25 files changed, 205 insertions, 45 deletions
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index bd87987010e..54bac29a6ce 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -218,6 +218,8 @@ impl<'a> State<'a> {
             ast::ItemKind::GlobalAsm(ref asm) => {
                 self.head(visibility_qualified(&item.vis, "global_asm!"));
                 self.print_inline_asm(asm);
+                self.word(";");
+                self.end();
                 self.end();
             }
             ast::ItemKind::TyAlias(box ast::TyAlias {
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 99046bd126f..8151d2b365d 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -450,12 +450,27 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         {
                             "consider using `()`, or a `Result`".to_owned()
                         } else {
-                            format!(
-                                "{}the trait `{}` is not implemented for `{}`",
-                                pre_message,
-                                trait_predicate.print_modifiers_and_trait_path(),
-                                trait_ref.skip_binder().self_ty(),
-                            )
+                            let ty_desc = match trait_ref.skip_binder().self_ty().kind() {
+                                ty::FnDef(_, _) => Some("fn item"),
+                                ty::Closure(_, _) => Some("closure"),
+                                _ => None,
+                            };
+
+                            match ty_desc {
+                                Some(desc) => format!(
+                                    "{}the trait `{}` is not implemented for {} `{}`",
+                                    pre_message,
+                                    trait_predicate.print_modifiers_and_trait_path(),
+                                    desc,
+                                    trait_ref.skip_binder().self_ty(),
+                                ),
+                                None => format!(
+                                    "{}the trait `{}` is not implemented for `{}`",
+                                    pre_message,
+                                    trait_predicate.print_modifiers_and_trait_path(),
+                                    trait_ref.skip_binder().self_ty(),
+                                ),
+                            }
                         };
 
                         if self.suggest_add_reference_to_arg(
@@ -1805,13 +1820,21 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                 return false;
             }
             if candidates.len() == 1 {
+                let ty_desc = match candidates[0].self_ty().kind() {
+                    ty::FnPtr(_) => Some("fn pointer"),
+                    _ => None,
+                };
+                let the_desc = match ty_desc {
+                    Some(desc) => format!(" implemented for {} `", desc),
+                    None => " implemented for `".to_string(),
+                };
                 err.highlighted_help(vec![
                     (
                         format!("the trait `{}` ", candidates[0].print_only_trait_path()),
                         Style::NoStyle,
                     ),
                     ("is".to_string(), Style::Highlight),
-                    (" implemented for `".to_string(), Style::NoStyle),
+                    (the_desc, Style::NoStyle),
                     (candidates[0].self_ty().to_string(), Style::Highlight),
                     ("`".to_string(), Style::NoStyle),
                 ]);
diff --git a/compiler/rustc_typeck/src/check/method/suggest.rs b/compiler/rustc_typeck/src/check/method/suggest.rs
index e99782fdc65..998405bcbe1 100644
--- a/compiler/rustc_typeck/src/check/method/suggest.rs
+++ b/compiler/rustc_typeck/src/check/method/suggest.rs
@@ -16,8 +16,8 @@ use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKi
 use rustc_middle::traits::util::supertraits;
 use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
 use rustc_middle::ty::print::with_crate_prefix;
-use rustc_middle::ty::ToPolyTraitRef;
 use rustc_middle::ty::{self, DefIdTree, ToPredicate, Ty, TyCtxt, TypeVisitable};
+use rustc_middle::ty::{IsSuggestable, ToPolyTraitRef};
 use rustc_span::symbol::{kw, sym, Ident};
 use rustc_span::Symbol;
 use rustc_span::{lev_distance, source_map, ExpnKind, FileName, MacroKind, Span};
@@ -30,7 +30,7 @@ use rustc_trait_selection::traits::{
 use std::cmp::Ordering;
 use std::iter;
 
-use super::probe::{Mode, ProbeScope};
+use super::probe::{IsSuggestion, Mode, ProbeScope};
 use super::{CandidateSource, MethodError, NoMatchData};
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -1069,6 +1069,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                 }
 
+                self.check_for_deref_method(&mut err, source, rcvr_ty, item_name);
+
                 return Some(err);
             }
 
@@ -1651,6 +1653,62 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
+    fn check_for_deref_method(
+        &self,
+        err: &mut Diagnostic,
+        self_source: SelfSource<'tcx>,
+        rcvr_ty: Ty<'tcx>,
+        item_name: Ident,
+    ) {
+        let SelfSource::QPath(ty) = self_source else { return; };
+        for (deref_ty, _) in self.autoderef(rustc_span::DUMMY_SP, rcvr_ty).skip(1) {
+            if let Ok(pick) = self.probe_for_name(
+                ty.span,
+                Mode::Path,
+                item_name,
+                IsSuggestion(true),
+                deref_ty,
+                ty.hir_id,
+                ProbeScope::TraitsInScope,
+            ) {
+                if deref_ty.is_suggestable(self.tcx, true)
+                    // If this method receives `&self`, then the provided
+                    // argument _should_ coerce, so it's valid to suggest
+                    // just changing the path.
+                    && pick.item.fn_has_self_parameter
+                    && let Some(self_ty) =
+                        self.tcx.fn_sig(pick.item.def_id).inputs().skip_binder().get(0)
+                    && self_ty.is_ref()
+                {
+                    let suggested_path = match deref_ty.kind() {
+                        ty::Bool
+                        | ty::Char
+                        | ty::Int(_)
+                        | ty::Uint(_)
+                        | ty::Float(_)
+                        | ty::Adt(_, _)
+                        | ty::Str
+                        | ty::Projection(_)
+                        | ty::Param(_) => format!("{deref_ty}"),
+                        _ => format!("<{deref_ty}>"),
+                    };
+                    err.span_suggestion_verbose(
+                        ty.span,
+                        format!("the function `{item_name}` is implemented on `{deref_ty}`"),
+                        suggested_path,
+                        Applicability::MaybeIncorrect,
+                    );
+                } else {
+                    err.span_note(
+                        ty.span,
+                        format!("the function `{item_name}` is implemented on `{deref_ty}`"),
+                    );
+                }
+                return;
+            }
+        }
+    }
+
     /// Print out the type for use in value namespace.
     fn ty_to_value_string(&self, ty: Ty<'tcx>) -> String {
         match ty.kind() {
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 38b6ebd66d3..fddff771f1c 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -778,10 +778,6 @@ pre, .rustdoc.source .example-wrap {
 	margin-bottom: .6em;
 }
 
-.impl-items {
-	flex-basis: 100%;
-}
-
 #main-content > .item-info {
 	margin-top: 0;
 	margin-left: 0;
diff --git a/src/test/ui/asm/unpretty-expanded.rs b/src/test/ui/asm/unpretty-expanded.rs
new file mode 100644
index 00000000000..6128f49b89a
--- /dev/null
+++ b/src/test/ui/asm/unpretty-expanded.rs
@@ -0,0 +1,3 @@
+// check-pass
+// compile-flags: -Zunpretty=expanded
+core::arch::global_asm!("x: .byte 42");
diff --git a/src/test/ui/asm/unpretty-expanded.stdout b/src/test/ui/asm/unpretty-expanded.stdout
new file mode 100644
index 00000000000..15b60d1559c
--- /dev/null
+++ b/src/test/ui/asm/unpretty-expanded.stdout
@@ -0,0 +1,9 @@
+#![feature(prelude_import)]
+#![no_std]
+#[prelude_import]
+use ::std::prelude::rust_2015::*;
+#[macro_use]
+extern crate std;
+// check-pass
+// compile-flags: -Zunpretty=expanded
+global_asm! ("x: .byte 42");
diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr
index fb9dee11f2a..0e323443ae8 100644
--- a/src/test/ui/async-await/issues/issue-62009-1.stderr
+++ b/src/test/ui/async-await/issues/issue-62009-1.stderr
@@ -30,7 +30,7 @@ error[E0277]: `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future
 LL |     (|_| 2333).await;
    |               ^^^^^^ `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` is not a future
    |
-   = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]`
+   = help: the trait `Future` is not implemented for closure `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]`
    = note: [closure@$DIR/issue-62009-1.rs:12:6: 12:9] must be a future or must implement `IntoFuture` to be awaited
    = note: required for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` to implement `IntoFuture`
 help: remove the `.await`
diff --git a/src/test/ui/binop/issue-77910-1.stderr b/src/test/ui/binop/issue-77910-1.stderr
index 68303b84208..097a14f26f8 100644
--- a/src/test/ui/binop/issue-77910-1.stderr
+++ b/src/test/ui/binop/issue-77910-1.stderr
@@ -18,7 +18,7 @@ LL | fn foo(s: &i32) -> &i32 {
 LL |     assert_eq!(foo, y);
    |     ^^^^^^^^^^^^^^^^^^ `for<'r> fn(&'r i32) -> &'r i32 {foo}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = help: the trait `Debug` is not implemented for `for<'r> fn(&'r i32) -> &'r i32 {foo}`
+   = help: the trait `Debug` is not implemented for fn item `for<'r> fn(&'r i32) -> &'r i32 {foo}`
    = help: use parentheses to call the function: `foo(s)`
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/closures/coerce-unsafe-to-closure.stderr b/src/test/ui/closures/coerce-unsafe-to-closure.stderr
index bd095c2d83d..6ce63e829b3 100644
--- a/src/test/ui/closures/coerce-unsafe-to-closure.stderr
+++ b/src/test/ui/closures/coerce-unsafe-to-closure.stderr
@@ -6,7 +6,7 @@ LL |     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
    |                                        |
    |                                        required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<(&str,)>` is not implemented for `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
+   = help: the trait `FnOnce<(&str,)>` is not implemented for fn item `unsafe extern "rust-intrinsic" fn(_) -> _ {transmute::<_, _>}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `Option::<T>::map`
   --> $SRC_DIR/core/src/option.rs:LL:COL
diff --git a/src/test/ui/extern/extern-wrong-value-type.stderr b/src/test/ui/extern/extern-wrong-value-type.stderr
index c6f0d5df9b5..ff2934a2ba8 100644
--- a/src/test/ui/extern/extern-wrong-value-type.stderr
+++ b/src/test/ui/extern/extern-wrong-value-type.stderr
@@ -6,7 +6,7 @@ LL |     is_fn(f);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for `extern "C" fn() {f}`
+   = help: the trait `Fn<()>` is not implemented for fn item `extern "C" fn() {f}`
    = note: wrap the `extern "C" fn() {f}` in a closure with no arguments: `|| { /* code */ }`
 note: required by a bound in `is_fn`
   --> $DIR/extern-wrong-value-type.rs:4:28
diff --git a/src/test/ui/intrinsics/const-eval-select-bad.stderr b/src/test/ui/intrinsics/const-eval-select-bad.stderr
index 1a761ad5441..904e83624b3 100644
--- a/src/test/ui/intrinsics/const-eval-select-bad.stderr
+++ b/src/test/ui/intrinsics/const-eval-select-bad.stderr
@@ -6,7 +6,7 @@ LL |     const_eval_select((), || {}, || {});
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `~const FnOnce<()>` is not implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`
+   = help: the trait `~const FnOnce<()>` is not implemented for closure `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`
 note: the trait `FnOnce<()>` is implemented for `[closure@$DIR/const-eval-select-bad.rs:7:27: 7:29]`, but that implementation is not `const`
   --> $DIR/const-eval-select-bad.rs:7:27
    |
diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr
index e5368ddf1e5..08fe0b35eb7 100644
--- a/src/test/ui/issues/issue-59488.stderr
+++ b/src/test/ui/issues/issue-59488.stderr
@@ -89,7 +89,7 @@ error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug`
 LL |     assert_eq!(Foo::Bar, i);
    |     ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
+   = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
    = help: the following other types implement trait `Debug`:
              extern "C" fn() -> Ret
              extern "C" fn(A, B) -> Ret
@@ -108,7 +108,7 @@ error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug`
 LL |     assert_eq!(Foo::Bar, i);
    |     ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
+   = help: the trait `Debug` is not implemented for fn item `fn(usize) -> Foo {Foo::Bar}`
    = help: the following other types implement trait `Debug`:
              extern "C" fn() -> Ret
              extern "C" fn(A, B) -> Ret
diff --git a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
index 9239385e643..7f29709ce50 100644
--- a/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
+++ b/src/test/ui/issues/issue-70724-add_type_neq_err_label-unwrap.stderr
@@ -28,7 +28,7 @@ LL | fn a() -> i32 {
 LL |     assert_eq!(a, 0);
    |     ^^^^^^^^^^^^^^^^ `fn() -> i32 {a}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = help: the trait `Debug` is not implemented for `fn() -> i32 {a}`
+   = help: the trait `Debug` is not implemented for fn item `fn() -> i32 {a}`
    = help: use parentheses to call the function: `a()`
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/test/ui/issues/issue-99875.rs b/src/test/ui/issues/issue-99875.rs
new file mode 100644
index 00000000000..cf73fd8d31f
--- /dev/null
+++ b/src/test/ui/issues/issue-99875.rs
@@ -0,0 +1,16 @@
+struct Argument;
+struct Return;
+
+fn function(_: Argument) -> Return { todo!() }
+
+trait Trait {}
+impl Trait for fn(Argument) -> Return {}
+
+fn takes(_: impl Trait) {}
+
+fn main() {
+    takes(function);
+    //~^ ERROR the trait bound
+    takes(|_: Argument| -> Return { todo!() });
+    //~^ ERROR the trait bound
+}
diff --git a/src/test/ui/issues/issue-99875.stderr b/src/test/ui/issues/issue-99875.stderr
new file mode 100644
index 00000000000..3ff8f12f1b8
--- /dev/null
+++ b/src/test/ui/issues/issue-99875.stderr
@@ -0,0 +1,33 @@
+error[E0277]: the trait bound `fn(Argument) -> Return {function}: Trait` is not satisfied
+  --> $DIR/issue-99875.rs:12:11
+   |
+LL |     takes(function);
+   |     ----- ^^^^^^^^ the trait `Trait` is not implemented for fn item `fn(Argument) -> Return {function}`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
+note: required by a bound in `takes`
+  --> $DIR/issue-99875.rs:9:18
+   |
+LL | fn takes(_: impl Trait) {}
+   |                  ^^^^^ required by this bound in `takes`
+
+error[E0277]: the trait bound `[closure@$DIR/issue-99875.rs:14:11: 14:34]: Trait` is not satisfied
+  --> $DIR/issue-99875.rs:14:11
+   |
+LL |     takes(|_: Argument| -> Return { todo!() });
+   |     ----- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for closure `[closure@$DIR/issue-99875.rs:14:11: 14:34]`
+   |     |
+   |     required by a bound introduced by this call
+   |
+   = help: the trait `Trait` is implemented for fn pointer `fn(Argument) -> Return`
+note: required by a bound in `takes`
+  --> $DIR/issue-99875.rs:9:18
+   |
+LL | fn takes(_: impl Trait) {}
+   |                  ^^^^^ required by this bound in `takes`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/namespace/namespace-mix.stderr b/src/test/ui/namespace/namespace-mix.stderr
index b04ea14d1a5..c07914df727 100644
--- a/src/test/ui/namespace/namespace-mix.stderr
+++ b/src/test/ui/namespace/namespace-mix.stderr
@@ -218,7 +218,7 @@ error[E0277]: the trait bound `fn() -> c::TS {c::TS}: Impossible` is not satisfi
   --> $DIR/namespace-mix.rs:56:11
    |
 LL |     check(m3::TS);
-   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::TS {c::TS}`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::TS {c::TS}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -274,7 +274,7 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::TS {namespace_mix::c::T
   --> $DIR/namespace-mix.rs:62:11
    |
 LL |     check(xm3::TS);
-   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::TS {namespace_mix::c::TS}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -526,7 +526,7 @@ error[E0277]: the trait bound `fn() -> c::E {c::E::TV}: Impossible` is not satis
   --> $DIR/namespace-mix.rs:122:11
    |
 LL |     check(m9::TV);
-   |     ----- ^^^^^^ the trait `Impossible` is not implemented for `fn() -> c::E {c::E::TV}`
+   |     ----- ^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> c::E {c::E::TV}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -582,7 +582,7 @@ error[E0277]: the trait bound `fn() -> namespace_mix::c::E {namespace_mix::xm7::
   --> $DIR/namespace-mix.rs:128:11
    |
 LL |     check(xm9::TV);
-   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
+   |     ----- ^^^^^^^ the trait `Impossible` is not implemented for fn item `fn() -> namespace_mix::c::E {namespace_mix::xm7::TV}`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/src/test/ui/proc-macro/signature.stderr b/src/test/ui/proc-macro/signature.stderr
index 78b0beff0da..59b3e44c74a 100644
--- a/src/test/ui/proc-macro/signature.stderr
+++ b/src/test/ui/proc-macro/signature.stderr
@@ -10,7 +10,7 @@ LL | | }
    | |_call the function in a closure: `|| unsafe { /* code */ }`
    |   required by a bound introduced by this call
    |
-   = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
+   = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for fn item `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `ProcMacro::custom_derive`
   --> $SRC_DIR/proc_macro/src/bridge/client.rs:LL:COL
diff --git a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
index 94a90a56854..fc7bf22775d 100644
--- a/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
+++ b/src/test/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr
@@ -6,7 +6,7 @@ LL |     call(foo);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for `fn() {foo}`
+   = help: the trait `Fn<()>` is not implemented for fn item `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call`
@@ -23,7 +23,7 @@ LL |     call_mut(foo);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnMut<()>` is not implemented for `fn() {foo}`
+   = help: the trait `FnMut<()>` is not implemented for fn item `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call_mut`
@@ -40,7 +40,7 @@ LL |     call_once(foo);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<()>` is not implemented for `fn() {foo}`
+   = help: the trait `FnOnce<()>` is not implemented for fn item `fn() {foo}`
    = note: wrap the `fn() {foo}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call_once`
@@ -57,7 +57,7 @@ LL |     call(foo_unsafe);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Fn<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+   = help: the trait `Fn<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call`
@@ -74,7 +74,7 @@ LL |     call_mut(foo_unsafe);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnMut<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+   = help: the trait `FnMut<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call_mut`
@@ -91,7 +91,7 @@ LL |     call_once(foo_unsafe);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `FnOnce<()>` is not implemented for `unsafe fn() {foo_unsafe}`
+   = help: the trait `FnOnce<()>` is not implemented for fn item `unsafe fn() {foo_unsafe}`
    = note: wrap the `unsafe fn() {foo_unsafe}` in a closure with no arguments: `|| { /* code */ }`
    = note: `#[target_feature]` functions do not implement the `Fn` traits
 note: required by a bound in `call_once`
diff --git a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
index c7d420e0aae..bfd506c9f6e 100644
--- a/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
+++ b/src/test/ui/suggestions/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -9,7 +9,7 @@ LL |     bar(foo);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Future` is not implemented for `fn() -> impl Future<Output = ()> {foo}`
+   = help: the trait `Future` is not implemented for fn item `fn() -> impl Future<Output = ()> {foo}`
    = note: fn() -> impl Future<Output = ()> {foo} must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `bar`
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
@@ -31,7 +31,7 @@ LL |     bar(async_closure);
    |     |
    |     required by a bound introduced by this call
    |
-   = help: the trait `Future` is not implemented for `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]`
+   = help: the trait `Future` is not implemented for closure `[closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33]`
    = note: [closure@$DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:11:25: 11:33] must be a future or must implement `IntoFuture` to be awaited
 note: required by a bound in `bar`
   --> $DIR/async-fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:7:16
diff --git a/src/test/ui/suggestions/deref-path-method.rs b/src/test/ui/suggestions/deref-path-method.rs
new file mode 100644
index 00000000000..0281cdb6b37
--- /dev/null
+++ b/src/test/ui/suggestions/deref-path-method.rs
@@ -0,0 +1,6 @@
+fn main() {
+    let vec = Vec::new();
+    Vec::contains(&vec, &0);
+    //~^ ERROR no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
+    //~| HELP the function `contains` is implemented on `[_]`
+}
diff --git a/src/test/ui/suggestions/deref-path-method.stderr b/src/test/ui/suggestions/deref-path-method.stderr
new file mode 100644
index 00000000000..1cc37d61151
--- /dev/null
+++ b/src/test/ui/suggestions/deref-path-method.stderr
@@ -0,0 +1,14 @@
+error[E0599]: no function or associated item named `contains` found for struct `Vec<_, _>` in the current scope
+  --> $DIR/deref-path-method.rs:3:10
+   |
+LL |     Vec::contains(&vec, &0);
+   |          ^^^^^^^^ function or associated item not found in `Vec<_, _>`
+   |
+help: the function `contains` is implemented on `[_]`
+   |
+LL |     <[_]>::contains(&vec, &0);
+   |     ~~~~~
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
index fb0a6f70bfb..fe603b67575 100644
--- a/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
+++ b/src/test/ui/suggestions/fn-ctor-passed-as-arg-where-it-should-have-been-called.stderr
@@ -5,7 +5,7 @@ LL | fn foo() -> impl T<O=()> { S }
    |    --- consider calling this function
 ...
 LL |     bar(foo);
-   |     --- ^^^ the trait `T` is not implemented for `fn() -> impl T<O = ()> {foo}`
+   |     --- ^^^ the trait `T` is not implemented for fn item `fn() -> impl T<O = ()> {foo}`
    |     |
    |     required by a bound introduced by this call
    |
@@ -25,7 +25,7 @@ error[E0277]: the trait bound `[closure@$DIR/fn-ctor-passed-as-arg-where-it-shou
 LL |     let closure = || S;
    |                   -- consider calling this closure
 LL |     bar(closure);
-   |     --- ^^^^^^^ the trait `T` is not implemented for `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]`
+   |     --- ^^^^^^^ the trait `T` is not implemented for closure `[closure@$DIR/fn-ctor-passed-as-arg-where-it-should-have-been-called.rs:18:19: 18:21]`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
index 18e133957ba..9833304c636 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr
@@ -6,7 +6,7 @@ LL |     let x = call_it(&square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:9:15
@@ -22,7 +22,7 @@ LL |     let y = call_it_mut(&mut square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_mut`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:12:19
@@ -38,7 +38,7 @@ LL |     let z = call_it_once(square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> unsafe fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> unsafe fn(&'r isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_once`
   --> $DIR/unboxed-closures-unsafe-extern-fn.rs:15:20
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
index 77c176de625..54c92e0cd04 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr
@@ -6,7 +6,7 @@ LL |     let x = call_it(&square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-wrong-abi.rs:9:15
    |
@@ -21,7 +21,7 @@ LL |     let y = call_it_mut(&mut square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_mut`
   --> $DIR/unboxed-closures-wrong-abi.rs:12:19
    |
@@ -36,7 +36,7 @@ LL |     let z = call_it_once(square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `for<'r> extern "C" fn(&'r isize) -> isize {square}`
+   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `for<'r> extern "C" fn(&'r isize) -> isize {square}`
 note: required by a bound in `call_it_once`
   --> $DIR/unboxed-closures-wrong-abi.rs:15:20
    |
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
index c826af3c4c3..2fedb5b92c2 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr
@@ -6,7 +6,7 @@ LL |     let x = call_it(&square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   = help: the trait `for<'r> Fn<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:10:15
@@ -22,7 +22,7 @@ LL |     let y = call_it_mut(&mut square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   = help: the trait `for<'r> FnMut<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_mut`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:13:19
@@ -38,7 +38,7 @@ LL |     let z = call_it_once(square, 22);
    |             |
    |             required by a bound introduced by this call
    |
-   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for `unsafe fn(isize) -> isize {square}`
+   = help: the trait `for<'r> FnOnce<(&'r isize,)>` is not implemented for fn item `unsafe fn(isize) -> isize {square}`
    = note: unsafe function cannot be called generically without an unsafe block
 note: required by a bound in `call_it_once`
   --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:16:20