Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Fable.Cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

* [Python] Fix function references passed as arguments inside tail-call optimised functions gaining unnecessary default parameters for outer TCO variables they don't reference (fix #3877)
* [TS] Fix abstract instance methods not emitted in TypeScript when class uses `[<AttachMembers>]` (fixes #3506) (by @MangelMaxime)
* [JS/TS] Fix `Unchecked.defaultof<'T>` for struct types with fields returning `undefined` instead of zero-initialized values (by @MangelMaxime)
* [JS/TS] Fixed quotation for union string cases (by @MangelMaxime)
Expand Down
1 change: 1 addition & 0 deletions src/Fable.Compiler/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Fixed

* [Python] Fix function references passed as arguments inside tail-call optimised functions gaining unnecessary default parameters for outer TCO variables they don't reference (fix #3877)
* [TS] Fix abstract instance methods not emitted in TypeScript when class uses `[<AttachMembers>]` (fixes #3506) (by @MangelMaxime)
* [JS/TS] Fix `Unchecked.defaultof<'T>` for struct types with fields returning `undefined` instead of zero-initialized values (by @MangelMaxime)
* [JS/TS] Fixed quotation for union string cases (by @MangelMaxime)
Expand Down
4 changes: 4 additions & 0 deletions src/Fable.Transforms/Python/Fable2Python.Transforms.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3005,6 +3005,10 @@ let transformFunction

match name with
| "tupled_arg_m" -> None // Remove these arguments (not sure why)
// Only capture TCO variables actually referenced in the function body.
// This avoids unnecessary default parameters on nested lambdas that don't
// use the outer TCO variables. See #3877.
| _ when not (isIdentUsed name body) -> None
| _ ->
let annotation =
// Cleanup type annotations to avoid non-repeated generics
Expand Down
14 changes: 14 additions & 0 deletions tests/Python/TestTailCall.fs
Original file line number Diff line number Diff line change
Expand Up @@ -292,3 +292,17 @@ let ``test Expressiones captured in a closure don't change after tail-call optim

main init view update
accValue |> equal 10

// See https://github.com/fable-compiler/Fable/issues/3877
[<Fact>]
let ``test Passing a function reference in a TCO context does not capture unneeded outer args`` () =
let applyFn (f: unit -> int) = f()
let alwaysFortyTwo () = 42

// `alwaysFortyTwo` doesn't reference `_unused`, so it should not capture it
// even though `loop` is tail-call optimised with `_unused` in scope.
let rec loop (_unused: string) acc n =
if n <= 0 then acc
else loop _unused (acc + applyFn alwaysFortyTwo) (n - 1)

loop "ignored" 0 5 |> equal 210
Loading