@@ -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,14 +180,15 @@ 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
+ "Default" => gen_default_impl ( adt, func) ,
191
192
_ => Some ( ( ) ) ,
192
193
}
193
194
}
@@ -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
+ match adt {
283
+ // `Debug` cannot be derived for unions, so no default impl can be provided.
284
+ ast:: Adt :: Union ( _) => Some ( ( ) ) ,
285
+ // Deriving `Debug` for enums is not stable yet.
286
+ ast:: Adt :: Enum ( _) => Some ( ( ) ) ,
287
+ ast:: Adt :: Struct ( strukt) => {
288
+ let expr = match strukt. field_list ( ) {
289
+ Some ( ast:: FieldList :: RecordFieldList ( field_list) ) => {
290
+ let mut fields = vec ! [ ] ;
291
+ for field in field_list. fields ( ) {
292
+ let trait_name = make:: ext:: ident_path ( "Default" ) ;
293
+ let method_name = make:: ext:: ident_path ( "default" ) ;
294
+ let fn_name = make:: expr_path ( make:: path_concat ( trait_name, method_name) ) ;
295
+ let method_call = make:: expr_call ( fn_name, make:: arg_list ( None ) ) ;
296
+ let name_ref = make:: name_ref ( & field. name ( ) ?. to_string ( ) ) ;
297
+ let field = make:: record_expr_field ( name_ref, Some ( method_call) ) ;
298
+ fields. push ( field) ;
299
+ }
300
+ let struct_name = make:: ext:: ident_path ( "Self" ) ;
301
+ let fields = make:: record_expr_field_list ( fields) ;
302
+ make:: record_expr ( struct_name, fields) . into ( )
303
+ }
304
+ Some ( ast:: FieldList :: TupleFieldList ( field_list) ) => {
305
+ let mut fields = vec ! [ ] ;
306
+ for _ in field_list. fields ( ) {
307
+ let trait_name = make:: ext:: ident_path ( "Default" ) ;
308
+ let method_name = make:: ext:: ident_path ( "default" ) ;
309
+ let fn_name = make:: expr_path ( make:: path_concat ( trait_name, method_name) ) ;
310
+ let method_call = make:: expr_call ( fn_name, make:: arg_list ( None ) ) ;
311
+ fields. push ( method_call) ;
312
+ }
313
+ let struct_name = make:: expr_path ( make:: ext:: ident_path ( "Self" ) ) ;
314
+ make:: expr_call ( struct_name, make:: arg_list ( fields) )
315
+ }
316
+ None => todo ! ( ) ,
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,50 @@ 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
+ }
408
497
"# ,
409
498
)
410
499
}
0 commit comments