-
Notifications
You must be signed in to change notification settings - Fork 858
Stabilize parallel optimizer Val iteration for deterministic synthetic names #19810
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -704,7 +704,18 @@ let determineTransforms g (z: Results) = | |
| let callPatterns = sitesCPs sites // callPatterns from sites | ||
| decideTransform g z f callPatterns (m, tps, vss, retTy) // make transform (if required) | ||
|
|
||
| let vtransforms = Zmap.chooseL selectTransform z.Uses | ||
| // Walk z.Uses in stable source-position order so the contained call to | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Optimizer correctness — confirm] The old |
||
| // NiceNameGenerator (via decideTransform) sees the same call order across | ||
| // runs, regardless of Val.Stamp values assigned during parallel parse. | ||
| // See https://github.com/dotnet/fsharp/issues/19732. | ||
| let vtransforms = | ||
| Zmap.toList z.Uses | ||
| |> List.sortWith (fun (v1: Val, _) (v2: Val, _) -> | ||
| let r1, r2 = v1.Range, v2.Range | ||
| compare | ||
| struct (r1.FileIndex, r1.StartLine, r1.StartColumn, v1.LogicalName) | ||
| struct (r2.FileIndex, r2.StartLine, r2.StartColumn, v2.LogicalName)) | ||
| |> List.choose (fun (f, sites) -> selectTransform f sites) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Code quality] The four-tuple source-position key is now duplicated verbatim across two optimizer passes (and any future pass that calls |
||
| let vtransforms = Zmap.ofList valOrder vtransforms | ||
| vtransforms | ||
|
|
||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -844,7 +844,16 @@ let CreateNewValuesForTLR g tlrS arityM fclassM envPackM = | |
| let fHat = mkLocalNameTypeArity f.IsCompilerGenerated m fHatName fHatTy (Some fHatArity) | ||
| fHat | ||
|
|
||
| let fs = Zset.elements tlrS | ||
| // Sort by source position + logical name so the call order into | ||
| // NiceNameGenerator is stable regardless of Val.Stamp assignment race | ||
| // during parallel type checking. See https://github.com/dotnet/fsharp/issues/19732. | ||
| let fs = | ||
| Zset.elements tlrS | ||
| |> List.sortWith (fun (v1: Val) (v2: Val) -> | ||
| let r1, r2 = v1.Range, v2.Range | ||
| compare | ||
| struct (r1.FileIndex, r1.StartLine, r1.StartColumn, v1.LogicalName) | ||
| struct (r2.FileIndex, r2.StartLine, r2.StartColumn, v2.LogicalName)) | ||
|
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Concurrency / determinism]
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [Test coverage] No regression test in the PR — the only guard is the external |
||
| let ffHats = List.map (fun f -> f, createFHat f) fs | ||
| let fHatM = Zmap.ofList valOrder ffHats | ||
| fHatM | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[Diagnostics / maintainability] Dropping the
Parallel optimization breaks determinismcomment removes the only in-code signpost telling future readers why iteration order matters in the optimizer. After this PR the invariant becomes implicit in twoList.sortWithcalls inDetupleArgs/InnerLambdasToTopLevelFuncs. Please leave a short note here (or aboveParallelOptimization.optimizeFilesInParallel) explaining that determinism now relies on those two sort sites and pointing to issue #19732, so the next person adding aNiceNameGeneratorcall from a parallel pass knows to sort first.