Skip to content

go/ast: formally deprecate Object #52463

Closed

Description

@mvdan

https://pkg.go.dev/go/ast is the package declaring the syntax tree types for parsed Go code, where https://pkg.go.dev/go/parser produces them.

However, note that it also has a rather rudimentary form of typechecking, as it attempts to keep track of objects and scopes. However, this doesn't really work in practice, because go/ast and go/parser do not implement a proper Go typechecker; that's https://pkg.go.dev/go/types.

I find this to be very unfortunate in terms of confusing users, especially those new to Go tools and static analysis who are not aware of this historical gotcha. For example, I was just helping someone on Slack who was finding that objects were sometimes not resolved correctly, and the reason was the use of ast.Object rather than types.Object. See their code for context.

For some more context, we added a mode bit to go/parser to skip object resolution in #46485, bringing significant speedups at basically no cost for many programs, since they made no use of this partial object resolution.

We can't outright remove types and fields like ast.Object for backwards compatibility concerns, but we could certainly warn users against the use of ast.Object. For instance:

package ast

// [...]
//
// Deprecated: go/ast does not implement a full Go type checker; use go/types.Object instead.
type Object [...]

// [...]
//
// Deprecated: go/ast does not implement a full Go type checker; use go/types.Scope instead.
type Scope [...]

It is true that, potentially, using the partial object resolution in go/ast is fine for some use cases. Perhaps they only deal with very simple Go code that doesn't run into any of the limitations against go/types. I think it should be fine for those (hopefully very rare) cases to consciously ignore the deprecation notice.

cc @findleyr @griesemer @josharian @dominikh

Activity

  1. added
    DocumentationIssues describing a change to documentation.
    ToolsThis label describes issues relating to any tools in the x/tools repository.
    on Apr 21, 2022
  2. added this to the Proposal milestone on Apr 21, 2022
  3. mvdan commented on Apr 21, 2022

    @mvdan
    MemberAuthor

    One potential question is what to do with existing users of ast.Object. For example, cmd/gofmt uses it for its rewrite feature (which arguably is deprecated in its own right, as it's rather limited and hasn't been developed in many years) and for its simplify feature, where it's only used to simplify s[:len(s)] into s[:]. I don't think we're necessarily in a rush to replace both of those bits of code.

  4. timothy-king commented on Apr 22, 2022

    @timothy-king
    Contributor

    Two others examples of existing users include x/tools/go/{ssa,cfg}. Both use the *ast.Objects to build control flow internally.

  5. dominikh commented on Apr 22, 2022

    @dominikh
    Member

    I've switched from ast.Object to types.Object in my fork of go/ssa and it was a trivial change. I can't speak to go/cfg, but I reckon it'll be roughly the same.

  6. gopherbot commented on Apr 22, 2022

    @gopherbot
    Contributor

    Change https://go.dev/cl/401875 mentions this issue: cmd/gofmt: use SkipObjectResolution with -s as well

  7. mvdan commented on Apr 22, 2022

    @mvdan
    MemberAuthor

    The CL above removes the lone use in gofmt -s, which was arguably unnecessary to begin with. Or rather, it only prevented simple forms of false positives, and the assumption was that there shouldn't be any false positives anyway.

  8. timothy-king commented on Apr 25, 2022

    @timothy-king
    Contributor

    Took a look at go/cfg. It does not depend on go/types yet. This would need a types.Info for the same solution to apply. The obvious fix is to pass a *types.Info which is a breaking change.

  9. gopherbot commented on Apr 25, 2022

    @gopherbot
    Contributor

    Change https://go.dev/cl/402034 mentions this issue: ssa: switch lblocks to types.Object

  10. gopherbot commented on Apr 25, 2022

    @gopherbot
    Contributor

    Change https://go.dev/cl/402054 mentions this issue: nilness: add unit test for generic instantiation.

  11. gopherbot commented on Apr 25, 2022

    @gopherbot
    Contributor

    Change https://go.dev/cl/402055 mentions this issue: ssautil: Add unit tests that set ssa.InstantiateGenerics

  12. findleyr commented on Apr 25, 2022

    @findleyr
    Contributor

    This came up in #50956 as well. With the status-quo, users are likely to be confused about whether to use ast.Object, and then even more confused when they encounter a limitation of ast.Object. With that said, there are currently several valid uses of syntactic object resolution, such as in cmd/godoc, that we probably won't ever update to use go/types. This is of course OK even if we deprecate the API.

    I have hesitated to use the SkipObjectResolution parser mode more widely, because I am wary of creating a world where we have different color syntax trees. Deprecating ast.Object would be a step toward skipping object resolution in more contexts. However I think we should consider first providing an API to do syntactic object resolution without relying on ast.Ident.Obj. This would allow existing valid usage of ast.Object to migrate off the API without the machinery of go/types.

    For example, something equivalent to the following would be trivial to implement based on the current factoring of go/parser, though the API requires some serious thought.

    // ResolveFiles syntactically resolves identifiers in the package defined by files, recording their referenced declarations
    // in the given decls map, if non-nil. The resulting error will wrap a scanner.ErrorList reporting errors encountered
    // during resolution.
    func ResolveFiles(files []*ast.File, decls map[*ast.Ident]ast.Node) error

    CC @adonovan, who has been thinking about this problem recently.

  13. added a commit that references this issue on Apr 25, 2022
  14. 14 remaining items

  15. added this to the Backlog milestone on May 25, 2022
  16. added a commit that references this issue on Jun 13, 2022
  17. moved this to Accepted in Proposalson Aug 10, 2022
  18. gopherbot commented on Jun 21, 2023

    @gopherbot
    Contributor

    Change https://go.dev/cl/504915 mentions this issue: go/ast: deprecate Object

  19. added a commit that references this issue on Aug 7, 2023
  20. locked and limited conversation to collaborators on Aug 6, 2024
  21. removed this from Proposalson Aug 7, 2024
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

    DocumentationIssues describing a change to documentation.FrozenDueToAgeProposalProposal-AcceptedToolsThis label describes issues relating to any tools in the x/tools repository.

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions