mirror of
https://github.com/golang/go.git
synced 2025-05-07 08:32:59 +00:00
Compare commits
30 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
69234ded30 | ||
|
032ac075c2 | ||
|
fa8ff1a46d | ||
|
53487e5477 | ||
|
3d1f1f27cf | ||
|
6de5a7180c | ||
|
9625a7faae | ||
|
9c939a1e60 | ||
|
7afe17bbdb | ||
|
8002845759 | ||
|
9166d2feec | ||
|
76346b3543 | ||
|
3c9340557c | ||
|
dbecb416d1 | ||
|
6885bad7dd | ||
|
ec7d6094e6 | ||
|
63b0f805cd | ||
|
7adb012205 | ||
|
c9940fe2a9 | ||
|
3509415eca | ||
|
559c77592f | ||
|
f5e4e45ef7 | ||
|
30b6fd60a6 | ||
|
7e4d6c2bcb | ||
|
8bd4ed6cbb | ||
|
7dff7439dc | ||
|
62c3a6350b | ||
|
eba9e08766 | ||
|
f3bdcda88a | ||
|
362f22d2d2 |
@ -1 +1,2 @@
|
||||
branch: master
|
||||
branch: release-branch.go1.23
|
||||
parent-branch: master
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"cmd/compile/internal/syntax"
|
||||
"cmd/compile/internal/types2"
|
||||
"cmd/internal/src"
|
||||
"internal/buildcfg"
|
||||
"internal/pkgbits"
|
||||
)
|
||||
|
||||
@ -411,6 +412,14 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
|
||||
panic("weird")
|
||||
|
||||
case pkgbits.ObjAlias:
|
||||
if buildcfg.Experiment.AliasTypeParams && len(r.dict.bounds) > 0 {
|
||||
// Temporary work-around for issue #68526: rather than panicking
|
||||
// with an non-descriptive index-out-of-bounds panic when trying
|
||||
// to access a missing type parameter, instead panic with a more
|
||||
// descriptive error. Only needed for Go 1.23; Go 1.24 will have
|
||||
// the correct implementation.
|
||||
panic("importing generic type aliases is not supported in Go 1.23 (see issue #68526)")
|
||||
}
|
||||
pos := r.pos()
|
||||
typ := r.typ()
|
||||
return newAliasTypeName(pr.enableAlias, pos, objPkg, objName, typ)
|
||||
|
@ -134,10 +134,10 @@ func (check *Checker) newAlias(obj *TypeName, rhs Type) *Alias {
|
||||
// newAliasInstance creates a new alias instance for the given origin and type
|
||||
// arguments, recording pos as the position of its synthetic object (for error
|
||||
// reporting).
|
||||
func (check *Checker) newAliasInstance(pos syntax.Pos, orig *Alias, targs []Type, ctxt *Context) *Alias {
|
||||
func (check *Checker) newAliasInstance(pos syntax.Pos, orig *Alias, targs []Type, expanding *Named, ctxt *Context) *Alias {
|
||||
assert(len(targs) > 0)
|
||||
obj := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
|
||||
rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), nil, ctxt)
|
||||
rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), expanding, ctxt)
|
||||
res := check.newAlias(obj, rhs)
|
||||
res.orig = orig
|
||||
res.tparams = orig.tparams
|
||||
|
@ -2898,22 +2898,48 @@ func TestFileVersions(t *testing.T) {
|
||||
fileVersion string
|
||||
wantVersion string
|
||||
}{
|
||||
{"", "", ""}, // 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)
|
||||
{"", "", ""}, // no versions specified
|
||||
{"go1.19", "", "go1.19"}, // module version specified
|
||||
{"", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1", "", "go1"}, // no file version specified
|
||||
{"go1", "goo1.22", "go1"}, // invalid file version specified
|
||||
{"go1", "go1.19", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1", "go1.21", "go1.21"}, // file version specified at 1.21
|
||||
{"go1", "go1.22", "go1.22"}, // file version specified above 1.21
|
||||
{"go1.19", "", "go1.19"}, // no file version specified
|
||||
{"go1.19", "goo1.22", "go1.19"}, // invalid file version specified
|
||||
{"go1.19", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.19", "go1.21", "go1.21"}, // file version specified at 1.21
|
||||
{"go1.19", "go1.22", "go1.22"}, // file version specified above 1.21
|
||||
{"go1.20", "", "go1.20"}, // no file version specified
|
||||
{"go1.20", "goo1.22", "go1.20"}, // invalid file version specified
|
||||
{"go1.20", "go1.19", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.20", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.20", "go1.21", "go1.21"}, // file version specified at 1.21
|
||||
{"go1.20", "go1.22", "go1.22"}, // file version specified above 1.21
|
||||
{"go1.21", "", "go1.21"}, // no file version specified
|
||||
{"go1.21", "goo1.22", "go1.21"}, // invalid file version specified
|
||||
{"go1.21", "go1.19", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.21", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.21", "go1.21", "go1.21"}, // file version specified at 1.21
|
||||
{"go1.21", "go1.22", "go1.22"}, // file version specified above 1.21
|
||||
{"go1.22", "", "go1.22"}, // no file version specified
|
||||
{"go1.22", "goo1.22", "go1.22"}, // invalid file version specified
|
||||
{"go1.22", "go1.19", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.22", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.22", "go1.21", "go1.21"}, // file version specified at 1.21
|
||||
{"go1.22", "go1.22", "go1.22"}, // file version specified above 1.21
|
||||
|
||||
// versions containing release numbers
|
||||
// (file versions containing release numbers are considered invalid)
|
||||
{"go1.19.0", "", "go1.19.0"}, // no file version specified
|
||||
{"go1.20", "go1.20.1", "go1.20"}, // file upgrade ignored
|
||||
{"go1.20.1", "go1.20", "go1.20.1"}, // file upgrade ignored
|
||||
{"go1.20.1", "go1.21", "go1.21"}, // file upgrade permitted
|
||||
{"go1.20.1", "go1.19", "go1.20.1"}, // file downgrade not permitted
|
||||
{"go1.21.1", "go1.19.1", "go1.21.1"}, // file downgrade not permitted (invalid file version)
|
||||
{"go1.21.1", "go1.19", "go1.19"}, // file downgrade permitted (module version is >= go1.21)
|
||||
{"go1.20.1", "go1.19.1", "go1.20.1"}, // invalid file version
|
||||
{"go1.20.1", "go1.21.1", "go1.20.1"}, // invalid file version
|
||||
{"go1.21.1", "go1.19.1", "go1.21.1"}, // invalid file version
|
||||
{"go1.21.1", "go1.21.1", "go1.21.1"}, // invalid file version
|
||||
{"go1.22.1", "go1.19.1", "go1.22.1"}, // invalid file version
|
||||
{"go1.22.1", "go1.21.1", "go1.22.1"}, // invalid file version
|
||||
} {
|
||||
var src string
|
||||
if test.fileVersion != "" {
|
||||
|
@ -327,7 +327,6 @@ func (check *Checker) initFiles(files []*syntax.File) {
|
||||
check.errorf(files[0], TooNew, "package requires newer Go version %v (application built with %v)",
|
||||
check.version, go_current)
|
||||
}
|
||||
downgradeOk := check.version.cmp(go1_21) >= 0
|
||||
|
||||
// determine Go version for each file
|
||||
for _, file := range check.files {
|
||||
@ -336,33 +335,18 @@ func (check *Checker) initFiles(files []*syntax.File) {
|
||||
// unlike file versions which are Go language versions only, if valid.)
|
||||
v := check.conf.GoVersion
|
||||
|
||||
fileVersion := asGoVersion(file.GoVersion)
|
||||
if fileVersion.isValid() {
|
||||
// use the file version, if applicable
|
||||
// (file versions are either the empty string or of the form go1.dd)
|
||||
if pkgVersionOk {
|
||||
cmp := fileVersion.cmp(check.version)
|
||||
// Go 1.21 introduced the feature of setting the go.mod
|
||||
// go line to an early version of Go and allowing //go:build lines
|
||||
// to “upgrade” (cmp > 0) the Go version in a given file.
|
||||
// We can do that backwards compatibly.
|
||||
//
|
||||
// Go 1.21 also introduced the feature of allowing //go:build lines
|
||||
// to “downgrade” (cmp < 0) the Go version in a given file.
|
||||
// That can't be done compatibly in general, since before the
|
||||
// build lines were ignored and code got the module's Go version.
|
||||
// To work around this, downgrades are only allowed when the
|
||||
// module's Go version is Go 1.21 or later.
|
||||
//
|
||||
// If there is no valid check.version, then we don't really know what
|
||||
// Go version to apply.
|
||||
// Legacy tools may do this, and they historically have accepted everything.
|
||||
// Preserve that behavior by ignoring //go:build constraints entirely in that
|
||||
// case (!pkgVersionOk).
|
||||
if cmp > 0 || cmp < 0 && downgradeOk {
|
||||
v = file.GoVersion
|
||||
}
|
||||
}
|
||||
// If the file specifies a version, use max(fileVersion, go1.21).
|
||||
if fileVersion := asGoVersion(file.GoVersion); fileVersion.isValid() {
|
||||
// Go 1.21 introduced the feature of allowing //go:build lines
|
||||
// to sometimes set the Go version in a given file. Versions Go 1.21 and later
|
||||
// can be set backwards compatibly as that was the first version
|
||||
// files with go1.21 or later build tags could be built with.
|
||||
//
|
||||
// Set the version to max(fileVersion, go1.21): That will allow a
|
||||
// downgrade to a version before go1.22, where the for loop semantics
|
||||
// change was made, while being backwards compatible with versions of
|
||||
// go before the new //go:build semantics were introduced.
|
||||
v = string(versionMax(fileVersion, go1_21))
|
||||
|
||||
// Report a specific error for each tagged file that's too new.
|
||||
// (Normally the build system will have filtered files by version,
|
||||
@ -377,6 +361,13 @@ func (check *Checker) initFiles(files []*syntax.File) {
|
||||
}
|
||||
}
|
||||
|
||||
func versionMax(a, b goVersion) goVersion {
|
||||
if a.cmp(b) > 0 {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
// A bailout panic is used for early termination.
|
||||
type bailout struct{}
|
||||
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"cmd/compile/internal/syntax"
|
||||
"errors"
|
||||
"fmt"
|
||||
"internal/buildcfg"
|
||||
. "internal/types/errors"
|
||||
)
|
||||
|
||||
@ -126,8 +127,9 @@ func (check *Checker) instance(pos syntax.Pos, orig genericType, targs []Type, e
|
||||
res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
|
||||
|
||||
case *Alias:
|
||||
// TODO(gri) is this correct?
|
||||
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
||||
if !buildcfg.Experiment.AliasTypeParams {
|
||||
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
||||
}
|
||||
|
||||
tparams := orig.TypeParams()
|
||||
// TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
|
||||
@ -138,7 +140,7 @@ func (check *Checker) instance(pos syntax.Pos, orig genericType, targs []Type, e
|
||||
return orig // nothing to do (minor optimization)
|
||||
}
|
||||
|
||||
return check.newAliasInstance(pos, orig, targs, ctxt)
|
||||
return check.newAliasInstance(pos, orig, targs, expanding, ctxt)
|
||||
|
||||
case *Signature:
|
||||
assert(expanding == nil) // function instances cannot be reached from Named types
|
||||
|
@ -1121,3 +1121,23 @@ func f(x int) {
|
||||
t.Errorf("got: %s want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue68877(t *testing.T) {
|
||||
const src = `
|
||||
package p
|
||||
|
||||
type (
|
||||
S struct{}
|
||||
A = S
|
||||
T A
|
||||
)`
|
||||
|
||||
conf := Config{EnableAlias: true}
|
||||
pkg := mustTypecheck(src, &conf, nil)
|
||||
T := pkg.Scope().Lookup("T").(*TypeName)
|
||||
got := T.String() // this must not panic (was issue)
|
||||
const want = "type p.T struct{}"
|
||||
if got != want {
|
||||
t.Errorf("got %s, want %s", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -282,7 +282,7 @@ func (t *Named) cleanup() {
|
||||
if t.TypeArgs().Len() == 0 {
|
||||
panic("nil underlying")
|
||||
}
|
||||
case *Named:
|
||||
case *Named, *Alias:
|
||||
t.under() // t.under may add entries to check.cleaners
|
||||
}
|
||||
t.check = nil
|
||||
|
@ -115,7 +115,7 @@ func (subst *subster) typ(typ Type) Type {
|
||||
// that has a type argument for it.
|
||||
targs, updated := subst.typeList(t.TypeArgs().list())
|
||||
if updated {
|
||||
return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.ctxt)
|
||||
return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.expanding, subst.ctxt)
|
||||
}
|
||||
|
||||
case *Array:
|
||||
|
@ -131,8 +131,8 @@ func (s *_TypeSet) underIs(f func(Type) bool) bool {
|
||||
}
|
||||
for _, t := range s.terms {
|
||||
assert(t.typ != nil)
|
||||
// x == under(x) for ~x terms
|
||||
u := t.typ
|
||||
// Unalias(x) == under(x) for ~x terms
|
||||
u := Unalias(t.typ)
|
||||
if !t.tilde {
|
||||
u = under(u)
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ require (
|
||||
golang.org/x/mod v0.19.0
|
||||
golang.org/x/sync v0.7.0
|
||||
golang.org/x/sys v0.22.0
|
||||
golang.org/x/telemetry v0.0.0-20240717194752-0b706e19b701
|
||||
golang.org/x/telemetry v0.0.0-20240828213427-40b6b7fe7147
|
||||
golang.org/x/term v0.20.0
|
||||
golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72
|
||||
)
|
||||
|
@ -16,8 +16,8 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240717194752-0b706e19b701 h1:+bltxAtk8YFEQ61B/lcYQM8e+7XjLwSDbpspVaVYkz8=
|
||||
golang.org/x/telemetry v0.0.0-20240717194752-0b706e19b701/go.mod h1:amNmu/SBSm2GAF3X+9U2C0epLocdh+r5Z+7oMYO5cLM=
|
||||
golang.org/x/telemetry v0.0.0-20240828213427-40b6b7fe7147 h1:Lj8KbuZmoFUbI6pQ28G3Diz/5bRYD2UY5vfAmhrLZWo=
|
||||
golang.org/x/telemetry v0.0.0-20240828213427-40b6b7fe7147/go.mod h1:amNmu/SBSm2GAF3X+9U2C0epLocdh+r5Z+7oMYO5cLM=
|
||||
golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
|
11
src/cmd/vendor/golang.org/x/telemetry/internal/configstore/download.go
generated
vendored
11
src/cmd/vendor/golang.org/x/telemetry/internal/configstore/download.go
generated
vendored
@ -16,6 +16,7 @@ import (
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sync/atomic"
|
||||
|
||||
"golang.org/x/telemetry/internal/telemetry"
|
||||
)
|
||||
@ -29,12 +30,22 @@ const (
|
||||
// creation flag.
|
||||
var needNoConsole = func(cmd *exec.Cmd) {}
|
||||
|
||||
var downloads int64
|
||||
|
||||
// Downloads reports, for testing purposes, the number of times [Download] has
|
||||
// been called.
|
||||
func Downloads() int64 {
|
||||
return atomic.LoadInt64(&downloads)
|
||||
}
|
||||
|
||||
// Download fetches the requested telemetry UploadConfig using "go mod
|
||||
// download". If envOverlay is provided, it is appended to the environment used
|
||||
// for invoking the go command.
|
||||
//
|
||||
// The second result is the canonical version of the requested configuration.
|
||||
func Download(version string, envOverlay []string) (*telemetry.UploadConfig, string, error) {
|
||||
atomic.AddInt64(&downloads, 1)
|
||||
|
||||
if version == "" {
|
||||
version = "latest"
|
||||
}
|
||||
|
4
src/cmd/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go
generated
vendored
4
src/cmd/vendor/golang.org/x/telemetry/internal/crashmonitor/monitor.go
generated
vendored
@ -21,12 +21,12 @@ import (
|
||||
"golang.org/x/telemetry/internal/counter"
|
||||
)
|
||||
|
||||
// Supported reports whether the runtime supports [runtime.SetCrashOutput].
|
||||
// Supported reports whether the runtime supports [runtime/debug.SetCrashOutput].
|
||||
//
|
||||
// TODO(adonovan): eliminate once go1.23+ is assured.
|
||||
func Supported() bool { return setCrashOutput != nil }
|
||||
|
||||
var setCrashOutput func(*os.File) error // = runtime.SetCrashOutput on go1.23+
|
||||
var setCrashOutput func(*os.File) error // = runtime/debug.SetCrashOutput on go1.23+
|
||||
|
||||
// Parent sets up the parent side of the crashmonitor. It requires
|
||||
// exclusive use of a writable pipe connected to the child process's stdin.
|
||||
|
21
src/cmd/vendor/golang.org/x/telemetry/internal/upload/run.go
generated
vendored
21
src/cmd/vendor/golang.org/x/telemetry/internal/upload/run.go
generated
vendored
@ -112,9 +112,24 @@ func newUploader(rcfg RunConfig) (*uploader, error) {
|
||||
logger := log.New(logWriter, "", log.Ltime|log.Lmicroseconds|log.Lshortfile)
|
||||
|
||||
// Fetch the upload config, if it is not provided.
|
||||
config, configVersion, err := configstore.Download("latest", rcfg.Env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var (
|
||||
config *telemetry.UploadConfig
|
||||
configVersion string
|
||||
)
|
||||
|
||||
if mode, _ := dir.Mode(); mode == "on" {
|
||||
// golang/go#68946: only download the upload config if it will be used.
|
||||
//
|
||||
// TODO(rfindley): This is a narrow change aimed at minimally fixing the
|
||||
// associated bug. In the future, we should read the mode only once during
|
||||
// the upload process.
|
||||
config, configVersion, err = configstore.Download("latest", rcfg.Env)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
config = &telemetry.UploadConfig{}
|
||||
configVersion = "v0.0.0-0"
|
||||
}
|
||||
|
||||
// Set the start time, if it is not provided.
|
||||
|
19
src/cmd/vendor/golang.org/x/telemetry/start.go
generated
vendored
19
src/cmd/vendor/golang.org/x/telemetry/start.go
generated
vendored
@ -206,7 +206,8 @@ func startChild(reportCrashes, upload bool, result *StartResult) {
|
||||
fd, err := os.Stat(telemetry.Default.DebugDir())
|
||||
if err != nil {
|
||||
if !os.IsNotExist(err) {
|
||||
log.Fatalf("failed to stat debug directory: %v", err)
|
||||
log.Printf("failed to stat debug directory: %v", err)
|
||||
return
|
||||
}
|
||||
} else if fd.IsDir() {
|
||||
// local/debug exists and is a directory. Set stderr to a log file path
|
||||
@ -214,23 +215,31 @@ func startChild(reportCrashes, upload bool, result *StartResult) {
|
||||
childLogPath := filepath.Join(telemetry.Default.DebugDir(), "sidecar.log")
|
||||
childLog, err := os.OpenFile(childLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
|
||||
if err != nil {
|
||||
log.Fatalf("opening sidecar log file for child: %v", err)
|
||||
log.Printf("opening sidecar log file for child: %v", err)
|
||||
return
|
||||
}
|
||||
defer childLog.Close()
|
||||
cmd.Stderr = childLog
|
||||
}
|
||||
|
||||
var crashOutputFile *os.File
|
||||
if reportCrashes {
|
||||
pipe, err := cmd.StdinPipe()
|
||||
if err != nil {
|
||||
log.Fatalf("StdinPipe: %v", err)
|
||||
log.Printf("StdinPipe: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
crashmonitor.Parent(pipe.(*os.File)) // (this conversion is safe)
|
||||
crashOutputFile = pipe.(*os.File) // (this conversion is safe)
|
||||
}
|
||||
|
||||
if err := cmd.Start(); err != nil {
|
||||
log.Fatalf("can't start telemetry child process: %v", err)
|
||||
// The child couldn't be started. Log the failure.
|
||||
log.Printf("can't start telemetry child process: %v", err)
|
||||
return
|
||||
}
|
||||
if reportCrashes {
|
||||
crashmonitor.Parent(crashOutputFile)
|
||||
}
|
||||
result.wg.Add(1)
|
||||
go func() {
|
||||
|
2
src/cmd/vendor/modules.txt
vendored
2
src/cmd/vendor/modules.txt
vendored
@ -45,7 +45,7 @@ golang.org/x/sync/semaphore
|
||||
golang.org/x/sys/plan9
|
||||
golang.org/x/sys/unix
|
||||
golang.org/x/sys/windows
|
||||
# golang.org/x/telemetry v0.0.0-20240717194752-0b706e19b701
|
||||
# golang.org/x/telemetry v0.0.0-20240828213427-40b6b7fe7147
|
||||
## explicit; go 1.20
|
||||
golang.org/x/telemetry
|
||||
golang.org/x/telemetry/counter
|
||||
|
@ -491,9 +491,10 @@ func testHandshake(t *testing.T, clientConfig, serverConfig *Config) (serverStat
|
||||
if got := string(buf); got != sentinel {
|
||||
t.Errorf("read %q from TLS connection, but expected %q", got, sentinel)
|
||||
}
|
||||
if err := cli.Close(); err != nil {
|
||||
t.Errorf("failed to call cli.Close: %v", err)
|
||||
}
|
||||
// We discard the error because after ReadAll returns the server must
|
||||
// have already closed the connection. Sending data (the closeNotify
|
||||
// alert) can cause a reset, that will make Close return an error.
|
||||
cli.Close()
|
||||
}()
|
||||
server := Server(s, serverConfig)
|
||||
err = server.Handshake()
|
||||
|
@ -1368,8 +1368,8 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn
|
||||
|
||||
db.waitDuration.Add(int64(time.Since(waitStart)))
|
||||
|
||||
// If we failed to delete it, that means something else
|
||||
// grabbed it and is about to send on it.
|
||||
// If we failed to delete it, that means either the DB was closed or
|
||||
// something else grabbed it and is about to send on it.
|
||||
if !deleted {
|
||||
// TODO(bradfitz): rather than this best effort select, we
|
||||
// should probably start a goroutine to read from req. This best
|
||||
@ -3594,6 +3594,7 @@ type connRequestAndIndex struct {
|
||||
// and clears the set.
|
||||
func (s *connRequestSet) CloseAndRemoveAll() {
|
||||
for _, v := range s.s {
|
||||
*v.curIdx = -1
|
||||
close(v.req)
|
||||
}
|
||||
s.s = nil
|
||||
|
@ -4920,6 +4920,17 @@ func TestConnRequestSet(t *testing.T) {
|
||||
t.Error("wasn't random")
|
||||
}
|
||||
})
|
||||
t.Run("close-delete", func(t *testing.T) {
|
||||
reset()
|
||||
ch := make(chan connRequest)
|
||||
dh := s.Add(ch)
|
||||
wantLen(1)
|
||||
s.CloseAndRemoveAll()
|
||||
wantLen(0)
|
||||
if s.Delete(dh) {
|
||||
t.Error("unexpected delete after CloseAndRemoveAll")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkConnRequestSet(b *testing.B) {
|
||||
|
@ -911,8 +911,11 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
|
||||
var maxIgnoreNestingDepth = 10000
|
||||
|
||||
// decIgnoreOpFor returns the decoding op for a field that has no destination.
|
||||
func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp, depth int) *decOp {
|
||||
if depth > maxIgnoreNestingDepth {
|
||||
func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) *decOp {
|
||||
// Track how deep we've recursed trying to skip nested ignored fields.
|
||||
dec.ignoreDepth++
|
||||
defer func() { dec.ignoreDepth-- }()
|
||||
if dec.ignoreDepth > maxIgnoreNestingDepth {
|
||||
error_(errors.New("invalid nesting depth"))
|
||||
}
|
||||
// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
|
||||
@ -938,7 +941,7 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp,
|
||||
errorf("bad data: undefined type %s", wireId.string())
|
||||
case wire.ArrayT != nil:
|
||||
elemId := wire.ArrayT.Elem
|
||||
elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
|
||||
elemOp := dec.decIgnoreOpFor(elemId, inProgress)
|
||||
op = func(i *decInstr, state *decoderState, value reflect.Value) {
|
||||
state.dec.ignoreArray(state, *elemOp, wire.ArrayT.Len)
|
||||
}
|
||||
@ -946,15 +949,15 @@ func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp,
|
||||
case wire.MapT != nil:
|
||||
keyId := dec.wireType[wireId].MapT.Key
|
||||
elemId := dec.wireType[wireId].MapT.Elem
|
||||
keyOp := dec.decIgnoreOpFor(keyId, inProgress, depth+1)
|
||||
elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
|
||||
keyOp := dec.decIgnoreOpFor(keyId, inProgress)
|
||||
elemOp := dec.decIgnoreOpFor(elemId, inProgress)
|
||||
op = func(i *decInstr, state *decoderState, value reflect.Value) {
|
||||
state.dec.ignoreMap(state, *keyOp, *elemOp)
|
||||
}
|
||||
|
||||
case wire.SliceT != nil:
|
||||
elemId := wire.SliceT.Elem
|
||||
elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
|
||||
elemOp := dec.decIgnoreOpFor(elemId, inProgress)
|
||||
op = func(i *decInstr, state *decoderState, value reflect.Value) {
|
||||
state.dec.ignoreSlice(state, *elemOp)
|
||||
}
|
||||
@ -1115,7 +1118,7 @@ func (dec *Decoder) compileSingle(remoteId typeId, ut *userTypeInfo) (engine *de
|
||||
func (dec *Decoder) compileIgnoreSingle(remoteId typeId) *decEngine {
|
||||
engine := new(decEngine)
|
||||
engine.instr = make([]decInstr, 1) // one item
|
||||
op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp), 0)
|
||||
op := dec.decIgnoreOpFor(remoteId, make(map[typeId]*decOp))
|
||||
ovfl := overflow(dec.typeString(remoteId))
|
||||
engine.instr[0] = decInstr{*op, 0, nil, ovfl}
|
||||
engine.numInstr = 1
|
||||
@ -1160,7 +1163,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
|
||||
localField, present := srt.FieldByName(wireField.Name)
|
||||
// TODO(r): anonymous names
|
||||
if !present || !isExported(wireField.Name) {
|
||||
op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp), 0)
|
||||
op := dec.decIgnoreOpFor(wireField.Id, make(map[typeId]*decOp))
|
||||
engine.instr[fieldnum] = decInstr{*op, fieldnum, nil, ovfl}
|
||||
continue
|
||||
}
|
||||
|
@ -35,6 +35,8 @@ type Decoder struct {
|
||||
freeList *decoderState // list of free decoderStates; avoids reallocation
|
||||
countBuf []byte // used for decoding integers while parsing messages
|
||||
err error
|
||||
// ignoreDepth tracks the depth of recursively parsed ignored fields
|
||||
ignoreDepth int
|
||||
}
|
||||
|
||||
// NewDecoder returns a new decoder that reads from the [io.Reader].
|
||||
|
@ -806,6 +806,8 @@ func TestIgnoreDepthLimit(t *testing.T) {
|
||||
defer func() { maxIgnoreNestingDepth = oldNestingDepth }()
|
||||
b := new(bytes.Buffer)
|
||||
enc := NewEncoder(b)
|
||||
|
||||
// Nested slice
|
||||
typ := reflect.TypeFor[int]()
|
||||
nested := reflect.ArrayOf(1, typ)
|
||||
for i := 0; i < 100; i++ {
|
||||
@ -819,4 +821,16 @@ func TestIgnoreDepthLimit(t *testing.T) {
|
||||
if err := dec.Decode(&output); err == nil || err.Error() != expectedErr {
|
||||
t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err)
|
||||
}
|
||||
|
||||
// Nested struct
|
||||
nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: typ}})
|
||||
for i := 0; i < 100; i++ {
|
||||
nested = reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}})
|
||||
}
|
||||
badStruct = reflect.New(reflect.StructOf([]reflect.StructField{{Name: "F", Type: nested}}))
|
||||
enc.Encode(badStruct.Interface())
|
||||
dec = NewDecoder(b)
|
||||
if err := dec.Decode(&output); err == nil || err.Error() != expectedErr {
|
||||
t.Errorf("Decode didn't fail with depth limit of 100: want %q, got %q", expectedErr, err)
|
||||
}
|
||||
}
|
||||
|
@ -16,6 +16,10 @@ import (
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
// maxSize is a limit used to control the complexity of expressions, in order
|
||||
// to prevent stack exhaustion issues due to recursion.
|
||||
const maxSize = 1000
|
||||
|
||||
// An Expr is a build tag constraint expression.
|
||||
// The underlying concrete type is *[AndExpr], *[OrExpr], *[NotExpr], or *[TagExpr].
|
||||
type Expr interface {
|
||||
@ -151,7 +155,7 @@ func Parse(line string) (Expr, error) {
|
||||
return parseExpr(text)
|
||||
}
|
||||
if text, ok := splitPlusBuild(line); ok {
|
||||
return parsePlusBuildExpr(text), nil
|
||||
return parsePlusBuildExpr(text)
|
||||
}
|
||||
return nil, errNotConstraint
|
||||
}
|
||||
@ -201,6 +205,8 @@ type exprParser struct {
|
||||
tok string // last token read
|
||||
isTag bool
|
||||
pos int // position (start) of last token
|
||||
|
||||
size int
|
||||
}
|
||||
|
||||
// parseExpr parses a boolean build tag expression.
|
||||
@ -249,6 +255,10 @@ func (p *exprParser) and() Expr {
|
||||
// On entry, the next input token has not yet been lexed.
|
||||
// On exit, the next input token has been lexed and is in p.tok.
|
||||
func (p *exprParser) not() Expr {
|
||||
p.size++
|
||||
if p.size > maxSize {
|
||||
panic(&SyntaxError{Offset: p.pos, Err: "build expression too large"})
|
||||
}
|
||||
p.lex()
|
||||
if p.tok == "!" {
|
||||
p.lex()
|
||||
@ -388,7 +398,13 @@ func splitPlusBuild(line string) (expr string, ok bool) {
|
||||
}
|
||||
|
||||
// parsePlusBuildExpr parses a legacy build tag expression (as used with “// +build”).
|
||||
func parsePlusBuildExpr(text string) Expr {
|
||||
func parsePlusBuildExpr(text string) (Expr, error) {
|
||||
// Only allow up to 100 AND/OR operators for "old" syntax.
|
||||
// This is much less than the limit for "new" syntax,
|
||||
// but uses of old syntax were always very simple.
|
||||
const maxOldSize = 100
|
||||
size := 0
|
||||
|
||||
var x Expr
|
||||
for _, clause := range strings.Fields(text) {
|
||||
var y Expr
|
||||
@ -414,19 +430,25 @@ func parsePlusBuildExpr(text string) Expr {
|
||||
if y == nil {
|
||||
y = z
|
||||
} else {
|
||||
if size++; size > maxOldSize {
|
||||
return nil, errComplex
|
||||
}
|
||||
y = and(y, z)
|
||||
}
|
||||
}
|
||||
if x == nil {
|
||||
x = y
|
||||
} else {
|
||||
if size++; size > maxOldSize {
|
||||
return nil, errComplex
|
||||
}
|
||||
x = or(x, y)
|
||||
}
|
||||
}
|
||||
if x == nil {
|
||||
x = tag("ignore")
|
||||
}
|
||||
return x
|
||||
return x, nil
|
||||
}
|
||||
|
||||
// isValidTag reports whether the word is a valid build tag.
|
||||
|
@ -222,7 +222,7 @@ var parsePlusBuildExprTests = []struct {
|
||||
func TestParsePlusBuildExpr(t *testing.T) {
|
||||
for i, tt := range parsePlusBuildExprTests {
|
||||
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
||||
x := parsePlusBuildExpr(tt.in)
|
||||
x, _ := parsePlusBuildExpr(tt.in)
|
||||
if x.String() != tt.x.String() {
|
||||
t.Errorf("parsePlusBuildExpr(%q):\nhave %v\nwant %v", tt.in, x, tt.x)
|
||||
}
|
||||
@ -319,3 +319,66 @@ func TestPlusBuildLines(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestSizeLimits(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
expr string
|
||||
}{
|
||||
{
|
||||
name: "go:build or limit",
|
||||
expr: "//go:build " + strings.Repeat("a || ", maxSize+2),
|
||||
},
|
||||
{
|
||||
name: "go:build and limit",
|
||||
expr: "//go:build " + strings.Repeat("a && ", maxSize+2),
|
||||
},
|
||||
{
|
||||
name: "go:build and depth limit",
|
||||
expr: "//go:build " + strings.Repeat("(a &&", maxSize+2),
|
||||
},
|
||||
{
|
||||
name: "go:build or depth limit",
|
||||
expr: "//go:build " + strings.Repeat("(a ||", maxSize+2),
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, err := Parse(tc.expr)
|
||||
if err == nil {
|
||||
t.Error("expression did not trigger limit")
|
||||
} else if syntaxErr, ok := err.(*SyntaxError); !ok || syntaxErr.Err != "build expression too large" {
|
||||
if !ok {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
} else {
|
||||
t.Errorf("unexpected syntax error: %s", syntaxErr.Err)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlusSizeLimits(t *testing.T) {
|
||||
maxOldSize := 100
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
expr string
|
||||
}{
|
||||
{
|
||||
name: "+build or limit",
|
||||
expr: "// +build " + strings.Repeat("a ", maxOldSize+2),
|
||||
},
|
||||
{
|
||||
name: "+build and limit",
|
||||
expr: "// +build " + strings.Repeat("a,", maxOldSize+2),
|
||||
},
|
||||
} {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
_, err := Parse(tc.expr)
|
||||
if err == nil {
|
||||
t.Error("expression did not trigger limit")
|
||||
} else if err != errComplex {
|
||||
t.Errorf("unexpected error: got %q, want %q", err, errComplex)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1676,6 +1676,8 @@ func (p *parser) parseElementList() (list []ast.Expr) {
|
||||
}
|
||||
|
||||
func (p *parser) parseLiteralValue(typ ast.Expr) ast.Expr {
|
||||
defer decNestLev(incNestLev(p))
|
||||
|
||||
if p.trace {
|
||||
defer un(trace(p, "LiteralValue"))
|
||||
}
|
||||
|
@ -598,10 +598,11 @@ var parseDepthTests = []struct {
|
||||
{name: "chan2", format: "package main; var x «<-chan »int"},
|
||||
{name: "interface", format: "package main; var x «interface { M() «int» }»", scope: true, scopeMultiplier: 2}, // Scopes: InterfaceType, FuncType
|
||||
{name: "map", format: "package main; var x «map[int]»int"},
|
||||
{name: "slicelit", format: "package main; var x = «[]any{«»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
|
||||
{name: "arraylit", format: "package main; var x = «[1]any{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
|
||||
{name: "structlit", format: "package main; var x = «struct{x any}{«nil»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
|
||||
{name: "maplit", format: "package main; var x = «map[int]any{1:«nil»}»", parseMultiplier: 2}, // Parser nodes: CompositeLit, KeyValueExpr
|
||||
{name: "slicelit", format: "package main; var x = []any{«[]any{«»}»}", parseMultiplier: 3}, // Parser nodes: UnaryExpr, CompositeLit
|
||||
{name: "arraylit", format: "package main; var x = «[1]any{«nil»}»", parseMultiplier: 3}, // Parser nodes: UnaryExpr, CompositeLit
|
||||
{name: "structlit", format: "package main; var x = «struct{x any}{«nil»}»", parseMultiplier: 3}, // Parser nodes: UnaryExpr, CompositeLit
|
||||
{name: "maplit", format: "package main; var x = «map[int]any{1:«nil»}»", parseMultiplier: 3}, // Parser nodes: CompositeLit, KeyValueExpr
|
||||
{name: "element", format: "package main; var x = struct{x any}{x: «{«»}»}"},
|
||||
{name: "dot", format: "package main; var x = «x.»x"},
|
||||
{name: "index", format: "package main; var x = x«[1]»"},
|
||||
{name: "slice", format: "package main; var x = x«[1:2]»"},
|
||||
|
@ -137,10 +137,10 @@ func (check *Checker) newAlias(obj *TypeName, rhs Type) *Alias {
|
||||
// newAliasInstance creates a new alias instance for the given origin and type
|
||||
// arguments, recording pos as the position of its synthetic object (for error
|
||||
// reporting).
|
||||
func (check *Checker) newAliasInstance(pos token.Pos, orig *Alias, targs []Type, ctxt *Context) *Alias {
|
||||
func (check *Checker) newAliasInstance(pos token.Pos, orig *Alias, targs []Type, expanding *Named, ctxt *Context) *Alias {
|
||||
assert(len(targs) > 0)
|
||||
obj := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
|
||||
rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), nil, ctxt)
|
||||
rhs := check.subst(pos, orig.fromRHS, makeSubstMap(orig.TypeParams().list(), targs), expanding, ctxt)
|
||||
res := check.newAlias(obj, rhs)
|
||||
res.orig = orig
|
||||
res.tparams = orig.tparams
|
||||
|
@ -2904,22 +2904,48 @@ func TestFileVersions(t *testing.T) {
|
||||
fileVersion string
|
||||
wantVersion string
|
||||
}{
|
||||
{"", "", ""}, // 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)
|
||||
{"", "", ""}, // no versions specified
|
||||
{"go1.19", "", "go1.19"}, // module version specified
|
||||
{"", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1", "", "go1"}, // no file version specified
|
||||
{"go1", "goo1.22", "go1"}, // invalid file version specified
|
||||
{"go1", "go1.19", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1", "go1.21", "go1.21"}, // file version specified at 1.21
|
||||
{"go1", "go1.22", "go1.22"}, // file version specified above 1.21
|
||||
{"go1.19", "", "go1.19"}, // no file version specified
|
||||
{"go1.19", "goo1.22", "go1.19"}, // invalid file version specified
|
||||
{"go1.19", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.19", "go1.21", "go1.21"}, // file version specified at 1.21
|
||||
{"go1.19", "go1.22", "go1.22"}, // file version specified above 1.21
|
||||
{"go1.20", "", "go1.20"}, // no file version specified
|
||||
{"go1.20", "goo1.22", "go1.20"}, // invalid file version specified
|
||||
{"go1.20", "go1.19", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.20", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.20", "go1.21", "go1.21"}, // file version specified at 1.21
|
||||
{"go1.20", "go1.22", "go1.22"}, // file version specified above 1.21
|
||||
{"go1.21", "", "go1.21"}, // no file version specified
|
||||
{"go1.21", "goo1.22", "go1.21"}, // invalid file version specified
|
||||
{"go1.21", "go1.19", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.21", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.21", "go1.21", "go1.21"}, // file version specified at 1.21
|
||||
{"go1.21", "go1.22", "go1.22"}, // file version specified above 1.21
|
||||
{"go1.22", "", "go1.22"}, // no file version specified
|
||||
{"go1.22", "goo1.22", "go1.22"}, // invalid file version specified
|
||||
{"go1.22", "go1.19", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.22", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||
{"go1.22", "go1.21", "go1.21"}, // file version specified at 1.21
|
||||
{"go1.22", "go1.22", "go1.22"}, // file version specified above 1.21
|
||||
|
||||
// versions containing release numbers
|
||||
// (file versions containing release numbers are considered invalid)
|
||||
{"go1.19.0", "", "go1.19.0"}, // no file version specified
|
||||
{"go1.20", "go1.20.1", "go1.20"}, // file upgrade ignored
|
||||
{"go1.20.1", "go1.20", "go1.20.1"}, // file upgrade ignored
|
||||
{"go1.20.1", "go1.21", "go1.21"}, // file upgrade permitted
|
||||
{"go1.20.1", "go1.19", "go1.20.1"}, // file downgrade not permitted
|
||||
{"go1.21.1", "go1.19.1", "go1.21.1"}, // file downgrade not permitted (invalid file version)
|
||||
{"go1.21.1", "go1.19", "go1.19"}, // file downgrade permitted (module version is >= go1.21)
|
||||
{"go1.20.1", "go1.19.1", "go1.20.1"}, // invalid file version
|
||||
{"go1.20.1", "go1.21.1", "go1.20.1"}, // invalid file version
|
||||
{"go1.21.1", "go1.19.1", "go1.21.1"}, // invalid file version
|
||||
{"go1.21.1", "go1.21.1", "go1.21.1"}, // invalid file version
|
||||
{"go1.22.1", "go1.19.1", "go1.22.1"}, // invalid file version
|
||||
{"go1.22.1", "go1.21.1", "go1.22.1"}, // invalid file version
|
||||
} {
|
||||
var src string
|
||||
if test.fileVersion != "" {
|
||||
|
@ -349,7 +349,6 @@ func (check *Checker) initFiles(files []*ast.File) {
|
||||
check.errorf(files[0], TooNew, "package requires newer Go version %v (application built with %v)",
|
||||
check.version, go_current)
|
||||
}
|
||||
downgradeOk := check.version.cmp(go1_21) >= 0
|
||||
|
||||
// determine Go version for each file
|
||||
for _, file := range check.files {
|
||||
@ -358,33 +357,19 @@ func (check *Checker) initFiles(files []*ast.File) {
|
||||
// unlike file versions which are Go language versions only, if valid.)
|
||||
v := check.conf.GoVersion
|
||||
|
||||
fileVersion := asGoVersion(file.GoVersion)
|
||||
if fileVersion.isValid() {
|
||||
// use the file version, if applicable
|
||||
// (file versions are either the empty string or of the form go1.dd)
|
||||
if pkgVersionOk {
|
||||
cmp := fileVersion.cmp(check.version)
|
||||
// Go 1.21 introduced the feature of setting the go.mod
|
||||
// go line to an early version of Go and allowing //go:build lines
|
||||
// to “upgrade” (cmp > 0) the Go version in a given file.
|
||||
// We can do that backwards compatibly.
|
||||
//
|
||||
// Go 1.21 also introduced the feature of allowing //go:build lines
|
||||
// to “downgrade” (cmp < 0) the Go version in a given file.
|
||||
// That can't be done compatibly in general, since before the
|
||||
// build lines were ignored and code got the module's Go version.
|
||||
// To work around this, downgrades are only allowed when the
|
||||
// module's Go version is Go 1.21 or later.
|
||||
//
|
||||
// If there is no valid check.version, then we don't really know what
|
||||
// Go version to apply.
|
||||
// Legacy tools may do this, and they historically have accepted everything.
|
||||
// Preserve that behavior by ignoring //go:build constraints entirely in that
|
||||
// case (!pkgVersionOk).
|
||||
if cmp > 0 || cmp < 0 && downgradeOk {
|
||||
v = file.GoVersion
|
||||
}
|
||||
}
|
||||
// If the file specifies a version, use max(fileVersion, go1.21).
|
||||
if fileVersion := asGoVersion(file.GoVersion); fileVersion.isValid() {
|
||||
// Go 1.21 introduced the feature of setting the go.mod
|
||||
// go line to an early version of Go and allowing //go:build lines
|
||||
// to set the Go version in a given file. Versions Go 1.21 and later
|
||||
// can be set backwards compatibly as that was the first version
|
||||
// files with go1.21 or later build tags could be built with.
|
||||
//
|
||||
// Set the version to max(fileVersion, go1.21): That will allow a
|
||||
// downgrade to a version before go1.22, where the for loop semantics
|
||||
// change was made, while being backwards compatible with versions of
|
||||
// go before the new //go:build semantics were introduced.
|
||||
v = string(versionMax(fileVersion, go1_21))
|
||||
|
||||
// Report a specific error for each tagged file that's too new.
|
||||
// (Normally the build system will have filtered files by version,
|
||||
@ -399,6 +384,13 @@ func (check *Checker) initFiles(files []*ast.File) {
|
||||
}
|
||||
}
|
||||
|
||||
func versionMax(a, b goVersion) goVersion {
|
||||
if a.cmp(b) < 0 {
|
||||
return b
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
// A bailout panic is used for early termination.
|
||||
type bailout struct{}
|
||||
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/token"
|
||||
"internal/buildcfg"
|
||||
. "internal/types/errors"
|
||||
)
|
||||
|
||||
@ -129,8 +130,9 @@ func (check *Checker) instance(pos token.Pos, orig genericType, targs []Type, ex
|
||||
res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
|
||||
|
||||
case *Alias:
|
||||
// TODO(gri) is this correct?
|
||||
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
||||
if !buildcfg.Experiment.AliasTypeParams {
|
||||
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
||||
}
|
||||
|
||||
tparams := orig.TypeParams()
|
||||
// TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
|
||||
@ -141,7 +143,7 @@ func (check *Checker) instance(pos token.Pos, orig genericType, targs []Type, ex
|
||||
return orig // nothing to do (minor optimization)
|
||||
}
|
||||
|
||||
return check.newAliasInstance(pos, orig, targs, ctxt)
|
||||
return check.newAliasInstance(pos, orig, targs, expanding, ctxt)
|
||||
|
||||
case *Signature:
|
||||
assert(expanding == nil) // function instances cannot be reached from Named types
|
||||
|
@ -1131,3 +1131,23 @@ func f(x int) {
|
||||
t.Errorf("got: %s want: %s", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIssue68877(t *testing.T) {
|
||||
const src = `
|
||||
package p
|
||||
|
||||
type (
|
||||
S struct{}
|
||||
A = S
|
||||
T A
|
||||
)`
|
||||
|
||||
t.Setenv("GODEBUG", "gotypesalias=1")
|
||||
pkg := mustTypecheck(src, nil, nil)
|
||||
T := pkg.Scope().Lookup("T").(*TypeName)
|
||||
got := T.String() // this must not panic (was issue)
|
||||
const want = "type p.T struct{}"
|
||||
if got != want {
|
||||
t.Errorf("got %s, want %s", got, want)
|
||||
}
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ func (t *Named) cleanup() {
|
||||
if t.TypeArgs().Len() == 0 {
|
||||
panic("nil underlying")
|
||||
}
|
||||
case *Named:
|
||||
case *Named, *Alias:
|
||||
t.under() // t.under may add entries to check.cleaners
|
||||
}
|
||||
t.check = nil
|
||||
|
@ -118,7 +118,7 @@ func (subst *subster) typ(typ Type) Type {
|
||||
// that has a type argument for it.
|
||||
targs, updated := subst.typeList(t.TypeArgs().list())
|
||||
if updated {
|
||||
return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.ctxt)
|
||||
return subst.check.newAliasInstance(subst.pos, t.orig, targs, subst.expanding, subst.ctxt)
|
||||
}
|
||||
|
||||
case *Array:
|
||||
|
@ -134,8 +134,8 @@ func (s *_TypeSet) underIs(f func(Type) bool) bool {
|
||||
}
|
||||
for _, t := range s.terms {
|
||||
assert(t.typ != nil)
|
||||
// x == under(x) for ~x terms
|
||||
u := t.typ
|
||||
// Unalias(x) == under(x) for ~x terms
|
||||
u := Unalias(t.typ)
|
||||
if !t.tilde {
|
||||
u = under(u)
|
||||
}
|
||||
|
@ -177,6 +177,15 @@ func TypeOf(a any) *Type {
|
||||
return (*Type)(NoEscape(unsafe.Pointer(eface.Type)))
|
||||
}
|
||||
|
||||
// TypeFor returns the abi.Type for a type parameter.
|
||||
func TypeFor[T any]() *Type {
|
||||
var v T
|
||||
if t := TypeOf(v); t != nil {
|
||||
return t // optimize for T being a non-interface kind
|
||||
}
|
||||
return TypeOf((*T)(nil)).Elem() // only for an interface kind
|
||||
}
|
||||
|
||||
func (t *Type) Kind() Kind { return t.Kind_ & KindMask }
|
||||
|
||||
func (t *Type) HasName() bool {
|
||||
|
@ -14,4 +14,4 @@ type Slice []byte
|
||||
type Array [8]byte
|
||||
|
||||
var s Slice
|
||||
var p = (Array)(s /* ok because Go 1.20 ignored the //go:build go1.19 */)
|
||||
var p = (Array)(s /* ok because file versions below go1.21 set the langage version to go1.21 */)
|
||||
|
@ -14,4 +14,4 @@ type Slice []byte
|
||||
type Array [8]byte
|
||||
|
||||
var s Slice
|
||||
var p = (Array)(s /* ERROR "requires go1.20 or later" */)
|
||||
var p = (Array)(s /* ok because file versions below go1.21 set the langage version to go1.21 */)
|
||||
|
16
src/internal/types/testdata/check/go1_21_22.go
vendored
Normal file
16
src/internal/types/testdata/check/go1_21_22.go
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
// -lang=go1.21
|
||||
|
||||
// Copyright 2022 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.
|
||||
|
||||
// Check Go language version-specific errors.
|
||||
|
||||
//go:build go1.22
|
||||
|
||||
package p
|
||||
|
||||
func f() {
|
||||
for _ = range /* ok because of upgrade to 1.22 */ 10 {
|
||||
}
|
||||
}
|
16
src/internal/types/testdata/check/go1_22_21.go
vendored
Normal file
16
src/internal/types/testdata/check/go1_22_21.go
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
// -lang=go1.22
|
||||
|
||||
// Copyright 2024 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.
|
||||
|
||||
// Check Go language version-specific errors.
|
||||
|
||||
//go:build go1.21
|
||||
|
||||
package p
|
||||
|
||||
func f() {
|
||||
for _ = range 10 /* ERROR "requires go1.22 or later" */ {
|
||||
}
|
||||
}
|
@ -1,14 +1,9 @@
|
||||
// -lang=go1.21
|
||||
// -lang=go1.13
|
||||
|
||||
// Copyright 2024 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.
|
||||
|
||||
// Note: Downgrading to go1.13 requires at least go1.21,
|
||||
// hence the need for -lang=go1.21 at the top.
|
||||
|
||||
//go:build go1.13
|
||||
|
||||
package p
|
||||
|
||||
import "io"
|
||||
|
24
src/internal/types/testdata/fixedbugs/issue68903.go
vendored
Normal file
24
src/internal/types/testdata/fixedbugs/issue68903.go
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2024 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
|
||||
|
||||
type A = [4]int
|
||||
type B = map[string]interface{}
|
||||
|
||||
func _[T ~A](x T) {
|
||||
_ = len(x)
|
||||
}
|
||||
|
||||
func _[U ~A](x U) {
|
||||
_ = cap(x)
|
||||
}
|
||||
|
||||
func _[V ~A]() {
|
||||
_ = V{}
|
||||
}
|
||||
|
||||
func _[W ~B](a interface{}) {
|
||||
_ = a.(W)["key"]
|
||||
}
|
26
src/internal/types/testdata/fixedbugs/issue68935.go
vendored
Normal file
26
src/internal/types/testdata/fixedbugs/issue68935.go
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2024 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
|
||||
|
||||
type A = struct {
|
||||
F string
|
||||
G int
|
||||
}
|
||||
|
||||
func Make[T ~A]() T {
|
||||
return T{
|
||||
F: "blah",
|
||||
G: 1234,
|
||||
}
|
||||
}
|
||||
|
||||
type N struct {
|
||||
F string
|
||||
G int
|
||||
}
|
||||
|
||||
func _() {
|
||||
_ = Make[N]()
|
||||
}
|
@ -132,15 +132,18 @@ func ReadDir(name string) ([]DirEntry, error) {
|
||||
// CopyFS copies the file system fsys into the directory dir,
|
||||
// creating dir if necessary.
|
||||
//
|
||||
// Newly created directories and files have their default modes
|
||||
// where any bits from the file in fsys that are not part of the
|
||||
// standard read, write, and execute permissions will be zeroed
|
||||
// out, and standard read and write permissions are set for owner,
|
||||
// group, and others while retaining any existing execute bits from
|
||||
// the file in fsys.
|
||||
// Files are created with mode 0o666 plus any execute permissions
|
||||
// from the source, and directories are created with mode 0o777
|
||||
// (before umask).
|
||||
//
|
||||
// Symbolic links in fsys are not supported, a *PathError with Err set
|
||||
// to ErrInvalid is returned on symlink.
|
||||
// CopyFS will not overwrite existing files. If a file name in fsys
|
||||
// already exists in the destination, CopyFS will return an error
|
||||
// such that errors.Is(err, fs.ErrExist) will be true.
|
||||
//
|
||||
// Symbolic links in fsys are not supported. A *PathError with Err set
|
||||
// to ErrInvalid is returned when copying from a symbolic link.
|
||||
//
|
||||
// Symbolic links in dir are followed.
|
||||
//
|
||||
// Copying stops at and returns the first error encountered.
|
||||
func CopyFS(dir string, fsys fs.FS) error {
|
||||
@ -174,7 +177,7 @@ func CopyFS(dir string, fsys fs.FS) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w, err := OpenFile(newPath, O_CREATE|O_TRUNC|O_WRONLY, 0666|info.Mode()&0777)
|
||||
w, err := OpenFile(newPath, O_CREATE|O_EXCL|O_WRONLY, 0666|info.Mode()&0777)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -61,7 +61,7 @@ func ExampleFileMode() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Printf("permissions: %#o\n", fi.Mode().Perm()) // 0400, 0777, etc.
|
||||
fmt.Printf("permissions: %#o\n", fi.Mode().Perm()) // 0o400, 0o777, etc.
|
||||
switch mode := fi.Mode(); {
|
||||
case mode.IsRegular():
|
||||
fmt.Println("regular file")
|
||||
|
@ -366,7 +366,7 @@ func Open(name string) (*File, error) {
|
||||
}
|
||||
|
||||
// Create creates or truncates the named file. If the file already exists,
|
||||
// it is truncated. If the file does not exist, it is created with mode 0666
|
||||
// it is truncated. If the file does not exist, it is created with mode 0o666
|
||||
// (before umask). If successful, methods on the returned File can
|
||||
// be used for I/O; the associated file descriptor has mode O_RDWR.
|
||||
// If there is an error, it will be of type *PathError.
|
||||
@ -602,11 +602,11 @@ func UserHomeDir() (string, error) {
|
||||
// On Unix, the mode's permission bits, ModeSetuid, ModeSetgid, and
|
||||
// ModeSticky are used.
|
||||
//
|
||||
// On Windows, only the 0200 bit (owner writable) of mode is used; it
|
||||
// On Windows, only the 0o200 bit (owner writable) of mode is used; it
|
||||
// controls whether the file's read-only attribute is set or cleared.
|
||||
// The other bits are currently unused. For compatibility with Go 1.12
|
||||
// and earlier, use a non-zero mode. Use mode 0400 for a read-only
|
||||
// file and 0600 for a readable+writable file.
|
||||
// and earlier, use a non-zero mode. Use mode 0o400 for a read-only
|
||||
// file and 0o600 for a readable+writable file.
|
||||
//
|
||||
// On Plan 9, the mode's permission bits, ModeAppend, ModeExclusive,
|
||||
// and ModeTemporary are used.
|
||||
|
@ -1376,8 +1376,7 @@ func TestChtimes(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
f := newFile(t)
|
||||
|
||||
f.Write([]byte("hello, world\n"))
|
||||
// This should be an empty file (see #68687, #68663).
|
||||
f.Close()
|
||||
|
||||
testChtimes(t, f.Name())
|
||||
@ -1395,12 +1394,9 @@ func TestChtimesOmit(t *testing.T) {
|
||||
func testChtimesOmit(t *testing.T, omitAt, omitMt bool) {
|
||||
t.Logf("omit atime: %v, mtime: %v", omitAt, omitMt)
|
||||
file := newFile(t)
|
||||
_, err := file.Write([]byte("hello, world\n"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
// This should be an empty file (see #68687, #68663).
|
||||
name := file.Name()
|
||||
err = file.Close()
|
||||
err := file.Close()
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
@ -3358,6 +3354,14 @@ func TestCopyFS(t *testing.T) {
|
||||
t.Fatal("comparing two directories:", err)
|
||||
}
|
||||
|
||||
// Test whether CopyFS disallows copying for disk filesystem when there is any
|
||||
// existing file in the destination directory.
|
||||
if err := CopyFS(tmpDir, fsys); !errors.Is(err, fs.ErrExist) {
|
||||
t.Errorf("CopyFS should have failed and returned error when there is"+
|
||||
"any existing file in the destination directory (in disk filesystem), "+
|
||||
"got: %v, expected any error that indicates <file exists>", err)
|
||||
}
|
||||
|
||||
// Test with memory filesystem.
|
||||
fsys = fstest.MapFS{
|
||||
"william": {Data: []byte("Shakespeare\n")},
|
||||
@ -3395,6 +3399,14 @@ func TestCopyFS(t *testing.T) {
|
||||
}); err != nil {
|
||||
t.Fatal("comparing two directories:", err)
|
||||
}
|
||||
|
||||
// Test whether CopyFS disallows copying for memory filesystem when there is any
|
||||
// existing file in the destination directory.
|
||||
if err := CopyFS(tmpDir, fsys); !errors.Is(err, fs.ErrExist) {
|
||||
t.Errorf("CopyFS should have failed and returned error when there is"+
|
||||
"any existing file in the destination directory (in memory filesystem), "+
|
||||
"got: %v, expected any error that indicates <file exists>", err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyFSWithSymlinks(t *testing.T) {
|
||||
|
@ -338,9 +338,14 @@ func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) {
|
||||
// stack. However, since we're returning to an earlier stack frame and
|
||||
// need to pair with the entersyscall() call made by cgocall, we must
|
||||
// save syscall* and let reentersyscall restore them.
|
||||
//
|
||||
// Note: savedsp and savedbp MUST be held in locals as an unsafe.Pointer.
|
||||
// When we call into Go, the stack is free to be moved. If these locals
|
||||
// aren't visible in the stack maps, they won't get updated properly,
|
||||
// and will end up being stale when restored by reentersyscall.
|
||||
savedsp := unsafe.Pointer(gp.syscallsp)
|
||||
savedpc := gp.syscallpc
|
||||
savedbp := gp.syscallbp
|
||||
savedbp := unsafe.Pointer(gp.syscallbp)
|
||||
exitsyscall() // coming out of cgo call
|
||||
gp.m.incgo = false
|
||||
if gp.m.isextra {
|
||||
@ -372,7 +377,7 @@ func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) {
|
||||
osPreemptExtEnter(gp.m)
|
||||
|
||||
// going back to cgo call
|
||||
reentersyscall(savedpc, uintptr(savedsp), savedbp)
|
||||
reentersyscall(savedpc, uintptr(savedsp), uintptr(savedbp))
|
||||
|
||||
gp.m.winsyscall = winsyscall
|
||||
}
|
||||
|
@ -4415,7 +4415,13 @@ func reentersyscall(pc, sp, bp uintptr) {
|
||||
}
|
||||
if gp.syscallsp < gp.stack.lo || gp.stack.hi < gp.syscallsp {
|
||||
systemstack(func() {
|
||||
print("entersyscall inconsistent ", hex(gp.syscallsp), " [", hex(gp.stack.lo), ",", hex(gp.stack.hi), "]\n")
|
||||
print("entersyscall inconsistent sp ", hex(gp.syscallsp), " [", hex(gp.stack.lo), ",", hex(gp.stack.hi), "]\n")
|
||||
throw("entersyscall")
|
||||
})
|
||||
}
|
||||
if gp.syscallbp != 0 && gp.syscallbp < gp.stack.lo || gp.stack.hi < gp.syscallbp {
|
||||
systemstack(func() {
|
||||
print("entersyscall inconsistent bp ", hex(gp.syscallbp), " [", hex(gp.stack.lo), ",", hex(gp.stack.hi), "]\n")
|
||||
throw("entersyscall")
|
||||
})
|
||||
}
|
||||
@ -4553,14 +4559,20 @@ func entersyscallblock() {
|
||||
sp2 := gp.sched.sp
|
||||
sp3 := gp.syscallsp
|
||||
systemstack(func() {
|
||||
print("entersyscallblock inconsistent ", hex(sp1), " ", hex(sp2), " ", hex(sp3), " [", hex(gp.stack.lo), ",", hex(gp.stack.hi), "]\n")
|
||||
print("entersyscallblock inconsistent sp ", hex(sp1), " ", hex(sp2), " ", hex(sp3), " [", hex(gp.stack.lo), ",", hex(gp.stack.hi), "]\n")
|
||||
throw("entersyscallblock")
|
||||
})
|
||||
}
|
||||
casgstatus(gp, _Grunning, _Gsyscall)
|
||||
if gp.syscallsp < gp.stack.lo || gp.stack.hi < gp.syscallsp {
|
||||
systemstack(func() {
|
||||
print("entersyscallblock inconsistent ", hex(sp), " ", hex(gp.sched.sp), " ", hex(gp.syscallsp), " [", hex(gp.stack.lo), ",", hex(gp.stack.hi), "]\n")
|
||||
print("entersyscallblock inconsistent sp ", hex(sp), " ", hex(gp.sched.sp), " ", hex(gp.syscallsp), " [", hex(gp.stack.lo), ",", hex(gp.stack.hi), "]\n")
|
||||
throw("entersyscallblock")
|
||||
})
|
||||
}
|
||||
if gp.syscallbp != 0 && gp.syscallbp < gp.stack.lo || gp.stack.hi < gp.syscallbp {
|
||||
systemstack(func() {
|
||||
print("entersyscallblock inconsistent bp ", hex(bp), " ", hex(gp.sched.bp), " ", hex(gp.syscallbp), " [", hex(gp.stack.lo), ",", hex(gp.stack.hi), "]\n")
|
||||
throw("entersyscallblock")
|
||||
})
|
||||
}
|
||||
|
@ -41,6 +41,8 @@ TEXT _main(SB),NOSPLIT,$-8
|
||||
MOVD R12, CTR
|
||||
BR (CTR)
|
||||
|
||||
// Paramater save space required to cross-call into _cgo_sys_thread_create
|
||||
#define PARAM_SPACE 16
|
||||
|
||||
TEXT _rt0_ppc64_aix_lib(SB),NOSPLIT,$-8
|
||||
// Start with standard C stack frame layout and linkage.
|
||||
@ -49,45 +51,45 @@ TEXT _rt0_ppc64_aix_lib(SB),NOSPLIT,$-8
|
||||
MOVW CR, R0 // Save CR in caller's frame
|
||||
MOVD R0, 8(R1)
|
||||
|
||||
MOVDU R1, -344(R1) // Allocate frame.
|
||||
MOVDU R1, -344-PARAM_SPACE(R1) // Allocate frame.
|
||||
|
||||
// Preserve callee-save registers.
|
||||
MOVD R14, 48(R1)
|
||||
MOVD R15, 56(R1)
|
||||
MOVD R16, 64(R1)
|
||||
MOVD R17, 72(R1)
|
||||
MOVD R18, 80(R1)
|
||||
MOVD R19, 88(R1)
|
||||
MOVD R20, 96(R1)
|
||||
MOVD R21,104(R1)
|
||||
MOVD R22, 112(R1)
|
||||
MOVD R23, 120(R1)
|
||||
MOVD R24, 128(R1)
|
||||
MOVD R25, 136(R1)
|
||||
MOVD R26, 144(R1)
|
||||
MOVD R27, 152(R1)
|
||||
MOVD R28, 160(R1)
|
||||
MOVD R29, 168(R1)
|
||||
MOVD g, 176(R1) // R30
|
||||
MOVD R31, 184(R1)
|
||||
FMOVD F14, 192(R1)
|
||||
FMOVD F15, 200(R1)
|
||||
FMOVD F16, 208(R1)
|
||||
FMOVD F17, 216(R1)
|
||||
FMOVD F18, 224(R1)
|
||||
FMOVD F19, 232(R1)
|
||||
FMOVD F20, 240(R1)
|
||||
FMOVD F21, 248(R1)
|
||||
FMOVD F22, 256(R1)
|
||||
FMOVD F23, 264(R1)
|
||||
FMOVD F24, 272(R1)
|
||||
FMOVD F25, 280(R1)
|
||||
FMOVD F26, 288(R1)
|
||||
FMOVD F27, 296(R1)
|
||||
FMOVD F28, 304(R1)
|
||||
FMOVD F29, 312(R1)
|
||||
FMOVD F30, 320(R1)
|
||||
FMOVD F31, 328(R1)
|
||||
MOVD R14, 48+PARAM_SPACE(R1)
|
||||
MOVD R15, 56+PARAM_SPACE(R1)
|
||||
MOVD R16, 64+PARAM_SPACE(R1)
|
||||
MOVD R17, 72+PARAM_SPACE(R1)
|
||||
MOVD R18, 80+PARAM_SPACE(R1)
|
||||
MOVD R19, 88+PARAM_SPACE(R1)
|
||||
MOVD R20, 96+PARAM_SPACE(R1)
|
||||
MOVD R21,104+PARAM_SPACE(R1)
|
||||
MOVD R22, 112+PARAM_SPACE(R1)
|
||||
MOVD R23, 120+PARAM_SPACE(R1)
|
||||
MOVD R24, 128+PARAM_SPACE(R1)
|
||||
MOVD R25, 136+PARAM_SPACE(R1)
|
||||
MOVD R26, 144+PARAM_SPACE(R1)
|
||||
MOVD R27, 152+PARAM_SPACE(R1)
|
||||
MOVD R28, 160+PARAM_SPACE(R1)
|
||||
MOVD R29, 168+PARAM_SPACE(R1)
|
||||
MOVD g, 176+PARAM_SPACE(R1) // R30
|
||||
MOVD R31, 184+PARAM_SPACE(R1)
|
||||
FMOVD F14, 192+PARAM_SPACE(R1)
|
||||
FMOVD F15, 200+PARAM_SPACE(R1)
|
||||
FMOVD F16, 208+PARAM_SPACE(R1)
|
||||
FMOVD F17, 216+PARAM_SPACE(R1)
|
||||
FMOVD F18, 224+PARAM_SPACE(R1)
|
||||
FMOVD F19, 232+PARAM_SPACE(R1)
|
||||
FMOVD F20, 240+PARAM_SPACE(R1)
|
||||
FMOVD F21, 248+PARAM_SPACE(R1)
|
||||
FMOVD F22, 256+PARAM_SPACE(R1)
|
||||
FMOVD F23, 264+PARAM_SPACE(R1)
|
||||
FMOVD F24, 272+PARAM_SPACE(R1)
|
||||
FMOVD F25, 280+PARAM_SPACE(R1)
|
||||
FMOVD F26, 288+PARAM_SPACE(R1)
|
||||
FMOVD F27, 296+PARAM_SPACE(R1)
|
||||
FMOVD F28, 304+PARAM_SPACE(R1)
|
||||
FMOVD F29, 312+PARAM_SPACE(R1)
|
||||
FMOVD F30, 320+PARAM_SPACE(R1)
|
||||
FMOVD F31, 328+PARAM_SPACE(R1)
|
||||
|
||||
// Synchronous initialization.
|
||||
MOVD $runtime·reginit(SB), R12
|
||||
@ -130,44 +132,44 @@ nocgo:
|
||||
|
||||
done:
|
||||
// Restore saved registers.
|
||||
MOVD 48(R1), R14
|
||||
MOVD 56(R1), R15
|
||||
MOVD 64(R1), R16
|
||||
MOVD 72(R1), R17
|
||||
MOVD 80(R1), R18
|
||||
MOVD 88(R1), R19
|
||||
MOVD 96(R1), R20
|
||||
MOVD 104(R1), R21
|
||||
MOVD 112(R1), R22
|
||||
MOVD 120(R1), R23
|
||||
MOVD 128(R1), R24
|
||||
MOVD 136(R1), R25
|
||||
MOVD 144(R1), R26
|
||||
MOVD 152(R1), R27
|
||||
MOVD 160(R1), R28
|
||||
MOVD 168(R1), R29
|
||||
MOVD 176(R1), g // R30
|
||||
MOVD 184(R1), R31
|
||||
FMOVD 196(R1), F14
|
||||
FMOVD 200(R1), F15
|
||||
FMOVD 208(R1), F16
|
||||
FMOVD 216(R1), F17
|
||||
FMOVD 224(R1), F18
|
||||
FMOVD 232(R1), F19
|
||||
FMOVD 240(R1), F20
|
||||
FMOVD 248(R1), F21
|
||||
FMOVD 256(R1), F22
|
||||
FMOVD 264(R1), F23
|
||||
FMOVD 272(R1), F24
|
||||
FMOVD 280(R1), F25
|
||||
FMOVD 288(R1), F26
|
||||
FMOVD 296(R1), F27
|
||||
FMOVD 304(R1), F28
|
||||
FMOVD 312(R1), F29
|
||||
FMOVD 320(R1), F30
|
||||
FMOVD 328(R1), F31
|
||||
MOVD 48+PARAM_SPACE(R1), R14
|
||||
MOVD 56+PARAM_SPACE(R1), R15
|
||||
MOVD 64+PARAM_SPACE(R1), R16
|
||||
MOVD 72+PARAM_SPACE(R1), R17
|
||||
MOVD 80+PARAM_SPACE(R1), R18
|
||||
MOVD 88+PARAM_SPACE(R1), R19
|
||||
MOVD 96+PARAM_SPACE(R1), R20
|
||||
MOVD 104+PARAM_SPACE(R1), R21
|
||||
MOVD 112+PARAM_SPACE(R1), R22
|
||||
MOVD 120+PARAM_SPACE(R1), R23
|
||||
MOVD 128+PARAM_SPACE(R1), R24
|
||||
MOVD 136+PARAM_SPACE(R1), R25
|
||||
MOVD 144+PARAM_SPACE(R1), R26
|
||||
MOVD 152+PARAM_SPACE(R1), R27
|
||||
MOVD 160+PARAM_SPACE(R1), R28
|
||||
MOVD 168+PARAM_SPACE(R1), R29
|
||||
MOVD 176+PARAM_SPACE(R1), g // R30
|
||||
MOVD 184+PARAM_SPACE(R1), R31
|
||||
FMOVD 196+PARAM_SPACE(R1), F14
|
||||
FMOVD 200+PARAM_SPACE(R1), F15
|
||||
FMOVD 208+PARAM_SPACE(R1), F16
|
||||
FMOVD 216+PARAM_SPACE(R1), F17
|
||||
FMOVD 224+PARAM_SPACE(R1), F18
|
||||
FMOVD 232+PARAM_SPACE(R1), F19
|
||||
FMOVD 240+PARAM_SPACE(R1), F20
|
||||
FMOVD 248+PARAM_SPACE(R1), F21
|
||||
FMOVD 256+PARAM_SPACE(R1), F22
|
||||
FMOVD 264+PARAM_SPACE(R1), F23
|
||||
FMOVD 272+PARAM_SPACE(R1), F24
|
||||
FMOVD 280+PARAM_SPACE(R1), F25
|
||||
FMOVD 288+PARAM_SPACE(R1), F26
|
||||
FMOVD 296+PARAM_SPACE(R1), F27
|
||||
FMOVD 304+PARAM_SPACE(R1), F28
|
||||
FMOVD 312+PARAM_SPACE(R1), F29
|
||||
FMOVD 320+PARAM_SPACE(R1), F30
|
||||
FMOVD 328+PARAM_SPACE(R1), F31
|
||||
|
||||
ADD $344, R1
|
||||
ADD $344+PARAM_SPACE, R1
|
||||
|
||||
MOVD 8(R1), R0
|
||||
MOVFL R0, $0xff
|
||||
|
@ -27,7 +27,7 @@ func cSeq(stringOffsets ...uintptr) cloneSeq {
|
||||
|
||||
func testCloneSeq[T any](t *testing.T, want cloneSeq) {
|
||||
typName := reflect.TypeFor[T]().Name()
|
||||
typ := abi.TypeOf(*new(T))
|
||||
typ := abi.TypeFor[T]()
|
||||
t.Run(typName, func(t *testing.T) {
|
||||
got := makeCloneSeq(typ)
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
|
@ -31,7 +31,7 @@ func (h Handle[T]) Value() T {
|
||||
// are equal if and only if the values used to produce them are equal.
|
||||
func Make[T comparable](value T) Handle[T] {
|
||||
// Find the map for type T.
|
||||
typ := abi.TypeOf(value)
|
||||
typ := abi.TypeFor[T]()
|
||||
ma, ok := uniqueMaps.Load(typ)
|
||||
if !ok {
|
||||
// This is a good time to initialize cleanup, since we must go through
|
||||
|
@ -41,6 +41,7 @@ func TestHandle(t *testing.T) {
|
||||
s: [2]testStringStruct{testStringStruct{"y"}, testStringStruct{"z"}},
|
||||
})
|
||||
testHandle[testStruct](t, testStruct{0.5, "184"})
|
||||
testHandle[testEface](t, testEface("hello"))
|
||||
}
|
||||
|
||||
func testHandle[T comparable](t *testing.T, value T) {
|
||||
@ -93,7 +94,7 @@ func drainMaps(t *testing.T) {
|
||||
|
||||
func checkMapsFor[T comparable](t *testing.T, value T) {
|
||||
// Manually load the value out of the map.
|
||||
typ := abi.TypeOf(value)
|
||||
typ := abi.TypeFor[T]()
|
||||
a, ok := uniqueMaps.Load(typ)
|
||||
if !ok {
|
||||
return
|
||||
|
@ -1,16 +1,20 @@
|
||||
// errorcheck -lang=go1.21
|
||||
// errorcheck -lang=go1.22
|
||||
|
||||
// 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.
|
||||
|
||||
//go:build go1.4
|
||||
// This file has been changed from its original version as
|
||||
// //go:build file versions below 1.21 set the language version to 1.21.
|
||||
// The original tested a -lang version of 1.21 with a file version of
|
||||
// go1.4 while this new version tests a -lang version of go1.22
|
||||
// with a file version of go1.21.
|
||||
|
||||
//go:build go1.21
|
||||
|
||||
package p
|
||||
|
||||
const c = 0o123 // ERROR "file declares //go:build go1.4"
|
||||
|
||||
// ERROR "file declares //go:build go1.4"
|
||||
|
||||
//line issue63489a.go:13:1
|
||||
const d = 0o124
|
||||
func f() {
|
||||
for _ = range 10 { // ERROR "file declares //go:build go1.21"
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,20 @@
|
||||
// errorcheck -lang=go1.4
|
||||
// errorcheck -lang=go1.21
|
||||
|
||||
// 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.
|
||||
|
||||
//go:build go1.4
|
||||
// This file has been changed from its original version as
|
||||
// //go:build file versions below 1.21 set the language version to 1.21.
|
||||
// The original tested a -lang version of 1.4 with a file version of
|
||||
// go1.4 while this new version tests a -lang version of go1.1
|
||||
// with a file version of go1.21.
|
||||
|
||||
//go:build go1.21
|
||||
|
||||
package p
|
||||
|
||||
const c = 0o123 // ERROR "file declares //go:build go1.4"
|
||||
func f() {
|
||||
for _ = range 10 { // ERROR "file declares //go:build go1.21"
|
||||
}
|
||||
}
|
||||
|
15
test/fixedbugs/issue68580.go
Normal file
15
test/fixedbugs/issue68580.go
Normal file
@ -0,0 +1,15 @@
|
||||
// compile -goexperiment aliastypeparams
|
||||
|
||||
// Copyright 2024 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 main
|
||||
|
||||
type A[P any] = struct{ _ P }
|
||||
|
||||
type N[P any] A[P]
|
||||
|
||||
func f[P any](N[P]) {}
|
||||
|
||||
var _ = f[int]
|
Loading…
x
Reference in New Issue
Block a user