Skip to content

x/tools/gopls: modernizer for sync.OnceValues #76822

Open

Description

@adonovan

Some complex uses of sync.Once can be much simplified using OnceValues; see
https://go.dev/cl/728860 for example. Let's add a modernizer that recognizes the pattern.

Activity

  1. added
    ToolsThis label describes issues relating to any tools in the x/tools repository.
    goplsIssues related to the Go language server, gopls.
    on Dec 13, 2025
  2. added this to the Unreleased milestone on Dec 13, 2025
  3. added
    FeatureRequestIssues asking for a new feature that does not need a proposal.
    on Dec 13, 2025
  4. linsite commented on Dec 18, 2025

    @linsite
    Contributor

    May I request to be assigned to this task? I’m new to gopls, but I’d like to give it a try if it’s not too complicated.

  5. adonovan commented on Dec 18, 2025

    @adonovan
    MemberAuthor

    May I request to be assigned to this task? I’m new to gopls, but I’d like to give it a try if it’s not too complicated.

    By all means! Thanks.

    Before you start coding, I suggest you start by posting a brief plan here for the patterns you want to match, so that we can try to enumerate all the necessary safety conditions, reducing surprises and the need for rewrites.

  6. linsite commented on Dec 20, 2025

    @linsite
    Contributor

    May I request to be assigned to this task? I’m new to gopls, but I’d like to give it a try if it’s not too complicated.

    By all means! Thanks.

    Before you start coding, I suggest you start by posting a brief plan here for the patterns you want to match, so that we can try to enumerate all the necessary safety conditions, reducing surprises and the need for rewrites.

    Thanks for the guidance. I'll post them later.

  7. linsite commented on Jan 7, 2026

    @linsite
    Contributor

    The sync.Once instance can be a package var or a member of a struct, and the returned values must be closure-captured.

    Patterns should be considered:

    1. The instance is a package var:

      • Once.Do returns 1 value by closure.
      • Once.Do returns 2 values by closure.
      • If Once.Do returns more than 2 values, we should leave out the third and all subsequent values, as sync.OnceValues can return at most 2 values.
    2. The instance is a struct member:

      Basically this is the same as a package var, but we should update the corresponding member type from sync.Once to the return type of sync.OnceValues.

    Return values

    The returned values should be updated accordingly—typically by deleting unused ones, as in https://go.dev/cl/728860.

    Patterns should not be considered:

    1. The closure-captured variable is a struct. As we may break the original behavior.
    2. sync.Once.Do does not return any values.
    3. The instance is a struct member whose type is not defined locally. We may not be able to update the member type.
    4. The returned value is a package var and is either created by a function call or is partially initialized. We would change the initialization timing.

    cc @adonovan

  8. adonovan commented on Jan 7, 2026

    @adonovan
    MemberAuthor

    I found this rather hard to follow; Once.Do doesn't return any values, it is called only for effects (which occur once). An example may make it clearer.

    The question here is how exactly we will ascertain whether the effects of the function f passed to Do are of the appropriate form that Do could be replaced by OnceValue (or Values), and, once ascertained, what parts of the code would need to change.

    BTW, I would be surprised if this modernizer, correctly implemented, would have flagged the code in CL 728860 because that code had a bug (the ineffassign diagnostic that prompted the CL).

  9. linsite commented on Jan 9, 2026

    @linsite
    Contributor

    I apologize for the poor writing—the quotes around 'return' were removed by a grammar checker. I underestimated the complexity. I'll rethink this thoroughly.

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

    FeatureRequestIssues asking for a new feature that does not need a proposal.ProposalToolsThis label describes issues relating to any tools in the x/tools repository.goplsIssues related to the Go language server, gopls.

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions