@@ -379,17 +379,6 @@ module HashTastMemberOrVals =
379379///
380380/// </summary>
381381module StructuralUtilities =
382- [<Struct; CustomEquality; NoComparison>]
383- type NeverEqual =
384- struct
385- interface System.IEquatable< NeverEqual> with
386- member _.Equals _ = false
387-
388- override _.Equals _ = false
389- override _.GetHashCode () = 0
390- end
391-
392- static member Singleton = NeverEqual()
393382
394383 [<Struct; NoComparison; RequireQualifiedAccess>]
395384 type TypeToken =
@@ -399,16 +388,17 @@ module StructuralUtilities =
399388 | TupInfo of b : bool
400389 | MeasureOne
401390 | MeasureRational of int * int
402- | NeverEqual of never : NeverEqual
391+ | Unsolved
403392
404393 type TypeStructure =
405394 | TypeStructure of TypeToken []
406- | PossiblyInfinite of never : NeverEqual
395+ | UnsolvedTypeStructure of TypeToken []
396+ | PossiblyInfinite
407397
408398 let inline toNullnessToken ( n : Nullness ) =
409399 match n.TryEvaluate() with
410400 | ValueSome k -> TypeToken.Nullness k
411- | _ -> TypeToken.NeverEqual NeverEqual.Singleton
401+ | _ -> TypeToken.Unsolved
412402
413403 let rec private accumulateMeasure ( m : Measure ) =
414404 seq {
@@ -425,7 +415,14 @@ module StructuralUtilities =
425415 TypeToken.MeasureRational( GetNumerator r, GetDenominator r)
426416 }
427417
428- let rec private accumulateTType ( ty : TType ) =
418+ let rec private accumulateTypar ( typar : Typar ) =
419+ seq {
420+ match typar.Solution with
421+ | Some ty -> yield ! accumulateTType ty
422+ | None -> TypeToken.Unsolved
423+ }
424+
425+ and private accumulateTType ( ty : TType ) =
429426 seq {
430427 match ty with
431428 | TType_ ucase( u, tinst) ->
@@ -441,40 +438,55 @@ module StructuralUtilities =
441438
442439 for arg in tinst do
443440 yield ! accumulateTType arg
441+
444442 | TType_ anon( info, tys) ->
445443 TypeToken.Stamp info.Stamp
446444
447445 for arg in tys do
448446 yield ! accumulateTType arg
447+
449448 | TType_ tuple( tupInfo, tys) ->
450449 TypeToken.TupInfo( evalTupInfoIsStruct tupInfo)
451450
452451 for arg in tys do
453452 yield ! accumulateTType arg
453+
454454 | TType_ forall( tps, tau) ->
455455 for tp in tps do
456- TypeToken.Stamp tp.Stamp
456+ yield ! accumulateTypar tp
457457
458458 yield ! accumulateTType tau
459+
459460 | TType_ fun( d, r, n) ->
460461 yield ! accumulateTType d
461462 yield ! accumulateTType r
462463 toNullnessToken n
464+
463465 | TType_ var( r, n) ->
464- TypeToken.Stamp r.Stamp
465466 toNullnessToken n
467+ yield ! accumulateTypar r
468+
466469 | TType_ measure m -> yield ! accumulateMeasure m
467470 }
468471
469472 // 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
473+ let private toTypeStructure ( tokens : TypeToken seq ) =
474+ let tokens = tokens |> Seq.truncate 256 |> Seq.toArray
472475
473- if tokens.Length = 256 then
474- PossiblyInfinite NeverEqual.Singleton
476+ if Seq.length tokens = 256 then
477+ PossiblyInfinite
478+ elif tokens |> Array.exists _. IsUnsolved then
479+ UnsolvedTypeStructure tokens
475480 else
476481 TypeStructure tokens
477482
478483 /// Get the full structure of a type as a sequence of tokens, suitable for equality
479484 let getTypeStructure =
480- Extras.WeakMap.getOrCreate ( fun ty -> accumulateTType ty |> toTypeStructure)
485+ let shouldCache =
486+ function
487+ | PossiblyInfinite
488+ | UnsolvedTypeStructure _ -> false
489+ | _ -> true
490+
491+ // Speed up repeated calls by caching results for types that yield a stable structure.
492+ Extras.WeakMap.cacheConditionally shouldCache ( fun ty -> accumulateTType ty |> toTypeStructure)
0 commit comments