Skip to content

Commit ceb0401

Browse files
Fix suggestion when there are generics, inline some things
1 parent bca0ab8 commit ceb0401

File tree

3 files changed

+50
-17
lines changed

3 files changed

+50
-17
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs

+30-16
Original file line numberDiff line numberDiff line change
@@ -78,13 +78,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
7878
}
7979

8080
if self_ty.span.edition().at_least_rust_2021() {
81-
let msg = "expected a type, found a trait";
82-
let label = "you can add the `dyn` keyword if you want a trait object";
83-
let mut diag =
84-
rustc_errors::struct_span_code_err!(self.dcx(), self_ty.span, E0782, "{}", msg);
81+
let mut diag = rustc_errors::struct_span_code_err!(
82+
self.dcx(),
83+
self_ty.span,
84+
E0782,
85+
"{}",
86+
"expected a type, found a trait"
87+
);
8588
if self_ty.span.can_be_used_for_suggestions()
8689
&& !self.maybe_suggest_impl_trait(self_ty, &mut diag)
87-
&& !self.maybe_suggest_dyn_trait(self_ty, label, sugg, &mut diag)
90+
&& !self.maybe_suggest_dyn_trait(self_ty, sugg, &mut diag)
8891
{
8992
self.maybe_suggest_add_generic_impl_trait(self_ty, &mut diag);
9093
}
@@ -131,8 +134,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
131134
diag: &mut Diag<'_>,
132135
) -> bool {
133136
let tcx = self.tcx();
134-
let msg = "you might be missing a type parameter";
135-
let mut sugg = vec![];
136137

137138
let parent_hir_id = tcx.parent_hir_id(self_ty.hir_id);
138139
let parent_item = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
@@ -160,13 +161,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
160161
_ => return false,
161162
};
162163

163-
// FIXME: `T` may already be taken.
164-
sugg.push((
165-
generics.where_clause_span,
166-
format!("<T: {}>", self.tcx().sess.source_map().span_to_snippet(self_ty.span).unwrap()),
167-
));
168-
sugg.push((self_ty.span, "T".to_string()));
169-
diag.multipart_suggestion_verbose(msg, sugg, Applicability::MachineApplicable);
164+
let Ok(rendered_ty) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
165+
return false;
166+
};
167+
168+
let param = "TUV"
169+
.chars()
170+
.map(|c| c.to_string())
171+
.chain((0..).map(|i| format!("P{i}")))
172+
.find(|s| !generics.params.iter().any(|param| param.name.ident().as_str() == s))
173+
.expect("we definitely can find at least one param name to generate");
174+
let mut sugg = vec![(self_ty.span, param.to_string())];
175+
if let Some(insertion_span) = generics.span_for_param_suggestion() {
176+
sugg.push((insertion_span, format!(", {param}: {}", rendered_ty)));
177+
} else {
178+
sugg.push((generics.where_clause_span, format!("<{param}: {}>", rendered_ty)));
179+
}
180+
diag.multipart_suggestion_verbose(
181+
"you might be missing a type parameter",
182+
sugg,
183+
Applicability::MachineApplicable,
184+
);
170185
true
171186
}
172187
/// Make sure that we are in the condition to suggest the blanket implementation.
@@ -227,7 +242,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
227242
fn maybe_suggest_dyn_trait(
228243
&self,
229244
self_ty: &hir::Ty<'_>,
230-
label: &str,
231245
sugg: Vec<(Span, String)>,
232246
diag: &mut Diag<'_>,
233247
) -> bool {
@@ -270,7 +284,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
270284

271285
// FIXME: Only emit this suggestion if the trait is dyn-compatible.
272286
diag.multipart_suggestion_verbose(
273-
label.to_string(),
287+
"you can add the `dyn` keyword if you want a trait object",
274288
sugg,
275289
Applicability::MachineApplicable,
276290
);

tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.rs

+7
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,11 @@ where
3131
Trait:, {}
3232
//~^ ERROR expected a type, found a trait
3333

34+
struct HasGenerics<T> {
35+
f: Trait,
36+
//~^ ERROR expected a type, found a trait
37+
t: T,
38+
}
39+
40+
3441
fn main() {}

tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.stderr

+13-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@ LL | A(u32),
4646
LL ~ B(T),
4747
|
4848

49+
error[E0782]: expected a type, found a trait
50+
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:35:8
51+
|
52+
LL | f: Trait,
53+
| ^^^^^
54+
|
55+
help: you might be missing a type parameter
56+
|
57+
LL ~ struct HasGenerics<T, U: Trait> {
58+
LL ~ f: U,
59+
|
60+
4961
error[E0782]: expected a type, found a trait
5062
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:31:5
5163
|
@@ -57,6 +69,6 @@ help: you can add the `dyn` keyword if you want a trait object
5769
LL | dyn Trait:, {}
5870
| +++
5971

60-
error: aborting due to 5 previous errors
72+
error: aborting due to 6 previous errors
6173

6274
For more information about this error, try `rustc --explain E0782`.

0 commit comments

Comments
 (0)