@@ -633,6 +633,15 @@ impl BsnType {
633633 return Ok ( quote ! { #( #type_assigns) * } ) ;
634634 }
635635
636+ if let Some ( value @ ( BsnValue :: Ident ( _)
637+ | BsnValue :: Expr ( _)
638+ | BsnValue :: Closure ( _)
639+ | BsnValue :: Tuple ( _) ) ) = value
640+ {
641+ let ident = ctx. hoisted_expressions . hoist ( value) ;
642+ return Ok ( quote ! { * #bind_name = #ident; } ) ;
643+ }
644+
636645 // NOTE: It is very important to still produce outputs for None field values. This is what
637646 // enables field autocomplete in Rust Analyzer
638647 value
@@ -995,6 +1004,52 @@ mod tests {
9951004 . contains( "Duplicate field `x` found in BSN enum variant" ) ) ;
9961005 }
9971006
1007+ #[ test]
1008+ fn enum_variant_expr_is_hoisted ( ) {
1009+ let mut refs = EntityRefs :: default ( ) ;
1010+ let paths = TestPaths :: new ( ) ;
1011+ let mut exprs = HoistedExpressions :: default ( ) ;
1012+ let mut ctx = paths. ctx ( & mut refs, & mut exprs) ;
1013+ let mut assignments = vec ! [ ] ;
1014+ let handle = BsnType {
1015+ path : parse_quote ! ( FontSourceTemplate ) ,
1016+ enum_variant : Some ( parse_quote ! ( Handle ) ) ,
1017+ fields : BsnFields :: Tuple ( vec ! [ BsnUnnamedField {
1018+ value: BsnValue :: Expr ( quote!( some_borrow. clone( ) ) ) ,
1019+ } ] ) ,
1020+ } ;
1021+
1022+ let res = handle. push_enum_patch (
1023+ & mut ctx,
1024+ & parse_quote ! ( Handle ) ,
1025+ & mut assignments,
1026+ PatchTarget {
1027+ path : & [ ] ,
1028+ is_ref : false ,
1029+ } ,
1030+ ) ;
1031+
1032+ assert ! ( res. is_ok( ) ) ;
1033+ assert_eq ! ( ctx. errors. len( ) , 0 ) ;
1034+ assert_eq ! ( exprs. expressions. len( ) , 1 ) ;
1035+ assert_eq ! (
1036+ exprs. expressions[ 0 ] . to_string( ) ,
1037+ "let _expr0 = { some_borrow . clone () } . into () ;"
1038+ ) ;
1039+ let assignment_output: String = assignments
1040+ . iter ( )
1041+ . map ( |t| t. to_string ( ) )
1042+ . collect ( ) ;
1043+ assert ! (
1044+ assignment_output. contains( "_expr0" ) ,
1045+ "expected hoisted ident in assignment output: {assignment_output}"
1046+ ) ;
1047+ assert ! (
1048+ !assignment_output. contains( "some_borrow" ) ,
1049+ "borrow should not appear inline in assignment output: {assignment_output}"
1050+ ) ;
1051+ }
1052+
9981053 #[ test]
9991054 fn bsn_root_preserves_inference_on_error ( ) {
10001055 // Arrange
0 commit comments