Skip to content

Commit 6c5af5d

Browse files
authored
Merge pull request #32 from safesparrow/pairs
Pairs
2 parents ce1fdea + 4ae81ee commit 6c5af5d

File tree

11 files changed

+267
-110
lines changed

11 files changed

+267
-110
lines changed

src/Compiler/Driver/ParseAndCheckInputs.fs

Lines changed: 63 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1426,7 +1426,7 @@ let CheckOneInputAux'
14261426
tcState: TcState,
14271427
inp: ParsedInput,
14281428
_skipImplIfSigExists: bool): (unit -> bool) * TcConfig * TcImports * TcGlobals * LongIdent option * TcResultsSink * TcState * ParsedInput * bool)
1429-
: Cancellable<bool -> TcState -> PartialResult * TcState> =
1429+
: Cancellable<TcState -> PartialResult * TcState> =
14301430

14311431
cancellable {
14321432
try
@@ -1478,39 +1478,27 @@ let CheckOneInputAux'
14781478

14791479
// printfn $"Finished Processing Sig {file.FileName}"
14801480
return
1481-
fun isFinalFold tcState ->
1481+
fun tcState ->
14821482
// printfn $"Applying Sig {file.FileName}"
1483-
let fsiPartialResult, tcState =
1484-
let rootSigs = Zmap.add qualNameOfFile sigFileType tcState.tcsRootSigs
14851483

1486-
let tcSigEnv =
1487-
AddLocalRootModuleOrNamespace TcResultsSink.NoSink tcGlobals amap m tcState.tcsTcSigEnv sigFileType
1484+
let rootSigs = Zmap.add qualNameOfFile sigFileType tcState.tcsRootSigs
14881485

1489-
// Add the signature to the signature env (unless it had an explicit signature)
1490-
let ccuSigForFile = CombineCcuContentFragments [ sigFileType; tcState.tcsCcuSig ]
1486+
let tcSigEnv =
1487+
AddLocalRootModuleOrNamespace TcResultsSink.NoSink tcGlobals amap m tcState.tcsTcSigEnv sigFileType
14911488

1492-
let partialResult = tcEnv, EmptyTopAttrs, None, ccuSigForFile
1489+
// Add the signature to the signature env (unless it had an explicit signature)
1490+
let ccuSigForFile = CombineCcuContentFragments [ sigFileType; tcState.tcsCcuSig ]
14931491

1494-
let tcState =
1495-
{ tcState with
1496-
tcsTcSigEnv = tcSigEnv
1497-
tcsRootSigs = rootSigs
1498-
tcsCreatesGeneratedProvidedTypes =
1499-
tcState.tcsCreatesGeneratedProvidedTypes || createsGeneratedProvidedTypes
1500-
}
1492+
let partialResult = tcEnv, EmptyTopAttrs, None, ccuSigForFile
15011493

1502-
partialResult, tcState
1494+
let tcState =
1495+
{ tcState with
1496+
tcsTcSigEnv = tcSigEnv
1497+
tcsRootSigs = rootSigs
1498+
tcsCreatesGeneratedProvidedTypes = tcState.tcsCreatesGeneratedProvidedTypes || createsGeneratedProvidedTypes
1499+
}
15031500

1504-
if isFinalFold then
1505-
fsiPartialResult, tcState
1506-
else
1507-
// Update the TcEnv of implementation files to also contain the signature data.
1508-
let _ccuSigForFile, tcState =
1509-
AddCheckResultsToTcState
1510-
(tcGlobals, amap, true, prefixPathOpt, tcSink, tcState.tcsTcImplEnv, qualNameOfFile, sigFileType)
1511-
tcState
1512-
1513-
fsiPartialResult, tcState
1501+
partialResult, tcState
15141502

15151503
| ParsedInput.ImplFile file ->
15161504
// printfn $"Processing Impl {file.FileName}"
@@ -1539,45 +1527,34 @@ let CheckOneInputAux'
15391527

15401528
// printfn $"Finished Processing Impl {file.FileName}"
15411529
return
1542-
fun isFinalFold tcState ->
1543-
let addResultToState () =
1544-
// Check if we've already seen an implementation for this fragment
1545-
if Zset.contains qualNameOfFile tcState.tcsRootImpls then
1546-
errorR (Error(FSComp.SR.buildImplementationAlreadyGiven (qualNameOfFile.Text), m))
1547-
1548-
// printfn $"Applying Impl Backed={backed} {file.FileName}"
1549-
let ccuSigForFile, fsTcState =
1550-
AddCheckResultsToTcState
1551-
(tcGlobals, amap, false, prefixPathOpt, tcSink, tcState.tcsTcImplEnv, qualNameOfFile, implFile.Signature)
1552-
tcState
1553-
1554-
// backed impl files must not add results as there are already results from .fsi files
1555-
//let fsTcState = if backed then tcState else fsTcState
1556-
1557-
let partialResult = tcEnvAtEnd, topAttrs, Some implFile, ccuSigForFile
1558-
1559-
let tcState =
1560-
{ fsTcState with
1561-
tcsCreatesGeneratedProvidedTypes =
1562-
fsTcState.tcsCreatesGeneratedProvidedTypes || createsGeneratedProvidedTypes
1563-
}
1564-
1565-
// printfn $"Finished applying Impl {file.FileName}"
1566-
partialResult, tcState
1567-
1568-
match rootSigOpt with
1569-
| None -> addResultToState ()
1570-
| Some _ when isFinalFold -> addResultToState ()
1571-
| Some rootSig ->
1572-
// In this case, we are skipping the step where we add the results of the implementation file to the tcState.
1573-
// The fold function of a signature file will add the result (of the signature),
1574-
// to the implementation when it is not processing the final fold.
1575-
let partialResult = tcEnvAtEnd, topAttrs, Some implFile, rootSig
1576-
partialResult, tcState
1530+
fun tcState ->
1531+
// Check if we've already seen an implementation for this fragment
1532+
if Zset.contains qualNameOfFile tcState.tcsRootImpls then
1533+
errorR (Error(FSComp.SR.buildImplementationAlreadyGiven (qualNameOfFile.Text), m))
1534+
1535+
// printfn $"Applying Impl Backed={backed} {file.FileName}"
1536+
let ccuSigForFile, fsTcState =
1537+
AddCheckResultsToTcState
1538+
(tcGlobals, amap, false, prefixPathOpt, tcSink, tcState.tcsTcImplEnv, qualNameOfFile, implFile.Signature)
1539+
tcState
1540+
1541+
// backed impl files must not add results as there are already results from .fsi files
1542+
//let fsTcState = if backed then tcState else fsTcState
1543+
1544+
let partialResult = tcEnvAtEnd, topAttrs, Some implFile, ccuSigForFile
1545+
1546+
let tcState =
1547+
{ fsTcState with
1548+
tcsCreatesGeneratedProvidedTypes =
1549+
fsTcState.tcsCreatesGeneratedProvidedTypes || createsGeneratedProvidedTypes
1550+
}
1551+
1552+
// printfn $"Finished applying Impl {file.FileName}"
1553+
partialResult, tcState
15771554

15781555
with e ->
15791556
errorRecovery e range0
1580-
return fun _ tcState -> (tcState.TcEnvFromSignatures, EmptyTopAttrs, None, tcState.tcsCcuSig), tcState
1557+
return fun tcState -> (tcState.TcEnvFromSignatures, EmptyTopAttrs, None, tcState.tcsCcuSig), tcState
15811558
}
15821559

15831560
/// Typecheck a single file (or interactive entry into F# Interactive). If skipImplIfSigExists is set to true
@@ -1592,9 +1569,31 @@ let CheckOneInput'
15921569
tcState: TcState,
15931570
input: ParsedInput,
15941571
skipImplIfSigExists: bool): (unit -> bool) * TcConfig * TcImports * TcGlobals * LongIdent option * TcResultsSink * TcState * ParsedInput * bool)
1595-
: Cancellable<bool -> TcState -> PartialResult * TcState> =
1572+
: Cancellable<TcState -> PartialResult * TcState> =
15961573
CheckOneInputAux'(checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input, skipImplIfSigExists)
15971574

1575+
let AddSignatureResultToTcImplEnv (tcImports: TcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input: ParsedInput) =
1576+
let qualNameOfFile = input.QualifiedName
1577+
let rootSigOpt = tcState.tcsRootSigs.TryFind qualNameOfFile
1578+
1579+
match rootSigOpt with
1580+
| None -> failwithf $"No signature data was found for %s{input.FileName}"
1581+
| Some rootSig ->
1582+
fun (tcState: TcState) ->
1583+
let amap = tcImports.GetImportMap()
1584+
1585+
// Add the results of type checking the signature file to the TcEnv of implementation files.
1586+
let ccuSigForFile, tcState =
1587+
AddCheckResultsToTcState
1588+
(tcGlobals, amap, true, prefixPathOpt, tcSink, tcState.tcsTcImplEnv, qualNameOfFile, rootSig)
1589+
tcState
1590+
1591+
// This partial result will be discarded in the end of the graph resolution.
1592+
let partialResult: PartialResult =
1593+
tcState.tcsTcSigEnv, EmptyTopAttrs, None, ccuSigForFile
1594+
1595+
partialResult, tcState
1596+
15981597
// Within a file, equip loggers to locally filter w.r.t. scope pragmas in each input
15991598
let DiagnosticsLoggerForInput (tcConfig: TcConfig, input: ParsedInput, oldLogger) =
16001599
GetDiagnosticsLoggerFilteringByScopedPragmas(false, input.ScopedPragmas, tcConfig.diagnosticsOptions, oldLogger)

src/Compiler/Driver/ParseAndCheckInputs.fsi

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,16 @@ val CheckOneInput':
185185
tcState: TcState *
186186
input: ParsedInput *
187187
skipImplIfSigExists: bool ->
188-
Cancellable<bool -> TcState -> PartialResult * TcState>
188+
Cancellable<TcState -> PartialResult * TcState>
189+
190+
val AddSignatureResultToTcImplEnv:
191+
tcImports: TcImports *
192+
tcGlobals: TcGlobals *
193+
prefixPathOpt: LongIdent option *
194+
tcSink: NameResolution.TcResultsSink *
195+
tcState: TcState *
196+
input: ParsedInput ->
197+
(TcState -> PartialResult * TcState)
189198

190199
val CheckMultipleInputsInParallel:
191200
(CompilationThreadToken * (unit -> bool) * TcConfig * TcImports * TcGlobals * LongIdent option * TcState * (PhasedDiagnostic -> PhasedDiagnostic) * ParsedInput list) ->

tests/ParallelTypeCheckingTests/Code/DependencyResolution.fs

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -177,28 +177,14 @@ let collectGhostDependencies (fileIndex: int) (trie: TrieNode) (queryTrie: Query
177177
// The partial open did eventually lead to a link in a file
178178
Array.empty)
179179

180-
let mkGraph (files: FileWithAST array) : Graph<int> =
181-
// Map to easily retrieve the signature file index
182-
let implToSig =
183-
Array.choose
184-
(fun f ->
185-
match f.AST with
186-
| ParsedInput.SigFile _ ->
187-
files
188-
|> Array.skip (f.Idx + 1)
189-
|> Array.tryFind (fun (implFile: FileWithAST) -> $"{implFile.File}i" = f.File)
190-
|> Option.map (fun (implFile: FileWithAST) -> (implFile.Idx, f.Idx))
191-
| ParsedInput.ImplFile _ -> None)
192-
files
193-
|> Map.ofArray
194-
180+
let mkGraph (filePairs: FilePairMap) (files: FileWithAST array) : Graph<int> =
195181
// Implementation files backed by signatures should be excluded to construct the trie.
196182
let trieInput =
197183
Array.choose
198184
(fun f ->
199185
match f.AST with
200186
| ParsedInput.SigFile _ -> Some f
201-
| ParsedInput.ImplFile _ -> if Map.containsKey f.Idx implToSig then None else Some f)
187+
| ParsedInput.ImplFile _ -> if filePairs.HasSignature f.Idx then None else Some f)
202188
files
203189

204190
let trie = TrieMapping.mkTrie trieInput
@@ -221,7 +207,7 @@ let mkGraph (files: FileWithAST array) : Graph<int> =
221207

222208
// Automatically add a link from an implementation to its signature file (if present)
223209
let signatureDependency =
224-
match Map.tryFind file.Idx implToSig with
210+
match filePairs.TryGetSignatureIndex file.Idx with
225211
| None -> Array.empty
226212
| Some sigIdx -> Array.singleton sigIdx
227213

tests/ParallelTypeCheckingTests/Code/GraphProcessing.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ type ProcessedNode<'Item, 'Result> =
4040
let processGraph<'Item, 'Result when 'Item: equality and 'Item: comparison>
4141
(graph: Graph<'Item>)
4242
(work: ('Item -> ProcessedNode<'Item, 'Result>) -> NodeInfo<'Item> -> 'Result)
43+
(includeInFinalState: 'Item -> bool)
4344
(ct: CancellationToken)
4445
: ('Item * 'Result)[] =
4546
let transitiveDeps = graph |> Graph.transitiveOpt
@@ -125,6 +126,7 @@ let processGraph<'Item, 'Result when 'Item: equality and 'Item: comparison>
125126
waitHandle.WaitOne() |> ignore
126127

127128
nodes.Values
129+
|> Seq.filter (fun node -> includeInFinalState node.Info.Item)
128130
|> Seq.map (fun node ->
129131
let result =
130132
node.Result

0 commit comments

Comments
 (0)