diff --git a/src/go/types/api.go b/src/go/types/api.go index 30a9c1f3fee..a9d6ec02fda 100644 --- a/src/go/types/api.go +++ b/src/go/types/api.go @@ -286,10 +286,11 @@ type Info struct { // appear in this list. InitOrder []*Initializer - // _FileVersions maps a file's start position 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.Pos]_Version + // _FileVersions maps a file to the file's Go version string. + // If the file doesn't specify a version and Config.GoVersion + // is not given, the reported version is the empty string. + // TODO(gri) should this be "go0.0" instead in that case? + _FileVersions map[*ast.File]string } func (info *Info) recordTypes() bool { @@ -414,12 +415,6 @@ func (init *Initializer) String() string { return buf.String() } -// A _Version represents a released Go version. -type _Version struct { - _Major int - _Minor int -} - // Check type-checks a package and returns the resulting package object and // the first error if any. Additionally, if info != nil, Check populates each // of the non-nil maps in the Info struct. diff --git a/src/go/types/api_test.go b/src/go/types/api_test.go index 6370786772b..f3719ddf6d2 100644 --- a/src/go/types/api_test.go +++ b/src/go/types/api_test.go @@ -2778,14 +2778,14 @@ func TestFileVersions(t *testing.T) { for _, test := range []struct { moduleVersion string fileVersion string - want Version + wantVersion string }{ - {"", "", Version{0, 0}}, // no versions specified - {"go1.19", "", Version{1, 19}}, // module version specified - {"", "go1.20", Version{0, 0}}, // file upgrade ignored - {"go1.19", "go1.20", Version{1, 20}}, // file upgrade permitted - {"go1.20", "go1.19", Version{1, 20}}, // file downgrade not permitted - {"go1.21", "go1.19", Version{1, 19}}, // file downgrade permitted (module version is >= go1.21) + {"", "", ""}, // no versions specified + {"go1.19", "", "go1.19"}, // module version specified + {"", "go1.20", ""}, // file upgrade ignored + {"go1.19", "go1.20", "go1.20"}, // file upgrade permitted + {"go1.20", "go1.19", "go1.20"}, // file downgrade not permitted + {"go1.21", "go1.19", "go1.19"}, // file downgrade permitted (module version is >= go1.21) } { var src string if test.fileVersion != "" { @@ -2794,16 +2794,16 @@ func TestFileVersions(t *testing.T) { src += "package p" conf := Config{GoVersion: test.moduleVersion} - versions := make(map[*token.File]Version) + versions := make(map[*ast.File]string) var info Info *_FileVersionsAddr(&info) = versions mustTypecheck(src, &conf, &info) n := 0 for _, v := range versions { - want := test.want - if v.Major != want.Major || v.Minor != want.Minor { - t.Errorf("%q: unexpected file version: got %v, want %v", src, v, want) + want := test.wantVersion + if v != want { + t.Errorf("%q: unexpected file version: got %q, want %q", src, v, want) } n++ } @@ -2813,15 +2813,8 @@ func TestFileVersions(t *testing.T) { } } -// Version must match types._Version exactly. -// TODO(gri) remove this declaration once types.Version is exported. -type Version struct { - Major int - Minor int -} - // _FileVersionsAddr(conf) returns the address of the field info._FileVersions. -func _FileVersionsAddr(info *Info) *map[*token.File]Version { +func _FileVersionsAddr(info *Info) *map[*ast.File]string { v := reflect.Indirect(reflect.ValueOf(info)) - return (*map[*token.File]Version)(v.FieldByName("_FileVersions").Addr().UnsafePointer()) + return (*map[*ast.File]string)(v.FieldByName("_FileVersions").Addr().UnsafePointer()) } diff --git a/src/go/types/check.go b/src/go/types/check.go index c714754fef6..28515aea239 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -287,11 +287,10 @@ func (check *Checker) initFiles(files []*ast.File) { } } + // collect file versions for _, file := range check.files { - fbase := file.FileStart - check.recordFileVersion(fbase, check.version) // record package version (possibly zero version) - v, _ := parseGoVersion(file.GoVersion) - if v.major > 0 { + check.recordFileVersion(file, check.conf.GoVersion) + if v, _ := parseGoVersion(file.GoVersion); v.major > 0 { if v.equal(check.version) { continue } @@ -314,18 +313,12 @@ func (check *Checker) initFiles(files []*ast.File) { if check.posVers == nil { check.posVers = make(map[token.Pos]version) } - check.posVers[fbase] = v - check.recordFileVersion(fbase, v) // overwrite package version + check.posVers[file.FileStart] = v + check.recordFileVersion(file, file.GoVersion) // overwrite package version } } } -// A posVers records that the file starting at pos declares the Go version vers. -type posVers struct { - pos token.Pos - vers version -} - // A bailout panic is used for early termination. type bailout struct{} @@ -640,8 +633,8 @@ func (check *Checker) recordScope(node ast.Node, scope *Scope) { } } -func (check *Checker) recordFileVersion(pos token.Pos, v version) { +func (check *Checker) recordFileVersion(file *ast.File, version string) { if m := check._FileVersions; m != nil { - m[pos] = _Version{v.major, v.minor} + m[file] = version } }