@@ -955,8 +955,12 @@ let AdjustValSynInfoInSignature g ty (SynValInfo(argsData, retData) as sigMD) =
955
955
| _ ->
956
956
sigMD
957
957
958
+ let getArgInfoCache =
959
+ let options = Caches.CacheOptions.getDefault() |> Caches.CacheOptions.withNoEviction
960
+ let factory _ = new Caches.Cache<_, ArgReprInfo>(options, "argInfoCache")
961
+ WeakMap.getOrCreate factory
958
962
959
- let TranslateTopArgSynInfo ( cenv: cenv) isArg m tcAttributes (SynArgInfo(Attributes attrs, isOpt, nm)) =
963
+ let TranslateTopArgSynInfo cenv isArg m tcAttributes (SynArgInfo(Attributes attrs, isOpt, nm)) =
960
964
// Synthesize an artificial "OptionalArgument" attribute for the parameter
961
965
let optAttrs =
962
966
if isOpt then
@@ -977,20 +981,14 @@ let TranslateTopArgSynInfo (cenv: cenv) isArg m tcAttributes (SynArgInfo(Attribu
977
981
// Call the attribute checking function
978
982
let attribs = tcAttributes (optAttrs@attrs)
979
983
980
- let key = nm |> Option.map (fun id -> id.idText, id.idRange)
984
+ let key = nm |> Option.map (fun id -> (id.idText, id.idRange))
985
+
986
+ let mkDefaultArgInfo _ : ArgReprInfo = { Attribs = attribs; Name = nm; OtherRange = None }
981
987
982
988
let argInfo =
983
- key
984
- |> Option.map cenv.argInfoCache.TryGetValue
985
- |> Option.bind (fun (found, info) ->
986
- if found then
987
- Some info
988
- else None)
989
- |> Option.defaultValue ({ Attribs = attribs; Name = nm; OtherRange = None }: ArgReprInfo)
990
-
991
- match key with
992
- | Some k -> cenv.argInfoCache.[k] <- argInfo
993
- | None -> ()
989
+ match key with
990
+ | Some key -> (getArgInfoCache cenv).GetOrAdd(key, mkDefaultArgInfo)
991
+ | _ -> mkDefaultArgInfo ()
994
992
995
993
// Set freshly computed attribs in case they are different in the cache
996
994
argInfo.Attribs <- attribs
@@ -4051,6 +4049,13 @@ type ImplicitlyBoundTyparsAllowed =
4051
4049
| NewTyparsOK
4052
4050
| NoNewTypars
4053
4051
4052
+ // In order to avoid checking implicit-yield expressions multiple times, we cache the resulting checked expressions.
4053
+ // This avoids exponential behavior in the type checker when nesting implicit-yield expressions.
4054
+ let getImplicitYieldExpressionsCache =
4055
+ let options = Caches.CacheOptions.getReferenceIdentity() |> Caches.CacheOptions.withNoEviction
4056
+ let factory _ = new Caches.Cache<SynExpr, _>(options, "implicitYieldExpressions")
4057
+ WeakMap.getOrCreate factory
4058
+
4054
4059
//-------------------------------------------------------------------------
4055
4060
// Checking types and type constraints
4056
4061
//-------------------------------------------------------------------------
@@ -5503,19 +5508,12 @@ and CheckForAdjacentListExpression (cenv: cenv) synExpr hpa isInfix delayed (arg
5503
5508
and TcExprThen (cenv: cenv) overallTy env tpenv isArg synExpr delayed =
5504
5509
let g = cenv.g
5505
5510
5506
- let cachedExpression =
5507
- env.eCachedImplicitYieldExpressions.FindAll synExpr.Range
5508
- |> List.tryPick (fun (se, ty, e) ->
5509
- if obj.ReferenceEquals(se, synExpr) then Some (ty, e) else None
5510
- )
5511
-
5512
- match cachedExpression with
5513
- | Some (ty, expr) ->
5511
+ match (getImplicitYieldExpressionsCache cenv).TryGetValue synExpr with
5512
+ | true, (ty, expr) ->
5514
5513
UnifyOverallType cenv env synExpr.Range overallTy ty
5515
5514
expr, tpenv
5516
5515
| _ ->
5517
5516
5518
-
5519
5517
match synExpr with
5520
5518
5521
5519
// A.
@@ -6378,9 +6376,8 @@ and TcExprSequentialOrImplicitYield (cenv: cenv) overallTy env tpenv (sp, synExp
6378
6376
| Expr.DebugPoint(_,e) -> e
6379
6377
| _ -> expr1
6380
6378
6381
- env.eCachedImplicitYieldExpressions.Add(synExpr1.Range, (synExpr1, expr1Ty, cachedExpr))
6382
- try TcExpr cenv overallTy env tpenv otherExpr
6383
- finally env.eCachedImplicitYieldExpressions.Remove synExpr1.Range
6379
+ (getImplicitYieldExpressionsCache cenv).AddOrUpdate(synExpr1, (expr1Ty, cachedExpr))
6380
+ TcExpr cenv overallTy env tpenv otherExpr
6384
6381
6385
6382
and TcExprStaticOptimization (cenv: cenv) overallTy env tpenv (constraints, synExpr2, expr3, m) =
6386
6383
let constraintsR, tpenv = List.mapFold (TcStaticOptimizationConstraint cenv env) tpenv constraints
0 commit comments