Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
91 commits
Select commit Hold shift + click to select a range
6f59f9f
Stabilize parallel optimizer Val iteration for deterministic names (#…
T-Gro May 26, 2026
2b39c15
Add Val.Stamp tiebreaker to sort keys; fix release note
T-Gro May 27, 2026
151f443
Address self-review: extract helper, trim prose, run determinism in R…
T-Gro May 28, 2026
c067580
Retrigger CI
T-Gro May 28, 2026
e44ee25
Revert CI to Debug config, add multi-file determinism regression test
T-Gro May 28, 2026
6f8ba18
Re-enable Determinism_Release CI
T-Gro May 29, 2026
1498292
Make TypeDefsBuilder emit order deterministic under parallel codegen
T-Gro May 31, 2026
684b291
Stabilize extra binding emit order and parallel FileIndex assignment
T-Gro May 31, 2026
e279b7e
Update release note to cover full determinism scope
T-Gro May 31, 2026
a629ee6
Stabilize IL emit order across --parallelcompilation+/-
T-Gro Jun 1, 2026
609540e
Round 1 review fixes: tighter code, debug-assert tiebreaker safety, t…
T-Gro Jun 1, 2026
7f5fe7a
Round 2 review fixes: drop speculative locks, drop unsound assertion,…
T-Gro Jun 1, 2026
55d983d
Merge remote-tracking branch 'origin/main' into HEAD
T-Gro Jun 1, 2026
2e30a0a
Update net472 anon-record IL baselines and trimmed size
T-Gro Jun 1, 2026
27718b2
test-determinism: add seq-vs-par mode for 1-shot deterministic diff
T-Gro Jun 1, 2026
1ad8183
CI: add seq-vs-par determinism leg alongside the race detector
T-Gro Jun 1, 2026
4e1b248
Remove .scratch/ files accidentally included in previous commit
T-Gro Jun 1, 2026
87cdc4c
CI: mark seq-vs-par determinism leg as informational (continueOnError)
T-Gro Jun 2, 2026
b28c598
Revert "CI: mark seq-vs-par determinism leg as informational (continu…
T-Gro Jun 2, 2026
3ed584d
Revert "Update net472 anon-record IL baselines and trimmed size"
T-Gro Jun 2, 2026
ecc5eaa
Revert "Round 2 review fixes: drop speculative locks, drop unsound as…
T-Gro Jun 2, 2026
f6006be
Revert "Round 1 review fixes: tighter code, debug-assert tiebreaker s…
T-Gro Jun 2, 2026
5a6226a
Revert "Stabilize IL emit order across --parallelcompilation+/-"
T-Gro Jun 2, 2026
27f854c
Revert "Stabilize extra binding emit order and parallel FileIndex ass…
T-Gro Jun 2, 2026
903471b
Revert "Make TypeDefsBuilder emit order deterministic under parallel …
T-Gro Jun 2, 2026
0976278
Merge remote-tracking branch 'origin/main' into pr-19810
T-Gro Jun 2, 2026
602f23c
Option B: per-ImplFile naming scope + deterministic FileIndex pre-reg…
T-Gro Jun 2, 2026
97a5d76
Bucket compiler-generated names by emitting file for parallel determi…
T-Gro Jun 2, 2026
67c14fd
Revert "Bucket compiler-generated names by emitting file for parallel…
T-Gro Jun 2, 2026
83eb8eb
Reapply IlxGen emit-order determinism and per-file CodegenNamingScope
Jun 3, 2026
d688459
Merge remote-tracking branch 'origin/main' into fix-deterministic-str…
Jun 3, 2026
d406e33
Fix CodegenNamingScope: use actual FileIndex and Lazy for determinism
Jun 3, 2026
04d034a
Merge remote-tracking branch 'origin/main' into fix-deterministic-str…
Jun 3, 2026
a53d13a
Revert "Fix CodegenNamingScope: use actual FileIndex and Lazy for det…
T-Gro Jun 4, 2026
80215df
Revert "Reapply IlxGen emit-order determinism and per-file CodegenNam…
T-Gro Jun 4, 2026
e72ec26
Determinism for #19732: prime StableNameGenerator before parallel cod…
T-Gro Jun 4, 2026
b137970
Merge branch 'main' into fix-deterministic-strings
T-Gro Jun 4, 2026
22f4e5f
fantomas formatting fix
T-Gro Jun 4, 2026
4f8a94c
StableNiceNameGenerator: wrap niceNames factory in Lazy<string>
T-Gro Jun 4, 2026
b843fbe
Optimizer: sort ValInfos entries before pickling for deterministic op…
T-Gro Jun 4, 2026
2206d47
DeterministicallySortIlModule: sort only within types, preserve decla…
T-Gro Jun 4, 2026
d885ff7
fantomas formatting fix
T-Gro Jun 4, 2026
611bb32
Drop DeterministicallySortIlModule; sequentialize codegen iter
T-Gro Jun 4, 2026
9ec6a96
Cleanup: drop now-dead per-file closure-naming scope plumbing
T-Gro Jun 4, 2026
2ab1b83
fantomas formatting fix
T-Gro Jun 4, 2026
cf5d32e
Force sequential pipelines under --deterministic+
T-Gro Jun 4, 2026
127e5be
Cleanup: revert defensive workarounds, the deterministic guard subsum…
T-Gro Jun 4, 2026
dc63444
Revert "Cleanup: revert defensive workarounds, the deterministic guar…
T-Gro Jun 5, 2026
0fcabd6
Revert "Force sequential pipelines under --deterministic+"
T-Gro Jun 5, 2026
dc81124
Optimizer: canonicalize ValMakesNoCriticalTailcalls at pickle time
T-Gro Jun 5, 2026
46a753e
IlxGen: stable nested-type sort key to fix Windows determinism race
T-Gro Jun 5, 2026
d8bd9ca
Revert "IlxGen: stable nested-type sort key to fix Windows determinis…
T-Gro Jun 5, 2026
7eee766
IlxGen: stable source-position sort for AddTypeDef + drop seq-vs-par …
T-Gro Jun 5, 2026
0e1ee34
Revert AddTypeDef source-position sort
T-Gro Jun 5, 2026
11273a9
Revert "IlxGen: stable source-position sort for AddTypeDef + drop seq…
T-Gro Jun 5, 2026
7584d84
Revert "Revert AddTypeDef source-position sort"
T-Gro Jun 5, 2026
a52dbec
Undo AddTypeDef sort, keep CI seq-vs-par gate restored
T-Gro Jun 5, 2026
b60e4a0
IlxGen: close seq-vs-par byte-equality gap via source-order priming +…
T-Gro Jun 5, 2026
04e6ca0
Revert "IlxGen: close seq-vs-par byte-equality gap via source-order p…
T-Gro Jun 5, 2026
b65bb11
IlxGen: always emit method bodies inline so seq-vs-par produces ident…
T-Gro Jun 5, 2026
f9e6191
Restore parallel codegen with deterministic ordering (#19732)
T-Gro Jun 8, 2026
3e41953
IlxGen: split addAtEnd=true sort into two buckets (#19732)
T-Gro Jun 8, 2026
955fe85
IlxGen: drop Lambda closure-name priming (#19732)
T-Gro Jun 9, 2026
5413489
EmittedIL: regenerate baselines for deterministic codegen ordering (#…
T-Gro Jun 9, 2026
a3d8690
IlxGen: safe inline strip of outer Top-Lambda in PrimeStableNamesForC…
T-Gro Jun 9, 2026
bfd4e34
SequenceExpressionTests: update Basic-recursive IL baseline for .ccto…
T-Gro Jun 9, 2026
2f7287f
EmittedIL: additional baseline regen after Phase 1.8 (#19732)
T-Gro Jun 9, 2026
315ca28
Update test sources/baselines for emit-order changes (#19732)
T-Gro Jun 9, 2026
56d4e1b
IlxGen: preserve field/event insertion order (don't sort) (#19732)
T-Gro Jun 9, 2026
f810d70
EmittedIL: third baseline regen for field-order-preserve fix (#19732)
T-Gro Jun 9, 2026
ecfb86e
EmittedIL: regen 61 more baselines + StaticLet field-order swap (#19732)
T-Gro Jun 9, 2026
3d09f00
Merge remote-tracking branch 'origin/main' into fix-deterministic-str…
T-Gro Jun 9, 2026
4c24edb
fantomas: format IlxGen.fs after merge (#19732)
T-Gro Jun 9, 2026
9253e83
CI: drop seq-vs-par determinism leg, keep strict same-flags Release (…
T-Gro Jun 10, 2026
074c858
WIP: PerFileClosureNameScope for closure type names — partial fix for…
T-Gro Jun 10, 2026
10a5b1a
Determinism: SEQ=PAR byte-identical (closes #19928)
T-Gro Jun 10, 2026
2fa0762
EmittedIL: regen 28 baselines for closure name per-line bucket (#19928)
T-Gro Jun 10, 2026
c64d486
SequenceExpressionTests: update inline IL for closure name bucket cha…
T-Gro Jun 10, 2026
2f46170
CI: re-enable seq-vs-par determinism leg (#19928 fixed)
T-Gro Jun 10, 2026
8854b51
Determinism: route in-file closures through legacy StableNameGenerato…
T-Gro Jun 10, 2026
a468bd1
CI: update ILVerify normalizer and trim sizes for closure name F<file…
T-Gro Jun 10, 2026
2c4d0de
Determinism: narrow TLR priming to compiler-generated Vals only (#19928)
T-Gro Jun 10, 2026
ff82e2d
fantomas: format IlxGen.fs (#19928)
T-Gro Jun 10, 2026
f8cda02
Merge remote-tracking branch 'origin/main' into fix/determinism-seq-v…
T-Gro Jun 10, 2026
bfe00d1
Merge main + regen 2 baselines for CompiledNameAttribute06/07 (#19928)
T-Gro Jun 10, 2026
18897b6
Determinism: 2-bucket method sort (user-methods keep insertion order)…
T-Gro Jun 10, 2026
da51457
fantomas: format IlxGen.fs after 2-bucket method sort (#19928)
T-Gro Jun 10, 2026
6787ddb
Determinism: keep sort-by-(name, idx) for user methods, regen baselin…
T-Gro Jun 10, 2026
f2c5b28
EmittedIL: regenerate 96 .net472 baselines for method sort (#19928)
T-Gro Jun 10, 2026
b3f5ed4
Trim: update sizes again — fluctuates between builds (#19928)
T-Gro Jun 10, 2026
2eff5fd
EmittedIL: append .net472 polyfill classes to migrated baselines (#19…
T-Gro Jun 11, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,4 @@ tests/projects/CompilerCompat/local-nuget-packages/
tests/projects/CompilerCompat/lib-output-*/
tests/projects/CompilerCompat/**/bin/
tests/projects/CompilerCompat/**/obj/
.scratch/
21 changes: 7 additions & 14 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 @@ -109,13 +109,6 @@ stages:
name: $(DncEngPublicBuildPool)
demands: ImageOverride -equals $(_WindowsMachineQueueName)
timeoutInMinutes: 90
strategy:
maxParallel: 2
matrix:
regular:
_experimental_flag: ''
experimental_features:
_experimental_flag: ''
steps:
- checkout: self
clean: true
Expand All @@ -129,15 +122,15 @@ stages:
workingDirectory: $(Build.SourcesDirectory)
installationPath: $(Build.SourcesDirectory)/.dotnet
- script: .\eng\common\dotnet.cmd
- script: .\eng\test-determinism.cmd -configuration Debug
env:
FSHARP_EXPERIMENTAL_FEATURES: $(_experimental_flag)
displayName: Determinism tests with Debug configuration
- script: .\eng\test-determinism.cmd -configuration Release
displayName: Determinism tests (race detector — same flags both builds)
- script: .\eng\test-determinism.cmd -configuration Release -mode seq-vs-par
displayName: Determinism tests (1-shot diff — sequential vs parallel)
- 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
3 changes: 3 additions & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
### Fixed

* Stabilize codegen order under `--parallelcompilation+` so `--deterministic` Release builds produce byte-identical IL across rebuilds: optimizer Val iteration, IlxGen type/method/field/event emit order, anonymous-record extra-binding drain, and `FileIndex` assignment now follow source position rather than thread-scheduling order. Compiler-generated names are also bucketed by the file being optimized/emitted (per-file naming scope) rather than by inlined source location, so parallel optimization and code generation no longer race on a shared name counter. ([Issue #19732](https://github.com/dotnet/fsharp/issues/19732), [PR #19810](https://github.com/dotnet/fsharp/pull/19810))
* Suppress hover/symbol resolution for wildcard `_` patterns inside `member _.…` bodies that incorrectly showed `val _: T` tooltip. ([PR #19760](https://github.com/dotnet/fsharp/pull/19760))
* Deduplicate format specifier locations in computation expressions so editor tooling no longer reports duplicate entries for the same `%` specifier. ([Issue #16419](https://github.com/dotnet/fsharp/issues/16419), [PR #19791](https://github.com/dotnet/fsharp/pull/19791))
* Stabilize codegen order under `--parallelcompilation+` so `--deterministic` Release builds produce byte-identical IL across rebuilds: optimizer Val iteration, IlxGen type/method/field/event emit order, anonymous-record extra-binding drain, and `FileIndex` assignment now follow source position rather than thread-scheduling order. ([Issue #19732](https://github.com/dotnet/fsharp/issues/19732), [PR #19810](https://github.com/dotnet/fsharp/pull/19810))
* Reject non-function bindings for single-case and partial active pattern names with FS1209, matching the existing multi-case behavior. ([PR #19763](https://github.com/dotnet/fsharp/pull/19763))
* Fix FS0421 "The address of the variable cannot be used at this point" incorrectly raised for the discard pattern `let _ = &expr` when `let x = &expr` compiles. ([Issue #18841](https://github.com/dotnet/fsharp/issues/18841), [PR #19811](https://github.com/dotnet/fsharp/pull/19811))
* Make `--deterministic` Release builds byte-reproducible under `--parallelcompilation+`. Compiler-generated names produced by the Detuple/TLR optimizer passes and by closure code-generation are now bucketed by the emitting file rather than by the (possibly inlined) source range, so parallel codegen of distinct consumer files no longer races on a shared name-counter. ([Issue #19732](https://github.com/dotnet/fsharp/issues/19732), [PR #19810](https://github.com/dotnet/fsharp/pull/19810))
* Honor `--nowarn` and `--warnaserror` for warnings emitted during command-line option parsing ([Issue #19576](https://github.com/dotnet/fsharp/issues/19576), [PR #19776](https://github.com/dotnet/fsharp/pull/19776))
* Fix `[<return: X>]` prefix attributes being silently dropped on class members, and fix false-positive `AllowMultiple=false` errors when `[<X>]` and `[<return: X>]` are applied to the same binding. ([Issue #17904](https://github.com/dotnet/fsharp/issues/17904), [Issue #19020](https://github.com/dotnet/fsharp/issues/19020), [PR #19738](https://github.com/dotnet/fsharp/pull/19738))
* Preserve type abbreviations (`string`, user-defined aliases) in the refined type of bindings introduced after a `| null` pattern in a `match` expression. ([Issue #19646](https://github.com/dotnet/fsharp/issues/19646), [PR #19745](https://github.com/dotnet/fsharp/pull/19745))
Expand Down
37 changes: 31 additions & 6 deletions eng/test-determinism.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
param([string]$configuration = "Debug",
[string]$msbuildEngine = "vs",
[string]$altRootDrive = "q:",
[ValidateSet("same", "seq-vs-par")]
[string]$mode = "same",
[switch]$help,
[switch]$norestore,
[switch]$rebuild)
Expand All @@ -15,6 +17,8 @@ function Print-Usage() {
Write-Host " -msbuildEngine <value> Msbuild engine to use to run build ('dotnet', 'vs', or unspecified)."
Write-Host " -bootstrapDir Directory containing the bootstrap compiler"
Write-Host " -altRootDrive The drive we build on (via subst) for verifying pathmap implementation"
Write-Host " -mode <value> 'same' (default): build twice with identical flags (race-detector)"
Write-Host " 'seq-vs-par': first build sequential, second build parallel (deterministic 1-shot diff)"
}

if ($help) {
Expand All @@ -25,7 +29,7 @@ if ($help) {
# List of binary names that should be skipped because they have a known issue that
# makes them non-deterministic.
$script:skipList = @()
function Run-Build([string]$rootDir, [string]$increment) {
function Run-Build([string]$rootDir, [string]$increment, [string]$additionalFscFlags = "") {

$logFileName = $increment

Expand Down Expand Up @@ -62,6 +66,9 @@ function Run-Build([string]$rootDir, [string]$increment) {
Stop-Processes

Write-Host "Building $solution using $bootstrapDir into '$increment' $incrementDir"
if ($additionalFscFlags -ne "") {
Write-Host " AdditionalFscCmdFlags = '$additionalFscFlags'"
}
MSBuild $toolsetBuildProj `
/p:Configuration=$configuration `
/p:Projects=$solution `
Expand All @@ -86,6 +93,7 @@ function Run-Build([string]$rootDir, [string]$increment) {
/p:RunAnalyzers=false `
/p:RunAnalyzersDuringBuild=false `
/p:BUILDING_USING_DOTNET=false `
/p:AdditionalFscCmdFlags="$additionalFscFlags" `
/bl:$logFilePath

Write-Host "Copy-Item -Path $binDir -Destination $incrementDir -ErrorAction SilentlyContinue -Recurse"
Expand Down Expand Up @@ -202,9 +210,9 @@ function Test-MapContents($dataMap) {
}
}

function Test-Build([string]$rootDir, $dataMap, [string]$increment) {
function Test-Build([string]$rootDir, $dataMap, [string]$increment, [string]$additionalFscFlags = "") {
$logFileName = $increment
Run-Build $rootDir -increment $increment
Run-Build $rootDir -increment $increment -additionalFscFlags $additionalFscFlags

$errorList = @()
$allGood = $true
Expand Down Expand Up @@ -273,14 +281,31 @@ function Test-Build([string]$rootDir, $dataMap, [string]$increment) {
}

function Run-Test() {
$seqFlags = ""
$parFlags = ""
if ($mode -eq "seq-vs-par") {
# First build: sequential (force single-threaded, disable any parallel test paths)
$seqFlags = "--parallelcompilation- --test:ParallelOff --nowarn:75"
# Second build: parallel (default in modern fsc, made explicit for clarity)
$parFlags = "--parallelcompilation+"
Write-Host "Determinism mode: seq-vs-par"
Write-Host " Initial (seq): $seqFlags"
Write-Host " Test1 (par): $parFlags"
}
else {
Write-Host "Determinism mode: same (race-detector; both builds identical)"
}

# Run the initial build so that we can populate the maps
Run-Build $RepoRoot -increment "Initial" -useBootstrap
Run-Build $RepoRoot -increment "Initial" -additionalFscFlags $seqFlags

$dataMap = Record-Binaries $RepoRoot "Initial"
Test-MapContents $dataMap

# Run a test against the source in the same directory location
Test-Build -rootDir $RepoRoot -dataMap $dataMap -increment "Test1"
# Run a test against the source in the same directory location.
# In 'same' mode: same flags as Initial (probabilistic race detector).
# In 'seq-vs-par' mode: parallel flags, contrasting against the sequential Initial.
Test-Build -rootDir $RepoRoot -dataMap $dataMap -increment "Test1" -additionalFscFlags $parFlags

# Run another build in a different source location and verify that path mapping
# allows the build to be identical. To do this we'll copy the entire source
Expand Down
Loading
Loading