diff options
| author | Jacob Pratt <jacob@jhpratt.dev> | 2021-07-12 02:26:14 -0400 |
|---|---|---|
| committer | Jacob Pratt <jacob@jhpratt.dev> | 2021-07-27 15:47:49 -0400 |
| commit | eef2856eaf63bfaa39b4a124ecc691cf9a0306e8 (patch) | |
| tree | 4c433ba1936aa3b405764c9ed5ecccab5c399ec9 /compiler | |
| parent | c70147fd66e08962ab06adf12eb6a41bc1ea7f08 (diff) | |
| download | rust-eef2856eaf63bfaa39b4a124ecc691cf9a0306e8.tar.gz rust-eef2856eaf63bfaa39b4a124ecc691cf9a0306e8.zip | |
Add machine-applicable suggestions
This avoids the need for tools like rust-analyzer to implement these suggestions themselves.
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_builtin_macros/src/deriving/default.rs | 50 |
1 files changed, 42 insertions, 8 deletions
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 7c1dc5e5365..8f672bb7d65 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -132,18 +132,52 @@ fn extract_default_variant<'a>( let variant = match default_variants.as_slice() { [variant] => variant, [] => { - cx.struct_span_err(trait_span, "no default declared") - .help("make a unit variant default by placing `#[default]` above it") - .emit(); + let possible_defaults = enum_def + .variants + .iter() + .filter(|variant| matches!(variant.data, VariantData::Unit(..))) + .filter(|variant| !cx.sess.contains_name(&variant.attrs, sym::non_exhaustive)); + + let mut diag = cx.struct_span_err(trait_span, "no default declared"); + diag.help("make a unit variant default by placing `#[default]` above it"); + for variant in possible_defaults { + // Suggest making each unit variant default. + diag.tool_only_span_suggestion( + variant.span, + &format!("make `{}` default", variant.ident), + format!("#[default] {}", variant.ident), + Applicability::MaybeIncorrect, + ); + } + diag.emit(); return Err(()); } [first, rest @ ..] => { - cx.struct_span_err(trait_span, "multiple declared defaults") - .span_label(first.span, "first default") - .span_labels(rest.iter().map(|variant| variant.span), "additional default") - .note("only one variant can be default") - .emit(); + let mut diag = cx.struct_span_err(trait_span, "multiple declared defaults"); + diag.span_label(first.span, "first default"); + diag.span_labels(rest.iter().map(|variant| variant.span), "additional default"); + diag.note("only one variant can be default"); + for variant in &default_variants { + // Suggest making each variant already tagged default. + let suggestion = default_variants + .iter() + .filter_map(|v| { + if v.ident == variant.ident { + None + } else { + Some((cx.sess.find_by_name(&v.attrs, kw::Default)?.span, String::new())) + } + }) + .collect(); + + diag.tool_only_multipart_suggestion( + &format!("make `{}` default", variant.ident), + suggestion, + Applicability::MaybeIncorrect, + ); + } + diag.emit(); return Err(()); } |
