Skip to content

Commit db81a08

Browse files
authored
Backport PR #19010: Type relations cache: Add a failsafe in case of infinite types (#19022)
1 parent 855cb1d commit db81a08

File tree

2 files changed

+23
-6
lines changed

2 files changed

+23
-6
lines changed

src/Compiler/Checking/TypeRelations.fs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,12 @@ type CanCoerce =
2828
[<Struct; NoComparison>]
2929
type TTypeCacheKey =
3030
| TTypeCacheKey of TypeStructure * TypeStructure * CanCoerce
31-
static member FromStrippedTypes(ty1, ty2, canCoerce) =
32-
TTypeCacheKey(getTypeStructure ty1, getTypeStructure ty2, canCoerce)
31+
static member TryGetFromStrippedTypes(ty1, ty2, canCoerce) =
32+
let t1, t2 = getTypeStructure ty1, getTypeStructure ty2
33+
if t1.IsPossiblyInfinite || t2.IsPossiblyInfinite then
34+
ValueNone
35+
else
36+
ValueSome (TTypeCacheKey(t1, t2, canCoerce))
3337

3438
let getTypeSubsumptionCache =
3539
let factory (g: TcGlobals) =
@@ -157,8 +161,10 @@ let rec TypeFeasiblySubsumesType ndeep (g: TcGlobals) (amap: ImportMap) m (ty1:
157161
List.exists (TypeFeasiblySubsumesType (ndeep + 1) g amap m ty1 NoCoerce) interfaces
158162

159163
if g.langVersion.SupportsFeature LanguageFeature.UseTypeSubsumptionCache then
160-
let key = TTypeCacheKey.FromStrippedTypes(ty1, ty2, canCoerce)
161-
(getTypeSubsumptionCache g).GetOrAdd(key, fun _ -> checkSubsumes ty1 ty2)
164+
match TTypeCacheKey.TryGetFromStrippedTypes(ty1, ty2, canCoerce) with
165+
| ValueSome key ->
166+
(getTypeSubsumptionCache g).GetOrAdd(key, fun _ -> checkSubsumes ty1 ty2)
167+
| _ -> checkSubsumes ty1 ty2
162168
else
163169
checkSubsumes ty1 ty2
164170

src/Compiler/Utilities/TypeHashing.fs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,9 @@ module StructuralUtilities =
401401
| MeasureRational of int * int
402402
| NeverEqual of never: NeverEqual
403403

404-
type TypeStructure = TypeStructure of ImmutableArray<TypeToken>
404+
type TypeStructure =
405+
| TypeStructure of TypeToken[]
406+
| PossiblyInfinite of never: NeverEqual
405407

406408
let inline toNullnessToken (n: Nullness) =
407409
match n.TryEvaluate() with
@@ -464,6 +466,15 @@ module StructuralUtilities =
464466
| TType_measure m -> yield! accumulateMeasure m
465467
}
466468

469+
// If the sequence got too long, just drop it, we could be dealing with an infinite type.
470+
let private toTypeStructure tokens =
471+
let tokens = tokens |> Seq.truncate 256 |> Array.ofSeq
472+
473+
if tokens.Length = 256 then
474+
PossiblyInfinite NeverEqual.Singleton
475+
else
476+
TypeStructure tokens
477+
467478
/// Get the full structure of a type as a sequence of tokens, suitable for equality
468479
let getTypeStructure =
469-
Extras.WeakMap.getOrCreate (fun ty -> accumulateTType ty |> ImmutableArray.ofSeq |> TypeStructure)
480+
Extras.WeakMap.getOrCreate (fun ty -> accumulateTType ty |> toTypeStructure)

0 commit comments

Comments
 (0)