Skip to content

Commit aa34915

Browse files
authored
Unrolled build for rust-lang#138042
Rollup merge of rust-lang#138042 - xizheyin:issue-135759, r=nnethercote Suggest struct or union to add generic that impls trait Fixes rust-lang#135759 cc ```@tdittr```
2 parents c53af1c + 7e199b1 commit aa34915

File tree

3 files changed

+142
-2
lines changed

3 files changed

+142
-2
lines changed

compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs

+61-2
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
8484
rustc_errors::struct_span_code_err!(self.dcx(), self_ty.span, E0782, "{}", msg);
8585
if self_ty.span.can_be_used_for_suggestions()
8686
&& !self.maybe_suggest_impl_trait(self_ty, &mut diag)
87+
&& !self.maybe_suggest_dyn_trait(self_ty, label, sugg, &mut diag)
8788
{
88-
// FIXME: Only emit this suggestion if the trait is dyn-compatible.
89-
diag.multipart_suggestion_verbose(label, sugg, Applicability::MachineApplicable);
89+
self.maybe_suggest_add_generic_impl_trait(self_ty, &mut diag);
9090
}
9191
// Check if the impl trait that we are considering is an impl of a local trait.
9292
self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag);
@@ -123,6 +123,33 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
123123
}
124124
}
125125

126+
fn maybe_suggest_add_generic_impl_trait(
127+
&self,
128+
self_ty: &hir::Ty<'_>,
129+
diag: &mut Diag<'_>,
130+
) -> bool {
131+
let tcx = self.tcx();
132+
let msg = "you might be missing a type parameter";
133+
let mut sugg = vec![];
134+
135+
let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
136+
let parent_item = tcx.hir_node_by_def_id(parent_id).expect_item();
137+
match parent_item.kind {
138+
hir::ItemKind::Struct(_, generics) | hir::ItemKind::Enum(_, generics) => {
139+
sugg.push((
140+
generics.where_clause_span,
141+
format!(
142+
"<T: {}>",
143+
self.tcx().sess.source_map().span_to_snippet(self_ty.span).unwrap()
144+
),
145+
));
146+
sugg.push((self_ty.span, "T".to_string()));
147+
}
148+
_ => {}
149+
}
150+
diag.multipart_suggestion_verbose(msg, sugg, Applicability::MachineApplicable);
151+
true
152+
}
126153
/// Make sure that we are in the condition to suggest the blanket implementation.
127154
fn maybe_suggest_blanket_trait_impl<G: EmissionGuarantee>(
128155
&self,
@@ -171,6 +198,38 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
171198
}
172199
}
173200

201+
fn maybe_suggest_dyn_trait(
202+
&self,
203+
self_ty: &hir::Ty<'_>,
204+
label: &str,
205+
sugg: Vec<(Span, String)>,
206+
diag: &mut Diag<'_>,
207+
) -> bool {
208+
let tcx = self.tcx();
209+
let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
210+
let parent_item = tcx.hir_node_by_def_id(parent_id).expect_item();
211+
212+
// If the parent item is an enum, don't suggest the dyn trait.
213+
if let hir::ItemKind::Enum(..) = parent_item.kind {
214+
return false;
215+
}
216+
217+
// If the parent item is a struct, check if self_ty is the last field.
218+
if let hir::ItemKind::Struct(variant_data, _) = parent_item.kind {
219+
if variant_data.fields().last().unwrap().ty.span != self_ty.span {
220+
return false;
221+
}
222+
}
223+
224+
// FIXME: Only emit this suggestion if the trait is dyn-compatible.
225+
diag.multipart_suggestion_verbose(
226+
label.to_string(),
227+
sugg,
228+
Applicability::MachineApplicable,
229+
);
230+
true
231+
}
232+
174233
fn add_generic_param_suggestion(
175234
&self,
176235
generics: &hir::Generics<'_>,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
//@ edition:2021
2+
trait Trait {}
3+
4+
struct Foo1 {
5+
a: Trait,
6+
//~^ ERROR expected a type, found a trait
7+
b: u32,
8+
}
9+
10+
struct Foo2 {
11+
a: i32,
12+
b: Trait,
13+
//~^ ERROR expected a type, found a trait
14+
}
15+
16+
17+
enum Enum1 {
18+
A(Trait),
19+
//~^ ERROR expected a type, found a trait
20+
B(u32),
21+
}
22+
23+
enum Enum2 {
24+
A(u32),
25+
B(Trait),
26+
//~^ ERROR expected a type, found a trait
27+
}
28+
29+
30+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
error[E0782]: expected a type, found a trait
2+
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:5:8
3+
|
4+
LL | a: Trait,
5+
| ^^^^^
6+
|
7+
help: you might be missing a type parameter
8+
|
9+
LL ~ struct Foo1<T: Trait> {
10+
LL ~ a: T,
11+
|
12+
13+
error[E0782]: expected a type, found a trait
14+
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:12:8
15+
|
16+
LL | b: Trait,
17+
| ^^^^^
18+
|
19+
help: you can add the `dyn` keyword if you want a trait object
20+
|
21+
LL | b: dyn Trait,
22+
| +++
23+
24+
error[E0782]: expected a type, found a trait
25+
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:18:7
26+
|
27+
LL | A(Trait),
28+
| ^^^^^
29+
|
30+
help: you might be missing a type parameter
31+
|
32+
LL ~ enum Enum1<T: Trait> {
33+
LL ~ A(T),
34+
|
35+
36+
error[E0782]: expected a type, found a trait
37+
--> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:25:7
38+
|
39+
LL | B(Trait),
40+
| ^^^^^
41+
|
42+
help: you might be missing a type parameter
43+
|
44+
LL ~ enum Enum2<T: Trait> {
45+
LL | A(u32),
46+
LL ~ B(T),
47+
|
48+
49+
error: aborting due to 4 previous errors
50+
51+
For more information about this error, try `rustc --explain E0782`.

0 commit comments

Comments
 (0)