@@ -1215,6 +1215,11 @@ let AddDummyCheckResultsToTcState
12151215
12161216type PartialResult = TcEnv * TopAttribs * CheckedImplFile option * ModuleOrNamespaceType
12171217
1218+ type PairResultOfImplementInPair =
1219+ Import.ImportMap * string list option * ModuleOrNamespaceType * bool * ParsedImplFileInput * TcState * ModuleOrNamespaceType
1220+
1221+ type PartialTypeCheckResult = Choice< PartialResult, PairResultOfImplementInPair>
1222+
12181223type CheckArgs =
12191224 CompilationThreadToken * ( unit -> bool) * TcConfig * TcImports * TcGlobals * LongIdent option * TcState * ( PhasedDiagnostic -> PhasedDiagnostic) * ParsedInput list
12201225
@@ -1406,7 +1411,7 @@ let CheckOneInputAux'
14061411 tcState : TcState ,
14071412 inp : ParsedInput ,
14081413 _skipImplIfSigExists : bool ): ( unit -> bool ) * TcConfig * TcImports * TcGlobals * LongIdent option * TcResultsSink * TcState * ParsedInput * bool )
1409- : Cancellable < TcState -> PartialResult * TcState > =
1414+ : Cancellable < TcState -> PartialTypeCheckResult * TcState > =
14101415
14111416 cancellable {
14121417 try
@@ -1468,7 +1473,7 @@ let CheckOneInputAux'
14681473 // Add the signature to the signature env (unless it had an explicit signature)
14691474 let ccuSigForFile = CombineCcuContentFragments [ sigFileType; tcState.tcsCcuSig ]
14701475
1471- let partialResult = tcEnv, EmptyTopAttrs, None, ccuSigForFile
1476+ let partialResult = Choice1Of2 ( tcEnv, EmptyTopAttrs, None, ccuSigForFile)
14721477
14731478 let tcState =
14741479 { tcState with
@@ -1489,55 +1494,76 @@ let CheckOneInputAux'
14891494 // Check if we've got an interface for this fragment
14901495 let rootSigOpt = tcState.tcsRootSigs.TryFind qualNameOfFile
14911496
1492- // Typecheck the implementation file not backed by a signature file
1497+ match rootSigOpt with
1498+ | None ->
1499+ // Typecheck the implementation file not backed by a signature file
14931500
1494- // Check if we've already seen an implementation for this fragment
1495- if Zset.contains qualNameOfFile tcState.tcsRootImpls then
1496- errorR ( Error( FSComp.SR.buildImplementationAlreadyGiven ( qualNameOfFile.Text), m))
1501+ // Check if we've already seen an implementation for this fragment
1502+ if Zset.contains qualNameOfFile tcState.tcsRootImpls then
1503+ errorR ( Error( FSComp.SR.buildImplementationAlreadyGiven ( qualNameOfFile.Text), m))
14971504
1498- let! topAttrs , implFile , tcEnvAtEnd , createsGeneratedProvidedTypes =
1499- CheckOneImplFile(
1500- tcGlobals,
1501- amap,
1502- tcState.tcsCcu,
1503- tcState.tcsImplicitOpenDeclarations,
1504- checkForErrors,
1505- conditionalDefines,
1506- tcSink,
1507- tcConfig.internalTestSpanStackReferring,
1508- tcState.tcsTcImplEnv,
1509- rootSigOpt,
1510- file
1511- )
1505+ let! topAttrs , implFile , tcEnvAtEnd , createsGeneratedProvidedTypes =
1506+ CheckOneImplFile(
1507+ tcGlobals,
1508+ amap,
1509+ tcState.tcsCcu,
1510+ tcState.tcsImplicitOpenDeclarations,
1511+ checkForErrors,
1512+ conditionalDefines,
1513+ tcSink,
1514+ tcConfig.internalTestSpanStackReferring,
1515+ tcState.tcsTcImplEnv,
1516+ rootSigOpt,
1517+ file
1518+ )
15121519
1513- // printfn $"Finished Processing Impl {file.FileName}"
1514- return
1515- fun tcState ->
1516- // let backed = rootSigOpt.IsSome
1517- // printfn $"Applying Impl Backed={backed} {file.FileName}"
1520+ // printfn $"Finished Processing Impl {file.FileName}"
1521+ return
1522+ fun tcState ->
1523+ // let backed = rootSigOpt.IsSome
1524+ // printfn $"Applying Impl Backed={backed} {file.FileName}"
1525+
1526+ let ccuSigForFile , fsTcState =
1527+ AddCheckResultsToTcState
1528+ ( tcGlobals, amap, false , prefixPathOpt, tcSink, tcState.tcsTcImplEnv, qualNameOfFile, implFile.Signature)
1529+ tcState
15181530
1519- let ccuSigForFile , fsTcState =
1520- AddCheckResultsToTcState
1521- ( tcGlobals, amap, false , prefixPathOpt, tcSink, tcState.tcsTcImplEnv, qualNameOfFile, implFile.Signature)
1522- tcState
1531+ // backed impl files must not add results as there are already results from .fsi files
1532+ //let fsTcState = if backed then tcState else fsTcState
15231533
1524- // backed impl files must not add results as there are already results from .fsi files
1525- //let fsTcState = if backed then tcState else fsTcState
1534+ let partialResult = Choice1Of2( tcEnvAtEnd, topAttrs, Some implFile, ccuSigForFile)
15261535
1527- let partialResult = tcEnvAtEnd, topAttrs, Some implFile, ccuSigForFile
1536+ let tcState =
1537+ { fsTcState with
1538+ tcsCreatesGeneratedProvidedTypes =
1539+ fsTcState.tcsCreatesGeneratedProvidedTypes || createsGeneratedProvidedTypes
1540+ }
1541+
1542+ // printfn $"Finished applying Impl {file.FileName}"
1543+ partialResult, tcState
1544+
1545+ | Some rootSig ->
1546+ // Delay the typecheck the implementation file until the second phase of parallel processing.
1547+ // Adjust the TcState as if it has been checked, which makes the signature for the file available later
1548+ // in the compilation order.
1549+ let tcStateForImplFile = tcState
1550+ let qualNameOfFile = file.QualifiedName
1551+ let priorErrors = checkForErrors ()
15281552
1529- let tcState =
1530- { fsTcState with
1531- tcsCreatesGeneratedProvidedTypes =
1532- fsTcState.tcsCreatesGeneratedProvidedTypes || createsGeneratedProvidedTypes
1533- }
1553+ return
1554+ fun tcState ->
1555+ let ccuSigForFile , tcState =
1556+ AddCheckResultsToTcState
1557+ ( tcGlobals, amap, true , prefixPathOpt, tcSink, tcState.tcsTcImplEnv, qualNameOfFile, rootSig)
1558+ tcState
15341559
1535- // printfn $"Finished applying Impl {file.FileName}"
1536- partialResult , tcState
1560+ let partialResult =
1561+ Choice2Of2 ( amap , conditionalDefines , rootSig , priorErrors , file , tcStateForImplFile , ccuSigForFile )
15371562
1563+ partialResult, tcState
15381564 with e ->
15391565 errorRecovery e range0
1540- return fun tcState -> ( tcState.TcEnvFromSignatures, EmptyTopAttrs, None, tcState.tcsCcuSig), tcState
1566+ return fun tcState -> Choice1Of2 ( tcState.TcEnvFromSignatures, EmptyTopAttrs, None, tcState.tcsCcuSig), tcState
15411567 }
15421568
15431569/// Typecheck a single file (or interactive entry into F# Interactive). If skipImplIfSigExists is set to true
@@ -1552,7 +1578,7 @@ let CheckOneInput'
15521578 tcState : TcState ,
15531579 input : ParsedInput ,
15541580 skipImplIfSigExists : bool ): ( unit -> bool ) * TcConfig * TcImports * TcGlobals * LongIdent option * TcResultsSink * TcState * ParsedInput * bool )
1555- : Cancellable < TcState -> PartialResult * TcState > =
1581+ : Cancellable < TcState -> PartialTypeCheckResult * TcState > =
15561582 CheckOneInputAux'( checkForErrors, tcConfig, tcImports, tcGlobals, prefixPathOpt, tcSink, tcState, input, skipImplIfSigExists)
15571583
15581584// Within a file, equip loggers to locally filter w.r.t. scope pragmas in each input
@@ -1747,3 +1773,41 @@ let CheckClosedInputSet (ctok, checkForErrors, tcConfig: TcConfig, tcImports, tc
17471773
17481774 tcState.Ccu.Deref.Contents <- ccuContents
17491775 tcState, topAttrs, declaredImpls, tcEnvAtEndOfLastFile
1776+
1777+ let checkBackedImplementationFile
1778+ ( tcGlobals : TcGlobals )
1779+ ( tcConfig : TcConfig )
1780+ ( logger : DiagnosticsLogger )
1781+ ( pairResult : PairResultOfImplementInPair )
1782+ =
1783+ let amap , conditionalDefines , rootSig , priorErrors , file , tcStateForImplFile , ccuSigForFile =
1784+ pairResult
1785+
1786+ // In the first linear part of parallel checking, we use a 'checkForErrors' that checks either for errors
1787+ // somewhere in the files processed prior to this one, including from the first phase, or in the processing
1788+ // of this particular file.
1789+ let checkForErrors2 () = priorErrors || ( logger.ErrorCount > 0 )
1790+
1791+ let topAttrs , implFile , tcEnvAtEnd , createsGeneratedProvidedTypes =
1792+ CheckOneImplFile(
1793+ tcGlobals,
1794+ amap,
1795+ tcStateForImplFile.tcsCcu,
1796+ tcStateForImplFile.tcsImplicitOpenDeclarations,
1797+ checkForErrors2,
1798+ conditionalDefines,
1799+ TcResultsSink.NoSink,
1800+ tcConfig.internalTestSpanStackReferring,
1801+ tcStateForImplFile.tcsTcImplEnv,
1802+ Some rootSig,
1803+ file
1804+ )
1805+ |> Cancellable.runWithoutCancellation
1806+
1807+ let result = ( tcEnvAtEnd, topAttrs, Some implFile, ccuSigForFile)
1808+ result, createsGeneratedProvidedTypes
1809+
1810+ let updateCreatesGeneratedProvidedTypes tcState value =
1811+ { tcState with
1812+ tcsCreatesGeneratedProvidedTypes = value
1813+ }
0 commit comments