Skip to content

Commit 62612a5

Browse files
dbrattliclaude
andauthored
fix(all): duplicate LetRec bindings during inline expansion (#4592)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 6e78058 commit 62612a5

2 files changed

Lines changed: 23 additions & 1 deletion

File tree

src/Fable.Transforms/FSharp2Fable.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2227,7 +2227,7 @@ let resolveInlineExpr (com: IFableCompiler) ctx info expr =
22272227

22282228
| Fable.LetRec(bindings, b) ->
22292229
let ctx, bindings =
2230-
((ctx, bindings), bindings)
2230+
((ctx, []), bindings)
22312231
||> List.fold (fun (ctx, bindings) (i, e) ->
22322232
let i = resolveInlineIdent ctx info i
22332233
let e = resolveInlineExpr com ctx info e

tests/Beam/NonRegressionTests.fs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,3 +142,25 @@ let ``test string StartsWith char from tuple element`` () =
142142
let pair = (1, 'H')
143143
let result = "Hello".StartsWith(snd pair)
144144
equal true result
145+
146+
// Inline outer + nested non-inline helper + innermost `let rec ... and ...`
147+
// referencing an outer-scope capture: the inliner used to emit each binding
148+
// twice, with the first (unresolved) copy losing the capture.
149+
module IssueInlineMutualRec =
150+
let inline outer<'T> (capture: int) =
151+
let inner () =
152+
let rec a () =
153+
if capture = 0 then
154+
"ok"
155+
else
156+
b ()
157+
158+
and b () = a () + "!"
159+
160+
a ()
161+
162+
inner ()
163+
164+
[<Fact>]
165+
let ``test inline outer with nested mutual recursion captures outer scope`` () =
166+
IssueInlineMutualRec.outer<int> 0 |> equal "ok"

0 commit comments

Comments
 (0)