Skip to content

Commit 05bffa0

Browse files
committed
Mention associated type with same name as trait in E0782
``` error[E0782]: trait objects must include the `dyn` keyword --> $DIR/issue-116434-2021.rs:5:17 | LL | type Clone; | ---------- you might have meant to use this associated type LL | fn foo() -> Clone; | ^^^^^ | help: `Clone` is not object safe, use `impl Clone` to return an opaque type, as long as you return a single underlying type | LL | fn foo() -> impl Clone; | ++++ help: there is an associated type with the same name | LL | fn foo() -> Self::Clone; | ++++++ ```
1 parent aec9eeb commit 05bffa0

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use rustc_hir as hir;
44
use rustc_hir::def::{DefKind, Res};
55
use rustc_infer::traits::error_reporting::suggest_path_on_bare_trait;
66
use rustc_lint_defs::{builtin::BARE_TRAIT_OBJECTS, Applicability};
7+
use rustc_middle::ty;
78
use rustc_span::Span;
89
use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
910

@@ -87,6 +88,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
8788
// Check if the impl trait that we are considering is an impl of a local trait.
8889
self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag);
8990
self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag);
91+
self.maybe_suggest_assoc_type(&poly_trait_ref.trait_ref, &mut diag);
9092

9193
if object_safe {
9294
let parents = self.tcx().hir().parent_iter(self_ty.hir_id);
@@ -338,4 +340,39 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
338340
);
339341
}
340342
}
343+
344+
/// Look for associated types with the same name as the `-> Trait` and suggest `-> Self::Trait`.
345+
fn maybe_suggest_assoc_type(&self, trait_ref: &hir::TraitRef<'_>, diag: &mut Diag<'_>) {
346+
let tcx = self.tcx();
347+
let [segment] = trait_ref.path.segments else { return };
348+
let mut trait_or_impl = None;
349+
let mut iter = tcx.hir().parent_owner_iter(trait_ref.hir_ref_id);
350+
while let Some((def_id, node)) = iter.next() {
351+
if let hir::OwnerNode::Item(hir::Item {
352+
kind: hir::ItemKind::Trait(..) | hir::ItemKind::Impl(..),
353+
..
354+
}) = node
355+
{
356+
trait_or_impl = Some(def_id);
357+
break;
358+
}
359+
}
360+
let Some(parent_id) = trait_or_impl else { return };
361+
let mut assocs = tcx
362+
.associated_items(parent_id)
363+
.filter_by_name_unhygienic(segment.ident.name)
364+
.filter(|assoc| assoc.kind == ty::AssocKind::Type);
365+
if let Some(assoc) = assocs.next() {
366+
diag.span_label(
367+
tcx.def_span(assoc.def_id),
368+
"you might have meant to use this associated type",
369+
);
370+
diag.span_suggestion_verbose(
371+
segment.ident.span.shrink_to_lo(),
372+
"there is an associated type with the same name",
373+
"Self::",
374+
Applicability::MaybeIncorrect,
375+
);
376+
}
377+
}
341378
}
Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
//@ edition:2021
22

33
trait Foo {
4-
type Clone;
4+
type Clone; //~ NOTE you might have meant to use this associated type
55
fn foo() -> Clone;
66
//~^ ERROR trait objects must include the `dyn` keyword
77
//~| HELP `Clone` is not object safe, use `impl Clone` to return an opaque type, as long as you return a single underlying type
8+
//~| HELP there is an associated type with the same name
89
}
910

1011
trait DbHandle: Sized {}
1112

1213
trait DbInterface {
13-
type DbHandle;
14+
type DbHandle; //~ NOTE you might have meant to use this associated type
1415
fn handle() -> DbHandle;
1516
//~^ ERROR trait objects must include the `dyn` keyword
1617
//~| HELP `DbHandle` is not object safe, use `impl DbHandle` to return an opaque type, as long as you return a single underlying type
18+
//~| HELP there is an associated type with the same name
1719
}
1820

1921
fn main() {}

tests/ui/suggestions/issue-116434-2021.stderr

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,36 @@
11
error[E0782]: trait objects must include the `dyn` keyword
22
--> $DIR/issue-116434-2021.rs:5:17
33
|
4+
LL | type Clone;
5+
| ---------- you might have meant to use this associated type
46
LL | fn foo() -> Clone;
57
| ^^^^^
68
|
79
help: `Clone` is not object safe, use `impl Clone` to return an opaque type, as long as you return a single underlying type
810
|
911
LL | fn foo() -> impl Clone;
1012
| ++++
13+
help: there is an associated type with the same name
14+
|
15+
LL | fn foo() -> Self::Clone;
16+
| ++++++
1117

1218
error[E0782]: trait objects must include the `dyn` keyword
13-
--> $DIR/issue-116434-2021.rs:14:20
19+
--> $DIR/issue-116434-2021.rs:15:20
1420
|
21+
LL | type DbHandle;
22+
| ------------- you might have meant to use this associated type
1523
LL | fn handle() -> DbHandle;
1624
| ^^^^^^^^
1725
|
1826
help: `DbHandle` is not object safe, use `impl DbHandle` to return an opaque type, as long as you return a single underlying type
1927
|
2028
LL | fn handle() -> impl DbHandle;
2129
| ++++
30+
help: there is an associated type with the same name
31+
|
32+
LL | fn handle() -> Self::DbHandle;
33+
| ++++++
2234

2335
error: aborting due to 2 previous errors
2436

0 commit comments

Comments
 (0)