Skip to content

Commit

Permalink
Rollup merge of #121111 - trevyn:associated-type-suggestion, r=davidtwco
Browse files Browse the repository at this point in the history
For E0038, suggest associated type if available

Closes #116434
  • Loading branch information
GuillaumeGomez authored Feb 16, 2024
2 parents e5a743c + 220e8a7 commit 670bdbf
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 6 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -526,6 +526,7 @@ pub enum StashKey {
MaybeFruTypo,
CallAssocMethod,
TraitMissingMethod,
AssociatedTypeSuggestion,
OpaqueHiddenTypeMismatch,
MaybeForgetReturn,
/// Query cycle detected, stashing in favor of a better error.
Expand Down
18 changes: 18 additions & 0 deletions compiler/rustc_resolve/src/late.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
}

Expand Down
6 changes: 6 additions & 0 deletions tests/ui/suggestions/issue-116434-2015.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand All @@ -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() {}
16 changes: 12 additions & 4 deletions tests/ui/suggestions/issue-116434-2015.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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;
| ^^^^^^^^
Expand Down Expand Up @@ -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;
| ^^^^^^^^
Expand All @@ -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

Expand Down
2 changes: 2 additions & 0 deletions tests/ui/suggestions/issue-116434-2021.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}
Expand All @@ -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() {}
12 changes: 10 additions & 2 deletions tests/ui/suggestions/issue-116434-2021.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 670bdbf

Please sign in to comment.