1
1
//! This module contains functions to generate default trait impl function bodies where possible.
2
2
3
3
use hir:: TraitRef ;
4
- use syntax:: {
5
- ast:: { self , AstNode , BinaryOp , CmpOp , HasName , LogicOp , edit:: AstNodeEdit , make} ,
6
- ted,
7
- } ;
4
+ use syntax:: ast:: { self , AstNode , BinaryOp , CmpOp , HasName , LogicOp , edit:: AstNodeEdit , make} ;
8
5
9
6
/// Generate custom trait bodies without default implementation where possible.
10
7
///
@@ -18,21 +15,33 @@ pub(crate) fn gen_trait_fn_body(
18
15
trait_path : & ast:: Path ,
19
16
adt : & ast:: Adt ,
20
17
trait_ref : Option < TraitRef < ' _ > > ,
21
- ) -> Option < ( ) > {
18
+ ) -> Option < ast:: BlockExpr > {
19
+ let _ = func. body ( ) ?;
22
20
match trait_path. segment ( ) ?. name_ref ( ) ?. text ( ) . as_str ( ) {
23
- "Clone" => gen_clone_impl ( adt, func) ,
24
- "Debug" => gen_debug_impl ( adt, func) ,
25
- "Default" => gen_default_impl ( adt, func) ,
26
- "Hash" => gen_hash_impl ( adt, func) ,
27
- "PartialEq" => gen_partial_eq ( adt, func, trait_ref) ,
28
- "PartialOrd" => gen_partial_ord ( adt, func, trait_ref) ,
21
+ "Clone" => {
22
+ stdx:: always!( func. name( ) . is_some_and( |name| name. text( ) == "clone" ) ) ;
23
+ gen_clone_impl ( adt)
24
+ }
25
+ "Debug" => gen_debug_impl ( adt) ,
26
+ "Default" => gen_default_impl ( adt) ,
27
+ "Hash" => {
28
+ stdx:: always!( func. name( ) . is_some_and( |name| name. text( ) == "hash" ) ) ;
29
+ gen_hash_impl ( adt)
30
+ }
31
+ "PartialEq" => {
32
+ stdx:: always!( func. name( ) . is_some_and( |name| name. text( ) == "eq" ) ) ;
33
+ gen_partial_eq ( adt, trait_ref)
34
+ }
35
+ "PartialOrd" => {
36
+ stdx:: always!( func. name( ) . is_some_and( |name| name. text( ) == "partial_cmp" ) ) ;
37
+ gen_partial_ord ( adt, trait_ref)
38
+ }
29
39
_ => None ,
30
40
}
31
41
}
32
42
33
43
/// Generate a `Clone` impl based on the fields and members of the target type.
34
- fn gen_clone_impl ( adt : & ast:: Adt , func : & ast:: Fn ) -> Option < ( ) > {
35
- stdx:: always!( func. name( ) . is_some_and( |name| name. text( ) == "clone" ) ) ;
44
+ fn gen_clone_impl ( adt : & ast:: Adt ) -> Option < ast:: BlockExpr > {
36
45
fn gen_clone_call ( target : ast:: Expr ) -> ast:: Expr {
37
46
let method = make:: name_ref ( "clone" ) ;
38
47
make:: expr_method_call ( target, method, make:: arg_list ( None ) ) . into ( )
@@ -139,12 +148,11 @@ fn gen_clone_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
139
148
}
140
149
} ;
141
150
let body = make:: block_expr ( None , Some ( expr) ) . indent ( ast:: edit:: IndentLevel ( 1 ) ) ;
142
- ted:: replace ( func. body ( ) ?. syntax ( ) , body. syntax ( ) ) ;
143
- Some ( ( ) )
151
+ Some ( body)
144
152
}
145
153
146
154
/// Generate a `Debug` impl based on the fields and members of the target type.
147
- fn gen_debug_impl ( adt : & ast:: Adt , func : & ast :: Fn ) -> Option < ( ) > {
155
+ fn gen_debug_impl ( adt : & ast:: Adt ) -> Option < ast :: BlockExpr > {
148
156
let annotated_name = adt. name ( ) ?;
149
157
match adt {
150
158
// `Debug` cannot be derived for unions, so no default impl can be provided.
@@ -248,8 +256,7 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
248
256
249
257
let body = make:: block_expr ( None , Some ( match_expr. into ( ) ) ) ;
250
258
let body = body. indent ( ast:: edit:: IndentLevel ( 1 ) ) ;
251
- ted:: replace ( func. body ( ) ?. syntax ( ) , body. syntax ( ) ) ;
252
- Some ( ( ) )
259
+ Some ( body)
253
260
}
254
261
255
262
ast:: Adt :: Struct ( strukt) => {
@@ -296,14 +303,13 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
296
303
let method = make:: name_ref ( "finish" ) ;
297
304
let expr = make:: expr_method_call ( expr, method, make:: arg_list ( None ) ) . into ( ) ;
298
305
let body = make:: block_expr ( None , Some ( expr) ) . indent ( ast:: edit:: IndentLevel ( 1 ) ) ;
299
- ted:: replace ( func. body ( ) ?. syntax ( ) , body. syntax ( ) ) ;
300
- Some ( ( ) )
306
+ Some ( body)
301
307
}
302
308
}
303
309
}
304
310
305
311
/// Generate a `Debug` impl based on the fields and members of the target type.
306
- fn gen_default_impl ( adt : & ast:: Adt , func : & ast :: Fn ) -> Option < ( ) > {
312
+ fn gen_default_impl ( adt : & ast:: Adt ) -> Option < ast :: BlockExpr > {
307
313
fn gen_default_call ( ) -> Option < ast:: Expr > {
308
314
let fn_name = make:: ext:: path_from_idents ( [ "Default" , "default" ] ) ?;
309
315
Some ( make:: expr_call ( make:: expr_path ( fn_name) , make:: arg_list ( None ) ) . into ( ) )
@@ -342,15 +348,13 @@ fn gen_default_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
342
348
}
343
349
} ;
344
350
let body = make:: block_expr ( None , Some ( expr) ) . indent ( ast:: edit:: IndentLevel ( 1 ) ) ;
345
- ted:: replace ( func. body ( ) ?. syntax ( ) , body. syntax ( ) ) ;
346
- Some ( ( ) )
351
+ Some ( body)
347
352
}
348
353
}
349
354
}
350
355
351
356
/// Generate a `Hash` impl based on the fields and members of the target type.
352
- fn gen_hash_impl ( adt : & ast:: Adt , func : & ast:: Fn ) -> Option < ( ) > {
353
- stdx:: always!( func. name( ) . is_some_and( |name| name. text( ) == "hash" ) ) ;
357
+ fn gen_hash_impl ( adt : & ast:: Adt ) -> Option < ast:: BlockExpr > {
354
358
fn gen_hash_call ( target : ast:: Expr ) -> ast:: Stmt {
355
359
let method = make:: name_ref ( "hash" ) ;
356
360
let arg = make:: expr_path ( make:: ext:: ident_path ( "state" ) ) ;
@@ -400,13 +404,11 @@ fn gen_hash_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
400
404
} ,
401
405
} ;
402
406
403
- ted:: replace ( func. body ( ) ?. syntax ( ) , body. syntax ( ) ) ;
404
- Some ( ( ) )
407
+ Some ( body)
405
408
}
406
409
407
410
/// Generate a `PartialEq` impl based on the fields and members of the target type.
408
- fn gen_partial_eq ( adt : & ast:: Adt , func : & ast:: Fn , trait_ref : Option < TraitRef < ' _ > > ) -> Option < ( ) > {
409
- stdx:: always!( func. name( ) . is_some_and( |name| name. text( ) == "eq" ) ) ;
411
+ fn gen_partial_eq ( adt : & ast:: Adt , trait_ref : Option < TraitRef < ' _ > > ) -> Option < ast:: BlockExpr > {
410
412
fn gen_eq_chain ( expr : Option < ast:: Expr > , cmp : ast:: Expr ) -> Option < ast:: Expr > {
411
413
match expr {
412
414
Some ( expr) => Some ( make:: expr_bin_op ( expr, BinaryOp :: LogicOp ( LogicOp :: And ) , cmp) ) ,
@@ -595,12 +597,10 @@ fn gen_partial_eq(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef<'_>
595
597
} ,
596
598
} ;
597
599
598
- ted:: replace ( func. body ( ) ?. syntax ( ) , body. syntax ( ) ) ;
599
- Some ( ( ) )
600
+ Some ( body)
600
601
}
601
602
602
- fn gen_partial_ord ( adt : & ast:: Adt , func : & ast:: Fn , trait_ref : Option < TraitRef < ' _ > > ) -> Option < ( ) > {
603
- stdx:: always!( func. name( ) . is_some_and( |name| name. text( ) == "partial_cmp" ) ) ;
603
+ fn gen_partial_ord ( adt : & ast:: Adt , trait_ref : Option < TraitRef < ' _ > > ) -> Option < ast:: BlockExpr > {
604
604
fn gen_partial_eq_match ( match_target : ast:: Expr ) -> Option < ast:: Stmt > {
605
605
let mut arms = vec ! [ ] ;
606
606
@@ -686,8 +686,7 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef<'_
686
686
} ,
687
687
} ;
688
688
689
- ted:: replace ( func. body ( ) ?. syntax ( ) , body. syntax ( ) ) ;
690
- Some ( ( ) )
689
+ Some ( body)
691
690
}
692
691
693
692
fn make_discriminant ( ) -> Option < ast:: Expr > {
0 commit comments