about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2022-07-19 13:30:44 +0200
committerGitHub <noreply@github.com>2022-07-19 13:30:44 +0200
commitbfefd587c081305ab81074fee1ff7fd26b058ef6 (patch)
tree3da347d4655a970ff0ece525cafe8bf9bba58e79
parent4603ac31b0655793a82f110f544dc1c6abc57bb7 (diff)
parent38ea23558eca629d668208e368dfa711b8229192 (diff)
downloadrust-bfefd587c081305ab81074fee1ff7fd26b058ef6.tar.gz
rust-bfefd587c081305ab81074fee1ff7fd26b058ef6.zip
Rollup merge of #98028 - aticu:master, r=estebank
Add E0790 as more specific variant of E0283

Fixes #81701

I think this should be good to go, there are only two things where I am somewhat unsure:
- Is there a better way to get the fully-qualified path for the suggestion? I tried `self.tcx.def_path_str`, but that didn't seem to always give a correct path for the context.
- Should all this be extracted into it's own method or is it fine where it is?

r? `@estebank`
-rw-r--r--compiler/rustc_error_codes/src/error_codes.rs1
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0283.md45
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0790.md47
-rw-r--r--compiler/rustc_middle/src/ty/trait_def.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs92
-rw-r--r--src/test/ui/associated-consts/issue-63496.rs4
-rw-r--r--src/test/ui/associated-consts/issue-63496.stderr28
-rw-r--r--src/test/ui/associated-item/issue-48027.rs2
-rw-r--r--src/test/ui/associated-item/issue-48027.stderr14
-rw-r--r--src/test/ui/associated-types/associated-types-unconstrained.rs2
-rw-r--r--src/test/ui/associated-types/associated-types-unconstrained.stderr11
-rw-r--r--src/test/ui/error-codes/E0283.rs2
-rw-r--r--src/test/ui/error-codes/E0283.stderr15
-rw-r--r--src/test/ui/error-codes/E0790.rs53
-rw-r--r--src/test/ui/error-codes/E0790.stderr73
-rw-r--r--src/test/ui/issues/issue-54954.rs2
-rw-r--r--src/test/ui/issues/issue-54954.stderr16
-rw-r--r--src/test/ui/issues/issue-58022.rs2
-rw-r--r--src/test/ui/issues/issue-58022.stderr17
-rw-r--r--src/test/ui/traits/static-method-generic-inference.rs2
-rw-r--r--src/test/ui/traits/static-method-generic-inference.stderr14
21 files changed, 350 insertions, 96 deletions
diff --git a/compiler/rustc_error_codes/src/error_codes.rs b/compiler/rustc_error_codes/src/error_codes.rs
index 977318b8589..97766b8368a 100644
--- a/compiler/rustc_error_codes/src/error_codes.rs
+++ b/compiler/rustc_error_codes/src/error_codes.rs
@@ -492,6 +492,7 @@ E0785: include_str!("./error_codes/E0785.md"),
 E0786: include_str!("./error_codes/E0786.md"),
 E0787: include_str!("./error_codes/E0787.md"),
 E0788: include_str!("./error_codes/E0788.md"),
+E0790: include_str!("./error_codes/E0790.md"),
 ;
 //  E0006, // merged with E0005
 //  E0008, // cannot bind by-move into a pattern guard
diff --git a/compiler/rustc_error_codes/src/error_codes/E0283.md b/compiler/rustc_error_codes/src/error_codes/E0283.md
index 6885f9a486d..79d2c8204f9 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0283.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0283.md
@@ -3,48 +3,27 @@ An implementation cannot be chosen unambiguously because of lack of information.
 Erroneous code example:
 
 ```compile_fail,E0283
-trait Generator {
-    fn create() -> u32;
-}
-
-struct Impl;
-
-impl Generator for Impl {
-    fn create() -> u32 { 1 }
-}
-
-struct AnotherImpl;
+struct Foo;
 
-impl Generator for AnotherImpl {
-    fn create() -> u32 { 2 }
+impl Into<u32> for Foo {
+    fn into(self) -> u32 { 1 }
 }
 
-fn main() {
-    let cont: u32 = Generator::create();
-    // error, impossible to choose one of Generator trait implementation
-    // Should it be Impl or AnotherImpl, maybe something else?
-}
+let foo = Foo;
+let bar: u32 = foo.into() * 1u32;
 ```
 
 This error can be solved by adding type annotations that provide the missing
-information to the compiler. In this case, the solution is to use a concrete
-type:
+information to the compiler. In this case, the solution is to specify the
+trait's type parameter:
 
 ```
-trait Generator {
-    fn create() -> u32;
-}
-
-struct AnotherImpl;
+struct Foo;
 
-impl Generator for AnotherImpl {
-    fn create() -> u32 { 2 }
+impl Into<u32> for Foo {
+    fn into(self) -> u32 { 1 }
 }
 
-fn main() {
-    let gen1 = AnotherImpl::create();
-
-    // if there are multiple methods with same name (different traits)
-    let gen2 = <AnotherImpl as Generator>::create();
-}
+let foo = Foo;
+let bar: u32 = Into::<u32>::into(foo) * 1u32;
 ```
diff --git a/compiler/rustc_error_codes/src/error_codes/E0790.md b/compiler/rustc_error_codes/src/error_codes/E0790.md
new file mode 100644
index 00000000000..2aee9dfbdbd
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0790.md
@@ -0,0 +1,47 @@
+You need to specify a specific implementation of the trait in order to call the
+method.
+
+Erroneous code example:
+
+```compile_fail,E0790
+trait Generator {
+    fn create() -> u32;
+}
+
+struct Impl;
+
+impl Generator for Impl {
+    fn create() -> u32 { 1 }
+}
+
+struct AnotherImpl;
+
+impl Generator for AnotherImpl {
+    fn create() -> u32 { 2 }
+}
+
+let cont: u32 = Generator::create();
+// error, impossible to choose one of Generator trait implementation
+// Should it be Impl or AnotherImpl, maybe something else?
+```
+
+This error can be solved by adding type annotations that provide the missing
+information to the compiler. In this case, the solution is to use a concrete
+type:
+
+```
+trait Generator {
+    fn create() -> u32;
+}
+
+struct AnotherImpl;
+
+impl Generator for AnotherImpl {
+    fn create() -> u32 { 2 }
+}
+
+let gen1 = AnotherImpl::create();
+
+// if there are multiple methods with same name (different traits)
+let gen2 = <AnotherImpl as Generator>::create();
+```
diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs
index 826c16dda4a..541dace5cc2 100644
--- a/compiler/rustc_middle/src/ty/trait_def.rs
+++ b/compiler/rustc_middle/src/ty/trait_def.rs
@@ -74,6 +74,10 @@ impl TraitImpls {
     pub fn blanket_impls(&self) -> &[DefId] {
         self.blanket_impls.as_slice()
     }
+
+    pub fn non_blanket_impls(&self) -> &FxIndexMap<SimplifiedType, Vec<DefId>> {
+        &self.non_blanket_impls
+    }
 }
 
 impl<'tcx> TraitDef {
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 8a679ca005f..585159e309f 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -2104,6 +2104,98 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                         );
                     }
                 }
+
+                if let (Some(body_id), Some(ty::subst::GenericArgKind::Type(_))) =
+                    (body_id, subst.map(|subst| subst.unpack()))
+                {
+                    struct FindExprBySpan<'hir> {
+                        span: Span,
+                        result: Option<&'hir hir::Expr<'hir>>,
+                    }
+
+                    impl<'v> hir::intravisit::Visitor<'v> for FindExprBySpan<'v> {
+                        fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+                            if self.span == ex.span {
+                                self.result = Some(ex);
+                            } else {
+                                hir::intravisit::walk_expr(self, ex);
+                            }
+                        }
+                    }
+
+                    let mut expr_finder = FindExprBySpan { span, result: None };
+
+                    expr_finder.visit_expr(&self.tcx.hir().body(body_id).value);
+
+                    if let Some(hir::Expr {
+                        kind: hir::ExprKind::Path(hir::QPath::Resolved(None, path)), .. }
+                    ) = expr_finder.result
+                        && let [
+                            ..,
+                            trait_path_segment @ hir::PathSegment {
+                                res: Some(rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, trait_id)),
+                                ..
+                            },
+                            hir::PathSegment {
+                                ident: assoc_item_name,
+                                res: Some(rustc_hir::def::Res::Def(_, item_id)),
+                                ..
+                            }
+                        ] = path.segments
+                        && data.trait_ref.def_id == *trait_id
+                        && self.tcx.trait_of_item(item_id) == Some(*trait_id)
+                        && !self.is_tainted_by_errors()
+                    {
+                        let (verb, noun) = match self.tcx.associated_item(item_id).kind {
+                            ty::AssocKind::Const => ("refer to the", "constant"),
+                            ty::AssocKind::Fn => ("call", "function"),
+                            ty::AssocKind::Type => ("refer to the", "type"), // this is already covered by E0223, but this single match arm doesn't hurt here
+                        };
+
+                        // Replace the more general E0283 with a more specific error
+                        err.cancel();
+                        err = self.tcx.sess.struct_span_err_with_code(
+                            span,
+                            &format!(
+                                "cannot {verb} associated {noun} on trait without specifying the corresponding `impl` type",
+                             ),
+                            rustc_errors::error_code!(E0790),
+                        );
+
+                        if let Some(local_def_id) = data.trait_ref.def_id.as_local()
+                            && let Some(hir::Node::Item(hir::Item { ident: trait_name, kind: hir::ItemKind::Trait(_, _, _, _, trait_item_refs), .. })) = self.tcx.hir().find_by_def_id(local_def_id)
+                            && let Some(method_ref) = trait_item_refs.iter().find(|item_ref| item_ref.ident == *assoc_item_name) {
+                            err.span_label(method_ref.span, format!("`{}::{}` defined here", trait_name, assoc_item_name));
+                        }
+
+                        err.span_label(span, format!("cannot {verb} associated {noun} of trait"));
+
+                        let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id);
+
+                        if trait_impls.blanket_impls().is_empty()
+                            && let Some((impl_ty, _)) = trait_impls.non_blanket_impls().iter().next()
+                            && let Some(impl_def_id) = impl_ty.def() {
+                            let message = if trait_impls.non_blanket_impls().len() == 1 {
+                                "use the fully-qualified path to the only available implementation".to_string()
+                            } else {
+                                format!(
+                                    "use a fully-qualified path to a specific available implementation ({} found)",
+                                    trait_impls.non_blanket_impls().len()
+                                )
+                            };
+
+                            err.multipart_suggestion(
+                                message,
+                                vec![
+                                    (trait_path_segment.ident.span.shrink_to_lo(), format!("<{} as ", self.tcx.def_path(impl_def_id).to_string_no_crate_verbose())),
+                                    (trait_path_segment.ident.span.shrink_to_hi(), format!(">"))
+                                ],
+                                Applicability::MaybeIncorrect
+                            );
+                        }
+                    }
+                };
+
                 err
             }
 
diff --git a/src/test/ui/associated-consts/issue-63496.rs b/src/test/ui/associated-consts/issue-63496.rs
index f9f663af5e2..67ef4e74cf2 100644
--- a/src/test/ui/associated-consts/issue-63496.rs
+++ b/src/test/ui/associated-consts/issue-63496.rs
@@ -2,8 +2,8 @@ trait A {
     const C: usize;
 
     fn f() -> ([u8; A::C], [u8; A::C]);
-    //~^ ERROR: type annotations needed
-    //~| ERROR: type annotations needed
+    //~^ ERROR: E0790
+    //~| ERROR: E0790
 }
 
 fn main() {}
diff --git a/src/test/ui/associated-consts/issue-63496.stderr b/src/test/ui/associated-consts/issue-63496.stderr
index db39fd762c3..f2a4e01adea 100644
--- a/src/test/ui/associated-consts/issue-63496.stderr
+++ b/src/test/ui/associated-consts/issue-63496.stderr
@@ -1,27 +1,21 @@
-error[E0283]: type annotations needed
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
   --> $DIR/issue-63496.rs:4:21
    |
+LL |     const C: usize;
+   |     --------------- `A::C` defined here
+LL |
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
-   |                     ^^^^
-   |                     |
-   |                     cannot infer type
-   |                     help: use the fully qualified path to an implementation: `<Type as A>::C`
-   |
-   = note: cannot satisfy `_: A`
-   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+   |                     ^^^^ cannot refer to the associated constant of trait
 
-error[E0283]: type annotations needed
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
   --> $DIR/issue-63496.rs:4:33
    |
+LL |     const C: usize;
+   |     --------------- `A::C` defined here
+LL |
 LL |     fn f() -> ([u8; A::C], [u8; A::C]);
-   |                                 ^^^^
-   |                                 |
-   |                                 cannot infer type
-   |                                 help: use the fully qualified path to an implementation: `<Type as A>::C`
-   |
-   = note: cannot satisfy `_: A`
-   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+   |                                 ^^^^ cannot refer to the associated constant of trait
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/test/ui/associated-item/issue-48027.rs b/src/test/ui/associated-item/issue-48027.rs
index c9b4ccd3e8a..d2b51184c99 100644
--- a/src/test/ui/associated-item/issue-48027.rs
+++ b/src/test/ui/associated-item/issue-48027.rs
@@ -1,6 +1,6 @@
 trait Bar {
     const X: usize;
-    fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: type annotations needed
+    fn return_n(&self) -> [u8; Bar::X]; //~ ERROR: E0790
 }
 
 impl dyn Bar {} //~ ERROR: the trait `Bar` cannot be made into an object
diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr
index 5487af1a835..45ea419336b 100644
--- a/src/test/ui/associated-item/issue-48027.stderr
+++ b/src/test/ui/associated-item/issue-48027.stderr
@@ -13,19 +13,15 @@ LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
    = help: consider moving `X` to another trait
 
-error[E0283]: type annotations needed
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
   --> $DIR/issue-48027.rs:3:32
    |
+LL |     const X: usize;
+   |     --------------- `Bar::X` defined here
 LL |     fn return_n(&self) -> [u8; Bar::X];
-   |                                ^^^^^^
-   |                                |
-   |                                cannot infer type
-   |                                help: use the fully qualified path to an implementation: `<Type as Bar>::X`
-   |
-   = note: cannot satisfy `_: Bar`
-   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+   |                                ^^^^^^ cannot refer to the associated constant of trait
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0038, E0283.
+Some errors have detailed explanations: E0038, E0790.
 For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/associated-types/associated-types-unconstrained.rs b/src/test/ui/associated-types/associated-types-unconstrained.rs
index b97d4af184f..2fb27bf3cd1 100644
--- a/src/test/ui/associated-types/associated-types-unconstrained.rs
+++ b/src/test/ui/associated-types/associated-types-unconstrained.rs
@@ -12,5 +12,5 @@ impl Foo for isize {
 
 pub fn main() {
     let x: isize = Foo::bar();
-    //~^ ERROR type annotations needed
+    //~^ ERROR E0790
 }
diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr
index 60ec23cf655..e51a8f3bd1a 100644
--- a/src/test/ui/associated-types/associated-types-unconstrained.stderr
+++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr
@@ -1,11 +1,12 @@
-error[E0283]: type annotations needed
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/associated-types-unconstrained.rs:14:20
    |
+LL |     fn bar() -> isize;
+   |     ------------------ `Foo::bar` defined here
+...
 LL |     let x: isize = Foo::bar();
-   |                    ^^^^^^^^ cannot infer type
-   |
-   = note: cannot satisfy `_: Foo`
+   |                    ^^^^^^^^ cannot call associated function of trait
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/test/ui/error-codes/E0283.rs b/src/test/ui/error-codes/E0283.rs
index 4d7c2f2396d..0643af4b7e8 100644
--- a/src/test/ui/error-codes/E0283.rs
+++ b/src/test/ui/error-codes/E0283.rs
@@ -27,7 +27,7 @@ impl Generator for AnotherImpl {
 }
 
 fn main() {
-    let cont: u32 = Generator::create(); //~ ERROR E0283
+    let cont: u32 = Generator::create(); //~ ERROR E0790
 }
 
 fn buzz() {
diff --git a/src/test/ui/error-codes/E0283.stderr b/src/test/ui/error-codes/E0283.stderr
index a107160d11a..90a28874ead 100644
--- a/src/test/ui/error-codes/E0283.stderr
+++ b/src/test/ui/error-codes/E0283.stderr
@@ -1,10 +1,16 @@
-error[E0283]: type annotations needed
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/E0283.rs:30:21
    |
+LL |     fn create() -> u32;
+   |     ------------------- `Generator::create` defined here
+...
 LL |     let cont: u32 = Generator::create();
-   |                     ^^^^^^^^^^^^^^^^^ cannot infer type
+   |                     ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
+   |
+help: use a fully-qualified path to a specific available implementation (2 found)
    |
-   = note: cannot satisfy `_: Generator`
+LL |     let cont: u32 = <::Impl as Generator>::create();
+   |                     ++++++++++          +
 
 error[E0283]: type annotations needed
   --> $DIR/E0283.rs:35:24
@@ -27,4 +33,5 @@ LL |     let bar = <Impl as Into<T>>::into(foo_impl) * 1u32;
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0283`.
+Some errors have detailed explanations: E0283, E0790.
+For more information about an error, try `rustc --explain E0283`.
diff --git a/src/test/ui/error-codes/E0790.rs b/src/test/ui/error-codes/E0790.rs
new file mode 100644
index 00000000000..d99006d2df7
--- /dev/null
+++ b/src/test/ui/error-codes/E0790.rs
@@ -0,0 +1,53 @@
+mod inner {
+    pub trait MyTrait {
+        const MY_ASSOC_CONST: ();
+
+        fn my_fn();
+    }
+
+    pub struct MyStruct;
+
+    impl MyTrait for MyStruct {
+        const MY_ASSOC_CONST: () = ();
+
+        fn my_fn() {}
+    }
+
+    fn call() {
+        MyTrait::my_fn(); //~ ERROR E0790
+    }
+
+    fn use_const() {
+        let _ = MyTrait::MY_ASSOC_CONST; //~ ERROR E0790
+    }
+}
+
+fn call_inner() {
+    inner::MyTrait::my_fn(); //~ ERROR E0790
+}
+
+fn use_const_inner() {
+    let _ = inner::MyTrait::MY_ASSOC_CONST; //~ ERROR E0790
+}
+
+trait MyTrait2 {
+    fn my_fn();
+}
+
+struct Impl1;
+
+impl MyTrait2 for Impl1 {
+    fn my_fn() {}
+}
+
+struct Impl2;
+
+impl MyTrait2 for Impl2 {
+    fn my_fn() {}
+}
+
+fn call_multiple_impls() {
+    MyTrait2::my_fn(); //~ ERROR E0790
+}
+
+fn main() {}
diff --git a/src/test/ui/error-codes/E0790.stderr b/src/test/ui/error-codes/E0790.stderr
new file mode 100644
index 00000000000..6e173a9682a
--- /dev/null
+++ b/src/test/ui/error-codes/E0790.stderr
@@ -0,0 +1,73 @@
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/E0790.rs:17:9
+   |
+LL |         fn my_fn();
+   |         ----------- `MyTrait::my_fn` defined here
+...
+LL |         MyTrait::my_fn();
+   |         ^^^^^^^^^^^^^^ cannot call associated function of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |         <::inner::MyStruct as MyTrait>::my_fn();
+   |         +++++++++++++++++++++        +
+
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
+  --> $DIR/E0790.rs:21:17
+   |
+LL |         const MY_ASSOC_CONST: ();
+   |         ------------------------- `MyTrait::MY_ASSOC_CONST` defined here
+...
+LL |         let _ = MyTrait::MY_ASSOC_CONST;
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^ cannot refer to the associated constant of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |         let _ = <::inner::MyStruct as MyTrait>::MY_ASSOC_CONST;
+   |                 +++++++++++++++++++++        +
+
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/E0790.rs:26:5
+   |
+LL |         fn my_fn();
+   |         ----------- `MyTrait::my_fn` defined here
+...
+LL |     inner::MyTrait::my_fn();
+   |     ^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     inner::<::inner::MyStruct as MyTrait>::my_fn();
+   |            +++++++++++++++++++++        +
+
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
+  --> $DIR/E0790.rs:30:13
+   |
+LL |         const MY_ASSOC_CONST: ();
+   |         ------------------------- `MyTrait::MY_ASSOC_CONST` defined here
+...
+LL |     let _ = inner::MyTrait::MY_ASSOC_CONST;
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot refer to the associated constant of trait
+   |
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     let _ = inner::<::inner::MyStruct as MyTrait>::MY_ASSOC_CONST;
+   |                    +++++++++++++++++++++        +
+
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
+  --> $DIR/E0790.rs:50:5
+   |
+LL |     fn my_fn();
+   |     ----------- `MyTrait2::my_fn` defined here
+...
+LL |     MyTrait2::my_fn();
+   |     ^^^^^^^^^^^^^^^ cannot call associated function of trait
+   |
+help: use a fully-qualified path to a specific available implementation (2 found)
+   |
+LL |     <::Impl1 as MyTrait2>::my_fn();
+   |     +++++++++++         +
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0790`.
diff --git a/src/test/ui/issues/issue-54954.rs b/src/test/ui/issues/issue-54954.rs
index ddd39141541..d4e1df22770 100644
--- a/src/test/ui/issues/issue-54954.rs
+++ b/src/test/ui/issues/issue-54954.rs
@@ -1,5 +1,5 @@
 const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-//~^ ERROR type annotations needed
+//~^ ERROR E0790
 
 trait Tt {
     const fn const_val<T: Sized>() -> usize {
diff --git a/src/test/ui/issues/issue-54954.stderr b/src/test/ui/issues/issue-54954.stderr
index 6e8d3cac9a7..668985c2b59 100644
--- a/src/test/ui/issues/issue-54954.stderr
+++ b/src/test/ui/issues/issue-54954.stderr
@@ -4,13 +4,17 @@ error[E0379]: functions in traits cannot be declared const
 LL |     const fn const_val<T: Sized>() -> usize {
    |     ^^^^^ functions in traits cannot be const
 
-error[E0283]: type annotations needed
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/issue-54954.rs:1:24
    |
-LL | const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
-   |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
-   |
-   = note: cannot satisfy `_: Tt`
+LL |   const ARR_LEN: usize = Tt::const_val::<[i8; 123]>();
+   |                          ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot call associated function of trait
+...
+LL | /     const fn const_val<T: Sized>() -> usize {
+LL | |
+LL | |         core::mem::size_of::<T>()
+LL | |     }
+   | |_____- `Tt::const_val` defined here
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/issue-54954.rs:11:15
@@ -26,5 +30,5 @@ LL | fn f(z: [f32; ARR_LEN]) -> [f32; ARR_LEN] {
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0080, E0283, E0379.
+Some errors have detailed explanations: E0080, E0379, E0790.
 For more information about an error, try `rustc --explain E0080`.
diff --git a/src/test/ui/issues/issue-58022.rs b/src/test/ui/issues/issue-58022.rs
index e4b9b3b53a6..2a8a1eaa6d3 100644
--- a/src/test/ui/issues/issue-58022.rs
+++ b/src/test/ui/issues/issue-58022.rs
@@ -2,7 +2,7 @@ pub trait Foo: Sized {
     const SIZE: usize;
 
     fn new(slice: &[u8; Foo::SIZE]) -> Self;
-    //~^ ERROR: type annotations needed
+    //~^ ERROR: E0790
 }
 
 pub struct Bar<T: ?Sized>(T);
diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr
index 0128b70e216..6d24209ad3c 100644
--- a/src/test/ui/issues/issue-58022.stderr
+++ b/src/test/ui/issues/issue-58022.stderr
@@ -4,19 +4,16 @@ error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo
 LL |         Foo(Box::new(*slice))
    |         ^^^ not a function, tuple struct or tuple variant
 
-error[E0283]: type annotations needed
+error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type
   --> $DIR/issue-58022.rs:4:25
    |
+LL |     const SIZE: usize;
+   |     ------------------ `Foo::SIZE` defined here
+LL |
 LL |     fn new(slice: &[u8; Foo::SIZE]) -> Self;
-   |                         ^^^^^^^^^
-   |                         |
-   |                         cannot infer type
-   |                         help: use the fully qualified path to an implementation: `<Type as Foo>::SIZE`
-   |
-   = note: cannot satisfy `_: Foo`
-   = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl`
+   |                         ^^^^^^^^^ cannot refer to the associated constant of trait
 
 error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0283, E0423.
-For more information about an error, try `rustc --explain E0283`.
+Some errors have detailed explanations: E0423, E0790.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/src/test/ui/traits/static-method-generic-inference.rs b/src/test/ui/traits/static-method-generic-inference.rs
index 759416d1901..f4e94c4f786 100644
--- a/src/test/ui/traits/static-method-generic-inference.rs
+++ b/src/test/ui/traits/static-method-generic-inference.rs
@@ -22,7 +22,7 @@ mod base {
 
 pub fn foo() {
     let _f: base::Foo = base::HasNew::new();
-    //~^ ERROR type annotations needed
+    //~^ ERROR E0790
 }
 
 fn main() { }
diff --git a/src/test/ui/traits/static-method-generic-inference.stderr b/src/test/ui/traits/static-method-generic-inference.stderr
index 1a0bcf00a67..f1b8f23ecc7 100644
--- a/src/test/ui/traits/static-method-generic-inference.stderr
+++ b/src/test/ui/traits/static-method-generic-inference.stderr
@@ -1,11 +1,17 @@
-error[E0283]: type annotations needed
+error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
   --> $DIR/static-method-generic-inference.rs:24:25
    |
+LL |         fn new() -> T;
+   |         -------------- `HasNew::new` defined here
+...
 LL |     let _f: base::Foo = base::HasNew::new();
-   |                         ^^^^^^^^^^^^^^^^^ cannot infer type
+   |                         ^^^^^^^^^^^^^^^^^ cannot call associated function of trait
    |
-   = note: cannot satisfy `_: HasNew<Foo>`
+help: use the fully-qualified path to the only available implementation
+   |
+LL |     let _f: base::Foo = base::<::base::Foo as HasNew>::new();
+   |                               +++++++++++++++       +
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0283`.
+For more information about this error, try `rustc --explain E0790`.