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