Skip to content

Commit 220e8a7

Browse files
committed
For E0038, suggest associated type if available
1 parent 502ce82 commit 220e8a7

File tree

7 files changed

+58
-6
lines changed

7 files changed

+58
-6
lines changed

Diff for: compiler/rustc_errors/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -524,6 +524,7 @@ pub enum StashKey {
524524
MaybeFruTypo,
525525
CallAssocMethod,
526526
TraitMissingMethod,
527+
AssociatedTypeSuggestion,
527528
OpaqueHiddenTypeMismatch,
528529
MaybeForgetReturn,
529530
/// Query cycle detected, stashing in favor of a better error.

Diff for: compiler/rustc_resolve/src/late.rs

+18
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_ast::*;
1818
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
1919
use rustc_errors::{
2020
codes::*, struct_span_code_err, Applicability, DiagnosticArgValue, ErrCode, IntoDiagnosticArg,
21+
StashKey,
2122
};
2223
use rustc_hir::def::Namespace::{self, *};
2324
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> {
38903891
finalize,
38913892
) {
38923893
Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => {
3894+
// if we also have an associated type that matches the ident, stash a suggestion
3895+
if let Some(items) = self.diagnostic_metadata.current_trait_assoc_items
3896+
&& let [Segment { ident, .. }] = path
3897+
&& items.iter().any(|item| {
3898+
item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_))
3899+
})
3900+
{
3901+
let mut diag = self.r.tcx.dcx().struct_allow("");
3902+
diag.span_suggestion_verbose(
3903+
path_span.shrink_to_lo(),
3904+
"there is an associated type with the same name",
3905+
"Self::",
3906+
Applicability::MaybeIncorrect,
3907+
);
3908+
diag.stash(path_span, StashKey::AssociatedTypeSuggestion);
3909+
}
3910+
38933911
if source.is_expected(res) || res == Res::Err {
38943912
partial_res
38953913
} else {

Diff for: compiler/rustc_trait_selection/src/traits/error_reporting/type_err_ctxt_ext.rs

+9
Original file line numberDiff line numberDiff line change
@@ -2922,6 +2922,15 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
29222922
&mut Default::default(),
29232923
);
29242924
self.suggest_unsized_bound_if_applicable(err, obligation);
2925+
if let Some(span) = err.span.primary_span()
2926+
&& let Some(mut diag) =
2927+
self.tcx.dcx().steal_diagnostic(span, StashKey::AssociatedTypeSuggestion)
2928+
&& let Ok(ref mut s1) = err.suggestions
2929+
&& let Ok(ref mut s2) = diag.suggestions
2930+
{
2931+
s1.append(s2);
2932+
diag.cancel()
2933+
}
29252934
}
29262935
}
29272936

Diff for: tests/ui/suggestions/issue-116434-2015.rs

+6
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@ trait Foo {
33
fn foo() -> Clone;
44
//~^ WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
55
//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
6+
//~| HELP if this is an object-safe trait, use `dyn`
67
//~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
78
//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
9+
//~| HELP if this is an object-safe trait, use `dyn`
810
//~| ERROR the trait `Clone` cannot be made into an object [E0038]
11+
//~| HELP there is an associated type with the same name
912
}
1013

1114
trait DbHandle: Sized {}
@@ -15,9 +18,12 @@ trait DbInterface {
1518
fn handle() -> DbHandle;
1619
//~^ WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
1720
//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
21+
//~| HELP if this is an object-safe trait, use `dyn`
1822
//~| WARNING trait objects without an explicit `dyn` are deprecated [bare_trait_objects]
1923
//~| WARNING this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021!
24+
//~| HELP if this is an object-safe trait, use `dyn`
2025
//~| ERROR the trait `DbHandle` cannot be made into an object [E0038]
26+
//~| HELP there is an associated type with the same name
2127
}
2228

2329
fn main() {}

Diff for: tests/ui/suggestions/issue-116434-2015.stderr

+12-4
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ LL | fn foo() -> dyn Clone;
1313
| +++
1414

1515
warning: trait objects without an explicit `dyn` are deprecated
16-
--> $DIR/issue-116434-2015.rs:15:20
16+
--> $DIR/issue-116434-2015.rs:18:20
1717
|
1818
LL | fn handle() -> DbHandle;
1919
| ^^^^^^^^
@@ -47,9 +47,13 @@ LL | fn foo() -> Clone;
4747
|
4848
= note: the trait cannot be made into an object because it requires `Self: Sized`
4949
= 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>
50+
help: there is an associated type with the same name
51+
|
52+
LL | fn foo() -> Self::Clone;
53+
| ++++++
5054

5155
warning: trait objects without an explicit `dyn` are deprecated
52-
--> $DIR/issue-116434-2015.rs:15:20
56+
--> $DIR/issue-116434-2015.rs:18:20
5357
|
5458
LL | fn handle() -> DbHandle;
5559
| ^^^^^^^^
@@ -63,18 +67,22 @@ LL | fn handle() -> dyn DbHandle;
6367
| +++
6468

6569
error[E0038]: the trait `DbHandle` cannot be made into an object
66-
--> $DIR/issue-116434-2015.rs:15:20
70+
--> $DIR/issue-116434-2015.rs:18:20
6771
|
6872
LL | fn handle() -> DbHandle;
6973
| ^^^^^^^^ `DbHandle` cannot be made into an object
7074
|
7175
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>
72-
--> $DIR/issue-116434-2015.rs:11:17
76+
--> $DIR/issue-116434-2015.rs:14:17
7377
|
7478
LL | trait DbHandle: Sized {}
7579
| -------- ^^^^^ ...because it requires `Self: Sized`
7680
| |
7781
| this trait cannot be made into an object...
82+
help: there is an associated type with the same name
83+
|
84+
LL | fn handle() -> Self::DbHandle;
85+
| ++++++
7886

7987
error: aborting due to 2 previous errors; 4 warnings emitted
8088

Diff for: tests/ui/suggestions/issue-116434-2021.rs

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ trait Foo {
44
type Clone;
55
fn foo() -> Clone;
66
//~^ ERROR the trait `Clone` cannot be made into an object [E0038]
7+
//~| HELP there is an associated type with the same name
78
}
89

910
trait DbHandle: Sized {}
@@ -12,6 +13,7 @@ trait DbInterface {
1213
type DbHandle;
1314
fn handle() -> DbHandle;
1415
//~^ ERROR the trait `DbHandle` cannot be made into an object [E0038]
16+
//~| HELP there is an associated type with the same name
1517
}
1618

1719
fn main() {}

Diff for: tests/ui/suggestions/issue-116434-2021.stderr

+10-2
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,28 @@ LL | fn foo() -> Clone;
66
|
77
= note: the trait cannot be made into an object because it requires `Self: Sized`
88
= 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>
9+
help: there is an associated type with the same name
10+
|
11+
LL | fn foo() -> Self::Clone;
12+
| ++++++
913

1014
error[E0038]: the trait `DbHandle` cannot be made into an object
11-
--> $DIR/issue-116434-2021.rs:13:20
15+
--> $DIR/issue-116434-2021.rs:14:20
1216
|
1317
LL | fn handle() -> DbHandle;
1418
| ^^^^^^^^ `DbHandle` cannot be made into an object
1519
|
1620
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>
17-
--> $DIR/issue-116434-2021.rs:9:17
21+
--> $DIR/issue-116434-2021.rs:10:17
1822
|
1923
LL | trait DbHandle: Sized {}
2024
| -------- ^^^^^ ...because it requires `Self: Sized`
2125
| |
2226
| this trait cannot be made into an object...
27+
help: there is an associated type with the same name
28+
|
29+
LL | fn handle() -> Self::DbHandle;
30+
| ++++++
2331

2432
error: aborting due to 2 previous errors
2533

0 commit comments

Comments
 (0)