1
1
use rustc_ast as ast;
2
2
use rustc_ast:: { ItemKind , VariantData } ;
3
+ use rustc_errors:: MultiSpan ;
3
4
use rustc_expand:: base:: { Annotatable , DummyResult , ExtCtxt } ;
4
5
use rustc_span:: { Ident , Span , kw, sym} ;
5
6
use thin_vec:: thin_vec;
@@ -18,17 +19,18 @@ pub(crate) fn expand_deriving_from(
18
19
cx : & ExtCtxt < ' _ > ,
19
20
span : Span ,
20
21
mitem : & ast:: MetaItem ,
21
- item : & Annotatable ,
22
+ annotatable : & Annotatable ,
22
23
push : & mut dyn FnMut ( Annotatable ) ,
23
24
is_const : bool ,
24
25
) {
26
+ let Annotatable :: Item ( item) = & annotatable else {
27
+ cx. dcx ( ) . bug ( "derive(From) used on something else than an item" ) ;
28
+ } ;
29
+
25
30
// #[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 ( ) ) ,
32
34
_ => None ,
33
35
} ,
34
36
_ => None ,
@@ -70,7 +72,24 @@ pub(crate) fn expand_deriving_from(
70
72
fieldless_variants_strategy: FieldlessVariantsStrategy :: Default ,
71
73
combine_substructure: combine_substructure( Box :: new( |cx, span, substructure| {
72
74
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
+
74
93
return BlockOrExpr :: new_expr( DummyResult :: raw_expr( span, Some ( error) ) ) ;
75
94
} ;
76
95
@@ -109,5 +128,5 @@ pub(crate) fn expand_deriving_from(
109
128
is_staged_api_crate : cx. ecfg . features . staged_api ( ) ,
110
129
} ;
111
130
112
- from_trait_def. expand ( cx, mitem, item , push) ;
131
+ from_trait_def. expand ( cx, mitem, annotatable , push) ;
113
132
}
0 commit comments