Skip to content

Commit

Permalink
Merge branch 'golang:master' into patch-1
Browse files Browse the repository at this point in the history
  • Loading branch information
David-Mao authored Jul 7, 2023
2 parents bca616b + d3d78b4 commit 2c26c97
Show file tree
Hide file tree
Showing 23 changed files with 277 additions and 89 deletions.
1 change: 1 addition & 0 deletions api/go1.21.txt
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,7 @@ pkg go/build, type Package struct, Directives []Directive #56986
pkg go/build, type Package struct, TestDirectives []Directive #56986
pkg go/build, type Package struct, XTestDirectives []Directive #56986
pkg go/token, method (*File) Lines() []int #57708
pkg go/types, method (*Package) GoVersion() string #61175
pkg html/template, const ErrJSTemplate = 12 #59584
pkg html/template, const ErrJSTemplate ErrorCode #59584
pkg io/fs, func FormatDirEntry(DirEntry) string #54451
Expand Down
21 changes: 14 additions & 7 deletions src/cmd/compile/internal/types2/package.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ import (

// A Package describes a Go package.
type Package struct {
path string
name string
scope *Scope
imports []*Package
complete bool
fake bool // scope lookup errors are silently dropped if package is fake (internal use only)
cgo bool // uses of this package will be rewritten into uses of declarations from _cgo_gotypes.go
path string
name string
scope *Scope
imports []*Package
complete bool
fake bool // scope lookup errors are silently dropped if package is fake (internal use only)
cgo bool // uses of this package will be rewritten into uses of declarations from _cgo_gotypes.go
goVersion string // minimum Go version required for package (by Config.GoVersion, typically from go.mod)
}

// NewPackage returns a new Package for the given package path and name.
Expand All @@ -35,6 +36,12 @@ func (pkg *Package) Name() string { return pkg.name }
// SetName sets the package name.
func (pkg *Package) SetName(name string) { pkg.name = name }

// GoVersion returns the minimum Go version required by this package.
// If the minimum version is unknown, GoVersion returns the empty string.
// Individual source files may specify a different minimum Go version,
// as reported in the [go/ast.File.GoVersion] field.
func (pkg *Package) GoVersion() string { return pkg.goVersion }

// Scope returns the (complete or incomplete) package scope
// holding the objects declared at package level (TypeNames,
// Consts, Vars, and Funcs).
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/compile/internal/types2/sizeof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ func TestSizeof(t *testing.T) {

// Misc
{Scope{}, 60, 104},
{Package{}, 36, 72},
{Package{}, 44, 88},
{_TypeSet{}, 28, 56},
}

Expand Down
23 changes: 12 additions & 11 deletions src/cmd/compile/internal/types2/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package types2

import (
"cmd/compile/internal/syntax"
"errors"
"fmt"
"strings"
)
Expand Down Expand Up @@ -44,31 +43,32 @@ var (
go1_21 = version{1, 21}
)

var errVersionSyntax = errors.New("invalid Go version syntax")

// parseGoVersion parses a Go version string (such as "go1.12")
// and returns the version, or an error. If s is the empty
// string, the version is 0.0.
func parseGoVersion(s string) (v version, err error) {
bad := func() (version, error) {
return version{}, fmt.Errorf("invalid Go version syntax %q", s)
}
if s == "" {
return
}
if !strings.HasPrefix(s, "go") {
return version{}, errVersionSyntax
return bad()
}
s = s[len("go"):]
i := 0
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
if i >= 10 || i == 0 && s[i] == '0' {
return version{}, errVersionSyntax
return bad()
}
v.major = 10*v.major + int(s[i]) - '0'
}
if i > 0 && i == len(s) {
return
}
if i == 0 || s[i] != '.' {
return version{}, errVersionSyntax
return bad()
}
s = s[i+1:]
if s == "0" {
Expand All @@ -81,14 +81,15 @@ func parseGoVersion(s string) (v version, err error) {
i = 0
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
if i >= 10 || i == 0 && s[i] == '0' {
return version{}, errVersionSyntax
return bad()
}
v.minor = 10*v.minor + int(s[i]) - '0'
}
if i > 0 && i == len(s) {
return
}
return version{}, errVersionSyntax
// Accept any suffix after the minor number.
// We are only looking for the language version (major.minor)
// but want to accept any valid Go version, like go1.21.0
// and go1.21rc2.
return
}

// langCompat reports an error if the representation of a numeric
Expand Down
8 changes: 8 additions & 0 deletions src/cmd/go/internal/work/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -1115,6 +1115,7 @@ type vetConfig struct {
PackageVetx map[string]string // map package path to vetx data from earlier vet run
VetxOnly bool // only compute vetx data; don't report detected problems
VetxOutput string // write vetx data to this output file
GoVersion string // Go version for package

SucceedOnTypecheckFailure bool // awful hack; see #18395 and below
}
Expand Down Expand Up @@ -1149,6 +1150,13 @@ func buildVetConfig(a *Action, srcfiles []string) {
PackageFile: make(map[string]string),
Standard: make(map[string]bool),
}
if a.Package.Module != nil {
v := a.Package.Module.GoVersion
if v == "" {
v = gover.DefaultGoModVersion
}
vcfg.GoVersion = "go" + v
}
a.vetCfg = vcfg
for i, raw := range a.Package.Internal.RawImports {
final := a.Package.Imports[i]
Expand Down
14 changes: 1 addition & 13 deletions src/cmd/go/internal/work/gc.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,19 +85,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg
if p.Module != nil {
v := p.Module.GoVersion
if v == "" {
// We started adding a 'go' directive to the go.mod file unconditionally
// as of Go 1.12, so any module that still lacks such a directive must
// either have been authored before then, or have a hand-edited go.mod
// file that hasn't been updated by cmd/go since that edit.
//
// Unfortunately, through at least Go 1.16 we didn't add versions to
// vendor/modules.txt. So this could also be a vendored 1.16 dependency.
//
// Fortunately, there were no breaking changes to the language between Go
// 1.11 and 1.16, so if we assume Go 1.16 semantics we will not introduce
// any spurious errors — we will only mask errors, and not particularly
// important ones at that.
v = "1.16"
v = gover.DefaultGoModVersion
}
if allowedVersion(v) {
defaultGcFlags = append(defaultGcFlags, "-lang=go"+gover.Lang(v))
Expand Down
2 changes: 1 addition & 1 deletion src/go/build/deps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ var depsRules = `
math/big, go/token
< go/constant;
container/heap, go/constant, go/parser, internal/types/errors
container/heap, go/constant, go/parser, internal/goversion, internal/types/errors
< go/types;
# The vast majority of standard library packages should not be resorting to regexp.
Expand Down
41 changes: 25 additions & 16 deletions src/go/types/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import (
"go/ast"
"go/constant"
"go/token"
"internal/goversion"
. "internal/types/errors"
)

Expand Down Expand Up @@ -98,11 +99,12 @@ type Checker struct {
fset *token.FileSet
pkg *Package
*Info
version version // accepted language version
nextID uint64 // unique Id for type parameters (first valid Id is 1)
objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info
impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
valids instanceLookup // valid *Named (incl. instantiated) types per the validType check
version version // accepted language version
versionErr error // version error, delayed from NewChecker
nextID uint64 // unique Id for type parameters (first valid Id is 1)
objMap map[Object]*declInfo // maps package-level objects and (non-interface) methods to declaration info
impMap map[importKey]*Package // maps (import path, source directory) to (complete or fake) package
valids instanceLookup // valid *Named (incl. instantiated) types per the validType check

// pkgPathMap maps package names to the set of distinct import paths we've
// seen for that name, anywhere in the import graph. It is used for
Expand Down Expand Up @@ -233,20 +235,21 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
info = new(Info)
}

version, err := parseGoVersion(conf.GoVersion)
if err != nil {
panic(fmt.Sprintf("invalid Go version %q (%v)", conf.GoVersion, err))
version, versionErr := parseGoVersion(conf.GoVersion)
if pkg != nil {
pkg.goVersion = conf.GoVersion
}

return &Checker{
conf: conf,
ctxt: conf.Context,
fset: fset,
pkg: pkg,
Info: info,
version: version,
objMap: make(map[Object]*declInfo),
impMap: make(map[importKey]*Package),
conf: conf,
ctxt: conf.Context,
fset: fset,
pkg: pkg,
Info: info,
version: version,
versionErr: versionErr,
objMap: make(map[Object]*declInfo),
impMap: make(map[importKey]*Package),
}
}

Expand Down Expand Up @@ -342,6 +345,12 @@ func (check *Checker) Files(files []*ast.File) error { return check.checkFiles(f
var errBadCgo = errors.New("cannot use FakeImportC and go115UsesCgo together")

func (check *Checker) checkFiles(files []*ast.File) (err error) {
if check.versionErr != nil {
return check.versionErr
}
if check.version.after(version{1, goversion.Version}) {
return fmt.Errorf("package requires newer Go version %v", check.version)
}
if check.conf.FakeImportC && check.conf.go115UsesCgo {
return errBadCgo
}
Expand Down
21 changes: 14 additions & 7 deletions src/go/types/package.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion src/go/types/sizeof_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ func TestSizeof(t *testing.T) {

// Misc
{Scope{}, 44, 88},
{Package{}, 36, 72},
{Package{}, 44, 88},
{_TypeSet{}, 28, 56},
}
for _, test := range tests {
Expand Down
23 changes: 12 additions & 11 deletions src/go/types/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
package types

import (
"errors"
"fmt"
"go/ast"
"go/token"
Expand Down Expand Up @@ -45,31 +44,32 @@ var (
go1_21 = version{1, 21}
)

var errVersionSyntax = errors.New("invalid Go version syntax")

// parseGoVersion parses a Go version string (such as "go1.12")
// and returns the version, or an error. If s is the empty
// string, the version is 0.0.
func parseGoVersion(s string) (v version, err error) {
bad := func() (version, error) {
return version{}, fmt.Errorf("invalid Go version syntax %q", s)
}
if s == "" {
return
}
if !strings.HasPrefix(s, "go") {
return version{}, errVersionSyntax
return bad()
}
s = s[len("go"):]
i := 0
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
if i >= 10 || i == 0 && s[i] == '0' {
return version{}, errVersionSyntax
return bad()
}
v.major = 10*v.major + int(s[i]) - '0'
}
if i > 0 && i == len(s) {
return
}
if i == 0 || s[i] != '.' {
return version{}, errVersionSyntax
return bad()
}
s = s[i+1:]
if s == "0" {
Expand All @@ -82,14 +82,15 @@ func parseGoVersion(s string) (v version, err error) {
i = 0
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
if i >= 10 || i == 0 && s[i] == '0' {
return version{}, errVersionSyntax
return bad()
}
v.minor = 10*v.minor + int(s[i]) - '0'
}
if i > 0 && i == len(s) {
return
}
return version{}, errVersionSyntax
// Accept any suffix after the minor number.
// We are only looking for the language version (major.minor)
// but want to accept any valid Go version, like go1.21.0
// and go1.21rc2.
return
}

// langCompat reports an error if the representation of a numeric
Expand Down
24 changes: 24 additions & 0 deletions src/go/types/version_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2023 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package types

import "testing"

var parseGoVersionTests = []struct {
in string
out version
}{
{"go1.21", version{1, 21}},
{"go1.21.0", version{1, 21}},
{"go1.21rc2", version{1, 21}},
}

func TestParseGoVersion(t *testing.T) {
for _, tt := range parseGoVersionTests {
if out, err := parseGoVersion(tt.in); out != tt.out || err != nil {
t.Errorf("parseGoVersion(%q) = %v, %v, want %v, nil", tt.in, out, err, tt.out)
}
}
}
Loading

0 comments on commit 2c26c97

Please sign in to comment.