diff --git a/src/Compiler/Checking/OverloadResolutionCache.fs b/src/Compiler/Checking/OverloadResolutionCache.fs index cbf6b1aca0..995b1e5e21 100644 --- a/src/Compiler/Checking/OverloadResolutionCache.fs +++ b/src/Compiler/Checking/OverloadResolutionCache.fs @@ -83,12 +83,12 @@ let tryGetTypeStructureForOverloadCache (g: TcGlobals) (ty: TType) : TypeStructu let ty = stripTyEqns g ty match tryGetTypeStructureOfStrippedType ty with - | ValueSome(Stable tokens) -> ValueSome(Stable tokens) - | ValueSome(Unstable tokens) -> + | ValueSome(Stable(h, tokens)) -> ValueSome(Stable(h, tokens)) + | ValueSome(Unstable(h, tokens)) -> if hasUnsolvedTokens tokens then ValueNone else - ValueSome(Stable tokens) + ValueSome(Stable(h, tokens)) | ValueSome PossiblyInfinite -> ValueNone | ValueNone -> ValueNone @@ -162,8 +162,8 @@ let tryComputeOverloadCacheKey | Some retTy -> match tryGetTypeStructureForOverloadCache g retTy with | ValueSome ts -> ValueSome ts - | ValueNone -> if anyHasOutArgs then ValueNone else ValueSome(Stable [||]) - | None -> ValueSome(Stable [||]) + | ValueNone -> if anyHasOutArgs then ValueNone else ValueSome(Stable(0, [||])) + | None -> ValueSome(Stable(0, [||])) match retTyStructure with | ValueNone -> ValueNone diff --git a/src/Compiler/Utilities/TypeHashing.fs b/src/Compiler/Utilities/TypeHashing.fs index 7723e8b04d..ff4bab0a40 100644 --- a/src/Compiler/Utilities/TypeHashing.fs +++ b/src/Compiler/Utilities/TypeHashing.fs @@ -407,12 +407,35 @@ module StructuralUtilities = | Unsolved of int | Rigid of int + let private hashTokenArray (tokens: TypeToken[]) = + let mutable acc = 0 + for t in tokens do + acc <- combineHash acc (hash t) + acc + + [] type TypeStructure = - | Stable of TypeToken[] + | Stable of hash: int * tokens: TypeToken[] // Unstable means that the type structure of a given TType may change because of constraint solving or Trace.Undo. - | Unstable of TypeToken[] + | Unstable of hash: int * tokens: TypeToken[] | PossiblyInfinite + override this.GetHashCode() = + match this with + | Stable(h, _) -> h + | Unstable(h, _) -> h ||| 0x40000000 + | PossiblyInfinite -> 0 + + override this.Equals(obj) = + match obj with + | :? TypeStructure as other -> + match this, other with + | Stable(h1, a), Stable(h2, b) -> h1 = h2 && a = b + | Unstable(h1, a), Unstable(h2, b) -> h1 = h2 && a = b + | PossiblyInfinite, PossiblyInfinite -> true + | _ -> false + | _ -> false + type private GenerationContext() = member val TyparMap = System.Collections.Generic.Dictionary(4) member val Tokens = ResizeArray(MaxTokenCount) @@ -566,8 +589,11 @@ module StructuralUtilities = // If the sequence got too long, just drop it, we could be dealing with an infinite type. if out.Count >= MaxTokenCount then PossiblyInfinite - elif not ctx.Stable then Unstable(out.ToArray()) - else Stable(out.ToArray()) + else + let tokens = out.ToArray() + let h = hashTokenArray tokens + if not ctx.Stable then Unstable(h, tokens) + else Stable(h, tokens) // Speed up repeated calls by memoizing results for types that yield a stable structure. let private getTypeStructureOfStrippedType =