The skipImplFilesIfSigExists feature introduces non-deterministic naming of type parameters.
This is due to race conditions triggered by breaking the otherwise fully sequential nature of type-checking.
Repro steps
Provide the steps required to reproduce the problem:
- Open the following code in Rider: NondeterminismSample.zip
- Open the 5 files one-by-one in compilation order, wait for code analysis to finish.
- In
NonGenericUse.fs hover over the A.ReportWarnings call. You should see that the type parameter's name is 'b:

4. Close all files
5. Unload&reload the project
6. Repeat 2. but skip The files `GenericUse.fsi` and `GenericUse.fs`.
7. Repeat 3. You should see that the type parameter's name is now `'a`:

Here is a gif showing the steps 1-6 performed:

Expected behavior
The name of the type parameter should not depend on the order of files being opened.
As noted in #14836 (comment) , the expectation is that typars would not leak between files, so their names should be established within the same file they are defined in.
Actual behavior
There is a race condition. Depending on user actions and on which callsite is visited first, the typar gets a different name assigned.
Known workarounds
- Do not use the
skipImplFilesIfSigExists feature. .fsi files have been marketed for quite some time as a way to speedup IDE performance, so having to disable this feature would be unfortunate.
- Ignore the discrepancy. This would probably be fine, except that the issue surfaces a more general problem that
skipImplFilesIfSigExists generates - mutable parts of TcState are reused between different files' type-checks and independent type-checking requests affect each other's results.
Related information
Provide any related information (optional):
Note that the same problem can be seen in compilation when any sort of parallel type-checking is attempted: #14734 .
The underlying problem is the shared, mutable state, causing race conditions.
The
skipImplFilesIfSigExistsfeature introduces non-deterministic naming of type parameters.This is due to race conditions triggered by breaking the otherwise fully sequential nature of type-checking.
Repro steps
Provide the steps required to reproduce the problem:
NonGenericUse.fshover over theA.ReportWarningscall. You should see that the type parameter's name is'b:
4. Close all files 5. Unload&reload the project 6. Repeat 2. but skip The files `GenericUse.fsi` and `GenericUse.fs`. 7. Repeat 3. You should see that the type parameter's name is now `'a`:Here is a gif showing the steps 1-6 performed:

Expected behavior
The name of the type parameter should not depend on the order of files being opened.
As noted in #14836 (comment) , the expectation is that typars would not leak between files, so their names should be established within the same file they are defined in.
Actual behavior
There is a race condition. Depending on user actions and on which callsite is visited first, the typar gets a different name assigned.
Known workarounds
skipImplFilesIfSigExistsfeature..fsifiles have been marketed for quite some time as a way to speedup IDE performance, so having to disable this feature would be unfortunate.skipImplFilesIfSigExistsgenerates - mutable parts ofTcStateare reused between different files' type-checks and independent type-checking requests affect each other's results.Related information
Provide any related information (optional):
Note that the same problem can be seen in compilation when any sort of parallel type-checking is attempted: #14734 .
The underlying problem is the shared, mutable state, causing race conditions.