mirror of https://github.com/containers/podman.git
Merge pull request #24182 from containers/renovate/golang.org-x-tools-0.x
fix(deps): update module golang.org/x/tools to v0.26.0
This commit is contained in:
commit
6b0ad8269c
|
@ -9,7 +9,7 @@ require (
|
||||||
github.com/go-swagger/go-swagger v0.30.5
|
github.com/go-swagger/go-swagger v0.30.5
|
||||||
github.com/onsi/ginkgo/v2 v2.20.2
|
github.com/onsi/ginkgo/v2 v2.20.2
|
||||||
github.com/vbatts/git-validation v1.2.1
|
github.com/vbatts/git-validation v1.2.1
|
||||||
golang.org/x/tools v0.25.0
|
golang.org/x/tools v0.26.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
@ -69,7 +69,7 @@ require (
|
||||||
golang.org/x/crypto v0.17.0 // indirect
|
golang.org/x/crypto v0.17.0 // indirect
|
||||||
golang.org/x/mod v0.21.0 // indirect
|
golang.org/x/mod v0.21.0 // indirect
|
||||||
golang.org/x/sync v0.8.0 // indirect
|
golang.org/x/sync v0.8.0 // indirect
|
||||||
golang.org/x/sys v0.25.0 // indirect
|
golang.org/x/sys v0.26.0 // indirect
|
||||||
golang.org/x/text v0.17.0 // indirect
|
golang.org/x/text v0.17.0 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
|
|
|
@ -461,8 +461,8 @@ golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
|
golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4=
|
||||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
|
golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
|
@ -536,8 +536,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo=
|
||||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
||||||
|
@ -608,8 +608,8 @@ golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4f
|
||||||
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.25.0 h1:oFU9pkj/iJgs+0DT+VMHrx+oBKs/LJMV+Uvg78sl+fE=
|
golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ=
|
||||||
golang.org/x/tools v0.25.0/go.mod h1:/vtpO8WL1N9cQC3FN5zPqb//fRXskFHbLKk4OW1Q7rg=
|
golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
|
|
|
@ -156,7 +156,7 @@ from the generated architecture-specific files listed below, and merge these
|
||||||
into a common file for each OS.
|
into a common file for each OS.
|
||||||
|
|
||||||
The merge is performed in the following steps:
|
The merge is performed in the following steps:
|
||||||
1. Construct the set of common code that is idential in all architecture-specific files.
|
1. Construct the set of common code that is identical in all architecture-specific files.
|
||||||
2. Write this common code to the merged file.
|
2. Write this common code to the merged file.
|
||||||
3. Remove the common code from all architecture-specific files.
|
3. Remove the common code from all architecture-specific files.
|
||||||
|
|
||||||
|
|
|
@ -656,7 +656,7 @@ errors=$(
|
||||||
signals=$(
|
signals=$(
|
||||||
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
|
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print $2 }' |
|
||||||
grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
|
grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
|
||||||
sort
|
sort
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -666,7 +666,7 @@ echo '#include <errno.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
sort >_error.grep
|
sort >_error.grep
|
||||||
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
echo '#include <signal.h>' | $CC -x c - -E -dM $ccflags |
|
||||||
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
|
awk '$1=="#define" && $2 ~ /^SIG[A-Z0-9]+$/ { print "^\t" $2 "[ \t]*=" }' |
|
||||||
grep -v 'SIGSTKSIZE\|SIGSTKSZ\|SIGRT\|SIGMAX64' |
|
grep -E -v '(SIGSTKSIZE|SIGSTKSZ|SIGRT|SIGMAX64)' |
|
||||||
sort >_signal.grep
|
sort >_signal.grep
|
||||||
|
|
||||||
echo '// mkerrors.sh' "$@"
|
echo '// mkerrors.sh' "$@"
|
||||||
|
|
|
@ -360,7 +360,7 @@ func Wait4(pid int, wstatus *WaitStatus, options int, rusage *Rusage) (wpid int,
|
||||||
var status _C_int
|
var status _C_int
|
||||||
var r Pid_t
|
var r Pid_t
|
||||||
err = ERESTART
|
err = ERESTART
|
||||||
// AIX wait4 may return with ERESTART errno, while the processus is still
|
// AIX wait4 may return with ERESTART errno, while the process is still
|
||||||
// active.
|
// active.
|
||||||
for err == ERESTART {
|
for err == ERESTART {
|
||||||
r, err = wait4(Pid_t(pid), &status, options, rusage)
|
r, err = wait4(Pid_t(pid), &status, options, rusage)
|
||||||
|
|
|
@ -1295,6 +1295,48 @@ func GetsockoptTCPInfo(fd, level, opt int) (*TCPInfo, error) {
|
||||||
return &value, err
|
return &value, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetsockoptTCPCCVegasInfo returns algorithm specific congestion control information for a socket using the "vegas"
|
||||||
|
// algorithm.
|
||||||
|
//
|
||||||
|
// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option:
|
||||||
|
//
|
||||||
|
// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION)
|
||||||
|
func GetsockoptTCPCCVegasInfo(fd, level, opt int) (*TCPVegasInfo, error) {
|
||||||
|
var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment
|
||||||
|
vallen := _Socklen(SizeofTCPCCInfo)
|
||||||
|
err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
|
||||||
|
out := (*TCPVegasInfo)(unsafe.Pointer(&value[0]))
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetsockoptTCPCCDCTCPInfo returns algorithm specific congestion control information for a socket using the "dctp"
|
||||||
|
// algorithm.
|
||||||
|
//
|
||||||
|
// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option:
|
||||||
|
//
|
||||||
|
// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION)
|
||||||
|
func GetsockoptTCPCCDCTCPInfo(fd, level, opt int) (*TCPDCTCPInfo, error) {
|
||||||
|
var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment
|
||||||
|
vallen := _Socklen(SizeofTCPCCInfo)
|
||||||
|
err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
|
||||||
|
out := (*TCPDCTCPInfo)(unsafe.Pointer(&value[0]))
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetsockoptTCPCCBBRInfo returns algorithm specific congestion control information for a socket using the "bbr"
|
||||||
|
// algorithm.
|
||||||
|
//
|
||||||
|
// The socket's congestion control algorighm can be retrieved via [GetsockoptString] with the [TCP_CONGESTION] option:
|
||||||
|
//
|
||||||
|
// algo, err := unix.GetsockoptString(fd, unix.IPPROTO_TCP, unix.TCP_CONGESTION)
|
||||||
|
func GetsockoptTCPCCBBRInfo(fd, level, opt int) (*TCPBBRInfo, error) {
|
||||||
|
var value [SizeofTCPCCInfo / 4]uint32 // ensure proper alignment
|
||||||
|
vallen := _Socklen(SizeofTCPCCInfo)
|
||||||
|
err := getsockopt(fd, level, opt, unsafe.Pointer(&value[0]), &vallen)
|
||||||
|
out := (*TCPBBRInfo)(unsafe.Pointer(&value[0]))
|
||||||
|
return out, err
|
||||||
|
}
|
||||||
|
|
||||||
// GetsockoptString returns the string value of the socket option opt for the
|
// GetsockoptString returns the string value of the socket option opt for the
|
||||||
// socket associated with fd at the given socket level.
|
// socket associated with fd at the given socket level.
|
||||||
func GetsockoptString(fd, level, opt int) (string, error) {
|
func GetsockoptString(fd, level, opt int) (string, error) {
|
||||||
|
@ -1959,7 +2001,26 @@ func Getpgrp() (pid int) {
|
||||||
//sysnb Getpid() (pid int)
|
//sysnb Getpid() (pid int)
|
||||||
//sysnb Getppid() (ppid int)
|
//sysnb Getppid() (ppid int)
|
||||||
//sys Getpriority(which int, who int) (prio int, err error)
|
//sys Getpriority(which int, who int) (prio int, err error)
|
||||||
//sys Getrandom(buf []byte, flags int) (n int, err error)
|
|
||||||
|
func Getrandom(buf []byte, flags int) (n int, err error) {
|
||||||
|
vdsoRet, supported := vgetrandom(buf, uint32(flags))
|
||||||
|
if supported {
|
||||||
|
if vdsoRet < 0 {
|
||||||
|
return 0, errnoErr(syscall.Errno(-vdsoRet))
|
||||||
|
}
|
||||||
|
return vdsoRet, nil
|
||||||
|
}
|
||||||
|
var p *byte
|
||||||
|
if len(buf) > 0 {
|
||||||
|
p = &buf[0]
|
||||||
|
}
|
||||||
|
r, _, e := Syscall(SYS_GETRANDOM, uintptr(unsafe.Pointer(p)), uintptr(len(buf)), uintptr(flags))
|
||||||
|
if e != 0 {
|
||||||
|
return 0, errnoErr(e)
|
||||||
|
}
|
||||||
|
return int(r), nil
|
||||||
|
}
|
||||||
|
|
||||||
//sysnb Getrusage(who int, rusage *Rusage) (err error)
|
//sysnb Getrusage(who int, rusage *Rusage) (err error)
|
||||||
//sysnb Getsid(pid int) (sid int, err error)
|
//sysnb Getsid(pid int) (sid int, err error)
|
||||||
//sysnb Gettid() (tid int)
|
//sysnb Gettid() (tid int)
|
||||||
|
|
|
@ -182,3 +182,5 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
|
||||||
}
|
}
|
||||||
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
|
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SYS_FSTATAT = SYS_NEWFSTATAT
|
||||||
|
|
|
@ -214,3 +214,5 @@ func KexecFileLoad(kernelFd int, initrdFd int, cmdline string, flags int) error
|
||||||
}
|
}
|
||||||
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
|
return kexecFileLoad(kernelFd, initrdFd, cmdlineLen, cmdline, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SYS_FSTATAT = SYS_NEWFSTATAT
|
||||||
|
|
|
@ -187,3 +187,5 @@ func RISCVHWProbe(pairs []RISCVHWProbePairs, set *CPUSet, flags uint) (err error
|
||||||
}
|
}
|
||||||
return riscvHWProbe(pairs, setSize, set, flags)
|
return riscvHWProbe(pairs, setSize, set, flags)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SYS_FSTATAT = SYS_NEWFSTATAT
|
||||||
|
|
|
@ -0,0 +1,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.
|
||||||
|
|
||||||
|
//go:build linux && go1.24
|
||||||
|
|
||||||
|
package unix
|
||||||
|
|
||||||
|
import _ "unsafe"
|
||||||
|
|
||||||
|
//go:linkname vgetrandom runtime.vgetrandom
|
||||||
|
//go:noescape
|
||||||
|
func vgetrandom(p []byte, flags uint32) (ret int, supported bool)
|
|
@ -2,13 +2,10 @@
|
||||||
// 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.21
|
//go:build !linux || !go1.24
|
||||||
// +build go1.21
|
|
||||||
|
|
||||||
package versions
|
package unix
|
||||||
|
|
||||||
func init() {
|
func vgetrandom(p []byte, flags uint32) (ret int, supported bool) {
|
||||||
if Compare(toolchain, Go1_21) < 0 {
|
return -1, false
|
||||||
toolchain = Go1_21
|
|
||||||
}
|
|
||||||
}
|
}
|
|
@ -495,6 +495,7 @@ const (
|
||||||
BPF_F_TEST_REG_INVARIANTS = 0x80
|
BPF_F_TEST_REG_INVARIANTS = 0x80
|
||||||
BPF_F_TEST_RND_HI32 = 0x4
|
BPF_F_TEST_RND_HI32 = 0x4
|
||||||
BPF_F_TEST_RUN_ON_CPU = 0x1
|
BPF_F_TEST_RUN_ON_CPU = 0x1
|
||||||
|
BPF_F_TEST_SKB_CHECKSUM_COMPLETE = 0x4
|
||||||
BPF_F_TEST_STATE_FREQ = 0x8
|
BPF_F_TEST_STATE_FREQ = 0x8
|
||||||
BPF_F_TEST_XDP_LIVE_FRAMES = 0x2
|
BPF_F_TEST_XDP_LIVE_FRAMES = 0x2
|
||||||
BPF_F_XDP_DEV_BOUND_ONLY = 0x40
|
BPF_F_XDP_DEV_BOUND_ONLY = 0x40
|
||||||
|
@ -1922,6 +1923,7 @@ const (
|
||||||
MNT_EXPIRE = 0x4
|
MNT_EXPIRE = 0x4
|
||||||
MNT_FORCE = 0x1
|
MNT_FORCE = 0x1
|
||||||
MNT_ID_REQ_SIZE_VER0 = 0x18
|
MNT_ID_REQ_SIZE_VER0 = 0x18
|
||||||
|
MNT_ID_REQ_SIZE_VER1 = 0x20
|
||||||
MODULE_INIT_COMPRESSED_FILE = 0x4
|
MODULE_INIT_COMPRESSED_FILE = 0x4
|
||||||
MODULE_INIT_IGNORE_MODVERSIONS = 0x1
|
MODULE_INIT_IGNORE_MODVERSIONS = 0x1
|
||||||
MODULE_INIT_IGNORE_VERMAGIC = 0x2
|
MODULE_INIT_IGNORE_VERMAGIC = 0x2
|
||||||
|
@ -2187,7 +2189,7 @@ const (
|
||||||
NFT_REG_SIZE = 0x10
|
NFT_REG_SIZE = 0x10
|
||||||
NFT_REJECT_ICMPX_MAX = 0x3
|
NFT_REJECT_ICMPX_MAX = 0x3
|
||||||
NFT_RT_MAX = 0x4
|
NFT_RT_MAX = 0x4
|
||||||
NFT_SECMARK_CTX_MAXLEN = 0x100
|
NFT_SECMARK_CTX_MAXLEN = 0x1000
|
||||||
NFT_SET_MAXNAMELEN = 0x100
|
NFT_SET_MAXNAMELEN = 0x100
|
||||||
NFT_SOCKET_MAX = 0x3
|
NFT_SOCKET_MAX = 0x3
|
||||||
NFT_TABLE_F_MASK = 0x7
|
NFT_TABLE_F_MASK = 0x7
|
||||||
|
@ -2356,9 +2358,11 @@ const (
|
||||||
PERF_MEM_LVLNUM_IO = 0xa
|
PERF_MEM_LVLNUM_IO = 0xa
|
||||||
PERF_MEM_LVLNUM_L1 = 0x1
|
PERF_MEM_LVLNUM_L1 = 0x1
|
||||||
PERF_MEM_LVLNUM_L2 = 0x2
|
PERF_MEM_LVLNUM_L2 = 0x2
|
||||||
|
PERF_MEM_LVLNUM_L2_MHB = 0x5
|
||||||
PERF_MEM_LVLNUM_L3 = 0x3
|
PERF_MEM_LVLNUM_L3 = 0x3
|
||||||
PERF_MEM_LVLNUM_L4 = 0x4
|
PERF_MEM_LVLNUM_L4 = 0x4
|
||||||
PERF_MEM_LVLNUM_LFB = 0xc
|
PERF_MEM_LVLNUM_LFB = 0xc
|
||||||
|
PERF_MEM_LVLNUM_MSC = 0x6
|
||||||
PERF_MEM_LVLNUM_NA = 0xf
|
PERF_MEM_LVLNUM_NA = 0xf
|
||||||
PERF_MEM_LVLNUM_PMEM = 0xe
|
PERF_MEM_LVLNUM_PMEM = 0xe
|
||||||
PERF_MEM_LVLNUM_RAM = 0xd
|
PERF_MEM_LVLNUM_RAM = 0xd
|
||||||
|
@ -2431,6 +2435,7 @@ const (
|
||||||
PRIO_PGRP = 0x1
|
PRIO_PGRP = 0x1
|
||||||
PRIO_PROCESS = 0x0
|
PRIO_PROCESS = 0x0
|
||||||
PRIO_USER = 0x2
|
PRIO_USER = 0x2
|
||||||
|
PROCFS_IOCTL_MAGIC = 'f'
|
||||||
PROC_SUPER_MAGIC = 0x9fa0
|
PROC_SUPER_MAGIC = 0x9fa0
|
||||||
PROT_EXEC = 0x4
|
PROT_EXEC = 0x4
|
||||||
PROT_GROWSDOWN = 0x1000000
|
PROT_GROWSDOWN = 0x1000000
|
||||||
|
@ -2933,11 +2938,12 @@ const (
|
||||||
RUSAGE_SELF = 0x0
|
RUSAGE_SELF = 0x0
|
||||||
RUSAGE_THREAD = 0x1
|
RUSAGE_THREAD = 0x1
|
||||||
RWF_APPEND = 0x10
|
RWF_APPEND = 0x10
|
||||||
|
RWF_ATOMIC = 0x40
|
||||||
RWF_DSYNC = 0x2
|
RWF_DSYNC = 0x2
|
||||||
RWF_HIPRI = 0x1
|
RWF_HIPRI = 0x1
|
||||||
RWF_NOAPPEND = 0x20
|
RWF_NOAPPEND = 0x20
|
||||||
RWF_NOWAIT = 0x8
|
RWF_NOWAIT = 0x8
|
||||||
RWF_SUPPORTED = 0x3f
|
RWF_SUPPORTED = 0x7f
|
||||||
RWF_SYNC = 0x4
|
RWF_SYNC = 0x4
|
||||||
RWF_WRITE_LIFE_NOT_SET = 0x0
|
RWF_WRITE_LIFE_NOT_SET = 0x0
|
||||||
SCHED_BATCH = 0x3
|
SCHED_BATCH = 0x3
|
||||||
|
@ -3210,6 +3216,7 @@ const (
|
||||||
STATX_ATTR_MOUNT_ROOT = 0x2000
|
STATX_ATTR_MOUNT_ROOT = 0x2000
|
||||||
STATX_ATTR_NODUMP = 0x40
|
STATX_ATTR_NODUMP = 0x40
|
||||||
STATX_ATTR_VERITY = 0x100000
|
STATX_ATTR_VERITY = 0x100000
|
||||||
|
STATX_ATTR_WRITE_ATOMIC = 0x400000
|
||||||
STATX_BASIC_STATS = 0x7ff
|
STATX_BASIC_STATS = 0x7ff
|
||||||
STATX_BLOCKS = 0x400
|
STATX_BLOCKS = 0x400
|
||||||
STATX_BTIME = 0x800
|
STATX_BTIME = 0x800
|
||||||
|
@ -3226,6 +3233,7 @@ const (
|
||||||
STATX_SUBVOL = 0x8000
|
STATX_SUBVOL = 0x8000
|
||||||
STATX_TYPE = 0x1
|
STATX_TYPE = 0x1
|
||||||
STATX_UID = 0x8
|
STATX_UID = 0x8
|
||||||
|
STATX_WRITE_ATOMIC = 0x10000
|
||||||
STATX__RESERVED = 0x80000000
|
STATX__RESERVED = 0x80000000
|
||||||
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
SYNC_FILE_RANGE_WAIT_AFTER = 0x4
|
||||||
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
SYNC_FILE_RANGE_WAIT_BEFORE = 0x1
|
||||||
|
@ -3624,6 +3632,7 @@ const (
|
||||||
XDP_UMEM_PGOFF_COMPLETION_RING = 0x180000000
|
XDP_UMEM_PGOFF_COMPLETION_RING = 0x180000000
|
||||||
XDP_UMEM_PGOFF_FILL_RING = 0x100000000
|
XDP_UMEM_PGOFF_FILL_RING = 0x100000000
|
||||||
XDP_UMEM_REG = 0x4
|
XDP_UMEM_REG = 0x4
|
||||||
|
XDP_UMEM_TX_METADATA_LEN = 0x4
|
||||||
XDP_UMEM_TX_SW_CSUM = 0x2
|
XDP_UMEM_TX_SW_CSUM = 0x2
|
||||||
XDP_UMEM_UNALIGNED_CHUNK_FLAG = 0x1
|
XDP_UMEM_UNALIGNED_CHUNK_FLAG = 0x1
|
||||||
XDP_USE_NEED_WAKEUP = 0x8
|
XDP_USE_NEED_WAKEUP = 0x8
|
||||||
|
|
|
@ -153,9 +153,14 @@ const (
|
||||||
NFDBITS = 0x20
|
NFDBITS = 0x20
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x8008b705
|
||||||
NS_GET_NSTYPE = 0xb703
|
NS_GET_NSTYPE = 0xb703
|
||||||
NS_GET_OWNER_UID = 0xb704
|
NS_GET_OWNER_UID = 0xb704
|
||||||
NS_GET_PARENT = 0xb702
|
NS_GET_PARENT = 0xb702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||||
NS_GET_USERNS = 0xb701
|
NS_GET_USERNS = 0xb701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -153,9 +153,14 @@ const (
|
||||||
NFDBITS = 0x40
|
NFDBITS = 0x40
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x8008b705
|
||||||
NS_GET_NSTYPE = 0xb703
|
NS_GET_NSTYPE = 0xb703
|
||||||
NS_GET_OWNER_UID = 0xb704
|
NS_GET_OWNER_UID = 0xb704
|
||||||
NS_GET_PARENT = 0xb702
|
NS_GET_PARENT = 0xb702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||||
NS_GET_USERNS = 0xb701
|
NS_GET_USERNS = 0xb701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -150,9 +150,14 @@ const (
|
||||||
NFDBITS = 0x20
|
NFDBITS = 0x20
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x8008b705
|
||||||
NS_GET_NSTYPE = 0xb703
|
NS_GET_NSTYPE = 0xb703
|
||||||
NS_GET_OWNER_UID = 0xb704
|
NS_GET_OWNER_UID = 0xb704
|
||||||
NS_GET_PARENT = 0xb702
|
NS_GET_PARENT = 0xb702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||||
NS_GET_USERNS = 0xb701
|
NS_GET_USERNS = 0xb701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -154,9 +154,14 @@ const (
|
||||||
NFDBITS = 0x40
|
NFDBITS = 0x40
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x8008b705
|
||||||
NS_GET_NSTYPE = 0xb703
|
NS_GET_NSTYPE = 0xb703
|
||||||
NS_GET_OWNER_UID = 0xb704
|
NS_GET_OWNER_UID = 0xb704
|
||||||
NS_GET_PARENT = 0xb702
|
NS_GET_PARENT = 0xb702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||||
NS_GET_USERNS = 0xb701
|
NS_GET_USERNS = 0xb701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -154,9 +154,14 @@ const (
|
||||||
NFDBITS = 0x40
|
NFDBITS = 0x40
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x8008b705
|
||||||
NS_GET_NSTYPE = 0xb703
|
NS_GET_NSTYPE = 0xb703
|
||||||
NS_GET_OWNER_UID = 0xb704
|
NS_GET_OWNER_UID = 0xb704
|
||||||
NS_GET_PARENT = 0xb702
|
NS_GET_PARENT = 0xb702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||||
NS_GET_USERNS = 0xb701
|
NS_GET_USERNS = 0xb701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -150,9 +150,14 @@ const (
|
||||||
NFDBITS = 0x20
|
NFDBITS = 0x20
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x4008b705
|
||||||
NS_GET_NSTYPE = 0x2000b703
|
NS_GET_NSTYPE = 0x2000b703
|
||||||
NS_GET_OWNER_UID = 0x2000b704
|
NS_GET_OWNER_UID = 0x2000b704
|
||||||
NS_GET_PARENT = 0x2000b702
|
NS_GET_PARENT = 0x2000b702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x4004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x4004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x4004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x4004b709
|
||||||
NS_GET_USERNS = 0x2000b701
|
NS_GET_USERNS = 0x2000b701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -150,9 +150,14 @@ const (
|
||||||
NFDBITS = 0x40
|
NFDBITS = 0x40
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x4008b705
|
||||||
NS_GET_NSTYPE = 0x2000b703
|
NS_GET_NSTYPE = 0x2000b703
|
||||||
NS_GET_OWNER_UID = 0x2000b704
|
NS_GET_OWNER_UID = 0x2000b704
|
||||||
NS_GET_PARENT = 0x2000b702
|
NS_GET_PARENT = 0x2000b702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x4004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x4004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x4004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x4004b709
|
||||||
NS_GET_USERNS = 0x2000b701
|
NS_GET_USERNS = 0x2000b701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -150,9 +150,14 @@ const (
|
||||||
NFDBITS = 0x40
|
NFDBITS = 0x40
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x4008b705
|
||||||
NS_GET_NSTYPE = 0x2000b703
|
NS_GET_NSTYPE = 0x2000b703
|
||||||
NS_GET_OWNER_UID = 0x2000b704
|
NS_GET_OWNER_UID = 0x2000b704
|
||||||
NS_GET_PARENT = 0x2000b702
|
NS_GET_PARENT = 0x2000b702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x4004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x4004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x4004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x4004b709
|
||||||
NS_GET_USERNS = 0x2000b701
|
NS_GET_USERNS = 0x2000b701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -150,9 +150,14 @@ const (
|
||||||
NFDBITS = 0x20
|
NFDBITS = 0x20
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x4008b705
|
||||||
NS_GET_NSTYPE = 0x2000b703
|
NS_GET_NSTYPE = 0x2000b703
|
||||||
NS_GET_OWNER_UID = 0x2000b704
|
NS_GET_OWNER_UID = 0x2000b704
|
||||||
NS_GET_PARENT = 0x2000b702
|
NS_GET_PARENT = 0x2000b702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x4004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x4004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x4004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x4004b709
|
||||||
NS_GET_USERNS = 0x2000b701
|
NS_GET_USERNS = 0x2000b701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -152,9 +152,14 @@ const (
|
||||||
NL3 = 0x300
|
NL3 = 0x300
|
||||||
NLDLY = 0x300
|
NLDLY = 0x300
|
||||||
NOFLSH = 0x80000000
|
NOFLSH = 0x80000000
|
||||||
|
NS_GET_MNTNS_ID = 0x4008b705
|
||||||
NS_GET_NSTYPE = 0x2000b703
|
NS_GET_NSTYPE = 0x2000b703
|
||||||
NS_GET_OWNER_UID = 0x2000b704
|
NS_GET_OWNER_UID = 0x2000b704
|
||||||
NS_GET_PARENT = 0x2000b702
|
NS_GET_PARENT = 0x2000b702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x4004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x4004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x4004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x4004b709
|
||||||
NS_GET_USERNS = 0x2000b701
|
NS_GET_USERNS = 0x2000b701
|
||||||
OLCUC = 0x4
|
OLCUC = 0x4
|
||||||
ONLCR = 0x2
|
ONLCR = 0x2
|
||||||
|
|
|
@ -152,9 +152,14 @@ const (
|
||||||
NL3 = 0x300
|
NL3 = 0x300
|
||||||
NLDLY = 0x300
|
NLDLY = 0x300
|
||||||
NOFLSH = 0x80000000
|
NOFLSH = 0x80000000
|
||||||
|
NS_GET_MNTNS_ID = 0x4008b705
|
||||||
NS_GET_NSTYPE = 0x2000b703
|
NS_GET_NSTYPE = 0x2000b703
|
||||||
NS_GET_OWNER_UID = 0x2000b704
|
NS_GET_OWNER_UID = 0x2000b704
|
||||||
NS_GET_PARENT = 0x2000b702
|
NS_GET_PARENT = 0x2000b702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x4004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x4004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x4004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x4004b709
|
||||||
NS_GET_USERNS = 0x2000b701
|
NS_GET_USERNS = 0x2000b701
|
||||||
OLCUC = 0x4
|
OLCUC = 0x4
|
||||||
ONLCR = 0x2
|
ONLCR = 0x2
|
||||||
|
|
|
@ -152,9 +152,14 @@ const (
|
||||||
NL3 = 0x300
|
NL3 = 0x300
|
||||||
NLDLY = 0x300
|
NLDLY = 0x300
|
||||||
NOFLSH = 0x80000000
|
NOFLSH = 0x80000000
|
||||||
|
NS_GET_MNTNS_ID = 0x4008b705
|
||||||
NS_GET_NSTYPE = 0x2000b703
|
NS_GET_NSTYPE = 0x2000b703
|
||||||
NS_GET_OWNER_UID = 0x2000b704
|
NS_GET_OWNER_UID = 0x2000b704
|
||||||
NS_GET_PARENT = 0x2000b702
|
NS_GET_PARENT = 0x2000b702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x4004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x4004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x4004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x4004b709
|
||||||
NS_GET_USERNS = 0x2000b701
|
NS_GET_USERNS = 0x2000b701
|
||||||
OLCUC = 0x4
|
OLCUC = 0x4
|
||||||
ONLCR = 0x2
|
ONLCR = 0x2
|
||||||
|
|
|
@ -150,9 +150,14 @@ const (
|
||||||
NFDBITS = 0x40
|
NFDBITS = 0x40
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x8008b705
|
||||||
NS_GET_NSTYPE = 0xb703
|
NS_GET_NSTYPE = 0xb703
|
||||||
NS_GET_OWNER_UID = 0xb704
|
NS_GET_OWNER_UID = 0xb704
|
||||||
NS_GET_PARENT = 0xb702
|
NS_GET_PARENT = 0xb702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||||
NS_GET_USERNS = 0xb701
|
NS_GET_USERNS = 0xb701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -150,9 +150,14 @@ const (
|
||||||
NFDBITS = 0x40
|
NFDBITS = 0x40
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x8008b705
|
||||||
NS_GET_NSTYPE = 0xb703
|
NS_GET_NSTYPE = 0xb703
|
||||||
NS_GET_OWNER_UID = 0xb704
|
NS_GET_OWNER_UID = 0xb704
|
||||||
NS_GET_PARENT = 0xb702
|
NS_GET_PARENT = 0xb702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x8004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x8004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x8004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x8004b709
|
||||||
NS_GET_USERNS = 0xb701
|
NS_GET_USERNS = 0xb701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -155,9 +155,14 @@ const (
|
||||||
NFDBITS = 0x40
|
NFDBITS = 0x40
|
||||||
NLDLY = 0x100
|
NLDLY = 0x100
|
||||||
NOFLSH = 0x80
|
NOFLSH = 0x80
|
||||||
|
NS_GET_MNTNS_ID = 0x4008b705
|
||||||
NS_GET_NSTYPE = 0x2000b703
|
NS_GET_NSTYPE = 0x2000b703
|
||||||
NS_GET_OWNER_UID = 0x2000b704
|
NS_GET_OWNER_UID = 0x2000b704
|
||||||
NS_GET_PARENT = 0x2000b702
|
NS_GET_PARENT = 0x2000b702
|
||||||
|
NS_GET_PID_FROM_PIDNS = 0x4004b706
|
||||||
|
NS_GET_PID_IN_PIDNS = 0x4004b708
|
||||||
|
NS_GET_TGID_FROM_PIDNS = 0x4004b707
|
||||||
|
NS_GET_TGID_IN_PIDNS = 0x4004b709
|
||||||
NS_GET_USERNS = 0x2000b701
|
NS_GET_USERNS = 0x2000b701
|
||||||
OLCUC = 0x2
|
OLCUC = 0x2
|
||||||
ONLCR = 0x4
|
ONLCR = 0x4
|
||||||
|
|
|
@ -971,23 +971,6 @@ func Getpriority(which int, who int) (prio int, err error) {
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Getrandom(buf []byte, flags int) (n int, err error) {
|
|
||||||
var _p0 unsafe.Pointer
|
|
||||||
if len(buf) > 0 {
|
|
||||||
_p0 = unsafe.Pointer(&buf[0])
|
|
||||||
} else {
|
|
||||||
_p0 = unsafe.Pointer(&_zero)
|
|
||||||
}
|
|
||||||
r0, _, e1 := Syscall(SYS_GETRANDOM, uintptr(_p0), uintptr(len(buf)), uintptr(flags))
|
|
||||||
n = int(r0)
|
|
||||||
if e1 != 0 {
|
|
||||||
err = errnoErr(e1)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
|
||||||
|
|
||||||
func Getrusage(who int, rusage *Rusage) (err error) {
|
func Getrusage(who int, rusage *Rusage) (err error) {
|
||||||
_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
|
_, _, e1 := RawSyscall(SYS_GETRUSAGE, uintptr(who), uintptr(unsafe.Pointer(rusage)), 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
|
|
|
@ -341,6 +341,7 @@ const (
|
||||||
SYS_STATX = 332
|
SYS_STATX = 332
|
||||||
SYS_IO_PGETEVENTS = 333
|
SYS_IO_PGETEVENTS = 333
|
||||||
SYS_RSEQ = 334
|
SYS_RSEQ = 334
|
||||||
|
SYS_URETPROBE = 335
|
||||||
SYS_PIDFD_SEND_SIGNAL = 424
|
SYS_PIDFD_SEND_SIGNAL = 424
|
||||||
SYS_IO_URING_SETUP = 425
|
SYS_IO_URING_SETUP = 425
|
||||||
SYS_IO_URING_ENTER = 426
|
SYS_IO_URING_ENTER = 426
|
||||||
|
|
|
@ -85,7 +85,7 @@ const (
|
||||||
SYS_SPLICE = 76
|
SYS_SPLICE = 76
|
||||||
SYS_TEE = 77
|
SYS_TEE = 77
|
||||||
SYS_READLINKAT = 78
|
SYS_READLINKAT = 78
|
||||||
SYS_FSTATAT = 79
|
SYS_NEWFSTATAT = 79
|
||||||
SYS_FSTAT = 80
|
SYS_FSTAT = 80
|
||||||
SYS_SYNC = 81
|
SYS_SYNC = 81
|
||||||
SYS_FSYNC = 82
|
SYS_FSYNC = 82
|
||||||
|
|
|
@ -84,6 +84,8 @@ const (
|
||||||
SYS_SPLICE = 76
|
SYS_SPLICE = 76
|
||||||
SYS_TEE = 77
|
SYS_TEE = 77
|
||||||
SYS_READLINKAT = 78
|
SYS_READLINKAT = 78
|
||||||
|
SYS_NEWFSTATAT = 79
|
||||||
|
SYS_FSTAT = 80
|
||||||
SYS_SYNC = 81
|
SYS_SYNC = 81
|
||||||
SYS_FSYNC = 82
|
SYS_FSYNC = 82
|
||||||
SYS_FDATASYNC = 83
|
SYS_FDATASYNC = 83
|
||||||
|
|
|
@ -84,7 +84,7 @@ const (
|
||||||
SYS_SPLICE = 76
|
SYS_SPLICE = 76
|
||||||
SYS_TEE = 77
|
SYS_TEE = 77
|
||||||
SYS_READLINKAT = 78
|
SYS_READLINKAT = 78
|
||||||
SYS_FSTATAT = 79
|
SYS_NEWFSTATAT = 79
|
||||||
SYS_FSTAT = 80
|
SYS_FSTAT = 80
|
||||||
SYS_SYNC = 81
|
SYS_SYNC = 81
|
||||||
SYS_FSYNC = 82
|
SYS_FSYNC = 82
|
||||||
|
|
|
@ -87,31 +87,35 @@ type StatxTimestamp struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Statx_t struct {
|
type Statx_t struct {
|
||||||
Mask uint32
|
Mask uint32
|
||||||
Blksize uint32
|
Blksize uint32
|
||||||
Attributes uint64
|
Attributes uint64
|
||||||
Nlink uint32
|
Nlink uint32
|
||||||
Uid uint32
|
Uid uint32
|
||||||
Gid uint32
|
Gid uint32
|
||||||
Mode uint16
|
Mode uint16
|
||||||
_ [1]uint16
|
_ [1]uint16
|
||||||
Ino uint64
|
Ino uint64
|
||||||
Size uint64
|
Size uint64
|
||||||
Blocks uint64
|
Blocks uint64
|
||||||
Attributes_mask uint64
|
Attributes_mask uint64
|
||||||
Atime StatxTimestamp
|
Atime StatxTimestamp
|
||||||
Btime StatxTimestamp
|
Btime StatxTimestamp
|
||||||
Ctime StatxTimestamp
|
Ctime StatxTimestamp
|
||||||
Mtime StatxTimestamp
|
Mtime StatxTimestamp
|
||||||
Rdev_major uint32
|
Rdev_major uint32
|
||||||
Rdev_minor uint32
|
Rdev_minor uint32
|
||||||
Dev_major uint32
|
Dev_major uint32
|
||||||
Dev_minor uint32
|
Dev_minor uint32
|
||||||
Mnt_id uint64
|
Mnt_id uint64
|
||||||
Dio_mem_align uint32
|
Dio_mem_align uint32
|
||||||
Dio_offset_align uint32
|
Dio_offset_align uint32
|
||||||
Subvol uint64
|
Subvol uint64
|
||||||
_ [11]uint64
|
Atomic_write_unit_min uint32
|
||||||
|
Atomic_write_unit_max uint32
|
||||||
|
Atomic_write_segments_max uint32
|
||||||
|
_ [1]uint32
|
||||||
|
_ [9]uint64
|
||||||
}
|
}
|
||||||
|
|
||||||
type Fsid struct {
|
type Fsid struct {
|
||||||
|
@ -516,6 +520,29 @@ type TCPInfo struct {
|
||||||
Total_rto_time uint32
|
Total_rto_time uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TCPVegasInfo struct {
|
||||||
|
Enabled uint32
|
||||||
|
Rttcnt uint32
|
||||||
|
Rtt uint32
|
||||||
|
Minrtt uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type TCPDCTCPInfo struct {
|
||||||
|
Enabled uint16
|
||||||
|
Ce_state uint16
|
||||||
|
Alpha uint32
|
||||||
|
Ab_ecn uint32
|
||||||
|
Ab_tot uint32
|
||||||
|
}
|
||||||
|
|
||||||
|
type TCPBBRInfo struct {
|
||||||
|
Bw_lo uint32
|
||||||
|
Bw_hi uint32
|
||||||
|
Min_rtt uint32
|
||||||
|
Pacing_gain uint32
|
||||||
|
Cwnd_gain uint32
|
||||||
|
}
|
||||||
|
|
||||||
type CanFilter struct {
|
type CanFilter struct {
|
||||||
Id uint32
|
Id uint32
|
||||||
Mask uint32
|
Mask uint32
|
||||||
|
@ -557,6 +584,7 @@ const (
|
||||||
SizeofICMPv6Filter = 0x20
|
SizeofICMPv6Filter = 0x20
|
||||||
SizeofUcred = 0xc
|
SizeofUcred = 0xc
|
||||||
SizeofTCPInfo = 0xf8
|
SizeofTCPInfo = 0xf8
|
||||||
|
SizeofTCPCCInfo = 0x14
|
||||||
SizeofCanFilter = 0x8
|
SizeofCanFilter = 0x8
|
||||||
SizeofTCPRepairOpt = 0x8
|
SizeofTCPRepairOpt = 0x8
|
||||||
)
|
)
|
||||||
|
@ -3766,7 +3794,7 @@ const (
|
||||||
ETHTOOL_MSG_PSE_GET = 0x24
|
ETHTOOL_MSG_PSE_GET = 0x24
|
||||||
ETHTOOL_MSG_PSE_SET = 0x25
|
ETHTOOL_MSG_PSE_SET = 0x25
|
||||||
ETHTOOL_MSG_RSS_GET = 0x26
|
ETHTOOL_MSG_RSS_GET = 0x26
|
||||||
ETHTOOL_MSG_USER_MAX = 0x2b
|
ETHTOOL_MSG_USER_MAX = 0x2c
|
||||||
ETHTOOL_MSG_KERNEL_NONE = 0x0
|
ETHTOOL_MSG_KERNEL_NONE = 0x0
|
||||||
ETHTOOL_MSG_STRSET_GET_REPLY = 0x1
|
ETHTOOL_MSG_STRSET_GET_REPLY = 0x1
|
||||||
ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2
|
ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2
|
||||||
|
@ -3806,7 +3834,7 @@ const (
|
||||||
ETHTOOL_MSG_MODULE_NTF = 0x24
|
ETHTOOL_MSG_MODULE_NTF = 0x24
|
||||||
ETHTOOL_MSG_PSE_GET_REPLY = 0x25
|
ETHTOOL_MSG_PSE_GET_REPLY = 0x25
|
||||||
ETHTOOL_MSG_RSS_GET_REPLY = 0x26
|
ETHTOOL_MSG_RSS_GET_REPLY = 0x26
|
||||||
ETHTOOL_MSG_KERNEL_MAX = 0x2b
|
ETHTOOL_MSG_KERNEL_MAX = 0x2c
|
||||||
ETHTOOL_FLAG_COMPACT_BITSETS = 0x1
|
ETHTOOL_FLAG_COMPACT_BITSETS = 0x1
|
||||||
ETHTOOL_FLAG_OMIT_REPLY = 0x2
|
ETHTOOL_FLAG_OMIT_REPLY = 0x2
|
||||||
ETHTOOL_FLAG_STATS = 0x4
|
ETHTOOL_FLAG_STATS = 0x4
|
||||||
|
@ -3951,7 +3979,7 @@ const (
|
||||||
ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL = 0x17
|
ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL = 0x17
|
||||||
ETHTOOL_A_COALESCE_USE_CQE_MODE_TX = 0x18
|
ETHTOOL_A_COALESCE_USE_CQE_MODE_TX = 0x18
|
||||||
ETHTOOL_A_COALESCE_USE_CQE_MODE_RX = 0x19
|
ETHTOOL_A_COALESCE_USE_CQE_MODE_RX = 0x19
|
||||||
ETHTOOL_A_COALESCE_MAX = 0x1c
|
ETHTOOL_A_COALESCE_MAX = 0x1e
|
||||||
ETHTOOL_A_PAUSE_UNSPEC = 0x0
|
ETHTOOL_A_PAUSE_UNSPEC = 0x0
|
||||||
ETHTOOL_A_PAUSE_HEADER = 0x1
|
ETHTOOL_A_PAUSE_HEADER = 0x1
|
||||||
ETHTOOL_A_PAUSE_AUTONEG = 0x2
|
ETHTOOL_A_PAUSE_AUTONEG = 0x2
|
||||||
|
@ -4609,7 +4637,7 @@ const (
|
||||||
NL80211_ATTR_MAC_HINT = 0xc8
|
NL80211_ATTR_MAC_HINT = 0xc8
|
||||||
NL80211_ATTR_MAC_MASK = 0xd7
|
NL80211_ATTR_MAC_MASK = 0xd7
|
||||||
NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca
|
NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca
|
||||||
NL80211_ATTR_MAX = 0x14a
|
NL80211_ATTR_MAX = 0x14c
|
||||||
NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4
|
NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4
|
||||||
NL80211_ATTR_MAX_CSA_COUNTERS = 0xce
|
NL80211_ATTR_MAX_CSA_COUNTERS = 0xce
|
||||||
NL80211_ATTR_MAX_MATCH_SETS = 0x85
|
NL80211_ATTR_MAX_MATCH_SETS = 0x85
|
||||||
|
@ -5213,7 +5241,7 @@ const (
|
||||||
NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf
|
NL80211_FREQUENCY_ATTR_GO_CONCURRENT = 0xf
|
||||||
NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe
|
NL80211_FREQUENCY_ATTR_INDOOR_ONLY = 0xe
|
||||||
NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf
|
NL80211_FREQUENCY_ATTR_IR_CONCURRENT = 0xf
|
||||||
NL80211_FREQUENCY_ATTR_MAX = 0x20
|
NL80211_FREQUENCY_ATTR_MAX = 0x21
|
||||||
NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6
|
NL80211_FREQUENCY_ATTR_MAX_TX_POWER = 0x6
|
||||||
NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11
|
NL80211_FREQUENCY_ATTR_NO_10MHZ = 0x11
|
||||||
NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc
|
NL80211_FREQUENCY_ATTR_NO_160MHZ = 0xc
|
||||||
|
|
|
@ -65,7 +65,7 @@ func LoadDLL(name string) (dll *DLL, err error) {
|
||||||
return d, nil
|
return d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// MustLoadDLL is like LoadDLL but panics if load operation failes.
|
// MustLoadDLL is like LoadDLL but panics if load operation fails.
|
||||||
func MustLoadDLL(name string) *DLL {
|
func MustLoadDLL(name string) *DLL {
|
||||||
d, e := LoadDLL(name)
|
d, e := LoadDLL(name)
|
||||||
if e != nil {
|
if e != nil {
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
// 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:debug gotypesalias=0
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -7,13 +7,5 @@ package astutil
|
||||||
import "go/ast"
|
import "go/ast"
|
||||||
|
|
||||||
// Unparen returns e with any enclosing parentheses stripped.
|
// Unparen returns e with any enclosing parentheses stripped.
|
||||||
// TODO(adonovan): use go1.22's ast.Unparen.
|
// Deprecated: use [ast.Unparen].
|
||||||
func Unparen(e ast.Expr) ast.Expr {
|
func Unparen(e ast.Expr) ast.Expr { return ast.Unparen(e) }
|
||||||
for {
|
|
||||||
p, ok := e.(*ast.ParenExpr)
|
|
||||||
if !ok {
|
|
||||||
return e
|
|
||||||
}
|
|
||||||
e = p.X
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -73,6 +73,15 @@ func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) {
|
||||||
// check, Preorder is almost twice as fast as Nodes. The two
|
// check, Preorder is almost twice as fast as Nodes. The two
|
||||||
// features seem to contribute similar slowdowns (~1.4x each).
|
// features seem to contribute similar slowdowns (~1.4x each).
|
||||||
|
|
||||||
|
// This function is equivalent to the PreorderSeq call below,
|
||||||
|
// but to avoid the additional dynamic call (which adds 13-35%
|
||||||
|
// to the benchmarks), we expand it out.
|
||||||
|
//
|
||||||
|
// in.PreorderSeq(types...)(func(n ast.Node) bool {
|
||||||
|
// f(n)
|
||||||
|
// return true
|
||||||
|
// })
|
||||||
|
|
||||||
mask := maskOf(types)
|
mask := maskOf(types)
|
||||||
for i := 0; i < len(in.events); {
|
for i := 0; i < len(in.events); {
|
||||||
ev := in.events[i]
|
ev := in.events[i]
|
||||||
|
|
|
@ -0,0 +1,85 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
//go:build go1.23
|
||||||
|
|
||||||
|
package inspector
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"iter"
|
||||||
|
)
|
||||||
|
|
||||||
|
// PreorderSeq returns an iterator that visits all the
|
||||||
|
// nodes of the files supplied to New in depth-first order.
|
||||||
|
// It visits each node n before n's children.
|
||||||
|
// The complete traversal sequence is determined by ast.Inspect.
|
||||||
|
//
|
||||||
|
// The types argument, if non-empty, enables type-based
|
||||||
|
// filtering of events: only nodes whose type matches an
|
||||||
|
// element of the types slice are included in the sequence.
|
||||||
|
func (in *Inspector) PreorderSeq(types ...ast.Node) iter.Seq[ast.Node] {
|
||||||
|
|
||||||
|
// This implementation is identical to Preorder,
|
||||||
|
// except that it supports breaking out of the loop.
|
||||||
|
|
||||||
|
return func(yield func(ast.Node) bool) {
|
||||||
|
mask := maskOf(types)
|
||||||
|
for i := 0; i < len(in.events); {
|
||||||
|
ev := in.events[i]
|
||||||
|
if ev.index > i {
|
||||||
|
// push
|
||||||
|
if ev.typ&mask != 0 {
|
||||||
|
if !yield(ev.node) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pop := ev.index
|
||||||
|
if in.events[pop].typ&mask == 0 {
|
||||||
|
// Subtrees do not contain types: skip them and pop.
|
||||||
|
i = pop + 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// All[N] returns an iterator over all the nodes of type N.
|
||||||
|
// N must be a pointer-to-struct type that implements ast.Node.
|
||||||
|
//
|
||||||
|
// Example:
|
||||||
|
//
|
||||||
|
// for call := range All[*ast.CallExpr](in) { ... }
|
||||||
|
func All[N interface {
|
||||||
|
*S
|
||||||
|
ast.Node
|
||||||
|
}, S any](in *Inspector) iter.Seq[N] {
|
||||||
|
|
||||||
|
// To avoid additional dynamic call overheads,
|
||||||
|
// we duplicate rather than call the logic of PreorderSeq.
|
||||||
|
|
||||||
|
mask := typeOf((N)(nil))
|
||||||
|
return func(yield func(N) bool) {
|
||||||
|
for i := 0; i < len(in.events); {
|
||||||
|
ev := in.events[i]
|
||||||
|
if ev.index > i {
|
||||||
|
// push
|
||||||
|
if ev.typ&mask != 0 {
|
||||||
|
if !yield(ev.node.(N)) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pop := ev.index
|
||||||
|
if in.events[pop].typ&mask == 0 {
|
||||||
|
// Subtrees do not contain types: skip them and pop.
|
||||||
|
i = pop + 1
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -64,7 +64,7 @@ graph using the Imports fields.
|
||||||
|
|
||||||
The Load function can be configured by passing a pointer to a Config as
|
The Load function can be configured by passing a pointer to a Config as
|
||||||
the first argument. A nil Config is equivalent to the zero Config, which
|
the first argument. A nil Config is equivalent to the zero Config, which
|
||||||
causes Load to run in LoadFiles mode, collecting minimal information.
|
causes Load to run in [LoadFiles] mode, collecting minimal information.
|
||||||
See the documentation for type Config for details.
|
See the documentation for type Config for details.
|
||||||
|
|
||||||
As noted earlier, the Config.Mode controls the amount of detail
|
As noted earlier, the Config.Mode controls the amount of detail
|
||||||
|
@ -72,14 +72,14 @@ reported about the loaded packages. See the documentation for type LoadMode
|
||||||
for details.
|
for details.
|
||||||
|
|
||||||
Most tools should pass their command-line arguments (after any flags)
|
Most tools should pass their command-line arguments (after any flags)
|
||||||
uninterpreted to [Load], so that it can interpret them
|
uninterpreted to Load, so that it can interpret them
|
||||||
according to the conventions of the underlying build system.
|
according to the conventions of the underlying build system.
|
||||||
|
|
||||||
See the Example function for typical usage.
|
See the Example function for typical usage.
|
||||||
|
|
||||||
# The driver protocol
|
# The driver protocol
|
||||||
|
|
||||||
[Load] may be used to load Go packages even in Go projects that use
|
Load may be used to load Go packages even in Go projects that use
|
||||||
alternative build systems, by installing an appropriate "driver"
|
alternative build systems, by installing an appropriate "driver"
|
||||||
program for the build system and specifying its location in the
|
program for the build system and specifying its location in the
|
||||||
GOPACKAGESDRIVER environment variable.
|
GOPACKAGESDRIVER environment variable.
|
||||||
|
@ -97,6 +97,15 @@ JSON-encoded [DriverRequest] message providing additional information
|
||||||
is written to the driver's standard input. The driver must write a
|
is written to the driver's standard input. The driver must write a
|
||||||
JSON-encoded [DriverResponse] message to its standard output. (This
|
JSON-encoded [DriverResponse] message to its standard output. (This
|
||||||
message differs from the JSON schema produced by 'go list'.)
|
message differs from the JSON schema produced by 'go list'.)
|
||||||
|
|
||||||
|
The value of the PWD environment variable seen by the driver process
|
||||||
|
is the preferred name of its working directory. (The working directory
|
||||||
|
may have other aliases due to symbolic links; see the comment on the
|
||||||
|
Dir field of [exec.Cmd] for related information.)
|
||||||
|
When the driver process emits in its response the name of a file
|
||||||
|
that is a descendant of this directory, it must use an absolute path
|
||||||
|
that has the value of PWD as a prefix, to ensure that the returned
|
||||||
|
filenames satisfy the original query.
|
||||||
*/
|
*/
|
||||||
package packages // import "golang.org/x/tools/go/packages"
|
package packages // import "golang.org/x/tools/go/packages"
|
||||||
|
|
||||||
|
|
|
@ -9,49 +9,46 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
var allModes = []LoadMode{
|
var modes = [...]struct {
|
||||||
NeedName,
|
mode LoadMode
|
||||||
NeedFiles,
|
name string
|
||||||
NeedCompiledGoFiles,
|
}{
|
||||||
NeedImports,
|
{NeedName, "NeedName"},
|
||||||
NeedDeps,
|
{NeedFiles, "NeedFiles"},
|
||||||
NeedExportFile,
|
{NeedCompiledGoFiles, "NeedCompiledGoFiles"},
|
||||||
NeedTypes,
|
{NeedImports, "NeedImports"},
|
||||||
NeedSyntax,
|
{NeedDeps, "NeedDeps"},
|
||||||
NeedTypesInfo,
|
{NeedExportFile, "NeedExportFile"},
|
||||||
NeedTypesSizes,
|
{NeedTypes, "NeedTypes"},
|
||||||
|
{NeedSyntax, "NeedSyntax"},
|
||||||
|
{NeedTypesInfo, "NeedTypesInfo"},
|
||||||
|
{NeedTypesSizes, "NeedTypesSizes"},
|
||||||
|
{NeedModule, "NeedModule"},
|
||||||
|
{NeedEmbedFiles, "NeedEmbedFiles"},
|
||||||
|
{NeedEmbedPatterns, "NeedEmbedPatterns"},
|
||||||
}
|
}
|
||||||
|
|
||||||
var modeStrings = []string{
|
func (mode LoadMode) String() string {
|
||||||
"NeedName",
|
if mode == 0 {
|
||||||
"NeedFiles",
|
|
||||||
"NeedCompiledGoFiles",
|
|
||||||
"NeedImports",
|
|
||||||
"NeedDeps",
|
|
||||||
"NeedExportFile",
|
|
||||||
"NeedTypes",
|
|
||||||
"NeedSyntax",
|
|
||||||
"NeedTypesInfo",
|
|
||||||
"NeedTypesSizes",
|
|
||||||
}
|
|
||||||
|
|
||||||
func (mod LoadMode) String() string {
|
|
||||||
m := mod
|
|
||||||
if m == 0 {
|
|
||||||
return "LoadMode(0)"
|
return "LoadMode(0)"
|
||||||
}
|
}
|
||||||
var out []string
|
var out []string
|
||||||
for i, x := range allModes {
|
// named bits
|
||||||
if x > m {
|
for _, item := range modes {
|
||||||
break
|
if (mode & item.mode) != 0 {
|
||||||
}
|
mode ^= item.mode
|
||||||
if (m & x) != 0 {
|
out = append(out, item.name)
|
||||||
out = append(out, modeStrings[i])
|
|
||||||
m = m ^ x
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if m != 0 {
|
// unnamed residue
|
||||||
out = append(out, "Unknown")
|
if mode != 0 {
|
||||||
|
if out == nil {
|
||||||
|
return fmt.Sprintf("LoadMode(%#x)", int(mode))
|
||||||
|
}
|
||||||
|
out = append(out, fmt.Sprintf("%#x", int(mode)))
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("LoadMode(%s)", strings.Join(out, "|"))
|
if len(out) == 1 {
|
||||||
|
return out[0]
|
||||||
|
}
|
||||||
|
return "(" + strings.Join(out, "|") + ")"
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,10 +46,10 @@ import (
|
||||||
//
|
//
|
||||||
// Unfortunately there are a number of open bugs related to
|
// Unfortunately there are a number of open bugs related to
|
||||||
// interactions among the LoadMode bits:
|
// interactions among the LoadMode bits:
|
||||||
// - https://github.com/golang/go/issues/56633
|
// - https://github.com/golang/go/issues/56633
|
||||||
// - https://github.com/golang/go/issues/56677
|
// - https://github.com/golang/go/issues/56677
|
||||||
// - https://github.com/golang/go/issues/58726
|
// - https://github.com/golang/go/issues/58726
|
||||||
// - https://github.com/golang/go/issues/63517
|
// - https://github.com/golang/go/issues/63517
|
||||||
type LoadMode int
|
type LoadMode int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -103,25 +103,37 @@ const (
|
||||||
|
|
||||||
// NeedEmbedPatterns adds EmbedPatterns.
|
// NeedEmbedPatterns adds EmbedPatterns.
|
||||||
NeedEmbedPatterns
|
NeedEmbedPatterns
|
||||||
|
|
||||||
|
// Be sure to update loadmode_string.go when adding new items!
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
// LoadFiles loads the name and file names for the initial packages.
|
||||||
|
//
|
||||||
// Deprecated: LoadFiles exists for historical compatibility
|
// Deprecated: LoadFiles exists for historical compatibility
|
||||||
// and should not be used. Please directly specify the needed fields using the Need values.
|
// and should not be used. Please directly specify the needed fields using the Need values.
|
||||||
LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles
|
LoadFiles = NeedName | NeedFiles | NeedCompiledGoFiles
|
||||||
|
|
||||||
|
// LoadImports loads the name, file names, and import mapping for the initial packages.
|
||||||
|
//
|
||||||
// Deprecated: LoadImports exists for historical compatibility
|
// Deprecated: LoadImports exists for historical compatibility
|
||||||
// and should not be used. Please directly specify the needed fields using the Need values.
|
// and should not be used. Please directly specify the needed fields using the Need values.
|
||||||
LoadImports = LoadFiles | NeedImports
|
LoadImports = LoadFiles | NeedImports
|
||||||
|
|
||||||
|
// LoadTypes loads exported type information for the initial packages.
|
||||||
|
//
|
||||||
// Deprecated: LoadTypes exists for historical compatibility
|
// Deprecated: LoadTypes exists for historical compatibility
|
||||||
// and should not be used. Please directly specify the needed fields using the Need values.
|
// and should not be used. Please directly specify the needed fields using the Need values.
|
||||||
LoadTypes = LoadImports | NeedTypes | NeedTypesSizes
|
LoadTypes = LoadImports | NeedTypes | NeedTypesSizes
|
||||||
|
|
||||||
|
// LoadSyntax loads typed syntax for the initial packages.
|
||||||
|
//
|
||||||
// Deprecated: LoadSyntax exists for historical compatibility
|
// Deprecated: LoadSyntax exists for historical compatibility
|
||||||
// and should not be used. Please directly specify the needed fields using the Need values.
|
// and should not be used. Please directly specify the needed fields using the Need values.
|
||||||
LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo
|
LoadSyntax = LoadTypes | NeedSyntax | NeedTypesInfo
|
||||||
|
|
||||||
|
// LoadAllSyntax loads typed syntax for the initial packages and all dependencies.
|
||||||
|
//
|
||||||
// Deprecated: LoadAllSyntax exists for historical compatibility
|
// Deprecated: LoadAllSyntax exists for historical compatibility
|
||||||
// and should not be used. Please directly specify the needed fields using the Need values.
|
// and should not be used. Please directly specify the needed fields using the Need values.
|
||||||
LoadAllSyntax = LoadSyntax | NeedDeps
|
LoadAllSyntax = LoadSyntax | NeedDeps
|
||||||
|
@ -236,14 +248,13 @@ type Config struct {
|
||||||
|
|
||||||
// Load loads and returns the Go packages named by the given patterns.
|
// Load loads and returns the Go packages named by the given patterns.
|
||||||
//
|
//
|
||||||
// Config specifies loading options;
|
// The cfg parameter specifies loading options; nil behaves the same as an empty [Config].
|
||||||
// nil behaves the same as an empty Config.
|
|
||||||
//
|
//
|
||||||
// The [Config.Mode] field is a set of bits that determine what kinds
|
// The [Config.Mode] field is a set of bits that determine what kinds
|
||||||
// of information should be computed and returned. Modes that require
|
// of information should be computed and returned. Modes that require
|
||||||
// more information tend to be slower. See [LoadMode] for details
|
// more information tend to be slower. See [LoadMode] for details
|
||||||
// and important caveats. Its zero value is equivalent to
|
// and important caveats. Its zero value is equivalent to
|
||||||
// NeedName | NeedFiles | NeedCompiledGoFiles.
|
// [NeedName] | [NeedFiles] | [NeedCompiledGoFiles].
|
||||||
//
|
//
|
||||||
// Each call to Load returns a new set of [Package] instances.
|
// Each call to Load returns a new set of [Package] instances.
|
||||||
// The Packages and their Imports form a directed acyclic graph.
|
// The Packages and their Imports form a directed acyclic graph.
|
||||||
|
@ -260,7 +271,7 @@ type Config struct {
|
||||||
// Errors associated with a particular package are recorded in the
|
// Errors associated with a particular package are recorded in the
|
||||||
// corresponding Package's Errors list, and do not cause Load to
|
// corresponding Package's Errors list, and do not cause Load to
|
||||||
// return an error. Clients may need to handle such errors before
|
// return an error. Clients may need to handle such errors before
|
||||||
// proceeding with further analysis. The PrintErrors function is
|
// proceeding with further analysis. The [PrintErrors] function is
|
||||||
// provided for convenient display of all errors.
|
// provided for convenient display of all errors.
|
||||||
func Load(cfg *Config, patterns ...string) ([]*Package, error) {
|
func Load(cfg *Config, patterns ...string) ([]*Package, error) {
|
||||||
ld := newLoader(cfg)
|
ld := newLoader(cfg)
|
||||||
|
@ -763,6 +774,7 @@ func newLoader(cfg *Config) *loader {
|
||||||
// because we load source if export data is missing.
|
// because we load source if export data is missing.
|
||||||
if ld.ParseFile == nil {
|
if ld.ParseFile == nil {
|
||||||
ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
|
ld.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
|
||||||
|
// We implicitly promise to keep doing ast.Object resolution. :(
|
||||||
const mode = parser.AllErrors | parser.ParseComments
|
const mode = parser.AllErrors | parser.ParseComments
|
||||||
return parser.ParseFile(fset, filename, src, mode)
|
return parser.ParseFile(fset, filename, src, mode)
|
||||||
}
|
}
|
||||||
|
|
|
@ -228,7 +228,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
|
||||||
// Reject obviously non-viable cases.
|
// Reject obviously non-viable cases.
|
||||||
switch obj := obj.(type) {
|
switch obj := obj.(type) {
|
||||||
case *types.TypeName:
|
case *types.TypeName:
|
||||||
if _, ok := aliases.Unalias(obj.Type()).(*types.TypeParam); !ok {
|
if _, ok := types.Unalias(obj.Type()).(*types.TypeParam); !ok {
|
||||||
// With the exception of type parameters, only package-level type names
|
// With the exception of type parameters, only package-level type names
|
||||||
// have a path.
|
// have a path.
|
||||||
return "", fmt.Errorf("no path for %v", obj)
|
return "", fmt.Errorf("no path for %v", obj)
|
||||||
|
@ -280,7 +280,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
|
||||||
path = append(path, opType)
|
path = append(path, opType)
|
||||||
|
|
||||||
T := o.Type()
|
T := o.Type()
|
||||||
if alias, ok := T.(*aliases.Alias); ok {
|
if alias, ok := T.(*types.Alias); ok {
|
||||||
if r := findTypeParam(obj, aliases.TypeParams(alias), path, opTypeParam, nil); r != nil {
|
if r := findTypeParam(obj, aliases.TypeParams(alias), path, opTypeParam, nil); r != nil {
|
||||||
return Path(r), nil
|
return Path(r), nil
|
||||||
}
|
}
|
||||||
|
@ -320,7 +320,7 @@ func (enc *Encoder) For(obj types.Object) (Path, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inspect declared methods of defined types.
|
// Inspect declared methods of defined types.
|
||||||
if T, ok := aliases.Unalias(o.Type()).(*types.Named); ok {
|
if T, ok := types.Unalias(o.Type()).(*types.Named); ok {
|
||||||
path = append(path, opType)
|
path = append(path, opType)
|
||||||
// The method index here is always with respect
|
// The method index here is always with respect
|
||||||
// to the underlying go/types data structures,
|
// to the underlying go/types data structures,
|
||||||
|
@ -449,8 +449,8 @@ func (enc *Encoder) concreteMethod(meth *types.Func) (Path, bool) {
|
||||||
// nil, it will be allocated as necessary.
|
// nil, it will be allocated as necessary.
|
||||||
func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte {
|
func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte {
|
||||||
switch T := T.(type) {
|
switch T := T.(type) {
|
||||||
case *aliases.Alias:
|
case *types.Alias:
|
||||||
return find(obj, aliases.Unalias(T), path, seen)
|
return find(obj, types.Unalias(T), path, seen)
|
||||||
case *types.Basic, *types.Named:
|
case *types.Basic, *types.Named:
|
||||||
// Named types belonging to pkg were handled already,
|
// Named types belonging to pkg were handled already,
|
||||||
// so T must belong to another package. No path.
|
// so T must belong to another package. No path.
|
||||||
|
@ -626,7 +626,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
|
||||||
|
|
||||||
// Inv: t != nil, obj == nil
|
// Inv: t != nil, obj == nil
|
||||||
|
|
||||||
t = aliases.Unalias(t)
|
t = types.Unalias(t)
|
||||||
switch code {
|
switch code {
|
||||||
case opElem:
|
case opElem:
|
||||||
hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map
|
hasElem, ok := t.(hasElem) // Pointer, Slice, Array, Chan, Map
|
||||||
|
@ -664,7 +664,7 @@ func Object(pkg *types.Package, p Path) (types.Object, error) {
|
||||||
t = named.Underlying()
|
t = named.Underlying()
|
||||||
|
|
||||||
case opRhs:
|
case opRhs:
|
||||||
if alias, ok := t.(*aliases.Alias); ok {
|
if alias, ok := t.(*types.Alias); ok {
|
||||||
t = aliases.Rhs(alias)
|
t = aliases.Rhs(alias)
|
||||||
} else if false && aliases.Enabled() {
|
} else if false && aliases.Enabled() {
|
||||||
// The Enabled check is too expensive, so for now we
|
// The Enabled check is too expensive, so for now we
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
// Copyright 2018 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 typeutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/types"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/typeparams"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Callee returns the named target of a function call, if any:
|
||||||
|
// a function, method, builtin, or variable.
|
||||||
|
//
|
||||||
|
// Functions and methods may potentially have type parameters.
|
||||||
|
func Callee(info *types.Info, call *ast.CallExpr) types.Object {
|
||||||
|
fun := ast.Unparen(call.Fun)
|
||||||
|
|
||||||
|
// Look through type instantiation if necessary.
|
||||||
|
isInstance := false
|
||||||
|
switch fun.(type) {
|
||||||
|
case *ast.IndexExpr, *ast.IndexListExpr:
|
||||||
|
// When extracting the callee from an *IndexExpr, we need to check that
|
||||||
|
// it is a *types.Func and not a *types.Var.
|
||||||
|
// Example: Don't match a slice m within the expression `m[0]()`.
|
||||||
|
isInstance = true
|
||||||
|
fun, _, _, _ = typeparams.UnpackIndexExpr(fun)
|
||||||
|
}
|
||||||
|
|
||||||
|
var obj types.Object
|
||||||
|
switch fun := fun.(type) {
|
||||||
|
case *ast.Ident:
|
||||||
|
obj = info.Uses[fun] // type, var, builtin, or declared func
|
||||||
|
case *ast.SelectorExpr:
|
||||||
|
if sel, ok := info.Selections[fun]; ok {
|
||||||
|
obj = sel.Obj() // method or field
|
||||||
|
} else {
|
||||||
|
obj = info.Uses[fun.Sel] // qualified identifier?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, ok := obj.(*types.TypeName); ok {
|
||||||
|
return nil // T(x) is a conversion, not a call
|
||||||
|
}
|
||||||
|
// A Func is required to match instantiations.
|
||||||
|
if _, ok := obj.(*types.Func); isInstance && !ok {
|
||||||
|
return nil // Was not a Func.
|
||||||
|
}
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
// StaticCallee returns the target (function or method) of a static function
|
||||||
|
// call, if any. It returns nil for calls to builtins.
|
||||||
|
//
|
||||||
|
// Note: for calls of instantiated functions and methods, StaticCallee returns
|
||||||
|
// the corresponding generic function or method on the generic type.
|
||||||
|
func StaticCallee(info *types.Info, call *ast.CallExpr) *types.Func {
|
||||||
|
if f, ok := Callee(info, call).(*types.Func); ok && !interfaceMethod(f) {
|
||||||
|
return f
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func interfaceMethod(f *types.Func) bool {
|
||||||
|
recv := f.Type().(*types.Signature).Recv()
|
||||||
|
return recv != nil && types.IsInterface(recv.Type())
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
// Copyright 2014 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 typeutil
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
// Dependencies returns all dependencies of the specified packages.
|
||||||
|
//
|
||||||
|
// Dependent packages appear in topological order: if package P imports
|
||||||
|
// package Q, Q appears earlier than P in the result.
|
||||||
|
// The algorithm follows import statements in the order they
|
||||||
|
// appear in the source code, so the result is a total order.
|
||||||
|
func Dependencies(pkgs ...*types.Package) []*types.Package {
|
||||||
|
var result []*types.Package
|
||||||
|
seen := make(map[*types.Package]bool)
|
||||||
|
var visit func(pkgs []*types.Package)
|
||||||
|
visit = func(pkgs []*types.Package) {
|
||||||
|
for _, p := range pkgs {
|
||||||
|
if !seen[p] {
|
||||||
|
seen[p] = true
|
||||||
|
visit(p.Imports())
|
||||||
|
result = append(result, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visit(pkgs)
|
||||||
|
return result
|
||||||
|
}
|
|
@ -0,0 +1,517 @@
|
||||||
|
// Copyright 2014 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 typeutil defines various utilities for types, such as Map,
|
||||||
|
// a mapping from types.Type to any values.
|
||||||
|
package typeutil // import "golang.org/x/tools/go/types/typeutil"
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
"golang.org/x/tools/internal/typeparams"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Map is a hash-table-based mapping from types (types.Type) to
|
||||||
|
// arbitrary any values. The concrete types that implement
|
||||||
|
// the Type interface are pointers. Since they are not canonicalized,
|
||||||
|
// == cannot be used to check for equivalence, and thus we cannot
|
||||||
|
// simply use a Go map.
|
||||||
|
//
|
||||||
|
// Just as with map[K]V, a nil *Map is a valid empty map.
|
||||||
|
//
|
||||||
|
// Not thread-safe.
|
||||||
|
type Map struct {
|
||||||
|
hasher Hasher // shared by many Maps
|
||||||
|
table map[uint32][]entry // maps hash to bucket; entry.key==nil means unused
|
||||||
|
length int // number of map entries
|
||||||
|
}
|
||||||
|
|
||||||
|
// entry is an entry (key/value association) in a hash bucket.
|
||||||
|
type entry struct {
|
||||||
|
key types.Type
|
||||||
|
value any
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetHasher sets the hasher used by Map.
|
||||||
|
//
|
||||||
|
// All Hashers are functionally equivalent but contain internal state
|
||||||
|
// used to cache the results of hashing previously seen types.
|
||||||
|
//
|
||||||
|
// A single Hasher created by MakeHasher() may be shared among many
|
||||||
|
// Maps. This is recommended if the instances have many keys in
|
||||||
|
// common, as it will amortize the cost of hash computation.
|
||||||
|
//
|
||||||
|
// A Hasher may grow without bound as new types are seen. Even when a
|
||||||
|
// type is deleted from the map, the Hasher never shrinks, since other
|
||||||
|
// types in the map may reference the deleted type indirectly.
|
||||||
|
//
|
||||||
|
// Hashers are not thread-safe, and read-only operations such as
|
||||||
|
// Map.Lookup require updates to the hasher, so a full Mutex lock (not a
|
||||||
|
// read-lock) is require around all Map operations if a shared
|
||||||
|
// hasher is accessed from multiple threads.
|
||||||
|
//
|
||||||
|
// If SetHasher is not called, the Map will create a private hasher at
|
||||||
|
// the first call to Insert.
|
||||||
|
func (m *Map) SetHasher(hasher Hasher) {
|
||||||
|
m.hasher = hasher
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete removes the entry with the given key, if any.
|
||||||
|
// It returns true if the entry was found.
|
||||||
|
func (m *Map) Delete(key types.Type) bool {
|
||||||
|
if m != nil && m.table != nil {
|
||||||
|
hash := m.hasher.Hash(key)
|
||||||
|
bucket := m.table[hash]
|
||||||
|
for i, e := range bucket {
|
||||||
|
if e.key != nil && types.Identical(key, e.key) {
|
||||||
|
// We can't compact the bucket as it
|
||||||
|
// would disturb iterators.
|
||||||
|
bucket[i] = entry{}
|
||||||
|
m.length--
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// At returns the map entry for the given key.
|
||||||
|
// The result is nil if the entry is not present.
|
||||||
|
func (m *Map) At(key types.Type) any {
|
||||||
|
if m != nil && m.table != nil {
|
||||||
|
for _, e := range m.table[m.hasher.Hash(key)] {
|
||||||
|
if e.key != nil && types.Identical(key, e.key) {
|
||||||
|
return e.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set sets the map entry for key to val,
|
||||||
|
// and returns the previous entry, if any.
|
||||||
|
func (m *Map) Set(key types.Type, value any) (prev any) {
|
||||||
|
if m.table != nil {
|
||||||
|
hash := m.hasher.Hash(key)
|
||||||
|
bucket := m.table[hash]
|
||||||
|
var hole *entry
|
||||||
|
for i, e := range bucket {
|
||||||
|
if e.key == nil {
|
||||||
|
hole = &bucket[i]
|
||||||
|
} else if types.Identical(key, e.key) {
|
||||||
|
prev = e.value
|
||||||
|
bucket[i].value = value
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if hole != nil {
|
||||||
|
*hole = entry{key, value} // overwrite deleted entry
|
||||||
|
} else {
|
||||||
|
m.table[hash] = append(bucket, entry{key, value})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if m.hasher.memo == nil {
|
||||||
|
m.hasher = MakeHasher()
|
||||||
|
}
|
||||||
|
hash := m.hasher.Hash(key)
|
||||||
|
m.table = map[uint32][]entry{hash: {entry{key, value}}}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.length++
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Len returns the number of map entries.
|
||||||
|
func (m *Map) Len() int {
|
||||||
|
if m != nil {
|
||||||
|
return m.length
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate calls function f on each entry in the map in unspecified order.
|
||||||
|
//
|
||||||
|
// If f should mutate the map, Iterate provides the same guarantees as
|
||||||
|
// Go maps: if f deletes a map entry that Iterate has not yet reached,
|
||||||
|
// f will not be invoked for it, but if f inserts a map entry that
|
||||||
|
// Iterate has not yet reached, whether or not f will be invoked for
|
||||||
|
// it is unspecified.
|
||||||
|
func (m *Map) Iterate(f func(key types.Type, value any)) {
|
||||||
|
if m != nil {
|
||||||
|
for _, bucket := range m.table {
|
||||||
|
for _, e := range bucket {
|
||||||
|
if e.key != nil {
|
||||||
|
f(e.key, e.value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keys returns a new slice containing the set of map keys.
|
||||||
|
// The order is unspecified.
|
||||||
|
func (m *Map) Keys() []types.Type {
|
||||||
|
keys := make([]types.Type, 0, m.Len())
|
||||||
|
m.Iterate(func(key types.Type, _ any) {
|
||||||
|
keys = append(keys, key)
|
||||||
|
})
|
||||||
|
return keys
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Map) toString(values bool) string {
|
||||||
|
if m == nil {
|
||||||
|
return "{}"
|
||||||
|
}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
fmt.Fprint(&buf, "{")
|
||||||
|
sep := ""
|
||||||
|
m.Iterate(func(key types.Type, value any) {
|
||||||
|
fmt.Fprint(&buf, sep)
|
||||||
|
sep = ", "
|
||||||
|
fmt.Fprint(&buf, key)
|
||||||
|
if values {
|
||||||
|
fmt.Fprintf(&buf, ": %q", value)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
fmt.Fprint(&buf, "}")
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// String returns a string representation of the map's entries.
|
||||||
|
// Values are printed using fmt.Sprintf("%v", v).
|
||||||
|
// Order is unspecified.
|
||||||
|
func (m *Map) String() string {
|
||||||
|
return m.toString(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// KeysString returns a string representation of the map's key set.
|
||||||
|
// Order is unspecified.
|
||||||
|
func (m *Map) KeysString() string {
|
||||||
|
return m.toString(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
// Hasher
|
||||||
|
|
||||||
|
// A Hasher maps each type to its hash value.
|
||||||
|
// For efficiency, a hasher uses memoization; thus its memory
|
||||||
|
// footprint grows monotonically over time.
|
||||||
|
// Hashers are not thread-safe.
|
||||||
|
// Hashers have reference semantics.
|
||||||
|
// Call MakeHasher to create a Hasher.
|
||||||
|
type Hasher struct {
|
||||||
|
memo map[types.Type]uint32
|
||||||
|
|
||||||
|
// ptrMap records pointer identity.
|
||||||
|
ptrMap map[any]uint32
|
||||||
|
|
||||||
|
// sigTParams holds type parameters from the signature being hashed.
|
||||||
|
// Signatures are considered identical modulo renaming of type parameters, so
|
||||||
|
// within the scope of a signature type the identity of the signature's type
|
||||||
|
// parameters is just their index.
|
||||||
|
//
|
||||||
|
// Since the language does not currently support referring to uninstantiated
|
||||||
|
// generic types or functions, and instantiated signatures do not have type
|
||||||
|
// parameter lists, we should never encounter a second non-empty type
|
||||||
|
// parameter list when hashing a generic signature.
|
||||||
|
sigTParams *types.TypeParamList
|
||||||
|
}
|
||||||
|
|
||||||
|
// MakeHasher returns a new Hasher instance.
|
||||||
|
func MakeHasher() Hasher {
|
||||||
|
return Hasher{
|
||||||
|
memo: make(map[types.Type]uint32),
|
||||||
|
ptrMap: make(map[any]uint32),
|
||||||
|
sigTParams: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash computes a hash value for the given type t such that
|
||||||
|
// Identical(t, t') => Hash(t) == Hash(t').
|
||||||
|
func (h Hasher) Hash(t types.Type) uint32 {
|
||||||
|
hash, ok := h.memo[t]
|
||||||
|
if !ok {
|
||||||
|
hash = h.hashFor(t)
|
||||||
|
h.memo[t] = hash
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashString computes the Fowler–Noll–Vo hash of s.
|
||||||
|
func hashString(s string) uint32 {
|
||||||
|
var h uint32
|
||||||
|
for i := 0; i < len(s); i++ {
|
||||||
|
h ^= uint32(s[i])
|
||||||
|
h *= 16777619
|
||||||
|
}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashFor computes the hash of t.
|
||||||
|
func (h Hasher) hashFor(t types.Type) uint32 {
|
||||||
|
// See Identical for rationale.
|
||||||
|
switch t := t.(type) {
|
||||||
|
case *types.Basic:
|
||||||
|
return uint32(t.Kind())
|
||||||
|
|
||||||
|
case *types.Alias:
|
||||||
|
return h.Hash(types.Unalias(t))
|
||||||
|
|
||||||
|
case *types.Array:
|
||||||
|
return 9043 + 2*uint32(t.Len()) + 3*h.Hash(t.Elem())
|
||||||
|
|
||||||
|
case *types.Slice:
|
||||||
|
return 9049 + 2*h.Hash(t.Elem())
|
||||||
|
|
||||||
|
case *types.Struct:
|
||||||
|
var hash uint32 = 9059
|
||||||
|
for i, n := 0, t.NumFields(); i < n; i++ {
|
||||||
|
f := t.Field(i)
|
||||||
|
if f.Anonymous() {
|
||||||
|
hash += 8861
|
||||||
|
}
|
||||||
|
hash += hashString(t.Tag(i))
|
||||||
|
hash += hashString(f.Name()) // (ignore f.Pkg)
|
||||||
|
hash += h.Hash(f.Type())
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
|
||||||
|
case *types.Pointer:
|
||||||
|
return 9067 + 2*h.Hash(t.Elem())
|
||||||
|
|
||||||
|
case *types.Signature:
|
||||||
|
var hash uint32 = 9091
|
||||||
|
if t.Variadic() {
|
||||||
|
hash *= 8863
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use a separate hasher for types inside of the signature, where type
|
||||||
|
// parameter identity is modified to be (index, constraint). We must use a
|
||||||
|
// new memo for this hasher as type identity may be affected by this
|
||||||
|
// masking. For example, in func[T any](*T), the identity of *T depends on
|
||||||
|
// whether we are mapping the argument in isolation, or recursively as part
|
||||||
|
// of hashing the signature.
|
||||||
|
//
|
||||||
|
// We should never encounter a generic signature while hashing another
|
||||||
|
// generic signature, but defensively set sigTParams only if h.mask is
|
||||||
|
// unset.
|
||||||
|
tparams := t.TypeParams()
|
||||||
|
if h.sigTParams == nil && tparams.Len() != 0 {
|
||||||
|
h = Hasher{
|
||||||
|
// There may be something more efficient than discarding the existing
|
||||||
|
// memo, but it would require detecting whether types are 'tainted' by
|
||||||
|
// references to type parameters.
|
||||||
|
memo: make(map[types.Type]uint32),
|
||||||
|
// Re-using ptrMap ensures that pointer identity is preserved in this
|
||||||
|
// hasher.
|
||||||
|
ptrMap: h.ptrMap,
|
||||||
|
sigTParams: tparams,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for i := 0; i < tparams.Len(); i++ {
|
||||||
|
tparam := tparams.At(i)
|
||||||
|
hash += 7 * h.Hash(tparam.Constraint())
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash + 3*h.hashTuple(t.Params()) + 5*h.hashTuple(t.Results())
|
||||||
|
|
||||||
|
case *types.Union:
|
||||||
|
return h.hashUnion(t)
|
||||||
|
|
||||||
|
case *types.Interface:
|
||||||
|
// Interfaces are identical if they have the same set of methods, with
|
||||||
|
// identical names and types, and they have the same set of type
|
||||||
|
// restrictions. See go/types.identical for more details.
|
||||||
|
var hash uint32 = 9103
|
||||||
|
|
||||||
|
// Hash methods.
|
||||||
|
for i, n := 0, t.NumMethods(); i < n; i++ {
|
||||||
|
// Method order is not significant.
|
||||||
|
// Ignore m.Pkg().
|
||||||
|
m := t.Method(i)
|
||||||
|
// Use shallow hash on method signature to
|
||||||
|
// avoid anonymous interface cycles.
|
||||||
|
hash += 3*hashString(m.Name()) + 5*h.shallowHash(m.Type())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hash type restrictions.
|
||||||
|
terms, err := typeparams.InterfaceTermSet(t)
|
||||||
|
// if err != nil t has invalid type restrictions.
|
||||||
|
if err == nil {
|
||||||
|
hash += h.hashTermSet(terms)
|
||||||
|
}
|
||||||
|
|
||||||
|
return hash
|
||||||
|
|
||||||
|
case *types.Map:
|
||||||
|
return 9109 + 2*h.Hash(t.Key()) + 3*h.Hash(t.Elem())
|
||||||
|
|
||||||
|
case *types.Chan:
|
||||||
|
return 9127 + 2*uint32(t.Dir()) + 3*h.Hash(t.Elem())
|
||||||
|
|
||||||
|
case *types.Named:
|
||||||
|
hash := h.hashPtr(t.Obj())
|
||||||
|
targs := t.TypeArgs()
|
||||||
|
for i := 0; i < targs.Len(); i++ {
|
||||||
|
targ := targs.At(i)
|
||||||
|
hash += 2 * h.Hash(targ)
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
|
||||||
|
case *types.TypeParam:
|
||||||
|
return h.hashTypeParam(t)
|
||||||
|
|
||||||
|
case *types.Tuple:
|
||||||
|
return h.hashTuple(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
panic(fmt.Sprintf("%T: %v", t, t))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Hasher) hashTuple(tuple *types.Tuple) uint32 {
|
||||||
|
// See go/types.identicalTypes for rationale.
|
||||||
|
n := tuple.Len()
|
||||||
|
hash := 9137 + 2*uint32(n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
hash += 3 * h.Hash(tuple.At(i).Type())
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Hasher) hashUnion(t *types.Union) uint32 {
|
||||||
|
// Hash type restrictions.
|
||||||
|
terms, err := typeparams.UnionTermSet(t)
|
||||||
|
// if err != nil t has invalid type restrictions. Fall back on a non-zero
|
||||||
|
// hash.
|
||||||
|
if err != nil {
|
||||||
|
return 9151
|
||||||
|
}
|
||||||
|
return h.hashTermSet(terms)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (h Hasher) hashTermSet(terms []*types.Term) uint32 {
|
||||||
|
hash := 9157 + 2*uint32(len(terms))
|
||||||
|
for _, term := range terms {
|
||||||
|
// term order is not significant.
|
||||||
|
termHash := h.Hash(term.Type())
|
||||||
|
if term.Tilde() {
|
||||||
|
termHash *= 9161
|
||||||
|
}
|
||||||
|
hash += 3 * termHash
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashTypeParam returns a hash of the type parameter t, with a hash value
|
||||||
|
// depending on whether t is contained in h.sigTParams.
|
||||||
|
//
|
||||||
|
// If h.sigTParams is set and contains t, then we are in the process of hashing
|
||||||
|
// a signature, and the hash value of t must depend only on t's index and
|
||||||
|
// constraint: signatures are considered identical modulo type parameter
|
||||||
|
// renaming. To avoid infinite recursion, we only hash the type parameter
|
||||||
|
// index, and rely on types.Identical to handle signatures where constraints
|
||||||
|
// are not identical.
|
||||||
|
//
|
||||||
|
// Otherwise the hash of t depends only on t's pointer identity.
|
||||||
|
func (h Hasher) hashTypeParam(t *types.TypeParam) uint32 {
|
||||||
|
if h.sigTParams != nil {
|
||||||
|
i := t.Index()
|
||||||
|
if i >= 0 && i < h.sigTParams.Len() && t == h.sigTParams.At(i) {
|
||||||
|
return 9173 + 3*uint32(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return h.hashPtr(t.Obj())
|
||||||
|
}
|
||||||
|
|
||||||
|
// hashPtr hashes the pointer identity of ptr. It uses h.ptrMap to ensure that
|
||||||
|
// pointers values are not dependent on the GC.
|
||||||
|
func (h Hasher) hashPtr(ptr any) uint32 {
|
||||||
|
if hash, ok := h.ptrMap[ptr]; ok {
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
hash := uint32(reflect.ValueOf(ptr).Pointer())
|
||||||
|
h.ptrMap[ptr] = hash
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
// shallowHash computes a hash of t without looking at any of its
|
||||||
|
// element Types, to avoid potential anonymous cycles in the types of
|
||||||
|
// interface methods.
|
||||||
|
//
|
||||||
|
// When an unnamed non-empty interface type appears anywhere among the
|
||||||
|
// arguments or results of an interface method, there is a potential
|
||||||
|
// for endless recursion. Consider:
|
||||||
|
//
|
||||||
|
// type X interface { m() []*interface { X } }
|
||||||
|
//
|
||||||
|
// The problem is that the Methods of the interface in m's result type
|
||||||
|
// include m itself; there is no mention of the named type X that
|
||||||
|
// might help us break the cycle.
|
||||||
|
// (See comment in go/types.identical, case *Interface, for more.)
|
||||||
|
func (h Hasher) shallowHash(t types.Type) uint32 {
|
||||||
|
// t is the type of an interface method (Signature),
|
||||||
|
// its params or results (Tuples), or their immediate
|
||||||
|
// elements (mostly Slice, Pointer, Basic, Named),
|
||||||
|
// so there's no need to optimize anything else.
|
||||||
|
switch t := t.(type) {
|
||||||
|
case *types.Alias:
|
||||||
|
return h.shallowHash(types.Unalias(t))
|
||||||
|
|
||||||
|
case *types.Signature:
|
||||||
|
var hash uint32 = 604171
|
||||||
|
if t.Variadic() {
|
||||||
|
hash *= 971767
|
||||||
|
}
|
||||||
|
// The Signature/Tuple recursion is always finite
|
||||||
|
// and invariably shallow.
|
||||||
|
return hash + 1062599*h.shallowHash(t.Params()) + 1282529*h.shallowHash(t.Results())
|
||||||
|
|
||||||
|
case *types.Tuple:
|
||||||
|
n := t.Len()
|
||||||
|
hash := 9137 + 2*uint32(n)
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
hash += 53471161 * h.shallowHash(t.At(i).Type())
|
||||||
|
}
|
||||||
|
return hash
|
||||||
|
|
||||||
|
case *types.Basic:
|
||||||
|
return 45212177 * uint32(t.Kind())
|
||||||
|
|
||||||
|
case *types.Array:
|
||||||
|
return 1524181 + 2*uint32(t.Len())
|
||||||
|
|
||||||
|
case *types.Slice:
|
||||||
|
return 2690201
|
||||||
|
|
||||||
|
case *types.Struct:
|
||||||
|
return 3326489
|
||||||
|
|
||||||
|
case *types.Pointer:
|
||||||
|
return 4393139
|
||||||
|
|
||||||
|
case *types.Union:
|
||||||
|
return 562448657
|
||||||
|
|
||||||
|
case *types.Interface:
|
||||||
|
return 2124679 // no recursion here
|
||||||
|
|
||||||
|
case *types.Map:
|
||||||
|
return 9109
|
||||||
|
|
||||||
|
case *types.Chan:
|
||||||
|
return 9127
|
||||||
|
|
||||||
|
case *types.Named:
|
||||||
|
return h.hashPtr(t.Obj())
|
||||||
|
|
||||||
|
case *types.TypeParam:
|
||||||
|
return h.hashPtr(t.Obj())
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("shallowHash: %T: %v", t, t))
|
||||||
|
}
|
71
test/tools/vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go
generated
vendored
Normal file
71
test/tools/vendor/golang.org/x/tools/go/types/typeutil/methodsetcache.go
generated
vendored
Normal file
|
@ -0,0 +1,71 @@
|
||||||
|
// Copyright 2014 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.
|
||||||
|
|
||||||
|
// This file implements a cache of method sets.
|
||||||
|
|
||||||
|
package typeutil
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A MethodSetCache records the method set of each type T for which
|
||||||
|
// MethodSet(T) is called so that repeat queries are fast.
|
||||||
|
// The zero value is a ready-to-use cache instance.
|
||||||
|
type MethodSetCache struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
named map[*types.Named]struct{ value, pointer *types.MethodSet } // method sets for named N and *N
|
||||||
|
others map[types.Type]*types.MethodSet // all other types
|
||||||
|
}
|
||||||
|
|
||||||
|
// MethodSet returns the method set of type T. It is thread-safe.
|
||||||
|
//
|
||||||
|
// If cache is nil, this function is equivalent to types.NewMethodSet(T).
|
||||||
|
// Utility functions can thus expose an optional *MethodSetCache
|
||||||
|
// parameter to clients that care about performance.
|
||||||
|
func (cache *MethodSetCache) MethodSet(T types.Type) *types.MethodSet {
|
||||||
|
if cache == nil {
|
||||||
|
return types.NewMethodSet(T)
|
||||||
|
}
|
||||||
|
cache.mu.Lock()
|
||||||
|
defer cache.mu.Unlock()
|
||||||
|
|
||||||
|
switch T := types.Unalias(T).(type) {
|
||||||
|
case *types.Named:
|
||||||
|
return cache.lookupNamed(T).value
|
||||||
|
|
||||||
|
case *types.Pointer:
|
||||||
|
if N, ok := types.Unalias(T.Elem()).(*types.Named); ok {
|
||||||
|
return cache.lookupNamed(N).pointer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// all other types
|
||||||
|
// (The map uses pointer equivalence, not type identity.)
|
||||||
|
mset := cache.others[T]
|
||||||
|
if mset == nil {
|
||||||
|
mset = types.NewMethodSet(T)
|
||||||
|
if cache.others == nil {
|
||||||
|
cache.others = make(map[types.Type]*types.MethodSet)
|
||||||
|
}
|
||||||
|
cache.others[T] = mset
|
||||||
|
}
|
||||||
|
return mset
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cache *MethodSetCache) lookupNamed(named *types.Named) struct{ value, pointer *types.MethodSet } {
|
||||||
|
if cache.named == nil {
|
||||||
|
cache.named = make(map[*types.Named]struct{ value, pointer *types.MethodSet })
|
||||||
|
}
|
||||||
|
// Avoid recomputing mset(*T) for each distinct Pointer
|
||||||
|
// instance whose underlying type is a named type.
|
||||||
|
msets, ok := cache.named[named]
|
||||||
|
if !ok {
|
||||||
|
msets.value = types.NewMethodSet(named)
|
||||||
|
msets.pointer = types.NewMethodSet(types.NewPointer(named))
|
||||||
|
cache.named[named] = msets
|
||||||
|
}
|
||||||
|
return msets
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
// Copyright 2014 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 typeutil
|
||||||
|
|
||||||
|
// This file defines utilities for user interfaces that display types.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IntuitiveMethodSet returns the intuitive method set of a type T,
|
||||||
|
// which is the set of methods you can call on an addressable value of
|
||||||
|
// that type.
|
||||||
|
//
|
||||||
|
// The result always contains MethodSet(T), and is exactly MethodSet(T)
|
||||||
|
// for interface types and for pointer-to-concrete types.
|
||||||
|
// For all other concrete types T, the result additionally
|
||||||
|
// contains each method belonging to *T if there is no identically
|
||||||
|
// named method on T itself.
|
||||||
|
//
|
||||||
|
// This corresponds to user intuition about method sets;
|
||||||
|
// this function is intended only for user interfaces.
|
||||||
|
//
|
||||||
|
// The order of the result is as for types.MethodSet(T).
|
||||||
|
func IntuitiveMethodSet(T types.Type, msets *MethodSetCache) []*types.Selection {
|
||||||
|
isPointerToConcrete := func(T types.Type) bool {
|
||||||
|
ptr, ok := types.Unalias(T).(*types.Pointer)
|
||||||
|
return ok && !types.IsInterface(ptr.Elem())
|
||||||
|
}
|
||||||
|
|
||||||
|
var result []*types.Selection
|
||||||
|
mset := msets.MethodSet(T)
|
||||||
|
if types.IsInterface(T) || isPointerToConcrete(T) {
|
||||||
|
for i, n := 0, mset.Len(); i < n; i++ {
|
||||||
|
result = append(result, mset.At(i))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// T is some other concrete type.
|
||||||
|
// Report methods of T and *T, preferring those of T.
|
||||||
|
pmset := msets.MethodSet(types.NewPointer(T))
|
||||||
|
for i, n := 0, pmset.Len(); i < n; i++ {
|
||||||
|
meth := pmset.At(i)
|
||||||
|
if m := mset.Lookup(meth.Obj().Pkg(), meth.Obj().Name()); m != nil {
|
||||||
|
meth = m
|
||||||
|
}
|
||||||
|
result = append(result, meth)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
|
@ -28,7 +28,7 @@ import (
|
||||||
func NewAlias(enabled bool, pos token.Pos, pkg *types.Package, name string, rhs types.Type, tparams []*types.TypeParam) *types.TypeName {
|
func NewAlias(enabled bool, pos token.Pos, pkg *types.Package, name string, rhs types.Type, tparams []*types.TypeParam) *types.TypeName {
|
||||||
if enabled {
|
if enabled {
|
||||||
tname := types.NewTypeName(pos, pkg, name, nil)
|
tname := types.NewTypeName(pos, pkg, name, nil)
|
||||||
newAlias(tname, rhs, tparams)
|
SetTypeParams(types.NewAlias(tname, rhs), tparams)
|
||||||
return tname
|
return tname
|
||||||
}
|
}
|
||||||
if len(tparams) > 0 {
|
if len(tparams) > 0 {
|
||||||
|
|
|
@ -1,37 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
//go:build !go1.22
|
|
||||||
// +build !go1.22
|
|
||||||
|
|
||||||
package aliases
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Alias is a placeholder for a go/types.Alias for <=1.21.
|
|
||||||
// It will never be created by go/types.
|
|
||||||
type Alias struct{}
|
|
||||||
|
|
||||||
func (*Alias) String() string { panic("unreachable") }
|
|
||||||
func (*Alias) Underlying() types.Type { panic("unreachable") }
|
|
||||||
func (*Alias) Obj() *types.TypeName { panic("unreachable") }
|
|
||||||
func Rhs(alias *Alias) types.Type { panic("unreachable") }
|
|
||||||
func TypeParams(alias *Alias) *types.TypeParamList { panic("unreachable") }
|
|
||||||
func SetTypeParams(alias *Alias, tparams []*types.TypeParam) { panic("unreachable") }
|
|
||||||
func TypeArgs(alias *Alias) *types.TypeList { panic("unreachable") }
|
|
||||||
func Origin(alias *Alias) *Alias { panic("unreachable") }
|
|
||||||
|
|
||||||
// Unalias returns the type t for go <=1.21.
|
|
||||||
func Unalias(t types.Type) types.Type { return t }
|
|
||||||
|
|
||||||
func newAlias(name *types.TypeName, rhs types.Type, tparams []*types.TypeParam) *Alias {
|
|
||||||
panic("unreachable")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enabled reports whether [NewAlias] should create [types.Alias] types.
|
|
||||||
//
|
|
||||||
// Before go1.22, this function always returns false.
|
|
||||||
func Enabled() bool { return false }
|
|
|
@ -2,9 +2,6 @@
|
||||||
// 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.22
|
|
||||||
// +build go1.22
|
|
||||||
|
|
||||||
package aliases
|
package aliases
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -14,22 +11,19 @@ import (
|
||||||
"go/types"
|
"go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Alias is an alias of types.Alias.
|
|
||||||
type Alias = types.Alias
|
|
||||||
|
|
||||||
// Rhs returns the type on the right-hand side of the alias declaration.
|
// Rhs returns the type on the right-hand side of the alias declaration.
|
||||||
func Rhs(alias *Alias) types.Type {
|
func Rhs(alias *types.Alias) types.Type {
|
||||||
if alias, ok := any(alias).(interface{ Rhs() types.Type }); ok {
|
if alias, ok := any(alias).(interface{ Rhs() types.Type }); ok {
|
||||||
return alias.Rhs() // go1.23+
|
return alias.Rhs() // go1.23+
|
||||||
}
|
}
|
||||||
|
|
||||||
// go1.22's Alias didn't have the Rhs method,
|
// go1.22's Alias didn't have the Rhs method,
|
||||||
// so Unalias is the best we can do.
|
// so Unalias is the best we can do.
|
||||||
return Unalias(alias)
|
return types.Unalias(alias)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeParams returns the type parameter list of the alias.
|
// TypeParams returns the type parameter list of the alias.
|
||||||
func TypeParams(alias *Alias) *types.TypeParamList {
|
func TypeParams(alias *types.Alias) *types.TypeParamList {
|
||||||
if alias, ok := any(alias).(interface{ TypeParams() *types.TypeParamList }); ok {
|
if alias, ok := any(alias).(interface{ TypeParams() *types.TypeParamList }); ok {
|
||||||
return alias.TypeParams() // go1.23+
|
return alias.TypeParams() // go1.23+
|
||||||
}
|
}
|
||||||
|
@ -37,7 +31,7 @@ func TypeParams(alias *Alias) *types.TypeParamList {
|
||||||
}
|
}
|
||||||
|
|
||||||
// SetTypeParams sets the type parameters of the alias type.
|
// SetTypeParams sets the type parameters of the alias type.
|
||||||
func SetTypeParams(alias *Alias, tparams []*types.TypeParam) {
|
func SetTypeParams(alias *types.Alias, tparams []*types.TypeParam) {
|
||||||
if alias, ok := any(alias).(interface {
|
if alias, ok := any(alias).(interface {
|
||||||
SetTypeParams(tparams []*types.TypeParam)
|
SetTypeParams(tparams []*types.TypeParam)
|
||||||
}); ok {
|
}); ok {
|
||||||
|
@ -48,7 +42,7 @@ func SetTypeParams(alias *Alias, tparams []*types.TypeParam) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeArgs returns the type arguments used to instantiate the Alias type.
|
// TypeArgs returns the type arguments used to instantiate the Alias type.
|
||||||
func TypeArgs(alias *Alias) *types.TypeList {
|
func TypeArgs(alias *types.Alias) *types.TypeList {
|
||||||
if alias, ok := any(alias).(interface{ TypeArgs() *types.TypeList }); ok {
|
if alias, ok := any(alias).(interface{ TypeArgs() *types.TypeList }); ok {
|
||||||
return alias.TypeArgs() // go1.23+
|
return alias.TypeArgs() // go1.23+
|
||||||
}
|
}
|
||||||
|
@ -57,25 +51,13 @@ func TypeArgs(alias *Alias) *types.TypeList {
|
||||||
|
|
||||||
// Origin returns the generic Alias type of which alias is an instance.
|
// Origin returns the generic Alias type of which alias is an instance.
|
||||||
// If alias is not an instance of a generic alias, Origin returns alias.
|
// If alias is not an instance of a generic alias, Origin returns alias.
|
||||||
func Origin(alias *Alias) *Alias {
|
func Origin(alias *types.Alias) *types.Alias {
|
||||||
if alias, ok := any(alias).(interface{ Origin() *types.Alias }); ok {
|
if alias, ok := any(alias).(interface{ Origin() *types.Alias }); ok {
|
||||||
return alias.Origin() // go1.23+
|
return alias.Origin() // go1.23+
|
||||||
}
|
}
|
||||||
return alias // not an instance of a generic alias (go1.22)
|
return alias // not an instance of a generic alias (go1.22)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unalias is a wrapper of types.Unalias.
|
|
||||||
func Unalias(t types.Type) types.Type { return types.Unalias(t) }
|
|
||||||
|
|
||||||
// newAlias is an internal alias around types.NewAlias.
|
|
||||||
// Direct usage is discouraged as the moment.
|
|
||||||
// Try to use NewAlias instead.
|
|
||||||
func newAlias(tname *types.TypeName, rhs types.Type, tparams []*types.TypeParam) *Alias {
|
|
||||||
a := types.NewAlias(tname, rhs)
|
|
||||||
SetTypeParams(a, tparams)
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enabled reports whether [NewAlias] should create [types.Alias] types.
|
// Enabled reports whether [NewAlias] should create [types.Alias] types.
|
||||||
//
|
//
|
||||||
// This function is expensive! Call it sparingly.
|
// This function is expensive! Call it sparingly.
|
||||||
|
@ -91,7 +73,7 @@ func Enabled() bool {
|
||||||
// many tests. Therefore any attempt to cache the result
|
// many tests. Therefore any attempt to cache the result
|
||||||
// is just incorrect.
|
// is just incorrect.
|
||||||
fset := token.NewFileSet()
|
fset := token.NewFileSet()
|
||||||
f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", 0)
|
f, _ := parser.ParseFile(fset, "a.go", "package p; type A = int", parser.SkipObjectResolution)
|
||||||
pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil)
|
pkg, _ := new(types.Config).Check("p", fset, []*ast.File{f}, nil)
|
||||||
_, enabled := pkg.Scope().Lookup("A").Type().(*types.Alias)
|
_, enabled := pkg.Scope().Lookup("A").Type().(*types.Alias)
|
||||||
return enabled
|
return enabled
|
||||||
|
|
|
@ -87,64 +87,3 @@ func chanDir(d int) types.ChanDir {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var predeclOnce sync.Once
|
|
||||||
var predecl []types.Type // initialized lazily
|
|
||||||
|
|
||||||
func predeclared() []types.Type {
|
|
||||||
predeclOnce.Do(func() {
|
|
||||||
// initialize lazily to be sure that all
|
|
||||||
// elements have been initialized before
|
|
||||||
predecl = []types.Type{ // basic types
|
|
||||||
types.Typ[types.Bool],
|
|
||||||
types.Typ[types.Int],
|
|
||||||
types.Typ[types.Int8],
|
|
||||||
types.Typ[types.Int16],
|
|
||||||
types.Typ[types.Int32],
|
|
||||||
types.Typ[types.Int64],
|
|
||||||
types.Typ[types.Uint],
|
|
||||||
types.Typ[types.Uint8],
|
|
||||||
types.Typ[types.Uint16],
|
|
||||||
types.Typ[types.Uint32],
|
|
||||||
types.Typ[types.Uint64],
|
|
||||||
types.Typ[types.Uintptr],
|
|
||||||
types.Typ[types.Float32],
|
|
||||||
types.Typ[types.Float64],
|
|
||||||
types.Typ[types.Complex64],
|
|
||||||
types.Typ[types.Complex128],
|
|
||||||
types.Typ[types.String],
|
|
||||||
|
|
||||||
// basic type aliases
|
|
||||||
types.Universe.Lookup("byte").Type(),
|
|
||||||
types.Universe.Lookup("rune").Type(),
|
|
||||||
|
|
||||||
// error
|
|
||||||
types.Universe.Lookup("error").Type(),
|
|
||||||
|
|
||||||
// untyped types
|
|
||||||
types.Typ[types.UntypedBool],
|
|
||||||
types.Typ[types.UntypedInt],
|
|
||||||
types.Typ[types.UntypedRune],
|
|
||||||
types.Typ[types.UntypedFloat],
|
|
||||||
types.Typ[types.UntypedComplex],
|
|
||||||
types.Typ[types.UntypedString],
|
|
||||||
types.Typ[types.UntypedNil],
|
|
||||||
|
|
||||||
// package unsafe
|
|
||||||
types.Typ[types.UnsafePointer],
|
|
||||||
|
|
||||||
// invalid type
|
|
||||||
types.Typ[types.Invalid], // only appears in packages with errors
|
|
||||||
|
|
||||||
// used internally by gc; never used by this package or in .a files
|
|
||||||
anyType{},
|
|
||||||
}
|
|
||||||
predecl = append(predecl, additionalPredeclared()...)
|
|
||||||
})
|
|
||||||
return predecl
|
|
||||||
}
|
|
||||||
|
|
||||||
type anyType struct{}
|
|
||||||
|
|
||||||
func (t anyType) Underlying() types.Type { return t }
|
|
||||||
func (t anyType) String() string { return "any" }
|
|
||||||
|
|
|
@ -232,14 +232,19 @@ func Import(packages map[string]*types.Package, path, srcDir string, lookup func
|
||||||
// Select appropriate importer.
|
// Select appropriate importer.
|
||||||
if len(data) > 0 {
|
if len(data) > 0 {
|
||||||
switch data[0] {
|
switch data[0] {
|
||||||
case 'v', 'c', 'd': // binary, till go1.10
|
case 'v', 'c', 'd':
|
||||||
|
// binary: emitted by cmd/compile till go1.10; obsolete.
|
||||||
return nil, fmt.Errorf("binary (%c) import format is no longer supported", data[0])
|
return nil, fmt.Errorf("binary (%c) import format is no longer supported", data[0])
|
||||||
|
|
||||||
case 'i': // indexed, till go1.19
|
case 'i':
|
||||||
|
// indexed: emitted by cmd/compile till go1.19;
|
||||||
|
// now used only for serializing go/types.
|
||||||
|
// See https://github.com/golang/go/issues/69491.
|
||||||
_, pkg, err := IImportData(fset, packages, data[1:], id)
|
_, pkg, err := IImportData(fset, packages, data[1:], id)
|
||||||
return pkg, err
|
return pkg, err
|
||||||
|
|
||||||
case 'u': // unified, from go1.20
|
case 'u':
|
||||||
|
// unified: emitted by cmd/compile since go1.20.
|
||||||
_, pkg, err := UImportData(fset, packages, data[1:size], id)
|
_, pkg, err := UImportData(fset, packages, data[1:size], id)
|
||||||
return pkg, err
|
return pkg, err
|
||||||
|
|
||||||
|
|
|
@ -242,7 +242,6 @@ import (
|
||||||
|
|
||||||
"golang.org/x/tools/go/types/objectpath"
|
"golang.org/x/tools/go/types/objectpath"
|
||||||
"golang.org/x/tools/internal/aliases"
|
"golang.org/x/tools/internal/aliases"
|
||||||
"golang.org/x/tools/internal/tokeninternal"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// IExportShallow encodes "shallow" export data for the specified package.
|
// IExportShallow encodes "shallow" export data for the specified package.
|
||||||
|
@ -441,7 +440,7 @@ func (p *iexporter) encodeFile(w *intWriter, file *token.File, needed []uint64)
|
||||||
// Sort the set of needed offsets. Duplicates are harmless.
|
// Sort the set of needed offsets. Duplicates are harmless.
|
||||||
sort.Slice(needed, func(i, j int) bool { return needed[i] < needed[j] })
|
sort.Slice(needed, func(i, j int) bool { return needed[i] < needed[j] })
|
||||||
|
|
||||||
lines := tokeninternal.GetLines(file) // byte offset of each line start
|
lines := file.Lines() // byte offset of each line start
|
||||||
w.uint64(uint64(len(lines)))
|
w.uint64(uint64(len(lines)))
|
||||||
|
|
||||||
// Rather than record the entire array of line start offsets,
|
// Rather than record the entire array of line start offsets,
|
||||||
|
@ -725,13 +724,13 @@ func (p *iexporter) doDecl(obj types.Object) {
|
||||||
case *types.TypeName:
|
case *types.TypeName:
|
||||||
t := obj.Type()
|
t := obj.Type()
|
||||||
|
|
||||||
if tparam, ok := aliases.Unalias(t).(*types.TypeParam); ok {
|
if tparam, ok := types.Unalias(t).(*types.TypeParam); ok {
|
||||||
w.tag(typeParamTag)
|
w.tag(typeParamTag)
|
||||||
w.pos(obj.Pos())
|
w.pos(obj.Pos())
|
||||||
constraint := tparam.Constraint()
|
constraint := tparam.Constraint()
|
||||||
if p.version >= iexportVersionGo1_18 {
|
if p.version >= iexportVersionGo1_18 {
|
||||||
implicit := false
|
implicit := false
|
||||||
if iface, _ := aliases.Unalias(constraint).(*types.Interface); iface != nil {
|
if iface, _ := types.Unalias(constraint).(*types.Interface); iface != nil {
|
||||||
implicit = iface.IsImplicit()
|
implicit = iface.IsImplicit()
|
||||||
}
|
}
|
||||||
w.bool(implicit)
|
w.bool(implicit)
|
||||||
|
@ -741,7 +740,7 @@ func (p *iexporter) doDecl(obj types.Object) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if obj.IsAlias() {
|
if obj.IsAlias() {
|
||||||
alias, materialized := t.(*aliases.Alias) // may fail when aliases are not enabled
|
alias, materialized := t.(*types.Alias) // may fail when aliases are not enabled
|
||||||
|
|
||||||
var tparams *types.TypeParamList
|
var tparams *types.TypeParamList
|
||||||
if materialized {
|
if materialized {
|
||||||
|
@ -975,7 +974,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
switch t := t.(type) {
|
switch t := t.(type) {
|
||||||
case *aliases.Alias:
|
case *types.Alias:
|
||||||
if targs := aliases.TypeArgs(t); targs.Len() > 0 {
|
if targs := aliases.TypeArgs(t); targs.Len() > 0 {
|
||||||
w.startType(instanceType)
|
w.startType(instanceType)
|
||||||
w.pos(t.Obj().Pos())
|
w.pos(t.Obj().Pos())
|
||||||
|
@ -1091,7 +1090,7 @@ func (w *exportWriter) doTyp(t types.Type, pkg *types.Package) {
|
||||||
for i := 0; i < n; i++ {
|
for i := 0; i < n; i++ {
|
||||||
ft := t.EmbeddedType(i)
|
ft := t.EmbeddedType(i)
|
||||||
tPkg := pkg
|
tPkg := pkg
|
||||||
if named, _ := aliases.Unalias(ft).(*types.Named); named != nil {
|
if named, _ := types.Unalias(ft).(*types.Named); named != nil {
|
||||||
w.pos(named.Obj().Pos())
|
w.pos(named.Obj().Pos())
|
||||||
} else {
|
} else {
|
||||||
w.pos(token.NoPos)
|
w.pos(token.NoPos)
|
||||||
|
|
|
@ -53,6 +53,7 @@ const (
|
||||||
iexportVersionPosCol = 1
|
iexportVersionPosCol = 1
|
||||||
iexportVersionGo1_18 = 2
|
iexportVersionGo1_18 = 2
|
||||||
iexportVersionGenerics = 2
|
iexportVersionGenerics = 2
|
||||||
|
iexportVersion = iexportVersionGenerics
|
||||||
|
|
||||||
iexportVersionCurrent = 2
|
iexportVersionCurrent = 2
|
||||||
)
|
)
|
||||||
|
@ -540,7 +541,7 @@ func canReuse(def *types.Named, rhs types.Type) bool {
|
||||||
if def == nil {
|
if def == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
iface, _ := aliases.Unalias(rhs).(*types.Interface)
|
iface, _ := types.Unalias(rhs).(*types.Interface)
|
||||||
if iface == nil {
|
if iface == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
@ -615,7 +616,7 @@ func (r *importReader) obj(name string) {
|
||||||
if targs.Len() > 0 {
|
if targs.Len() > 0 {
|
||||||
rparams = make([]*types.TypeParam, targs.Len())
|
rparams = make([]*types.TypeParam, targs.Len())
|
||||||
for i := range rparams {
|
for i := range rparams {
|
||||||
rparams[i] = aliases.Unalias(targs.At(i)).(*types.TypeParam)
|
rparams[i] = types.Unalias(targs.At(i)).(*types.TypeParam)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msig := r.signature(recv, rparams, nil)
|
msig := r.signature(recv, rparams, nil)
|
||||||
|
@ -645,7 +646,7 @@ func (r *importReader) obj(name string) {
|
||||||
}
|
}
|
||||||
constraint := r.typ()
|
constraint := r.typ()
|
||||||
if implicit {
|
if implicit {
|
||||||
iface, _ := aliases.Unalias(constraint).(*types.Interface)
|
iface, _ := types.Unalias(constraint).(*types.Interface)
|
||||||
if iface == nil {
|
if iface == nil {
|
||||||
errorf("non-interface constraint marked implicit")
|
errorf("non-interface constraint marked implicit")
|
||||||
}
|
}
|
||||||
|
@ -852,7 +853,7 @@ func (r *importReader) typ() types.Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
func isInterface(t types.Type) bool {
|
func isInterface(t types.Type) bool {
|
||||||
_, ok := aliases.Unalias(t).(*types.Interface)
|
_, ok := types.Unalias(t).(*types.Interface)
|
||||||
return ok
|
return ok
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -959,7 +960,7 @@ func (r *importReader) doType(base *types.Named) (res types.Type) {
|
||||||
methods[i] = method
|
methods[i] = method
|
||||||
}
|
}
|
||||||
|
|
||||||
typ := newInterface(methods, embeddeds)
|
typ := types.NewInterfaceType(methods, embeddeds)
|
||||||
r.p.interfaceList = append(r.p.interfaceList, typ)
|
r.p.interfaceList = append(r.p.interfaceList, typ)
|
||||||
return typ
|
return typ
|
||||||
|
|
||||||
|
@ -1051,7 +1052,7 @@ func (r *importReader) tparamList() []*types.TypeParam {
|
||||||
for i := range xs {
|
for i := range xs {
|
||||||
// Note: the standard library importer is tolerant of nil types here,
|
// Note: the standard library importer is tolerant of nil types here,
|
||||||
// though would panic in SetTypeParams.
|
// though would panic in SetTypeParams.
|
||||||
xs[i] = aliases.Unalias(r.typ()).(*types.TypeParam)
|
xs[i] = types.Unalias(r.typ()).(*types.TypeParam)
|
||||||
}
|
}
|
||||||
return xs
|
return xs
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,22 +0,0 @@
|
||||||
// Copyright 2018 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.11
|
|
||||||
// +build !go1.11
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
import "go/types"
|
|
||||||
|
|
||||||
func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface {
|
|
||||||
named := make([]*types.Named, len(embeddeds))
|
|
||||||
for i, e := range embeddeds {
|
|
||||||
var ok bool
|
|
||||||
named[i], ok = e.(*types.Named)
|
|
||||||
if !ok {
|
|
||||||
panic("embedding of non-defined interfaces in interfaces is not supported before Go 1.11")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return types.NewInterface(methods, named)
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
// Copyright 2018 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.11
|
|
||||||
// +build go1.11
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
import "go/types"
|
|
||||||
|
|
||||||
func newInterface(methods []*types.Func, embeddeds []types.Type) *types.Interface {
|
|
||||||
return types.NewInterfaceType(methods, embeddeds)
|
|
||||||
}
|
|
91
test/tools/vendor/golang.org/x/tools/internal/gcimporter/predeclared.go
generated
vendored
Normal file
91
test/tools/vendor/golang.org/x/tools/internal/gcimporter/predeclared.go
generated
vendored
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
// 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 gcimporter
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// predecl is a cache for the predeclared types in types.Universe.
|
||||||
|
//
|
||||||
|
// Cache a distinct result based on the runtime value of any.
|
||||||
|
// The pointer value of the any type varies based on GODEBUG settings.
|
||||||
|
var predeclMu sync.Mutex
|
||||||
|
var predecl map[types.Type][]types.Type
|
||||||
|
|
||||||
|
func predeclared() []types.Type {
|
||||||
|
anyt := types.Universe.Lookup("any").Type()
|
||||||
|
|
||||||
|
predeclMu.Lock()
|
||||||
|
defer predeclMu.Unlock()
|
||||||
|
|
||||||
|
if pre, ok := predecl[anyt]; ok {
|
||||||
|
return pre
|
||||||
|
}
|
||||||
|
|
||||||
|
if predecl == nil {
|
||||||
|
predecl = make(map[types.Type][]types.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
decls := []types.Type{ // basic types
|
||||||
|
types.Typ[types.Bool],
|
||||||
|
types.Typ[types.Int],
|
||||||
|
types.Typ[types.Int8],
|
||||||
|
types.Typ[types.Int16],
|
||||||
|
types.Typ[types.Int32],
|
||||||
|
types.Typ[types.Int64],
|
||||||
|
types.Typ[types.Uint],
|
||||||
|
types.Typ[types.Uint8],
|
||||||
|
types.Typ[types.Uint16],
|
||||||
|
types.Typ[types.Uint32],
|
||||||
|
types.Typ[types.Uint64],
|
||||||
|
types.Typ[types.Uintptr],
|
||||||
|
types.Typ[types.Float32],
|
||||||
|
types.Typ[types.Float64],
|
||||||
|
types.Typ[types.Complex64],
|
||||||
|
types.Typ[types.Complex128],
|
||||||
|
types.Typ[types.String],
|
||||||
|
|
||||||
|
// basic type aliases
|
||||||
|
types.Universe.Lookup("byte").Type(),
|
||||||
|
types.Universe.Lookup("rune").Type(),
|
||||||
|
|
||||||
|
// error
|
||||||
|
types.Universe.Lookup("error").Type(),
|
||||||
|
|
||||||
|
// untyped types
|
||||||
|
types.Typ[types.UntypedBool],
|
||||||
|
types.Typ[types.UntypedInt],
|
||||||
|
types.Typ[types.UntypedRune],
|
||||||
|
types.Typ[types.UntypedFloat],
|
||||||
|
types.Typ[types.UntypedComplex],
|
||||||
|
types.Typ[types.UntypedString],
|
||||||
|
types.Typ[types.UntypedNil],
|
||||||
|
|
||||||
|
// package unsafe
|
||||||
|
types.Typ[types.UnsafePointer],
|
||||||
|
|
||||||
|
// invalid type
|
||||||
|
types.Typ[types.Invalid], // only appears in packages with errors
|
||||||
|
|
||||||
|
// used internally by gc; never used by this package or in .a files
|
||||||
|
anyType{},
|
||||||
|
|
||||||
|
// comparable
|
||||||
|
types.Universe.Lookup("comparable").Type(),
|
||||||
|
|
||||||
|
// any
|
||||||
|
anyt,
|
||||||
|
}
|
||||||
|
|
||||||
|
predecl[anyt] = decls
|
||||||
|
return decls
|
||||||
|
}
|
||||||
|
|
||||||
|
type anyType struct{}
|
||||||
|
|
||||||
|
func (t anyType) Underlying() types.Type { return t }
|
||||||
|
func (t anyType) String() string { return "any" }
|
|
@ -1,34 +0,0 @@
|
||||||
// Copyright 2021 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
import "go/types"
|
|
||||||
|
|
||||||
const iexportVersion = iexportVersionGenerics
|
|
||||||
|
|
||||||
// additionalPredeclared returns additional predeclared types in go.1.18.
|
|
||||||
func additionalPredeclared() []types.Type {
|
|
||||||
return []types.Type{
|
|
||||||
// comparable
|
|
||||||
types.Universe.Lookup("comparable").Type(),
|
|
||||||
|
|
||||||
// any
|
|
||||||
types.Universe.Lookup("any").Type(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// See cmd/compile/internal/types.SplitVargenSuffix.
|
|
||||||
func splitVargenSuffix(name string) (base, suffix string) {
|
|
||||||
i := len(name)
|
|
||||||
for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' {
|
|
||||||
i--
|
|
||||||
}
|
|
||||||
const dot = "·"
|
|
||||||
if i >= len(dot) && name[i-len(dot):i] == dot {
|
|
||||||
i -= len(dot)
|
|
||||||
return name[:i], name[i:]
|
|
||||||
}
|
|
||||||
return name, ""
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
//go:build !goexperiment.unified
|
|
||||||
// +build !goexperiment.unified
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
const unifiedIR = false
|
|
|
@ -1,10 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
//go:build goexperiment.unified
|
|
||||||
// +build goexperiment.unified
|
|
||||||
|
|
||||||
package gcimporter
|
|
||||||
|
|
||||||
const unifiedIR = true
|
|
|
@ -562,7 +562,7 @@ func (pr *pkgReader) objIdx(idx pkgbits.Index) (*types.Package, string) {
|
||||||
// If the underlying type is an interface, we need to
|
// If the underlying type is an interface, we need to
|
||||||
// duplicate its methods so we can replace the receiver
|
// duplicate its methods so we can replace the receiver
|
||||||
// parameter's type (#49906).
|
// parameter's type (#49906).
|
||||||
if iface, ok := aliases.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
|
if iface, ok := types.Unalias(underlying).(*types.Interface); ok && iface.NumExplicitMethods() != 0 {
|
||||||
methods := make([]*types.Func, iface.NumExplicitMethods())
|
methods := make([]*types.Func, iface.NumExplicitMethods())
|
||||||
for i := range methods {
|
for i := range methods {
|
||||||
fn := iface.ExplicitMethod(i)
|
fn := iface.ExplicitMethod(i)
|
||||||
|
@ -738,3 +738,17 @@ func pkgScope(pkg *types.Package) *types.Scope {
|
||||||
}
|
}
|
||||||
return types.Universe
|
return types.Universe
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// See cmd/compile/internal/types.SplitVargenSuffix.
|
||||||
|
func splitVargenSuffix(name string) (base, suffix string) {
|
||||||
|
i := len(name)
|
||||||
|
for i > 0 && name[i-1] >= '0' && name[i-1] <= '9' {
|
||||||
|
i--
|
||||||
|
}
|
||||||
|
const dot = "·"
|
||||||
|
if i >= len(dot) && name[i-len(dot):i] == dot {
|
||||||
|
i -= len(dot)
|
||||||
|
return name[:i], name[i:]
|
||||||
|
}
|
||||||
|
return name, ""
|
||||||
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"reflect"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -250,16 +249,13 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
|
||||||
cmd.Stdout = stdout
|
cmd.Stdout = stdout
|
||||||
cmd.Stderr = stderr
|
cmd.Stderr = stderr
|
||||||
|
|
||||||
// cmd.WaitDelay was added only in go1.20 (see #50436).
|
// https://go.dev/issue/59541: don't wait forever copying stderr
|
||||||
if waitDelay := reflect.ValueOf(cmd).Elem().FieldByName("WaitDelay"); waitDelay.IsValid() {
|
// after the command has exited.
|
||||||
// https://go.dev/issue/59541: don't wait forever copying stderr
|
// After CL 484741 we copy stdout manually, so we we'll stop reading that as
|
||||||
// after the command has exited.
|
// soon as ctx is done. However, we also don't want to wait around forever
|
||||||
// After CL 484741 we copy stdout manually, so we we'll stop reading that as
|
// for stderr. Give a much-longer-than-reasonable delay and then assume that
|
||||||
// soon as ctx is done. However, we also don't want to wait around forever
|
// something has wedged in the kernel or runtime.
|
||||||
// for stderr. Give a much-longer-than-reasonable delay and then assume that
|
cmd.WaitDelay = 30 * time.Second
|
||||||
// something has wedged in the kernel or runtime.
|
|
||||||
waitDelay.Set(reflect.ValueOf(30 * time.Second))
|
|
||||||
}
|
|
||||||
|
|
||||||
// The cwd gets resolved to the real path. On Darwin, where
|
// The cwd gets resolved to the real path. On Darwin, where
|
||||||
// /tmp is a symlink, this breaks anything that expects the
|
// /tmp is a symlink, this breaks anything that expects the
|
||||||
|
|
|
@ -131,7 +131,7 @@ func parseOtherFiles(ctx context.Context, fset *token.FileSet, srcDir, filename
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := parser.ParseFile(fset, filepath.Join(srcDir, fi.Name()), nil, 0)
|
f, err := parser.ParseFile(fset, filepath.Join(srcDir, fi.Name()), nil, parser.SkipObjectResolution)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -1620,6 +1620,7 @@ func loadExportsFromFiles(ctx context.Context, env *ProcessEnv, dir string, incl
|
||||||
}
|
}
|
||||||
|
|
||||||
fullFile := filepath.Join(dir, fi.Name())
|
fullFile := filepath.Join(dir, fi.Name())
|
||||||
|
// Legacy ast.Object resolution is needed here.
|
||||||
f, err := parser.ParseFile(fset, fullFile, nil, 0)
|
f, err := parser.ParseFile(fset, fullFile, nil, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
env.logf("error parsing %v: %v", fullFile, err)
|
env.logf("error parsing %v: %v", fullFile, err)
|
||||||
|
|
|
@ -86,7 +86,7 @@ func ApplyFixes(fixes []*ImportFix, filename string, src []byte, opt *Options, e
|
||||||
// Don't use parse() -- we don't care about fragments or statement lists
|
// Don't use parse() -- we don't care about fragments or statement lists
|
||||||
// here, and we need to work with unparseable files.
|
// here, and we need to work with unparseable files.
|
||||||
fileSet := token.NewFileSet()
|
fileSet := token.NewFileSet()
|
||||||
parserMode := parser.Mode(0)
|
parserMode := parser.SkipObjectResolution
|
||||||
if opt.Comments {
|
if opt.Comments {
|
||||||
parserMode |= parser.ParseComments
|
parserMode |= parser.ParseComments
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@ func formatFile(fset *token.FileSet, file *ast.File, src []byte, adjust func(ori
|
||||||
// parse parses src, which was read from filename,
|
// parse parses src, which was read from filename,
|
||||||
// as a Go source file or statement list.
|
// as a Go source file or statement list.
|
||||||
func parse(fset *token.FileSet, filename string, src []byte, opt *Options) (*ast.File, func(orig, src []byte) []byte, error) {
|
func parse(fset *token.FileSet, filename string, src []byte, opt *Options) (*ast.File, func(orig, src []byte) []byte, error) {
|
||||||
parserMode := parser.Mode(0)
|
var parserMode parser.Mode // legacy ast.Object resolution is required here
|
||||||
if opt.Comments {
|
if opt.Comments {
|
||||||
parserMode |= parser.ParseComments
|
parserMode |= parser.ParseComments
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,137 +0,0 @@
|
||||||
// Copyright 2023 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// package tokeninternal provides access to some internal features of the token
|
|
||||||
// package.
|
|
||||||
package tokeninternal
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"go/token"
|
|
||||||
"sort"
|
|
||||||
"sync"
|
|
||||||
"unsafe"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GetLines returns the table of line-start offsets from a token.File.
|
|
||||||
func GetLines(file *token.File) []int {
|
|
||||||
// token.File has a Lines method on Go 1.21 and later.
|
|
||||||
if file, ok := (interface{})(file).(interface{ Lines() []int }); ok {
|
|
||||||
return file.Lines()
|
|
||||||
}
|
|
||||||
|
|
||||||
// This declaration must match that of token.File.
|
|
||||||
// This creates a risk of dependency skew.
|
|
||||||
// For now we check that the size of the two
|
|
||||||
// declarations is the same, on the (fragile) assumption
|
|
||||||
// that future changes would add fields.
|
|
||||||
type tokenFile119 struct {
|
|
||||||
_ string
|
|
||||||
_ int
|
|
||||||
_ int
|
|
||||||
mu sync.Mutex // we're not complete monsters
|
|
||||||
lines []int
|
|
||||||
_ []struct{}
|
|
||||||
}
|
|
||||||
|
|
||||||
if unsafe.Sizeof(*file) != unsafe.Sizeof(tokenFile119{}) {
|
|
||||||
panic("unexpected token.File size")
|
|
||||||
}
|
|
||||||
var ptr *tokenFile119
|
|
||||||
type uP = unsafe.Pointer
|
|
||||||
*(*uP)(uP(&ptr)) = uP(file)
|
|
||||||
ptr.mu.Lock()
|
|
||||||
defer ptr.mu.Unlock()
|
|
||||||
return ptr.lines
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddExistingFiles adds the specified files to the FileSet if they
|
|
||||||
// are not already present. It panics if any pair of files in the
|
|
||||||
// resulting FileSet would overlap.
|
|
||||||
func AddExistingFiles(fset *token.FileSet, files []*token.File) {
|
|
||||||
// Punch through the FileSet encapsulation.
|
|
||||||
type tokenFileSet struct {
|
|
||||||
// This type remained essentially consistent from go1.16 to go1.21.
|
|
||||||
mutex sync.RWMutex
|
|
||||||
base int
|
|
||||||
files []*token.File
|
|
||||||
_ *token.File // changed to atomic.Pointer[token.File] in go1.19
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the size of token.FileSet changes, this will fail to compile.
|
|
||||||
const delta = int64(unsafe.Sizeof(tokenFileSet{})) - int64(unsafe.Sizeof(token.FileSet{}))
|
|
||||||
var _ [-delta * delta]int
|
|
||||||
|
|
||||||
type uP = unsafe.Pointer
|
|
||||||
var ptr *tokenFileSet
|
|
||||||
*(*uP)(uP(&ptr)) = uP(fset)
|
|
||||||
ptr.mutex.Lock()
|
|
||||||
defer ptr.mutex.Unlock()
|
|
||||||
|
|
||||||
// Merge and sort.
|
|
||||||
newFiles := append(ptr.files, files...)
|
|
||||||
sort.Slice(newFiles, func(i, j int) bool {
|
|
||||||
return newFiles[i].Base() < newFiles[j].Base()
|
|
||||||
})
|
|
||||||
|
|
||||||
// Reject overlapping files.
|
|
||||||
// Discard adjacent identical files.
|
|
||||||
out := newFiles[:0]
|
|
||||||
for i, file := range newFiles {
|
|
||||||
if i > 0 {
|
|
||||||
prev := newFiles[i-1]
|
|
||||||
if file == prev {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if prev.Base()+prev.Size()+1 > file.Base() {
|
|
||||||
panic(fmt.Sprintf("file %s (%d-%d) overlaps with file %s (%d-%d)",
|
|
||||||
prev.Name(), prev.Base(), prev.Base()+prev.Size(),
|
|
||||||
file.Name(), file.Base(), file.Base()+file.Size()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out = append(out, file)
|
|
||||||
}
|
|
||||||
newFiles = out
|
|
||||||
|
|
||||||
ptr.files = newFiles
|
|
||||||
|
|
||||||
// Advance FileSet.Base().
|
|
||||||
if len(newFiles) > 0 {
|
|
||||||
last := newFiles[len(newFiles)-1]
|
|
||||||
newBase := last.Base() + last.Size() + 1
|
|
||||||
if ptr.base < newBase {
|
|
||||||
ptr.base = newBase
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FileSetFor returns a new FileSet containing a sequence of new Files with
|
|
||||||
// the same base, size, and line as the input files, for use in APIs that
|
|
||||||
// require a FileSet.
|
|
||||||
//
|
|
||||||
// Precondition: the input files must be non-overlapping, and sorted in order
|
|
||||||
// of their Base.
|
|
||||||
func FileSetFor(files ...*token.File) *token.FileSet {
|
|
||||||
fset := token.NewFileSet()
|
|
||||||
for _, f := range files {
|
|
||||||
f2 := fset.AddFile(f.Name(), f.Base(), f.Size())
|
|
||||||
lines := GetLines(f)
|
|
||||||
f2.SetLines(lines)
|
|
||||||
}
|
|
||||||
return fset
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloneFileSet creates a new FileSet holding all files in fset. It does not
|
|
||||||
// create copies of the token.Files in fset: they are added to the resulting
|
|
||||||
// FileSet unmodified.
|
|
||||||
func CloneFileSet(fset *token.FileSet) *token.FileSet {
|
|
||||||
var files []*token.File
|
|
||||||
fset.Iterate(func(f *token.File) bool {
|
|
||||||
files = append(files, f)
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
newFileSet := token.NewFileSet()
|
|
||||||
AddExistingFiles(newFileSet, files)
|
|
||||||
return newFileSet
|
|
||||||
}
|
|
140
test/tools/vendor/golang.org/x/tools/internal/typeparams/common.go
generated
vendored
Normal file
140
test/tools/vendor/golang.org/x/tools/internal/typeparams/common.go
generated
vendored
Normal file
|
@ -0,0 +1,140 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Package typeparams contains common utilities for writing tools that
|
||||||
|
// interact with generic Go code, as introduced with Go 1.18. It
|
||||||
|
// supplements the standard library APIs. Notably, the StructuralTerms
|
||||||
|
// API computes a minimal representation of the structural
|
||||||
|
// restrictions on a type parameter.
|
||||||
|
//
|
||||||
|
// An external version of these APIs is available in the
|
||||||
|
// golang.org/x/exp/typeparams module.
|
||||||
|
package typeparams
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/ast"
|
||||||
|
"go/token"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// UnpackIndexExpr extracts data from AST nodes that represent index
|
||||||
|
// expressions.
|
||||||
|
//
|
||||||
|
// For an ast.IndexExpr, the resulting indices slice will contain exactly one
|
||||||
|
// index expression. For an ast.IndexListExpr (go1.18+), it may have a variable
|
||||||
|
// number of index expressions.
|
||||||
|
//
|
||||||
|
// For nodes that don't represent index expressions, the first return value of
|
||||||
|
// UnpackIndexExpr will be nil.
|
||||||
|
func UnpackIndexExpr(n ast.Node) (x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) {
|
||||||
|
switch e := n.(type) {
|
||||||
|
case *ast.IndexExpr:
|
||||||
|
return e.X, e.Lbrack, []ast.Expr{e.Index}, e.Rbrack
|
||||||
|
case *ast.IndexListExpr:
|
||||||
|
return e.X, e.Lbrack, e.Indices, e.Rbrack
|
||||||
|
}
|
||||||
|
return nil, token.NoPos, nil, token.NoPos
|
||||||
|
}
|
||||||
|
|
||||||
|
// PackIndexExpr returns an *ast.IndexExpr or *ast.IndexListExpr, depending on
|
||||||
|
// the cardinality of indices. Calling PackIndexExpr with len(indices) == 0
|
||||||
|
// will panic.
|
||||||
|
func PackIndexExpr(x ast.Expr, lbrack token.Pos, indices []ast.Expr, rbrack token.Pos) ast.Expr {
|
||||||
|
switch len(indices) {
|
||||||
|
case 0:
|
||||||
|
panic("empty indices")
|
||||||
|
case 1:
|
||||||
|
return &ast.IndexExpr{
|
||||||
|
X: x,
|
||||||
|
Lbrack: lbrack,
|
||||||
|
Index: indices[0],
|
||||||
|
Rbrack: rbrack,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return &ast.IndexListExpr{
|
||||||
|
X: x,
|
||||||
|
Lbrack: lbrack,
|
||||||
|
Indices: indices,
|
||||||
|
Rbrack: rbrack,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// IsTypeParam reports whether t is a type parameter (or an alias of one).
|
||||||
|
func IsTypeParam(t types.Type) bool {
|
||||||
|
_, ok := types.Unalias(t).(*types.TypeParam)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenericAssignableTo is a generalization of types.AssignableTo that
|
||||||
|
// implements the following rule for uninstantiated generic types:
|
||||||
|
//
|
||||||
|
// If V and T are generic named types, then V is considered assignable to T if,
|
||||||
|
// for every possible instantiation of V[A_1, ..., A_N], the instantiation
|
||||||
|
// T[A_1, ..., A_N] is valid and V[A_1, ..., A_N] implements T[A_1, ..., A_N].
|
||||||
|
//
|
||||||
|
// If T has structural constraints, they must be satisfied by V.
|
||||||
|
//
|
||||||
|
// For example, consider the following type declarations:
|
||||||
|
//
|
||||||
|
// type Interface[T any] interface {
|
||||||
|
// Accept(T)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// type Container[T any] struct {
|
||||||
|
// Element T
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (c Container[T]) Accept(t T) { c.Element = t }
|
||||||
|
//
|
||||||
|
// In this case, GenericAssignableTo reports that instantiations of Container
|
||||||
|
// are assignable to the corresponding instantiation of Interface.
|
||||||
|
func GenericAssignableTo(ctxt *types.Context, V, T types.Type) bool {
|
||||||
|
V = types.Unalias(V)
|
||||||
|
T = types.Unalias(T)
|
||||||
|
|
||||||
|
// If V and T are not both named, or do not have matching non-empty type
|
||||||
|
// parameter lists, fall back on types.AssignableTo.
|
||||||
|
|
||||||
|
VN, Vnamed := V.(*types.Named)
|
||||||
|
TN, Tnamed := T.(*types.Named)
|
||||||
|
if !Vnamed || !Tnamed {
|
||||||
|
return types.AssignableTo(V, T)
|
||||||
|
}
|
||||||
|
|
||||||
|
vtparams := VN.TypeParams()
|
||||||
|
ttparams := TN.TypeParams()
|
||||||
|
if vtparams.Len() == 0 || vtparams.Len() != ttparams.Len() || VN.TypeArgs().Len() != 0 || TN.TypeArgs().Len() != 0 {
|
||||||
|
return types.AssignableTo(V, T)
|
||||||
|
}
|
||||||
|
|
||||||
|
// V and T have the same (non-zero) number of type params. Instantiate both
|
||||||
|
// with the type parameters of V. This must always succeed for V, and will
|
||||||
|
// succeed for T if and only if the type set of each type parameter of V is a
|
||||||
|
// subset of the type set of the corresponding type parameter of T, meaning
|
||||||
|
// that every instantiation of V corresponds to a valid instantiation of T.
|
||||||
|
|
||||||
|
// Minor optimization: ensure we share a context across the two
|
||||||
|
// instantiations below.
|
||||||
|
if ctxt == nil {
|
||||||
|
ctxt = types.NewContext()
|
||||||
|
}
|
||||||
|
|
||||||
|
var targs []types.Type
|
||||||
|
for i := 0; i < vtparams.Len(); i++ {
|
||||||
|
targs = append(targs, vtparams.At(i))
|
||||||
|
}
|
||||||
|
|
||||||
|
vinst, err := types.Instantiate(ctxt, V, targs, true)
|
||||||
|
if err != nil {
|
||||||
|
panic("type parameters should satisfy their own constraints")
|
||||||
|
}
|
||||||
|
|
||||||
|
tinst, err := types.Instantiate(ctxt, T, targs, true)
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.AssignableTo(vinst, tinst)
|
||||||
|
}
|
150
test/tools/vendor/golang.org/x/tools/internal/typeparams/coretype.go
generated
vendored
Normal file
150
test/tools/vendor/golang.org/x/tools/internal/typeparams/coretype.go
generated
vendored
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
package typeparams
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// CoreType returns the core type of T or nil if T does not have a core type.
|
||||||
|
//
|
||||||
|
// See https://go.dev/ref/spec#Core_types for the definition of a core type.
|
||||||
|
func CoreType(T types.Type) types.Type {
|
||||||
|
U := T.Underlying()
|
||||||
|
if _, ok := U.(*types.Interface); !ok {
|
||||||
|
return U // for non-interface types,
|
||||||
|
}
|
||||||
|
|
||||||
|
terms, err := NormalTerms(U)
|
||||||
|
if len(terms) == 0 || err != nil {
|
||||||
|
// len(terms) -> empty type set of interface.
|
||||||
|
// err != nil => U is invalid, exceeds complexity bounds, or has an empty type set.
|
||||||
|
return nil // no core type.
|
||||||
|
}
|
||||||
|
|
||||||
|
U = terms[0].Type().Underlying()
|
||||||
|
var identical int // i in [0,identical) => Identical(U, terms[i].Type().Underlying())
|
||||||
|
for identical = 1; identical < len(terms); identical++ {
|
||||||
|
if !types.Identical(U, terms[identical].Type().Underlying()) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if identical == len(terms) {
|
||||||
|
// https://go.dev/ref/spec#Core_types
|
||||||
|
// "There is a single type U which is the underlying type of all types in the type set of T"
|
||||||
|
return U
|
||||||
|
}
|
||||||
|
ch, ok := U.(*types.Chan)
|
||||||
|
if !ok {
|
||||||
|
return nil // no core type as identical < len(terms) and U is not a channel.
|
||||||
|
}
|
||||||
|
// https://go.dev/ref/spec#Core_types
|
||||||
|
// "the type chan E if T contains only bidirectional channels, or the type chan<- E or
|
||||||
|
// <-chan E depending on the direction of the directional channels present."
|
||||||
|
for chans := identical; chans < len(terms); chans++ {
|
||||||
|
curr, ok := terms[chans].Type().Underlying().(*types.Chan)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
if !types.Identical(ch.Elem(), curr.Elem()) {
|
||||||
|
return nil // channel elements are not identical.
|
||||||
|
}
|
||||||
|
if ch.Dir() == types.SendRecv {
|
||||||
|
// ch is bidirectional. We can safely always use curr's direction.
|
||||||
|
ch = curr
|
||||||
|
} else if curr.Dir() != types.SendRecv && ch.Dir() != curr.Dir() {
|
||||||
|
// ch and curr are not bidirectional and not the same direction.
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ch
|
||||||
|
}
|
||||||
|
|
||||||
|
// NormalTerms returns a slice of terms representing the normalized structural
|
||||||
|
// type restrictions of a type, if any.
|
||||||
|
//
|
||||||
|
// For all types other than *types.TypeParam, *types.Interface, and
|
||||||
|
// *types.Union, this is just a single term with Tilde() == false and
|
||||||
|
// Type() == typ. For *types.TypeParam, *types.Interface, and *types.Union, see
|
||||||
|
// below.
|
||||||
|
//
|
||||||
|
// Structural type restrictions of a type parameter are created via
|
||||||
|
// non-interface types embedded in its constraint interface (directly, or via a
|
||||||
|
// chain of interface embeddings). For example, in the declaration type
|
||||||
|
// T[P interface{~int; m()}] int the structural restriction of the type
|
||||||
|
// parameter P is ~int.
|
||||||
|
//
|
||||||
|
// With interface embedding and unions, the specification of structural type
|
||||||
|
// restrictions may be arbitrarily complex. For example, consider the
|
||||||
|
// following:
|
||||||
|
//
|
||||||
|
// type A interface{ ~string|~[]byte }
|
||||||
|
//
|
||||||
|
// type B interface{ int|string }
|
||||||
|
//
|
||||||
|
// type C interface { ~string|~int }
|
||||||
|
//
|
||||||
|
// type T[P interface{ A|B; C }] int
|
||||||
|
//
|
||||||
|
// In this example, the structural type restriction of P is ~string|int: A|B
|
||||||
|
// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
|
||||||
|
// which when intersected with C (~string|~int) yields ~string|int.
|
||||||
|
//
|
||||||
|
// NormalTerms computes these expansions and reductions, producing a
|
||||||
|
// "normalized" form of the embeddings. A structural restriction is normalized
|
||||||
|
// if it is a single union containing no interface terms, and is minimal in the
|
||||||
|
// sense that removing any term changes the set of types satisfying the
|
||||||
|
// constraint. It is left as a proof for the reader that, modulo sorting, there
|
||||||
|
// is exactly one such normalized form.
|
||||||
|
//
|
||||||
|
// Because the minimal representation always takes this form, NormalTerms
|
||||||
|
// returns a slice of tilde terms corresponding to the terms of the union in
|
||||||
|
// the normalized structural restriction. An error is returned if the type is
|
||||||
|
// invalid, exceeds complexity bounds, or has an empty type set. In the latter
|
||||||
|
// case, NormalTerms returns ErrEmptyTypeSet.
|
||||||
|
//
|
||||||
|
// NormalTerms makes no guarantees about the order of terms, except that it
|
||||||
|
// is deterministic.
|
||||||
|
func NormalTerms(typ types.Type) ([]*types.Term, error) {
|
||||||
|
switch typ := typ.Underlying().(type) {
|
||||||
|
case *types.TypeParam:
|
||||||
|
return StructuralTerms(typ)
|
||||||
|
case *types.Union:
|
||||||
|
return UnionTermSet(typ)
|
||||||
|
case *types.Interface:
|
||||||
|
return InterfaceTermSet(typ)
|
||||||
|
default:
|
||||||
|
return []*types.Term{types.NewTerm(false, typ)}, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deref returns the type of the variable pointed to by t,
|
||||||
|
// if t's core type is a pointer; otherwise it returns t.
|
||||||
|
//
|
||||||
|
// Do not assume that Deref(T)==T implies T is not a pointer:
|
||||||
|
// consider "type T *T", for example.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): ideally this would live in typesinternal, but that
|
||||||
|
// creates an import cycle. Move there when we melt this package down.
|
||||||
|
func Deref(t types.Type) types.Type {
|
||||||
|
if ptr, ok := CoreType(t).(*types.Pointer); ok {
|
||||||
|
return ptr.Elem()
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustDeref returns the type of the variable pointed to by t.
|
||||||
|
// It panics if t's core type is not a pointer.
|
||||||
|
//
|
||||||
|
// TODO(adonovan): ideally this would live in typesinternal, but that
|
||||||
|
// creates an import cycle. Move there when we melt this package down.
|
||||||
|
func MustDeref(t types.Type) types.Type {
|
||||||
|
if ptr, ok := CoreType(t).(*types.Pointer); ok {
|
||||||
|
return ptr.Elem()
|
||||||
|
}
|
||||||
|
panic(fmt.Sprintf("%v is not a pointer", t))
|
||||||
|
}
|
|
@ -0,0 +1,118 @@
|
||||||
|
// 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 typeparams
|
||||||
|
|
||||||
|
import (
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Free is a memoization of the set of free type parameters within a
|
||||||
|
// type. It makes a sequence of calls to [Free.Has] for overlapping
|
||||||
|
// types more efficient. The zero value is ready for use.
|
||||||
|
//
|
||||||
|
// NOTE: Adapted from go/types/infer.go. If it is later exported, factor.
|
||||||
|
type Free struct {
|
||||||
|
seen map[types.Type]bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// Has reports whether the specified type has a free type parameter.
|
||||||
|
func (w *Free) Has(typ types.Type) (res bool) {
|
||||||
|
// detect cycles
|
||||||
|
if x, ok := w.seen[typ]; ok {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
if w.seen == nil {
|
||||||
|
w.seen = make(map[types.Type]bool)
|
||||||
|
}
|
||||||
|
w.seen[typ] = false
|
||||||
|
defer func() {
|
||||||
|
w.seen[typ] = res
|
||||||
|
}()
|
||||||
|
|
||||||
|
switch t := typ.(type) {
|
||||||
|
case nil, *types.Basic: // TODO(gri) should nil be handled here?
|
||||||
|
break
|
||||||
|
|
||||||
|
case *types.Alias:
|
||||||
|
return w.Has(types.Unalias(t))
|
||||||
|
|
||||||
|
case *types.Array:
|
||||||
|
return w.Has(t.Elem())
|
||||||
|
|
||||||
|
case *types.Slice:
|
||||||
|
return w.Has(t.Elem())
|
||||||
|
|
||||||
|
case *types.Struct:
|
||||||
|
for i, n := 0, t.NumFields(); i < n; i++ {
|
||||||
|
if w.Has(t.Field(i).Type()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Pointer:
|
||||||
|
return w.Has(t.Elem())
|
||||||
|
|
||||||
|
case *types.Tuple:
|
||||||
|
n := t.Len()
|
||||||
|
for i := 0; i < n; i++ {
|
||||||
|
if w.Has(t.At(i).Type()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Signature:
|
||||||
|
// t.tparams may not be nil if we are looking at a signature
|
||||||
|
// of a generic function type (or an interface method) that is
|
||||||
|
// part of the type we're testing. We don't care about these type
|
||||||
|
// parameters.
|
||||||
|
// Similarly, the receiver of a method may declare (rather than
|
||||||
|
// use) type parameters, we don't care about those either.
|
||||||
|
// Thus, we only need to look at the input and result parameters.
|
||||||
|
return w.Has(t.Params()) || w.Has(t.Results())
|
||||||
|
|
||||||
|
case *types.Interface:
|
||||||
|
for i, n := 0, t.NumMethods(); i < n; i++ {
|
||||||
|
if w.Has(t.Method(i).Type()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
terms, err := InterfaceTermSet(t)
|
||||||
|
if err != nil {
|
||||||
|
return false // ill typed
|
||||||
|
}
|
||||||
|
for _, term := range terms {
|
||||||
|
if w.Has(term.Type()) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Map:
|
||||||
|
return w.Has(t.Key()) || w.Has(t.Elem())
|
||||||
|
|
||||||
|
case *types.Chan:
|
||||||
|
return w.Has(t.Elem())
|
||||||
|
|
||||||
|
case *types.Named:
|
||||||
|
args := t.TypeArgs()
|
||||||
|
// TODO(taking): this does not match go/types/infer.go. Check with rfindley.
|
||||||
|
if params := t.TypeParams(); params.Len() > args.Len() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
for i, n := 0, args.Len(); i < n; i++ {
|
||||||
|
if w.Has(args.At(i)) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return w.Has(t.Underlying()) // recurse for types local to parameterized functions
|
||||||
|
|
||||||
|
case *types.TypeParam:
|
||||||
|
return true
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(t) // unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
218
test/tools/vendor/golang.org/x/tools/internal/typeparams/normalize.go
generated
vendored
Normal file
218
test/tools/vendor/golang.org/x/tools/internal/typeparams/normalize.go
generated
vendored
Normal file
|
@ -0,0 +1,218 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package typeparams
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go run copytermlist.go
|
||||||
|
|
||||||
|
const debug = false
|
||||||
|
|
||||||
|
var ErrEmptyTypeSet = errors.New("empty type set")
|
||||||
|
|
||||||
|
// StructuralTerms returns a slice of terms representing the normalized
|
||||||
|
// structural type restrictions of a type parameter, if any.
|
||||||
|
//
|
||||||
|
// Structural type restrictions of a type parameter are created via
|
||||||
|
// non-interface types embedded in its constraint interface (directly, or via a
|
||||||
|
// chain of interface embeddings). For example, in the declaration
|
||||||
|
//
|
||||||
|
// type T[P interface{~int; m()}] int
|
||||||
|
//
|
||||||
|
// the structural restriction of the type parameter P is ~int.
|
||||||
|
//
|
||||||
|
// With interface embedding and unions, the specification of structural type
|
||||||
|
// restrictions may be arbitrarily complex. For example, consider the
|
||||||
|
// following:
|
||||||
|
//
|
||||||
|
// type A interface{ ~string|~[]byte }
|
||||||
|
//
|
||||||
|
// type B interface{ int|string }
|
||||||
|
//
|
||||||
|
// type C interface { ~string|~int }
|
||||||
|
//
|
||||||
|
// type T[P interface{ A|B; C }] int
|
||||||
|
//
|
||||||
|
// In this example, the structural type restriction of P is ~string|int: A|B
|
||||||
|
// expands to ~string|~[]byte|int|string, which reduces to ~string|~[]byte|int,
|
||||||
|
// which when intersected with C (~string|~int) yields ~string|int.
|
||||||
|
//
|
||||||
|
// StructuralTerms computes these expansions and reductions, producing a
|
||||||
|
// "normalized" form of the embeddings. A structural restriction is normalized
|
||||||
|
// if it is a single union containing no interface terms, and is minimal in the
|
||||||
|
// sense that removing any term changes the set of types satisfying the
|
||||||
|
// constraint. It is left as a proof for the reader that, modulo sorting, there
|
||||||
|
// is exactly one such normalized form.
|
||||||
|
//
|
||||||
|
// Because the minimal representation always takes this form, StructuralTerms
|
||||||
|
// returns a slice of tilde terms corresponding to the terms of the union in
|
||||||
|
// the normalized structural restriction. An error is returned if the
|
||||||
|
// constraint interface is invalid, exceeds complexity bounds, or has an empty
|
||||||
|
// type set. In the latter case, StructuralTerms returns ErrEmptyTypeSet.
|
||||||
|
//
|
||||||
|
// StructuralTerms makes no guarantees about the order of terms, except that it
|
||||||
|
// is deterministic.
|
||||||
|
func StructuralTerms(tparam *types.TypeParam) ([]*types.Term, error) {
|
||||||
|
constraint := tparam.Constraint()
|
||||||
|
if constraint == nil {
|
||||||
|
return nil, fmt.Errorf("%s has nil constraint", tparam)
|
||||||
|
}
|
||||||
|
iface, _ := constraint.Underlying().(*types.Interface)
|
||||||
|
if iface == nil {
|
||||||
|
return nil, fmt.Errorf("constraint is %T, not *types.Interface", constraint.Underlying())
|
||||||
|
}
|
||||||
|
return InterfaceTermSet(iface)
|
||||||
|
}
|
||||||
|
|
||||||
|
// InterfaceTermSet computes the normalized terms for a constraint interface,
|
||||||
|
// returning an error if the term set cannot be computed or is empty. In the
|
||||||
|
// latter case, the error will be ErrEmptyTypeSet.
|
||||||
|
//
|
||||||
|
// See the documentation of StructuralTerms for more information on
|
||||||
|
// normalization.
|
||||||
|
func InterfaceTermSet(iface *types.Interface) ([]*types.Term, error) {
|
||||||
|
return computeTermSet(iface)
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnionTermSet computes the normalized terms for a union, returning an error
|
||||||
|
// if the term set cannot be computed or is empty. In the latter case, the
|
||||||
|
// error will be ErrEmptyTypeSet.
|
||||||
|
//
|
||||||
|
// See the documentation of StructuralTerms for more information on
|
||||||
|
// normalization.
|
||||||
|
func UnionTermSet(union *types.Union) ([]*types.Term, error) {
|
||||||
|
return computeTermSet(union)
|
||||||
|
}
|
||||||
|
|
||||||
|
func computeTermSet(typ types.Type) ([]*types.Term, error) {
|
||||||
|
tset, err := computeTermSetInternal(typ, make(map[types.Type]*termSet), 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if tset.terms.isEmpty() {
|
||||||
|
return nil, ErrEmptyTypeSet
|
||||||
|
}
|
||||||
|
if tset.terms.isAll() {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
var terms []*types.Term
|
||||||
|
for _, term := range tset.terms {
|
||||||
|
terms = append(terms, types.NewTerm(term.tilde, term.typ))
|
||||||
|
}
|
||||||
|
return terms, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// A termSet holds the normalized set of terms for a given type.
|
||||||
|
//
|
||||||
|
// The name termSet is intentionally distinct from 'type set': a type set is
|
||||||
|
// all types that implement a type (and includes method restrictions), whereas
|
||||||
|
// a term set just represents the structural restrictions on a type.
|
||||||
|
type termSet struct {
|
||||||
|
complete bool
|
||||||
|
terms termlist
|
||||||
|
}
|
||||||
|
|
||||||
|
func indentf(depth int, format string, args ...interface{}) {
|
||||||
|
fmt.Fprintf(os.Stderr, strings.Repeat(".", depth)+format+"\n", args...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func computeTermSetInternal(t types.Type, seen map[types.Type]*termSet, depth int) (res *termSet, err error) {
|
||||||
|
if t == nil {
|
||||||
|
panic("nil type")
|
||||||
|
}
|
||||||
|
|
||||||
|
if debug {
|
||||||
|
indentf(depth, "%s", t.String())
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
indentf(depth, "=> %s", err)
|
||||||
|
} else {
|
||||||
|
indentf(depth, "=> %s", res.terms.String())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
|
|
||||||
|
const maxTermCount = 100
|
||||||
|
if tset, ok := seen[t]; ok {
|
||||||
|
if !tset.complete {
|
||||||
|
return nil, fmt.Errorf("cycle detected in the declaration of %s", t)
|
||||||
|
}
|
||||||
|
return tset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mark the current type as seen to avoid infinite recursion.
|
||||||
|
tset := new(termSet)
|
||||||
|
defer func() {
|
||||||
|
tset.complete = true
|
||||||
|
}()
|
||||||
|
seen[t] = tset
|
||||||
|
|
||||||
|
switch u := t.Underlying().(type) {
|
||||||
|
case *types.Interface:
|
||||||
|
// The term set of an interface is the intersection of the term sets of its
|
||||||
|
// embedded types.
|
||||||
|
tset.terms = allTermlist
|
||||||
|
for i := 0; i < u.NumEmbeddeds(); i++ {
|
||||||
|
embedded := u.EmbeddedType(i)
|
||||||
|
if _, ok := embedded.Underlying().(*types.TypeParam); ok {
|
||||||
|
return nil, fmt.Errorf("invalid embedded type %T", embedded)
|
||||||
|
}
|
||||||
|
tset2, err := computeTermSetInternal(embedded, seen, depth+1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
tset.terms = tset.terms.intersect(tset2.terms)
|
||||||
|
}
|
||||||
|
case *types.Union:
|
||||||
|
// The term set of a union is the union of term sets of its terms.
|
||||||
|
tset.terms = nil
|
||||||
|
for i := 0; i < u.Len(); i++ {
|
||||||
|
t := u.Term(i)
|
||||||
|
var terms termlist
|
||||||
|
switch t.Type().Underlying().(type) {
|
||||||
|
case *types.Interface:
|
||||||
|
tset2, err := computeTermSetInternal(t.Type(), seen, depth+1)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
terms = tset2.terms
|
||||||
|
case *types.TypeParam, *types.Union:
|
||||||
|
// A stand-alone type parameter or union is not permitted as union
|
||||||
|
// term.
|
||||||
|
return nil, fmt.Errorf("invalid union term %T", t)
|
||||||
|
default:
|
||||||
|
if t.Type() == types.Typ[types.Invalid] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
terms = termlist{{t.Tilde(), t.Type()}}
|
||||||
|
}
|
||||||
|
tset.terms = tset.terms.union(terms)
|
||||||
|
if len(tset.terms) > maxTermCount {
|
||||||
|
return nil, fmt.Errorf("exceeded max term count %d", maxTermCount)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case *types.TypeParam:
|
||||||
|
panic("unreachable")
|
||||||
|
default:
|
||||||
|
// For all other types, the term set is just a single non-tilde term
|
||||||
|
// holding the type itself.
|
||||||
|
if u != types.Typ[types.Invalid] {
|
||||||
|
tset.terms = termlist{{false, t}}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tset, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// under is a facade for the go/types internal function of the same name. It is
|
||||||
|
// used by typeterm.go.
|
||||||
|
func under(t types.Type) types.Type {
|
||||||
|
return t.Underlying()
|
||||||
|
}
|
163
test/tools/vendor/golang.org/x/tools/internal/typeparams/termlist.go
generated
vendored
Normal file
163
test/tools/vendor/golang.org/x/tools/internal/typeparams/termlist.go
generated
vendored
Normal file
|
@ -0,0 +1,163 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Code generated by copytermlist.go DO NOT EDIT.
|
||||||
|
|
||||||
|
package typeparams
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"go/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
// A termlist represents the type set represented by the union
|
||||||
|
// t1 ∪ y2 ∪ ... tn of the type sets of the terms t1 to tn.
|
||||||
|
// A termlist is in normal form if all terms are disjoint.
|
||||||
|
// termlist operations don't require the operands to be in
|
||||||
|
// normal form.
|
||||||
|
type termlist []*term
|
||||||
|
|
||||||
|
// allTermlist represents the set of all types.
|
||||||
|
// It is in normal form.
|
||||||
|
var allTermlist = termlist{new(term)}
|
||||||
|
|
||||||
|
// String prints the termlist exactly (without normalization).
|
||||||
|
func (xl termlist) String() string {
|
||||||
|
if len(xl) == 0 {
|
||||||
|
return "∅"
|
||||||
|
}
|
||||||
|
var buf bytes.Buffer
|
||||||
|
for i, x := range xl {
|
||||||
|
if i > 0 {
|
||||||
|
buf.WriteString(" | ")
|
||||||
|
}
|
||||||
|
buf.WriteString(x.String())
|
||||||
|
}
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
// isEmpty reports whether the termlist xl represents the empty set of types.
|
||||||
|
func (xl termlist) isEmpty() bool {
|
||||||
|
// If there's a non-nil term, the entire list is not empty.
|
||||||
|
// If the termlist is in normal form, this requires at most
|
||||||
|
// one iteration.
|
||||||
|
for _, x := range xl {
|
||||||
|
if x != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// isAll reports whether the termlist xl represents the set of all types.
|
||||||
|
func (xl termlist) isAll() bool {
|
||||||
|
// If there's a 𝓤 term, the entire list is 𝓤.
|
||||||
|
// If the termlist is in normal form, this requires at most
|
||||||
|
// one iteration.
|
||||||
|
for _, x := range xl {
|
||||||
|
if x != nil && x.typ == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// norm returns the normal form of xl.
|
||||||
|
func (xl termlist) norm() termlist {
|
||||||
|
// Quadratic algorithm, but good enough for now.
|
||||||
|
// TODO(gri) fix asymptotic performance
|
||||||
|
used := make([]bool, len(xl))
|
||||||
|
var rl termlist
|
||||||
|
for i, xi := range xl {
|
||||||
|
if xi == nil || used[i] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
for j := i + 1; j < len(xl); j++ {
|
||||||
|
xj := xl[j]
|
||||||
|
if xj == nil || used[j] {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if u1, u2 := xi.union(xj); u2 == nil {
|
||||||
|
// If we encounter a 𝓤 term, the entire list is 𝓤.
|
||||||
|
// Exit early.
|
||||||
|
// (Note that this is not just an optimization;
|
||||||
|
// if we continue, we may end up with a 𝓤 term
|
||||||
|
// and other terms and the result would not be
|
||||||
|
// in normal form.)
|
||||||
|
if u1.typ == nil {
|
||||||
|
return allTermlist
|
||||||
|
}
|
||||||
|
xi = u1
|
||||||
|
used[j] = true // xj is now unioned into xi - ignore it in future iterations
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rl = append(rl, xi)
|
||||||
|
}
|
||||||
|
return rl
|
||||||
|
}
|
||||||
|
|
||||||
|
// union returns the union xl ∪ yl.
|
||||||
|
func (xl termlist) union(yl termlist) termlist {
|
||||||
|
return append(xl, yl...).norm()
|
||||||
|
}
|
||||||
|
|
||||||
|
// intersect returns the intersection xl ∩ yl.
|
||||||
|
func (xl termlist) intersect(yl termlist) termlist {
|
||||||
|
if xl.isEmpty() || yl.isEmpty() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quadratic algorithm, but good enough for now.
|
||||||
|
// TODO(gri) fix asymptotic performance
|
||||||
|
var rl termlist
|
||||||
|
for _, x := range xl {
|
||||||
|
for _, y := range yl {
|
||||||
|
if r := x.intersect(y); r != nil {
|
||||||
|
rl = append(rl, r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rl.norm()
|
||||||
|
}
|
||||||
|
|
||||||
|
// equal reports whether xl and yl represent the same type set.
|
||||||
|
func (xl termlist) equal(yl termlist) bool {
|
||||||
|
// TODO(gri) this should be more efficient
|
||||||
|
return xl.subsetOf(yl) && yl.subsetOf(xl)
|
||||||
|
}
|
||||||
|
|
||||||
|
// includes reports whether t ∈ xl.
|
||||||
|
func (xl termlist) includes(t types.Type) bool {
|
||||||
|
for _, x := range xl {
|
||||||
|
if x.includes(t) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// supersetOf reports whether y ⊆ xl.
|
||||||
|
func (xl termlist) supersetOf(y *term) bool {
|
||||||
|
for _, x := range xl {
|
||||||
|
if y.subsetOf(x) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// subsetOf reports whether xl ⊆ yl.
|
||||||
|
func (xl termlist) subsetOf(yl termlist) bool {
|
||||||
|
if yl.isEmpty() {
|
||||||
|
return xl.isEmpty()
|
||||||
|
}
|
||||||
|
|
||||||
|
// each term x of xl must be a subset of yl
|
||||||
|
for _, x := range xl {
|
||||||
|
if !yl.supersetOf(x) {
|
||||||
|
return false // x is not a subset yl
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
169
test/tools/vendor/golang.org/x/tools/internal/typeparams/typeterm.go
generated
vendored
Normal file
169
test/tools/vendor/golang.org/x/tools/internal/typeparams/typeterm.go
generated
vendored
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Code generated by copytermlist.go DO NOT EDIT.
|
||||||
|
|
||||||
|
package typeparams
|
||||||
|
|
||||||
|
import "go/types"
|
||||||
|
|
||||||
|
// A term describes elementary type sets:
|
||||||
|
//
|
||||||
|
// ∅: (*term)(nil) == ∅ // set of no types (empty set)
|
||||||
|
// 𝓤: &term{} == 𝓤 // set of all types (𝓤niverse)
|
||||||
|
// T: &term{false, T} == {T} // set of type T
|
||||||
|
// ~t: &term{true, t} == {t' | under(t') == t} // set of types with underlying type t
|
||||||
|
type term struct {
|
||||||
|
tilde bool // valid if typ != nil
|
||||||
|
typ types.Type
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *term) String() string {
|
||||||
|
switch {
|
||||||
|
case x == nil:
|
||||||
|
return "∅"
|
||||||
|
case x.typ == nil:
|
||||||
|
return "𝓤"
|
||||||
|
case x.tilde:
|
||||||
|
return "~" + x.typ.String()
|
||||||
|
default:
|
||||||
|
return x.typ.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// equal reports whether x and y represent the same type set.
|
||||||
|
func (x *term) equal(y *term) bool {
|
||||||
|
// easy cases
|
||||||
|
switch {
|
||||||
|
case x == nil || y == nil:
|
||||||
|
return x == y
|
||||||
|
case x.typ == nil || y.typ == nil:
|
||||||
|
return x.typ == y.typ
|
||||||
|
}
|
||||||
|
// ∅ ⊂ x, y ⊂ 𝓤
|
||||||
|
|
||||||
|
return x.tilde == y.tilde && types.Identical(x.typ, y.typ)
|
||||||
|
}
|
||||||
|
|
||||||
|
// union returns the union x ∪ y: zero, one, or two non-nil terms.
|
||||||
|
func (x *term) union(y *term) (_, _ *term) {
|
||||||
|
// easy cases
|
||||||
|
switch {
|
||||||
|
case x == nil && y == nil:
|
||||||
|
return nil, nil // ∅ ∪ ∅ == ∅
|
||||||
|
case x == nil:
|
||||||
|
return y, nil // ∅ ∪ y == y
|
||||||
|
case y == nil:
|
||||||
|
return x, nil // x ∪ ∅ == x
|
||||||
|
case x.typ == nil:
|
||||||
|
return x, nil // 𝓤 ∪ y == 𝓤
|
||||||
|
case y.typ == nil:
|
||||||
|
return y, nil // x ∪ 𝓤 == 𝓤
|
||||||
|
}
|
||||||
|
// ∅ ⊂ x, y ⊂ 𝓤
|
||||||
|
|
||||||
|
if x.disjoint(y) {
|
||||||
|
return x, y // x ∪ y == (x, y) if x ∩ y == ∅
|
||||||
|
}
|
||||||
|
// x.typ == y.typ
|
||||||
|
|
||||||
|
// ~t ∪ ~t == ~t
|
||||||
|
// ~t ∪ T == ~t
|
||||||
|
// T ∪ ~t == ~t
|
||||||
|
// T ∪ T == T
|
||||||
|
if x.tilde || !y.tilde {
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
return y, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// intersect returns the intersection x ∩ y.
|
||||||
|
func (x *term) intersect(y *term) *term {
|
||||||
|
// easy cases
|
||||||
|
switch {
|
||||||
|
case x == nil || y == nil:
|
||||||
|
return nil // ∅ ∩ y == ∅ and ∩ ∅ == ∅
|
||||||
|
case x.typ == nil:
|
||||||
|
return y // 𝓤 ∩ y == y
|
||||||
|
case y.typ == nil:
|
||||||
|
return x // x ∩ 𝓤 == x
|
||||||
|
}
|
||||||
|
// ∅ ⊂ x, y ⊂ 𝓤
|
||||||
|
|
||||||
|
if x.disjoint(y) {
|
||||||
|
return nil // x ∩ y == ∅ if x ∩ y == ∅
|
||||||
|
}
|
||||||
|
// x.typ == y.typ
|
||||||
|
|
||||||
|
// ~t ∩ ~t == ~t
|
||||||
|
// ~t ∩ T == T
|
||||||
|
// T ∩ ~t == T
|
||||||
|
// T ∩ T == T
|
||||||
|
if !x.tilde || y.tilde {
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
return y
|
||||||
|
}
|
||||||
|
|
||||||
|
// includes reports whether t ∈ x.
|
||||||
|
func (x *term) includes(t types.Type) bool {
|
||||||
|
// easy cases
|
||||||
|
switch {
|
||||||
|
case x == nil:
|
||||||
|
return false // t ∈ ∅ == false
|
||||||
|
case x.typ == nil:
|
||||||
|
return true // t ∈ 𝓤 == true
|
||||||
|
}
|
||||||
|
// ∅ ⊂ x ⊂ 𝓤
|
||||||
|
|
||||||
|
u := t
|
||||||
|
if x.tilde {
|
||||||
|
u = under(u)
|
||||||
|
}
|
||||||
|
return types.Identical(x.typ, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
// subsetOf reports whether x ⊆ y.
|
||||||
|
func (x *term) subsetOf(y *term) bool {
|
||||||
|
// easy cases
|
||||||
|
switch {
|
||||||
|
case x == nil:
|
||||||
|
return true // ∅ ⊆ y == true
|
||||||
|
case y == nil:
|
||||||
|
return false // x ⊆ ∅ == false since x != ∅
|
||||||
|
case y.typ == nil:
|
||||||
|
return true // x ⊆ 𝓤 == true
|
||||||
|
case x.typ == nil:
|
||||||
|
return false // 𝓤 ⊆ y == false since y != 𝓤
|
||||||
|
}
|
||||||
|
// ∅ ⊂ x, y ⊂ 𝓤
|
||||||
|
|
||||||
|
if x.disjoint(y) {
|
||||||
|
return false // x ⊆ y == false if x ∩ y == ∅
|
||||||
|
}
|
||||||
|
// x.typ == y.typ
|
||||||
|
|
||||||
|
// ~t ⊆ ~t == true
|
||||||
|
// ~t ⊆ T == false
|
||||||
|
// T ⊆ ~t == true
|
||||||
|
// T ⊆ T == true
|
||||||
|
return !x.tilde || y.tilde
|
||||||
|
}
|
||||||
|
|
||||||
|
// disjoint reports whether x ∩ y == ∅.
|
||||||
|
// x.typ and y.typ must not be nil.
|
||||||
|
func (x *term) disjoint(y *term) bool {
|
||||||
|
if debug && (x.typ == nil || y.typ == nil) {
|
||||||
|
panic("invalid argument(s)")
|
||||||
|
}
|
||||||
|
ux := x.typ
|
||||||
|
if y.tilde {
|
||||||
|
ux = under(ux)
|
||||||
|
}
|
||||||
|
uy := y.typ
|
||||||
|
if x.tilde {
|
||||||
|
uy = under(uy)
|
||||||
|
}
|
||||||
|
return !types.Identical(ux, uy)
|
||||||
|
}
|
133
test/tools/vendor/golang.org/x/tools/internal/typesinternal/element.go
generated
vendored
Normal file
133
test/tools/vendor/golang.org/x/tools/internal/typesinternal/element.go
generated
vendored
Normal file
|
@ -0,0 +1,133 @@
|
||||||
|
// 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 typesinternal
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"go/types"
|
||||||
|
|
||||||
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// ForEachElement calls f for type T and each type reachable from its
|
||||||
|
// type through reflection. It does this by recursively stripping off
|
||||||
|
// type constructors; in addition, for each named type N, the type *N
|
||||||
|
// is added to the result as it may have additional methods.
|
||||||
|
//
|
||||||
|
// The caller must provide an initially empty set used to de-duplicate
|
||||||
|
// identical types, potentially across multiple calls to ForEachElement.
|
||||||
|
// (Its final value holds all the elements seen, matching the arguments
|
||||||
|
// passed to f.)
|
||||||
|
//
|
||||||
|
// TODO(adonovan): share/harmonize with go/callgraph/rta.
|
||||||
|
func ForEachElement(rtypes *typeutil.Map, msets *typeutil.MethodSetCache, T types.Type, f func(types.Type)) {
|
||||||
|
var visit func(T types.Type, skip bool)
|
||||||
|
visit = func(T types.Type, skip bool) {
|
||||||
|
if !skip {
|
||||||
|
if seen, _ := rtypes.Set(T, true).(bool); seen {
|
||||||
|
return // de-dup
|
||||||
|
}
|
||||||
|
|
||||||
|
f(T) // notify caller of new element type
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recursion over signatures of each method.
|
||||||
|
tmset := msets.MethodSet(T)
|
||||||
|
for i := 0; i < tmset.Len(); i++ {
|
||||||
|
sig := tmset.At(i).Type().(*types.Signature)
|
||||||
|
// It is tempting to call visit(sig, false)
|
||||||
|
// but, as noted in golang.org/cl/65450043,
|
||||||
|
// the Signature.Recv field is ignored by
|
||||||
|
// types.Identical and typeutil.Map, which
|
||||||
|
// is confusing at best.
|
||||||
|
//
|
||||||
|
// More importantly, the true signature rtype
|
||||||
|
// reachable from a method using reflection
|
||||||
|
// has no receiver but an extra ordinary parameter.
|
||||||
|
// For the Read method of io.Reader we want:
|
||||||
|
// func(Reader, []byte) (int, error)
|
||||||
|
// but here sig is:
|
||||||
|
// func([]byte) (int, error)
|
||||||
|
// with .Recv = Reader (though it is hard to
|
||||||
|
// notice because it doesn't affect Signature.String
|
||||||
|
// or types.Identical).
|
||||||
|
//
|
||||||
|
// TODO(adonovan): construct and visit the correct
|
||||||
|
// non-method signature with an extra parameter
|
||||||
|
// (though since unnamed func types have no methods
|
||||||
|
// there is essentially no actual demand for this).
|
||||||
|
//
|
||||||
|
// TODO(adonovan): document whether or not it is
|
||||||
|
// safe to skip non-exported methods (as RTA does).
|
||||||
|
visit(sig.Params(), true) // skip the Tuple
|
||||||
|
visit(sig.Results(), true) // skip the Tuple
|
||||||
|
}
|
||||||
|
|
||||||
|
switch T := T.(type) {
|
||||||
|
case *types.Alias:
|
||||||
|
visit(types.Unalias(T), skip) // emulates the pre-Alias behavior
|
||||||
|
|
||||||
|
case *types.Basic:
|
||||||
|
// nop
|
||||||
|
|
||||||
|
case *types.Interface:
|
||||||
|
// nop---handled by recursion over method set.
|
||||||
|
|
||||||
|
case *types.Pointer:
|
||||||
|
visit(T.Elem(), false)
|
||||||
|
|
||||||
|
case *types.Slice:
|
||||||
|
visit(T.Elem(), false)
|
||||||
|
|
||||||
|
case *types.Chan:
|
||||||
|
visit(T.Elem(), false)
|
||||||
|
|
||||||
|
case *types.Map:
|
||||||
|
visit(T.Key(), false)
|
||||||
|
visit(T.Elem(), false)
|
||||||
|
|
||||||
|
case *types.Signature:
|
||||||
|
if T.Recv() != nil {
|
||||||
|
panic(fmt.Sprintf("Signature %s has Recv %s", T, T.Recv()))
|
||||||
|
}
|
||||||
|
visit(T.Params(), true) // skip the Tuple
|
||||||
|
visit(T.Results(), true) // skip the Tuple
|
||||||
|
|
||||||
|
case *types.Named:
|
||||||
|
// A pointer-to-named type can be derived from a named
|
||||||
|
// type via reflection. It may have methods too.
|
||||||
|
visit(types.NewPointer(T), false)
|
||||||
|
|
||||||
|
// Consider 'type T struct{S}' where S has methods.
|
||||||
|
// Reflection provides no way to get from T to struct{S},
|
||||||
|
// only to S, so the method set of struct{S} is unwanted,
|
||||||
|
// so set 'skip' flag during recursion.
|
||||||
|
visit(T.Underlying(), true) // skip the unnamed type
|
||||||
|
|
||||||
|
case *types.Array:
|
||||||
|
visit(T.Elem(), false)
|
||||||
|
|
||||||
|
case *types.Struct:
|
||||||
|
for i, n := 0, T.NumFields(); i < n; i++ {
|
||||||
|
// TODO(adonovan): document whether or not
|
||||||
|
// it is safe to skip non-exported fields.
|
||||||
|
visit(T.Field(i).Type(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.Tuple:
|
||||||
|
for i, n := 0, T.Len(); i < n; i++ {
|
||||||
|
visit(T.At(i).Type(), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *types.TypeParam, *types.Union:
|
||||||
|
// forEachReachable must not be called on parameterized types.
|
||||||
|
panic(T)
|
||||||
|
|
||||||
|
default:
|
||||||
|
panic(T)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
visit(T, false)
|
||||||
|
}
|
|
@ -6,8 +6,6 @@ package typesinternal
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"go/types"
|
"go/types"
|
||||||
|
|
||||||
"golang.org/x/tools/internal/aliases"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReceiverNamed returns the named type (if any) associated with the
|
// ReceiverNamed returns the named type (if any) associated with the
|
||||||
|
@ -15,11 +13,11 @@ import (
|
||||||
// It also reports whether a Pointer was present.
|
// It also reports whether a Pointer was present.
|
||||||
func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) {
|
func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) {
|
||||||
t := recv.Type()
|
t := recv.Type()
|
||||||
if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok {
|
if ptr, ok := types.Unalias(t).(*types.Pointer); ok {
|
||||||
isPtr = true
|
isPtr = true
|
||||||
t = ptr.Elem()
|
t = ptr.Elem()
|
||||||
}
|
}
|
||||||
named, _ = aliases.Unalias(t).(*types.Named)
|
named, _ = types.Unalias(t).(*types.Named)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,7 +34,7 @@ func ReceiverNamed(recv *types.Var) (isPtr bool, named *types.Named) {
|
||||||
// indirection from the type, regardless of named types (analogous to
|
// indirection from the type, regardless of named types (analogous to
|
||||||
// a LOAD instruction).
|
// a LOAD instruction).
|
||||||
func Unpointer(t types.Type) types.Type {
|
func Unpointer(t types.Type) types.Type {
|
||||||
if ptr, ok := aliases.Unalias(t).(*types.Pointer); ok {
|
if ptr, ok := types.Unalias(t).(*types.Pointer); ok {
|
||||||
return ptr.Elem()
|
return ptr.Elem()
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
|
|
@ -1,14 +0,0 @@
|
||||||
// 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 versions
|
|
||||||
|
|
||||||
// toolchain is maximum version (<1.22) that the go toolchain used
|
|
||||||
// to build the current tool is known to support.
|
|
||||||
//
|
|
||||||
// When a tool is built with >=1.22, the value of toolchain is unused.
|
|
||||||
//
|
|
||||||
// x/tools does not support building with go <1.18. So we take this
|
|
||||||
// as the minimum possible maximum.
|
|
||||||
var toolchain string = Go1_18
|
|
|
@ -1,14 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
//go:build go1.19
|
|
||||||
// +build go1.19
|
|
||||||
|
|
||||||
package versions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
if Compare(toolchain, Go1_19) < 0 {
|
|
||||||
toolchain = Go1_19
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
// 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.
|
|
||||||
|
|
||||||
//go:build go1.20
|
|
||||||
// +build go1.20
|
|
||||||
|
|
||||||
package versions
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
if Compare(toolchain, Go1_20) < 0 {
|
|
||||||
toolchain = Go1_20
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,15 +5,34 @@
|
||||||
package versions
|
package versions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"go/ast"
|
||||||
"go/types"
|
"go/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
// GoVersion returns the Go version of the type package.
|
// FileVersion returns a file's Go version.
|
||||||
// It returns zero if no version can be determined.
|
// The reported version is an unknown Future version if a
|
||||||
func GoVersion(pkg *types.Package) string {
|
// version cannot be determined.
|
||||||
// TODO(taking): x/tools can call GoVersion() [from 1.21] after 1.25.
|
func FileVersion(info *types.Info, file *ast.File) string {
|
||||||
if pkg, ok := any(pkg).(interface{ GoVersion() string }); ok {
|
// In tools built with Go >= 1.22, the Go version of a file
|
||||||
return pkg.GoVersion()
|
// follow a cascades of sources:
|
||||||
|
// 1) types.Info.FileVersion, which follows the cascade:
|
||||||
|
// 1.a) file version (ast.File.GoVersion),
|
||||||
|
// 1.b) the package version (types.Config.GoVersion), or
|
||||||
|
// 2) is some unknown Future version.
|
||||||
|
//
|
||||||
|
// File versions require a valid package version to be provided to types
|
||||||
|
// in Config.GoVersion. Config.GoVersion is either from the package's module
|
||||||
|
// or the toolchain (go run). This value should be provided by go/packages
|
||||||
|
// or unitchecker.Config.GoVersion.
|
||||||
|
if v := info.FileVersions[file]; IsValid(v) {
|
||||||
|
return v
|
||||||
}
|
}
|
||||||
return ""
|
// Note: we could instead return runtime.Version() [if valid].
|
||||||
|
// This would act as a max version on what a tool can support.
|
||||||
|
return Future
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitFileVersions initializes info to record Go versions for Go files.
|
||||||
|
func InitFileVersions(info *types.Info) {
|
||||||
|
info.FileVersions = make(map[*ast.File]string)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +0,0 @@
|
||||||
// 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.22
|
|
||||||
// +build !go1.22
|
|
||||||
|
|
||||||
package versions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/ast"
|
|
||||||
"go/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileVersion returns a language version (<=1.21) derived from runtime.Version()
|
|
||||||
// or an unknown future version.
|
|
||||||
func FileVersion(info *types.Info, file *ast.File) string {
|
|
||||||
// In x/tools built with Go <= 1.21, we do not have Info.FileVersions
|
|
||||||
// available. We use a go version derived from the toolchain used to
|
|
||||||
// compile the tool by default.
|
|
||||||
// This will be <= go1.21. We take this as the maximum version that
|
|
||||||
// this tool can support.
|
|
||||||
//
|
|
||||||
// There are no features currently in x/tools that need to tell fine grained
|
|
||||||
// differences for versions <1.22.
|
|
||||||
return toolchain
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitFileVersions is a noop when compiled with this Go version.
|
|
||||||
func InitFileVersions(*types.Info) {}
|
|
|
@ -1,41 +0,0 @@
|
||||||
// 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.22
|
|
||||||
// +build go1.22
|
|
||||||
|
|
||||||
package versions
|
|
||||||
|
|
||||||
import (
|
|
||||||
"go/ast"
|
|
||||||
"go/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
// FileVersion returns a file's Go version.
|
|
||||||
// The reported version is an unknown Future version if a
|
|
||||||
// version cannot be determined.
|
|
||||||
func FileVersion(info *types.Info, file *ast.File) string {
|
|
||||||
// In tools built with Go >= 1.22, the Go version of a file
|
|
||||||
// follow a cascades of sources:
|
|
||||||
// 1) types.Info.FileVersion, which follows the cascade:
|
|
||||||
// 1.a) file version (ast.File.GoVersion),
|
|
||||||
// 1.b) the package version (types.Config.GoVersion), or
|
|
||||||
// 2) is some unknown Future version.
|
|
||||||
//
|
|
||||||
// File versions require a valid package version to be provided to types
|
|
||||||
// in Config.GoVersion. Config.GoVersion is either from the package's module
|
|
||||||
// or the toolchain (go run). This value should be provided by go/packages
|
|
||||||
// or unitchecker.Config.GoVersion.
|
|
||||||
if v := info.FileVersions[file]; IsValid(v) {
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
// Note: we could instead return runtime.Version() [if valid].
|
|
||||||
// This would act as a max version on what a tool can support.
|
|
||||||
return Future
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitFileVersions initializes info to record Go versions for Go files.
|
|
||||||
func InitFileVersions(info *types.Info) {
|
|
||||||
info.FileVersions = make(map[*ast.File]string)
|
|
||||||
}
|
|
|
@ -257,7 +257,7 @@ golang.org/x/mod/semver
|
||||||
# golang.org/x/sync v0.8.0
|
# golang.org/x/sync v0.8.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
golang.org/x/sync/errgroup
|
golang.org/x/sync/errgroup
|
||||||
# golang.org/x/sys v0.25.0
|
# golang.org/x/sys v0.26.0
|
||||||
## explicit; go 1.18
|
## explicit; go 1.18
|
||||||
golang.org/x/sys/unix
|
golang.org/x/sys/unix
|
||||||
golang.org/x/sys/windows
|
golang.org/x/sys/windows
|
||||||
|
@ -266,7 +266,7 @@ golang.org/x/sys/windows
|
||||||
golang.org/x/text/runes
|
golang.org/x/text/runes
|
||||||
golang.org/x/text/transform
|
golang.org/x/text/transform
|
||||||
golang.org/x/text/unicode/norm
|
golang.org/x/text/unicode/norm
|
||||||
# golang.org/x/tools v0.25.0
|
# golang.org/x/tools v0.26.0
|
||||||
## explicit; go 1.22.0
|
## explicit; go 1.22.0
|
||||||
golang.org/x/tools/cmd/goimports
|
golang.org/x/tools/cmd/goimports
|
||||||
golang.org/x/tools/cover
|
golang.org/x/tools/cover
|
||||||
|
@ -278,6 +278,7 @@ golang.org/x/tools/go/internal/cgo
|
||||||
golang.org/x/tools/go/loader
|
golang.org/x/tools/go/loader
|
||||||
golang.org/x/tools/go/packages
|
golang.org/x/tools/go/packages
|
||||||
golang.org/x/tools/go/types/objectpath
|
golang.org/x/tools/go/types/objectpath
|
||||||
|
golang.org/x/tools/go/types/typeutil
|
||||||
golang.org/x/tools/imports
|
golang.org/x/tools/imports
|
||||||
golang.org/x/tools/internal/aliases
|
golang.org/x/tools/internal/aliases
|
||||||
golang.org/x/tools/internal/event
|
golang.org/x/tools/internal/event
|
||||||
|
@ -291,7 +292,7 @@ golang.org/x/tools/internal/imports
|
||||||
golang.org/x/tools/internal/packagesinternal
|
golang.org/x/tools/internal/packagesinternal
|
||||||
golang.org/x/tools/internal/pkgbits
|
golang.org/x/tools/internal/pkgbits
|
||||||
golang.org/x/tools/internal/stdlib
|
golang.org/x/tools/internal/stdlib
|
||||||
golang.org/x/tools/internal/tokeninternal
|
golang.org/x/tools/internal/typeparams
|
||||||
golang.org/x/tools/internal/typesinternal
|
golang.org/x/tools/internal/typesinternal
|
||||||
golang.org/x/tools/internal/versions
|
golang.org/x/tools/internal/versions
|
||||||
# gopkg.in/ini.v1 v1.67.0
|
# gopkg.in/ini.v1 v1.67.0
|
||||||
|
|
Loading…
Reference in New Issue