Skip to content

Commit 208362a

Browse files
committed
argInfo + implicit yield
1 parent 6b0f7d5 commit 208362a

File tree

4 files changed

+24
-43
lines changed

4 files changed

+24
-43
lines changed

src/Compiler/Checking/CheckBasics.fs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -243,11 +243,7 @@ type TcEnv =
243243
eLambdaArgInfos: ArgReprInfo list list
244244

245245
// Do we lay down an implicit debug point?
246-
eIsControlFlow: bool
247-
248-
// In order to avoid checking implicit-yield expressions multiple times, we cache the resulting checked expressions.
249-
// This avoids exponential behavior in the type checker when nesting implicit-yield expressions.
250-
eCachedImplicitYieldExpressions : HashMultiMap<range, SynExpr * TType * Expr>
246+
eIsControlFlow: bool
251247
}
252248

253249
member tenv.DisplayEnv = tenv.eNameResEnv.DisplayEnv
@@ -319,8 +315,6 @@ type TcFileState =
319315

320316
diagnosticOptions: FSharpDiagnosticOptions
321317

322-
argInfoCache: ConcurrentDictionary<(string * range), ArgReprInfo>
323-
324318
// forward call
325319
TcPat: WarnOnUpperFlag -> TcFileState -> TcEnv -> PrelimValReprInfo option -> TcPatValFlags -> TcPatLinearEnv -> TType -> SynPat -> (TcPatPhase2Input -> Pattern) * TcPatLinearEnv
326320

@@ -370,7 +364,6 @@ type TcFileState =
370364
conditionalDefines = conditionalDefines
371365
isInternalTestSpanStackReferring = isInternalTestSpanStackReferring
372366
diagnosticOptions = diagnosticOptions
373-
argInfoCache = ConcurrentDictionary()
374367
TcPat = tcPat
375368
TcSimplePats = tcSimplePats
376369
TcSequenceExpressionEntry = tcSequenceExpressionEntry

src/Compiler/Checking/CheckBasics.fsi

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,6 @@ type TcEnv =
130130

131131
eIsControlFlow: bool
132132

133-
// In order to avoid checking implicit-yield expressions multiple times, we cache the resulting checked expressions.
134-
// This avoids exponential behavior in the type checker when nesting implicit-yield expressions.
135-
eCachedImplicitYieldExpressions: HashMultiMap<range, SynExpr * TType * Expr>
136133
}
137134

138135
member DisplayEnv: DisplayEnv
@@ -269,11 +266,6 @@ type TcFileState =
269266

270267
diagnosticOptions: FSharpDiagnosticOptions
271268

272-
/// A cache for ArgReprInfos which get created multiple times for the same values
273-
/// Since they need to be later mutated with updates from signature files this should make sure
274-
/// we're always dealing with the same instance and the updates don't get lost
275-
argInfoCache: ConcurrentDictionary<(string * range), ArgReprInfo>
276-
277269
// forward call
278270
TcPat:
279271
WarnOnUpperFlag

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5620,8 +5620,7 @@ let emptyTcEnv g =
56205620
eCtorInfo = None
56215621
eCallerMemberName = None
56225622
eLambdaArgInfos = []
5623-
eIsControlFlow = false
5624-
eCachedImplicitYieldExpressions = HashMultiMap(HashIdentity.Structural, useConcurrentDictionary = true) }
5623+
eIsControlFlow = false }
56255624

56265625
let CreateInitialTcEnv(g, amap, scopem, assemblyName, ccus) =
56275626
(emptyTcEnv g, ccus) ||> List.collectFold (fun env (ccu, autoOpens, internalsVisible) ->

src/Compiler/Checking/Expressions/CheckExpressions.fs

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -955,8 +955,12 @@ let AdjustValSynInfoInSignature g ty (SynValInfo(argsData, retData) as sigMD) =
955955
| _ ->
956956
sigMD
957957

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
958962

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)) =
960964
// Synthesize an artificial "OptionalArgument" attribute for the parameter
961965
let optAttrs =
962966
if isOpt then
@@ -977,20 +981,14 @@ let TranslateTopArgSynInfo (cenv: cenv) isArg m tcAttributes (SynArgInfo(Attribu
977981
// Call the attribute checking function
978982
let attribs = tcAttributes (optAttrs@attrs)
979983

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 }
981987

982988
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 ()
994992

995993
// Set freshly computed attribs in case they are different in the cache
996994
argInfo.Attribs <- attribs
@@ -4051,6 +4049,13 @@ type ImplicitlyBoundTyparsAllowed =
40514049
| NewTyparsOK
40524050
| NoNewTypars
40534051

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+
40544059
//-------------------------------------------------------------------------
40554060
// Checking types and type constraints
40564061
//-------------------------------------------------------------------------
@@ -5503,19 +5508,12 @@ and CheckForAdjacentListExpression (cenv: cenv) synExpr hpa isInfix delayed (arg
55035508
and TcExprThen (cenv: cenv) overallTy env tpenv isArg synExpr delayed =
55045509
let g = cenv.g
55055510

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) ->
55145513
UnifyOverallType cenv env synExpr.Range overallTy ty
55155514
expr, tpenv
55165515
| _ ->
55175516

5518-
55195517
match synExpr with
55205518

55215519
// A.
@@ -6378,9 +6376,8 @@ and TcExprSequentialOrImplicitYield (cenv: cenv) overallTy env tpenv (sp, synExp
63786376
| Expr.DebugPoint(_,e) -> e
63796377
| _ -> expr1
63806378

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
63846381

63856382
and TcExprStaticOptimization (cenv: cenv) overallTy env tpenv (constraints, synExpr2, expr3, m) =
63866383
let constraintsR, tpenv = List.mapFold (TcStaticOptimizationConstraint cenv env) tpenv constraints

0 commit comments

Comments
 (0)