@@ -1109,19 +1109,36 @@ let transformCall (com: IPythonCompiler) ctx range callee (callInfo: Fable.CallI
11091109let transformCurriedApply com ctx range ( TransformExpr com ctx ( applied , stmts )) args =
11101110 (( applied, stmts), args)
11111111 ||> List.fold ( fun ( applied , stmts ) arg ->
1112- let args , stmts' =
1112+ let args , argStmts =
11131113 match arg with
11141114 // TODO: If arg type is unit but it's an expression with potential
11151115 // side-effects, we need to extract it and execute it before the call
11161116
11171117 // TODO: discardUnitArg may still be needed in some cases
11181118 | Fable.Value( Fable.UnitConstant, _) -> [], []
11191119 | Fable.IdentExpr ident when ident.Type = Fable.Unit -> [], []
1120- | TransformExpr com ctx ( arg, stmts') -> [ arg ], stmts'
1120+ | arg ->
1121+ let argExpr , transformStmts = com.TransformAsExpr( ctx, arg)
1122+ // When a Call or CurriedApply result is passed as an argument,
1123+ // check if we need to erase Option[T] to T | None
1124+ let argExpr =
1125+ if needsOptionEraseForBinding arg arg.Type then
1126+ wrapInOptionErase com ctx argExpr
1127+ else
1128+ argExpr
1129+
1130+ [ argExpr ], transformStmts
11211131
1122- callFunction range applied args [], stmts @ stmts'
1132+ callFunction range applied args [], stmts @ argStmts
11231133 )
11241134
1135+ /// Extract the expected return type from a return strategy, unwrapping ResourceManager if needed
1136+ let rec private getExpectedReturnType ( strategy : ReturnStrategy option ) =
1137+ match strategy with
1138+ | Some( Return( Some expectedType)) -> Some expectedType
1139+ | Some( ResourceManager inner) -> getExpectedReturnType inner
1140+ | _ -> None
1141+
11251142let transformCallAsStatements com ctx range t returnStrategy callee callInfo =
11261143 let argsLen ( i : Fable.CallInfo ) =
11271144 List.length i.Args
@@ -1141,17 +1158,18 @@ let transformCallAsStatements com ctx range t returnStrategy callee callInfo =
11411158 | _ ->
11421159 let expr , stmts = transformCall com ctx range callee callInfo
11431160 // Check if we need to cast Option[T] to T | None for return statements
1161+ // Also handles ResourceManager-wrapped return strategies (e.g., inside `with` blocks)
11441162 let expr =
1145- match returnStrategy with
1146- | Some( Return ( Some expectedType)) ->
1163+ match getExpectedReturnType returnStrategy with
1164+ | Some expectedType ->
11471165 // Create a temporary Fable.Call to check if erase is needed
11481166 let callExpr = Fable.Call( callee, callInfo, t, range)
11491167
11501168 if needsOptionEraseForReturn callExpr expectedType then
11511169 wrapInOptionErase com ctx expr
11521170 else
11531171 expr
1154- | _ -> expr
1172+ | None -> expr
11551173
11561174 stmts @ ( expr |> resolveExpr ctx t returnStrategy)
11571175
@@ -3996,7 +4014,14 @@ let transformUnion (com: IPythonCompiler) ctx (ent: Fable.Entity) (entName: stri
39964014 // Convert to snake_case and clean to remove invalid characters like apostrophes
39974015 // Handles: "Item" -> "item", "Item1" -> "item1", "MyField" -> "my_field"
39984016 let fieldName = field.Name |> Naming.toSnakeCase |> Helpers.clean
3999- let ta , _ = Annotation.typeAnnotation com caseCtx None field.FieldType
4017+ // Uncurry lambda types for field annotations since union case fields
4018+ // store uncurried functions at runtime (same as record fields)
4019+ let fieldType =
4020+ match field.FieldType with
4021+ | Fable.LambdaType _ -> FableTransforms.uncurryType field.FieldType
4022+ | _ -> field.FieldType
4023+
4024+ let ta , _ = Annotation.typeAnnotation com caseCtx None fieldType
40004025 let target = Expression.name ( fieldName, Store)
40014026 // Use annAssign to generate: field: type (not field = type)
40024027 Statement.annAssign ( target, annotation = ta, simple = true )
@@ -4763,6 +4788,12 @@ let rec transformDeclaration (com: IPythonCompiler) ctx (decl: Fable.Declaration
47634788 let value , stmts = transformAsExpr com ctx decl.Body
47644789 let name = com.GetIdentifier( ctx, Naming.toPythonNaming decl.Name)
47654790 let ta , _ = Annotation.typeAnnotation com ctx None decl.Body.Type
4791+ // Erase Option wrapper if needed (Call/CurriedApply returning Option[T] to T | None)
4792+ let value =
4793+ if needsOptionEraseForBinding decl.Body decl.Body.Type then
4794+ wrapInOptionErase com ctx value
4795+ else
4796+ value
47664797
47674798 stmts @ declareModuleMember com ctx info.IsPublic name ( Some ta) value
47684799 else
0 commit comments