For E0038, suggest associated type if available

This commit is contained in:
trevyn 2024-02-14 12:42:32 -08:00
parent 502ce8287b
commit 220e8a7484
7 changed files with 58 additions and 6 deletions

View File

@ -524,6 +524,7 @@ pub enum StashKey {
MaybeFruTypo,
CallAssocMethod,
TraitMissingMethod,
AssociatedTypeSuggestion,
OpaqueHiddenTypeMismatch,
MaybeForgetReturn,
/// Query cycle detected, stashing in favor of a better error.

View File

@ -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 {

View File

@ -2922,6 +2922,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()
}
}
}

View File

@ -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() {}

View File

@ -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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $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

View File

@ -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() {}

View File

@ -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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
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 <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
--> $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