@@ -27,21 +27,39 @@ pub(crate) fn expand_deriving_from(
2727 cx. dcx ( ) . bug ( "derive(From) used on something else than an item" ) ;
2828 } ;
2929
30- // #[derive(From)] is currently usable only on structs with exactly one field.
31- let field = if let ItemKind :: Struct ( _, _, data) = & item. kind
32- && let [ field] = data. fields ( )
33- {
34- Some ( field. clone ( ) )
35- } else {
36- None
30+ let err_span = || {
31+ let item_span = item. kind . ident ( ) . map ( |ident| ident. span ) . unwrap_or ( item. span ) ;
32+ MultiSpan :: from_spans ( vec ! [ span, item_span] )
3733 } ;
3834
39- let from_type = match & field {
40- Some ( field) => Ty :: AstTy ( field. ty . clone ( ) ) ,
41- // We don't have a type to put into From<...> if we don't have a single field, so just put
42- // unit there.
43- None => Ty :: Unit ,
35+ // `#[derive(From)]` is currently usable only on structs with exactly one field.
36+ let field = match & item. kind {
37+ ItemKind :: Struct ( _, _, data) => {
38+ if let [ field] = data. fields ( ) {
39+ Ok ( field. clone ( ) )
40+ } else {
41+ let guar = cx. dcx ( ) . emit_err ( errors:: DeriveFromWrongFieldCount {
42+ span : err_span ( ) ,
43+ multiple_fields : data. fields ( ) . len ( ) > 1 ,
44+ } ) ;
45+ Err ( guar)
46+ }
47+ }
48+ ItemKind :: Enum ( _, _, _) | ItemKind :: Union ( _, _, _) => {
49+ let guar = cx. dcx ( ) . emit_err ( errors:: DeriveFromWrongTarget {
50+ span : err_span ( ) ,
51+ kind : & format ! ( "{} {}" , item. kind. article( ) , item. kind. descr( ) ) ,
52+ } ) ;
53+ Err ( guar)
54+ }
55+ _ => cx. dcx ( ) . bug ( "Invalid derive(From) ADT input" ) ,
4456 } ;
57+
58+ let from_type = Ty :: AstTy ( match field {
59+ Ok ( ref field) => field. ty . clone ( ) ,
60+ Err ( guar) => cx. ty ( span, ast:: TyKind :: Err ( guar) ) ,
61+ } ) ;
62+
4563 let path =
4664 Path :: new_ ( pathvec_std ! ( convert:: From ) , vec ! [ Box :: new( from_type. clone( ) ) ] , PathKind :: Std ) ;
4765
@@ -71,34 +89,17 @@ pub(crate) fn expand_deriving_from(
7189 attributes: thin_vec![ cx. attr_word( sym:: inline, span) ] ,
7290 fieldless_variants_strategy: FieldlessVariantsStrategy :: Default ,
7391 combine_substructure: combine_substructure( Box :: new( |cx, span, substructure| {
74- let Some ( field) = & field else {
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-
93- return BlockOrExpr :: new_expr( DummyResult :: raw_expr( span, Some ( error) ) ) ;
92+ let field = match field {
93+ Ok ( ref field) => field,
94+ Err ( guar) => {
95+ return BlockOrExpr :: new_expr( DummyResult :: raw_expr( span, Some ( guar) ) ) ;
96+ }
9497 } ;
9598
9699 let self_kw = Ident :: new( kw:: SelfUpper , span) ;
97100 let expr: Box <ast:: Expr > = match substructure. fields {
98101 SubstructureFields :: StaticStruct ( variant, _) => match variant {
99- // Self {
100- // field: value
101- // }
102+ // Self { field: value }
102103 VariantData :: Struct { .. } => cx. expr_struct_ident(
103104 span,
104105 self_kw,
0 commit comments