Skip to content

Commit 3b095e2

Browse files
committed
Improve error message
1 parent a0cd3c6 commit 3b095e2

File tree

3 files changed

+50
-13
lines changed

3 files changed

+50
-13
lines changed

compiler/rustc_builtin_macros/messages.ftl

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,14 @@ builtin_macros_format_unused_args = multiple unused formatting arguments
222222
223223
builtin_macros_format_use_positional = consider using a positional formatting argument instead
224224
225-
builtin_macros_from_wrong_target = `#[derive(From)]` can only be used on structs with a single field
225+
builtin_macros_derive_from_wrong_target = `#[derive(From)]` used on {$kind}
226+
227+
builtin_macros_derive_from_wrong_field_count = `#[derive(From)]` used on a struct with {$multiple_fields ->
228+
[true] multiple fields
229+
*[false] no fields
230+
}
231+
232+
builtin_macros_derive_from_usage_note = `#[derive(From)]` can only be used on structs with exactly one field
226233
227234
builtin_macros_multiple_default_attrs = multiple `#[default]` attributes
228235
.note = only one `#[default]` attribute is needed

compiler/rustc_builtin_macros/src/deriving/from.rs

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use rustc_ast as ast;
22
use rustc_ast::{ItemKind, VariantData};
3+
use rustc_errors::MultiSpan;
34
use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
45
use rustc_span::{Ident, Span, kw, sym};
56
use thin_vec::thin_vec;
@@ -18,17 +19,18 @@ pub(crate) fn expand_deriving_from(
1819
cx: &ExtCtxt<'_>,
1920
span: Span,
2021
mitem: &ast::MetaItem,
21-
item: &Annotatable,
22+
annotatable: &Annotatable,
2223
push: &mut dyn FnMut(Annotatable),
2324
is_const: bool,
2425
) {
26+
let Annotatable::Item(item) = &annotatable else {
27+
cx.dcx().bug("derive(From) used on something else than an item");
28+
};
29+
2530
// #[derive(From)] is currently usable only on structs with exactly one field.
26-
let field = match &item {
27-
Annotatable::Item(item) => match &item.kind {
28-
ItemKind::Struct(_, _, data) => match data.fields() {
29-
[field] => Some(field.clone()),
30-
_ => None,
31-
},
31+
let field = match &item.kind {
32+
ItemKind::Struct(_, _, data) => match data.fields() {
33+
[field] => Some(field.clone()),
3234
_ => None,
3335
},
3436
_ => None,
@@ -70,7 +72,24 @@ pub(crate) fn expand_deriving_from(
7072
fieldless_variants_strategy: FieldlessVariantsStrategy::Default,
7173
combine_substructure: combine_substructure(Box::new(|cx, span, substructure| {
7274
let Some(field) = &field else {
73-
let error = cx.dcx().emit_err(errors::DeriveFromWrongTarget { span });
75+
let item_span = item.kind.ident().map(|ident| ident.span).unwrap_or(item.span);
76+
let err_span = MultiSpan::from_spans(vec![span, item_span]);
77+
let error = match &item.kind {
78+
ItemKind::Struct(_, _, data) => {
79+
cx.dcx().emit_err(errors::DeriveFromWrongFieldCount {
80+
span: err_span,
81+
multiple_fields: data.fields().len() > 1,
82+
})
83+
}
84+
ItemKind::Enum(_, _, _) | ItemKind::Union(_, _, _) => {
85+
cx.dcx().emit_err(errors::DeriveFromWrongTarget {
86+
span: err_span,
87+
kind: &format!("{} {}", item.kind.article(), item.kind.descr()),
88+
})
89+
}
90+
_ => cx.dcx().bug("Invalid derive(From) ADT input"),
91+
};
92+
7493
return BlockOrExpr::new_expr(DummyResult::raw_expr(span, Some(error)));
7594
};
7695

@@ -109,5 +128,5 @@ pub(crate) fn expand_deriving_from(
109128
is_staged_api_crate: cx.ecfg.features.staged_api(),
110129
};
111130

112-
from_trait_def.expand(cx, mitem, item, push);
131+
from_trait_def.expand(cx, mitem, annotatable, push);
113132
}

compiler/rustc_builtin_macros/src/errors.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -447,10 +447,21 @@ pub(crate) struct DefaultHasArg {
447447
}
448448

449449
#[derive(Diagnostic)]
450-
#[diag(builtin_macros_from_wrong_target)]
451-
pub(crate) struct DeriveFromWrongTarget {
450+
#[diag(builtin_macros_derive_from_wrong_target)]
451+
#[note(builtin_macros_derive_from_usage_note)]
452+
pub(crate) struct DeriveFromWrongTarget<'a> {
452453
#[primary_span]
453-
pub(crate) span: Span,
454+
pub(crate) span: MultiSpan,
455+
pub(crate) kind: &'a str,
456+
}
457+
458+
#[derive(Diagnostic)]
459+
#[diag(builtin_macros_derive_from_wrong_field_count)]
460+
#[note(builtin_macros_derive_from_usage_note)]
461+
pub(crate) struct DeriveFromWrongFieldCount {
462+
#[primary_span]
463+
pub(crate) span: MultiSpan,
464+
pub(crate) multiple_fields: bool,
454465
}
455466

456467
#[derive(Diagnostic)]

0 commit comments

Comments
 (0)