11//! This module contains functions to generate default trait impl function bodies where possible.
22
33use 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} ;
85
96/// Generate custom trait bodies without default implementation where possible.
107///
@@ -18,21 +15,33 @@ pub(crate) fn gen_trait_fn_body(
1815 trait_path : & ast:: Path ,
1916 adt : & ast:: Adt ,
2017 trait_ref : Option < TraitRef < ' _ > > ,
21- ) -> Option < ( ) > {
18+ ) -> Option < ast:: BlockExpr > {
19+ let _ = func. body ( ) ?;
2220 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+ }
2939 _ => None ,
3040 }
3141}
3242
3343/// 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 > {
3645 fn gen_clone_call ( target : ast:: Expr ) -> ast:: Expr {
3746 let method = make:: name_ref ( "clone" ) ;
3847 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<()> {
139148 }
140149 } ;
141150 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)
144152}
145153
146154/// 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 > {
148156 let annotated_name = adt. name ( ) ?;
149157 match adt {
150158 // `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<()> {
248256
249257 let body = make:: block_expr ( None , Some ( match_expr. into ( ) ) ) ;
250258 let body = body. indent ( ast:: edit:: IndentLevel ( 1 ) ) ;
251- ted:: replace ( func. body ( ) ?. syntax ( ) , body. syntax ( ) ) ;
252- Some ( ( ) )
259+ Some ( body)
253260 }
254261
255262 ast:: Adt :: Struct ( strukt) => {
@@ -296,14 +303,13 @@ fn gen_debug_impl(adt: &ast::Adt, func: &ast::Fn) -> Option<()> {
296303 let method = make:: name_ref ( "finish" ) ;
297304 let expr = make:: expr_method_call ( expr, method, make:: arg_list ( None ) ) . into ( ) ;
298305 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)
301307 }
302308 }
303309}
304310
305311/// 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 > {
307313 fn gen_default_call ( ) -> Option < ast:: Expr > {
308314 let fn_name = make:: ext:: path_from_idents ( [ "Default" , "default" ] ) ?;
309315 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<()> {
342348 }
343349 } ;
344350 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)
347352 }
348353 }
349354}
350355
351356/// 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 > {
354358 fn gen_hash_call ( target : ast:: Expr ) -> ast:: Stmt {
355359 let method = make:: name_ref ( "hash" ) ;
356360 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<()> {
400404 } ,
401405 } ;
402406
403- ted:: replace ( func. body ( ) ?. syntax ( ) , body. syntax ( ) ) ;
404- Some ( ( ) )
407+ Some ( body)
405408}
406409
407410/// 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 > {
410412 fn gen_eq_chain ( expr : Option < ast:: Expr > , cmp : ast:: Expr ) -> Option < ast:: Expr > {
411413 match expr {
412414 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<'_>
595597 } ,
596598 } ;
597599
598- ted:: replace ( func. body ( ) ?. syntax ( ) , body. syntax ( ) ) ;
599- Some ( ( ) )
600+ Some ( body)
600601}
601602
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 > {
604604 fn gen_partial_eq_match ( match_target : ast:: Expr ) -> Option < ast:: Stmt > {
605605 let mut arms = vec ! [ ] ;
606606
@@ -686,8 +686,7 @@ fn gen_partial_ord(adt: &ast::Adt, func: &ast::Fn, trait_ref: Option<TraitRef<'_
686686 } ,
687687 } ;
688688
689- ted:: replace ( func. body ( ) ?. syntax ( ) , body. syntax ( ) ) ;
690- Some ( ( ) )
689+ Some ( body)
691690}
692691
693692fn make_discriminant ( ) -> Option < ast:: Expr > {
0 commit comments