From ae60015e764fa0ba8e56c58373166a1c5d267e8e Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 12 Nov 2022 19:42:06 +0000 Subject: [PATCH 1/2] Use impl's def id when calculating type to specify UFCS --- .../src/traits/error_reporting/mod.rs | 9 +++++---- .../associated-types-unconstrained.stderr | 5 +++++ src/test/ui/suggestions/issue-104327.rs | 12 ++++++++++++ src/test/ui/suggestions/issue-104327.stderr | 17 +++++++++++++++++ src/test/ui/suggestions/issue-104328.rs | 12 ++++++++++++ src/test/ui/suggestions/issue-104328.stderr | 17 +++++++++++++++++ 6 files changed, 68 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/suggestions/issue-104327.rs create mode 100644 src/test/ui/suggestions/issue-104327.stderr create mode 100644 src/test/ui/suggestions/issue-104328.rs create mode 100644 src/test/ui/suggestions/issue-104328.stderr 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 c68da3e24a190..31cc8d9ff6c65 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2290,14 +2290,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { 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 { + && let Some(impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next() + { + let non_blanket_impl_count = trait_impls.non_blanket_impls().values().flatten().count(); + let message = if non_blanket_impl_count == 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() + non_blanket_impl_count ) }; let mut suggestions = vec![( diff --git a/src/test/ui/associated-types/associated-types-unconstrained.stderr b/src/test/ui/associated-types/associated-types-unconstrained.stderr index e51a8f3bd1a3a..ef9b7cae01bbd 100644 --- a/src/test/ui/associated-types/associated-types-unconstrained.stderr +++ b/src/test/ui/associated-types/associated-types-unconstrained.stderr @@ -6,6 +6,11 @@ LL | fn bar() -> isize; ... LL | let x: isize = Foo::bar(); | ^^^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | let x: isize = ::bar(); + | +++++++++ + error: aborting due to previous error diff --git a/src/test/ui/suggestions/issue-104327.rs b/src/test/ui/suggestions/issue-104327.rs new file mode 100644 index 0000000000000..dd621ae71008f --- /dev/null +++ b/src/test/ui/suggestions/issue-104327.rs @@ -0,0 +1,12 @@ +trait Bar {} + +trait Foo { + fn f() {} +} + +impl Foo for dyn Bar {} + +fn main() { + Foo::f(); + //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type +} diff --git a/src/test/ui/suggestions/issue-104327.stderr b/src/test/ui/suggestions/issue-104327.stderr new file mode 100644 index 0000000000000..acec3a55d526e --- /dev/null +++ b/src/test/ui/suggestions/issue-104327.stderr @@ -0,0 +1,17 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/issue-104327.rs:10:5 + | +LL | fn f() {} + | --------- `Foo::f` defined here +... +LL | Foo::f(); + | ^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | <(dyn Bar + 'static) as Foo>::f(); + | +++++++++++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0790`. diff --git a/src/test/ui/suggestions/issue-104328.rs b/src/test/ui/suggestions/issue-104328.rs new file mode 100644 index 0000000000000..c3707baf79fc3 --- /dev/null +++ b/src/test/ui/suggestions/issue-104328.rs @@ -0,0 +1,12 @@ +#![feature(object_safe_for_dispatch)] + +trait Foo { + fn f() {} +} + +impl Foo for dyn Sized {} + +fn main() { + Foo::f(); + //~^ ERROR cannot call associated function on trait without specifying the corresponding `impl` type +} diff --git a/src/test/ui/suggestions/issue-104328.stderr b/src/test/ui/suggestions/issue-104328.stderr new file mode 100644 index 0000000000000..b31b84781bacb --- /dev/null +++ b/src/test/ui/suggestions/issue-104328.stderr @@ -0,0 +1,17 @@ +error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type + --> $DIR/issue-104328.rs:10:5 + | +LL | fn f() {} + | --------- `Foo::f` defined here +... +LL | Foo::f(); + | ^^^^^^ cannot call associated function of trait + | +help: use the fully-qualified path to the only available implementation + | +LL | <(dyn Sized + 'static) as Foo>::f(); + | +++++++++++++++++++++++++ + + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0790`. From 1225a6538999f32a10157c6965e86816d3820fe8 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Sat, 12 Nov 2022 20:03:20 +0000 Subject: [PATCH 2/2] drive-by: Fix path spans --- .../src/traits/error_reporting/mod.rs | 2 +- src/test/ui/error-codes/E0790.stderr | 8 ++++---- src/test/ui/traits/static-method-generic-inference.stderr | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) 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 31cc8d9ff6c65..8ee31e4b498af 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -2302,7 +2302,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ) }; let mut suggestions = vec![( - trait_path_segment.ident.span.shrink_to_lo(), + path.span.shrink_to_lo(), format!("<{} as ", self.tcx.type_of(impl_def_id)) )]; if let Some(generic_arg) = trait_path_segment.args { diff --git a/src/test/ui/error-codes/E0790.stderr b/src/test/ui/error-codes/E0790.stderr index f68c0e7d220f3..fc025a3fca2bf 100644 --- a/src/test/ui/error-codes/E0790.stderr +++ b/src/test/ui/error-codes/E0790.stderr @@ -37,8 +37,8 @@ LL | inner::MyTrait::my_fn(); | help: use the fully-qualified path to the only available implementation | -LL | inner::::my_fn(); - | ++++++++++++ + +LL | ::my_fn(); + | ++++++++++++ + error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type --> $DIR/E0790.rs:30:13 @@ -51,8 +51,8 @@ LL | let _ = inner::MyTrait::MY_ASSOC_CONST; | help: use the fully-qualified path to the only available implementation | -LL | let _ = inner::::MY_ASSOC_CONST; - | ++++++++++++ + +LL | let _ = ::MY_ASSOC_CONST; + | ++++++++++++ + error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type --> $DIR/E0790.rs:50:5 diff --git a/src/test/ui/traits/static-method-generic-inference.stderr b/src/test/ui/traits/static-method-generic-inference.stderr index 5f74d0c3b9260..575ace2374ee6 100644 --- a/src/test/ui/traits/static-method-generic-inference.stderr +++ b/src/test/ui/traits/static-method-generic-inference.stderr @@ -9,8 +9,8 @@ LL | let _f: base::Foo = base::HasNew::new(); | help: use the fully-qualified path to the only available implementation | -LL | let _f: base::Foo = base::::new(); - | +++++++ + +LL | let _f: base::Foo = ::new(); + | +++++++ + error: aborting due to previous error