Skip to content

Commit a28e007

Browse files
authored
Merge branch 'main' into repo-assist/codescan-interpolated-strings-1128-1143-1517-1518-380ff3b7c73331e7
2 parents bf17116 + 3564e8a commit a28e007

5 files changed

Lines changed: 53 additions & 5 deletions

File tree

src/Fable.Cli/CHANGELOG.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Fixed
1111

12-
* [Rust] Add type format specifiers to interpolated strings in Fable2Rust.fs (code scanning alerts #1128#1143)
13-
* [All] Add type format specifiers to interpolated strings in Fable.Compiler/Util.fs (code scanning alerts #1517#1518)
12+
* [All] Fix captured side-effect-free values (e.g. empty ResizeArray) being incorrectly inlined into object expression getters in release mode, causing a new instance to be created on each getter call (fixes #3779) (by @MangelMaxime)
1413
* [Python] Fix missing `await` on else branch of ternary expressions in async closures (by @dbrattli)
1514
* [Beam] Fix `|> ignore` on cross-module Emit calls generating variable bindings that shadow Emit case-clause variables (by @dbrattli)
1615
* [Beam] Fix `containsIdentRef` not checking `Call` ThisArg (by @dbrattli)

src/Fable.Compiler/CHANGELOG.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
99

1010
### Fixed
1111

12-
* [Rust] Add type format specifiers to interpolated strings in Fable2Rust.fs (code scanning alerts #1128#1143)
13-
* [All] Add type format specifiers to interpolated strings in Fable.Compiler/Util.fs (code scanning alerts #1517#1518)
12+
* [All] Fix captured side-effect-free values (e.g. empty ResizeArray) being incorrectly inlined into object expression getters in release mode, causing a new instance to be created on each getter call (fixes #3779) (by @MangelMaxime)
1413
* [Python] Fix missing `await` on else branch of ternary expressions in async closures (by @dbrattli)
1514
* [Beam] Fix `|> ignore` on cross-module Emit calls generating variable bindings that shadow Emit case-clause variables (by @dbrattli)
1615
* [Beam] Fix `containsIdentRef` not checking `Call` ThisArg (by @dbrattli)

src/Fable.Transforms/FableTransforms.fs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,22 @@ let canInlineArg (com: Compiler) identName value body =
242242
| _ ->
243243
let refCount = countReferencesUntil 2 identName body
244244

245-
(refCount <= 1 && not (canHaveSideEffects com value))
245+
// Don't inline values that create new mutable state (e.g. ResizeArray(), mutable arrays)
246+
// into closures: even though creation is side-effect-free, inlining into a closure
247+
// called multiple times would create a new instance per call instead of sharing the
248+
// single captured instance
249+
let createsMutableState =
250+
match value with
251+
| Value(NewArray(_, _, kind), _) ->
252+
match kind with
253+
| MutableArray
254+
| ResizeArray -> true
255+
| ImmutableArray -> false
256+
| _ -> false
257+
258+
(refCount <= 1
259+
&& not (canHaveSideEffects com value)
260+
&& not (createsMutableState && isIdentCaptured identName body))
246261
// If it can have side effects, make sure is at least referenced once so the expression is not erased
247262
|| (refCount = 1
248263
&& noSideEffectBeforeIdent identName body

tests/Js/Main/TypeTests.fs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,10 @@ type MangledAbstractClass5(v) =
657657
inherit MangledAbstractClass4(v + 5)
658658
override _.MyMethod(x: int) = base.MyMethod(x) + v + 7
659659

660+
[<AbstractClass>]
661+
type AbstractClassWithResizeArrayProp() =
662+
abstract Warnings: ResizeArray<string> with get
663+
660664
type ConcreteClass1() =
661665
inherit MangledAbstractClass5(2)
662666

@@ -1621,4 +1625,17 @@ let tests =
16211625
top.A |> equal 0
16221626
top.B.A |> equal 0
16231627
top.B.B |> equal false
1628+
1629+
testCase "Abstract class property backed by captured variable in object expression works" <| fun () ->
1630+
let warnings = ResizeArray<string>()
1631+
1632+
let reader =
1633+
{ new AbstractClassWithResizeArrayProp() with
1634+
member __.Warnings = warnings
1635+
}
1636+
1637+
reader.Warnings.Add("Warning 1")
1638+
reader.Warnings.Add("Warning 2")
1639+
1640+
reader.Warnings.Count |> equal 2
16241641
]

tests/Python/TestType.fs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,10 @@ type MangledAbstractClass5(v) =
577577
inherit MangledAbstractClass4(v + 5)
578578
override _.MyMethod(x: int) = base.MyMethod(x) + v + 7
579579

580+
[<AbstractClass>]
581+
type AbstractClassWithResizeArrayProp() =
582+
abstract Warnings: ResizeArray<string> with get
583+
580584
type ConcreteClass1() =
581585
inherit MangledAbstractClass5(2)
582586

@@ -1776,3 +1780,17 @@ let ``test Unchecked.defaultof works for fields on structs`` () =
17761780
top.A |> equal 0
17771781
top.B.A |> equal 0
17781782
top.B.B |> equal false
1783+
1784+
[<Fact>]
1785+
let ``test Abstract class property backed by captured variable in object expression works`` () =
1786+
let warnings = ResizeArray<string>()
1787+
1788+
let reader =
1789+
{ new AbstractClassWithResizeArrayProp() with
1790+
member __.Warnings = warnings
1791+
}
1792+
1793+
reader.Warnings.Add("Warning 1")
1794+
reader.Warnings.Add("Warning 2")
1795+
1796+
reader.Warnings.Count |> equal 2

0 commit comments

Comments
 (0)