Skip to content
Closed
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
28 changes: 20 additions & 8 deletions azure-pipelines-PR.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ stages:
helixRepo: dotnet/fsharp
jobs:
# Determinism, we want to run it only in PR builds
- job: Determinism_Debug
- job: Determinism_Release
condition: eq(variables['Build.Reason'], 'PullRequest')
variables:
- name: _SignType
Expand All @@ -110,11 +110,23 @@ stages:
demands: ImageOverride -equals $(_WindowsMachineQueueName)
timeoutInMinutes: 90
strategy:
maxParallel: 2
maxParallel: 8
matrix:
regular:
iter1:
_experimental_flag: ''
iter2:
_experimental_flag: ''
iter3:
_experimental_flag: ''
iter4:
_experimental_flag: ''
iter5:
_experimental_flag: ''
iter6:
_experimental_flag: ''
iter7:
_experimental_flag: ''
experimental_features:
iter8:
_experimental_flag: ''
steps:
- checkout: self
Expand All @@ -129,15 +141,15 @@ stages:
workingDirectory: $(Build.SourcesDirectory)
installationPath: $(Build.SourcesDirectory)/.dotnet
- script: .\eng\common\dotnet.cmd
- script: .\eng\test-determinism.cmd -configuration Debug
- script: .\eng\test-determinism.cmd -configuration Release
env:
FSHARP_EXPERIMENTAL_FEATURES: $(_experimental_flag)
displayName: Determinism tests with Debug configuration
displayName: Determinism tests with Release configuration
- task: PublishPipelineArtifact@1
displayName: Publish Determinism Logs
inputs:
targetPath: '$(Build.SourcesDirectory)/artifacts/log/Debug'
artifactName: 'Determinism_Debug Attempt $(System.JobAttempt) Logs'
targetPath: '$(Build.SourcesDirectory)/artifacts/log/Release'
artifactName: 'Determinism_Release Attempt $(System.JobAttempt) Logs'
continueOnError: true
condition: not(succeeded())

Expand Down
91 changes: 91 additions & 0 deletions tests/fsharp/Compiler/CodeGen/EmittedIL/DeterministicTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,97 @@ let inline myFunc x y = x - y"""
else
Assert.NotEqual(mvid1,mvid2)

// https://github.com/dotnet/fsharp/issues/19732
// Differential test: compile the same multi-file project once fully sequentially
// and once fully parallel, with --deterministic. If the MVIDs differ, the
// compiler is non-deterministic with respect to its own internal parallelism.
// This is a hard, repeatable signal — no need to retry across runs.
[<Fact>]
let ``Parallel and sequential compilation must produce identical assemblies`` () =
let outputDir = DirectoryInfo(Path.Combine(Path.GetTempPath(), "fsharp-determinism-seqpar"))
if outputDir.Exists then outputDir.Delete(true)
outputDir.Create()

let makeFile i =
let src =
(sprintf
"""
module File%d

let processTuple%d (a: int, b: string) =
let inner x = x + a
let nested () = inner 42
(nested (), b.Length)

let anon%d () =
{| Name = "f%d"; Index = %d; Children = [| 1; 2; 3 |] |}

let anon%db () =
{| Tag = "T%d"; Value = %d * 7; Extras = "x" |}

let useAnon%d () =
let r = anon%d ()
let r2 = anon%db ()
let composed (k: int) =
let h x = x + r.Index + r2.Value + k
h 100
composed 0 + r.Name.Length

[<Struct>]
type Rec%d = { X: int; Y: string }

let mkRec%d () = { X = %d; Y = "rec%d" }
"""
i i i i i i i i i i i i i i i)

FsSourceWithFileName $"File%d{i}.fs" src

let additionalFiles = [ for i in 2..12 -> makeFile i ]

let compileWith parallelism =
FSharp
"""
module File1

let processTuple1 (a: int, b: string) =
let inner x = x + a
let nested () = inner 42
(nested (), b.Length)

let anon1 () =
{| Name = "f1"; Index = 1; Children = [| 1; 2; 3 |] |}

let anon1b () =
{| Tag = "T1"; Value = 7; Extras = "x" |}

let useAnon1 () =
let r = anon1 ()
let r2 = anon1b ()
let composed (k: int) =
let h x = x + r.Index + r2.Value + k
h 100
composed 0 + r.Name.Length

[<Struct>]
type Rec1 = { X: int; Y: string }

let mkRec1 () = { X = 1; Y = "rec1" }
"""
|> withAdditionalSourceFiles additionalFiles
|> asLibrary
|> withOptimize
|> withName "DetTest"
|> withOutputDirectory (Some outputDir)
|> withOptions ("--deterministic" :: "--nowarn:75" :: parallelism)
|> compileGuid

let seqMvid = compileWith [ "--parallelcompilation-"; "--test:ParallelOff" ]
let parMvid = compileWith [ "--parallelcompilation+" ]

outputDir.Delete(true)

Assert.Equal(seqMvid, parMvid)

[<Fact>]
let ``Reference assemblies MVID must change when literal constant value changes`` () =
let codeWithLiteral42 = """
Expand Down
Loading