Skip to content

Commit 6d3d3cc

Browse files
committed
WIP Setup unit tests
1 parent cb4a99f commit 6d3d3cc

39 files changed

Lines changed: 1042 additions & 656 deletions

FSharp.Compiler.Service.sln

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
4040
src\Compiler\FSComp.txt = src\Compiler\FSComp.txt
4141
EndProjectSection
4242
EndProject
43-
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service.Tests2", "tests\FSharp.Compiler.Service.Tests2\FSharp.Compiler.Service.Tests2.fsproj", "{60EDC1C4-5B8B-4211-94CD-4CF5F9E0FC8B}"
43+
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ParallelTypeCheckingTests", "tests\ParallelTypeCheckingTests\ParallelTypeCheckingTests.fsproj", "{60EDC1C4-5B8B-4211-94CD-4CF5F9E0FC8B}"
4444
EndProject
4545
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "DiamondTest", "tests\DiamondTest\DiamondTest.fsproj", "{62288B06-B682-4774-A8A5-A21D677A7C70}"
4646
EndProject

FSharp.sln

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -107,10 +107,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
107107
src\Compiler\FSComp.txt = src\Compiler\FSComp.txt
108108
EndProjectSection
109109
EndProject
110-
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "FSharp.Compiler.Service.Tests2", "tests\FSharp.Compiler.Service.Tests2\FSharp.Compiler.Service.Tests2.fsproj", "{7F58653C-1B72-41C7-9A06-43CAAC3051B5}"
111-
EndProject
112110
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "DiamondTest", "tests\DiamondTest\DiamondTest.fsproj", "{B7C957CB-9E64-44CF-BC73-152BFC6E5BCC}"
113111
EndProject
112+
Project("{F2A71F9B-5D33-465A-A702-920D77279786}") = "ParallelTypeCheckingTests", "tests\ParallelTypeCheckingTests\ParallelTypeCheckingTests.fsproj", "{59C31D40-97E0-4A69-ABD9-D316BD798ED8}"
113+
EndProject
114114
Global
115115
GlobalSection(SolutionConfigurationPlatforms) = preSolution
116116
Debug|Any CPU = Debug|Any CPU
@@ -433,18 +433,6 @@ Global
433433
{9C7523BA-7AB2-4604-A5FD-653E82C2BAD1}.Release|Any CPU.Build.0 = Release|Any CPU
434434
{9C7523BA-7AB2-4604-A5FD-653E82C2BAD1}.Release|x86.ActiveCfg = Release|Any CPU
435435
{9C7523BA-7AB2-4604-A5FD-653E82C2BAD1}.Release|x86.Build.0 = Release|Any CPU
436-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
437-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Debug|Any CPU.Build.0 = Debug|Any CPU
438-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Debug|x86.ActiveCfg = Debug|Any CPU
439-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Debug|x86.Build.0 = Debug|Any CPU
440-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
441-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Proto|Any CPU.Build.0 = Debug|Any CPU
442-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Proto|x86.ActiveCfg = Debug|Any CPU
443-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Proto|x86.Build.0 = Debug|Any CPU
444-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Release|Any CPU.ActiveCfg = Release|Any CPU
445-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Release|Any CPU.Build.0 = Release|Any CPU
446-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Release|x86.ActiveCfg = Release|Any CPU
447-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5}.Release|x86.Build.0 = Release|Any CPU
448436
{B7C957CB-9E64-44CF-BC73-152BFC6E5BCC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
449437
{B7C957CB-9E64-44CF-BC73-152BFC6E5BCC}.Debug|Any CPU.Build.0 = Debug|Any CPU
450438
{B7C957CB-9E64-44CF-BC73-152BFC6E5BCC}.Debug|x86.ActiveCfg = Debug|Any CPU
@@ -457,6 +445,18 @@ Global
457445
{B7C957CB-9E64-44CF-BC73-152BFC6E5BCC}.Release|Any CPU.Build.0 = Release|Any CPU
458446
{B7C957CB-9E64-44CF-BC73-152BFC6E5BCC}.Release|x86.ActiveCfg = Release|Any CPU
459447
{B7C957CB-9E64-44CF-BC73-152BFC6E5BCC}.Release|x86.Build.0 = Release|Any CPU
448+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
449+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Debug|Any CPU.Build.0 = Debug|Any CPU
450+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Debug|x86.ActiveCfg = Debug|Any CPU
451+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Debug|x86.Build.0 = Debug|Any CPU
452+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Proto|Any CPU.ActiveCfg = Debug|Any CPU
453+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Proto|Any CPU.Build.0 = Debug|Any CPU
454+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Proto|x86.ActiveCfg = Debug|Any CPU
455+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Proto|x86.Build.0 = Debug|Any CPU
456+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Release|Any CPU.ActiveCfg = Release|Any CPU
457+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Release|Any CPU.Build.0 = Release|Any CPU
458+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Release|x86.ActiveCfg = Release|Any CPU
459+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8}.Release|x86.Build.0 = Release|Any CPU
460460
EndGlobalSection
461461
GlobalSection(SolutionProperties) = preSolution
462462
HideSolutionNode = FALSE
@@ -489,8 +489,8 @@ Global
489489
{209C7D37-8C01-413C-8698-EC25F4C86976} = {B8DDA694-7939-42E3-95E5-265C2217C142}
490490
{BEC6E796-7E53-4888-AAFC-B8FD55C425DF} = {CE70D631-C5DC-417E-9CDA-B16097BEF1AC}
491491
{9C7523BA-7AB2-4604-A5FD-653E82C2BAD1} = {CE70D631-C5DC-417E-9CDA-B16097BEF1AC}
492-
{7F58653C-1B72-41C7-9A06-43CAAC3051B5} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449}
493492
{B7C957CB-9E64-44CF-BC73-152BFC6E5BCC} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449}
493+
{59C31D40-97E0-4A69-ABD9-D316BD798ED8} = {CFE3259A-2D30-4EB0-80D5-E8B5F3D01449}
494494
EndGlobalSection
495495
GlobalSection(ExtensibilityGlobals) = postSolution
496496
SolutionGuid = {BD5177C7-1380-40E7-94D2-7768E1A8B1B8}

src/Compiler/Driver/ParseAndCheckInputs.fs

Lines changed: 11 additions & 209 deletions
Original file line numberDiff line numberDiff line change
@@ -1047,6 +1047,10 @@ type TcState =
10471047
tcsImplicitOpenDeclarations: OpenDeclaration list
10481048
}
10491049

1050+
member x.TcsRootSigs = x.tcsRootSigs
1051+
1052+
member x.TcsRootImpls = x.tcsRootImpls
1053+
10501054
member x.TcEnvFromSignatures = x.tcsTcSigEnv
10511055

10521056
member x.TcEnvFromImpls = x.tcsTcImplEnv
@@ -1070,6 +1074,13 @@ type TcState =
10701074
{ x with
10711075
tcsCreatesGeneratedProvidedTypes = y
10721076
}
1077+
1078+
member x.WithStuff tcEnv rootSigs creates : TcState =
1079+
{ x with
1080+
tcsTcSigEnv = tcEnv
1081+
tcsRootSigs = rootSigs
1082+
tcsCreatesGeneratedProvidedTypes = creates
1083+
}
10731084

10741085
type State = TcState * bool
10751086

@@ -1814,215 +1825,6 @@ let mutable CheckMultipleInputsInParallel2 : CheckArgs -> (PartialResult list *
18141825
=
18151826
CheckMultipleInputsInParallel
18161827

1817-
type WorkInput =
1818-
{
1819-
FileIndex : int
1820-
ParsedInput : ParsedInput
1821-
Logger : DiagnosticsLogger
1822-
}
1823-
1824-
/// Use parallel checking of implementation files that have signature files
1825-
let CheckMultipleInputsInParallel3
1826-
((ctok : CompilationThreadToken,
1827-
checkForErrors: unit -> bool,
1828-
tcConfig: TcConfig,
1829-
tcImports: TcImports,
1830-
tcGlobals: TcGlobals,
1831-
prefixPathOpt,
1832-
tcState,
1833-
eagerFormat,
1834-
inputs): CompilationThreadToken * (unit -> bool) * TcConfig * TcImports * TcGlobals * LongIdent option * TcState * (PhasedDiagnostic -> PhasedDiagnostic) * ParsedInput list)
1835-
: PartialResult list * TcState =
1836-
1837-
let _ = ctok // TODO Use
1838-
let diagnosticsLogger = DiagnosticsThreadStatics.DiagnosticsLogger
1839-
1840-
// In the first linear part of parallel checking, we use a 'checkForErrors' that checks either for errors
1841-
// somewhere in the files processed prior to each one, or in the processing of this particular file.
1842-
let priorErrors = checkForErrors ()
1843-
let amap = tcImports.GetImportMap()
1844-
let conditionalDefines =
1845-
if tcConfig.noConditionalErasure then
1846-
None
1847-
else
1848-
Some tcConfig.conditionalDefines
1849-
1850-
let processFile
1851-
(currentTcState : TcState)
1852-
((input, logger) : ParsedInput * DiagnosticsLogger)
1853-
: State -> PartialResult * State =
1854-
cancellable {
1855-
use _ = UseDiagnosticsLogger logger
1856-
// Is it OK that we don't update 'priorErrors' after processing batches?
1857-
let checkForErrors2 () = priorErrors || (logger.ErrorCount > 0)
1858-
1859-
// this is taken mostly from CheckOneInputAux, the case where the impl has no signature file
1860-
let file =
1861-
match input with
1862-
| ParsedInput.ImplFile file -> file
1863-
| ParsedInput.SigFile _ -> failwith "not expecting a signature file for now"
1864-
1865-
let tcSink = TcResultsSink.NoSink
1866-
1867-
// Typecheck the implementation file
1868-
let! topAttrs, implFile, tcEnvAtEnd, createsGeneratedProvidedTypes =
1869-
CheckOneImplFile(
1870-
tcGlobals,
1871-
amap,
1872-
currentTcState.tcsCcu,
1873-
currentTcState.tcsImplicitOpenDeclarations,
1874-
checkForErrors2,
1875-
conditionalDefines,
1876-
TcResultsSink.NoSink,
1877-
tcConfig.internalTestSpanStackReferring,
1878-
currentTcState.tcsTcImplEnv,
1879-
None,
1880-
file
1881-
)
1882-
1883-
return
1884-
(fun (state : State) ->
1885-
let tcState, _priorErrors = state
1886-
let tcState =
1887-
{ tcState with
1888-
tcsCreatesGeneratedProvidedTypes =
1889-
tcState.tcsCreatesGeneratedProvidedTypes || createsGeneratedProvidedTypes
1890-
}
1891-
1892-
let ccuSigForFile, updatedTcState =
1893-
let results =
1894-
tcGlobals,
1895-
amap,
1896-
false,
1897-
prefixPathOpt,
1898-
tcSink,
1899-
tcState.tcsTcImplEnv,
1900-
input.QualifiedName,
1901-
implFile.Signature
1902-
1903-
AddCheckResultsToTcState results tcState
1904-
1905-
let partialResult : PartialResult = tcEnvAtEnd, topAttrs, Some implFile, ccuSigForFile
1906-
let hasErrors = logger.ErrorCount > 0
1907-
let priorOrCurrentErrors = priorErrors || hasErrors
1908-
let state : State = updatedTcState, priorOrCurrentErrors
1909-
1910-
partialResult, state
1911-
)
1912-
}
1913-
|> Cancellable.runWithoutCancellation
1914-
1915-
1916-
// We create one CapturingDiagnosticLogger for each file we are processing and
1917-
// ensure the diagnostics are presented in deterministic order.
1918-
//
1919-
// eagerFormat is used to format diagnostics as they are emitted, just as they would be in the command-line
1920-
// compiler. This is necessary because some formatting of diagnostics is dependent on the
1921-
// type inference state at precisely the time the diagnostic is emitted.
1922-
// TODO Does this mean we can't have more than one TcState with different contents?
1923-
// How does the formatting code know the state of type-checking/type inference? We don't pass it to the formatter directly
1924-
UseMultipleDiagnosticLoggers (inputs, diagnosticsLogger, Some eagerFormat) (fun inputsWithLoggers ->
1925-
1926-
// Equip loggers to locally filter w.r.t. scope pragmas in each input
1927-
let inputsWithLoggers: (ParsedInput * DiagnosticsLogger)[] =
1928-
inputsWithLoggers
1929-
|> Seq.map (fun (input, oldLogger) ->
1930-
let logger = DiagnosticsLoggerForInput(tcConfig, input, oldLogger)
1931-
input, logger)
1932-
|> Seq.toArray
1933-
1934-
// In the first linear part of parallel checking, we use a 'checkForErrors' that checks either for errors
1935-
// somewhere in the files processed prior to each one, or in the processing of this particular file.
1936-
let priorErrors = checkForErrors ()
1937-
1938-
// Grand experiment
1939-
// This code assumes the following file structure
1940-
// A.fs
1941-
// B1.fs (uses A)
1942-
// B2.fs (uses A, B1)
1943-
// C1.fs (uses A)
1944-
// C2.fs (uses A, C1)
1945-
// D.fs (uses A, B2, C2)
1946-
assert (inputsWithLoggers.Length = 6)
1947-
1948-
let fileDependencies =
1949-
[|
1950-
Set.empty
1951-
set [ 0 ]
1952-
set [ 0; 1 ]
1953-
set [ 0 ]
1954-
set [ 0; 3 ]
1955-
set [ 0; 2; 4 ]
1956-
|]
1957-
1958-
let partialResults, (state : State) =
1959-
let lastIndex = inputsWithLoggers.Length - 1
1960-
1961-
// This function will type check all the files where it knows all the dependent file have already been seen.
1962-
// The `freeFiles` are a set of file indexes that have been type checked in a previous run.
1963-
// `processedFiles` stores the result of a typed checked file in a mutable fashion.
1964-
let rec visit (state : State) (freeFiles: Set<int>) (processedFiles: PartialResult array): PartialResult array * State =
1965-
let (currentTcState, currentPriorErrors) = state
1966-
// Find files that still needs processing.
1967-
let unprocessedFiles = freeFiles |> Set.difference (set [| 0..lastIndex |])
1968-
1969-
if Set.isEmpty unprocessedFiles then
1970-
// All done
1971-
processedFiles, state
1972-
else
1973-
// What files can we type check from the files that are left to type check.
1974-
let nextFreeIndexes: (int * (ParsedInput * DiagnosticsLogger))[] =
1975-
unprocessedFiles
1976-
|> Seq.choose (fun fileIndex ->
1977-
let isFreeFile =
1978-
Seq.forall (fun idx -> Set.contains idx freeFiles) fileDependencies.[fileIndex]
1979-
1980-
if isFreeFile then
1981-
Some(fileIndex, inputsWithLoggers.[fileIndex])
1982-
else
1983-
None)
1984-
|> Seq.toArray
1985-
1986-
let go (fileIndex : int, (input, logger)) : State -> int * (PartialResult * State) =
1987-
let r = processFile currentTcState (input, logger)
1988-
fun state ->
1989-
fileIndex, r state
1990-
1991-
// The next batch of files we can process in parallel
1992-
let next =
1993-
nextFreeIndexes
1994-
|> ArrayParallel.map go
1995-
|> fun results ->
1996-
((currentTcState, currentPriorErrors), results)
1997-
||> Array.fold (fun state result ->
1998-
// the `result` callback ensure that the TcState is synced correctly after a batch of file has been type checked in parallel.
1999-
// I believe this bit cannot be done in parallel, yet the order in which we fold the state does not matter.
2000-
let fileIndex, (partialResult, state) = result state
2001-
// Yikes!
2002-
// Nah, it's okay.
2003-
processedFiles[fileIndex] <- partialResult
2004-
state
2005-
)
2006-
2007-
// The next set of free files are the previous ones + the files we just type checked.
2008-
let nextFreeIndexes =
2009-
seq {
2010-
yield! freeFiles
2011-
yield! (Seq.map fst nextFreeIndexes)
2012-
}
2013-
|> Set.ofSeq
2014-
2015-
// Next round!
2016-
visit next nextFreeIndexes processedFiles
2017-
2018-
visit (tcState, priorErrors) Set.empty (Array.zeroCreate inputsWithLoggers.Length)
2019-
2020-
let tcState, _errors = state
2021-
let partialResults = partialResults |> Array.toList
2022-
partialResults, tcState
2023-
)
2024-
2025-
20261828
let CheckClosedInputSet (ctok, checkForErrors, tcConfig: TcConfig, tcImports, tcGlobals, prefixPathOpt, tcState, eagerFormat, inputs) =
20271829
// tcEnvAtEndOfLastFile is the environment required by fsi.exe when incrementally adding definitions
20281830
let results, tcState =

src/Compiler/Driver/ParseAndCheckInputs.fsi

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,10 @@ type TcState =
120120
/// The CcuThunk for the current assembly being checked
121121
member Ccu: CcuThunk
122122

123+
member TcsRootSigs : Internal.Utilities.Collections.Zmap<QualifiedNameOfFile, ModuleOrNamespaceType>
124+
125+
member TcsRootImpls : Internal.Utilities.Collections.Zset<QualifiedNameOfFile>
126+
123127
/// Get the typing environment implied by the set of signature files and/or inferred signatures of implementation files checked so far
124128
member TcEnvFromSignatures: TcEnv
125129

@@ -136,6 +140,8 @@ type TcState =
136140

137141
member TcsImplicitOpenDeclarations: OpenDeclaration list
138142

143+
member WithStuff : TcEnv -> Internal.Utilities.Collections.Zmap<QualifiedNameOfFile, ModuleOrNamespaceType> -> bool -> TcState
144+
139145
member WithCreatesGeneratedProvidedTypes : bool -> TcState
140146

141147
val AddCheckResultsToTcState :

src/Compiler/FSharp.Compiler.Service.fsproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@
7575
<InternalsVisibleTo Include="VisualFSharp.UnitTests" />
7676
<InternalsVisibleTo Include="FSharp.Compiler.UnitTests" />
7777
<InternalsVisibleTo Include="FSharp.Compiler.Service.Tests" />
78-
<InternalsVisibleTo Include="FSharp.Compiler.Service.Tests2" />
78+
<InternalsVisibleTo Include="ParallelTypeCheckingTests" />
7979
<InternalsVisibleTo Include="HostedCompilerServer" />
8080
<InternalsVisibleTo Include="FSharp.Tests.FSharpSuite" />
8181
<InternalsVisibleTo Include="LanguageServiceProfiling" />

src/Compiler/Utilities/lib.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ module ArrayParallel =
606606
arr |> iteri (fun i item -> mapped[i] <- f i item)
607607
mapped
608608

609-
let inline map f (arr: 'T []) =
609+
let map f (arr: 'T []) =
610610
arr |> mapi (fun _ item -> f item)
611611

612612
[<RequireQualifiedAccess>]

src/Compiler/Utilities/lib.fsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,7 @@ module ArrayParallel =
319319

320320
val inline iteri: (int -> 'T -> unit) -> 'T[] -> unit
321321

322-
val inline map: ('T -> 'U) -> 'T[] -> 'U[]
322+
val map: ('T -> 'U) -> 'T[] -> 'U[]
323323

324324
val inline mapi: (int -> 'T -> 'U) -> 'T[] -> 'U[]
325325

src/fsc/fscProject/fsc.fsproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
</PropertyGroup>
1717

1818
<ItemGroup>
19-
<InternalsVisibleTo Include="FSharp.Compiler.Service.Tests2" />
19+
<InternalsVisibleTo Include="ParallelTypeCheckingTests" />
2020
</ItemGroup>
2121

2222
<Import Project="$([MSBuild]::GetPathOfFileAbove('fsc.targets', '$(MSBuildThisFileDirectory)../'))" />

src/fsc/fscmain.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
22

3-
module internal FSharp.Compiler.CommandLineMain
3+
module FSharp.Compiler.CommandLineMain
44

55
open System
66

tests/FSharp.Compiler.ComponentTests/TypeChecks/ParallelCheckingWithSignatureFilesTests.fs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ val decode: string -> obj
4646
"Decode.fs",
4747
"""
4848
module Decode
49-
49+
let x : int = ""
5050
let decode (v: string) : obj = failwith "todo"
5151
"""
5252
)

0 commit comments

Comments
 (0)