Skip to content

Commit 5b910af

Browse files
authored
Bugfix :: Fix optimizer bug where field.Index included compiler generated static fields (#18280)
* Fix optimizer bug where field.Index included compiler generated static fields * notes added
1 parent 58560f8 commit 5b910af

File tree

4 files changed

+40
-5
lines changed

4 files changed

+40
-5
lines changed

docs/release-notes/.FSharp.Compiler.Service/9.0.300.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
### Fixed
22
* Fix Realsig+ generates nested closures with incorrect Generic ([Issue #17797](https://github.com/dotnet/fsharp/issues/17797), [PR #17877](https://github.com/dotnet/fsharp/pull/17877))
3+
* Fix optimizer internal error for records with static fields ([Issue #18165](https://github.com/dotnet/fsharp/issues/18165), [PR #18280](https://github.com/dotnet/fsharp/pull/18280))
34
* Fix internal error when missing measure attribute in an unsolved measure typar. ([Issue #7491](https://github.com/dotnet/fsharp/issues/7491), [PR #18234](https://github.com/dotnet/fsharp/pull/18234)==
45
* Set `Cancellable.token` from async computation ([Issue #18235](https://github.com/dotnet/fsharp/issues/18235), [PR #18238](https://github.com/dotnet/fsharp/pull/18238))
56
* Cancellable: only cancel on OCE with own token ([PR #18277](https://github.com/dotnet/fsharp/pull/18277))

src/Compiler/TypedTree/TypedTree.fs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4273,6 +4273,19 @@ type UnionCaseRef =
42734273

42744274
override x.ToString() = x.CaseName
42754275

4276+
let findLogicalFieldIndexOfRecordField (tcref:TyconRef) (id:string) =
4277+
let arr = tcref.AllFieldsArray
4278+
4279+
// We are skipping compiler generated fields such as "init@5" from index calculation
4280+
let rec go originalIdx skippedItems =
4281+
if originalIdx >= arr.Length then error(InternalError(sprintf "field %s not found in type %s" id tcref.LogicalName, tcref.Range))
4282+
else
4283+
let currentItem = arr[originalIdx]
4284+
if currentItem.LogicalName = id then (originalIdx-skippedItems)
4285+
else go (originalIdx + 1) (skippedItems + (if currentItem.IsCompilerGenerated && currentItem.IsStatic then 1 else 0))
4286+
4287+
go 0 0
4288+
42764289
/// Represents a reference to a field in a record, class or struct
42774290
[<NoEquality; NoComparison; StructuredFormatDisplay("{DebugText}")>]
42784291
type RecdFieldRef =
@@ -4316,11 +4329,8 @@ type RecdFieldRef =
43164329

43174330
member x.Index =
43184331
let (RecdFieldRef(tcref, id)) = x
4319-
try
4320-
// REVIEW: this could be faster, e.g. by storing the index in the NameMap
4321-
tcref.AllFieldsArray |> Array.findIndex (fun rfspec -> rfspec.LogicalName = id)
4322-
with :? KeyNotFoundException ->
4323-
error(InternalError(sprintf "field %s not found in type %s" id tcref.LogicalName, tcref.Range))
4332+
findLogicalFieldIndexOfRecordField tcref id
4333+
43244334

43254335
[<DebuggerBrowsable(DebuggerBrowsableState.Never)>]
43264336
member x.DebugText = x.ToString()
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
module Test
2+
3+
// https://github.com/dotnet/fsharp/issues/18165
4+
5+
type FooBar =
6+
{ xyz : string }
7+
static let staticLet = 1
8+
9+
let doThing (foo : FooBar) =
10+
let bar = { foo with xyz = foo.xyz }
11+
let baz = { bar with xyz = bar.xyz }
12+
printf "%O" baz
13+
14+
doThing { xyz = "" }

tests/FSharp.Compiler.ComponentTests/Conformance/BasicGrammarElements/StaticLet/StaticLetInUnionsAndRecords.fs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,16 @@ init R 2
9595
1
9696
2"""
9797

98+
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"RecordOptimizerRegression.fs"|])>]
99+
let ``Static let - record optimizer regression`` compilation =
100+
compilation
101+
|> withOptimize
102+
|> verifyCompileAndRun
103+
|> shouldSucceed
104+
|> withStdOutContains """{ xyz = "" }"""
105+
106+
107+
98108
[<Theory; Directory(__SOURCE_DIRECTORY__, Includes=[|"LowercaseDuTest.fs"|])>]
99109
let ``Static let - lowercase DU`` compilation =
100110
compilation

0 commit comments

Comments
 (0)