Skip to content

Commit d7ed32b

Browse files
committed
Suggest struct or union to add generic that impls trait
Signed-off-by: xizheyin <xizheyin@smail.nju.edu.cn>
1 parent 2010bba commit d7ed32b

File tree

1 file changed

+61
-2
lines changed
  • compiler/rustc_hir_analysis/src/hir_ty_lowering

1 file changed

+61
-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<'_>,

0 commit comments

Comments
 (0)