Skip to content
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

proposal: go/types: Export Info.FileVersions for access to file-specific version information #62605

Open
griesemer opened this issue Sep 13, 2023 · 9 comments
Labels
Milestone

Comments

@griesemer
Copy link
Contributor

Background

Tools (such as the compiler) need access to per-file version information as provided in the processed Go source such that they (the tools) can do correct semantic analysis. For instance, this information is needed for correct scoping rules for the loop variable scoping change (#60078). The type checker (go/types) can collect this information during type-checking and provide it to clients.

Proposal

We propose to export the following additional data structures from go/types:

We add a new map to the go/types.Info struct which will be populated if present:

// FileVersions maps a file to the file's Go version.
// If the file doesn't specify a version and Config.GoVersion is not
// given, the reported version is the zero version (Major, Minor = 0, 0).
FileVersions map[*token.File]Version

The Version type will be defined as follows:

// A Version represents a released Go version.
type Version struct {
	Major int
	Minor int
}

The Version type may also define/export the following methods for convenience:

// String returns a string representation of v in the form "goMajor.Minor".
func (v Version) String() string

// Equal reports whether v and u are the same version.
func (v Version) Equal(u Version) bool

// Before reports whether version v is before version u.
func (v Version) Before(u Version) bool

// After reports whether version v is after version u.
func (v Version) After(u Version) bool

These methods are not necessary (they are trivial to implement if needed), but unexported versions of them exist in the type checker and there are no strong reasons to withhold them from being exported.

Implementation

This proposal has been implemented in types2 for use by the compiler and the code is present in unexported form in go/types, see CL 515135. If there are no objections to the proposed API we can simply export the functionality. If there are viable alternative proposals, we can adjust the existing implementation as needed.

@griesemer griesemer added this to the Go1.22 milestone Sep 13, 2023
@griesemer
Copy link
Contributor Author

cc: @findleyr

@mvdan
Copy link
Member

mvdan commented Sep 13, 2023

I seem to understand that this information is already available via the GoVersion field in https://pkg.go.dev/go/ast#File, just in string form.

Is this new API about parsing the version so that it can be used and compared more easily? That would remind me of #62039, so I wonder if we could deduplicate.

Or is it about accessing the version information when one loads go/types without go/ast, such as using https://pkg.go.dev/golang.org/x/tools/go/packages with NeedTypesInfo but without NeedSyntax?

@griesemer
Copy link
Contributor Author

@mvdan You are correct that clients can find out about the respective Go version already, but that would involve duplicating parsing the string and various decisions. For instance, the File.GoVersion field will be empty ("") if the file doesn't contain the respective //go:build line and then the version comes from the go.mod file, if one is specified, etc.

The type checker needs to make all these decisions already internally. By exporting the data via FileVersions, clients can get the same information consistently, w/o having to redo the work again.

@mvdan
Copy link
Member

mvdan commented Sep 13, 2023

Ah, so go/types would "flatten" this information beyond just parsing it out of the go/ast string - that makes sense then.

It might still make sense to reuse the logic from #62039 if possible, or somehow merge the proposals. That API is still in flux, but it would be a bit weird for the x/mod/gover API to be entirely separate or wildly different than that of go/types.Info.FileVersions, since they ultimately talk about the same kind of versions.

@timothy-king
Copy link
Contributor

Maybe the Version should be a string to match ast.File.GoVersion?

@griesemer
Copy link
Contributor Author

@timothy-king A string doesn't lend itself well to before/after comparisons.

@findleyr
Copy link
Contributor

I think the key of the map should be *ast.File, for consistency with other maps in types.Info.

I think there's meandering history that led us to token.Pos (it was originally *token.File), but reconsidering it now, *ast.File makes the most sense.

@rsc
Copy link
Contributor

rsc commented Oct 3, 2023

This proposal has been added to the active column of the proposals project
and will now be reviewed at the weekly proposal review meetings.
— rsc for the proposal review group

@rsc
Copy link
Contributor

rsc commented Oct 4, 2023

We should probably do something to fit better with #62039. Maybe that proposal should become a new go/version package, and then this package can just use a plain string and direct people to the go/version package for operations.

If we do that, the only addition in this proposal is the FileVersions map added to Info, of type map[*File]string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Active
Development

No branches or pull requests

5 participants