diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 7c6caf442dc23..b9b257856e678 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -526,6 +526,7 @@ pub enum StashKey { MaybeFruTypo, CallAssocMethod, TraitMissingMethod, + AssociatedTypeSuggestion, OpaqueHiddenTypeMismatch, MaybeForgetReturn, /// Query cycle detected, stashing in favor of a better error. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 6bd221ff05874..3ea4df1d2a436 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -18,6 +18,7 @@ use rustc_ast::*; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_errors::{ codes::*, struct_span_code_err, Applicability, DiagnosticArgValue, ErrCode, IntoDiagnosticArg, + StashKey, }; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS}; @@ -3890,6 +3891,23 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { finalize, ) { Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => { + // if we also have an associated type that matches the ident, stash a suggestion + if let Some(items) = self.diagnostic_metadata.current_trait_assoc_items + && let [Segment { ident, .. }] = path + && items.iter().any(|item| { + item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_)) + }) + { + let mut diag = self.r.tcx.dcx().struct_allow(""); + diag.span_suggestion_verbose( + path_span.shrink_to_lo(), + "there is an associated type with the same name", + "Self::", + Applicability::MaybeIncorrect, + ); + diag.stash(path_span, StashKey::AssociatedTypeSuggestion); + } + if source.is_expected(res) || res == Res::Err { partial_res } else { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs index 68b1a0d4e61cd..661a444d04990 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs @@ -2993,6 +2993,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { &mut Default::default(), ); self.suggest_unsized_bound_if_applicable(err, obligation); + if let Some(span) = err.span.primary_span() + && let Some(mut diag) = + self.tcx.dcx().steal_diagnostic(span, StashKey::AssociatedTypeSuggestion) + && let Ok(ref mut s1) = err.suggestions + && let Ok(ref mut s2) = diag.suggestions + { + s1.append(s2); + diag.cancel() + } } } diff --git a/tests/ui/suggestions/issue-116434-2015.rs b/tests/ui/suggestions/issue-116434-2015.rs index 614fc27b77187..a53e2a044e93f 100644 --- a/tests/ui/suggestions/issue-116434-2015.rs +++ b/tests/ui/suggestions/issue-116434-2015.rs @@ -3,9 +3,12 @@ trait Foo { fn foo() -> Clone; //~^ WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| HELP if this is an object-safe trait, use `dyn` //~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| HELP if this is an object-safe trait, use `dyn` //~| ERROR the trait `Clone` cannot be made into an object [E0038] + //~| HELP there is an associated type with the same name } trait DbHandle: Sized {} @@ -15,9 +18,12 @@ trait DbInterface { fn handle() -> DbHandle; //~^ WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| HELP if this is an object-safe trait, use `dyn` //~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects] //~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + //~| HELP if this is an object-safe trait, use `dyn` //~| ERROR the trait `DbHandle` cannot be made into an object [E0038] + //~| HELP there is an associated type with the same name } fn main() {} diff --git a/tests/ui/suggestions/issue-116434-2015.stderr b/tests/ui/suggestions/issue-116434-2015.stderr index 2d87029b6eb11..73a1cfa9c1d54 100644 --- a/tests/ui/suggestions/issue-116434-2015.stderr +++ b/tests/ui/suggestions/issue-116434-2015.stderr @@ -13,7 +13,7 @@ LL | fn foo() -> dyn Clone; | +++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-116434-2015.rs:15:20 + --> $DIR/issue-116434-2015.rs:18:20 | LL | fn handle() -> DbHandle; | ^^^^^^^^ @@ -47,9 +47,13 @@ LL | fn foo() -> Clone; | = note: the trait cannot be made into an object because it requires `Self: Sized` = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit +help: there is an associated type with the same name + | +LL | fn foo() -> Self::Clone; + | ++++++ warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/issue-116434-2015.rs:15:20 + --> $DIR/issue-116434-2015.rs:18:20 | LL | fn handle() -> DbHandle; | ^^^^^^^^ @@ -63,18 +67,22 @@ LL | fn handle() -> dyn DbHandle; | +++ error[E0038]: the trait `DbHandle` cannot be made into an object - --> $DIR/issue-116434-2015.rs:15:20 + --> $DIR/issue-116434-2015.rs:18:20 | LL | fn handle() -> DbHandle; | ^^^^^^^^ `DbHandle` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-116434-2015.rs:11:17 + --> $DIR/issue-116434-2015.rs:14:17 | LL | trait DbHandle: Sized {} | -------- ^^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... +help: there is an associated type with the same name + | +LL | fn handle() -> Self::DbHandle; + | ++++++ error: aborting due to 2 previous errors; 4 warnings emitted diff --git a/tests/ui/suggestions/issue-116434-2021.rs b/tests/ui/suggestions/issue-116434-2021.rs index 74c30e0cc1fbe..e7159bc2f3cd9 100644 --- a/tests/ui/suggestions/issue-116434-2021.rs +++ b/tests/ui/suggestions/issue-116434-2021.rs @@ -4,6 +4,7 @@ trait Foo { type Clone; fn foo() -> Clone; //~^ ERROR the trait `Clone` cannot be made into an object [E0038] + //~| HELP there is an associated type with the same name } trait DbHandle: Sized {} @@ -12,6 +13,7 @@ trait DbInterface { type DbHandle; fn handle() -> DbHandle; //~^ ERROR the trait `DbHandle` cannot be made into an object [E0038] + //~| HELP there is an associated type with the same name } fn main() {} diff --git a/tests/ui/suggestions/issue-116434-2021.stderr b/tests/ui/suggestions/issue-116434-2021.stderr index 43ad82d484a66..a10d6ef6da4d9 100644 --- a/tests/ui/suggestions/issue-116434-2021.stderr +++ b/tests/ui/suggestions/issue-116434-2021.stderr @@ -6,20 +6,28 @@ LL | fn foo() -> Clone; | = note: the trait cannot be made into an object because it requires `Self: Sized` = note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit +help: there is an associated type with the same name + | +LL | fn foo() -> Self::Clone; + | ++++++ error[E0038]: the trait `DbHandle` cannot be made into an object - --> $DIR/issue-116434-2021.rs:13:20 + --> $DIR/issue-116434-2021.rs:14:20 | LL | fn handle() -> DbHandle; | ^^^^^^^^ `DbHandle` cannot be made into an object | note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit - --> $DIR/issue-116434-2021.rs:9:17 + --> $DIR/issue-116434-2021.rs:10:17 | LL | trait DbHandle: Sized {} | -------- ^^^^^ ...because it requires `Self: Sized` | | | this trait cannot be made into an object... +help: there is an associated type with the same name + | +LL | fn handle() -> Self::DbHandle; + | ++++++ error: aborting due to 2 previous errors