mirror of
https://github.com/golang/go.git
synced 2025-05-08 00:53:07 +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/syntax"
|
||||||
"cmd/compile/internal/types2"
|
"cmd/compile/internal/types2"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
|
"internal/buildcfg"
|
||||||
"internal/pkgbits"
|
"internal/pkgbits"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -411,6 +412,14 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types2.Package, string) {
|
|||||||
panic("weird")
|
panic("weird")
|
||||||
|
|
||||||
case pkgbits.ObjAlias:
|
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()
|
pos := r.pos()
|
||||||
typ := r.typ()
|
typ := r.typ()
|
||||||
return newAliasTypeName(pr.enableAlias, pos, objPkg, objName, 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
|
// newAliasInstance creates a new alias instance for the given origin and type
|
||||||
// arguments, recording pos as the position of its synthetic object (for error
|
// arguments, recording pos as the position of its synthetic object (for error
|
||||||
// reporting).
|
// 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)
|
assert(len(targs) > 0)
|
||||||
obj := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
|
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 := check.newAlias(obj, rhs)
|
||||||
res.orig = orig
|
res.orig = orig
|
||||||
res.tparams = orig.tparams
|
res.tparams = orig.tparams
|
||||||
|
@ -2898,22 +2898,48 @@ func TestFileVersions(t *testing.T) {
|
|||||||
fileVersion string
|
fileVersion string
|
||||||
wantVersion string
|
wantVersion string
|
||||||
}{
|
}{
|
||||||
{"", "", ""}, // no versions specified
|
{"", "", ""}, // no versions specified
|
||||||
{"go1.19", "", "go1.19"}, // module version specified
|
{"go1.19", "", "go1.19"}, // module version specified
|
||||||
{"", "go1.20", ""}, // file upgrade ignored
|
{"", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||||
{"go1.19", "go1.20", "go1.20"}, // file upgrade permitted
|
{"go1", "", "go1"}, // no file version specified
|
||||||
{"go1.20", "go1.19", "go1.20"}, // file downgrade not permitted
|
{"go1", "goo1.22", "go1"}, // invalid file version specified
|
||||||
{"go1.21", "go1.19", "go1.19"}, // file downgrade permitted (module version is >= go1.21)
|
{"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
|
// versions containing release numbers
|
||||||
// (file versions containing release numbers are considered invalid)
|
// (file versions containing release numbers are considered invalid)
|
||||||
{"go1.19.0", "", "go1.19.0"}, // no file version specified
|
{"go1.19.0", "", "go1.19.0"}, // no file version specified
|
||||||
{"go1.20", "go1.20.1", "go1.20"}, // file upgrade ignored
|
{"go1.20.1", "go1.19.1", "go1.20.1"}, // invalid file version
|
||||||
{"go1.20.1", "go1.20", "go1.20.1"}, // file upgrade ignored
|
{"go1.20.1", "go1.21.1", "go1.20.1"}, // invalid file version
|
||||||
{"go1.20.1", "go1.21", "go1.21"}, // file upgrade permitted
|
{"go1.21.1", "go1.19.1", "go1.21.1"}, // invalid file version
|
||||||
{"go1.20.1", "go1.19", "go1.20.1"}, // file downgrade not permitted
|
{"go1.21.1", "go1.21.1", "go1.21.1"}, // invalid file version
|
||||||
{"go1.21.1", "go1.19.1", "go1.21.1"}, // file downgrade not permitted (invalid file version)
|
{"go1.22.1", "go1.19.1", "go1.22.1"}, // invalid file version
|
||||||
{"go1.21.1", "go1.19", "go1.19"}, // file downgrade permitted (module version is >= go1.21)
|
{"go1.22.1", "go1.21.1", "go1.22.1"}, // invalid file version
|
||||||
} {
|
} {
|
||||||
var src string
|
var src string
|
||||||
if test.fileVersion != "" {
|
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.errorf(files[0], TooNew, "package requires newer Go version %v (application built with %v)",
|
||||||
check.version, go_current)
|
check.version, go_current)
|
||||||
}
|
}
|
||||||
downgradeOk := check.version.cmp(go1_21) >= 0
|
|
||||||
|
|
||||||
// determine Go version for each file
|
// determine Go version for each file
|
||||||
for _, file := range check.files {
|
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.)
|
// unlike file versions which are Go language versions only, if valid.)
|
||||||
v := check.conf.GoVersion
|
v := check.conf.GoVersion
|
||||||
|
|
||||||
fileVersion := asGoVersion(file.GoVersion)
|
// If the file specifies a version, use max(fileVersion, go1.21).
|
||||||
if fileVersion.isValid() {
|
if fileVersion := asGoVersion(file.GoVersion); fileVersion.isValid() {
|
||||||
// use the file version, if applicable
|
// Go 1.21 introduced the feature of allowing //go:build lines
|
||||||
// (file versions are either the empty string or of the form go1.dd)
|
// to sometimes set the Go version in a given file. Versions Go 1.21 and later
|
||||||
if pkgVersionOk {
|
// can be set backwards compatibly as that was the first version
|
||||||
cmp := fileVersion.cmp(check.version)
|
// files with go1.21 or later build tags could be built with.
|
||||||
// Go 1.21 introduced the feature of setting the go.mod
|
//
|
||||||
// go line to an early version of Go and allowing //go:build lines
|
// Set the version to max(fileVersion, go1.21): That will allow a
|
||||||
// to “upgrade” (cmp > 0) the Go version in a given file.
|
// downgrade to a version before go1.22, where the for loop semantics
|
||||||
// We can do that backwards compatibly.
|
// change was made, while being backwards compatible with versions of
|
||||||
//
|
// go before the new //go:build semantics were introduced.
|
||||||
// Go 1.21 also introduced the feature of allowing //go:build lines
|
v = string(versionMax(fileVersion, go1_21))
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report a specific error for each tagged file that's too new.
|
// Report a specific error for each tagged file that's too new.
|
||||||
// (Normally the build system will have filtered files by version,
|
// (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.
|
// A bailout panic is used for early termination.
|
||||||
type bailout struct{}
|
type bailout struct{}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@ import (
|
|||||||
"cmd/compile/internal/syntax"
|
"cmd/compile/internal/syntax"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"internal/buildcfg"
|
||||||
. "internal/types/errors"
|
. "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
|
res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
|
||||||
|
|
||||||
case *Alias:
|
case *Alias:
|
||||||
// TODO(gri) is this correct?
|
if !buildcfg.Experiment.AliasTypeParams {
|
||||||
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
||||||
|
}
|
||||||
|
|
||||||
tparams := orig.TypeParams()
|
tparams := orig.TypeParams()
|
||||||
// TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
|
// 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 orig // nothing to do (minor optimization)
|
||||||
}
|
}
|
||||||
|
|
||||||
return check.newAliasInstance(pos, orig, targs, ctxt)
|
return check.newAliasInstance(pos, orig, targs, expanding, ctxt)
|
||||||
|
|
||||||
case *Signature:
|
case *Signature:
|
||||||
assert(expanding == nil) // function instances cannot be reached from Named types
|
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)
|
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 {
|
if t.TypeArgs().Len() == 0 {
|
||||||
panic("nil underlying")
|
panic("nil underlying")
|
||||||
}
|
}
|
||||||
case *Named:
|
case *Named, *Alias:
|
||||||
t.under() // t.under may add entries to check.cleaners
|
t.under() // t.under may add entries to check.cleaners
|
||||||
}
|
}
|
||||||
t.check = nil
|
t.check = nil
|
||||||
|
@ -115,7 +115,7 @@ func (subst *subster) typ(typ Type) Type {
|
|||||||
// that has a type argument for it.
|
// that has a type argument for it.
|
||||||
targs, updated := subst.typeList(t.TypeArgs().list())
|
targs, updated := subst.typeList(t.TypeArgs().list())
|
||||||
if updated {
|
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:
|
case *Array:
|
||||||
|
@ -131,8 +131,8 @@ func (s *_TypeSet) underIs(f func(Type) bool) bool {
|
|||||||
}
|
}
|
||||||
for _, t := range s.terms {
|
for _, t := range s.terms {
|
||||||
assert(t.typ != nil)
|
assert(t.typ != nil)
|
||||||
// x == under(x) for ~x terms
|
// Unalias(x) == under(x) for ~x terms
|
||||||
u := t.typ
|
u := Unalias(t.typ)
|
||||||
if !t.tilde {
|
if !t.tilde {
|
||||||
u = under(u)
|
u = under(u)
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ require (
|
|||||||
golang.org/x/mod v0.19.0
|
golang.org/x/mod v0.19.0
|
||||||
golang.org/x/sync v0.7.0
|
golang.org/x/sync v0.7.0
|
||||||
golang.org/x/sys v0.22.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/term v0.20.0
|
||||||
golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72
|
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/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 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
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-20240828213427-40b6b7fe7147 h1:Lj8KbuZmoFUbI6pQ28G3Diz/5bRYD2UY5vfAmhrLZWo=
|
||||||
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/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 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
|
||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
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"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"golang.org/x/telemetry/internal/telemetry"
|
"golang.org/x/telemetry/internal/telemetry"
|
||||||
)
|
)
|
||||||
@ -29,12 +30,22 @@ const (
|
|||||||
// creation flag.
|
// creation flag.
|
||||||
var needNoConsole = func(cmd *exec.Cmd) {}
|
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 fetches the requested telemetry UploadConfig using "go mod
|
||||||
// download". If envOverlay is provided, it is appended to the environment used
|
// download". If envOverlay is provided, it is appended to the environment used
|
||||||
// for invoking the go command.
|
// for invoking the go command.
|
||||||
//
|
//
|
||||||
// The second result is the canonical version of the requested configuration.
|
// The second result is the canonical version of the requested configuration.
|
||||||
func Download(version string, envOverlay []string) (*telemetry.UploadConfig, string, error) {
|
func Download(version string, envOverlay []string) (*telemetry.UploadConfig, string, error) {
|
||||||
|
atomic.AddInt64(&downloads, 1)
|
||||||
|
|
||||||
if version == "" {
|
if version == "" {
|
||||||
version = "latest"
|
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"
|
"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.
|
// TODO(adonovan): eliminate once go1.23+ is assured.
|
||||||
func Supported() bool { return setCrashOutput != nil }
|
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
|
// Parent sets up the parent side of the crashmonitor. It requires
|
||||||
// exclusive use of a writable pipe connected to the child process's stdin.
|
// 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)
|
logger := log.New(logWriter, "", log.Ltime|log.Lmicroseconds|log.Lshortfile)
|
||||||
|
|
||||||
// Fetch the upload config, if it is not provided.
|
// Fetch the upload config, if it is not provided.
|
||||||
config, configVersion, err := configstore.Download("latest", rcfg.Env)
|
var (
|
||||||
if err != nil {
|
config *telemetry.UploadConfig
|
||||||
return nil, err
|
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.
|
// 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())
|
fd, err := os.Stat(telemetry.Default.DebugDir())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if !os.IsNotExist(err) {
|
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() {
|
} else if fd.IsDir() {
|
||||||
// local/debug exists and is a directory. Set stderr to a log file path
|
// 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")
|
childLogPath := filepath.Join(telemetry.Default.DebugDir(), "sidecar.log")
|
||||||
childLog, err := os.OpenFile(childLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
|
childLog, err := os.OpenFile(childLogPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0600)
|
||||||
if err != nil {
|
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()
|
defer childLog.Close()
|
||||||
cmd.Stderr = childLog
|
cmd.Stderr = childLog
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var crashOutputFile *os.File
|
||||||
if reportCrashes {
|
if reportCrashes {
|
||||||
pipe, err := cmd.StdinPipe()
|
pipe, err := cmd.StdinPipe()
|
||||||
if err != nil {
|
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 {
|
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)
|
result.wg.Add(1)
|
||||||
go func() {
|
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/plan9
|
||||||
golang.org/x/sys/unix
|
golang.org/x/sys/unix
|
||||||
golang.org/x/sys/windows
|
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
|
## explicit; go 1.20
|
||||||
golang.org/x/telemetry
|
golang.org/x/telemetry
|
||||||
golang.org/x/telemetry/counter
|
golang.org/x/telemetry/counter
|
||||||
|
@ -491,9 +491,10 @@ func testHandshake(t *testing.T, clientConfig, serverConfig *Config) (serverStat
|
|||||||
if got := string(buf); got != sentinel {
|
if got := string(buf); got != sentinel {
|
||||||
t.Errorf("read %q from TLS connection, but expected %q", got, sentinel)
|
t.Errorf("read %q from TLS connection, but expected %q", got, sentinel)
|
||||||
}
|
}
|
||||||
if err := cli.Close(); err != nil {
|
// We discard the error because after ReadAll returns the server must
|
||||||
t.Errorf("failed to call cli.Close: %v", err)
|
// 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)
|
server := Server(s, serverConfig)
|
||||||
err = server.Handshake()
|
err = server.Handshake()
|
||||||
|
@ -1368,8 +1368,8 @@ func (db *DB) conn(ctx context.Context, strategy connReuseStrategy) (*driverConn
|
|||||||
|
|
||||||
db.waitDuration.Add(int64(time.Since(waitStart)))
|
db.waitDuration.Add(int64(time.Since(waitStart)))
|
||||||
|
|
||||||
// If we failed to delete it, that means something else
|
// If we failed to delete it, that means either the DB was closed or
|
||||||
// grabbed it and is about to send on it.
|
// something else grabbed it and is about to send on it.
|
||||||
if !deleted {
|
if !deleted {
|
||||||
// TODO(bradfitz): rather than this best effort select, we
|
// TODO(bradfitz): rather than this best effort select, we
|
||||||
// should probably start a goroutine to read from req. This best
|
// should probably start a goroutine to read from req. This best
|
||||||
@ -3594,6 +3594,7 @@ type connRequestAndIndex struct {
|
|||||||
// and clears the set.
|
// and clears the set.
|
||||||
func (s *connRequestSet) CloseAndRemoveAll() {
|
func (s *connRequestSet) CloseAndRemoveAll() {
|
||||||
for _, v := range s.s {
|
for _, v := range s.s {
|
||||||
|
*v.curIdx = -1
|
||||||
close(v.req)
|
close(v.req)
|
||||||
}
|
}
|
||||||
s.s = nil
|
s.s = nil
|
||||||
|
@ -4920,6 +4920,17 @@ func TestConnRequestSet(t *testing.T) {
|
|||||||
t.Error("wasn't random")
|
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) {
|
func BenchmarkConnRequestSet(b *testing.B) {
|
||||||
|
@ -911,8 +911,11 @@ func (dec *Decoder) decOpFor(wireId typeId, rt reflect.Type, name string, inProg
|
|||||||
var maxIgnoreNestingDepth = 10000
|
var maxIgnoreNestingDepth = 10000
|
||||||
|
|
||||||
// decIgnoreOpFor returns the decoding op for a field that has no destination.
|
// 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 {
|
func (dec *Decoder) decIgnoreOpFor(wireId typeId, inProgress map[typeId]*decOp) *decOp {
|
||||||
if depth > maxIgnoreNestingDepth {
|
// 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"))
|
error_(errors.New("invalid nesting depth"))
|
||||||
}
|
}
|
||||||
// If this type is already in progress, it's a recursive type (e.g. map[string]*T).
|
// 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())
|
errorf("bad data: undefined type %s", wireId.string())
|
||||||
case wire.ArrayT != nil:
|
case wire.ArrayT != nil:
|
||||||
elemId := wire.ArrayT.Elem
|
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) {
|
op = func(i *decInstr, state *decoderState, value reflect.Value) {
|
||||||
state.dec.ignoreArray(state, *elemOp, wire.ArrayT.Len)
|
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:
|
case wire.MapT != nil:
|
||||||
keyId := dec.wireType[wireId].MapT.Key
|
keyId := dec.wireType[wireId].MapT.Key
|
||||||
elemId := dec.wireType[wireId].MapT.Elem
|
elemId := dec.wireType[wireId].MapT.Elem
|
||||||
keyOp := dec.decIgnoreOpFor(keyId, inProgress, depth+1)
|
keyOp := dec.decIgnoreOpFor(keyId, inProgress)
|
||||||
elemOp := dec.decIgnoreOpFor(elemId, inProgress, depth+1)
|
elemOp := dec.decIgnoreOpFor(elemId, inProgress)
|
||||||
op = func(i *decInstr, state *decoderState, value reflect.Value) {
|
op = func(i *decInstr, state *decoderState, value reflect.Value) {
|
||||||
state.dec.ignoreMap(state, *keyOp, *elemOp)
|
state.dec.ignoreMap(state, *keyOp, *elemOp)
|
||||||
}
|
}
|
||||||
|
|
||||||
case wire.SliceT != nil:
|
case wire.SliceT != nil:
|
||||||
elemId := wire.SliceT.Elem
|
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) {
|
op = func(i *decInstr, state *decoderState, value reflect.Value) {
|
||||||
state.dec.ignoreSlice(state, *elemOp)
|
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 {
|
func (dec *Decoder) compileIgnoreSingle(remoteId typeId) *decEngine {
|
||||||
engine := new(decEngine)
|
engine := new(decEngine)
|
||||||
engine.instr = make([]decInstr, 1) // one item
|
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))
|
ovfl := overflow(dec.typeString(remoteId))
|
||||||
engine.instr[0] = decInstr{*op, 0, nil, ovfl}
|
engine.instr[0] = decInstr{*op, 0, nil, ovfl}
|
||||||
engine.numInstr = 1
|
engine.numInstr = 1
|
||||||
@ -1160,7 +1163,7 @@ func (dec *Decoder) compileDec(remoteId typeId, ut *userTypeInfo) (engine *decEn
|
|||||||
localField, present := srt.FieldByName(wireField.Name)
|
localField, present := srt.FieldByName(wireField.Name)
|
||||||
// TODO(r): anonymous names
|
// TODO(r): anonymous names
|
||||||
if !present || !isExported(wireField.Name) {
|
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}
|
engine.instr[fieldnum] = decInstr{*op, fieldnum, nil, ovfl}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,8 @@ type Decoder struct {
|
|||||||
freeList *decoderState // list of free decoderStates; avoids reallocation
|
freeList *decoderState // list of free decoderStates; avoids reallocation
|
||||||
countBuf []byte // used for decoding integers while parsing messages
|
countBuf []byte // used for decoding integers while parsing messages
|
||||||
err error
|
err error
|
||||||
|
// ignoreDepth tracks the depth of recursively parsed ignored fields
|
||||||
|
ignoreDepth int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDecoder returns a new decoder that reads from the [io.Reader].
|
// NewDecoder returns a new decoder that reads from the [io.Reader].
|
||||||
|
@ -806,6 +806,8 @@ func TestIgnoreDepthLimit(t *testing.T) {
|
|||||||
defer func() { maxIgnoreNestingDepth = oldNestingDepth }()
|
defer func() { maxIgnoreNestingDepth = oldNestingDepth }()
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
enc := NewEncoder(b)
|
enc := NewEncoder(b)
|
||||||
|
|
||||||
|
// Nested slice
|
||||||
typ := reflect.TypeFor[int]()
|
typ := reflect.TypeFor[int]()
|
||||||
nested := reflect.ArrayOf(1, typ)
|
nested := reflect.ArrayOf(1, typ)
|
||||||
for i := 0; i < 100; i++ {
|
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 {
|
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)
|
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"
|
"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.
|
// An Expr is a build tag constraint expression.
|
||||||
// The underlying concrete type is *[AndExpr], *[OrExpr], *[NotExpr], or *[TagExpr].
|
// The underlying concrete type is *[AndExpr], *[OrExpr], *[NotExpr], or *[TagExpr].
|
||||||
type Expr interface {
|
type Expr interface {
|
||||||
@ -151,7 +155,7 @@ func Parse(line string) (Expr, error) {
|
|||||||
return parseExpr(text)
|
return parseExpr(text)
|
||||||
}
|
}
|
||||||
if text, ok := splitPlusBuild(line); ok {
|
if text, ok := splitPlusBuild(line); ok {
|
||||||
return parsePlusBuildExpr(text), nil
|
return parsePlusBuildExpr(text)
|
||||||
}
|
}
|
||||||
return nil, errNotConstraint
|
return nil, errNotConstraint
|
||||||
}
|
}
|
||||||
@ -201,6 +205,8 @@ type exprParser struct {
|
|||||||
tok string // last token read
|
tok string // last token read
|
||||||
isTag bool
|
isTag bool
|
||||||
pos int // position (start) of last token
|
pos int // position (start) of last token
|
||||||
|
|
||||||
|
size int
|
||||||
}
|
}
|
||||||
|
|
||||||
// parseExpr parses a boolean build tag expression.
|
// 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 entry, the next input token has not yet been lexed.
|
||||||
// On exit, the next input token has been lexed and is in p.tok.
|
// On exit, the next input token has been lexed and is in p.tok.
|
||||||
func (p *exprParser) not() Expr {
|
func (p *exprParser) not() Expr {
|
||||||
|
p.size++
|
||||||
|
if p.size > maxSize {
|
||||||
|
panic(&SyntaxError{Offset: p.pos, Err: "build expression too large"})
|
||||||
|
}
|
||||||
p.lex()
|
p.lex()
|
||||||
if p.tok == "!" {
|
if p.tok == "!" {
|
||||||
p.lex()
|
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”).
|
// 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
|
var x Expr
|
||||||
for _, clause := range strings.Fields(text) {
|
for _, clause := range strings.Fields(text) {
|
||||||
var y Expr
|
var y Expr
|
||||||
@ -414,19 +430,25 @@ func parsePlusBuildExpr(text string) Expr {
|
|||||||
if y == nil {
|
if y == nil {
|
||||||
y = z
|
y = z
|
||||||
} else {
|
} else {
|
||||||
|
if size++; size > maxOldSize {
|
||||||
|
return nil, errComplex
|
||||||
|
}
|
||||||
y = and(y, z)
|
y = and(y, z)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if x == nil {
|
if x == nil {
|
||||||
x = y
|
x = y
|
||||||
} else {
|
} else {
|
||||||
|
if size++; size > maxOldSize {
|
||||||
|
return nil, errComplex
|
||||||
|
}
|
||||||
x = or(x, y)
|
x = or(x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if x == nil {
|
if x == nil {
|
||||||
x = tag("ignore")
|
x = tag("ignore")
|
||||||
}
|
}
|
||||||
return x
|
return x, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// isValidTag reports whether the word is a valid build tag.
|
// isValidTag reports whether the word is a valid build tag.
|
||||||
|
@ -222,7 +222,7 @@ var parsePlusBuildExprTests = []struct {
|
|||||||
func TestParsePlusBuildExpr(t *testing.T) {
|
func TestParsePlusBuildExpr(t *testing.T) {
|
||||||
for i, tt := range parsePlusBuildExprTests {
|
for i, tt := range parsePlusBuildExprTests {
|
||||||
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
t.Run(fmt.Sprint(i), func(t *testing.T) {
|
||||||
x := parsePlusBuildExpr(tt.in)
|
x, _ := parsePlusBuildExpr(tt.in)
|
||||||
if x.String() != tt.x.String() {
|
if x.String() != tt.x.String() {
|
||||||
t.Errorf("parsePlusBuildExpr(%q):\nhave %v\nwant %v", tt.in, x, tt.x)
|
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 {
|
func (p *parser) parseLiteralValue(typ ast.Expr) ast.Expr {
|
||||||
|
defer decNestLev(incNestLev(p))
|
||||||
|
|
||||||
if p.trace {
|
if p.trace {
|
||||||
defer un(trace(p, "LiteralValue"))
|
defer un(trace(p, "LiteralValue"))
|
||||||
}
|
}
|
||||||
|
@ -598,10 +598,11 @@ var parseDepthTests = []struct {
|
|||||||
{name: "chan2", format: "package main; var x «<-chan »int"},
|
{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: "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: "map", format: "package main; var x «map[int]»int"},
|
||||||
{name: "slicelit", format: "package main; var x = «[]any{«»}»", parseMultiplier: 2}, // Parser nodes: UnaryExpr, CompositeLit
|
{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: 2}, // 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: 2}, // 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: 2}, // Parser nodes: CompositeLit, KeyValueExpr
|
{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: "dot", format: "package main; var x = «x.»x"},
|
||||||
{name: "index", format: "package main; var x = x«[1]»"},
|
{name: "index", format: "package main; var x = x«[1]»"},
|
||||||
{name: "slice", format: "package main; var x = x«[1:2]»"},
|
{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
|
// newAliasInstance creates a new alias instance for the given origin and type
|
||||||
// arguments, recording pos as the position of its synthetic object (for error
|
// arguments, recording pos as the position of its synthetic object (for error
|
||||||
// reporting).
|
// 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)
|
assert(len(targs) > 0)
|
||||||
obj := NewTypeName(pos, orig.obj.pkg, orig.obj.name, nil)
|
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 := check.newAlias(obj, rhs)
|
||||||
res.orig = orig
|
res.orig = orig
|
||||||
res.tparams = orig.tparams
|
res.tparams = orig.tparams
|
||||||
|
@ -2904,22 +2904,48 @@ func TestFileVersions(t *testing.T) {
|
|||||||
fileVersion string
|
fileVersion string
|
||||||
wantVersion string
|
wantVersion string
|
||||||
}{
|
}{
|
||||||
{"", "", ""}, // no versions specified
|
{"", "", ""}, // no versions specified
|
||||||
{"go1.19", "", "go1.19"}, // module version specified
|
{"go1.19", "", "go1.19"}, // module version specified
|
||||||
{"", "go1.20", ""}, // file upgrade ignored
|
{"", "go1.20", "go1.21"}, // file version specified below minimum of 1.21
|
||||||
{"go1.19", "go1.20", "go1.20"}, // file upgrade permitted
|
{"go1", "", "go1"}, // no file version specified
|
||||||
{"go1.20", "go1.19", "go1.20"}, // file downgrade not permitted
|
{"go1", "goo1.22", "go1"}, // invalid file version specified
|
||||||
{"go1.21", "go1.19", "go1.19"}, // file downgrade permitted (module version is >= go1.21)
|
{"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
|
// versions containing release numbers
|
||||||
// (file versions containing release numbers are considered invalid)
|
// (file versions containing release numbers are considered invalid)
|
||||||
{"go1.19.0", "", "go1.19.0"}, // no file version specified
|
{"go1.19.0", "", "go1.19.0"}, // no file version specified
|
||||||
{"go1.20", "go1.20.1", "go1.20"}, // file upgrade ignored
|
{"go1.20.1", "go1.19.1", "go1.20.1"}, // invalid file version
|
||||||
{"go1.20.1", "go1.20", "go1.20.1"}, // file upgrade ignored
|
{"go1.20.1", "go1.21.1", "go1.20.1"}, // invalid file version
|
||||||
{"go1.20.1", "go1.21", "go1.21"}, // file upgrade permitted
|
{"go1.21.1", "go1.19.1", "go1.21.1"}, // invalid file version
|
||||||
{"go1.20.1", "go1.19", "go1.20.1"}, // file downgrade not permitted
|
{"go1.21.1", "go1.21.1", "go1.21.1"}, // invalid file version
|
||||||
{"go1.21.1", "go1.19.1", "go1.21.1"}, // file downgrade not permitted (invalid file version)
|
{"go1.22.1", "go1.19.1", "go1.22.1"}, // invalid file version
|
||||||
{"go1.21.1", "go1.19", "go1.19"}, // file downgrade permitted (module version is >= go1.21)
|
{"go1.22.1", "go1.21.1", "go1.22.1"}, // invalid file version
|
||||||
} {
|
} {
|
||||||
var src string
|
var src string
|
||||||
if test.fileVersion != "" {
|
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.errorf(files[0], TooNew, "package requires newer Go version %v (application built with %v)",
|
||||||
check.version, go_current)
|
check.version, go_current)
|
||||||
}
|
}
|
||||||
downgradeOk := check.version.cmp(go1_21) >= 0
|
|
||||||
|
|
||||||
// determine Go version for each file
|
// determine Go version for each file
|
||||||
for _, file := range check.files {
|
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.)
|
// unlike file versions which are Go language versions only, if valid.)
|
||||||
v := check.conf.GoVersion
|
v := check.conf.GoVersion
|
||||||
|
|
||||||
fileVersion := asGoVersion(file.GoVersion)
|
// If the file specifies a version, use max(fileVersion, go1.21).
|
||||||
if fileVersion.isValid() {
|
if fileVersion := asGoVersion(file.GoVersion); fileVersion.isValid() {
|
||||||
// use the file version, if applicable
|
// Go 1.21 introduced the feature of setting the go.mod
|
||||||
// (file versions are either the empty string or of the form go1.dd)
|
// go line to an early version of Go and allowing //go:build lines
|
||||||
if pkgVersionOk {
|
// to set the Go version in a given file. Versions Go 1.21 and later
|
||||||
cmp := fileVersion.cmp(check.version)
|
// can be set backwards compatibly as that was the first version
|
||||||
// Go 1.21 introduced the feature of setting the go.mod
|
// files with go1.21 or later build tags could be built with.
|
||||||
// go line to an early version of Go and allowing //go:build lines
|
//
|
||||||
// to “upgrade” (cmp > 0) the Go version in a given file.
|
// Set the version to max(fileVersion, go1.21): That will allow a
|
||||||
// We can do that backwards compatibly.
|
// downgrade to a version before go1.22, where the for loop semantics
|
||||||
//
|
// change was made, while being backwards compatible with versions of
|
||||||
// Go 1.21 also introduced the feature of allowing //go:build lines
|
// go before the new //go:build semantics were introduced.
|
||||||
// to “downgrade” (cmp < 0) the Go version in a given file.
|
v = string(versionMax(fileVersion, go1_21))
|
||||||
// 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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Report a specific error for each tagged file that's too new.
|
// Report a specific error for each tagged file that's too new.
|
||||||
// (Normally the build system will have filtered files by version,
|
// (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.
|
// A bailout panic is used for early termination.
|
||||||
type bailout struct{}
|
type bailout struct{}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"internal/buildcfg"
|
||||||
. "internal/types/errors"
|
. "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
|
res = check.newNamedInstance(pos, orig, targs, expanding) // substituted lazily
|
||||||
|
|
||||||
case *Alias:
|
case *Alias:
|
||||||
// TODO(gri) is this correct?
|
if !buildcfg.Experiment.AliasTypeParams {
|
||||||
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
assert(expanding == nil) // Alias instances cannot be reached from Named types
|
||||||
|
}
|
||||||
|
|
||||||
tparams := orig.TypeParams()
|
tparams := orig.TypeParams()
|
||||||
// TODO(gri) investigate if this is needed (type argument and parameter count seem to be correct here)
|
// 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 orig // nothing to do (minor optimization)
|
||||||
}
|
}
|
||||||
|
|
||||||
return check.newAliasInstance(pos, orig, targs, ctxt)
|
return check.newAliasInstance(pos, orig, targs, expanding, ctxt)
|
||||||
|
|
||||||
case *Signature:
|
case *Signature:
|
||||||
assert(expanding == nil) // function instances cannot be reached from Named types
|
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)
|
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 {
|
if t.TypeArgs().Len() == 0 {
|
||||||
panic("nil underlying")
|
panic("nil underlying")
|
||||||
}
|
}
|
||||||
case *Named:
|
case *Named, *Alias:
|
||||||
t.under() // t.under may add entries to check.cleaners
|
t.under() // t.under may add entries to check.cleaners
|
||||||
}
|
}
|
||||||
t.check = nil
|
t.check = nil
|
||||||
|
@ -118,7 +118,7 @@ func (subst *subster) typ(typ Type) Type {
|
|||||||
// that has a type argument for it.
|
// that has a type argument for it.
|
||||||
targs, updated := subst.typeList(t.TypeArgs().list())
|
targs, updated := subst.typeList(t.TypeArgs().list())
|
||||||
if updated {
|
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:
|
case *Array:
|
||||||
|
@ -134,8 +134,8 @@ func (s *_TypeSet) underIs(f func(Type) bool) bool {
|
|||||||
}
|
}
|
||||||
for _, t := range s.terms {
|
for _, t := range s.terms {
|
||||||
assert(t.typ != nil)
|
assert(t.typ != nil)
|
||||||
// x == under(x) for ~x terms
|
// Unalias(x) == under(x) for ~x terms
|
||||||
u := t.typ
|
u := Unalias(t.typ)
|
||||||
if !t.tilde {
|
if !t.tilde {
|
||||||
u = under(u)
|
u = under(u)
|
||||||
}
|
}
|
||||||
|
@ -177,6 +177,15 @@ func TypeOf(a any) *Type {
|
|||||||
return (*Type)(NoEscape(unsafe.Pointer(eface.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) Kind() Kind { return t.Kind_ & KindMask }
|
||||||
|
|
||||||
func (t *Type) HasName() bool {
|
func (t *Type) HasName() bool {
|
||||||
|
@ -14,4 +14,4 @@ type Slice []byte
|
|||||||
type Array [8]byte
|
type Array [8]byte
|
||||||
|
|
||||||
var s Slice
|
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
|
type Array [8]byte
|
||||||
|
|
||||||
var s Slice
|
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.
|
// Copyright 2024 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// 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
|
package p
|
||||||
|
|
||||||
import "io"
|
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,
|
// CopyFS copies the file system fsys into the directory dir,
|
||||||
// creating dir if necessary.
|
// creating dir if necessary.
|
||||||
//
|
//
|
||||||
// Newly created directories and files have their default modes
|
// Files are created with mode 0o666 plus any execute permissions
|
||||||
// where any bits from the file in fsys that are not part of the
|
// from the source, and directories are created with mode 0o777
|
||||||
// standard read, write, and execute permissions will be zeroed
|
// (before umask).
|
||||||
// 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.
|
|
||||||
//
|
//
|
||||||
// Symbolic links in fsys are not supported, a *PathError with Err set
|
// CopyFS will not overwrite existing files. If a file name in fsys
|
||||||
// to ErrInvalid is returned on symlink.
|
// 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.
|
// Copying stops at and returns the first error encountered.
|
||||||
func CopyFS(dir string, fsys fs.FS) error {
|
func CopyFS(dir string, fsys fs.FS) error {
|
||||||
@ -174,7 +177,7 @@ func CopyFS(dir string, fsys fs.FS) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ func ExampleFileMode() {
|
|||||||
log.Fatal(err)
|
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(); {
|
switch mode := fi.Mode(); {
|
||||||
case mode.IsRegular():
|
case mode.IsRegular():
|
||||||
fmt.Println("regular file")
|
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,
|
// 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
|
// (before umask). If successful, methods on the returned File can
|
||||||
// be used for I/O; the associated file descriptor has mode O_RDWR.
|
// be used for I/O; the associated file descriptor has mode O_RDWR.
|
||||||
// If there is an error, it will be of type *PathError.
|
// 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
|
// On Unix, the mode's permission bits, ModeSetuid, ModeSetgid, and
|
||||||
// ModeSticky are used.
|
// 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.
|
// controls whether the file's read-only attribute is set or cleared.
|
||||||
// The other bits are currently unused. For compatibility with Go 1.12
|
// 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
|
// and earlier, use a non-zero mode. Use mode 0o400 for a read-only
|
||||||
// file and 0600 for a readable+writable file.
|
// file and 0o600 for a readable+writable file.
|
||||||
//
|
//
|
||||||
// On Plan 9, the mode's permission bits, ModeAppend, ModeExclusive,
|
// On Plan 9, the mode's permission bits, ModeAppend, ModeExclusive,
|
||||||
// and ModeTemporary are used.
|
// and ModeTemporary are used.
|
||||||
|
@ -1376,8 +1376,7 @@ func TestChtimes(t *testing.T) {
|
|||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
f := newFile(t)
|
f := newFile(t)
|
||||||
|
// This should be an empty file (see #68687, #68663).
|
||||||
f.Write([]byte("hello, world\n"))
|
|
||||||
f.Close()
|
f.Close()
|
||||||
|
|
||||||
testChtimes(t, f.Name())
|
testChtimes(t, f.Name())
|
||||||
@ -1395,12 +1394,9 @@ func TestChtimesOmit(t *testing.T) {
|
|||||||
func testChtimesOmit(t *testing.T, omitAt, omitMt bool) {
|
func testChtimesOmit(t *testing.T, omitAt, omitMt bool) {
|
||||||
t.Logf("omit atime: %v, mtime: %v", omitAt, omitMt)
|
t.Logf("omit atime: %v, mtime: %v", omitAt, omitMt)
|
||||||
file := newFile(t)
|
file := newFile(t)
|
||||||
_, err := file.Write([]byte("hello, world\n"))
|
// This should be an empty file (see #68687, #68663).
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
name := file.Name()
|
name := file.Name()
|
||||||
err = file.Close()
|
err := file.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
}
|
}
|
||||||
@ -3358,6 +3354,14 @@ func TestCopyFS(t *testing.T) {
|
|||||||
t.Fatal("comparing two directories:", err)
|
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.
|
// Test with memory filesystem.
|
||||||
fsys = fstest.MapFS{
|
fsys = fstest.MapFS{
|
||||||
"william": {Data: []byte("Shakespeare\n")},
|
"william": {Data: []byte("Shakespeare\n")},
|
||||||
@ -3395,6 +3399,14 @@ func TestCopyFS(t *testing.T) {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
t.Fatal("comparing two directories:", err)
|
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) {
|
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
|
// stack. However, since we're returning to an earlier stack frame and
|
||||||
// need to pair with the entersyscall() call made by cgocall, we must
|
// need to pair with the entersyscall() call made by cgocall, we must
|
||||||
// save syscall* and let reentersyscall restore them.
|
// 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)
|
savedsp := unsafe.Pointer(gp.syscallsp)
|
||||||
savedpc := gp.syscallpc
|
savedpc := gp.syscallpc
|
||||||
savedbp := gp.syscallbp
|
savedbp := unsafe.Pointer(gp.syscallbp)
|
||||||
exitsyscall() // coming out of cgo call
|
exitsyscall() // coming out of cgo call
|
||||||
gp.m.incgo = false
|
gp.m.incgo = false
|
||||||
if gp.m.isextra {
|
if gp.m.isextra {
|
||||||
@ -372,7 +377,7 @@ func cgocallbackg(fn, frame unsafe.Pointer, ctxt uintptr) {
|
|||||||
osPreemptExtEnter(gp.m)
|
osPreemptExtEnter(gp.m)
|
||||||
|
|
||||||
// going back to cgo call
|
// going back to cgo call
|
||||||
reentersyscall(savedpc, uintptr(savedsp), savedbp)
|
reentersyscall(savedpc, uintptr(savedsp), uintptr(savedbp))
|
||||||
|
|
||||||
gp.m.winsyscall = winsyscall
|
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 {
|
if gp.syscallsp < gp.stack.lo || gp.stack.hi < gp.syscallsp {
|
||||||
systemstack(func() {
|
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")
|
throw("entersyscall")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -4553,14 +4559,20 @@ func entersyscallblock() {
|
|||||||
sp2 := gp.sched.sp
|
sp2 := gp.sched.sp
|
||||||
sp3 := gp.syscallsp
|
sp3 := gp.syscallsp
|
||||||
systemstack(func() {
|
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")
|
throw("entersyscallblock")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
casgstatus(gp, _Grunning, _Gsyscall)
|
casgstatus(gp, _Grunning, _Gsyscall)
|
||||||
if gp.syscallsp < gp.stack.lo || gp.stack.hi < gp.syscallsp {
|
if gp.syscallsp < gp.stack.lo || gp.stack.hi < gp.syscallsp {
|
||||||
systemstack(func() {
|
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")
|
throw("entersyscallblock")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,8 @@ TEXT _main(SB),NOSPLIT,$-8
|
|||||||
MOVD R12, CTR
|
MOVD R12, CTR
|
||||||
BR (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
|
TEXT _rt0_ppc64_aix_lib(SB),NOSPLIT,$-8
|
||||||
// Start with standard C stack frame layout and linkage.
|
// 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
|
MOVW CR, R0 // Save CR in caller's frame
|
||||||
MOVD R0, 8(R1)
|
MOVD R0, 8(R1)
|
||||||
|
|
||||||
MOVDU R1, -344(R1) // Allocate frame.
|
MOVDU R1, -344-PARAM_SPACE(R1) // Allocate frame.
|
||||||
|
|
||||||
// Preserve callee-save registers.
|
// Preserve callee-save registers.
|
||||||
MOVD R14, 48(R1)
|
MOVD R14, 48+PARAM_SPACE(R1)
|
||||||
MOVD R15, 56(R1)
|
MOVD R15, 56+PARAM_SPACE(R1)
|
||||||
MOVD R16, 64(R1)
|
MOVD R16, 64+PARAM_SPACE(R1)
|
||||||
MOVD R17, 72(R1)
|
MOVD R17, 72+PARAM_SPACE(R1)
|
||||||
MOVD R18, 80(R1)
|
MOVD R18, 80+PARAM_SPACE(R1)
|
||||||
MOVD R19, 88(R1)
|
MOVD R19, 88+PARAM_SPACE(R1)
|
||||||
MOVD R20, 96(R1)
|
MOVD R20, 96+PARAM_SPACE(R1)
|
||||||
MOVD R21,104(R1)
|
MOVD R21,104+PARAM_SPACE(R1)
|
||||||
MOVD R22, 112(R1)
|
MOVD R22, 112+PARAM_SPACE(R1)
|
||||||
MOVD R23, 120(R1)
|
MOVD R23, 120+PARAM_SPACE(R1)
|
||||||
MOVD R24, 128(R1)
|
MOVD R24, 128+PARAM_SPACE(R1)
|
||||||
MOVD R25, 136(R1)
|
MOVD R25, 136+PARAM_SPACE(R1)
|
||||||
MOVD R26, 144(R1)
|
MOVD R26, 144+PARAM_SPACE(R1)
|
||||||
MOVD R27, 152(R1)
|
MOVD R27, 152+PARAM_SPACE(R1)
|
||||||
MOVD R28, 160(R1)
|
MOVD R28, 160+PARAM_SPACE(R1)
|
||||||
MOVD R29, 168(R1)
|
MOVD R29, 168+PARAM_SPACE(R1)
|
||||||
MOVD g, 176(R1) // R30
|
MOVD g, 176+PARAM_SPACE(R1) // R30
|
||||||
MOVD R31, 184(R1)
|
MOVD R31, 184+PARAM_SPACE(R1)
|
||||||
FMOVD F14, 192(R1)
|
FMOVD F14, 192+PARAM_SPACE(R1)
|
||||||
FMOVD F15, 200(R1)
|
FMOVD F15, 200+PARAM_SPACE(R1)
|
||||||
FMOVD F16, 208(R1)
|
FMOVD F16, 208+PARAM_SPACE(R1)
|
||||||
FMOVD F17, 216(R1)
|
FMOVD F17, 216+PARAM_SPACE(R1)
|
||||||
FMOVD F18, 224(R1)
|
FMOVD F18, 224+PARAM_SPACE(R1)
|
||||||
FMOVD F19, 232(R1)
|
FMOVD F19, 232+PARAM_SPACE(R1)
|
||||||
FMOVD F20, 240(R1)
|
FMOVD F20, 240+PARAM_SPACE(R1)
|
||||||
FMOVD F21, 248(R1)
|
FMOVD F21, 248+PARAM_SPACE(R1)
|
||||||
FMOVD F22, 256(R1)
|
FMOVD F22, 256+PARAM_SPACE(R1)
|
||||||
FMOVD F23, 264(R1)
|
FMOVD F23, 264+PARAM_SPACE(R1)
|
||||||
FMOVD F24, 272(R1)
|
FMOVD F24, 272+PARAM_SPACE(R1)
|
||||||
FMOVD F25, 280(R1)
|
FMOVD F25, 280+PARAM_SPACE(R1)
|
||||||
FMOVD F26, 288(R1)
|
FMOVD F26, 288+PARAM_SPACE(R1)
|
||||||
FMOVD F27, 296(R1)
|
FMOVD F27, 296+PARAM_SPACE(R1)
|
||||||
FMOVD F28, 304(R1)
|
FMOVD F28, 304+PARAM_SPACE(R1)
|
||||||
FMOVD F29, 312(R1)
|
FMOVD F29, 312+PARAM_SPACE(R1)
|
||||||
FMOVD F30, 320(R1)
|
FMOVD F30, 320+PARAM_SPACE(R1)
|
||||||
FMOVD F31, 328(R1)
|
FMOVD F31, 328+PARAM_SPACE(R1)
|
||||||
|
|
||||||
// Synchronous initialization.
|
// Synchronous initialization.
|
||||||
MOVD $runtime·reginit(SB), R12
|
MOVD $runtime·reginit(SB), R12
|
||||||
@ -130,44 +132,44 @@ nocgo:
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
// Restore saved registers.
|
// Restore saved registers.
|
||||||
MOVD 48(R1), R14
|
MOVD 48+PARAM_SPACE(R1), R14
|
||||||
MOVD 56(R1), R15
|
MOVD 56+PARAM_SPACE(R1), R15
|
||||||
MOVD 64(R1), R16
|
MOVD 64+PARAM_SPACE(R1), R16
|
||||||
MOVD 72(R1), R17
|
MOVD 72+PARAM_SPACE(R1), R17
|
||||||
MOVD 80(R1), R18
|
MOVD 80+PARAM_SPACE(R1), R18
|
||||||
MOVD 88(R1), R19
|
MOVD 88+PARAM_SPACE(R1), R19
|
||||||
MOVD 96(R1), R20
|
MOVD 96+PARAM_SPACE(R1), R20
|
||||||
MOVD 104(R1), R21
|
MOVD 104+PARAM_SPACE(R1), R21
|
||||||
MOVD 112(R1), R22
|
MOVD 112+PARAM_SPACE(R1), R22
|
||||||
MOVD 120(R1), R23
|
MOVD 120+PARAM_SPACE(R1), R23
|
||||||
MOVD 128(R1), R24
|
MOVD 128+PARAM_SPACE(R1), R24
|
||||||
MOVD 136(R1), R25
|
MOVD 136+PARAM_SPACE(R1), R25
|
||||||
MOVD 144(R1), R26
|
MOVD 144+PARAM_SPACE(R1), R26
|
||||||
MOVD 152(R1), R27
|
MOVD 152+PARAM_SPACE(R1), R27
|
||||||
MOVD 160(R1), R28
|
MOVD 160+PARAM_SPACE(R1), R28
|
||||||
MOVD 168(R1), R29
|
MOVD 168+PARAM_SPACE(R1), R29
|
||||||
MOVD 176(R1), g // R30
|
MOVD 176+PARAM_SPACE(R1), g // R30
|
||||||
MOVD 184(R1), R31
|
MOVD 184+PARAM_SPACE(R1), R31
|
||||||
FMOVD 196(R1), F14
|
FMOVD 196+PARAM_SPACE(R1), F14
|
||||||
FMOVD 200(R1), F15
|
FMOVD 200+PARAM_SPACE(R1), F15
|
||||||
FMOVD 208(R1), F16
|
FMOVD 208+PARAM_SPACE(R1), F16
|
||||||
FMOVD 216(R1), F17
|
FMOVD 216+PARAM_SPACE(R1), F17
|
||||||
FMOVD 224(R1), F18
|
FMOVD 224+PARAM_SPACE(R1), F18
|
||||||
FMOVD 232(R1), F19
|
FMOVD 232+PARAM_SPACE(R1), F19
|
||||||
FMOVD 240(R1), F20
|
FMOVD 240+PARAM_SPACE(R1), F20
|
||||||
FMOVD 248(R1), F21
|
FMOVD 248+PARAM_SPACE(R1), F21
|
||||||
FMOVD 256(R1), F22
|
FMOVD 256+PARAM_SPACE(R1), F22
|
||||||
FMOVD 264(R1), F23
|
FMOVD 264+PARAM_SPACE(R1), F23
|
||||||
FMOVD 272(R1), F24
|
FMOVD 272+PARAM_SPACE(R1), F24
|
||||||
FMOVD 280(R1), F25
|
FMOVD 280+PARAM_SPACE(R1), F25
|
||||||
FMOVD 288(R1), F26
|
FMOVD 288+PARAM_SPACE(R1), F26
|
||||||
FMOVD 296(R1), F27
|
FMOVD 296+PARAM_SPACE(R1), F27
|
||||||
FMOVD 304(R1), F28
|
FMOVD 304+PARAM_SPACE(R1), F28
|
||||||
FMOVD 312(R1), F29
|
FMOVD 312+PARAM_SPACE(R1), F29
|
||||||
FMOVD 320(R1), F30
|
FMOVD 320+PARAM_SPACE(R1), F30
|
||||||
FMOVD 328(R1), F31
|
FMOVD 328+PARAM_SPACE(R1), F31
|
||||||
|
|
||||||
ADD $344, R1
|
ADD $344+PARAM_SPACE, R1
|
||||||
|
|
||||||
MOVD 8(R1), R0
|
MOVD 8(R1), R0
|
||||||
MOVFL R0, $0xff
|
MOVFL R0, $0xff
|
||||||
|
@ -27,7 +27,7 @@ func cSeq(stringOffsets ...uintptr) cloneSeq {
|
|||||||
|
|
||||||
func testCloneSeq[T any](t *testing.T, want cloneSeq) {
|
func testCloneSeq[T any](t *testing.T, want cloneSeq) {
|
||||||
typName := reflect.TypeFor[T]().Name()
|
typName := reflect.TypeFor[T]().Name()
|
||||||
typ := abi.TypeOf(*new(T))
|
typ := abi.TypeFor[T]()
|
||||||
t.Run(typName, func(t *testing.T) {
|
t.Run(typName, func(t *testing.T) {
|
||||||
got := makeCloneSeq(typ)
|
got := makeCloneSeq(typ)
|
||||||
if !reflect.DeepEqual(got, want) {
|
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.
|
// are equal if and only if the values used to produce them are equal.
|
||||||
func Make[T comparable](value T) Handle[T] {
|
func Make[T comparable](value T) Handle[T] {
|
||||||
// Find the map for type T.
|
// Find the map for type T.
|
||||||
typ := abi.TypeOf(value)
|
typ := abi.TypeFor[T]()
|
||||||
ma, ok := uniqueMaps.Load(typ)
|
ma, ok := uniqueMaps.Load(typ)
|
||||||
if !ok {
|
if !ok {
|
||||||
// This is a good time to initialize cleanup, since we must go through
|
// 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"}},
|
s: [2]testStringStruct{testStringStruct{"y"}, testStringStruct{"z"}},
|
||||||
})
|
})
|
||||||
testHandle[testStruct](t, testStruct{0.5, "184"})
|
testHandle[testStruct](t, testStruct{0.5, "184"})
|
||||||
|
testHandle[testEface](t, testEface("hello"))
|
||||||
}
|
}
|
||||||
|
|
||||||
func testHandle[T comparable](t *testing.T, value T) {
|
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) {
|
func checkMapsFor[T comparable](t *testing.T, value T) {
|
||||||
// Manually load the value out of the map.
|
// Manually load the value out of the map.
|
||||||
typ := abi.TypeOf(value)
|
typ := abi.TypeFor[T]()
|
||||||
a, ok := uniqueMaps.Load(typ)
|
a, ok := uniqueMaps.Load(typ)
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
|
@ -1,16 +1,20 @@
|
|||||||
// errorcheck -lang=go1.21
|
// errorcheck -lang=go1.22
|
||||||
|
|
||||||
// Copyright 2023 The Go Authors. All rights reserved.
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// 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
|
package p
|
||||||
|
|
||||||
const c = 0o123 // ERROR "file declares //go:build go1.4"
|
func f() {
|
||||||
|
for _ = range 10 { // ERROR "file declares //go:build go1.21"
|
||||||
// ERROR "file declares //go:build go1.4"
|
}
|
||||||
|
}
|
||||||
//line issue63489a.go:13:1
|
|
||||||
const d = 0o124
|
|
||||||
|
@ -1,11 +1,20 @@
|
|||||||
// errorcheck -lang=go1.4
|
// errorcheck -lang=go1.21
|
||||||
|
|
||||||
// Copyright 2023 The Go Authors. All rights reserved.
|
// Copyright 2023 The Go Authors. All rights reserved.
|
||||||
// Use of this source code is governed by a BSD-style
|
// Use of this source code is governed by a BSD-style
|
||||||
// license that can be found in the LICENSE file.
|
// 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
|
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