Skip to content

Commit ced09df

Browse files
authored
Fix type subsumption cache key perf regression (#18926)
1 parent 9749fb3 commit ced09df

File tree

2 files changed

+61
-59
lines changed

2 files changed

+61
-59
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
* Parser: fix range for computed binding expressions ([PR #18903](https://github.com/dotnet/fsharp/pull/18903))
3333
* Tests: set test source for range debug printing ([PR #18879](https://github.com/dotnet/fsharp/pull/18879))
3434
* Checker: fix declaring type for abbreviated types extensions ([PR #18909](https://github.com/dotnet/fsharp/pull/18909))
35+
* Caches: type subsumption cache key perf regression ([Issue #18925](https://github.com/dotnet/fsharp/issues/18925) [PR #18926](https://github.com/dotnet/fsharp/pull/18926))
3536

3637
### Changed
3738
* Use `errorR` instead of `error` in `CheckDeclarations.fs` when possible. ([PR #18645](https://github.com/dotnet/fsharp/pull/18645))

src/Compiler/Utilities/TypeHashing.fs

Lines changed: 60 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module internal Internal.Utilities.TypeHashing
22

33
open Internal.Utilities.Rational
4+
open Internal.Utilities.Library
45
open FSharp.Compiler.AbstractIL.IL
56
open FSharp.Compiler.Syntax
67
open FSharp.Compiler.TcGlobals
@@ -397,72 +398,72 @@ module StructuralUtilities =
397398
| Nullness of nullness: NullnessInfo
398399
| TupInfo of b: bool
399400
| MeasureOne
400-
| MeasureRational of rational: Rational
401+
| MeasureRational of int * int
401402
| NeverEqual of never: NeverEqual
402403

403-
type TypeStructure = TypeToken[]
404-
405-
[<Literal>]
406-
let private initialTokenCapacity = 4
404+
type TypeStructure = TypeStructure of ImmutableArray<TypeToken>
407405

408406
let inline toNullnessToken (n: Nullness) =
409407
match n.TryEvaluate() with
410408
| ValueSome k -> TypeToken.Nullness k
411409
| _ -> TypeToken.NeverEqual NeverEqual.Singleton
412410

413-
let rec private accumulateMeasure (tokens: ResizeArray<TypeToken>) (m: Measure) =
414-
match m with
415-
| Measure.Var mv -> tokens.Add(TypeToken.Stamp mv.Stamp)
416-
| Measure.Const(tcref, _) -> tokens.Add(TypeToken.Stamp tcref.Stamp)
417-
| Measure.Prod(m1, m2, _) ->
418-
accumulateMeasure tokens m1
419-
accumulateMeasure tokens m2
420-
| Measure.Inv m1 -> accumulateMeasure tokens m1
421-
| Measure.One _ -> tokens.Add(TypeToken.MeasureOne)
422-
| Measure.RationalPower(m1, r) ->
423-
accumulateMeasure tokens m1
424-
tokens.Add(TypeToken.MeasureRational r)
425-
426-
let rec private accumulateTType (tokens: ResizeArray<TypeToken>) (ty: TType) =
427-
match ty with
428-
| TType_ucase(u, tinst) ->
429-
tokens.Add(TypeToken.Stamp u.TyconRef.Stamp)
430-
tokens.Add(TypeToken.UCase u.CaseName)
431-
432-
for arg in tinst do
433-
accumulateTType tokens arg
434-
| TType_app(tcref, tinst, n) ->
435-
tokens.Add(TypeToken.Stamp tcref.Stamp)
436-
tokens.Add(toNullnessToken n)
437-
438-
for arg in tinst do
439-
accumulateTType tokens arg
440-
| TType_anon(info, tys) ->
441-
tokens.Add(TypeToken.Stamp info.Stamp)
442-
443-
for arg in tys do
444-
accumulateTType tokens arg
445-
| TType_tuple(tupInfo, tys) ->
446-
tokens.Add(TypeToken.TupInfo(evalTupInfoIsStruct tupInfo))
447-
448-
for arg in tys do
449-
accumulateTType tokens arg
450-
| TType_forall(tps, tau) ->
451-
for tp in tps do
452-
tokens.Add(TypeToken.Stamp tp.Stamp)
453-
454-
accumulateTType tokens tau
455-
| TType_fun(d, r, n) ->
456-
accumulateTType tokens d
457-
accumulateTType tokens r
458-
tokens.Add(toNullnessToken n)
459-
| TType_var(r, n) ->
460-
tokens.Add(TypeToken.Stamp r.Stamp)
461-
tokens.Add(toNullnessToken n)
462-
| TType_measure m -> accumulateMeasure tokens m
411+
let rec private accumulateMeasure (m: Measure) =
412+
seq {
413+
match m with
414+
| Measure.Var mv -> TypeToken.Stamp mv.Stamp
415+
| Measure.Const(tcref, _) -> TypeToken.Stamp tcref.Stamp
416+
| Measure.Prod(m1, m2, _) ->
417+
yield! accumulateMeasure m1
418+
yield! accumulateMeasure m2
419+
| Measure.Inv m1 -> yield! accumulateMeasure m1
420+
| Measure.One _ -> TypeToken.MeasureOne
421+
| Measure.RationalPower(m1, r) ->
422+
yield! accumulateMeasure m1
423+
TypeToken.MeasureRational(GetNumerator r, GetDenominator r)
424+
}
425+
426+
let rec private accumulateTType (ty: TType) =
427+
seq {
428+
match ty with
429+
| TType_ucase(u, tinst) ->
430+
TypeToken.Stamp u.TyconRef.Stamp
431+
TypeToken.UCase u.CaseName
432+
433+
for arg in tinst do
434+
yield! accumulateTType arg
435+
436+
| TType_app(tcref, tinst, n) ->
437+
TypeToken.Stamp tcref.Stamp
438+
toNullnessToken n
439+
440+
for arg in tinst do
441+
yield! accumulateTType arg
442+
| TType_anon(info, tys) ->
443+
TypeToken.Stamp info.Stamp
444+
445+
for arg in tys do
446+
yield! accumulateTType arg
447+
| TType_tuple(tupInfo, tys) ->
448+
TypeToken.TupInfo(evalTupInfoIsStruct tupInfo)
449+
450+
for arg in tys do
451+
yield! accumulateTType arg
452+
| TType_forall(tps, tau) ->
453+
for tp in tps do
454+
TypeToken.Stamp tp.Stamp
455+
456+
yield! accumulateTType tau
457+
| TType_fun(d, r, n) ->
458+
yield! accumulateTType d
459+
yield! accumulateTType r
460+
toNullnessToken n
461+
| TType_var(r, n) ->
462+
TypeToken.Stamp r.Stamp
463+
toNullnessToken n
464+
| TType_measure m -> yield! accumulateMeasure m
465+
}
463466

464467
/// Get the full structure of a type as a sequence of tokens, suitable for equality
465-
let getTypeStructure ty =
466-
let tokens = ResizeArray<TypeToken>(initialTokenCapacity)
467-
accumulateTType tokens ty
468-
tokens.ToArray()
468+
let getTypeStructure =
469+
Extras.WeakMap.getOrCreate (fun ty -> accumulateTType ty |> ImmutableArray.ofSeq |> TypeStructure)

0 commit comments

Comments
 (0)