Skip to content

Commit 10c1eff

Browse files
safesparrownojaf
andauthored
Parallel type-checking in compilation (behind a feature flag) (#14494)
Parallel type-checking in compilation (behind a feature flag) --------- Co-authored-by: nojaf <florian.verdonck@outlook.com>
1 parent a2c0c22 commit 10c1eff

File tree

70 files changed

+5270
-232
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

70 files changed

+5270
-232
lines changed

FSharpBuild.Directory.Build.props

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@
2626
<WarningsAsErrors>1182;0025;$(WarningsAsErrors)</WarningsAsErrors>
2727
<OtherFlags>$(OtherFlags) --nowarn:3384</OtherFlags>
2828
<OtherFlags>$(OtherFlags) --times --nowarn:75</OtherFlags>
29-
<OtherFlags Condition="$(ParallelCheckingWithSignatureFilesOn) == 'true'">$(OtherFlags) --test:ParallelCheckingWithSignatureFilesOn</OtherFlags>
3029
<OtherFlags Condition="$(AdditionalFscCmdFlags) != ''">$(OtherFlags) $(AdditionalFscCmdFlags)</OtherFlags>
3130
</PropertyGroup>
3231

src/Compiler/Checking/CheckDeclarations.fs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3028,6 +3028,17 @@ module EstablishTypeDefinitionCores =
30283028
let kind = if hasMeasureAttr then TyparKind.Measure else TyparKind.Type
30293029
let ty, _ = TcTypeOrMeasureAndRecover (Some kind) cenv NoNewTypars checkConstraints ItemOccurence.UseInType WarnOnIWSAM.No envinner tpenv rhsType
30303030

3031+
// Give a warning if `AutoOpenAttribute` is being aliased.
3032+
// If the user were to alias the `Microsoft.FSharp.Core.AutoOpenAttribute` type, it would not be detected by the project graph dependency resolution algorithm.
3033+
match stripTyEqns g ty with
3034+
| AppTy g (tcref, _) when not tcref.IsErased ->
3035+
match tcref.CompiledRepresentation with
3036+
| CompiledTypeRepr.ILAsmOpen _ -> ()
3037+
| CompiledTypeRepr.ILAsmNamed _ ->
3038+
if tcref.CompiledRepresentationForNamedType.FullName = g.attrib_AutoOpenAttribute.TypeRef.FullName then
3039+
warning(Error(FSComp.SR.chkAutoOpenAttributeInTypeAbbrev(), tycon.Id.idRange))
3040+
| _ -> ()
3041+
30313042
if not firstPass then
30323043
let ftyvs = freeInTypeLeftToRight g false ty
30333044
let typars = tycon.Typars m
@@ -4278,7 +4289,7 @@ module TcDeclarations =
42784289

42794290
if not (isNil members) && tcref.IsTypeAbbrev then
42804291
errorR(Error(FSComp.SR.tcTypeAbbreviationsCannotHaveAugmentations(), tyDeclRange))
4281-
4292+
42824293
let (SynComponentInfo (attributes, _, _, _, _, _, _, _)) = synTyconInfo
42834294
if not (List.isEmpty attributes) && (declKind = ExtrinsicExtensionBinding || declKind = IntrinsicExtensionBinding) then
42844295
let attributeRange = (List.head attributes).Range

src/Compiler/Driver/CompilerConfig.fs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -393,6 +393,18 @@ type ParallelReferenceResolution =
393393
| On
394394
| Off
395395

396+
[<RequireQualifiedAccess>]
397+
type TypeCheckingMode =
398+
| Sequential
399+
| Graph
400+
401+
[<RequireQualifiedAccess>]
402+
type TypeCheckingConfig =
403+
{
404+
Mode: TypeCheckingMode
405+
DumpGraph: bool
406+
}
407+
396408
[<NoEquality; NoComparison>]
397409
type TcConfigBuilder =
398410
{
@@ -507,7 +519,6 @@ type TcConfigBuilder =
507519
mutable emitTailcalls: bool
508520
mutable deterministic: bool
509521
mutable concurrentBuild: bool
510-
mutable parallelCheckingWithSignatureFiles: bool
511522
mutable parallelIlxGen: bool
512523
mutable emitMetadataAssembly: MetadataAssemblyGeneration
513524
mutable preferredUiLang: string option
@@ -591,6 +602,8 @@ type TcConfigBuilder =
591602
mutable parallelReferenceResolution: ParallelReferenceResolution
592603

593604
mutable captureIdentifiersWhenParsing: bool
605+
606+
mutable typeCheckingConfig: TypeCheckingConfig
594607
}
595608

596609
// Directories to start probing in
@@ -737,7 +750,6 @@ type TcConfigBuilder =
737750
emitTailcalls = true
738751
deterministic = false
739752
concurrentBuild = true
740-
parallelCheckingWithSignatureFiles = FSharpExperimentalFeaturesEnabledAutomatically
741753
parallelIlxGen = FSharpExperimentalFeaturesEnabledAutomatically
742754
emitMetadataAssembly = MetadataAssemblyGeneration.None
743755
preferredUiLang = None
@@ -782,6 +794,15 @@ type TcConfigBuilder =
782794
exiter = QuitProcessExiter
783795
parallelReferenceResolution = ParallelReferenceResolution.Off
784796
captureIdentifiersWhenParsing = false
797+
typeCheckingConfig =
798+
{
799+
TypeCheckingConfig.Mode =
800+
if FSharpExperimentalFeaturesEnabledAutomatically then
801+
TypeCheckingMode.Graph
802+
else
803+
TypeCheckingMode.Sequential
804+
DumpGraph = false
805+
}
785806
}
786807

787808
member tcConfigB.FxResolver =
@@ -1286,7 +1307,6 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) =
12861307
member _.emitTailcalls = data.emitTailcalls
12871308
member _.deterministic = data.deterministic
12881309
member _.concurrentBuild = data.concurrentBuild
1289-
member _.parallelCheckingWithSignatureFiles = data.parallelCheckingWithSignatureFiles
12901310
member _.parallelIlxGen = data.parallelIlxGen
12911311
member _.emitMetadataAssembly = data.emitMetadataAssembly
12921312
member _.pathMap = data.pathMap
@@ -1322,6 +1342,7 @@ type TcConfig private (data: TcConfigBuilder, validate: bool) =
13221342
member _.exiter = data.exiter
13231343
member _.parallelReferenceResolution = data.parallelReferenceResolution
13241344
member _.captureIdentifiersWhenParsing = data.captureIdentifiersWhenParsing
1345+
member _.typeCheckingConfig = data.typeCheckingConfig
13251346

13261347
static member Create(builder, validate) =
13271348
use _ = UseBuildPhase BuildPhase.Parameter

src/Compiler/Driver/CompilerConfig.fsi

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,24 @@ type ParallelReferenceResolution =
203203
| On
204204
| Off
205205

206+
/// Determines the algorithm used for type-checking.
207+
[<RequireQualifiedAccess>]
208+
type TypeCheckingMode =
209+
/// Default mode where all source files are processed sequentially in compilation order.
210+
| Sequential
211+
/// Parallel type-checking that uses automated file-to-file dependency detection to construct a file graph processed in parallel.
212+
| Graph
213+
214+
/// Some of the information dedicated to type-checking.
215+
[<RequireQualifiedAccess>]
216+
type TypeCheckingConfig =
217+
{
218+
Mode: TypeCheckingMode
219+
/// When using TypeCheckingMode.Graph, this flag determines whether the
220+
/// resolved file graph should be serialised as a Mermaid diagram into a file next to the output dll.
221+
DumpGraph: bool
222+
}
223+
206224
[<NoEquality; NoComparison>]
207225
type TcConfigBuilder =
208226
{
@@ -412,8 +430,6 @@ type TcConfigBuilder =
412430

413431
mutable concurrentBuild: bool
414432

415-
mutable parallelCheckingWithSignatureFiles: bool
416-
417433
mutable parallelIlxGen: bool
418434

419435
mutable emitMetadataAssembly: MetadataAssemblyGeneration
@@ -495,6 +511,8 @@ type TcConfigBuilder =
495511
mutable parallelReferenceResolution: ParallelReferenceResolution
496512

497513
mutable captureIdentifiersWhenParsing: bool
514+
515+
mutable typeCheckingConfig: TypeCheckingConfig
498516
}
499517

500518
static member CreateNew:
@@ -738,8 +756,6 @@ type TcConfig =
738756

739757
member concurrentBuild: bool
740758

741-
member parallelCheckingWithSignatureFiles: bool
742-
743759
member parallelIlxGen: bool
744760

745761
member emitMetadataAssembly: MetadataAssemblyGeneration
@@ -866,6 +882,8 @@ type TcConfig =
866882

867883
member captureIdentifiersWhenParsing: bool
868884

885+
member typeCheckingConfig: TypeCheckingConfig
886+
869887
/// Represents a computation to return a TcConfig. Normally this is just a constant immutable TcConfig,
870888
/// but for F# Interactive it may be based on an underlying mutable TcConfigBuilder.
871889
[<Sealed>]

src/Compiler/Driver/CompilerOptions.fs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1372,8 +1372,17 @@ let testFlag tcConfigB =
13721372
| "ShowLoadedAssemblies" -> tcConfigB.showLoadedAssemblies <- true
13731373
| "ContinueAfterParseFailure" -> tcConfigB.continueAfterParseFailure <- true
13741374
| "ParallelOff" -> tcConfigB.concurrentBuild <- false
1375-
| "ParallelCheckingWithSignatureFilesOn" -> tcConfigB.parallelCheckingWithSignatureFiles <- true
13761375
| "ParallelIlxGen" -> tcConfigB.parallelIlxGen <- true
1376+
| "GraphBasedChecking" ->
1377+
tcConfigB.typeCheckingConfig <-
1378+
{ tcConfigB.typeCheckingConfig with
1379+
Mode = TypeCheckingMode.Graph
1380+
}
1381+
| "DumpCheckingGraph" ->
1382+
tcConfigB.typeCheckingConfig <-
1383+
{ tcConfigB.typeCheckingConfig with
1384+
DumpGraph = true
1385+
}
13771386
#if DEBUG
13781387
| "ShowParserStackOnParseError" -> showParserStackOnParseError <- true
13791388
#endif
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
[<RequireQualifiedAccess>]
2+
module internal Continuation
3+
4+
let rec sequence<'T, 'TReturn> (recursions: (('T -> 'TReturn) -> 'TReturn) list) (finalContinuation: 'T list -> 'TReturn) : 'TReturn =
5+
match recursions with
6+
| [] -> finalContinuation []
7+
| andThenInner :: andThenInners ->
8+
fun (results: 'T list) ->
9+
fun (result: 'T) -> result :: results |> finalContinuation
10+
|> andThenInner
11+
|> sequence andThenInners
12+
13+
let concatenate<'T, 'TReturn> (recursions: (('T list -> 'TReturn) -> 'TReturn) list) (finalContinuation: 'T list -> 'TReturn) : 'TReturn =
14+
let ultimateContinuation = List.concat >> finalContinuation
15+
sequence recursions ultimateContinuation
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
[<RequireQualifiedAccess>]
2+
module internal Continuation
3+
4+
/// This function sequences computations that have been expressed in continuation-passing style.
5+
/// Concretely, when 'T is `int` as an example, can be expressed in continuation-passing style as a function,
6+
/// taking as its input another function that is "how to proceed with a computation given the value of the integer",
7+
/// and returning "the result of that computation".
8+
/// That is, an integer is equivalently represented as a generic function (howToProceed : int -> 'TReturn) -> 'TReturn,
9+
/// and the effect of the function corresponding to the integer 3 is simply to apply the input `howToProceed` to the value 3.
10+
///
11+
/// The motivation for Continuation.sequence is most easily understood when it is viewed without its second argument:
12+
/// it is a higher-order function that takes "a list of 'T expressed in continuation-passing style", and returns "a 'T list expressed in continuation-passing style".
13+
/// The resulting "continuation-passing 'T list" operates by chaining the input 'Ts together, and finally returning the result of continuing the computation after first sequencing the inputs.
14+
///
15+
/// Crucially, this technique can be used to enable unbounded recursion:
16+
/// it constructs and invokes closures representing intermediate stages of the sequenced computation on the heap, rather than consuming space on the (more constrained) stack.
17+
val sequence<'T, 'TReturn> :
18+
recursions: (('T -> 'TReturn) -> 'TReturn) list -> finalContinuation: ('T list -> 'TReturn) -> 'TReturn
19+
20+
/// Auxiliary function for `Continuation.sequence` that assumes the recursions return a 'T list.
21+
/// In the final continuation the `'T list list` will first be concatenated into one list, before being passed to the (final) `continuation`.
22+
val concatenate<'T, 'TReturn> :
23+
recursions: (('T list -> 'TReturn) -> 'TReturn) list -> finalContinuation: ('T list -> 'TReturn) -> 'TReturn

0 commit comments

Comments
 (0)