@@ -169,7 +169,7 @@ fn impl_def_from_trait(
169
169
170
170
// Generate a default `impl` function body for the derived trait.
171
171
if let ast:: AssocItem :: Fn ( ref func) = first_assoc_item {
172
- let _ = gen_default_impl ( func, trait_path, adt, annotated_name) ;
172
+ let _ = gen_trait_body_impl ( func, trait_path, adt, annotated_name) ;
173
173
} ;
174
174
175
175
Some ( ( impl_def, first_assoc_item) )
@@ -180,23 +180,24 @@ fn impl_def_from_trait(
180
180
/// Returns `Option` so that we can use `?` rather than `if let Some`. Returning
181
181
/// `None` means that generating a custom trait body failed, and the body will remain
182
182
/// as `todo!` instead.
183
- fn gen_default_impl (
183
+ fn gen_trait_body_impl (
184
184
func : & ast:: Fn ,
185
185
trait_path : & ast:: Path ,
186
186
adt : & ast:: Adt ,
187
187
annotated_name : & ast:: Name ,
188
188
) -> Option < ( ) > {
189
189
match trait_path. segment ( ) ?. name_ref ( ) ?. text ( ) . as_str ( ) {
190
190
"Debug" => gen_debug_impl ( adt, func, annotated_name) ,
191
- _ => Some ( ( ) ) ,
191
+ "Default" => gen_default_impl ( adt, func) ,
192
+ _ => None ,
192
193
}
193
194
}
194
195
195
196
/// Generate a `Debug` impl based on the fields and members of the target type.
196
197
fn gen_debug_impl ( adt : & ast:: Adt , func : & ast:: Fn , annotated_name : & ast:: Name ) -> Option < ( ) > {
197
198
match adt {
198
199
// `Debug` cannot be derived for unions, so no default impl can be provided.
199
- ast:: Adt :: Union ( _) => Some ( ( ) ) ,
200
+ ast:: Adt :: Union ( _) => None ,
200
201
201
202
// => match self { Self::Variant => write!(f, "Variant") }
202
203
ast:: Adt :: Enum ( enum_) => {
@@ -276,6 +277,50 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn, annotated_name: &ast::Name) ->
276
277
}
277
278
}
278
279
280
+ /// Generate a `Debug` impl based on the fields and members of the target type.
281
+ fn gen_default_impl ( adt : & ast:: Adt , func : & ast:: Fn ) -> Option < ( ) > {
282
+ fn gen_default_call ( ) -> ast:: Expr {
283
+ let trait_name = make:: ext:: ident_path ( "Default" ) ;
284
+ let method_name = make:: ext:: ident_path ( "default" ) ;
285
+ let fn_name = make:: expr_path ( make:: path_concat ( trait_name, method_name) ) ;
286
+ make:: expr_call ( fn_name, make:: arg_list ( None ) )
287
+ }
288
+ match adt {
289
+ // `Debug` cannot be derived for unions, so no default impl can be provided.
290
+ ast:: Adt :: Union ( _) => None ,
291
+ // Deriving `Debug` for enums is not stable yet.
292
+ ast:: Adt :: Enum ( _) => None ,
293
+ ast:: Adt :: Struct ( strukt) => {
294
+ let expr = match strukt. field_list ( ) {
295
+ Some ( ast:: FieldList :: RecordFieldList ( field_list) ) => {
296
+ let mut fields = vec ! [ ] ;
297
+ for field in field_list. fields ( ) {
298
+ let method_call = gen_default_call ( ) ;
299
+ let name_ref = make:: name_ref ( & field. name ( ) ?. to_string ( ) ) ;
300
+ let field = make:: record_expr_field ( name_ref, Some ( method_call) ) ;
301
+ fields. push ( field) ;
302
+ }
303
+ let struct_name = make:: ext:: ident_path ( "Self" ) ;
304
+ let fields = make:: record_expr_field_list ( fields) ;
305
+ make:: record_expr ( struct_name, fields) . into ( )
306
+ }
307
+ Some ( ast:: FieldList :: TupleFieldList ( field_list) ) => {
308
+ let struct_name = make:: expr_path ( make:: ext:: ident_path ( "Self" ) ) ;
309
+ let fields = field_list. fields ( ) . map ( |_| gen_default_call ( ) ) ;
310
+ make:: expr_call ( struct_name, make:: arg_list ( fields) )
311
+ }
312
+ None => {
313
+ let struct_name = make:: ext:: ident_path ( "Self" ) ;
314
+ let fields = make:: record_expr_field_list ( None ) ;
315
+ make:: record_expr ( struct_name, fields) . into ( )
316
+ }
317
+ } ;
318
+ let body = make:: block_expr ( None , Some ( expr) ) . indent ( ast:: edit:: IndentLevel ( 1 ) ) ;
319
+ ted:: replace ( func. body ( ) ?. syntax ( ) , body. clone_for_update ( ) . syntax ( ) ) ;
320
+ Some ( ( ) )
321
+ }
322
+ }
323
+ }
279
324
fn update_attribute (
280
325
builder : & mut AssistBuilder ,
281
326
input : & ast:: TokenTree ,
@@ -405,6 +450,70 @@ impl core::fmt::Debug for Foo {
405
450
}
406
451
}
407
452
}
453
+ "# ,
454
+ )
455
+ }
456
+ #[ test]
457
+ fn add_custom_impl_default_record_struct ( ) {
458
+ check_assist (
459
+ replace_derive_with_manual_impl,
460
+ r#"
461
+ //- minicore: default
462
+ #[derive(Defau$0lt)]
463
+ struct Foo {
464
+ foo: usize,
465
+ }
466
+ "# ,
467
+ r#"
468
+ struct Foo {
469
+ foo: usize,
470
+ }
471
+
472
+ impl Default for Foo {
473
+ $0fn default() -> Self {
474
+ Self { foo: Default::default() }
475
+ }
476
+ }
477
+ "# ,
478
+ )
479
+ }
480
+ #[ test]
481
+ fn add_custom_impl_default_tuple_struct ( ) {
482
+ check_assist (
483
+ replace_derive_with_manual_impl,
484
+ r#"
485
+ //- minicore: default
486
+ #[derive(Defau$0lt)]
487
+ struct Foo(usize);
488
+ "# ,
489
+ r#"
490
+ struct Foo(usize);
491
+
492
+ impl Default for Foo {
493
+ $0fn default() -> Self {
494
+ Self(Default::default())
495
+ }
496
+ }
497
+ "# ,
498
+ )
499
+ }
500
+ #[ test]
501
+ fn add_custom_impl_default_empty_struct ( ) {
502
+ check_assist (
503
+ replace_derive_with_manual_impl,
504
+ r#"
505
+ //- minicore: default
506
+ #[derive(Defau$0lt)]
507
+ struct Foo;
508
+ "# ,
509
+ r#"
510
+ struct Foo;
511
+
512
+ impl Default for Foo {
513
+ $0fn default() -> Self {
514
+ Self { }
515
+ }
516
+ }
408
517
"# ,
409
518
)
410
519
}
0 commit comments