Skip to content

Commit eef2856

Browse files
committed
Add machine-applicable suggestions
This avoids the need for tools like rust-analyzer to implement these suggestions themselves.
1 parent c70147f commit eef2856

File tree

1 file changed

+42
-8
lines changed
  • compiler/rustc_builtin_macros/src/deriving

1 file changed

+42
-8
lines changed

compiler/rustc_builtin_macros/src/deriving/default.rs

+42-8
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,52 @@ fn extract_default_variant<'a>(
132132
let variant = match default_variants.as_slice() {
133133
[variant] => variant,
134134
[] => {
135-
cx.struct_span_err(trait_span, "no default declared")
136-
.help("make a unit variant default by placing `#[default]` above it")
137-
.emit();
135+
let possible_defaults = enum_def
136+
.variants
137+
.iter()
138+
.filter(|variant| matches!(variant.data, VariantData::Unit(..)))
139+
.filter(|variant| !cx.sess.contains_name(&variant.attrs, sym::non_exhaustive));
140+
141+
let mut diag = cx.struct_span_err(trait_span, "no default declared");
142+
diag.help("make a unit variant default by placing `#[default]` above it");
143+
for variant in possible_defaults {
144+
// Suggest making each unit variant default.
145+
diag.tool_only_span_suggestion(
146+
variant.span,
147+
&format!("make `{}` default", variant.ident),
148+
format!("#[default] {}", variant.ident),
149+
Applicability::MaybeIncorrect,
150+
);
151+
}
152+
diag.emit();
138153

139154
return Err(());
140155
}
141156
[first, rest @ ..] => {
142-
cx.struct_span_err(trait_span, "multiple declared defaults")
143-
.span_label(first.span, "first default")
144-
.span_labels(rest.iter().map(|variant| variant.span), "additional default")
145-
.note("only one variant can be default")
146-
.emit();
157+
let mut diag = cx.struct_span_err(trait_span, "multiple declared defaults");
158+
diag.span_label(first.span, "first default");
159+
diag.span_labels(rest.iter().map(|variant| variant.span), "additional default");
160+
diag.note("only one variant can be default");
161+
for variant in &default_variants {
162+
// Suggest making each variant already tagged default.
163+
let suggestion = default_variants
164+
.iter()
165+
.filter_map(|v| {
166+
if v.ident == variant.ident {
167+
None
168+
} else {
169+
Some((cx.sess.find_by_name(&v.attrs, kw::Default)?.span, String::new()))
170+
}
171+
})
172+
.collect();
173+
174+
diag.tool_only_multipart_suggestion(
175+
&format!("make `{}` default", variant.ident),
176+
suggestion,
177+
Applicability::MaybeIncorrect,
178+
);
179+
}
180+
diag.emit();
147181

148182
return Err(());
149183
}

0 commit comments

Comments
 (0)