1
0
mirror of https://github.com/golang/go synced 2024-11-27 01:21:18 -07:00

Merge "[dev.typeparams] all: merge master (37f9a8f) into dev.typeparams" into dev.typeparams

This commit is contained in:
Gerrit Code Review 2021-06-25 15:51:12 +00:00
commit 373ca3a846
38 changed files with 505 additions and 122 deletions

View File

@ -187,6 +187,13 @@ Do not send CLs removing the interior tags from such phrases.
features. features.
</p> </p>
<p><!-- golang.org/issue/46366 -->
The <code>go</code> <code>mod</code> <code>graph</code> subcommand also
supports the <code>-go</code> flag, which causes it to report the graph as
seen by the indicated Go version, showing dependencies that may otherwise be
pruned out by lazy loading.
</p>
<h4 id="module-deprecation-comments">Module deprecation comments</h4> <h4 id="module-deprecation-comments">Module deprecation comments</h4>
<p><!-- golang.org/issue/40357 --> <p><!-- golang.org/issue/40357 -->

View File

@ -1,6 +1,6 @@
<!--{ <!--{
"Title": "The Go Programming Language Specification", "Title": "The Go Programming Language Specification",
"Subtitle": "Version of Jun 2, 2021", "Subtitle": "Version of Jun 22, 2021",
"Path": "/ref/spec" "Path": "/ref/spec"
}--> }-->
@ -4670,7 +4670,7 @@ The following built-in functions are not permitted in statement context:
<pre> <pre>
append cap complex imag len make new real append cap complex imag len make new real
unsafe.Alignof unsafe.Offsetof unsafe.Sizeof unsafe.Add unsafe.Alignof unsafe.Offsetof unsafe.Sizeof unsafe.Slice
</pre> </pre>
<pre> <pre>

View File

@ -3106,7 +3106,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
arrlen := s.constInt(types.Types[types.TINT], n.Type().Elem().NumElem()) arrlen := s.constInt(types.Types[types.TINT], n.Type().Elem().NumElem())
cap := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], v) cap := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], v)
s.boundsCheck(arrlen, cap, ssa.BoundsConvert, false) s.boundsCheck(arrlen, cap, ssa.BoundsConvert, false)
return s.newValue1(ssa.OpSlicePtrUnchecked, types.Types[types.TINT], v) return s.newValue1(ssa.OpSlicePtrUnchecked, n.Type(), v)
case ir.OCALLFUNC: case ir.OCALLFUNC:
n := n.(*ir.CallExpr) n := n.(*ir.CallExpr)

View File

@ -1186,13 +1186,17 @@
// //
// Usage: // Usage:
// //
// go mod graph // go mod graph [-go=version]
// //
// Graph prints the module requirement graph (with replacements applied) // Graph prints the module requirement graph (with replacements applied)
// in text form. Each line in the output has two space-separated fields: a module // in text form. Each line in the output has two space-separated fields: a module
// and one of its requirements. Each module is identified as a string of the form // and one of its requirements. Each module is identified as a string of the form
// path@version, except for the main module, which has no @version suffix. // path@version, except for the main module, which has no @version suffix.
// //
// The -go flag causes graph to report the module graph as loaded by by the
// given Go version, instead of the version indicated by the 'go' directive
// in the go.mod file.
//
// See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'. // See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'.
// //
// //
@ -1887,6 +1891,9 @@
// GOMIPS64 // GOMIPS64
// For GOARCH=mips64{,le}, whether to use floating point instructions. // For GOARCH=mips64{,le}, whether to use floating point instructions.
// Valid values are hardfloat (default), softfloat. // Valid values are hardfloat (default), softfloat.
// GOPPC64
// For GOARCH=ppc64{,le}, the target ISA (Instruction Set Architecture).
// Valid values are power8 (default), power9.
// GOWASM // GOWASM
// For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use. // For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
// Valid values are satconv, signext. // Valid values are satconv, signext.

View File

@ -77,6 +77,14 @@ func defaultContext() build.Context {
ctxt.GOOS = envOr("GOOS", ctxt.GOOS) ctxt.GOOS = envOr("GOOS", ctxt.GOOS)
ctxt.GOARCH = envOr("GOARCH", ctxt.GOARCH) ctxt.GOARCH = envOr("GOARCH", ctxt.GOARCH)
// The experiments flags are based on GOARCH, so they may
// need to change. TODO: This should be cleaned up.
buildcfg.UpdateExperiments(ctxt.GOARCH)
ctxt.ToolTags = nil
for _, exp := range buildcfg.EnabledExperiments() {
ctxt.ToolTags = append(ctxt.ToolTags, "goexperiment."+exp)
}
// The go/build rule for whether cgo is enabled is: // The go/build rule for whether cgo is enabled is:
// 1. If $CGO_ENABLED is set, respect it. // 1. If $CGO_ENABLED is set, respect it.
// 2. Otherwise, if this is a cross-compile, disable cgo. // 2. Otherwise, if this is a cross-compile, disable cgo.

View File

@ -598,6 +598,9 @@ Architecture-specific environment variables:
GOMIPS64 GOMIPS64
For GOARCH=mips64{,le}, whether to use floating point instructions. For GOARCH=mips64{,le}, whether to use floating point instructions.
Valid values are hardfloat (default), softfloat. Valid values are hardfloat (default), softfloat.
GOPPC64
For GOARCH=ppc64{,le}, the target ISA (Instruction Set Architecture).
Valid values are power8 (default), power9.
GOWASM GOWASM
For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use. For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
Valid values are satconv, signext. Valid values are satconv, signext.

View File

@ -116,7 +116,7 @@ func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, co
// Can't change that code, because that code is only for loading the // Can't change that code, because that code is only for loading the
// non-test copy of a package. // non-test copy of a package.
ptestErr = &PackageError{ ptestErr = &PackageError{
ImportStack: testImportStack(stk[0], p1, p.ImportPath), ImportStack: importCycleStack(p1, p.ImportPath),
Err: errors.New("import cycle not allowed in test"), Err: errors.New("import cycle not allowed in test"),
IsImportCycle: true, IsImportCycle: true,
} }
@ -375,22 +375,44 @@ func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, co
return pmain, ptest, pxtest return pmain, ptest, pxtest
} }
func testImportStack(top string, p *Package, target string) []string { // importCycleStack returns an import stack from p to the package whose import
stk := []string{top, p.ImportPath} // path is target.
Search: func importCycleStack(p *Package, target string) []string {
for p.ImportPath != target { // importerOf maps each import path to its importer nearest to p.
for _, p1 := range p.Internal.Imports { importerOf := map[string]string{p.ImportPath: ""}
if p1.ImportPath == target || str.Contains(p1.Deps, target) {
stk = append(stk, p1.ImportPath) // q is a breadth-first queue of packages to search for target.
p = p1 // Every package added to q has a corresponding entry in pathTo.
continue Search //
// We search breadth-first for two reasons:
//
// 1. We want to report the shortest cycle.
//
// 2. If p contains multiple cycles, the first cycle we encounter might not
// contain target. To ensure termination, we have to break all cycles
// other than the first.
q := []*Package{p}
for len(q) > 0 {
p := q[0]
q = q[1:]
if path := p.ImportPath; path == target {
var stk []string
for path != "" {
stk = append(stk, path)
path = importerOf[path]
}
return stk
}
for _, dep := range p.Internal.Imports {
if _, ok := importerOf[dep.ImportPath]; !ok {
importerOf[dep.ImportPath] = p.ImportPath
q = append(q, dep)
} }
} }
// Can't happen, but in case it does...
stk = append(stk, "<lost path to cycle>")
break
} }
return stk
panic("lost path to cycle")
} }
// recompileForTest copies and replaces certain packages in pmain's dependency // recompileForTest copies and replaces certain packages in pmain's dependency

View File

@ -18,7 +18,7 @@ import (
) )
var cmdGraph = &base.Command{ var cmdGraph = &base.Command{
UsageLine: "go mod graph", UsageLine: "go mod graph [-go=version]",
Short: "print module requirement graph", Short: "print module requirement graph",
Long: ` Long: `
Graph prints the module requirement graph (with replacements applied) Graph prints the module requirement graph (with replacements applied)
@ -26,12 +26,21 @@ in text form. Each line in the output has two space-separated fields: a module
and one of its requirements. Each module is identified as a string of the form and one of its requirements. Each module is identified as a string of the form
path@version, except for the main module, which has no @version suffix. path@version, except for the main module, which has no @version suffix.
The -go flag causes graph to report the module graph as loaded by by the
given Go version, instead of the version indicated by the 'go' directive
in the go.mod file.
See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'. See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'.
`, `,
Run: runGraph, Run: runGraph,
} }
var (
graphGo goVersionFlag
)
func init() { func init() {
cmdGraph.Flag.Var(&graphGo, "go", "")
base.AddModCommonFlags(&cmdGraph.Flag) base.AddModCommonFlags(&cmdGraph.Flag)
} }
@ -41,7 +50,7 @@ func runGraph(ctx context.Context, cmd *base.Command, args []string) {
} }
modload.ForceUseModules = true modload.ForceUseModules = true
modload.RootMode = modload.NeedRoot modload.RootMode = modload.NeedRoot
mg := modload.LoadModGraph(ctx) mg := modload.LoadModGraph(ctx, graphGo.String())
w := bufio.NewWriter(os.Stdout) w := bufio.NewWriter(os.Stdout)
defer w.Flush() defer w.Flush()

View File

@ -54,7 +54,8 @@ func runVerify(ctx context.Context, cmd *base.Command, args []string) {
sem := make(chan token, runtime.GOMAXPROCS(0)) sem := make(chan token, runtime.GOMAXPROCS(0))
// Use a slice of result channels, so that the output is deterministic. // Use a slice of result channels, so that the output is deterministic.
mods := modload.LoadModGraph(ctx).BuildList()[1:] const defaultGoVersion = ""
mods := modload.LoadModGraph(ctx, defaultGoVersion).BuildList()[1:]
errsChans := make([]<-chan []error, len(mods)) errsChans := make([]<-chan []error, len(mods))
for i, mod := range mods { for i, mod := range mods {

View File

@ -506,7 +506,8 @@ type versionReason struct {
func newResolver(ctx context.Context, queries []*query) *resolver { func newResolver(ctx context.Context, queries []*query) *resolver {
// LoadModGraph also sets modload.Target, which is needed by various resolver // LoadModGraph also sets modload.Target, which is needed by various resolver
// methods. // methods.
mg := modload.LoadModGraph(ctx) const defaultGoVersion = ""
mg := modload.LoadModGraph(ctx, defaultGoVersion)
buildList := mg.BuildList() buildList := mg.BuildList()
initialVersion := make(map[string]string, len(buildList)) initialVersion := make(map[string]string, len(buildList))
@ -1803,7 +1804,8 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi
return false return false
} }
r.buildList = modload.LoadModGraph(ctx).BuildList() const defaultGoVersion = ""
r.buildList = modload.LoadModGraph(ctx, defaultGoVersion).BuildList()
r.buildListVersion = make(map[string]string, len(r.buildList)) r.buildListVersion = make(map[string]string, len(r.buildList))
for _, m := range r.buildList { for _, m := range r.buildList {
r.buildListVersion[m.Path] = m.Version r.buildListVersion[m.Path] = m.Version

View File

@ -403,11 +403,33 @@ func (mg *ModuleGraph) allRootsSelected() bool {
// LoadModGraph loads and returns the graph of module dependencies of the main module, // LoadModGraph loads and returns the graph of module dependencies of the main module,
// without loading any packages. // without loading any packages.
// //
// If the goVersion string is non-empty, the returned graph is the graph
// as interpreted by the given Go version (instead of the version indicated
// in the go.mod file).
//
// Modules are loaded automatically (and lazily) in LoadPackages: // Modules are loaded automatically (and lazily) in LoadPackages:
// LoadModGraph need only be called if LoadPackages is not, // LoadModGraph need only be called if LoadPackages is not,
// typically in commands that care about modules but no particular package. // typically in commands that care about modules but no particular package.
func LoadModGraph(ctx context.Context) *ModuleGraph { func LoadModGraph(ctx context.Context, goVersion string) *ModuleGraph {
rs, mg, err := expandGraph(ctx, LoadModFile(ctx)) rs := LoadModFile(ctx)
if goVersion != "" {
depth := modDepthFromGoVersion(goVersion)
if depth == eager && rs.depth != eager {
// Use newRequirements instead of convertDepth because convertDepth
// also updates roots; here, we want to report the unmodified roots
// even though they may seem inconsistent.
rs = newRequirements(eager, rs.rootModules, rs.direct)
}
mg, err := rs.Graph(ctx)
if err != nil {
base.Fatalf("go: %v", err)
}
return mg
}
rs, mg, err := expandGraph(ctx, rs)
if err != nil { if err != nil {
base.Fatalf("go: %v", err) base.Fatalf("go: %v", err)
} }

View File

@ -428,6 +428,15 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver
mv = module.ZeroPseudoVersion("v0") mv = module.ZeroPseudoVersion("v0")
} }
} }
mg, err := rs.Graph(ctx)
if err != nil {
return module.Version{}, err
}
if cmpVersion(mg.Selected(mp), mv) >= 0 {
// We can't resolve the import by adding mp@mv to the module graph,
// because the selected version of mp is already at least mv.
continue
}
mods = append(mods, module.Version{Path: mp, Version: mv}) mods = append(mods, module.Version{Path: mp, Version: mv})
} }

View File

@ -0,0 +1,29 @@
# Test that the corect default GOEXPERIMENT is used when cross
# building with GOENV (#46815).
# Unset variables set by the TestScript harness. Users typically won't
# explicitly configure these, and #46815 doesn't repro if they are.
env GOOS=
env GOARCH=
env GOEXPERIMENT=
env GOENV=windows-amd64
go build internal/abi
env GOENV=ios-arm64
go build internal/abi
env GOENV=linux-mips
go build internal/abi
-- windows-amd64 --
GOOS=windows
GOARCH=amd64
-- ios-arm64 --
GOOS=ios
GOARCH=arm64
-- linux-mips --
GOOS=linux
GOARCH=mips

View File

@ -0,0 +1,101 @@
# For this module, Go 1.17 prunes out a (transitive and otherwise-irrelevant)
# requirement on a retracted higher version of a dependency.
# However, when Go 1.16 reads the same requirements from the go.mod file,
# it does not prune out that requirement, and selects the retracted version.
#
# The Go 1.16 module graph looks like:
#
# m ---- lazy v0.1.0 ---- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
# | |
# + -------+------------- incompatible v1.0.0
#
# The Go 1.17 module graph is the same except that the dependencies of
# requireincompatible are pruned out (because the module that requires
# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
# the main module).
cp go.mod go.mod.orig
go mod graph
cp stdout graph-1.17.txt
stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
stdout '^example\.net/lazy@v0\.1\.0 example\.com/retract/incompatible@v1\.0\.0$'
! stdout 'example\.com/retract/incompatible@v2\.0\.0\+incompatible'
go mod graph -go=1.17
cmp stdout graph-1.17.txt
cmp go.mod go.mod.orig
# Setting -go=1.16 should report the graph as viewed by Go 1.16,
# but should not edit the go.mod file.
go mod graph -go=1.16
cp stdout graph-1.16.txt
stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
stdout '^example\.net/lazy@v0\.1\.0 example.com/retract/incompatible@v1\.0\.0$'
stdout '^example.net/requireincompatible@v0.1.0 example.com/retract/incompatible@v2\.0\.0\+incompatible$'
cmp go.mod go.mod.orig
# If we actually update the go.mod file to the requested go version,
# we should get the same selected versions, but the roots of the graph
# may be updated.
#
# TODO(#45551): The roots should not be updated.
go mod edit -go=1.16
go mod graph
! stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
stdout '^example\.net/lazy@v0.1.0 example.com/retract/incompatible@v1\.0\.0$'
stdout '^example.net/requireincompatible@v0.1.0 example.com/retract/incompatible@v2\.0\.0\+incompatible$'
# TODO(#45551): cmp stdout graph-1.16.txt
# Unsupported go versions should be rejected, since we don't know
# what versions they would report.
! go mod graph -go=1.99999999999
stderr '^invalid value "1\.99999999999" for flag -go: maximum supported Go version is '$goversion'\nusage: go mod graph \[-go=version\]\nRun ''go help mod graph'' for details.$'
-- go.mod --
// Module m indirectly imports a package from
// example.com/retract/incompatible. Its selected version of
// that module is lower under Go 1.17 semantics than under Go 1.16.
module example.com/m
go 1.17
replace (
example.net/lazy v0.1.0 => ./lazy
example.net/requireincompatible v0.1.0 => ./requireincompatible
)
require (
example.com/retract/incompatible v1.0.0 // indirect
example.net/lazy v0.1.0
)
-- lazy/go.mod --
// Module lazy requires example.com/retract/incompatible v1.0.0.
//
// When viewed from the outside it also has a transitive dependency
// on v2.0.0+incompatible, but in lazy mode that transitive dependency
// is pruned out.
module example.net/lazy
go 1.17
exclude example.com/retract/incompatible v2.0.0+incompatible
require (
example.com/retract/incompatible v1.0.0
example.net/requireincompatible v0.1.0
)
-- requireincompatible/go.mod --
module example.net/requireincompatible
go 1.15
require example.com/retract/incompatible v2.0.0+incompatible

View File

@ -0,0 +1,23 @@
# https://golang.org/issue/45863: a typo in a test package leading to an
# import cycle should be diagnosed, instead of causing an infinite loop.
# The failure mode of this test prior to the fix was a timeout or OOM crash.
go list -e -test -deps ./datastore/sql
-- go.mod --
module golang.org/issue45863
go 1.17
-- datastore/datastore_health.go --
package datastore
import (
"golang.org/issue45863/datastore"
"golang.org/issue45863/datastore/sql"
)
-- datastore/sql/sql.go --
package sql
-- datastore/sql/sql_test.go --
package sql
import _ "golang.org/issue45863/datastore"

View File

@ -0,0 +1,34 @@
# Regression test for https://golang.org/issue/46659.
#
# If a 'replace' directive specifies an older-than-selected version of a module,
# 'go mod tidy' shouldn't try to add that version to the build list to resolve a
# missing package: it won't be selected, and would cause the module loader to
# loop indefinitely trying to resolve the package.
cp go.mod go.mod.orig
! go mod tidy
! stderr panic
stderr '^golang\.org/issue46659 imports\n\texample\.com/missingpkg/deprecated: package example\.com/missingpkg/deprecated provided by example\.com/missingpkg at latest version v1\.0\.0 but not at required version v1\.0\.1-beta$'
go mod tidy -e
cmp go.mod go.mod.orig
-- go.mod --
module golang.org/issue46659
go 1.17
replace example.com/missingpkg v1.0.1-alpha => example.com/missingpkg v1.0.0
require example.com/usemissingpre v1.0.0
require example.com/missingpkg v1.0.1-beta // indirect
-- m.go --
package m
import (
_ "example.com/missingpkg/deprecated"
_ "example.com/usemissingpre"
)

View File

@ -5,6 +5,7 @@
package moddeps_test package moddeps_test
import ( import (
"bytes"
"encoding/json" "encoding/json"
"fmt" "fmt"
"internal/testenv" "internal/testenv"
@ -68,7 +69,7 @@ func TestAllDependencies(t *testing.T) {
// There is no vendor directory, so the module must have no dependencies. // There is no vendor directory, so the module must have no dependencies.
// Check that the list of active modules contains only the main module. // Check that the list of active modules contains only the main module.
cmd := exec.Command(goBin, "list", "-mod=mod", "-m", "all") cmd := exec.Command(goBin, "list", "-mod=readonly", "-m", "all")
cmd.Env = append(os.Environ(), "GO111MODULE=on") cmd.Env = append(os.Environ(), "GO111MODULE=on")
cmd.Dir = m.Dir cmd.Dir = m.Dir
cmd.Stderr = new(strings.Builder) cmd.Stderr = new(strings.Builder)
@ -123,10 +124,38 @@ func TestAllDependencies(t *testing.T) {
t.Skip("skipping because a diff command with support for --recursive and --unified flags is unavailable") t.Skip("skipping because a diff command with support for --recursive and --unified flags is unavailable")
} }
// We're going to check the standard modules for tidiness, so we need a usable
// GOMODCACHE. If the default directory doesn't exist, use a temporary
// directory instead. (That can occur, for example, when running under
// run.bash with GO_TEST_SHORT=0: run.bash sets GOPATH=/nonexist-gopath, and
// GO_TEST_SHORT=0 causes it to run this portion of the test.)
var modcacheEnv []string
{
out, err := exec.Command(goBin, "env", "GOMODCACHE").Output()
if err != nil {
t.Fatalf("%s env GOMODCACHE: %v", goBin, err)
}
modcacheOk := false
if gomodcache := string(bytes.TrimSpace(out)); gomodcache != "" {
if _, err := os.Stat(gomodcache); err == nil {
modcacheOk = true
}
}
if !modcacheOk {
modcacheEnv = []string{
"GOMODCACHE=" + t.TempDir(),
"GOFLAGS=" + os.Getenv("GOFLAGS") + " -modcacherw", // Allow t.TempDir() to clean up subdirectories.
}
}
}
// Build the bundle binary at the golang.org/x/tools // Build the bundle binary at the golang.org/x/tools
// module version specified in GOROOT/src/cmd/go.mod. // module version specified in GOROOT/src/cmd/go.mod.
bundleDir := t.TempDir() bundleDir := t.TempDir()
r := runner{Dir: filepath.Join(runtime.GOROOT(), "src/cmd")} r := runner{
Dir: filepath.Join(runtime.GOROOT(), "src/cmd"),
Env: append(os.Environ(), modcacheEnv...),
}
r.run(t, goBin, "build", "-mod=readonly", "-o", bundleDir, "golang.org/x/tools/cmd/bundle") r.run(t, goBin, "build", "-mod=readonly", "-o", bundleDir, "golang.org/x/tools/cmd/bundle")
var gorootCopyDir string var gorootCopyDir string
@ -160,7 +189,7 @@ func TestAllDependencies(t *testing.T) {
} }
r := runner{ r := runner{
Dir: filepath.Join(gorootCopyDir, rel), Dir: filepath.Join(gorootCopyDir, rel),
Env: append(os.Environ(), Env: append(append(os.Environ(), modcacheEnv...),
// Set GOROOT. // Set GOROOT.
"GOROOT="+gorootCopyDir, "GOROOT="+gorootCopyDir,
// Explicitly override PWD and clear GOROOT_FINAL so that GOROOT=gorootCopyDir is definitely used. // Explicitly override PWD and clear GOROOT_FINAL so that GOROOT=gorootCopyDir is definitely used.

View File

@ -2841,7 +2841,6 @@ func TestTxStmtDeadlock(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
defer cancel() defer cancel()
tx, err := db.BeginTx(ctx, nil) tx, err := db.BeginTx(ctx, nil)
cancel()
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -2850,6 +2849,7 @@ func TestTxStmtDeadlock(t *testing.T) {
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
cancel()
// Run number of stmt queries to reproduce deadlock from context cancel // Run number of stmt queries to reproduce deadlock from context cancel
for i := 0; i < 1e3; i++ { for i := 0; i < 1e3; i++ {
// Encounter any close related errors (e.g. ErrTxDone, stmt is closed) // Encounter any close related errors (e.g. ErrTxDone, stmt is closed)

View File

@ -1379,7 +1379,12 @@ func (p *parser) parseIndexOrSliceOrInstance(x ast.Expr) ast.Expr {
p.errorExpected(p.pos, "operand") p.errorExpected(p.pos, "operand")
rbrack := p.pos rbrack := p.pos
p.next() p.next()
return &ast.BadExpr{From: x.Pos(), To: rbrack} return &ast.IndexExpr{
X: x,
Lbrack: lbrack,
Index: &ast.BadExpr{From: rbrack, To: rbrack},
Rbrack: rbrack,
}
} }
p.exprLev++ p.exprLev++

View File

@ -373,7 +373,7 @@ func (s *Scanner) scanIdentifier() string {
continue continue
} }
s.rdOffset += rdOffset s.rdOffset += rdOffset
if b < utf8.RuneSelf { if 0 < b && b < utf8.RuneSelf {
// Optimization: we've encountered an ASCII character that's not a letter // Optimization: we've encountered an ASCII character that's not a letter
// or number. Avoid the call into s.next() and corresponding set up. // or number. Avoid the call into s.next() and corresponding set up.
// //

View File

@ -813,6 +813,8 @@ var errors = []struct {
{"//\ufeff", token.COMMENT, 2, "//\ufeff", "illegal byte order mark"}, // only first BOM is ignored {"//\ufeff", token.COMMENT, 2, "//\ufeff", "illegal byte order mark"}, // only first BOM is ignored
{"'\ufeff" + `'`, token.CHAR, 1, "'\ufeff" + `'`, "illegal byte order mark"}, // only first BOM is ignored {"'\ufeff" + `'`, token.CHAR, 1, "'\ufeff" + `'`, "illegal byte order mark"}, // only first BOM is ignored
{`"` + "abc\ufeffdef" + `"`, token.STRING, 4, `"` + "abc\ufeffdef" + `"`, "illegal byte order mark"}, // only first BOM is ignored {`"` + "abc\ufeffdef" + `"`, token.STRING, 4, `"` + "abc\ufeffdef" + `"`, "illegal byte order mark"}, // only first BOM is ignored
{"abc\x00def", token.IDENT, 3, "abc", "illegal character NUL"},
{"abc\x00", token.IDENT, 3, "abc", "illegal character NUL"},
} }
func TestScanErrors(t *testing.T) { func TestScanErrors(t *testing.T) {

View File

@ -202,17 +202,20 @@ func asGoVersion(s string) string {
return "" return ""
} }
func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, manual bool) { func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, manual bool, imp Importer) {
if len(filenames) == 0 { if len(filenames) == 0 {
t.Fatal("no source files") t.Fatal("no source files")
} }
if strings.HasSuffix(filenames[0], ".go2") && !typeparams.Enabled {
t.Skip("type params are not enabled")
}
if strings.HasSuffix(filenames[0], ".go1") && typeparams.Enabled {
t.Skip("type params are enabled")
}
mode := parser.AllErrors mode := parser.AllErrors
if strings.HasSuffix(filenames[0], ".go2") { if !strings.HasSuffix(filenames[0], ".go2") {
if !typeparams.Enabled {
t.Skip("type params are not enabled")
}
} else {
mode |= typeparams.DisallowParsing mode |= typeparams.DisallowParsing
} }
@ -250,7 +253,10 @@ func testFiles(t *testing.T, sizes Sizes, filenames []string, srcs [][]byte, man
} }
} }
conf.Importer = importer.Default() conf.Importer = imp
if imp == nil {
conf.Importer = importer.Default()
}
conf.Error = func(err error) { conf.Error = func(err error) {
if *haltOnError { if *haltOnError {
defer panic(err) defer panic(err)
@ -339,7 +345,7 @@ func TestManual(t *testing.T) {
func TestLongConstants(t *testing.T) { func TestLongConstants(t *testing.T) {
format := "package longconst\n\nconst _ = %s\nconst _ = %s // ERROR excessively long constant" format := "package longconst\n\nconst _ = %s\nconst _ = %s // ERROR excessively long constant"
src := fmt.Sprintf(format, strings.Repeat("1", 9999), strings.Repeat("1", 10001)) src := fmt.Sprintf(format, strings.Repeat("1", 9999), strings.Repeat("1", 10001))
testFiles(t, nil, []string{"longconst.go"}, [][]byte{[]byte(src)}, false) testFiles(t, nil, []string{"longconst.go"}, [][]byte{[]byte(src)}, false, nil)
} }
// TestIndexRepresentability tests that constant index operands must // TestIndexRepresentability tests that constant index operands must
@ -347,7 +353,7 @@ func TestLongConstants(t *testing.T) {
// represent larger values. // represent larger values.
func TestIndexRepresentability(t *testing.T) { func TestIndexRepresentability(t *testing.T) {
const src = "package index\n\nvar s []byte\nvar _ = s[int64 /* ERROR \"int64\\(1\\) << 40 \\(.*\\) overflows int\" */ (1) << 40]" const src = "package index\n\nvar s []byte\nvar _ = s[int64 /* ERROR \"int64\\(1\\) << 40 \\(.*\\) overflows int\" */ (1) << 40]"
testFiles(t, &StdSizes{4, 4}, []string{"index.go"}, [][]byte{[]byte(src)}, false) testFiles(t, &StdSizes{4, 4}, []string{"index.go"}, [][]byte{[]byte(src)}, false, nil)
} }
func TestIssue46453(t *testing.T) { func TestIssue46453(t *testing.T) {
@ -355,7 +361,7 @@ func TestIssue46453(t *testing.T) {
t.Skip("type params are enabled") t.Skip("type params are enabled")
} }
const src = "package p\ntype _ comparable // ERROR \"undeclared name: comparable\"" const src = "package p\ntype _ comparable // ERROR \"undeclared name: comparable\""
testFiles(t, nil, []string{"issue46453.go"}, [][]byte{[]byte(src)}, false) testFiles(t, nil, []string{"issue46453.go"}, [][]byte{[]byte(src)}, false, nil)
} }
func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", false) } func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDirFiles(t, "testdata/check", false) }
@ -415,5 +421,5 @@ func testPkg(t *testing.T, filenames []string, manual bool) {
} }
srcs[i] = src srcs[i] = src
} }
testFiles(t, nil, filenames, srcs, manual) testFiles(t, nil, filenames, srcs, manual, nil)
} }

View File

@ -31,7 +31,7 @@ func (check *Checker) qualifier(pkg *Package) string {
if check.pkgPathMap == nil { if check.pkgPathMap == nil {
check.pkgPathMap = make(map[string]map[string]bool) check.pkgPathMap = make(map[string]map[string]bool)
check.seenPkgMap = make(map[*Package]bool) check.seenPkgMap = make(map[*Package]bool)
check.markImports(pkg) check.markImports(check.pkg)
} }
// If the same package name was used by multiple packages, display the full path. // If the same package name was used by multiple packages, display the full path.
if len(check.pkgPathMap[pkg.name]) > 1 { if len(check.pkgPathMap[pkg.name]) > 1 {

View File

@ -577,42 +577,64 @@ func TestIssue44515(t *testing.T) {
} }
func TestIssue43124(t *testing.T) { func TestIssue43124(t *testing.T) {
// TODO(rFindley) enhance the testdata tests to be able to express this type // TODO(rFindley) move this to testdata by enhancing support for importing.
// of setup.
// All involved packages have the same name (template). Error messages should // All involved packages have the same name (template). Error messages should
// disambiguate between text/template and html/template by printing the full // disambiguate between text/template and html/template by printing the full
// path. // path.
const ( const (
asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}` asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}`
bsrc = `package b; import ("a"; "html/template"); func _() { a.F(template.Template{}) }` bsrc = `
csrc = `package c; import ("a"; "html/template"); func _() { a.G(template.Template{}) }` package b
import (
"a"
"html/template"
)
func _() {
// Packages should be fully qualified when there is ambiguity within the
// error string itself.
a.F(template /* ERROR cannot use.*html/template.* as .*text/template */ .Template{})
}
`
csrc = `
package c
import (
"a"
"fmt"
"html/template"
)
// Issue #46905: make sure template is not the first package qualified.
var _ fmt.Stringer = 1 // ERROR cannot use 1.*as fmt\.Stringer
// Packages should be fully qualified when there is ambiguity in reachable
// packages. In this case both a (and for that matter html/template) import
// text/template.
func _() { a.G(template /* ERROR cannot use .*html/template.*Template */ .Template{}) }
`
tsrc = `
package template
import "text/template"
type T int
// Verify that the current package name also causes disambiguation.
var _ T = template /* ERROR cannot use.*text/template.* as T value */.Template{}
`
) )
a, err := pkgFor("a", asrc, nil) a, err := pkgFor("a", asrc, nil)
if err != nil { if err != nil {
t.Fatalf("package a failed to typecheck: %v", err) t.Fatalf("package a failed to typecheck: %v", err)
} }
conf := Config{Importer: importHelper{pkg: a, fallback: importer.Default()}} imp := importHelper{pkg: a, fallback: importer.Default()}
// Packages should be fully qualified when there is ambiguity within the testFiles(t, nil, []string{"b.go"}, [][]byte{[]byte(bsrc)}, false, imp)
// error string itself. testFiles(t, nil, []string{"c.go"}, [][]byte{[]byte(csrc)}, false, imp)
bast := mustParse(t, bsrc) testFiles(t, nil, []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, imp)
_, err = conf.Check(bast.Name.Name, fset, []*ast.File{bast}, nil)
if err == nil {
t.Fatal("package b had no errors")
}
if !strings.Contains(err.Error(), "text/template") || !strings.Contains(err.Error(), "html/template") {
t.Errorf("type checking error for b does not disambiguate package template: %q", err)
}
// ...and also when there is any ambiguity in reachable packages.
cast := mustParse(t, csrc)
_, err = conf.Check(cast.Name.Name, fset, []*ast.File{cast}, nil)
if err == nil {
t.Fatal("package c had no errors")
}
if !strings.Contains(err.Error(), "html/template") {
t.Errorf("type checking error for c does not disambiguate package template: %q", err)
}
} }

View File

@ -332,7 +332,7 @@ func issue28281g() (... /* ERROR can only use ... with final parameter */ TT)
func issue26234a(f *syn.File) { func issue26234a(f *syn.File) {
// The error message below should refer to the actual package name (syntax) // The error message below should refer to the actual package name (syntax)
// not the local package name (syn). // not the local package name (syn).
f.foo /* ERROR f.foo undefined \(type \*syntax.File has no field or method foo\) */ f.foo /* ERROR f\.foo undefined \(type \*syntax\.File has no field or method foo\) */
} }
type T struct { type T struct {
@ -361,7 +361,7 @@ func issue35895() {
// Because both t1 and t2 have the same global package name (template), // Because both t1 and t2 have the same global package name (template),
// qualify packages with full path name in this case. // qualify packages with full path name in this case.
var _ t1.Template = t2 /* ERROR cannot use .* \(value of type "html/template".Template\) as "text/template".Template */ .Template{} var _ t1.Template = t2 /* ERROR cannot use .* \(value of type .html/template.\.Template\) as .text/template.\.Template */ .Template{}
} }
func issue42989(s uint) { func issue42989(s uint) {

View File

@ -210,5 +210,5 @@ func _() {
func h[] /* ERROR empty type parameter list */ () func h[] /* ERROR empty type parameter list */ ()
func _() { func _() {
h[] /* ERROR operand */ () h /* ERROR cannot index */ [] /* ERROR operand */ ()
} }

View File

@ -0,0 +1,11 @@
// Copyright 2021 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 issue46403
func _() {
// a should be used, despite the parser error below.
var a []int
var _ = a[] // ERROR expected operand
}

View File

@ -0,0 +1,8 @@
// Copyright 2021 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 issue46404
// Check that we don't type check t[_] as an instantiation.
type t [t /* ERROR not a type */ [_]]_ // ERROR cannot use

View File

@ -262,8 +262,12 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) {
} }
case *ast.IndexExpr: case *ast.IndexExpr:
exprs := typeparams.UnpackExpr(e.Index) if typeparams.Enabled {
return check.instantiatedType(e.X, exprs, def) exprs := typeparams.UnpackExpr(e.Index)
return check.instantiatedType(e.X, exprs, def)
}
check.errorf(e0, _NotAType, "%s is not a type", e0)
check.use(e.X)
case *ast.ParenExpr: case *ast.ParenExpr:
// Generic types must be instantiated before they can be used in any form. // Generic types must be instantiated before they can be used in any form.

View File

@ -18,7 +18,7 @@ import (
// //
// (This is not necessarily the set of experiments the compiler itself // (This is not necessarily the set of experiments the compiler itself
// was built with.) // was built with.)
var Experiment goexperiment.Flags = parseExperiments() var Experiment goexperiment.Flags = parseExperiments(GOARCH)
var regabiSupported = GOARCH == "amd64" || GOARCH == "arm64" var regabiSupported = GOARCH == "amd64" || GOARCH == "arm64"
var regabiDeveloping = false var regabiDeveloping = false
@ -41,7 +41,7 @@ var experimentBaseline = goexperiment.Flags{
// Note: must agree with runtime.framepointer_enabled. // Note: must agree with runtime.framepointer_enabled.
var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64" var FramePointerEnabled = GOARCH == "amd64" || GOARCH == "arm64"
func parseExperiments() goexperiment.Flags { func parseExperiments(goarch string) goexperiment.Flags {
// Start with the statically enabled set of experiments. // Start with the statically enabled set of experiments.
flags := experimentBaseline flags := experimentBaseline
@ -96,11 +96,11 @@ func parseExperiments() goexperiment.Flags {
} }
// regabiwrappers is always enabled on amd64. // regabiwrappers is always enabled on amd64.
if GOARCH == "amd64" { if goarch == "amd64" {
flags.RegabiWrappers = true flags.RegabiWrappers = true
} }
// regabi is only supported on amd64 and arm64. // regabi is only supported on amd64 and arm64.
if GOARCH != "amd64" && GOARCH != "arm64" { if goarch != "amd64" && goarch != "arm64" {
flags.RegabiWrappers = false flags.RegabiWrappers = false
flags.RegabiReflect = false flags.RegabiReflect = false
flags.RegabiArgs = false flags.RegabiArgs = false
@ -161,3 +161,10 @@ func EnabledExperiments() []string {
func AllExperiments() []string { func AllExperiments() []string {
return expList(&Experiment, nil, true) return expList(&Experiment, nil, true)
} }
// UpdateExperiments updates the Experiment global based on a new GOARCH value.
// This is only required for cmd/go, which can change GOARCH after
// program startup due to use of "go env -w".
func UpdateExperiments(goarch string) {
Experiment = parseExperiments(goarch)
}

View File

@ -155,40 +155,27 @@ func slowDialTCP(ctx context.Context, network string, laddr, raddr *TCPAddr) (*T
return c, err return c, err
} }
func dialClosedPort(t *testing.T) (actual, expected time.Duration) { func dialClosedPort(t *testing.T) (dialLatency time.Duration) {
// Estimate the expected time for this platform. // On most platforms, dialing a closed port should be nearly instantaneous —
// On Windows, dialing a closed port takes roughly 1 second, // less than a few hundred milliseconds. However, on some platforms it may be
// but other platforms should be instantaneous. // much slower: on Windows and OpenBSD, it has been observed to take up to a
if runtime.GOOS == "windows" { // few seconds.
expected = 1500 * time.Millisecond
} else if runtime.GOOS == "darwin" || runtime.GOOS == "ios" {
expected = 150 * time.Millisecond
} else {
expected = 95 * time.Millisecond
}
l, err := Listen("tcp", "127.0.0.1:0") l, err := Listen("tcp", "127.0.0.1:0")
if err != nil { if err != nil {
t.Logf("dialClosedPort: Listen failed: %v", err) t.Fatalf("dialClosedPort: Listen failed: %v", err)
return 999 * time.Hour, expected
} }
addr := l.Addr().String() addr := l.Addr().String()
l.Close() l.Close()
// On OpenBSD, interference from TestTCPSelfConnect is mysteriously
// causing the first attempt to hang for a few seconds, so we throw startTime := time.Now()
// away the first result and keep the second. c, err := Dial("tcp", addr)
for i := 1; ; i++ { if err == nil {
startTime := time.Now() c.Close()
c, err := Dial("tcp", addr)
if err == nil {
c.Close()
}
elapsed := time.Now().Sub(startTime)
if i == 2 {
t.Logf("dialClosedPort: measured delay %v", elapsed)
return elapsed, expected
}
} }
elapsed := time.Now().Sub(startTime)
t.Logf("dialClosedPort: measured delay %v", elapsed)
return elapsed
} }
func TestDialParallel(t *testing.T) { func TestDialParallel(t *testing.T) {
@ -198,10 +185,7 @@ func TestDialParallel(t *testing.T) {
t.Skip("both IPv4 and IPv6 are required") t.Skip("both IPv4 and IPv6 are required")
} }
closedPortDelay, expectClosedPortDelay := dialClosedPort(t) closedPortDelay := dialClosedPort(t)
if closedPortDelay > expectClosedPortDelay {
t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay)
}
const instant time.Duration = 0 const instant time.Duration = 0
const fallbackDelay = 200 * time.Millisecond const fallbackDelay = 200 * time.Millisecond
@ -675,10 +659,7 @@ func TestDialerDualStack(t *testing.T) {
t.Skip("both IPv4 and IPv6 are required") t.Skip("both IPv4 and IPv6 are required")
} }
closedPortDelay, expectClosedPortDelay := dialClosedPort(t) closedPortDelay := dialClosedPort(t)
if closedPortDelay > expectClosedPortDelay {
t.Errorf("got %v; want <= %v", closedPortDelay, expectClosedPortDelay)
}
origTestHookLookupIP := testHookLookupIP origTestHookLookupIP := testHookLookupIP
defer func() { testHookLookupIP = origTestHookLookupIP }() defer func() { testHookLookupIP = origTestHookLookupIP }()

View File

@ -299,7 +299,7 @@ func lookupPTR(name string) (ptr []string, err error) {
ptr = make([]string, 0, 10) ptr = make([]string, 0, 10)
rx := regexp.MustCompile(`(?m)^Pinging\s+([a-zA-Z0-9.\-]+)\s+\[.*$`) rx := regexp.MustCompile(`(?m)^Pinging\s+([a-zA-Z0-9.\-]+)\s+\[.*$`)
for _, ans := range rx.FindAllStringSubmatch(r, -1) { for _, ans := range rx.FindAllStringSubmatch(r, -1) {
ptr = append(ptr, ans[1]+".") ptr = append(ptr, absDomainName([]byte(ans[1])))
} }
return return
} }

View File

@ -26,9 +26,6 @@ func TestFifoEOF(t *testing.T) {
switch runtime.GOOS { switch runtime.GOOS {
case "android": case "android":
t.Skip("skipping on Android; mkfifo syscall not available") t.Skip("skipping on Android; mkfifo syscall not available")
case "openbsd":
// On OpenBSD 6.2 this test just hangs for some reason.
t.Skip("skipping on OpenBSD; issue 25877")
} }
dir := t.TempDir() dir := t.TempDir()

View File

@ -1377,10 +1377,16 @@ func valueInterface(v Value, safe bool) interface{} {
return packEface(v) return packEface(v)
} }
// InterfaceData returns the interface v's value as a uintptr pair. // InterfaceData returns a pair of unspecified uintptr values.
// It panics if v's Kind is not Interface. // It panics if v's Kind is not Interface.
//
// In earlier versions of Go, this function returned the interface's
// value as a uintptr pair. As of Go 1.4, the implementation of
// interface values precludes any defined use of InterfaceData.
//
// Deprecated: The memory representation of interface values is not
// compatible with InterfaceData.
func (v Value) InterfaceData() [2]uintptr { func (v Value) InterfaceData() [2]uintptr {
// TODO: deprecate this
v.mustBe(Interface) v.mustBe(Interface)
// We treat this as a read operation, so we allow // We treat this as a read operation, so we allow
// it even for unexported data, because the caller // it even for unexported data, because the caller

View File

@ -65,7 +65,7 @@ TEXT ·Xaddint64(SB), NOSPLIT, $0-20
// bool ·Cas64(uint64 *val, uint64 old, uint64 new) // bool ·Cas64(uint64 *val, uint64 old, uint64 new)
// Atomically: // Atomically:
// if(*val == *old){ // if(*val == old){
// *val = new; // *val = new;
// return 1; // return 1;
// } else { // } else {

View File

@ -751,8 +751,11 @@ type ParseError struct {
// These are borrowed from unicode/utf8 and strconv and replicate behavior in // These are borrowed from unicode/utf8 and strconv and replicate behavior in
// that package, since we can't take a dependency on either. // that package, since we can't take a dependency on either.
const runeSelf = 0x80 const (
const lowerhex = "0123456789abcdef" lowerhex = "0123456789abcdef"
runeSelf = 0x80
runeError = '\uFFFD'
)
func quote(s string) string { func quote(s string) string {
buf := make([]byte, 1, len(s)+2) // slice will be at least len(s) + quotes buf := make([]byte, 1, len(s)+2) // slice will be at least len(s) + quotes
@ -765,7 +768,16 @@ func quote(s string) string {
// reproduce strconv.Quote's behavior with full fidelity but // reproduce strconv.Quote's behavior with full fidelity but
// given how rarely we expect to hit these edge cases, speed and // given how rarely we expect to hit these edge cases, speed and
// conciseness are better. // conciseness are better.
for j := 0; j < len(string(c)) && j < len(s); j++ { var width int
if c == runeError {
width = 1
if i+2 < len(s) && s[i:i+3] == string(runeError) {
width = 3
}
} else {
width = len(string(c))
}
for j := 0; j < width; j++ {
buf = append(buf, `\x`...) buf = append(buf, `\x`...)
buf = append(buf, lowerhex[s[i+j]>>4]) buf = append(buf, lowerhex[s[i+j]>>4])
buf = append(buf, lowerhex[s[i+j]&0xF]) buf = append(buf, lowerhex[s[i+j]&0xF])

View File

@ -917,6 +917,11 @@ var parseDurationErrorTests = []struct {
{".s", `".s"`}, {".s", `".s"`},
{"+.s", `"+.s"`}, {"+.s", `"+.s"`},
{"1d", `"1d"`}, {"1d", `"1d"`},
{"\x85\x85", `"\x85\x85"`},
{"\xffff", `"\xffff"`},
{"hello \xffff world", `"hello \xffff world"`},
{"\uFFFD", `"\xef\xbf\xbd"`}, // utf8.RuneError
{"\uFFFD hello \uFFFD world", `"\xef\xbf\xbd hello \xef\xbf\xbd world"`}, // utf8.RuneError
// overflow // overflow
{"9223372036854775810ns", `"9223372036854775810ns"`}, {"9223372036854775810ns", `"9223372036854775810ns"`},
{"9223372036854775808ns", `"9223372036854775808ns"`}, {"9223372036854775808ns", `"9223372036854775808ns"`},

View File

@ -0,0 +1,11 @@
// compile
// Copyright 2021 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 p
func f(b []byte) []byte {
return (*[32]byte)(b[:32])[:]
}