Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Stop incremental builder from accumulating TcSymbolUses/TcResolutions/etc. #11666

Merged
merged 3 commits into from
Jun 16, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 47 additions & 10 deletions src/fsharp/service/FSharpCheckerResults.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2182,7 +2182,7 @@ type FSharpCheckProjectResults
tcConfigOption: TcConfig option,
keepAssemblyContents: bool,
diagnostics: FSharpDiagnostic[],
details:(TcGlobals * TcImports * CcuThunk * ModuleOrNamespaceType * TcSymbolUses list *
details:(TcGlobals * TcImports * CcuThunk * ModuleOrNamespaceType * Choice<IncrementalBuilder, TcSymbolUses> *
TopAttribs option * IRawFSharpAssemblyData option * ILAssemblyRef *
AccessorDomain * TypedImplFile list option * string[] * FSharpProjectOptions) option) =

Expand All @@ -2201,12 +2201,12 @@ type FSharpCheckProjectResults
member _.HasCriticalErrors = details.IsNone

member _.AssemblySignature =
let (tcGlobals, tcImports, thisCcu, ccuSig, _tcSymbolUses, topAttribs, _tcAssemblyData, _ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()
let (tcGlobals, tcImports, thisCcu, ccuSig, _builderOrSymbolUses, topAttribs, _tcAssemblyData, _ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()
FSharpAssemblySignature(tcGlobals, thisCcu, ccuSig, tcImports, topAttribs, ccuSig)

member _.TypedImplementationFiles =
if not keepAssemblyContents then invalidOp "The 'keepAssemblyContents' flag must be set to true on the FSharpChecker in order to access the checked contents of assemblies"
let (tcGlobals, tcImports, thisCcu, _ccuSig, _tcSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()
let (tcGlobals, tcImports, thisCcu, _ccuSig, _builderOrSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()
let mimpls =
match tcAssemblyExpr with
| None -> []
Expand All @@ -2215,7 +2215,7 @@ type FSharpCheckProjectResults

member info.AssemblyContents =
if not keepAssemblyContents then invalidOp "The 'keepAssemblyContents' flag must be set to true on the FSharpChecker in order to access the checked contents of assemblies"
let (tcGlobals, tcImports, thisCcu, ccuSig, _tcSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()
let (tcGlobals, tcImports, thisCcu, ccuSig, _builderOrSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()
let mimpls =
match tcAssemblyExpr with
| None -> []
Expand All @@ -2224,7 +2224,7 @@ type FSharpCheckProjectResults

member _.GetOptimizedAssemblyContents() =
if not keepAssemblyContents then invalidOp "The 'keepAssemblyContents' flag must be set to true on the FSharpChecker in order to access the checked contents of assemblies"
let (tcGlobals, tcImports, thisCcu, ccuSig, _tcSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()
let (tcGlobals, tcImports, thisCcu, ccuSig, _builderOrSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()
let mimpls =
match tcAssemblyExpr with
| None -> []
Expand All @@ -2243,10 +2243,28 @@ type FSharpCheckProjectResults

// Not, this does not have to be a SyncOp, it can be called from any thread
member _.GetUsesOfSymbol(symbol:FSharpSymbol, ?cancellationToken: CancellationToken) =
let (tcGlobals, _tcImports, _thisCcu, _ccuSig, tcSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()
let (tcGlobals, _tcImports, _thisCcu, _ccuSig, builderOrSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()

let results =
match builderOrSymbolUses with
| Choice1Of2 builder ->
builder.SourceFiles
|> Array.ofList
|> Array.collect (fun x ->
match builder.GetCheckResultsForFileInProjectEvenIfStale x with
| Some partialCheckResults ->
match partialCheckResults.TryPeekTcInfoWithExtras() with
| Some(_, tcInfoExtras) ->
tcInfoExtras.TcSymbolUses.GetUsesOfSymbol symbol.Item
| _ ->
[||]
| _ ->
[||]
)
| Choice2Of2 tcSymbolUses ->
tcSymbolUses.GetUsesOfSymbol symbol.Item

tcSymbolUses
|> Seq.collect (fun r -> r.GetUsesOfSymbol symbol.Item)
results
|> Seq.filter (fun symbolUse -> symbolUse.ItemOccurence <> ItemOccurence.RelatedText)
|> Seq.distinctBy (fun symbolUse -> symbolUse.ItemOccurence, symbolUse.Range)
|> Seq.map (fun symbolUse ->
Expand All @@ -2256,9 +2274,28 @@ type FSharpCheckProjectResults

// Not, this does not have to be a SyncOp, it can be called from any thread
member _.GetAllUsesOfAllSymbols(?cancellationToken: CancellationToken) =
let (tcGlobals, tcImports, thisCcu, ccuSig, tcSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()
let (tcGlobals, tcImports, thisCcu, ccuSig, builderOrSymbolUses, _topAttribs, _tcAssemblyData, _ilAssemRef, _ad, _tcAssemblyExpr, _dependencyFiles, _projectOptions) = getDetails()
let cenv = SymbolEnv(tcGlobals, thisCcu, Some ccuSig, tcImports)

let tcSymbolUses =
match builderOrSymbolUses with
| Choice1Of2 builder ->
builder.SourceFiles
|> Array.ofList
|> Array.map (fun x ->
match builder.GetCheckResultsForFileInProjectEvenIfStale x with
| Some partialCheckResults ->
match partialCheckResults.TryPeekTcInfoWithExtras() with
| Some(_, tcInfoExtras) ->
tcInfoExtras.TcSymbolUses
| _ ->
TcSymbolUses.Empty
| _ ->
TcSymbolUses.Empty
)
| Choice2Of2 tcSymbolUses ->
[|tcSymbolUses|]

[| for r in tcSymbolUses do
for symbolUseChunk in r.AllUsesOfSymbols do
for symbolUse in symbolUseChunk do
Expand Down Expand Up @@ -2353,7 +2390,7 @@ type FsiInteractiveChecker(legacyReferenceResolver,
FSharpCheckProjectResults (filename, Some tcConfig,
keepAssemblyContents, errors,
Some(tcGlobals, tcImports, tcFileInfo.ThisCcu, tcFileInfo.CcuSigForFile,
[tcFileInfo.ScopeSymbolUses], None, None, mkSimpleAssemblyRef "stdin",
(Choice2Of2 tcFileInfo.ScopeSymbolUses), None, None, mkSimpleAssemblyRef "stdin",
tcState.TcEnvFromImpls.AccessRights, None, dependencyFiles,
projectOptions))

Expand Down
2 changes: 1 addition & 1 deletion src/fsharp/service/FSharpCheckerResults.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -446,7 +446,7 @@ type public FSharpCheckProjectResults =
TcImports *
CcuThunk *
ModuleOrNamespaceType *
TcSymbolUses list *
Choice<IncrementalBuilder, TcSymbolUses> *
TopAttribs option *
IRawFSharpAssemblyData option *
ILAssemblyRef *
Expand Down
54 changes: 28 additions & 26 deletions src/fsharp/service/IncrementalBuild.fs
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,9 @@ type TcInfo =
[<NoEquality; NoComparison>]
type TcInfoExtras =
{
/// Accumulated resolutions, last file first
tcResolutionsRev: TcResolutions list

/// Accumulated symbol uses, last file first
tcSymbolUsesRev: TcSymbolUses list

/// Accumulated 'open' declarations, last file first
tcOpenDeclarationsRev: OpenDeclaration[] list
tcResolutions: TcResolutions
tcSymbolUses: TcSymbolUses
tcOpenDeclarations: OpenDeclaration[]

/// Result of checking most recent file, if any
latestImplFile: TypedImplFile option
Expand All @@ -202,16 +197,16 @@ type TcInfoExtras =
}

member x.TcSymbolUses =
List.rev x.tcSymbolUsesRev
x.tcSymbolUses

[<AutoOpen>]
module TcInfoHelpers =

let emptyTcInfoExtras =
{
tcResolutionsRev = []
tcSymbolUsesRev = []
tcOpenDeclarationsRev = []
tcResolutions = TcResolutions.Empty
tcSymbolUses = TcSymbolUses.Empty
tcOpenDeclarations = [||]
latestImplFile = None
itemKeyStore = None
semanticClassificationKeyStore = None
Expand Down Expand Up @@ -258,7 +253,6 @@ type BoundModel private (tcConfig: TcConfig,
beforeFileChecked: Event<string>,
fileChecked: Event<string>,
prevTcInfo: TcInfo,
prevTcInfoExtras: NodeCode<TcInfoExtras>,
syntaxTreeOpt: SyntaxTree option,
tcInfoStateOpt: TcInfoState option) as this =

Expand Down Expand Up @@ -295,8 +289,7 @@ type BoundModel private (tcConfig: TcConfig,

let defaultTypeCheck () =
node {
let! prevTcInfoExtras = prevTcInfoExtras
return FullState(prevTcInfo, prevTcInfoExtras)
return PartialState(prevTcInfo)
}

member _.TcConfig = tcConfig
Expand Down Expand Up @@ -347,7 +340,6 @@ type BoundModel private (tcConfig: TcConfig,
beforeFileChecked,
fileChecked,
prevTcInfo,
prevTcInfoExtras,
newSyntaxTreeOpt,
newTcInfoStateOpt)
else
Expand All @@ -366,7 +358,6 @@ type BoundModel private (tcConfig: TcConfig,
beforeFileChecked,
fileChecked,
tcInfo,
this.GetOrComputeTcInfoExtras(),
Some syntaxTree,
None)

Expand Down Expand Up @@ -402,7 +393,6 @@ type BoundModel private (tcConfig: TcConfig,
beforeFileChecked,
fileChecked,
prevTcInfo,
prevTcInfoExtras,
syntaxTreeOpt,
Some finishState)
}
Expand All @@ -417,6 +407,13 @@ type BoundModel private (tcConfig: TcConfig,
| ValueSome(tcInfo, _) -> Some tcInfo
| _ -> None

member _.TryPeekTcInfoWithExtras() =
match tcInfoNode with
| TcInfoNode(_, fullGraphNode) ->
match fullGraphNode.TryPeekValue() with
| ValueSome(tcInfo, tcInfoExtras) -> Some(tcInfo, tcInfoExtras)
| _ -> None

member _.GetOrComputeTcInfo() =
match tcInfoNode with
| TcInfoNode(partialGraphNode, _) ->
Expand Down Expand Up @@ -512,7 +509,6 @@ type BoundModel private (tcConfig: TcConfig,
if partialCheck then
return PartialState tcInfo
else
let! prevTcInfoOptional = prevTcInfoExtras
// Build symbol keys
let itemKeyStore, semanticClassification =
if enableBackgroundItemKeyStoreAndSemanticClassification then
Expand Down Expand Up @@ -543,9 +539,9 @@ type BoundModel private (tcConfig: TcConfig,
{
/// Only keep the typed interface files when doing a "full" build for fsc.exe, otherwise just throw them away
latestImplFile = if keepAssemblyContents then implFile else None
tcResolutionsRev = (if keepAllBackgroundResolutions then sink.GetResolutions() else TcResolutions.Empty) :: prevTcInfoOptional.tcResolutionsRev
tcSymbolUsesRev = (if keepAllBackgroundSymbolUses then sink.GetSymbolUses() else TcSymbolUses.Empty) :: prevTcInfoOptional.tcSymbolUsesRev
tcOpenDeclarationsRev = sink.GetOpenDeclarations() :: prevTcInfoOptional.tcOpenDeclarationsRev
tcResolutions = (if keepAllBackgroundResolutions then sink.GetResolutions() else TcResolutions.Empty)
tcSymbolUses = (if keepAllBackgroundSymbolUses then sink.GetSymbolUses() else TcSymbolUses.Empty)
tcOpenDeclarations = sink.GetOpenDeclarations()
itemKeyStore = itemKeyStore
semanticClassificationKeyStore = semanticClassification
}
Expand All @@ -563,7 +559,6 @@ type BoundModel private (tcConfig: TcConfig,
beforeFileChecked: Event<string>,
fileChecked: Event<string>,
prevTcInfo: TcInfo,
prevTcInfoExtras: NodeCode<TcInfoExtras>,
syntaxTreeOpt: SyntaxTree option) =
BoundModel(tcConfig, tcGlobals, tcImports,
keepAssemblyContents, keepAllBackgroundResolutions,
Expand All @@ -573,7 +568,6 @@ type BoundModel private (tcConfig: TcConfig,
beforeFileChecked,
fileChecked,
prevTcInfo,
prevTcInfoExtras,
syntaxTreeOpt,
None)

Expand Down Expand Up @@ -650,6 +644,8 @@ type PartialCheckResults (boundModel: BoundModel, timeStamp: DateTime) =

member _.TryPeekTcInfo() = boundModel.TryPeekTcInfo()

member _.TryPeekTcInfoWithExtras() = boundModel.TryPeekTcInfoWithExtras()

member _.GetOrComputeTcInfo() = boundModel.GetOrComputeTcInfo()

member _.GetOrComputeTcInfoWithExtras() = boundModel.GetOrComputeTcInfoWithExtras()
Expand Down Expand Up @@ -836,7 +832,6 @@ type IncrementalBuilder(
tcDependencyFiles = basicDependencies
sigNameOpt = None
}
let tcInfoExtras = emptyTcInfoExtras
return
BoundModel.Create(
tcConfig,
Expand All @@ -850,7 +845,6 @@ type IncrementalBuilder(
beforeFileChecked,
fileChecked,
tcInfo,
node { return tcInfoExtras },
None) }

/// Type check all files eagerly.
Expand Down Expand Up @@ -1191,6 +1185,14 @@ type IncrementalBuilder(
| Some (boundModel, timestamp) -> Some (PartialCheckResults (boundModel, timestamp))
| _ -> None

member builder.GetCheckResultsForFileInProjectEvenIfStale filename: PartialCheckResults option =
let slotOfFile = builder.GetSlotOfFileName filename
let result = tryGetSlot currentState slotOfFile

match result with
| Some (boundModel, timestamp) -> Some (PartialCheckResults (boundModel, timestamp))
| _ -> None

member builder.TryGetCheckResultsBeforeFileInProject (filename) =
let cache = TimeStampCache defaultTimeStamp
let tmpState = computeStampedFileNames currentState cache
Expand Down
22 changes: 13 additions & 9 deletions src/fsharp/service/IncrementalBuild.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -73,14 +73,9 @@ type internal TcInfo =
[<NoEquality; NoComparison>]
type internal TcInfoExtras =
{
/// Accumulated resolutions, last file first
tcResolutionsRev: TcResolutions list

/// Accumulated symbol uses, last file first
tcSymbolUsesRev: TcSymbolUses list

/// Accumulated 'open' declarations, last file first
tcOpenDeclarationsRev: OpenDeclaration[] list
tcResolutions: TcResolutions
tcSymbolUses: TcSymbolUses
tcOpenDeclarations: OpenDeclaration[]

/// Result of checking most recent file, if any
latestImplFile: TypedImplFile option
Expand All @@ -92,7 +87,7 @@ type internal TcInfoExtras =
semanticClassificationKeyStore: SemanticClassificationKeyStore option
}

member TcSymbolUses: TcSymbolUses list
member TcSymbolUses: TcSymbolUses

/// Represents the state in the incremental graph associated with checking a file
[<Sealed>]
Expand All @@ -108,6 +103,8 @@ type internal PartialCheckResults =

member TryPeekTcInfo: unit -> TcInfo option

member TryPeekTcInfoWithExtras: unit -> (TcInfo * TcInfoExtras) option

/// Compute the "TcInfo" part of the results. If `enablePartialTypeChecking` is false then
/// extras will also be available.
member GetOrComputeTcInfo: unit -> NodeCode<TcInfo>
Expand Down Expand Up @@ -178,6 +175,13 @@ type internal IncrementalBuilder =
/// This is safe for use from non-compiler threads but the objects returned must in many cases be accessed only from the compiler thread.
member GetCheckResultsBeforeFileInProjectEvenIfStale: filename:string -> PartialCheckResults option

/// Get the typecheck state of a slot, without checking if it is up-to-date w.r.t.
/// the timestamps on files and referenced DLLs prior to this one. Return None if the result is not available.
/// This is a very quick operation.
///
/// This is safe for use from non-compiler threads but the objects returned must in many cases be accessed only from the compiler thread.
member GetCheckResultsForFileInProjectEvenIfStale: filename:string -> PartialCheckResults option

/// Get the preceding typecheck state of a slot, but only if it is up-to-date w.r.t.
/// the timestamps on files and referenced DLLs prior to this one. Return None if the result is not available.
/// This is a relatively quick operation.
Expand Down
18 changes: 9 additions & 9 deletions src/fsharp/service/service.fs
Original file line number Diff line number Diff line change
Expand Up @@ -698,9 +698,9 @@ type BackgroundCompiler(

let! tcInfo, tcInfoExtras = tcProj.GetOrComputeTcInfoWithExtras()

let tcResolutionsRev = tcInfoExtras.tcResolutionsRev
let tcSymbolUsesRev = tcInfoExtras.tcSymbolUsesRev
let tcOpenDeclarationsRev = tcInfoExtras.tcOpenDeclarationsRev
let tcResolutions = tcInfoExtras.tcResolutions
let tcSymbolUses = tcInfoExtras.tcSymbolUses
let tcOpenDeclarations = tcInfoExtras.tcOpenDeclarations
let latestCcuSigForFile = tcInfo.latestCcuSigForFile
let tcState = tcInfo.tcState
let tcEnvAtEnd = tcInfo.tcEnvAtEndOfFile
Expand Down Expand Up @@ -730,12 +730,12 @@ type BackgroundCompiler(
tcState.Ccu,
tcProj.TcImports,
tcEnvAtEnd.AccessRights,
List.head tcResolutionsRev,
List.head tcSymbolUsesRev,
tcResolutions,
tcSymbolUses,
tcEnvAtEnd.NameEnv,
loadClosure,
latestImplementationFile,
List.head tcOpenDeclarationsRev)
tcOpenDeclarations)
return (parseResults, typedResults)
}

Expand Down Expand Up @@ -799,9 +799,9 @@ type BackgroundCompiler(
let errorOptions = tcProj.TcConfig.errorSeverityOptions
let fileName = TcGlobals.DummyFileNameForRangesWithoutASpecificLocation

let! tcInfo, tcInfoExtras = tcProj.GetOrComputeTcInfoWithExtras()
// Although we do not use 'tcInfoExtras', computing it will make sure we get an extra info.
let! tcInfo, _tcInfoExtras = tcProj.GetOrComputeTcInfoWithExtras()

let tcSymbolUses = tcInfoExtras.TcSymbolUses
let topAttribs = tcInfo.topAttribs
let tcState = tcInfo.tcState
let tcEnvAtEnd = tcInfo.tcEnvAtEndOfFile
Expand All @@ -817,7 +817,7 @@ type BackgroundCompiler(
keepAssemblyContents,
diagnostics,
Some(tcProj.TcGlobals, tcProj.TcImports, tcState.Ccu, tcState.CcuSig,
tcSymbolUses, topAttribs, tcAssemblyDataOpt, ilAssemRef,
(Choice1Of2 builder), topAttribs, tcAssemblyDataOpt, ilAssemRef,
tcEnvAtEnd.AccessRights, tcAssemblyExprOpt,
Array.ofList tcDependencyFiles,
options))
Expand Down