Skip to content

Compiler service: Non-deterministic typar naming. #14850

Closed

Description

@safesparrow

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:

  1. Open the following code in Rider: NondeterminismSample.zip
  2. Open the 5 files one-by-one in compilation order, wait for code analysis to finish.
  3. In NonGenericUse.fs hover over the A.ReportWarnings call. You should see that the type parameter's name is 'b:

image

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`:

image

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

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):

  • Editing Tools - Rider

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.

Activity

  1. added this to the Backlog milestone on Mar 5, 2023
  2. added
    Impact-Medium(Internal MS Team use only) Describes an issue with moderate impact on existing code.
    Area-Compiler-CheckingType checking, attributes and all aspects of logic checking
    and removed on Mar 13, 2023
  3. nojaf commented on Mar 15, 2023

    @nojaf
    Contributor

    Another workaround would be to introduce a signature file for A.fs and be explicit about the typar name.

    image

    image

    In SignatureConformance, the name of the signature file will be used when they differ.

    implTypar.SetIdent (mkSynId implTypar.Range sigTypar.Id.idText)

  4. safesparrow commented on Mar 15, 2023

    @safesparrow
    ContributorAuthor

    I guess another related issue currently is that the typar does not get a name assigned (so it remains ?) unless it is used somewhere.

    Feels like the fix for the typar naming should be to give them a name when the definition is processed.

    This doesn't solve the more general problem of shared mutable state as discussed in #14836 - but so far this is the only way that issue becomes apparent.

  5. nojaf commented on Feb 19, 2024

    @nojaf
    Contributor

    I could no longer reproduce this problem in Rider 2023.3.3 and believe this problem is resolved by the linked PR.

  6. vzarytovskii commented on Feb 19, 2024

    @vzarytovskii
    Member

    I could no longer reproduce this problem in Rider 2023.3.3 and believe this problem is resolved by the linked PR.

    Oh, nice, thanks for checking it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Area-Compiler-CheckingType checking, attributes and all aspects of logic checkingBugImpact-Medium(Internal MS Team use only) Describes an issue with moderate impact on existing code.

    Type

    No type

    Projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions