aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCherry Mui <cherryyz@google.com>2023-07-12 17:23:11 -0400
committerCherry Mui <cherryyz@google.com>2023-07-12 17:23:13 -0400
commitcc0cb3020dee801d733bc9c20c4a5bbaa650a6d4 (patch)
tree522c40137c7c8854d88dd3ed1ca55f1edcf624f7
parentd8117459c513e048eb72f11988d5416110dff359 (diff)
parent6244b1946bc2101b01955468f1be502dbadd6807 (diff)
downloadgo-cc0cb3020dee801d733bc9c20c4a5bbaa650a6d4.tar.gz
go-cc0cb3020dee801d733bc9c20c4a5bbaa650a6d4.zip
[release-branch.go1.21] all: merge master (6244b19) into release-branch.go1.21
Merge List: + 2023-07-12 6244b1946b all: update vendored dependencies + 2023-07-12 b4872ea187 cmd/go: fix go get go@badversion + 2023-07-12 87350393e6 cmd/go: fix GOTOOLCHAIN parsing for +auto + 2023-07-12 230e549142 doc/go1.21: add a release note for CL 463177 + 2023-07-12 5e4000ad7f cmd/compile: on PPC64, fix sign/zero extension when masking + 2023-07-11 af8f94e3c5 src/README.vendor: s/latest/master/ + 2023-07-11 3eaee3d5dd testing/slogtest: check for no group with empty record + 2023-07-11 167c8b73bf net/http/fcgi: eliminate goroutine leaks in tests + 2023-07-11 cb7a091d72 os/exec: ignore context.Canceled errors in TestConcurrentExec + 2023-07-11 651869716a log/slog: replace nil contexts with context.Background() + 2023-07-11 3f8b04bfb5 log/slog: change XXXCtx functions to XXXContext + 2023-07-11 4c58d6bf52 time: increase arbitrary upper bound in TestReset to 10s + 2023-07-11 6a063b01b0 net: mptcp: force using MPTCP with GODEBUG + 2023-07-10 07ede7a543 syscall: serialize locks on ForkLock on platforms where forkExecPipe is not atomic + 2023-07-10 7dc62f3bda test: add test cases for index value with range array clear + 2023-07-10 0b65b02ba5 cmd/compile: fix clear on slice with zero size elem + 2023-07-10 c4db811e44 cmd/compile: don't ICE on unaligned offsets for pointer writes + 2023-07-07 5c15498609 os: support reading empty root directories on Windows + 2023-07-07 894d24d617 src/database/sql: run gofmt + 2023-07-07 ac9137f8d3 go/types, types2: do not mutate arguments in NewChecker + 2023-07-07 158d11196f math: add test that covers riscv64 fnm{add,sub} codegen + 2023-07-07 d3d78b4bcc log/slog: handle recursively empty groups + 2023-07-06 39c5070712 os: do not skip directory entries with zero inodes on wasip1 + 2023-07-06 e6ec2a34dc runtime: print output on failure in TestMemPprof + 2023-07-06 449ef3795d net: only build cgo_stub.go on unix or wasip1 + 2023-07-06 6305d7fdd3 cmd/go: pass GoVersion in vet config + 2023-07-06 b490bdc27d go/types: record Config.GoVersion for reporting in Package.GoVersion method + 2023-07-06 36ea4f9680 log/slog: fix faulty test + 2023-07-05 3fce111535 cmd/compile: fix FMA negative commutativity of riscv64 + 2023-07-05 c8dad424bf math: fix portable FMA when x*y < 0 and x*y == -z + 2023-07-05 cd6676126b database/sql: prevent internal context error from being returned from Rows.Err() + 2023-07-05 b2215e49c7 runtime,runtime/metrics: clarify OS stack metrics + 2023-07-04 e126572f8a runtime: have ReadMemStats do a nil check before switching stacks + 2023-07-04 e4ed92a355 os, syscall: update unreachable link about =C: envs + 2023-07-04 5c1a15df41 test/codegen: enable Mul2 DivPow2 test for riscv64 + 2023-06-30 5b72f45dd1 runtime: check GOFLAGS not GCFLAGS + 2023-06-29 18e17e2cb1 net: enable pure Go resolver for wasip1 + 2023-06-29 1e97c51536 syscall: stub Getrlimit on wasip1 + 2023-06-29 683f51d307 cmd/asm/internal/lex: fix comment, remove the first "has" + 2023-06-29 2db31efdba cmd/compile/internal/types2: make TestIssue43124 match the go/types version + 2023-06-29 499458f7ca net/http: validate Host header before sending + 2023-06-29 fe73c186eb cmd/{go,compile}: run gofmt + 2023-06-29 da5d8fdd0c runtime: run wasip1 tests with wazero + 2023-06-29 411c99671a slices, maps: add examples; doc comment fixes + 2023-06-29 03cd8a7b0e internal/bytealg: fix alignment code in equal_riscv64.s + 2023-06-28 8b5fe5980c cmd/compile: handle min/max correctly in mayCall + 2023-06-28 79d4defa75 cmd/compile/internal/ssagen: fix min/max codegen, again + 2023-06-28 a3093eca64 cmd/go: enable slog vet check during 'go test' + 2023-06-27 6691f438c3 cmd/dist, internal/abi: support bootstrapping with gccgo + 2023-06-27 942c1c12d8 runtime: fix trace.Stop deadlock when built with faketime + 2023-06-27 4ad4128d3c cmd/compile: fix bad order of evaluation for min/max builtin + 2023-06-27 4f36f7e4dd encoding: document that base32 and base64 do not use UTF-8 + 2023-06-27 8008c0840f syscall: clarify which handles are affected by SysProcAttr.NoInheritHandles + 2023-06-27 13529cc5f4 syscall: try non-blocking stdio on wasip1 + 2023-06-26 1dbbafc70f go/types, types2: replace TODO with clarifying comment + 2023-06-26 7cc0740596 slices: add godoc links + 2023-06-26 d49017a7c3 go/types, types2: fix interface unification + 2023-06-26 b3ca8d2b3c types2, go/types: record final type for min/max arguments + 2023-06-26 ee361ce66c go/types, types2: more readable inference trace + 2023-06-26 9f6e87ff74 doc/go1.21: document changes in crypto/x509 + 2023-06-26 f5015b5164 doc/go1.21: context.Background and TODO may now appear equal + 2023-06-24 a031f4ef83 cmd/compile: fix min/max builtin code generation + 2023-06-24 ea927e560d slices: clarify MinFunc/MaxFunc result for equal elements + 2023-06-23 3619255777 crypto/x509: rename duplicated test + 2023-06-23 48dbb6227a runtime: set raceignore to zero when starting a new goroutine + 2023-06-23 3adcce5ae7 crypto: document non-determinism of GenerateKey + 2023-06-23 6dce882b3a cmd/compile: scanning closures body when visiting wrapper function + 2023-06-23 164aceea08 log/slog: fix broken link to AnyValue in comment + 2023-06-23 82e17c4d11 log/slog: fix broken link to Record.Clone in package docs + 2023-06-22 25e46693a1 cmd/go: impersonate 'go tool dist list' if 'go tool dist' is not present + 2023-06-22 f8616b8484 internal/platform,cmd/dist: export the list of supported platforms + 2023-06-22 51885c1fa2 cmd/{go,cover}: enable response file args for cmd/cover + 2023-06-22 3479e1e543 internal/fuzz: fix typo in comment + 2023-06-22 20313660f5 crypto/x509: tolerate multiple matching chains in testVerify + 2023-06-21 78c3aba470 net/mail: permit more characters in mail headers + 2023-06-21 633b742ae0 test: add test that caused a gofrontend crash + 2023-06-21 ad2c517708 doc/go1.21: correct GOOS to GOARCH (another location) + 2023-06-21 b23cae8095 doc/go1.21: correct GOOS to GOARCH + 2023-06-21 b1f1fb2950 go/types, types2: avoid spurious "declared and not used" error + 2023-06-21 e45202f215 runtime: relate GODEBUG=gctrace output to runtime/metrics + 2023-06-21 36edde9d9f cmd/go: shorten longest 5 tests + 2023-06-21 413e6c0499 cmd/compile/internal/ir: typo + 2023-06-20 f3bf18117b log/slog: fix HandlerOptions.ReplaceAttr doc + 2023-06-20 e122ebabb6 encoding/binary: on invalid type return -1 from Size + 2023-06-20 8484f2fe02 cmd/go: add comment for intentional misspelling Change-Id: Ie91c398dde7ca2a210b286c7865d3e7a905d6ea9
-rw-r--r--.gitignore2
-rw-r--r--api/go1.21.txt17
-rw-r--r--doc/go1.21.html22
-rw-r--r--doc/godebug.md4
-rw-r--r--src/README.vendor2
-rw-r--r--src/bytes/bytes_test.go32
-rw-r--r--src/cmd/asm/internal/lex/slice.go2
-rw-r--r--src/cmd/compile/internal/devirtualize/devirtualize.go10
-rw-r--r--src/cmd/compile/internal/ir/node.go1
-rw-r--r--src/cmd/compile/internal/ir/visit.go11
-rw-r--r--src/cmd/compile/internal/noder/reader.go6
-rw-r--r--src/cmd/compile/internal/ssa/_gen/PPC64.rules10
-rw-r--r--src/cmd/compile/internal/ssa/_gen/RISCV64.rules10
-rw-r--r--src/cmd/compile/internal/ssa/rewritePPC64.go77
-rw-r--r--src/cmd/compile/internal/ssa/rewriteRISCV64.go16
-rw-r--r--src/cmd/compile/internal/ssa/writebarrier.go7
-rw-r--r--src/cmd/compile/internal/ssagen/ssa.go18
-rw-r--r--src/cmd/compile/internal/typecheck/stmt.go2
-rw-r--r--src/cmd/compile/internal/typecheck/subr.go4
-rw-r--r--src/cmd/compile/internal/types2/builtins.go5
-rw-r--r--src/cmd/compile/internal/types2/check.go38
-rw-r--r--src/cmd/compile/internal/types2/index.go1
-rw-r--r--src/cmd/compile/internal/types2/issues_test.go81
-rw-r--r--src/cmd/compile/internal/types2/package.go21
-rw-r--r--src/cmd/compile/internal/types2/sizeof_test.go2
-rw-r--r--src/cmd/compile/internal/types2/unify.go83
-rw-r--r--src/cmd/compile/internal/types2/version.go23
-rw-r--r--src/cmd/compile/internal/types2/version_test.go24
-rw-r--r--src/cmd/compile/internal/walk/builtin.go6
-rw-r--r--src/cmd/compile/internal/walk/order.go4
-rw-r--r--src/cmd/compile/internal/walk/walk.go6
-rw-r--r--src/cmd/cover/cover.go2
-rw-r--r--src/cmd/dist/build.go9
-rw-r--r--src/cmd/dist/buildruntime.go23
-rw-r--r--src/cmd/dist/buildtool.go6
-rw-r--r--src/cmd/dist/main.go16
-rw-r--r--src/cmd/distpack/pack.go1
-rw-r--r--src/cmd/go.mod12
-rw-r--r--src/cmd/go.sum24
-rw-r--r--src/cmd/go/internal/base/tool.go23
-rw-r--r--src/cmd/go/internal/gover/gover.go4
-rw-r--r--src/cmd/go/internal/gover/gover_test.go19
-rw-r--r--src/cmd/go/internal/gover/toolchain.go2
-rw-r--r--src/cmd/go/internal/modfetch/toolchain.go30
-rw-r--r--src/cmd/go/internal/modget/query.go5
-rw-r--r--src/cmd/go/internal/modload/query.go6
-rw-r--r--src/cmd/go/internal/test/test.go1
-rw-r--r--src/cmd/go/internal/tool/tool.go85
-rw-r--r--src/cmd/go/internal/toolchain/select.go2
-rw-r--r--src/cmd/go/internal/work/exec.go10
-rw-r--r--src/cmd/go/internal/work/gc.go14
-rw-r--r--src/cmd/go/main.go6
-rw-r--r--src/cmd/go/testdata/script/build_pgo_auto.txt30
-rw-r--r--src/cmd/go/testdata/script/build_pgo_auto_multi.txt18
-rw-r--r--src/cmd/go/testdata/script/build_unsupported_goos.txt4
-rw-r--r--src/cmd/go/testdata/script/dist_list_missing.txt57
-rw-r--r--src/cmd/go/testdata/script/gcflags_patterns.txt22
-rw-r--r--src/cmd/go/testdata/script/gotoolchain_local.txt4
-rw-r--r--src/cmd/go/testdata/script/mod_get_toolchain.txt43
-rw-r--r--src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt21
-rw-r--r--src/cmd/go/testdata/script/vet_flags.txt14
-rw-r--r--src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go6
-rw-r--r--src/cmd/vendor/golang.org/x/mod/internal/lazyregexp/lazyre.go2
-rw-r--r--src/cmd/vendor/golang.org/x/mod/modfile/read.go2
-rw-r--r--src/cmd/vendor/golang.org/x/mod/modfile/rule.go20
-rw-r--r--src/cmd/vendor/golang.org/x/mod/modfile/work.go4
-rw-r--r--src/cmd/vendor/golang.org/x/mod/module/module.go30
-rw-r--r--src/cmd/vendor/golang.org/x/mod/module/pseudo.go2
-rw-r--r--src/cmd/vendor/golang.org/x/mod/semver/semver.go6
-rw-r--r--src/cmd/vendor/golang.org/x/mod/sumdb/client.go14
-rw-r--r--src/cmd/vendor/golang.org/x/mod/sumdb/note/note.go38
-rw-r--r--src/cmd/vendor/golang.org/x/mod/sumdb/server.go4
-rw-r--r--src/cmd/vendor/golang.org/x/mod/sumdb/test.go6
-rw-r--r--src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tile.go8
-rw-r--r--src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tlog.go6
-rw-r--r--src/cmd/vendor/golang.org/x/mod/zip/zip.go86
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/mremap.go40
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go17
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go26
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go11
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go1
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go35
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go2
-rw-r--r--src/cmd/vendor/golang.org/x/sys/windows/service.go4
-rw-r--r--src/cmd/vendor/golang.org/x/term/term_unix.go2
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go1
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall_go120.go13
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall_go121.go13
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go9
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/passes/slog/slog.go51
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go6
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/ast/inspector/inspector.go4
-rw-r--r--src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go11
-rw-r--r--src/cmd/vendor/golang.org/x/tools/internal/facts/facts.go48
-rw-r--r--src/cmd/vendor/golang.org/x/tools/internal/facts/imports.go4
-rw-r--r--src/cmd/vendor/modules.txt12
-rw-r--r--src/crypto/ecdh/ecdh.go6
-rw-r--r--src/crypto/ecdsa/ecdsa.go10
-rw-r--r--src/crypto/ed25519/ed25519.go5
-rw-r--r--src/crypto/rsa/pkcs1v15.go9
-rw-r--r--src/crypto/rsa/pss.go10
-rw-r--r--src/crypto/rsa/rsa.go16
-rw-r--r--src/crypto/x509/root_darwin_test.go4
-rw-r--r--src/crypto/x509/root_windows_test.go4
-rw-r--r--src/crypto/x509/verify_test.go19
-rw-r--r--src/database/sql/sql.go17
-rw-r--r--src/database/sql/sql_test.go25
-rw-r--r--src/encoding/base32/base32.go5
-rw-r--r--src/encoding/base64/base64.go5
-rw-r--r--src/encoding/binary/binary.go7
-rw-r--r--src/encoding/binary/binary_test.go20
-rw-r--r--src/go.mod8
-rw-r--r--src/go.sum16
-rw-r--r--src/go/build/deps_test.go2
-rw-r--r--src/go/types/builtins.go5
-rw-r--r--src/go/types/check.go40
-rw-r--r--src/go/types/generate_test.go1
-rw-r--r--src/go/types/index.go1
-rw-r--r--src/go/types/package.go21
-rw-r--r--src/go/types/sizeof_test.go2
-rw-r--r--src/go/types/unify.go83
-rw-r--r--src/go/types/version.go23
-rw-r--r--src/go/types/version_test.go26
-rw-r--r--src/internal/abi/funcpc.go2
-rw-r--r--src/internal/abi/funcpc_gccgo.go21
-rw-r--r--src/internal/bytealg/equal_riscv64.s2
-rw-r--r--src/internal/fuzz/counters_unsupported.go2
-rw-r--r--src/internal/godebugs/table.go1
-rw-r--r--src/internal/platform/supported.go45
-rw-r--r--src/internal/platform/zosarch.go114
-rw-r--r--src/internal/platform/zosarch_test.go109
-rw-r--r--src/internal/types/testdata/fixedbugs/issue60906.go11
-rw-r--r--src/internal/types/testdata/fixedbugs/issue60933.go67
-rw-r--r--src/internal/types/testdata/fixedbugs/issue60946.go38
-rw-r--r--src/log/slog/attr.go2
-rw-r--r--src/log/slog/doc.go8
-rw-r--r--src/log/slog/example_custom_levels_test.go8
-rw-r--r--src/log/slog/handler.go26
-rw-r--r--src/log/slog/handler_test.go54
-rw-r--r--src/log/slog/json_handler_test.go6
-rw-r--r--src/log/slog/logger.go48
-rw-r--r--src/log/slog/logger_test.go61
-rw-r--r--src/log/slog/record.go24
-rw-r--r--src/log/slog/value.go34
-rw-r--r--src/log/slog/value_test.go12
-rw-r--r--src/maps/example_test.go45
-rw-r--r--src/math/all_test.go46
-rw-r--r--src/math/fma.go5
-rw-r--r--src/net/cgo_stub.go11
-rw-r--r--src/net/conf.go2
-rw-r--r--src/net/dial.go14
-rw-r--r--src/net/dnsclient_unix.go2
-rw-r--r--src/net/dnsconfig_unix.go2
-rw-r--r--src/net/http/fcgi/fcgi.go13
-rw-r--r--src/net/http/fcgi/fcgi_test.go57
-rw-r--r--src/net/http/h2_bundle.go30
-rw-r--r--src/net/http/http_test.go29
-rw-r--r--src/net/http/request.go47
-rw-r--r--src/net/http/request_test.go11
-rw-r--r--src/net/http/transport_test.go19
-rw-r--r--src/net/lookup_fake.go2
-rw-r--r--src/net/lookup_unix.go2
-rw-r--r--src/net/mail/message.go51
-rw-r--r--src/net/mail/message_test.go28
-rw-r--r--src/net/mptcpsock_linux_test.go66
-rw-r--r--src/net/net_fake.go6
-rw-r--r--src/net/net_fake_js.go11
-rw-r--r--src/os/dir_darwin.go9
-rw-r--r--src/os/dir_unix.go6
-rw-r--r--src/os/dir_windows.go12
-rw-r--r--src/os/env_test.go2
-rw-r--r--src/os/exec/exec_test.go74
-rw-r--r--src/runtime/crash_test.go2
-rw-r--r--src/runtime/crash_unix_test.go2
-rw-r--r--src/runtime/extern.go13
-rw-r--r--src/runtime/internal/wasitest/nonblock_test.go2
-rw-r--r--src/runtime/internal/wasitest/tcpecho_test.go2
-rw-r--r--src/runtime/metrics/description.go18
-rw-r--r--src/runtime/metrics/doc.go15
-rw-r--r--src/runtime/mstats.go13
-rw-r--r--src/runtime/proc.go1
-rw-r--r--src/runtime/race/testdata/mop_test.go37
-rw-r--r--src/runtime/trace.go9
-rw-r--r--src/runtime/traceback.go1
-rw-r--r--src/slices/example_test.go322
-rw-r--r--src/slices/slices.go13
-rw-r--r--src/slices/sort.go12
-rw-r--r--src/slices/sort_test.go28
-rw-r--r--src/syscall/dirent.go9
-rw-r--r--src/syscall/env_windows.go2
-rw-r--r--src/syscall/exec_linux.go5
-rw-r--r--src/syscall/exec_unix.go83
-rw-r--r--src/syscall/exec_windows.go2
-rw-r--r--src/syscall/forkpipe.go11
-rw-r--r--src/syscall/forkpipe2.go89
-rw-r--r--src/syscall/fs_wasip1.go14
-rw-r--r--src/syscall/syscall_wasip1.go13
-rw-r--r--src/testing/slogtest/slogtest.go14
-rw-r--r--src/time/sleep_test.go26
-rw-r--r--src/vendor/golang.org/x/net/dns/dnsmessage/message.go6
-rw-r--r--src/vendor/modules.txt8
-rw-r--r--test/codegen/bits.go20
-rw-r--r--test/codegen/floats.go4
-rw-r--r--test/codegen/math.go8
-rw-r--r--test/fixedbugs/bug516.go13
-rw-r--r--test/fixedbugs/issue60945.dir/a.go22
-rw-r--r--test/fixedbugs/issue60945.dir/b.go9
-rw-r--r--test/fixedbugs/issue60945.go7
-rw-r--r--test/fixedbugs/issue60982.go2023
-rw-r--r--test/fixedbugs/issue60990.go31
-rw-r--r--test/fixedbugs/issue60991.go13
-rw-r--r--test/fixedbugs/issue61127.go13
-rw-r--r--test/fixedbugs/issue61187.go22
-rw-r--r--test/for.go22
230 files changed, 5279 insertions, 1023 deletions
diff --git a/.gitignore b/.gitignore
index 52263cdb80..7978d68b76 100644
--- a/.gitignore
+++ b/.gitignore
@@ -33,12 +33,10 @@ _testmain.go
/src/cmd/cgo/zdefaultcc.go
/src/cmd/dist/dist
/src/cmd/go/internal/cfg/zdefaultcc.go
-/src/cmd/go/internal/cfg/zosarch.go
/src/cmd/internal/objabi/zbootstrap.go
/src/go/build/zcgo.go
/src/go/doc/headscan
/src/internal/buildcfg/zbootstrap.go
-/src/internal/platform/zosarch.go
/src/runtime/internal/sys/zversion.go
/src/unicode/maketables
/src/time/tzdata/zzipdata.go
diff --git a/api/go1.21.txt b/api/go1.21.txt
index 6435d10914..def0fa84e4 100644
--- a/api/go1.21.txt
+++ b/api/go1.21.txt
@@ -174,6 +174,7 @@ pkg go/build, type Package struct, Directives []Directive #56986
pkg go/build, type Package struct, TestDirectives []Directive #56986
pkg go/build, type Package struct, XTestDirectives []Directive #56986
pkg go/token, method (*File) Lines() []int #57708
+pkg go/types, method (*Package) GoVersion() string #61175
pkg html/template, const ErrJSTemplate = 12 #59584
pkg html/template, const ErrJSTemplate ErrorCode #59584
pkg io/fs, func FormatDirEntry(DirEntry) string #54451
@@ -218,18 +219,18 @@ pkg log/slog, func Any(string, interface{}) Attr #56345
pkg log/slog, func AnyValue(interface{}) Value #56345
pkg log/slog, func Bool(string, bool) Attr #56345
pkg log/slog, func BoolValue(bool) Value #56345
-pkg log/slog, func DebugCtx(context.Context, string, ...interface{}) #56345
+pkg log/slog, func DebugContext(context.Context, string, ...interface{}) #61200
pkg log/slog, func Debug(string, ...interface{}) #56345
pkg log/slog, func Default() *Logger #56345
pkg log/slog, func Duration(string, time.Duration) Attr #56345
pkg log/slog, func DurationValue(time.Duration) Value #56345
-pkg log/slog, func ErrorCtx(context.Context, string, ...interface{}) #56345
+pkg log/slog, func ErrorContext(context.Context, string, ...interface{}) #61200
pkg log/slog, func Error(string, ...interface{}) #56345
pkg log/slog, func Float64(string, float64) Attr #56345
pkg log/slog, func Float64Value(float64) Value #56345
pkg log/slog, func Group(string, ...interface{}) Attr #59204
pkg log/slog, func GroupValue(...Attr) Value #56345
-pkg log/slog, func InfoCtx(context.Context, string, ...interface{}) #56345
+pkg log/slog, func InfoContext(context.Context, string, ...interface{}) #61200
pkg log/slog, func Info(string, ...interface{}) #56345
pkg log/slog, func Int64(string, int64) Attr #56345
pkg log/slog, func Int64Value(int64) Value #56345
@@ -249,7 +250,7 @@ pkg log/slog, func Time(string, time.Time) Attr #56345
pkg log/slog, func TimeValue(time.Time) Value #56345
pkg log/slog, func Uint64(string, uint64) Attr #56345
pkg log/slog, func Uint64Value(uint64) Value #56345
-pkg log/slog, func WarnCtx(context.Context, string, ...interface{}) #56345
+pkg log/slog, func WarnContext(context.Context, string, ...interface{}) #61200
pkg log/slog, func Warn(string, ...interface{}) #56345
pkg log/slog, func With(...interface{}) *Logger #56345
pkg log/slog, method (Attr) Equal(Attr) bool #56345
@@ -270,17 +271,17 @@ pkg log/slog, method (*LevelVar) MarshalText() ([]uint8, error) #56345
pkg log/slog, method (*LevelVar) Set(Level) #56345
pkg log/slog, method (*LevelVar) String() string #56345
pkg log/slog, method (*LevelVar) UnmarshalText([]uint8) error #56345
-pkg log/slog, method (*Logger) DebugCtx(context.Context, string, ...interface{}) #56345
+pkg log/slog, method (*Logger) DebugContext(context.Context, string, ...interface{}) #61200
pkg log/slog, method (*Logger) Debug(string, ...interface{}) #56345
pkg log/slog, method (*Logger) Enabled(context.Context, Level) bool #56345
-pkg log/slog, method (*Logger) ErrorCtx(context.Context, string, ...interface{}) #56345
+pkg log/slog, method (*Logger) ErrorContext(context.Context, string, ...interface{}) #61200
pkg log/slog, method (*Logger) Error(string, ...interface{}) #56345
pkg log/slog, method (*Logger) Handler() Handler #56345
-pkg log/slog, method (*Logger) InfoCtx(context.Context, string, ...interface{}) #56345
+pkg log/slog, method (*Logger) InfoContext(context.Context, string, ...interface{}) #61200
pkg log/slog, method (*Logger) Info(string, ...interface{}) #56345
pkg log/slog, method (*Logger) LogAttrs(context.Context, Level, string, ...Attr) #56345
pkg log/slog, method (*Logger) Log(context.Context, Level, string, ...interface{}) #56345
-pkg log/slog, method (*Logger) WarnCtx(context.Context, string, ...interface{}) #56345
+pkg log/slog, method (*Logger) WarnContext(context.Context, string, ...interface{}) #61200
pkg log/slog, method (*Logger) Warn(string, ...interface{}) #56345
pkg log/slog, method (*Logger) WithGroup(string) *Logger #56345
pkg log/slog, method (*Logger) With(...interface{}) *Logger #56345
diff --git a/doc/go1.21.html b/doc/go1.21.html
index 1d49084325..6c58cb0590 100644
--- a/doc/go1.21.html
+++ b/doc/go1.21.html
@@ -473,6 +473,16 @@ Do not send CLs removing the interior tags from such phrases.
The new <a href="/pkg/context/#AfterFunc"><code>AfterFunc</code></a>
function registers a function to run after a context has been cancelled.
</p>
+
+ <p><!-- CL 455455 -->
+ An optimization means that the results of calling
+ <a href="/pkg/context/#Background"><code>Background</code></a>
+ and <a href="/pkg/context/#TODO"><code>TODO</code></a> and
+ converting them to a shared type can be considered equal.
+ In previous releases they were always different. Comparing
+ <a href="/pkg/context/#Context"><code>Context</code></a> values
+ for equality has never been well-defined, so this is not
+ considered to be an incompatible change.
</dd>
</dl>
@@ -495,7 +505,7 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="crypto/rsa"><dt><a href="/pkg/crypto/rsa/">crypto/rsa</a></dt>
<dd>
<p><!-- CL 471259, CL 492935 -->
- The performance of private RSA operations (decryption and signing) is now better than Go 1.19 for <code>GOOS=amd64</code> and <code>GOOS=arm64</code>. It had regressed in Go 1.20.
+ The performance of private RSA operations (decryption and signing) is now better than Go 1.19 for <code>GOARCH=amd64</code> and <code>GOARCH=arm64</code>. It had regressed in Go 1.20.
</p>
<p>
Due to the addition of private fields to <a href="/pkg/crypto/rsa/#PrecomputedValues"><code>PrecomputedValues</code></a>, <a href="/pkg/crypto/rsa/#PrivateKey.Precompute"><code>PrivateKey.Precompute</code></a> must be called for optimal performance even if deserializing (for example from JSON) a previously-precomputed private key.
@@ -511,7 +521,7 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="crypto/sha256"><dt><a href="/pkg/crypto/sha256/">crypto/sha256</a></dt>
<dd>
<p><!-- https://go.dev/issue/50543, CL 408795 -->
- SHA-224 and SHA-256 operations now use native instructions when available when <code>GOOS=amd64</code>, providing a performance improvement on the order of 3-4x.
+ SHA-224 and SHA-256 operations now use native instructions when available when <code>GOARCH=amd64</code>, providing a performance improvement on the order of 3-4x.
</p>
</dd>
</dl><!-- crypto/sha256 -->
@@ -579,7 +589,7 @@ Do not send CLs removing the interior tags from such phrases.
<dl id="crypto/x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt>
<dd>
<p><!-- https://go.dev/issue/53573, CL 468875 -->
- <a href="/pkg/crypto/x509/#RevocationList.RevokedCertificates"><code>RevocationList.RevokedCertificates</code></a> has been deprecated and replaced with the new <a href="/pkg/crypto/x509/#RevocationList.Entries"><code>RevocationList.Entries</code></a> field, which is a slice of <a href="/pkg/crypto/x509/#RevocationListEntry"><code>RevocationListEntry</code></a>. <a href="/pkg/crypto/x509/#RevocationListEntry"><code>RevocationListEntry</code></a> contains all of the fields in <a href="/pkg/crypto/x509/#pkix.RevokedCertificate"><code>pkix.RevokedCertificate</code></a>, as well as the revocation reason code.
+ <a href="/pkg/crypto/x509/#RevocationList.RevokedCertificates"><code>RevocationList.RevokedCertificates</code></a> has been deprecated and replaced with the new <a href="/pkg/crypto/x509/#RevocationList.RevokedCertificateEntries"><code>RevokedCertificateEntries</code></a> field, which is a slice of <a href="/pkg/crypto/x509/#RevocationListEntry"><code>RevocationListEntry</code></a>. <a href="/pkg/crypto/x509/#RevocationListEntry"><code>RevocationListEntry</code></a> contains all of the fields in <a href="/pkg/crypto/x509/pkix#RevokedCertificate"><code>pkix.RevokedCertificate</code></a>, as well as the revocation reason code.
</p>
</dd>
</dl><!-- crypto/x509 -->
@@ -907,6 +917,12 @@ Do not send CLs removing the interior tags from such phrases.
names, stored as UTF-16, can't be represented as valid UTF-8.
</p>
+ <p><!-- CL 463177 -->
+ On Windows <a href="/pkg/os/#Lstat"><code>Lstat</code></a> now resolves
+ symbolic links for paths ending with a path separator, consistent with its
+ behavior on POSIX platforms.
+ </p>
+
<p><!-- https://go.dev/issue/54451, CL 491175 -->
The implementation of the
<a href="/pkg/io/fs/#DirEntry"><code>io/fs.DirEntry</code></a>
diff --git a/doc/godebug.md b/doc/godebug.md
index 43dbcd645a..7a6d70e487 100644
--- a/doc/godebug.md
+++ b/doc/godebug.md
@@ -142,6 +142,10 @@ forms, controlled by the
respectively.
This behavior was backported to Go 1.19.8+ and Go 1.20.3+.
+Go 1.21 adds the support of Multipath TCP but it is only used if the application
+explicitly asked for it. This behavior can be controlled by the
+[`multipathtcp` setting](/pkg/net#Dialer.SetMultipathTCP).
+
There is no plan to remove any of these settings.
### Go 1.20
diff --git a/src/README.vendor b/src/README.vendor
index 4b6bdb8e74..43821b2900 100644
--- a/src/README.vendor
+++ b/src/README.vendor
@@ -38,7 +38,7 @@ The vendor directory may be updated with 'go mod vendor'.
A typical sequence might be:
cd src
- go get golang.org/x/net@latest
+ go get golang.org/x/net@master
go mod tidy
go mod vendor
diff --git a/src/bytes/bytes_test.go b/src/bytes/bytes_test.go
index 05c0090b61..f0733edd3f 100644
--- a/src/bytes/bytes_test.go
+++ b/src/bytes/bytes_test.go
@@ -652,6 +652,38 @@ func bmEqual(equal func([]byte, []byte) bool) func(b *testing.B, n int) {
}
}
+func BenchmarkEqualBothUnaligned(b *testing.B) {
+ sizes := []int{64, 4 << 10}
+ if !isRaceBuilder {
+ sizes = append(sizes, []int{4 << 20, 64 << 20}...)
+ }
+ maxSize := 2 * (sizes[len(sizes)-1] + 8)
+ if len(bmbuf) < maxSize {
+ bmbuf = make([]byte, maxSize)
+ }
+
+ for _, n := range sizes {
+ for _, off := range []int{0, 1, 4, 7} {
+ buf1 := bmbuf[off : off+n]
+ buf2Start := (len(bmbuf) / 2) + off
+ buf2 := bmbuf[buf2Start : buf2Start+n]
+ buf1[n-1] = 'x'
+ buf2[n-1] = 'x'
+ b.Run(fmt.Sprint(n, off), func(b *testing.B) {
+ b.SetBytes(int64(n))
+ for i := 0; i < b.N; i++ {
+ eq := Equal(buf1, buf2)
+ if !eq {
+ b.Fatal("bad equal")
+ }
+ }
+ })
+ buf1[n-1] = '\x00'
+ buf2[n-1] = '\x00'
+ }
+ }
+}
+
func BenchmarkIndex(b *testing.B) {
benchBytes(b, indexSizes, func(b *testing.B, n int) {
buf := bmbuf[0:n]
diff --git a/src/cmd/asm/internal/lex/slice.go b/src/cmd/asm/internal/lex/slice.go
index 8ee0c7035f..61b15dd963 100644
--- a/src/cmd/asm/internal/lex/slice.go
+++ b/src/cmd/asm/internal/lex/slice.go
@@ -65,7 +65,7 @@ func (s *Slice) Col() int {
// #define A #define B(x) x
// and
// #define A #define B (x) x
- // The first has definition of B has an argument, the second doesn't. Because we let
+ // The first definition of B has an argument, the second doesn't. Because we let
// text/scanner strip the blanks for us, this is extremely rare, hard to fix, and not worth it.
return s.pos
}
diff --git a/src/cmd/compile/internal/devirtualize/devirtualize.go b/src/cmd/compile/internal/devirtualize/devirtualize.go
index cfeb8d8ee9..b156b66312 100644
--- a/src/cmd/compile/internal/devirtualize/devirtualize.go
+++ b/src/cmd/compile/internal/devirtualize/devirtualize.go
@@ -4,11 +4,11 @@
// Package devirtualize implements two "devirtualization" optimization passes:
//
-// - "Static" devirtualization which replaces interface method calls with
-// direct concrete-type method calls where possible.
-// - "Profile-guided" devirtualization which replaces indirect calls with a
-// conditional direct call to the hottest concrete callee from a profile, as
-// well as a fallback using the original indirect call.
+// - "Static" devirtualization which replaces interface method calls with
+// direct concrete-type method calls where possible.
+// - "Profile-guided" devirtualization which replaces indirect calls with a
+// conditional direct call to the hottest concrete callee from a profile, as
+// well as a fallback using the original indirect call.
package devirtualize
import (
diff --git a/src/cmd/compile/internal/ir/node.go b/src/cmd/compile/internal/ir/node.go
index 7f8ca023f2..769340e9cd 100644
--- a/src/cmd/compile/internal/ir/node.go
+++ b/src/cmd/compile/internal/ir/node.go
@@ -52,7 +52,6 @@ type Node interface {
// 0 means the node is not typechecked
// 1 means the node is completely typechecked
// 2 means typechecking of the node is in progress
- // 3 means the node has its type from types2, but may need transformation
Typecheck() uint8
SetTypecheck(x uint8)
NonNil() bool
diff --git a/src/cmd/compile/internal/ir/visit.go b/src/cmd/compile/internal/ir/visit.go
index 016467081e..73ec1de544 100644
--- a/src/cmd/compile/internal/ir/visit.go
+++ b/src/cmd/compile/internal/ir/visit.go
@@ -115,6 +115,17 @@ func VisitList(list Nodes, visit func(Node)) {
}
}
+// VisitFuncAndClosures calls visit on each non-nil node in fn.Body,
+// including any nested closure bodies.
+func VisitFuncAndClosures(fn *Func, visit func(n Node)) {
+ VisitList(fn.Body, func(n Node) {
+ visit(n)
+ if n, ok := n.(*ClosureExpr); ok && n.Op() == OCLOSURE {
+ VisitFuncAndClosures(n.Func, visit)
+ }
+ })
+}
+
// Any looks for a non-nil node x in the IR tree rooted at n
// for which cond(x) returns true.
// Any considers nodes in a depth-first, preorder traversal.
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index 70f51e2253..610d02c07c 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -3919,7 +3919,11 @@ func finishWrapperFunc(fn *ir.Func, target *ir.Package) {
// The body of wrapper function after inlining may reveal new ir.OMETHVALUE node,
// we don't know whether wrapper function has been generated for it or not, so
// generate one immediately here.
- ir.VisitList(fn.Body, func(n ir.Node) {
+ //
+ // Further, after CL 492017, function that construct closures is allowed to be inlined,
+ // even though the closure itself can't be inline. So we also need to visit body of any
+ // closure that we see when visiting body of the wrapper function.
+ ir.VisitFuncAndClosures(fn, func(n ir.Node) {
if n, ok := n.(*ir.SelectorExpr); ok && n.Op() == ir.OMETHVALUE {
wrapMethodValue(n.X.Type(), n.Selection, target, true)
}
diff --git a/src/cmd/compile/internal/ssa/_gen/PPC64.rules b/src/cmd/compile/internal/ssa/_gen/PPC64.rules
index cbce468ad5..97e592fd7e 100644
--- a/src/cmd/compile/internal/ssa/_gen/PPC64.rules
+++ b/src/cmd/compile/internal/ssa/_gen/PPC64.rules
@@ -588,16 +588,16 @@
// small and of zero-extend => either zero-extend or small and
(Select0 (ANDCCconst [c] y:(MOVBZreg _))) && c&0xFF == 0xFF => y
-(Select0 (ANDCCconst [0xFF] y:(MOVBreg _))) => y
+(Select0 (ANDCCconst [0xFF] (MOVBreg x))) => (MOVBZreg x)
(Select0 (ANDCCconst [c] y:(MOVHZreg _))) && c&0xFFFF == 0xFFFF => y
-(Select0 (ANDCCconst [0xFFFF] y:(MOVHreg _))) => y
+(Select0 (ANDCCconst [0xFFFF] (MOVHreg x))) => (MOVHZreg x)
(AND (MOVDconst [c]) y:(MOVWZreg _)) && c&0xFFFFFFFF == 0xFFFFFFFF => y
(AND (MOVDconst [0xFFFFFFFF]) y:(MOVWreg x)) => (MOVWZreg x)
// normal case
-(Select0 (ANDCCconst [c] (MOV(B|BZ)reg x))) => (Select0 (ANDCCconst [c&0xFF] x))
-(Select0 (ANDCCconst [c] (MOV(H|HZ)reg x))) => (Select0 (ANDCCconst [c&0xFFFF] x))
-(Select0 (ANDCCconst [c] (MOV(W|WZ)reg x))) => (Select0 (ANDCCconst [c&0xFFFFFFFF] x))
+(Select0 (ANDCCconst [c] (MOVBZreg x))) => (Select0 (ANDCCconst [c&0xFF] x))
+(Select0 (ANDCCconst [c] (MOVHZreg x))) => (Select0 (ANDCCconst [c&0xFFFF] x))
+(Select0 (ANDCCconst [c] (MOVWZreg x))) => (Select0 (ANDCCconst [c&0xFFFFFFFF] x))
// Eliminate unnecessary sign/zero extend following right shift
(MOV(B|H|W)Zreg (SRWconst [c] (MOVBZreg x))) => (SRWconst [c] (MOVBZreg x))
diff --git a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules
index eb1f10de96..9a6fcebdc5 100644
--- a/src/cmd/compile/internal/ssa/_gen/RISCV64.rules
+++ b/src/cmd/compile/internal/ssa/_gen/RISCV64.rules
@@ -836,11 +836,11 @@
//
// Key:
//
-// [+ -](x * y) [+ -] z.
-// _ N A S
-// D U
-// D B
+// [+ -](x * y [+ -] z).
+// _ N A S
+// D U
+// D B
//
// Note: multiplication commutativity handled by rule generator.
-(F(MADD|NMADD|MSUB|NMSUB)D neg:(FNEGD x) y z) && neg.Uses == 1 => (F(NMADD|MADD|NMSUB|MSUB)D x y z)
+(F(MADD|NMADD|MSUB|NMSUB)D neg:(FNEGD x) y z) && neg.Uses == 1 => (F(NMSUB|MSUB|NMADD|MADD)D x y z)
(F(MADD|NMADD|MSUB|NMSUB)D x y neg:(FNEGD z)) && neg.Uses == 1 => (F(MSUB|NMSUB|MADD|NMADD)D x y z)
diff --git a/src/cmd/compile/internal/ssa/rewritePPC64.go b/src/cmd/compile/internal/ssa/rewritePPC64.go
index a380b4aeaf..d1c0c2b07f 100644
--- a/src/cmd/compile/internal/ssa/rewritePPC64.go
+++ b/src/cmd/compile/internal/ssa/rewritePPC64.go
@@ -14410,17 +14410,19 @@ func rewriteValuePPC64_OpSelect0(v *Value) bool {
v.copyOf(y)
return true
}
- // match: (Select0 (ANDCCconst [0xFF] y:(MOVBreg _)))
- // result: y
+ // match: (Select0 (ANDCCconst [0xFF] (MOVBreg x)))
+ // result: (MOVBZreg x)
for {
if v_0.Op != OpPPC64ANDCCconst || auxIntToInt64(v_0.AuxInt) != 0xFF {
break
}
- y := v_0.Args[0]
- if y.Op != OpPPC64MOVBreg {
+ v_0_0 := v_0.Args[0]
+ if v_0_0.Op != OpPPC64MOVBreg {
break
}
- v.copyOf(y)
+ x := v_0_0.Args[0]
+ v.reset(OpPPC64MOVBZreg)
+ v.AddArg(x)
return true
}
// match: (Select0 (ANDCCconst [c] y:(MOVHZreg _)))
@@ -14438,36 +14440,19 @@ func rewriteValuePPC64_OpSelect0(v *Value) bool {
v.copyOf(y)
return true
}
- // match: (Select0 (ANDCCconst [0xFFFF] y:(MOVHreg _)))
- // result: y
+ // match: (Select0 (ANDCCconst [0xFFFF] (MOVHreg x)))
+ // result: (MOVHZreg x)
for {
if v_0.Op != OpPPC64ANDCCconst || auxIntToInt64(v_0.AuxInt) != 0xFFFF {
break
}
- y := v_0.Args[0]
- if y.Op != OpPPC64MOVHreg {
- break
- }
- v.copyOf(y)
- return true
- }
- // match: (Select0 (ANDCCconst [c] (MOVBreg x)))
- // result: (Select0 (ANDCCconst [c&0xFF] x))
- for {
- if v_0.Op != OpPPC64ANDCCconst {
- break
- }
- c := auxIntToInt64(v_0.AuxInt)
v_0_0 := v_0.Args[0]
- if v_0_0.Op != OpPPC64MOVBreg {
+ if v_0_0.Op != OpPPC64MOVHreg {
break
}
x := v_0_0.Args[0]
- v.reset(OpSelect0)
- v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.NewTuple(typ.Int, types.TypeFlags))
- v0.AuxInt = int64ToAuxInt(c & 0xFF)
- v0.AddArg(x)
- v.AddArg(v0)
+ v.reset(OpPPC64MOVHZreg)
+ v.AddArg(x)
return true
}
// match: (Select0 (ANDCCconst [c] (MOVBZreg x)))
@@ -14489,25 +14474,6 @@ func rewriteValuePPC64_OpSelect0(v *Value) bool {
v.AddArg(v0)
return true
}
- // match: (Select0 (ANDCCconst [c] (MOVHreg x)))
- // result: (Select0 (ANDCCconst [c&0xFFFF] x))
- for {
- if v_0.Op != OpPPC64ANDCCconst {
- break
- }
- c := auxIntToInt64(v_0.AuxInt)
- v_0_0 := v_0.Args[0]
- if v_0_0.Op != OpPPC64MOVHreg {
- break
- }
- x := v_0_0.Args[0]
- v.reset(OpSelect0)
- v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.NewTuple(typ.Int, types.TypeFlags))
- v0.AuxInt = int64ToAuxInt(c & 0xFFFF)
- v0.AddArg(x)
- v.AddArg(v0)
- return true
- }
// match: (Select0 (ANDCCconst [c] (MOVHZreg x)))
// result: (Select0 (ANDCCconst [c&0xFFFF] x))
for {
@@ -14527,25 +14493,6 @@ func rewriteValuePPC64_OpSelect0(v *Value) bool {
v.AddArg(v0)
return true
}
- // match: (Select0 (ANDCCconst [c] (MOVWreg x)))
- // result: (Select0 (ANDCCconst [c&0xFFFFFFFF] x))
- for {
- if v_0.Op != OpPPC64ANDCCconst {
- break
- }
- c := auxIntToInt64(v_0.AuxInt)
- v_0_0 := v_0.Args[0]
- if v_0_0.Op != OpPPC64MOVWreg {
- break
- }
- x := v_0_0.Args[0]
- v.reset(OpSelect0)
- v0 := b.NewValue0(v.Pos, OpPPC64ANDCCconst, types.NewTuple(typ.Int, types.TypeFlags))
- v0.AuxInt = int64ToAuxInt(c & 0xFFFFFFFF)
- v0.AddArg(x)
- v.AddArg(v0)
- return true
- }
// match: (Select0 (ANDCCconst [c] (MOVWZreg x)))
// result: (Select0 (ANDCCconst [c&0xFFFFFFFF] x))
for {
diff --git a/src/cmd/compile/internal/ssa/rewriteRISCV64.go b/src/cmd/compile/internal/ssa/rewriteRISCV64.go
index f1debe0c21..ffbeb1df47 100644
--- a/src/cmd/compile/internal/ssa/rewriteRISCV64.go
+++ b/src/cmd/compile/internal/ssa/rewriteRISCV64.go
@@ -3322,7 +3322,7 @@ func rewriteValueRISCV64_OpRISCV64FMADDD(v *Value) bool {
v_0 := v.Args[0]
// match: (FMADDD neg:(FNEGD x) y z)
// cond: neg.Uses == 1
- // result: (FNMADDD x y z)
+ // result: (FNMSUBD x y z)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
neg := v_0
@@ -3335,7 +3335,7 @@ func rewriteValueRISCV64_OpRISCV64FMADDD(v *Value) bool {
if !(neg.Uses == 1) {
continue
}
- v.reset(OpRISCV64FNMADDD)
+ v.reset(OpRISCV64FNMSUBD)
v.AddArg3(x, y, z)
return true
}
@@ -3367,7 +3367,7 @@ func rewriteValueRISCV64_OpRISCV64FMSUBD(v *Value) bool {
v_0 := v.Args[0]
// match: (FMSUBD neg:(FNEGD x) y z)
// cond: neg.Uses == 1
- // result: (FNMSUBD x y z)
+ // result: (FNMADDD x y z)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
neg := v_0
@@ -3380,7 +3380,7 @@ func rewriteValueRISCV64_OpRISCV64FMSUBD(v *Value) bool {
if !(neg.Uses == 1) {
continue
}
- v.reset(OpRISCV64FNMSUBD)
+ v.reset(OpRISCV64FNMADDD)
v.AddArg3(x, y, z)
return true
}
@@ -3412,7 +3412,7 @@ func rewriteValueRISCV64_OpRISCV64FNMADDD(v *Value) bool {
v_0 := v.Args[0]
// match: (FNMADDD neg:(FNEGD x) y z)
// cond: neg.Uses == 1
- // result: (FMADDD x y z)
+ // result: (FMSUBD x y z)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
neg := v_0
@@ -3425,7 +3425,7 @@ func rewriteValueRISCV64_OpRISCV64FNMADDD(v *Value) bool {
if !(neg.Uses == 1) {
continue
}
- v.reset(OpRISCV64FMADDD)
+ v.reset(OpRISCV64FMSUBD)
v.AddArg3(x, y, z)
return true
}
@@ -3457,7 +3457,7 @@ func rewriteValueRISCV64_OpRISCV64FNMSUBD(v *Value) bool {
v_0 := v.Args[0]
// match: (FNMSUBD neg:(FNEGD x) y z)
// cond: neg.Uses == 1
- // result: (FMSUBD x y z)
+ // result: (FMADDD x y z)
for {
for _i0 := 0; _i0 <= 1; _i0, v_0, v_1 = _i0+1, v_1, v_0 {
neg := v_0
@@ -3470,7 +3470,7 @@ func rewriteValueRISCV64_OpRISCV64FNMSUBD(v *Value) bool {
if !(neg.Uses == 1) {
continue
}
- v.reset(OpRISCV64FMSUBD)
+ v.reset(OpRISCV64FMADDD)
v.AddArg3(x, y, z)
return true
}
diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go
index 5df65bfaa3..bd9e0b8268 100644
--- a/src/cmd/compile/internal/ssa/writebarrier.go
+++ b/src/cmd/compile/internal/ssa/writebarrier.go
@@ -53,7 +53,10 @@ func mightContainHeapPointer(ptr *Value, size int64, mem *Value, zeroes map[ID]Z
}
ptrSize := ptr.Block.Func.Config.PtrSize
- if off%ptrSize != 0 || size%ptrSize != 0 {
+ if off%ptrSize != 0 {
+ return true // see issue 61187
+ }
+ if size%ptrSize != 0 {
ptr.Fatalf("unaligned pointer write")
}
if off < 0 || off+size > 64*ptrSize {
@@ -130,7 +133,7 @@ func needWBdst(ptr, mem *Value, zeroes map[ID]ZeroRegion) bool {
}
ptrSize := ptr.Block.Func.Config.PtrSize
if off%ptrSize != 0 {
- ptr.Fatalf("unaligned pointer write")
+ return true // see issue 61187
}
if off < 0 || off >= 64*ptrSize {
// write goes off end of tracked offsets
diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go
index 88fee51d33..678e1ebc11 100644
--- a/src/cmd/compile/internal/ssagen/ssa.go
+++ b/src/cmd/compile/internal/ssagen/ssa.go
@@ -3620,8 +3620,13 @@ func (s *state) minMax(n *ir.CallExpr) *ssa.Value {
// ternary emits code to evaluate cond ? x : y.
func (s *state) ternary(cond, x, y *ssa.Value) *ssa.Value {
+ // Note that we need a new ternaryVar each time (unlike okVar where we can
+ // reuse the variable) because it might have a different type every time.
+ ternaryVar := ssaMarker("ternary")
+
bThen := s.f.NewBlock(ssa.BlockPlain)
bElse := s.f.NewBlock(ssa.BlockPlain)
+ bEnd := s.f.NewBlock(ssa.BlockPlain)
b := s.endBlock()
b.Kind = ssa.BlockIf
@@ -3629,11 +3634,18 @@ func (s *state) ternary(cond, x, y *ssa.Value) *ssa.Value {
b.AddEdgeTo(bThen)
b.AddEdgeTo(bElse)
+ s.startBlock(bThen)
+ s.vars[ternaryVar] = x
+ s.endBlock().AddEdgeTo(bEnd)
+
s.startBlock(bElse)
- s.endBlock().AddEdgeTo(bThen)
+ s.vars[ternaryVar] = y
+ s.endBlock().AddEdgeTo(bEnd)
- s.startBlock(bThen)
- return s.newValue2(ssa.OpPhi, x.Type, x, y)
+ s.startBlock(bEnd)
+ r := s.variable(ternaryVar, x.Type)
+ delete(s.vars, ternaryVar)
+ return r
}
// condBranch evaluates the boolean expression cond and branches to yes
diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go
index c434ff9118..9dea261bb9 100644
--- a/src/cmd/compile/internal/typecheck/stmt.go
+++ b/src/cmd/compile/internal/typecheck/stmt.go
@@ -607,7 +607,7 @@ func tcSwitchType(n *ir.SwitchStmt) {
if !n1.Type().IsInterface() {
why := ImplementsExplain(n1.Type(), t)
if why != "" {
- base.ErrorfAt(ncase.Pos(), errors.ImpossibleAssert, "impossible type switch case: %L cannot have dynamic type %v (%s)" , guard.X, n1.Type(), why)
+ base.ErrorfAt(ncase.Pos(), errors.ImpossibleAssert, "impossible type switch case: %L cannot have dynamic type %v (%s)", guard.X, n1.Type(), why)
}
continue
}
diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go
index 8554805fa6..2bb978a0fa 100644
--- a/src/cmd/compile/internal/typecheck/subr.go
+++ b/src/cmd/compile/internal/typecheck/subr.go
@@ -713,12 +713,12 @@ func ImplementsExplain(t, iface *types.Type) string {
return fmt.Sprintf("%v does not implement %v (%v method is marked 'nointerface')", t, iface, missing.Sym)
} else if have != nil && have.Sym == missing.Sym {
return fmt.Sprintf("%v does not implement %v (wrong type for %v method)\n"+
- "\t\thave %v%S\n\t\twant %v%S", t, iface, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
+ "\t\thave %v%S\n\t\twant %v%S", t, iface, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
} else if ptr != 0 {
return fmt.Sprintf("%v does not implement %v (%v method has pointer receiver)", t, iface, missing.Sym)
} else if have != nil {
return fmt.Sprintf("%v does not implement %v (missing %v method)\n"+
- "\t\thave %v%S\n\t\twant %v%S", t, iface, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
+ "\t\thave %v%S\n\t\twant %v%S", t, iface, missing.Sym, have.Sym, have.Type, missing.Sym, missing.Type)
}
return fmt.Sprintf("%v does not implement %v (missing %v method)", t, iface, missing.Sym)
}
diff --git a/src/cmd/compile/internal/types2/builtins.go b/src/cmd/compile/internal/types2/builtins.go
index a3e1981af6..f3763862ec 100644
--- a/src/cmd/compile/internal/types2/builtins.go
+++ b/src/cmd/compile/internal/types2/builtins.go
@@ -578,6 +578,11 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
x.mode = value
}
+ // Use the final type computed above for all arguments.
+ for _, a := range args {
+ check.updateExprType(a.expr, x.typ, true)
+ }
+
if check.recordTypes() && x.mode != constant_ {
types := make([]Type, nargs)
for i := range types {
diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go
index b2a9eb0dbc..0a2a49062b 100644
--- a/src/cmd/compile/internal/types2/check.go
+++ b/src/cmd/compile/internal/types2/check.go
@@ -11,6 +11,7 @@ import (
"errors"
"fmt"
"go/constant"
+ "internal/goversion"
. "internal/types/errors"
)
@@ -231,19 +232,19 @@ func NewChecker(conf *Config, pkg *Package, info *Info) *Checker {
info = new(Info)
}
- version, err := parseGoVersion(conf.GoVersion)
- if err != nil {
- panic(fmt.Sprintf("invalid Go version %q (%v)", conf.GoVersion, err))
- }
+ // Note: clients may call NewChecker with the Unsafe package, which is
+ // globally shared and must not be mutated. Therefore NewChecker must not
+ // mutate *pkg.
+ //
+ // (previously, pkg.goVersion was mutated here: go.dev/issue/61212)
return &Checker{
- conf: conf,
- ctxt: conf.Context,
- pkg: pkg,
- Info: info,
- version: version,
- objMap: make(map[Object]*declInfo),
- impMap: make(map[importKey]*Package),
+ conf: conf,
+ ctxt: conf.Context,
+ pkg: pkg,
+ Info: info,
+ objMap: make(map[Object]*declInfo),
+ impMap: make(map[importKey]*Package),
}
}
@@ -333,6 +334,20 @@ func (check *Checker) Files(files []*syntax.File) error { return check.checkFile
var errBadCgo = errors.New("cannot use FakeImportC and go115UsesCgo together")
func (check *Checker) checkFiles(files []*syntax.File) (err error) {
+ if check.pkg == Unsafe {
+ // Defensive handling for Unsafe, which cannot be type checked, and must
+ // not be mutated. See https://go.dev/issue/61212 for an example of where
+ // Unsafe is passed to NewChecker.
+ return nil
+ }
+
+ check.version, err = parseGoVersion(check.conf.GoVersion)
+ if err != nil {
+ return err
+ }
+ if check.version.after(version{1, goversion.Version}) {
+ return fmt.Errorf("package requires newer Go version %v", check.version)
+ }
if check.conf.FakeImportC && check.conf.go115UsesCgo {
return errBadCgo
}
@@ -377,6 +392,7 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) {
check.monomorph()
}
+ check.pkg.goVersion = check.conf.GoVersion
check.pkg.complete = true
// no longer needed - release memory
diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go
index 4fbe064da6..3ebe851355 100644
--- a/src/cmd/compile/internal/types2/index.go
+++ b/src/cmd/compile/internal/types2/index.go
@@ -184,6 +184,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo
if !valid {
check.errorf(e.Pos(), NonSliceableOperand, invalidOp+"cannot index %s", x)
+ check.use(e.Index)
x.mode = invalid
return false
}
diff --git a/src/cmd/compile/internal/types2/issues_test.go b/src/cmd/compile/internal/types2/issues_test.go
index 8bd42a5271..5e0ae213dc 100644
--- a/src/cmd/compile/internal/types2/issues_test.go
+++ b/src/cmd/compile/internal/types2/issues_test.go
@@ -497,14 +497,14 @@ func TestIssue43088(t *testing.T) {
// _ T2
// }
// }
- n1 := NewTypeName(syntax.Pos{}, nil, "T1", nil)
+ n1 := NewTypeName(nopos, nil, "T1", nil)
T1 := NewNamed(n1, nil, nil)
- n2 := NewTypeName(syntax.Pos{}, nil, "T2", nil)
+ n2 := NewTypeName(nopos, nil, "T2", nil)
T2 := NewNamed(n2, nil, nil)
- s1 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", T2, false)}, nil)
+ s1 := NewStruct([]*Var{NewField(nopos, nil, "_", T2, false)}, nil)
T1.SetUnderlying(s1)
- s2 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", T2, false)}, nil)
- s3 := NewStruct([]*Var{NewField(syntax.Pos{}, nil, "_", s2, false)}, nil)
+ s2 := NewStruct([]*Var{NewField(nopos, nil, "_", T2, false)}, nil)
+ s3 := NewStruct([]*Var{NewField(nopos, nil, "_", s2, false)}, nil)
T2.SetUnderlying(s3)
// These calls must terminate (no endless recursion).
@@ -535,38 +535,69 @@ func TestIssue44515(t *testing.T) {
}
func TestIssue43124(t *testing.T) {
- testenv.MustHaveGoBuild(t)
+ // TODO(rFindley) move this to testdata by enhancing support for importing.
+
+ testenv.MustHaveGoBuild(t) // The go command is needed for the importer to determine the locations of stdlib .a files.
// All involved packages have the same name (template). Error messages should
// disambiguate between text/template and html/template by printing the full
// path.
const (
asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}`
- bsrc = `package b; import ("a"; "html/template"); func _() { a.F(template.Template{}) }`
- csrc = `package c; import ("a"; "html/template"); func _() { a.G(template.Template{}) }`
- )
+ bsrc = `
+package b
- a := mustTypecheck(asrc, nil, nil)
- conf := Config{Importer: importHelper{pkg: a, fallback: defaultImporter()}}
+import (
+ "a"
+ "html/template"
+)
+func _() {
// Packages should be fully qualified when there is ambiguity within the
// error string itself.
- _, err := typecheck(bsrc, &conf, nil)
- if err == nil {
- t.Fatal("package b had no errors")
- }
- if !strings.Contains(err.Error(), "text/template") || !strings.Contains(err.Error(), "html/template") {
- t.Errorf("type checking error for b does not disambiguate package template: %q", err)
- }
+ a.F(template /* ERRORx "cannot use.*html/template.* as .*text/template" */ .Template{})
+}
+`
+ csrc = `
+package c
- // ...and also when there is any ambiguity in reachable packages.
- _, err = typecheck(csrc, &conf, nil)
- if err == nil {
- t.Fatal("package c had no errors")
- }
- if !strings.Contains(err.Error(), "html/template") {
- t.Errorf("type checking error for c does not disambiguate package template: %q", err)
+import (
+ "a"
+ "fmt"
+ "html/template"
+)
+
+// go.dev/issue/46905: make sure template is not the first package qualified.
+var _ fmt.Stringer = 1 // ERRORx "cannot use 1.*as fmt\\.Stringer"
+
+// Packages should be fully qualified when there is ambiguity in reachable
+// packages. In this case both a (and for that matter html/template) import
+// text/template.
+func _() { a.G(template /* ERRORx "cannot use .*html/template.*Template" */ .Template{}) }
+`
+
+ tsrc = `
+package template
+
+import "text/template"
+
+type T int
+
+// Verify that the current package name also causes disambiguation.
+var _ T = template /* ERRORx "cannot use.*text/template.* as T value" */.Template{}
+`
+ )
+
+ a := mustTypecheck(asrc, nil, nil)
+ imp := importHelper{pkg: a, fallback: defaultImporter()}
+
+ withImporter := func(cfg *Config) {
+ cfg.Importer = imp
}
+
+ testFiles(t, []string{"b.go"}, [][]byte{[]byte(bsrc)}, 0, false, withImporter)
+ testFiles(t, []string{"c.go"}, [][]byte{[]byte(csrc)}, 0, false, withImporter)
+ testFiles(t, []string{"t.go"}, [][]byte{[]byte(tsrc)}, 0, false, withImporter)
}
func TestIssue50646(t *testing.T) {
diff --git a/src/cmd/compile/internal/types2/package.go b/src/cmd/compile/internal/types2/package.go
index 61670f6718..e08099d81f 100644
--- a/src/cmd/compile/internal/types2/package.go
+++ b/src/cmd/compile/internal/types2/package.go
@@ -10,13 +10,14 @@ import (
// A Package describes a Go package.
type Package struct {
- path string
- name string
- scope *Scope
- imports []*Package
- complete bool
- fake bool // scope lookup errors are silently dropped if package is fake (internal use only)
- cgo bool // uses of this package will be rewritten into uses of declarations from _cgo_gotypes.go
+ path string
+ name string
+ scope *Scope
+ imports []*Package
+ complete bool
+ fake bool // scope lookup errors are silently dropped if package is fake (internal use only)
+ cgo bool // uses of this package will be rewritten into uses of declarations from _cgo_gotypes.go
+ goVersion string // minimum Go version required for package (by Config.GoVersion, typically from go.mod)
}
// NewPackage returns a new Package for the given package path and name.
@@ -35,6 +36,12 @@ func (pkg *Package) Name() string { return pkg.name }
// SetName sets the package name.
func (pkg *Package) SetName(name string) { pkg.name = name }
+// GoVersion returns the minimum Go version required by this package.
+// If the minimum version is unknown, GoVersion returns the empty string.
+// Individual source files may specify a different minimum Go version,
+// as reported in the [go/ast.File.GoVersion] field.
+func (pkg *Package) GoVersion() string { return pkg.goVersion }
+
// Scope returns the (complete or incomplete) package scope
// holding the objects declared at package level (TypeNames,
// Consts, Vars, and Funcs).
diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go
index af82b3fa7a..740dbc9276 100644
--- a/src/cmd/compile/internal/types2/sizeof_test.go
+++ b/src/cmd/compile/internal/types2/sizeof_test.go
@@ -47,7 +47,7 @@ func TestSizeof(t *testing.T) {
// Misc
{Scope{}, 60, 104},
- {Package{}, 36, 72},
+ {Package{}, 44, 88},
{_TypeSet{}, 28, 56},
}
diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go
index 48adc185c3..94830e94f7 100644
--- a/src/cmd/compile/internal/types2/unify.go
+++ b/src/cmd/compile/internal/types2/unify.go
@@ -124,6 +124,20 @@ const (
exact
)
+func (m unifyMode) String() string {
+ switch m {
+ case 0:
+ return "inexact"
+ case assign:
+ return "assign"
+ case exact:
+ return "exact"
+ case assign | exact:
+ return "assign, exact"
+ }
+ return fmt.Sprintf("mode %d", m)
+}
+
// unify attempts to unify x and y and reports whether it succeeded.
// As a side-effect, types may be inferred for type parameters.
// The mode parameter controls how types are compared.
@@ -256,6 +270,15 @@ func (u *unifier) inferred(tparams []*TypeParam) []Type {
return list
}
+// asInterface returns the underlying type of x as an interface if
+// it is a non-type parameter interface. Otherwise it returns nil.
+func asInterface(x Type) (i *Interface) {
+ if _, ok := x.(*TypeParam); !ok {
+ i, _ = under(x).(*Interface)
+ }
+ return i
+}
+
// nify implements the core unification algorithm which is an
// adapted version of Checker.identical. For changes to that
// code the corresponding changes should be made here.
@@ -263,7 +286,7 @@ func (u *unifier) inferred(tparams []*TypeParam) []Type {
func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
u.depth++
if traceInference {
- u.tracef("%s ≡ %s (mode %d)", x, y, mode)
+ u.tracef("%s ≡ %s\t// %s", x, y, mode)
}
defer func() {
if traceInference && !result {
@@ -294,7 +317,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
// - type parameter recorded with u, make sure one is in x
if _, ok := x.(*Named); ok || u.asTypeParam(y) != nil {
if traceInference {
- u.tracef("%s ≡ %s (swap)", y, x)
+ u.tracef("%s ≡ %s\t// swap", y, x)
}
x, y = y, x
}
@@ -350,11 +373,49 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
if x := u.at(px); x != nil {
// x has an inferred type which must match y
if u.nify(x, y, mode, p) {
- // If we have a match, possibly through underlying types,
- // and y is a defined type, make sure we record that type
+ // We have a match, possibly through underlying types.
+ xi := asInterface(x)
+ yi := asInterface(y)
+ _, xn := x.(*Named)
+ _, yn := y.(*Named)
+ // If we have two interfaces, what to do depends on
+ // whether they are named and their method sets.
+ if xi != nil && yi != nil {
+ // Both types are interfaces.
+ // If both types are defined types, they must be identical
+ // because unification doesn't know which type has the "right" name.
+ if xn && yn {
+ return Identical(x, y)
+ }
+ // In all other cases, the method sets must match.
+ // The types unified so we know that corresponding methods
+ // match and we can simply compare the number of methods.
+ // TODO(gri) We may be able to relax this rule and select
+ // the more general interface. But if one of them is a defined
+ // type, it's not clear how to choose and whether we introduce
+ // an order dependency or not. Requiring the same method set
+ // is conservative.
+ if len(xi.typeSet().methods) != len(yi.typeSet().methods) {
+ return false
+ }
+ } else if xi != nil || yi != nil {
+ // One but not both of them are interfaces.
+ // In this case, either x or y could be viable matches for the corresponding
+ // type parameter, which means choosing either introduces an order dependence.
+ // Therefore, we must fail unification (go.dev/issue/60933).
+ return false
+ }
+ // If y is a defined type, make sure we record that type
// for type parameter x, which may have until now only
// recorded an underlying type (go.dev/issue/43056).
- if _, ok := y.(*Named); ok {
+ // Either both types are interfaces, or neither type is.
+ // If both are interfaces, they have the same methods.
+ //
+ // Note: Changing the recorded type for a type parameter to
+ // a defined type is only ok when unification is inexact.
+ // But in exact unification, if we have a match, x and y must
+ // be identical, so changing the recorded type for x is a no-op.
+ if yn {
u.set(px, y)
}
return true
@@ -384,14 +445,8 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
if enableInterfaceInference && mode&exact == 0 {
// One or both interfaces may be defined types.
// Look under the name, but not under type parameters (go.dev/issue/60564).
- var xi *Interface
- if _, ok := x.(*TypeParam); !ok {
- xi, _ = under(x).(*Interface)
- }
- var yi *Interface
- if _, ok := y.(*TypeParam); !ok {
- yi, _ = under(y).(*Interface)
- }
+ xi := asInterface(x)
+ yi := asInterface(y)
// If we have two interfaces, check the type terms for equivalence,
// and unify common methods if possible.
if xi != nil && yi != nil {
@@ -492,7 +547,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
// TODO(gri) Factor out type parameter handling from the switch.
if isTypeParam(y) {
if traceInference {
- u.tracef("%s ≡ %s (swap)", y, x)
+ u.tracef("%s ≡ %s\t// swap", y, x)
}
x, y = y, x
}
diff --git a/src/cmd/compile/internal/types2/version.go b/src/cmd/compile/internal/types2/version.go
index 7d01b829a9..e525f16470 100644
--- a/src/cmd/compile/internal/types2/version.go
+++ b/src/cmd/compile/internal/types2/version.go
@@ -6,7 +6,6 @@ package types2
import (
"cmd/compile/internal/syntax"
- "errors"
"fmt"
"strings"
)
@@ -44,23 +43,24 @@ var (
go1_21 = version{1, 21}
)
-var errVersionSyntax = errors.New("invalid Go version syntax")
-
// parseGoVersion parses a Go version string (such as "go1.12")
// and returns the version, or an error. If s is the empty
// string, the version is 0.0.
func parseGoVersion(s string) (v version, err error) {
+ bad := func() (version, error) {
+ return version{}, fmt.Errorf("invalid Go version syntax %q", s)
+ }
if s == "" {
return
}
if !strings.HasPrefix(s, "go") {
- return version{}, errVersionSyntax
+ return bad()
}
s = s[len("go"):]
i := 0
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
if i >= 10 || i == 0 && s[i] == '0' {
- return version{}, errVersionSyntax
+ return bad()
}
v.major = 10*v.major + int(s[i]) - '0'
}
@@ -68,7 +68,7 @@ func parseGoVersion(s string) (v version, err error) {
return
}
if i == 0 || s[i] != '.' {
- return version{}, errVersionSyntax
+ return bad()
}
s = s[i+1:]
if s == "0" {
@@ -81,14 +81,15 @@ func parseGoVersion(s string) (v version, err error) {
i = 0
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
if i >= 10 || i == 0 && s[i] == '0' {
- return version{}, errVersionSyntax
+ return bad()
}
v.minor = 10*v.minor + int(s[i]) - '0'
}
- if i > 0 && i == len(s) {
- return
- }
- return version{}, errVersionSyntax
+ // Accept any suffix after the minor number.
+ // We are only looking for the language version (major.minor)
+ // but want to accept any valid Go version, like go1.21.0
+ // and go1.21rc2.
+ return
}
// langCompat reports an error if the representation of a numeric
diff --git a/src/cmd/compile/internal/types2/version_test.go b/src/cmd/compile/internal/types2/version_test.go
new file mode 100644
index 0000000000..651758e1b0
--- /dev/null
+++ b/src/cmd/compile/internal/types2/version_test.go
@@ -0,0 +1,24 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types2
+
+import "testing"
+
+var parseGoVersionTests = []struct {
+ in string
+ out version
+}{
+ {"go1.21", version{1, 21}},
+ {"go1.21.0", version{1, 21}},
+ {"go1.21rc2", version{1, 21}},
+}
+
+func TestParseGoVersion(t *testing.T) {
+ for _, tt := range parseGoVersionTests {
+ if out, err := parseGoVersion(tt.in); out != tt.out || err != nil {
+ t.Errorf("parseGoVersion(%q) = %v, %v, want %v, nil", tt.in, out, err, tt.out)
+ }
+ }
+}
diff --git a/src/cmd/compile/internal/walk/builtin.go b/src/cmd/compile/internal/walk/builtin.go
index 5c924a90c5..786c31313c 100644
--- a/src/cmd/compile/internal/walk/builtin.go
+++ b/src/cmd/compile/internal/walk/builtin.go
@@ -135,7 +135,11 @@ func walkClear(n *ir.UnaryExpr) ir.Node {
typ := n.X.Type()
switch {
case typ.IsSlice():
- return arrayClear(n.X.Pos(), n.X, nil)
+ if n := arrayClear(n.X.Pos(), n.X, nil); n != nil {
+ return n
+ }
+ // If n == nil, we are clearing an array which takes zero memory, do nothing.
+ return ir.NewBlockStmt(n.Pos(), nil)
case typ.IsMap():
return mapClear(n.X, reflectdata.TypePtrAt(n.X.Pos(), n.X.Type()))
}
diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go
index 1e76761de3..057e0b75b8 100644
--- a/src/cmd/compile/internal/walk/order.go
+++ b/src/cmd/compile/internal/walk/order.go
@@ -755,7 +755,7 @@ func (o *orderState) stmt(n ir.Node) {
o.out = append(o.out, n)
o.popTemp(t)
- case ir.OMAX, ir.OMIN, ir.OPRINT, ir.OPRINTN, ir.ORECOVERFP:
+ case ir.OPRINT, ir.OPRINTN, ir.ORECOVERFP:
n := n.(*ir.CallExpr)
t := o.markTemp()
o.call(n)
@@ -1247,6 +1247,8 @@ func (o *orderState) expr1(n, lhs ir.Node) ir.Node {
ir.OMAKEMAP,
ir.OMAKESLICE,
ir.OMAKESLICECOPY,
+ ir.OMAX,
+ ir.OMIN,
ir.ONEW,
ir.OREAL,
ir.ORECOVERFP,
diff --git a/src/cmd/compile/internal/walk/walk.go b/src/cmd/compile/internal/walk/walk.go
index 265066200c..778b95d547 100644
--- a/src/cmd/compile/internal/walk/walk.go
+++ b/src/cmd/compile/internal/walk/walk.go
@@ -337,10 +337,14 @@ func mayCall(n ir.Node) bool {
n := n.(*ir.ConvExpr)
return ssagen.Arch.SoftFloat && (isSoftFloat(n.Type()) || isSoftFloat(n.X.Type()))
+ case ir.OMIN, ir.OMAX:
+ // string or float requires runtime call, see (*ssagen.state).minmax method.
+ return n.Type().IsString() || n.Type().IsFloat()
+
case ir.OLITERAL, ir.ONIL, ir.ONAME, ir.OLINKSYMOFFSET, ir.OMETHEXPR,
ir.OAND, ir.OANDNOT, ir.OLSH, ir.OOR, ir.ORSH, ir.OXOR, ir.OCOMPLEX, ir.OEFACE,
ir.OADDR, ir.OBITNOT, ir.ONOT, ir.OPLUS,
- ir.OCAP, ir.OIMAG, ir.OLEN, ir.OREAL, ir.OMIN, ir.OMAX,
+ ir.OCAP, ir.OIMAG, ir.OLEN, ir.OREAL,
ir.OCONVNOP, ir.ODOT,
ir.OCFUNC, ir.OIDATA, ir.OITAB, ir.OSPTR,
ir.OBYTES2STRTMP, ir.OGETG, ir.OGETCALLERPC, ir.OGETCALLERSP, ir.OSLICEHEADER, ir.OSTRINGHEADER:
diff --git a/src/cmd/cover/cover.go b/src/cmd/cover/cover.go
index ea6562c999..a4b837c9ad 100644
--- a/src/cmd/cover/cover.go
+++ b/src/cmd/cover/cover.go
@@ -95,7 +95,7 @@ const (
func main() {
objabi.AddVersionFlag()
flag.Usage = usage
- flag.Parse()
+ objabi.Flagparse(usage)
// Usage information when no arguments.
if flag.NFlag() == 0 && flag.NArg() == 0 {
diff --git a/src/cmd/dist/build.go b/src/cmd/dist/build.go
index 4b77ed36f7..8973a87168 100644
--- a/src/cmd/dist/build.go
+++ b/src/cmd/dist/build.go
@@ -631,7 +631,6 @@ var gentab = []struct {
}{
{"go/build", "zcgo.go", mkzcgo},
{"cmd/go/internal/cfg", "zdefaultcc.go", mkzdefaultcc},
- {"internal/platform", "zosarch.go", mkzosarch},
{"runtime/internal/sys", "zversion.go", mkzversion},
{"time/tzdata", "zzipdata.go", mktzdata},
}
@@ -1899,11 +1898,12 @@ func cmdversion() {
// cmdlist lists all supported platforms.
func cmdlist() {
jsonFlag := flag.Bool("json", false, "produce JSON output")
+ brokenFlag := flag.Bool("broken", false, "include broken ports")
xflagparse(0)
var plats []string
for p := range cgoEnabled {
- if broken[p] {
+ if broken[p] && !*brokenFlag {
continue
}
plats = append(plats, p)
@@ -1922,6 +1922,7 @@ func cmdlist() {
GOARCH string
CgoSupported bool
FirstClass bool
+ Broken bool `json:",omitempty"`
}
var results []jsonResult
for _, p := range plats {
@@ -1930,7 +1931,9 @@ func cmdlist() {
GOOS: fields[0],
GOARCH: fields[1],
CgoSupported: cgoEnabled[p],
- FirstClass: firstClass[p]})
+ FirstClass: firstClass[p],
+ Broken: broken[p],
+ })
}
out, err := json.MarshalIndent(results, "", "\t")
if err != nil {
diff --git a/src/cmd/dist/buildruntime.go b/src/cmd/dist/buildruntime.go
index b3fe8b02d8..1de78f0fdb 100644
--- a/src/cmd/dist/buildruntime.go
+++ b/src/cmd/dist/buildruntime.go
@@ -6,7 +6,6 @@ package main
import (
"fmt"
- "sort"
"strings"
)
@@ -80,25 +79,3 @@ func mkobjabi(file string) {
writefile(buf.String(), file, writeSkipSame)
}
-
-// mkzosarch writes zosarch.go for internal/platform.
-func mkzosarch(dir, file string) {
- // sort for deterministic file contents.
- var list []string
- for plat := range cgoEnabled {
- list = append(list, plat)
- }
- sort.Strings(list)
-
- var buf strings.Builder
- writeHeader(&buf)
- fmt.Fprintf(&buf, "package platform\n")
- fmt.Fprintln(&buf)
- fmt.Fprintf(&buf, "var osArchSupportsCgo = map[string]bool{\n")
- for _, plat := range list {
- fmt.Fprintf(&buf, "\t\t%s: %v,\n", quote(plat), cgoEnabled[plat])
- }
- fmt.Fprintf(&buf, "}\n")
-
- writefile(buf.String(), file, writeSkipSame)
-}
diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go
index 5e026f7bed..a528d7aa76 100644
--- a/src/cmd/dist/buildtool.go
+++ b/src/cmd/dist/buildtool.go
@@ -70,6 +70,11 @@ var bootstrapDirs = []string{
"internal/goexperiment",
"internal/goroot",
"internal/goversion",
+ // internal/lazyregexp is provided by Go 1.17, which permits it to
+ // be imported by other packages in this list, but is not provided
+ // by the Go 1.17 version of gccgo. It's on this list only to
+ // support gccgo, and can be removed if we require gccgo 14 or later.
+ "internal/lazyregexp",
"internal/pkgbits",
"internal/platform",
"internal/profile",
@@ -126,7 +131,6 @@ func bootstrapBuildTools() {
mkbuildcfg(pathf("%s/src/internal/buildcfg/zbootstrap.go", goroot))
mkobjabi(pathf("%s/src/cmd/internal/objabi/zbootstrap.go", goroot))
- mkzosarch("", pathf("%s/src/internal/platform/zosarch.go", goroot))
// Use $GOROOT/pkg/bootstrap as the bootstrap workspace root.
// We use a subdirectory of $GOROOT/pkg because that's the
diff --git a/src/cmd/dist/main.go b/src/cmd/dist/main.go
index 5f3e5bc9bd..f3425a9dd8 100644
--- a/src/cmd/dist/main.go
+++ b/src/cmd/dist/main.go
@@ -16,14 +16,14 @@ func usage() {
xprintf(`usage: go tool dist [command]
Commands are:
-banner print installation banner
-bootstrap rebuild everything
-clean deletes all built files
-env [-p] print environment (-p: include $PATH)
-install [dir] install individual directory
-list [-json] list all supported platforms
-test [-h] run Go test(s)
-version print Go version
+banner print installation banner
+bootstrap rebuild everything
+clean deletes all built files
+env [-p] print environment (-p: include $PATH)
+install [dir] install individual directory
+list [-json] [-broken] list all supported platforms
+test [-h] run Go test(s)
+version print Go version
All commands take -v flags to emit extra information.
`)
diff --git a/src/cmd/distpack/pack.go b/src/cmd/distpack/pack.go
index 6867ac17c2..e8b5255e63 100644
--- a/src/cmd/distpack/pack.go
+++ b/src/cmd/distpack/pack.go
@@ -127,7 +127,6 @@ func main() {
// Generated during cmd/dist. See ../dist/build.go:/gentab.
"src/cmd/go/internal/cfg/zdefaultcc.go",
"src/go/build/zcgo.go",
- "src/internal/platform/zosarch.go",
"src/runtime/internal/sys/zversion.go",
"src/time/tzdata/zzipdata.go",
diff --git a/src/cmd/go.mod b/src/cmd/go.mod
index 6b36e7cd45..ac8c9e4976 100644
--- a/src/cmd/go.mod
+++ b/src/cmd/go.mod
@@ -4,12 +4,12 @@ go 1.21
require (
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26
- golang.org/x/arch v0.3.0
- golang.org/x/mod v0.10.1-0.20230606122920-62c7e578f1a7
- golang.org/x/sync v0.2.1-0.20230601203510-93782cc822b6
- golang.org/x/sys v0.9.0
- golang.org/x/term v0.9.0
- golang.org/x/tools v0.9.4-0.20230613194514-c6c983054920
+ golang.org/x/arch v0.4.0
+ golang.org/x/mod v0.12.0
+ golang.org/x/sync v0.3.0
+ golang.org/x/sys v0.10.0
+ golang.org/x/term v0.10.0
+ golang.org/x/tools v0.11.1-0.20230712164437-1ca21856af7b
)
require github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2 // indirect
diff --git a/src/cmd/go.sum b/src/cmd/go.sum
index 59e3f831ea..b7245ea447 100644
--- a/src/cmd/go.sum
+++ b/src/cmd/go.sum
@@ -2,15 +2,15 @@ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbu
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2 h1:rcanfLhLDA8nozr/K289V1zcntHr3V+SHlXwzz1ZI2g=
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
-golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
-golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
-golang.org/x/mod v0.10.1-0.20230606122920-62c7e578f1a7 h1:OSEstGpBW1+G0wiXI0bBgOnI8nRJQKX3GCNxF75VR1s=
-golang.org/x/mod v0.10.1-0.20230606122920-62c7e578f1a7/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
-golang.org/x/sync v0.2.1-0.20230601203510-93782cc822b6 h1:kiysxTbHE5FVnrNyc9BC/yeJi3DTUBHIJtNbC9uvXk4=
-golang.org/x/sync v0.2.1-0.20230601203510-93782cc822b6/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
-golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
-golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.9.0 h1:GRRCnKYhdQrD8kfRAdQ6Zcw1P0OcELxGLKJvtjVMZ28=
-golang.org/x/term v0.9.0/go.mod h1:M6DEAAIenWoTxdKrOltXcmDY3rSplQUkrvaDU5FcQyo=
-golang.org/x/tools v0.9.4-0.20230613194514-c6c983054920 h1:FJIPEU9owLOeJgghpx63YhobtkWkORJ3O5ZnbFr8Bzs=
-golang.org/x/tools v0.9.4-0.20230613194514-c6c983054920/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
+golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=
+golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
+golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
+golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E=
+golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
+golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
+golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
+golang.org/x/tools v0.11.1-0.20230712164437-1ca21856af7b h1:KIZCni6lCdxd4gxHx49Zp9mhckTFRbI/ZPDbR3jKu90=
+golang.org/x/tools v0.11.1-0.20230712164437-1ca21856af7b/go.mod h1:anzJrxPjNtfgiYQYirP2CPGzGLxrH2u2QBhn6Bf3qY8=
diff --git a/src/cmd/go/internal/base/tool.go b/src/cmd/go/internal/base/tool.go
index 202e314b94..ab623da426 100644
--- a/src/cmd/go/internal/base/tool.go
+++ b/src/cmd/go/internal/base/tool.go
@@ -11,20 +11,31 @@ import (
"path/filepath"
"cmd/go/internal/cfg"
+ "cmd/go/internal/par"
)
// Tool returns the path to the named tool (for example, "vet").
// If the tool cannot be found, Tool exits the process.
func Tool(toolName string) string {
- toolPath := filepath.Join(build.ToolDir, toolName) + cfg.ToolExeSuffix()
- if len(cfg.BuildToolexec) > 0 {
- return toolPath
- }
- // Give a nice message if there is no tool with that name.
- if _, err := os.Stat(toolPath); err != nil {
+ toolPath, err := ToolPath(toolName)
+ if err != nil && len(cfg.BuildToolexec) == 0 {
+ // Give a nice message if there is no tool with that name.
fmt.Fprintf(os.Stderr, "go: no such tool %q\n", toolName)
SetExitStatus(2)
Exit()
}
return toolPath
}
+
+// Tool returns the path at which we expect to find the named tool
+// (for example, "vet"), and the error (if any) from statting that path.
+func ToolPath(toolName string) (string, error) {
+ toolPath := filepath.Join(build.ToolDir, toolName) + cfg.ToolExeSuffix()
+ err := toolStatCache.Do(toolPath, func() error {
+ _, err := os.Stat(toolPath)
+ return err
+ })
+ return toolPath, err
+}
+
+var toolStatCache par.Cache[string, error]
diff --git a/src/cmd/go/internal/gover/gover.go b/src/cmd/go/internal/gover/gover.go
index 247717125b..b2a8261feb 100644
--- a/src/cmd/go/internal/gover/gover.go
+++ b/src/cmd/go/internal/gover/gover.go
@@ -111,7 +111,6 @@ func IsPrerelease(x string) bool {
//
// Prev("1.2") = "1.1"
// Prev("1.3rc4") = "1.2"
-//
func Prev(x string) string {
v := parse(x)
if cmpInt(v.minor, "1") <= 0 {
@@ -180,6 +179,9 @@ func parse(x string) version {
// Parse prerelease.
i := 0
for i < len(x) && (x[i] < '0' || '9' < x[i]) {
+ if x[i] < 'a' || 'z' < x[i] {
+ return version{}
+ }
i++
}
if i == 0 {
diff --git a/src/cmd/go/internal/gover/gover_test.go b/src/cmd/go/internal/gover/gover_test.go
index 97b3b761c8..3a0bf10fc5 100644
--- a/src/cmd/go/internal/gover/gover_test.go
+++ b/src/cmd/go/internal/gover/gover_test.go
@@ -95,6 +95,25 @@ var prevTests = []testCase1[string, string]{
{"1.40000000000000000", "1.39999999999999999"},
}
+func TestIsValid(t *testing.T) { test1(t, isValidTests, "IsValid", IsValid) }
+
+var isValidTests = []testCase1[string, bool]{
+ {"1.2rc3", true},
+ {"1.2.3", true},
+ {"1.999testmod", true},
+ {"1.600+auto", false},
+ {"1.22", true},
+ {"1.21.0", true},
+ {"1.21rc2", true},
+ {"1.21", true},
+ {"1.20.0", true},
+ {"1.20", true},
+ {"1.19", true},
+ {"1.3", true},
+ {"1.2", true},
+ {"1", true},
+}
+
type testCase1[In, Out any] struct {
in In
out Out
diff --git a/src/cmd/go/internal/gover/toolchain.go b/src/cmd/go/internal/gover/toolchain.go
index efa2de46a5..b520277618 100644
--- a/src/cmd/go/internal/gover/toolchain.go
+++ b/src/cmd/go/internal/gover/toolchain.go
@@ -15,7 +15,7 @@ import (
// FromToolchain returns the Go version for the named toolchain,
// derived from the name itself (not by running the toolchain).
// A toolchain is named "goVERSION".
-// A suffix after the VERSION introduced by a +, -, space, or tab is removed.
+// A suffix after the VERSION introduced by a -, space, or tab is removed.
// Examples:
//
// FromToolchain("go1.2.3") == "1.2.3"
diff --git a/src/cmd/go/internal/modfetch/toolchain.go b/src/cmd/go/internal/modfetch/toolchain.go
index 623f68f97b..1669ab92e7 100644
--- a/src/cmd/go/internal/modfetch/toolchain.go
+++ b/src/cmd/go/internal/modfetch/toolchain.go
@@ -60,6 +60,15 @@ func (r *toolchainRepo) Versions(ctx context.Context, prefix string) (*Versions,
}
}
+ // Always include our own version.
+ // This means that the development branch of Go 1.21 (say) will allow 'go get go@1.21'
+ // even though there are no Go 1.21 releases yet.
+ // Once there is a release, 1.21 will be treated as a query matching the latest available release.
+ // Before then, 1.21 will be treated as a query that resolves to this entry we are adding (1.21).
+ if v := gover.Local(); !have[v] {
+ list = append(list, goPrefix+v)
+ }
+
if r.path == "go" {
sort.Slice(list, func(i, j int) bool {
return gover.Compare(list[i], list[j]) < 0
@@ -74,20 +83,27 @@ func (r *toolchainRepo) Versions(ctx context.Context, prefix string) (*Versions,
}
func (r *toolchainRepo) Stat(ctx context.Context, rev string) (*RevInfo, error) {
- // If we're asking about "go" (not "toolchain"), pretend to have
- // all earlier Go versions available without network access:
- // we will provide those ourselves, at least in GOTOOLCHAIN=auto mode.
- if r.path == "go" && gover.Compare(rev, gover.Local()) <= 0 {
- return &RevInfo{Version: rev}, nil
- }
-
// Convert rev to DL version and stat that to make sure it exists.
+ // In theory the go@ versions should be like 1.21.0
+ // and the toolchain@ versions should be like go1.21.0
+ // but people will type the wrong one, and so we accept
+ // both and silently correct it to the standard form.
prefix := ""
v := rev
v = strings.TrimPrefix(v, "go")
if r.path == "toolchain" {
prefix = "go"
}
+
+ if !gover.IsValid(v) {
+ return nil, fmt.Errorf("invalid %s version %s", r.path, rev)
+ }
+ // If we're asking about "go" (not "toolchain"), pretend to have
+ // all earlier Go versions available without network access:
+ // we will provide those ourselves, at least in GOTOOLCHAIN=auto mode.
+ if r.path == "go" && gover.Compare(v, gover.Local()) <= 0 {
+ return &RevInfo{Version: prefix + v}, nil
+ }
if gover.IsLang(v) {
return nil, fmt.Errorf("go language version %s is not a toolchain version", rev)
}
diff --git a/src/cmd/go/internal/modget/query.go b/src/cmd/go/internal/modget/query.go
index 68706e7c79..b78c1c4621 100644
--- a/src/cmd/go/internal/modget/query.go
+++ b/src/cmd/go/internal/modget/query.go
@@ -239,10 +239,13 @@ func (q *query) matchesPath(path string) bool {
// canMatchInModule reports whether the given module path can potentially
// contain q.pattern.
func (q *query) canMatchInModule(mPath string) bool {
+ if gover.IsToolchain(mPath) {
+ return false
+ }
if q.canMatchWildcardInModule != nil {
return q.canMatchWildcardInModule(mPath)
}
- return str.HasPathPrefix(q.pattern, mPath) && !gover.IsToolchain(mPath)
+ return str.HasPathPrefix(q.pattern, mPath)
}
// pathOnce invokes f to generate the pathSet for the given path,
diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go
index 81c32d27a1..f8ddf1101a 100644
--- a/src/cmd/go/internal/modload/query.go
+++ b/src/cmd/go/internal/modload/query.go
@@ -473,7 +473,11 @@ func newQueryMatcher(path string, query, current string, allowed AllowedFunc) (*
// AllowedFunc of qm.
func (qm *queryMatcher) allowsVersion(ctx context.Context, v string) bool {
if qm.prefix != "" && !strings.HasPrefix(v, qm.prefix) {
- return false
+ if gover.IsToolchain(qm.path) && strings.TrimSuffix(qm.prefix, ".") == v {
+ // Allow 1.21 to match "1.21." prefix.
+ } else {
+ return false
+ }
}
if qm.filter != nil && !qm.filter(v) {
return false
diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go
index 995da15c90..7df6f421d6 100644
--- a/src/cmd/go/internal/test/test.go
+++ b/src/cmd/go/internal/test/test.go
@@ -660,6 +660,7 @@ var defaultVetFlags = []string{
"-printf",
// "-rangeloops",
// "-shift",
+ "-slog",
"-stringintconv",
// "-structtags",
// "-tests",
diff --git a/src/cmd/go/internal/tool/tool.go b/src/cmd/go/internal/tool/tool.go
index 069968b1b6..ebe189bb81 100644
--- a/src/cmd/go/internal/tool/tool.go
+++ b/src/cmd/go/internal/tool/tool.go
@@ -7,8 +7,11 @@ package tool
import (
"context"
+ "encoding/json"
+ "flag"
"fmt"
"go/build"
+ "internal/platform"
"os"
"os/exec"
"os/signal"
@@ -68,10 +71,25 @@ func runTool(ctx context.Context, cmd *base.Command, args []string) {
return
}
}
- toolPath := base.Tool(toolName)
- if toolPath == "" {
- return
+
+ toolPath, err := base.ToolPath(toolName)
+ if err != nil {
+ if toolName == "dist" && len(args) > 1 && args[1] == "list" {
+ // cmd/distpack removes the 'dist' tool from the toolchain to save space,
+ // since it is normally only used for building the toolchain in the first
+ // place. However, 'go tool dist list' is useful for listing all supported
+ // platforms.
+ //
+ // If the dist tool does not exist, impersonate this command.
+ if impersonateDistList(args[2:]) {
+ return
+ }
+ }
+
+ // Emit the usual error for the missing tool.
+ _ = base.Tool(toolName)
}
+
if toolN {
cmd := toolPath
if len(args) > 1 {
@@ -88,7 +106,7 @@ func runTool(ctx context.Context, cmd *base.Command, args []string) {
Stdout: os.Stdout,
Stderr: os.Stderr,
}
- err := toolCmd.Start()
+ err = toolCmd.Start()
if err == nil {
c := make(chan os.Signal, 100)
signal.Notify(c)
@@ -145,3 +163,62 @@ func listTools() {
fmt.Println(name)
}
}
+
+func impersonateDistList(args []string) (handled bool) {
+ fs := flag.NewFlagSet("go tool dist list", flag.ContinueOnError)
+ jsonFlag := fs.Bool("json", false, "produce JSON output")
+ brokenFlag := fs.Bool("broken", false, "include broken ports")
+
+ // The usage for 'go tool dist' claims that
+ // “All commands take -v flags to emit extra information”,
+ // but list -v appears not to have any effect.
+ _ = fs.Bool("v", false, "emit extra information")
+
+ if err := fs.Parse(args); err != nil || len(fs.Args()) > 0 {
+ // Unrecognized flag or argument.
+ // Force fallback to the real 'go tool dist'.
+ return false
+ }
+
+ if !*jsonFlag {
+ for _, p := range platform.List {
+ if !*brokenFlag && platform.Broken(p.GOOS, p.GOARCH) {
+ continue
+ }
+ fmt.Println(p)
+ }
+ return true
+ }
+
+ type jsonResult struct {
+ GOOS string
+ GOARCH string
+ CgoSupported bool
+ FirstClass bool
+ Broken bool `json:",omitempty"`
+ }
+
+ var results []jsonResult
+ for _, p := range platform.List {
+ broken := platform.Broken(p.GOOS, p.GOARCH)
+ if broken && !*brokenFlag {
+ continue
+ }
+ if *jsonFlag {
+ results = append(results, jsonResult{
+ GOOS: p.GOOS,
+ GOARCH: p.GOARCH,
+ CgoSupported: platform.CgoSupported(p.GOOS, p.GOARCH),
+ FirstClass: platform.FirstClass(p.GOOS, p.GOARCH),
+ Broken: broken,
+ })
+ }
+ }
+ out, err := json.MarshalIndent(results, "", "\t")
+ if err != nil {
+ return false
+ }
+
+ os.Stdout.Write(out)
+ return true
+}
diff --git a/src/cmd/go/internal/toolchain/select.go b/src/cmd/go/internal/toolchain/select.go
index 8b1a0b94be..a44f393bc0 100644
--- a/src/cmd/go/internal/toolchain/select.go
+++ b/src/cmd/go/internal/toolchain/select.go
@@ -131,7 +131,7 @@ func Select() {
} else {
min, suffix, plus := strings.Cut(gotoolchain, "+") // go1.2.3+auto
if min != "local" {
- v := gover.FromToolchain(gotoolchain)
+ v := gover.FromToolchain(min)
if v == "" {
if plus {
base.Fatalf("invalid GOTOOLCHAIN %q: invalid minimum toolchain %q", gotoolchain, min)
diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go
index eb05c91f30..13d2a78a97 100644
--- a/src/cmd/go/internal/work/exec.go
+++ b/src/cmd/go/internal/work/exec.go
@@ -1115,6 +1115,7 @@ type vetConfig struct {
PackageVetx map[string]string // map package path to vetx data from earlier vet run
VetxOnly bool // only compute vetx data; don't report detected problems
VetxOutput string // write vetx data to this output file
+ GoVersion string // Go version for package
SucceedOnTypecheckFailure bool // awful hack; see #18395 and below
}
@@ -1149,6 +1150,13 @@ func buildVetConfig(a *Action, srcfiles []string) {
PackageFile: make(map[string]string),
Standard: make(map[string]bool),
}
+ if a.Package.Module != nil {
+ v := a.Package.Module.GoVersion
+ if v == "" {
+ v = gover.DefaultGoModVersion
+ }
+ vcfg.GoVersion = "go" + v
+ }
a.vetCfg = vcfg
for i, raw := range a.Package.Internal.RawImports {
final := a.Package.Imports[i]
@@ -3886,7 +3894,7 @@ func useResponseFile(path string, argLen int) bool {
// TODO: Note that other toolchains like CC are missing here for now.
prog := strings.TrimSuffix(filepath.Base(path), ".exe")
switch prog {
- case "compile", "link", "cgo", "asm":
+ case "compile", "link", "cgo", "asm", "cover":
default:
return false
}
diff --git a/src/cmd/go/internal/work/gc.go b/src/cmd/go/internal/work/gc.go
index 6043ad5353..26b4e0f490 100644
--- a/src/cmd/go/internal/work/gc.go
+++ b/src/cmd/go/internal/work/gc.go
@@ -85,19 +85,7 @@ func (gcToolchain) gc(b *Builder, a *Action, archive string, importcfg, embedcfg
if p.Module != nil {
v := p.Module.GoVersion
if v == "" {
- // We started adding a 'go' directive to the go.mod file unconditionally
- // as of Go 1.12, so any module that still lacks such a directive must
- // either have been authored before then, or have a hand-edited go.mod
- // file that hasn't been updated by cmd/go since that edit.
- //
- // Unfortunately, through at least Go 1.16 we didn't add versions to
- // vendor/modules.txt. So this could also be a vendored 1.16 dependency.
- //
- // Fortunately, there were no breaking changes to the language between Go
- // 1.11 and 1.16, so if we assume Go 1.16 semantics we will not introduce
- // any spurious errors — we will only mask errors, and not particularly
- // important ones at that.
- v = "1.16"
+ v = gover.DefaultGoModVersion
}
if allowedVersion(v) {
defaultGcFlags = append(defaultGcFlags, "-lang=go"+gover.Lang(v))
diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go
index 00b0a2b78b..2898c68049 100644
--- a/src/cmd/go/main.go
+++ b/src/cmd/go/main.go
@@ -300,10 +300,10 @@ func maybeStartTrace(pctx context.Context) context.Context {
//
// We have to handle the -C flag this way for two reasons:
//
-// 1. Toolchain selection needs to be in the right directory to look for go.mod and go.work.
+// 1. Toolchain selection needs to be in the right directory to look for go.mod and go.work.
//
-// 2. A toolchain switch later on reinvokes the new go command with the same arguments.
-// The parent toolchain has already done the chdir; the child must not try to do it again.
+// 2. A toolchain switch later on reinvokes the new go command with the same arguments.
+// The parent toolchain has already done the chdir; the child must not try to do it again.
func handleChdirFlag() {
_, used := lookupCmd(os.Args[1:])
used++ // because of [1:]
diff --git a/src/cmd/go/testdata/script/build_pgo_auto.txt b/src/cmd/go/testdata/script/build_pgo_auto.txt
index bb5b0e4828..5dd799a77f 100644
--- a/src/cmd/go/testdata/script/build_pgo_auto.txt
+++ b/src/cmd/go/testdata/script/build_pgo_auto.txt
@@ -3,7 +3,7 @@
[short] skip 'compiles and links executables'
# use default.pgo for a single main package
-go build -a -x -pgo=auto -o a1.exe ./a/a1
+go build -n -pgo=auto -o a1.exe ./a/a1
stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
# check that pgo applied to dependencies
@@ -12,25 +12,22 @@ stderr 'compile.*-p test/dep.*-pgoprofile=.*default\.pgo'
# check that pgo appears in build info
# N.B. we can't start the stdout check with -pgo because the script assumes that
# if the first arg starts with - it is a grep flag.
-go version -m a1.exe
-stdout 'build\s+-pgo=.*default\.pgo'
+stderr 'build\\t-pgo=.*default\.pgo'
# use default.pgo for ... with a single main package
-go build -a -x -pgo=auto ./a/...
+go build -n -pgo=auto ./a/...
stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
# check that pgo appears in build info
-go version -m a1$GOEXE
-stdout 'build\s+-pgo=.*default\.pgo'
+stderr 'build\\t-pgo=.*default\.pgo'
# build succeeds without PGO when default.pgo file is absent
-go build -a -x -pgo=auto -o nopgo.exe ./nopgo
+go build -n -pgo=auto -o nopgo.exe ./nopgo
stderr 'compile.*nopgo.go'
! stderr 'compile.*-pgoprofile'
# check that pgo doesn't appear in build info
-go version -m nopgo.exe
-! stdout 'build\s+-pgo='
+! stderr 'build\\t-pgo='
# other build-related commands
go install -a -n -pgo=auto ./a/a1
@@ -52,30 +49,27 @@ go list -deps -pgo=auto ./a/a1
# -pgo=auto is the default. Commands without explicit -pgo=auto
# should work as -pgo=auto.
-go build -a -x -o a1.exe ./a/a1
+go build -a -n -o a1.exe ./a/a1
stderr 'compile.*-pgoprofile=.*default\.pgo.*a1.go'
stderr 'compile.*-p test/dep.*-pgoprofile=.*default\.pgo'
# check that pgo appears in build info
-go version -m a1.exe
-stdout 'build\s+-pgo=.*default\.pgo'
+stderr 'build\\t-pgo=.*default\.pgo'
-go build -a -x -o nopgo.exe ./nopgo
+go build -a -n -o nopgo.exe ./nopgo
stderr 'compile.*nopgo.go'
! stderr 'compile.*-pgoprofile'
# check that pgo doesn't appear in build info
-go version -m nopgo.exe
-! stdout 'build\s+-pgo='
+! stderr 'build\\t-pgo='
# -pgo=off should turn off PGO.
-go build -a -x -pgo=off -o a1.exe ./a/a1
+go build -a -n -pgo=off -o a1.exe ./a/a1
stderr 'compile.*a1.go'
! stderr 'compile.*-pgoprofile'
# check that pgo doesn't appear in build info
-go version -m a1.exe
-! stdout 'build\s+-pgo='
+! stderr 'build\\t-pgo='
-- go.mod --
module test
diff --git a/src/cmd/go/testdata/script/build_pgo_auto_multi.txt b/src/cmd/go/testdata/script/build_pgo_auto_multi.txt
index 66dc9128dc..9ac57ce0c1 100644
--- a/src/cmd/go/testdata/script/build_pgo_auto_multi.txt
+++ b/src/cmd/go/testdata/script/build_pgo_auto_multi.txt
@@ -1,9 +1,6 @@
# Test go build -pgo=auto flag with multiple main packages.
-[short] skip 'compiles and links executables'
-
-env GOBIN=$WORK/bin
-go install -a -x -pgo=auto ./a ./b ./nopgo
+go install -a -n -pgo=auto ./a ./b ./nopgo
# a/default.pgo applies to package a and (transitive)
# dependencies.
@@ -36,16 +33,9 @@ stderr -count=3 'compile.*dep3(/|\\\\)dep3.go'
stderr -count=2 'compile.*-pgoprofile=.*dep3(/|\\\\)dep3\.go'
# check that pgo appears or not in build info as expected
-# N.B. we can't start the stdout check with -pgo because the script assumes that
-# if the first arg starts with - it is a grep flag.
-go version -m $GOBIN/a$GOEXE
-stdout 'build\s+-pgo=.*a'${/}'default\.pgo'
-
-go version -m $GOBIN/b$GOEXE
-stdout 'build\s+-pgo=.*b'${/}'default\.pgo'
-
-go version -m $GOBIN/nopgo$GOEXE
-! stdout 'build\s+-pgo='
+stderr 'path\\ttest/a\\n.*build\\t-pgo=.*a(/|\\\\)default\.pgo'
+stderr 'path\\ttest/b\\n.*build\\t-pgo=.*b(/|\\\\)default\.pgo'
+! stderr 'path\\ttest/nopgo\\n.*build\\t-pgo='
# go test works the same way
go test -a -n -pgo=auto ./a ./b ./nopgo
diff --git a/src/cmd/go/testdata/script/build_unsupported_goos.txt b/src/cmd/go/testdata/script/build_unsupported_goos.txt
index 8c1212934e..c94d6d252e 100644
--- a/src/cmd/go/testdata/script/build_unsupported_goos.txt
+++ b/src/cmd/go/testdata/script/build_unsupported_goos.txt
@@ -1,6 +1,6 @@
[compiler:gccgo] skip # gccgo assumes cross-compilation is always possible
-env GOOS=windwos
+env GOOS=windwos # intentional misspelling of windows
! go build -n exclude
-stderr 'unsupported GOOS/GOARCH pair' \ No newline at end of file
+stderr 'unsupported GOOS/GOARCH pair'
diff --git a/src/cmd/go/testdata/script/dist_list_missing.txt b/src/cmd/go/testdata/script/dist_list_missing.txt
new file mode 100644
index 0000000000..affaa009d9
--- /dev/null
+++ b/src/cmd/go/testdata/script/dist_list_missing.txt
@@ -0,0 +1,57 @@
+# Regression test for #60939: when 'go tool dist' is missing,
+# 'go tool dist list' should inject its output.
+
+
+# Set GOROOT to a directory that definitely does not include
+# a compiled 'dist' tool. 'go tool dist list' should still
+# work, because 'cmd/go' itself can impersonate this command.
+
+mkdir $WORK/goroot/bin
+mkdir $WORK/goroot/pkg/tool/${GOOS}_${GOARCH}
+env GOROOT=$WORK/goroot
+
+! go tool -n dist
+stderr 'go: no such tool "dist"'
+
+go tool dist list
+stdout linux/amd64
+cp stdout tool.txt
+
+go tool dist list -v
+stdout linux/amd64
+cp stdout tool-v.txt
+
+go tool dist list -broken
+stdout $GOOS/$GOARCH
+cp stdout tool-broken.txt
+
+go tool dist list -json
+stdout '"GOOS": "linux",\n\s*"GOARCH": "amd64",\n'
+cp stdout tool-json.txt
+
+go tool dist list -json -broken
+stdout '"GOOS": "'$GOOS'",\n\s*"GOARCH": "'$GOARCH'",\n'
+cp stdout tool-json-broken.txt
+
+[short] stop
+
+
+# Check against the real cmd/dist as the source of truth.
+
+env GOROOT=$TESTGO_GOROOT
+go build -o dist.exe cmd/dist
+
+exec ./dist.exe list
+cmp stdout tool.txt
+
+exec ./dist.exe list -v
+cmp stdout tool-v.txt
+
+exec ./dist.exe list -broken
+cmp stdout tool-broken.txt
+
+exec ./dist.exe list -json
+cmp stdout tool-json.txt
+
+exec ./dist.exe list -json -broken
+cmp stdout tool-json-broken.txt
diff --git a/src/cmd/go/testdata/script/gcflags_patterns.txt b/src/cmd/go/testdata/script/gcflags_patterns.txt
index 918c32d679..cc7b2fc0ad 100644
--- a/src/cmd/go/testdata/script/gcflags_patterns.txt
+++ b/src/cmd/go/testdata/script/gcflags_patterns.txt
@@ -3,17 +3,15 @@ env GO111MODULE=off
[!compiler:gc] skip 'using -gcflags and -ldflags'
[short] skip
-env GOCACHE=$WORK/gocache # Looking for compile commands, so need a clean cache.
-
# -gcflags=-e applies to named packages, not dependencies
-go build -n -v -gcflags=-e z1 z2
+go build -a -n -v -gcflags=-e z1 z2
stderr 'compile.* -p z1.* -e '
stderr 'compile.* -p z2.* -e '
stderr 'compile.* -p y'
! stderr 'compile.* -p [^z].* -e '
# -gcflags can specify package=flags, and can be repeated; last match wins
-go build -n -v -gcflags=-e -gcflags=z1=-N z1 z2
+go build -a -n -v -gcflags=-e -gcflags=z1=-N z1 z2
stderr 'compile.* -p z1.* -N '
! stderr 'compile.* -p z1.* -e '
! stderr 'compile.* -p z2.* -N '
@@ -23,11 +21,11 @@ stderr 'compile.* -p y'
! stderr 'compile.* -p [^z].* -N '
# -gcflags can have arbitrary spaces around the flags
-go build -n -v -gcflags=' z1 = -e ' z1
+go build -a -n -v -gcflags=' z1 = -e ' z1
stderr 'compile.* -p z1.* -e '
# -gcflags='all=-e' should apply to all packages, even with go test
-go test -c -n -gcflags='all=-e' z1
+go test -a -c -n -gcflags='all=-e' z1
stderr 'compile.* -p z3.* -e '
# this particular -gcflags argument made the compiler crash
@@ -39,31 +37,31 @@ stderr 'PhaseOptions usage'
stderr 'invalid value'
# -ldflags for implicit test package applies to test binary
-go test -c -n -gcflags=-N -ldflags=-X=x.y=z z1
+go test -a -c -n -gcflags=-N -ldflags=-X=x.y=z z1
stderr 'compile.* -N .*z_test.go'
stderr 'link.* -X=x.y=z'
# -ldflags for explicit test package applies to test binary
-go test -c -n -gcflags=z1=-N -ldflags=z1=-X=x.y=z z1
+go test -a -c -n -gcflags=z1=-N -ldflags=z1=-X=x.y=z z1
stderr 'compile.* -N .*z_test.go'
stderr 'link.* -X=x.y=z'
# -ldflags applies to link of command
-go build -n -ldflags=-X=math.pi=3 my/cmd/prog
+go build -a -n -ldflags=-X=math.pi=3 my/cmd/prog
stderr 'link.* -X=math.pi=3'
# -ldflags applies to link of command even with strange directory name
-go build -n -ldflags=-X=math.pi=3 my/cmd/prog/
+go build -a -n -ldflags=-X=math.pi=3 my/cmd/prog/
stderr 'link.* -X=math.pi=3'
# -ldflags applies to current directory
cd my/cmd/prog
-go build -n -ldflags=-X=math.pi=3
+go build -a -n -ldflags=-X=math.pi=3
stderr 'link.* -X=math.pi=3'
# -ldflags applies to current directory even if GOPATH is funny
[!case-sensitive] cd $WORK/GoPath/src/my/cmd/prog
-go build -n -ldflags=-X=math.pi=3
+go build -a -n -ldflags=-X=math.pi=3
stderr 'link.* -X=math.pi=3'
# cgo.a should not be a dependency of internally-linked go package
diff --git a/src/cmd/go/testdata/script/gotoolchain_local.txt b/src/cmd/go/testdata/script/gotoolchain_local.txt
index 0e08207f45..93f557008a 100644
--- a/src/cmd/go/testdata/script/gotoolchain_local.txt
+++ b/src/cmd/go/testdata/script/gotoolchain_local.txt
@@ -34,9 +34,9 @@ env GOTOOLCHAIN=go1.600+auto
go version
stdout go1.600
-env GOTOOLCHAIN=go1.400+auto
+env GOTOOLCHAIN=go1.400.0+auto
go version
-stdout go1.400
+stdout go1.400.0
# GOTOOLCHAIN=version+path sets a minimum too.
env GOTOOLCHAIN=go1.600+path
diff --git a/src/cmd/go/testdata/script/mod_get_toolchain.txt b/src/cmd/go/testdata/script/mod_get_toolchain.txt
index 143ad32a4e..758142d668 100644
--- a/src/cmd/go/testdata/script/mod_get_toolchain.txt
+++ b/src/cmd/go/testdata/script/mod_get_toolchain.txt
@@ -1,5 +1,5 @@
# setup
-env TESTGO_VERSION=go1.99.0
+env TESTGO_VERSION=go1.99rc1
env TESTGO_VERSION_SWITCH=switch
# go get go should use the latest Go 1.23
@@ -7,28 +7,28 @@ cp go.mod.orig go.mod
go get go
stderr '^go: upgraded go 1.21 => 1.23.9$'
grep 'go 1.23.9' go.mod
-grep 'toolchain go1.99.0' go.mod
+grep 'toolchain go1.99rc1' go.mod
# go get go@1.23 should use the latest Go 1.23
cp go.mod.orig go.mod
go get go@1.23
stderr '^go: upgraded go 1.21 => 1.23.9$'
grep 'go 1.23.9' go.mod
-grep 'toolchain go1.99.0' go.mod
+grep 'toolchain go1.99rc1' go.mod
# go get go@1.22 should use the latest Go 1.22
cp go.mod.orig go.mod
go get go@1.22
stderr '^go: upgraded go 1.21 => 1.22.9$'
grep 'go 1.22.9' go.mod
-grep 'toolchain go1.99.0' go.mod
+grep 'toolchain go1.99rc1' go.mod
# go get go@patch should use the latest patch release
go get go@1.22.1
go get go@patch
stderr '^go: upgraded go 1.22.1 => 1.22.9$'
grep 'go 1.22.9' go.mod
-grep 'toolchain go1.99.0' go.mod
+grep 'toolchain go1.99rc1' go.mod
# go get go@1.24 does NOT find the release candidate
cp go.mod.orig go.mod
@@ -40,20 +40,20 @@ cp go.mod.orig go.mod
go get go@1.24rc1
stderr '^go: upgraded go 1.21 => 1.24rc1$'
grep 'go 1.24rc1' go.mod
-grep 'toolchain go1.99.0' go.mod
+grep 'toolchain go1.99rc1' go.mod
# go get go@latest finds the latest Go 1.23
cp go.mod.orig go.mod
go get go@latest
stderr '^go: upgraded go 1.21 => 1.23.9$'
grep 'go 1.23.9' go.mod
-grep 'toolchain go1.99.0' go.mod
+grep 'toolchain go1.99rc1' go.mod
# Again, with toolchains.
# go get toolchain should find go1.999testmod.
go get toolchain
-stderr '^go: upgraded toolchain go1.99.0 => go1.999testmod$'
+stderr '^go: upgraded toolchain go1.99rc1 => go1.999testmod$'
grep 'go 1.23.9' go.mod
grep 'toolchain go1.999testmod' go.mod
@@ -96,6 +96,33 @@ stderr '^go: added toolchain go1.999testmod$'
grep 'go 1.21' go.mod
grep 'toolchain go1.999testmod' go.mod
+# Bug fixes.
+
+# go get go@garbage should fail but not crash
+! go get go@garbage
+! stderr panic
+stderr '^go: invalid go version garbage$'
+
+# go get go@go1.21.0 is OK - we silently correct to 1.21.0
+go get go@1.19
+go get go@go1.21.0
+stderr '^go: upgraded go 1.19 => 1.21.0'
+
+# go get toolchain@1.24rc1 is OK too.
+go get toolchain@1.24rc1
+stderr '^go: downgraded toolchain go1.999testmod => go1.24rc1$'
+
+# go get go@1.21 should work if we are the Go 1.21 language version,
+# even though there's no toolchain for it.
+# (Older versions resolve to the latest release in that version, so for example
+# go get go@1.20 might resolve to 1.20.9, but if we're the devel copy of
+# Go 1.21, there's no release yet to resolve to, so we resolve to ourselves.)
+env TESTGO_VERSION=go1.21
+go get go@1.19 toolchain@none
+go get go@1.21
+grep 'go 1.21$' go.mod
+! grep toolchain go.mod
+
-- go.mod.orig --
module m
diff --git a/src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt b/src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt
index 896bbab9fc..195f7b1527 100644
--- a/src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt
+++ b/src/cmd/go/testdata/script/mod_list_compiled_concurrent.txt
@@ -5,33 +5,12 @@ env GO111MODULE=on
# Regression test for golang.org/issue/29667:
# spurious 'failed to cache compiled Go files' errors.
-# This test failed reliably when run with -count=10
-# on a Linux workstation.
env GOCACHE=$WORK/gocache
mkdir $GOCACHE
go list -json -compiled -test=false -export=false -deps=true -- . &
go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-go list -json -compiled -test=false -export=false -deps=true -- . &
-
wait
-- go.mod --
diff --git a/src/cmd/go/testdata/script/vet_flags.txt b/src/cmd/go/testdata/script/vet_flags.txt
index 1c130b579e..73f4e4135b 100644
--- a/src/cmd/go/testdata/script/vet_flags.txt
+++ b/src/cmd/go/testdata/script/vet_flags.txt
@@ -52,27 +52,25 @@ env GOFLAGS='-unsafeptr'
stderr 'go: parsing \$GOFLAGS: unknown flag -unsafeptr'
env GOFLAGS=
-env GOCACHE=$WORK/gocache
-
# "go test" on a user package should by default enable an explicit list of analyzers.
-go test -x -run=none .
+go test -n -run=none .
stderr '[/\\]vet'$GOEXE'["]? .* -errorsas .* ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
# An explicitly-empty -vet argument should imply the default analyzers.
-go test -x -vet= -run=none .
+go test -n -vet= -run=none .
stderr '[/\\]vet'$GOEXE'["]? .* -errorsas .* ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
# "go test" on a standard package should by default disable an explicit list.
-go test -x -run=none encoding/binary
+go test -n -run=none encoding/binary
stderr '[/\\]vet'$GOEXE'["]? -unsafeptr=false -unreachable=false ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
-go test -x -vet= -run=none encoding/binary
+go test -n -vet= -run=none encoding/binary
stderr '[/\\]vet'$GOEXE'["]? -unsafeptr=false -unreachable=false ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
# Both should allow users to override via the -vet flag.
-go test -x -vet=unreachable -run=none .
+go test -n -vet=unreachable -run=none .
stderr '[/\\]vet'$GOEXE'["]? -unreachable ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
-go test -x -vet=unreachable -run=none encoding/binary
+go test -n -vet=unreachable -run=none encoding/binary
stderr '[/\\]vet'$GOEXE'["]? -unreachable ["]?\$WORK[/\\][^ ]*[/\\]vet\.cfg'
-- go.mod --
diff --git a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go
index de417946a4..9e866d87b6 100644
--- a/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go
+++ b/src/cmd/vendor/golang.org/x/arch/x86/x86asm/plan9x.go
@@ -83,6 +83,12 @@ func GoSyntax(inst Inst, pc uint64, symname SymLookup) string {
}
}
+ if inst.Op == CMP {
+ // Use reads-left-to-right ordering for comparisons.
+ // See issue 60920.
+ args[0], args[1] = args[1], args[0]
+ }
+
if args != nil {
op += " " + strings.Join(args, ", ")
}
diff --git a/src/cmd/vendor/golang.org/x/mod/internal/lazyregexp/lazyre.go b/src/cmd/vendor/golang.org/x/mod/internal/lazyregexp/lazyre.go
index 2681af35af..150f887e7a 100644
--- a/src/cmd/vendor/golang.org/x/mod/internal/lazyregexp/lazyre.go
+++ b/src/cmd/vendor/golang.org/x/mod/internal/lazyregexp/lazyre.go
@@ -13,7 +13,7 @@ import (
"sync"
)
-// Regexp is a wrapper around regexp.Regexp, where the underlying regexp will be
+// Regexp is a wrapper around [regexp.Regexp], where the underlying regexp will be
// compiled the first time it is needed.
type Regexp struct {
str string
diff --git a/src/cmd/vendor/golang.org/x/mod/modfile/read.go b/src/cmd/vendor/golang.org/x/mod/modfile/read.go
index a503bc2105..5b5bb5e115 100644
--- a/src/cmd/vendor/golang.org/x/mod/modfile/read.go
+++ b/src/cmd/vendor/golang.org/x/mod/modfile/read.go
@@ -65,7 +65,7 @@ type Comments struct {
}
// Comment returns the receiver. This isn't useful by itself, but
-// a Comments struct is embedded into all the expression
+// a [Comments] struct is embedded into all the expression
// implementation types, and this gives each of those a Comment
// method to satisfy the Expr interface.
func (c *Comments) Comment() *Comments {
diff --git a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go
index b4dd7997b6..930b6c59bc 100644
--- a/src/cmd/vendor/golang.org/x/mod/modfile/rule.go
+++ b/src/cmd/vendor/golang.org/x/mod/modfile/rule.go
@@ -5,17 +5,17 @@
// Package modfile implements a parser and formatter for go.mod files.
//
// The go.mod syntax is described in
-// https://golang.org/cmd/go/#hdr-The_go_mod_file.
+// https://pkg.go.dev/cmd/go/#hdr-The_go_mod_file.
//
-// The Parse and ParseLax functions both parse a go.mod file and return an
+// The [Parse] and [ParseLax] functions both parse a go.mod file and return an
// abstract syntax tree. ParseLax ignores unknown statements and may be used to
// parse go.mod files that may have been developed with newer versions of Go.
//
-// The File struct returned by Parse and ParseLax represent an abstract
-// go.mod file. File has several methods like AddNewRequire and DropReplace
-// that can be used to programmatically edit a file.
+// The [File] struct returned by Parse and ParseLax represent an abstract
+// go.mod file. File has several methods like [File.AddNewRequire] and
+// [File.DropReplace] that can be used to programmatically edit a file.
//
-// The Format function formats a File back to a byte slice which can be
+// The [Format] function formats a File back to a byte slice which can be
// written to a file.
package modfile
@@ -226,7 +226,7 @@ var dontFixRetract VersionFixer = func(_, vers string) (string, error) {
// data is the content of the file.
//
// fix is an optional function that canonicalizes module versions.
-// If fix is nil, all module versions must be canonical (module.CanonicalVersion
+// If fix is nil, all module versions must be canonical ([module.CanonicalVersion]
// must return the same string).
func Parse(file string, data []byte, fix VersionFixer) (*File, error) {
return parseToFile(file, data, fix, true)
@@ -923,7 +923,7 @@ func (f *File) Format() ([]byte, error) {
}
// Cleanup cleans up the file f after any edit operations.
-// To avoid quadratic behavior, modifications like DropRequire
+// To avoid quadratic behavior, modifications like [File.DropRequire]
// clear the entry but do not remove it from the slice.
// Cleanup cleans out all the cleared entries.
func (f *File) Cleanup() {
@@ -1075,8 +1075,8 @@ func (f *File) AddNewRequire(path, vers string, indirect bool) {
// The requirements in req must specify at most one distinct version for each
// module path.
//
-// If any existing requirements may be removed, the caller should call Cleanup
-// after all edits are complete.
+// If any existing requirements may be removed, the caller should call
+// [File.Cleanup] after all edits are complete.
func (f *File) SetRequire(req []*Require) {
type elem struct {
version string
diff --git a/src/cmd/vendor/golang.org/x/mod/modfile/work.go b/src/cmd/vendor/golang.org/x/mod/modfile/work.go
index 75dc1c5491..d7b99376eb 100644
--- a/src/cmd/vendor/golang.org/x/mod/modfile/work.go
+++ b/src/cmd/vendor/golang.org/x/mod/modfile/work.go
@@ -34,7 +34,7 @@ type Use struct {
// data is the content of the file.
//
// fix is an optional function that canonicalizes module versions.
-// If fix is nil, all module versions must be canonical (module.CanonicalVersion
+// If fix is nil, all module versions must be canonical ([module.CanonicalVersion]
// must return the same string).
func ParseWork(file string, data []byte, fix VersionFixer) (*WorkFile, error) {
fs, err := parse(file, data)
@@ -83,7 +83,7 @@ func ParseWork(file string, data []byte, fix VersionFixer) (*WorkFile, error) {
}
// Cleanup cleans up the file f after any edit operations.
-// To avoid quadratic behavior, modifications like DropRequire
+// To avoid quadratic behavior, modifications like [WorkFile.DropRequire]
// clear the entry but do not remove it from the slice.
// Cleanup cleans out all the cleared entries.
func (f *WorkFile) Cleanup() {
diff --git a/src/cmd/vendor/golang.org/x/mod/module/module.go b/src/cmd/vendor/golang.org/x/mod/module/module.go
index e9dec6e614..2a364b229b 100644
--- a/src/cmd/vendor/golang.org/x/mod/module/module.go
+++ b/src/cmd/vendor/golang.org/x/mod/module/module.go
@@ -4,7 +4,7 @@
// Package module defines the module.Version type along with support code.
//
-// The module.Version type is a simple Path, Version pair:
+// The [module.Version] type is a simple Path, Version pair:
//
// type Version struct {
// Path string
@@ -12,7 +12,7 @@
// }
//
// There are no restrictions imposed directly by use of this structure,
-// but additional checking functions, most notably Check, verify that
+// but additional checking functions, most notably [Check], verify that
// a particular path, version pair is valid.
//
// # Escaped Paths
@@ -140,7 +140,7 @@ type ModuleError struct {
Err error
}
-// VersionError returns a ModuleError derived from a Version and error,
+// VersionError returns a [ModuleError] derived from a [Version] and error,
// or err itself if it is already such an error.
func VersionError(v Version, err error) error {
var mErr *ModuleError
@@ -169,7 +169,7 @@ func (e *ModuleError) Unwrap() error { return e.Err }
// An InvalidVersionError indicates an error specific to a version, with the
// module path unknown or specified externally.
//
-// A ModuleError may wrap an InvalidVersionError, but an InvalidVersionError
+// A [ModuleError] may wrap an InvalidVersionError, but an InvalidVersionError
// must not wrap a ModuleError.
type InvalidVersionError struct {
Version string
@@ -193,8 +193,8 @@ func (e *InvalidVersionError) Error() string {
func (e *InvalidVersionError) Unwrap() error { return e.Err }
// An InvalidPathError indicates a module, import, or file path doesn't
-// satisfy all naming constraints. See CheckPath, CheckImportPath,
-// and CheckFilePath for specific restrictions.
+// satisfy all naming constraints. See [CheckPath], [CheckImportPath],
+// and [CheckFilePath] for specific restrictions.
type InvalidPathError struct {
Kind string // "module", "import", or "file"
Path string
@@ -294,7 +294,7 @@ func fileNameOK(r rune) bool {
}
// CheckPath checks that a module path is valid.
-// A valid module path is a valid import path, as checked by CheckImportPath,
+// A valid module path is a valid import path, as checked by [CheckImportPath],
// with three additional constraints.
// First, the leading path element (up to the first slash, if any),
// by convention a domain name, must contain only lower-case ASCII letters,
@@ -380,7 +380,7 @@ const (
// checkPath returns an error describing why the path is not valid.
// Because these checks apply to module, import, and file paths,
// and because other checks may be applied, the caller is expected to wrap
-// this error with InvalidPathError.
+// this error with [InvalidPathError].
func checkPath(path string, kind pathKind) error {
if !utf8.ValidString(path) {
return fmt.Errorf("invalid UTF-8")
@@ -532,7 +532,7 @@ var badWindowsNames = []string{
// they require ".vN" instead of "/vN", and for all N, not just N >= 2.
// SplitPathVersion returns with ok = false when presented with
// a path whose last path element does not satisfy the constraints
-// applied by CheckPath, such as "example.com/pkg/v1" or "example.com/pkg/v1.2".
+// applied by [CheckPath], such as "example.com/pkg/v1" or "example.com/pkg/v1.2".
func SplitPathVersion(path string) (prefix, pathMajor string, ok bool) {
if strings.HasPrefix(path, "gopkg.in/") {
return splitGopkgIn(path)
@@ -582,7 +582,7 @@ func splitGopkgIn(path string) (prefix, pathMajor string, ok bool) {
// MatchPathMajor reports whether the semantic version v
// matches the path major version pathMajor.
//
-// MatchPathMajor returns true if and only if CheckPathMajor returns nil.
+// MatchPathMajor returns true if and only if [CheckPathMajor] returns nil.
func MatchPathMajor(v, pathMajor string) bool {
return CheckPathMajor(v, pathMajor) == nil
}
@@ -622,7 +622,7 @@ func CheckPathMajor(v, pathMajor string) error {
// PathMajorPrefix returns the major-version tag prefix implied by pathMajor.
// An empty PathMajorPrefix allows either v0 or v1.
//
-// Note that MatchPathMajor may accept some versions that do not actually begin
+// Note that [MatchPathMajor] may accept some versions that do not actually begin
// with this prefix: namely, it accepts a 'v0.0.0-' prefix for a '.v1'
// pathMajor, even though that pathMajor implies 'v1' tagging.
func PathMajorPrefix(pathMajor string) string {
@@ -643,7 +643,7 @@ func PathMajorPrefix(pathMajor string) string {
}
// CanonicalVersion returns the canonical form of the version string v.
-// It is the same as semver.Canonical(v) except that it preserves the special build suffix "+incompatible".
+// It is the same as [semver.Canonical] except that it preserves the special build suffix "+incompatible".
func CanonicalVersion(v string) string {
cv := semver.Canonical(v)
if semver.Build(v) == "+incompatible" {
@@ -652,8 +652,8 @@ func CanonicalVersion(v string) string {
return cv
}
-// Sort sorts the list by Path, breaking ties by comparing Version fields.
-// The Version fields are interpreted as semantic versions (using semver.Compare)
+// Sort sorts the list by Path, breaking ties by comparing [Version] fields.
+// The Version fields are interpreted as semantic versions (using [semver.Compare])
// optionally followed by a tie-breaking suffix introduced by a slash character,
// like in "v0.0.1/go.mod".
func Sort(list []Version) {
@@ -793,7 +793,7 @@ func unescapeString(escaped string) (string, bool) {
}
// MatchPrefixPatterns reports whether any path prefix of target matches one of
-// the glob patterns (as defined by path.Match) in the comma-separated globs
+// the glob patterns (as defined by [path.Match]) in the comma-separated globs
// list. This implements the algorithm used when matching a module path to the
// GOPRIVATE environment variable, as described by 'go help module-private'.
//
diff --git a/src/cmd/vendor/golang.org/x/mod/module/pseudo.go b/src/cmd/vendor/golang.org/x/mod/module/pseudo.go
index f04ad37886..9cf19d3254 100644
--- a/src/cmd/vendor/golang.org/x/mod/module/pseudo.go
+++ b/src/cmd/vendor/golang.org/x/mod/module/pseudo.go
@@ -125,7 +125,7 @@ func IsPseudoVersion(v string) bool {
}
// IsZeroPseudoVersion returns whether v is a pseudo-version with a zero base,
-// timestamp, and revision, as returned by ZeroPseudoVersion.
+// timestamp, and revision, as returned by [ZeroPseudoVersion].
func IsZeroPseudoVersion(v string) bool {
return v == ZeroPseudoVersion(semver.Major(v))
}
diff --git a/src/cmd/vendor/golang.org/x/mod/semver/semver.go b/src/cmd/vendor/golang.org/x/mod/semver/semver.go
index a30a22bf20..9a2dfd33a7 100644
--- a/src/cmd/vendor/golang.org/x/mod/semver/semver.go
+++ b/src/cmd/vendor/golang.org/x/mod/semver/semver.go
@@ -140,7 +140,7 @@ func Compare(v, w string) int {
// Max canonicalizes its arguments and then returns the version string
// that compares greater.
//
-// Deprecated: use Compare instead. In most cases, returning a canonicalized
+// Deprecated: use [Compare] instead. In most cases, returning a canonicalized
// version is not expected or desired.
func Max(v, w string) string {
v = Canonical(v)
@@ -151,7 +151,7 @@ func Max(v, w string) string {
return w
}
-// ByVersion implements sort.Interface for sorting semantic version strings.
+// ByVersion implements [sort.Interface] for sorting semantic version strings.
type ByVersion []string
func (vs ByVersion) Len() int { return len(vs) }
@@ -164,7 +164,7 @@ func (vs ByVersion) Less(i, j int) bool {
return vs[i] < vs[j]
}
-// Sort sorts a list of semantic version strings using ByVersion.
+// Sort sorts a list of semantic version strings using [ByVersion].
func Sort(list []string) {
sort.Sort(ByVersion(list))
}
diff --git a/src/cmd/vendor/golang.org/x/mod/sumdb/client.go b/src/cmd/vendor/golang.org/x/mod/sumdb/client.go
index 1c1b0297f0..aecdc68849 100644
--- a/src/cmd/vendor/golang.org/x/mod/sumdb/client.go
+++ b/src/cmd/vendor/golang.org/x/mod/sumdb/client.go
@@ -19,7 +19,7 @@ import (
)
// A ClientOps provides the external operations
-// (file caching, HTTP fetches, and so on) needed by the Client.
+// (file caching, HTTP fetches, and so on) needed by the [Client].
// The methods must be safe for concurrent use by multiple goroutines.
type ClientOps interface {
// ReadRemote reads and returns the content served at the given path
@@ -72,7 +72,7 @@ type ClientOps interface {
// ErrWriteConflict signals a write conflict during Client.WriteConfig.
var ErrWriteConflict = errors.New("write conflict")
-// ErrSecurity is returned by Client operations that invoke Client.SecurityError.
+// ErrSecurity is returned by [Client] operations that invoke Client.SecurityError.
var ErrSecurity = errors.New("security error: misbehaving server")
// A Client is a client connection to a checksum database.
@@ -102,7 +102,7 @@ type Client struct {
tileSaved map[tlog.Tile]bool // which tiles have been saved using c.ops.WriteCache already
}
-// NewClient returns a new Client using the given Client.
+// NewClient returns a new [Client] using the given [ClientOps].
func NewClient(ops ClientOps) *Client {
return &Client{
ops: ops,
@@ -155,7 +155,7 @@ func (c *Client) initWork() {
}
// SetTileHeight sets the tile height for the Client.
-// Any call to SetTileHeight must happen before the first call to Lookup.
+// Any call to SetTileHeight must happen before the first call to [Client.Lookup].
// If SetTileHeight is not called, the Client defaults to tile height 8.
// SetTileHeight can be called at most once,
// and if so it must be called before the first call to Lookup.
@@ -174,7 +174,7 @@ func (c *Client) SetTileHeight(height int) {
// SetGONOSUMDB sets the list of comma-separated GONOSUMDB patterns for the Client.
// For any module path matching one of the patterns,
-// Lookup will return ErrGONOSUMDB.
+// [Client.Lookup] will return ErrGONOSUMDB.
// SetGONOSUMDB can be called at most once,
// and if so it must be called before the first call to Lookup.
func (c *Client) SetGONOSUMDB(list string) {
@@ -187,8 +187,8 @@ func (c *Client) SetGONOSUMDB(list string) {
c.nosumdb = list
}
-// ErrGONOSUMDB is returned by Lookup for paths that match
-// a pattern listed in the GONOSUMDB list (set by SetGONOSUMDB,
+// ErrGONOSUMDB is returned by [Client.Lookup] for paths that match
+// a pattern listed in the GONOSUMDB list (set by [Client.SetGONOSUMDB],
// usually from the environment variable).
var ErrGONOSUMDB = errors.New("skipped (listed in GONOSUMDB)")
diff --git a/src/cmd/vendor/golang.org/x/mod/sumdb/note/note.go b/src/cmd/vendor/golang.org/x/mod/sumdb/note/note.go
index 8c22b19d31..db9865c317 100644
--- a/src/cmd/vendor/golang.org/x/mod/sumdb/note/note.go
+++ b/src/cmd/vendor/golang.org/x/mod/sumdb/note/note.go
@@ -20,45 +20,45 @@
//
// # Verifying Notes
//
-// A Verifier allows verification of signatures by one server public key.
+// A [Verifier] allows verification of signatures by one server public key.
// It can report the name of the server and the uint32 hash of the key,
// and it can verify a purported signature by that key.
//
// The standard implementation of a Verifier is constructed
-// by NewVerifier starting from a verifier key, which is a
+// by [NewVerifier] starting from a verifier key, which is a
// plain text string of the form "<name>+<hash>+<keydata>".
//
-// A Verifiers allows looking up a Verifier by the combination
+// A [Verifiers] allows looking up a Verifier by the combination
// of server name and key hash.
//
// The standard implementation of a Verifiers is constructed
// by VerifierList from a list of known verifiers.
//
-// A Note represents a text with one or more signatures.
+// A [Note] represents a text with one or more signatures.
// An implementation can reject a note with too many signatures
// (for example, more than 100 signatures).
//
-// A Signature represents a signature on a note, verified or not.
+// A [Signature] represents a signature on a note, verified or not.
//
-// The Open function takes as input a signed message
+// The [Open] function takes as input a signed message
// and a set of known verifiers. It decodes and verifies
-// the message signatures and returns a Note structure
+// the message signatures and returns a [Note] structure
// containing the message text and (verified or unverified) signatures.
//
// # Signing Notes
//
-// A Signer allows signing a text with a given key.
+// A [Signer] allows signing a text with a given key.
// It can report the name of the server and the hash of the key
// and can sign a raw text using that key.
//
// The standard implementation of a Signer is constructed
-// by NewSigner starting from an encoded signer key, which is a
+// by [NewSigner] starting from an encoded signer key, which is a
// plain text string of the form "PRIVATE+KEY+<name>+<hash>+<keydata>".
// Anyone with an encoded signer key can sign messages using that key,
// so it must be kept secret. The encoding begins with the literal text
// "PRIVATE+KEY" to avoid confusion with the public server key.
//
-// The Sign function takes as input a Note and a list of Signers
+// The [Sign] function takes as input a Note and a list of Signers
// and returns an encoded, signed message.
//
// # Signed Note Format
@@ -88,7 +88,7 @@
// although doing so will require deploying the new algorithms to all clients
// before starting to depend on them for signatures.
//
-// The GenerateKey function generates and returns a new signer
+// The [GenerateKey] function generates and returns a new signer
// and corresponding verifier.
//
// # Example
@@ -123,9 +123,9 @@
// base URLs, the only syntactic requirement is that they
// not contain spaces or newlines).
//
-// If Open is given access to a Verifiers including the
-// Verifier for this key, then it will succeed at verifying
-// the encoded message and returning the parsed Note:
+// If [Open] is given access to a [Verifiers] including the
+// [Verifier] for this key, then it will succeed at verifying
+// the encoded message and returning the parsed [Note]:
//
// vkey := "PeterNeumann+c74f20a3+ARpc2QcUPDhMQegwxbzhKqiBfsVkmqq/LDE4izWy10TW"
// msg := []byte("If you think cryptography is the answer to your problem,\n" +
@@ -238,7 +238,7 @@ func isValidName(name string) bool {
return name != "" && utf8.ValidString(name) && strings.IndexFunc(name, unicode.IsSpace) < 0 && !strings.Contains(name, "+")
}
-// NewVerifier construct a new Verifier from an encoded verifier key.
+// NewVerifier construct a new [Verifier] from an encoded verifier key.
func NewVerifier(vkey string) (Verifier, error) {
name, vkey := chop(vkey, "+")
hash16, key64 := chop(vkey, "+")
@@ -295,7 +295,7 @@ func (v *verifier) Name() string { return v.name }
func (v *verifier) KeyHash() uint32 { return v.hash }
func (v *verifier) Verify(msg, sig []byte) bool { return v.verify(msg, sig) }
-// NewSigner constructs a new Signer from an encoded signer key.
+// NewSigner constructs a new [Signer] from an encoded signer key.
func NewSigner(skey string) (Signer, error) {
priv1, skey := chop(skey, "+")
priv2, skey := chop(skey, "+")
@@ -409,7 +409,7 @@ func (e *UnknownVerifierError) Error() string {
}
// An ambiguousVerifierError indicates that the given name and hash
-// match multiple keys passed to VerifierList.
+// match multiple keys passed to [VerifierList].
// (If this happens, some malicious actor has taken control of the
// verifier list, at which point we may as well give up entirely,
// but we diagnose the problem instead.)
@@ -422,7 +422,7 @@ func (e *ambiguousVerifierError) Error() string {
return fmt.Sprintf("ambiguous key %s+%08x", e.name, e.hash)
}
-// VerifierList returns a Verifiers implementation that uses the given list of verifiers.
+// VerifierList returns a [Verifiers] implementation that uses the given list of verifiers.
func VerifierList(list ...Verifier) Verifiers {
m := make(verifierMap)
for _, v := range list {
@@ -510,7 +510,7 @@ var (
// If known.Verifier returns any other error, Open returns that error.
//
// If no known verifier has signed an otherwise valid note,
-// Open returns an UnverifiedNoteError.
+// Open returns an [UnverifiedNoteError].
// In this case, the unverified note can be fetched from inside the error.
func Open(msg []byte, known Verifiers) (*Note, error) {
if known == nil {
diff --git a/src/cmd/vendor/golang.org/x/mod/sumdb/server.go b/src/cmd/vendor/golang.org/x/mod/sumdb/server.go
index 899bd462bc..1e1779d025 100644
--- a/src/cmd/vendor/golang.org/x/mod/sumdb/server.go
+++ b/src/cmd/vendor/golang.org/x/mod/sumdb/server.go
@@ -17,7 +17,7 @@ import (
)
// A ServerOps provides the external operations
-// (underlying database access and so on) needed by the Server.
+// (underlying database access and so on) needed by the [Server].
type ServerOps interface {
// Signed returns the signed hash of the latest tree.
Signed(ctx context.Context) ([]byte, error)
@@ -36,7 +36,7 @@ type ServerOps interface {
// A Server is the checksum database HTTP server,
// which implements http.Handler and should be invoked
-// to serve the paths listed in ServerPaths.
+// to serve the paths listed in [ServerPaths].
type Server struct {
ops ServerOps
}
diff --git a/src/cmd/vendor/golang.org/x/mod/sumdb/test.go b/src/cmd/vendor/golang.org/x/mod/sumdb/test.go
index c2755b8495..fb772452d9 100644
--- a/src/cmd/vendor/golang.org/x/mod/sumdb/test.go
+++ b/src/cmd/vendor/golang.org/x/mod/sumdb/test.go
@@ -14,15 +14,15 @@ import (
"golang.org/x/mod/sumdb/tlog"
)
-// NewTestServer constructs a new TestServer
+// NewTestServer constructs a new [TestServer]
// that will sign its tree with the given signer key
-// (see golang.org/x/mod/sumdb/note)
+// (see [golang.org/x/mod/sumdb/note])
// and fetch new records as needed by calling gosum.
func NewTestServer(signer string, gosum func(path, vers string) ([]byte, error)) *TestServer {
return &TestServer{signer: signer, gosum: gosum}
}
-// A TestServer is an in-memory implementation of Server for testing.
+// A TestServer is an in-memory implementation of [ServerOps] for testing.
type TestServer struct {
signer string
gosum func(path, vers string) ([]byte, error)
diff --git a/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tile.go b/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tile.go
index e4aeb14eff..857d487551 100644
--- a/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tile.go
+++ b/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tile.go
@@ -28,7 +28,7 @@ import (
// is tile/3/4/x001/x234/067.p/1, and
// Tile{H: 3, L: 4, N: 1234067, W: 8}'s path
// is tile/3/4/x001/x234/067.
-// See Tile's Path method and the ParseTilePath function.
+// See the [Tile.Path] method and the [ParseTilePath] function.
//
// The special level L=-1 holds raw record data instead of hashes.
// In this case, the level encodes into a tile path as the path element
@@ -46,7 +46,7 @@ type Tile struct {
// TileForIndex returns the tile of fixed height h ≥ 1
// and least width storing the given hash storage index.
//
-// If h ≤ 0, TileForIndex panics.
+// If h ≤ 0, [TileForIndex] panics.
func TileForIndex(h int, index int64) Tile {
if h <= 0 {
panic(fmt.Sprintf("TileForIndex: invalid height %d", h))
@@ -105,7 +105,7 @@ func tileHash(data []byte) Hash {
// size newTreeSize to replace a tree of size oldTreeSize.
// (No tiles need to be published for a tree of size zero.)
//
-// If h ≤ 0, TileForIndex panics.
+// If h ≤ 0, NewTiles panics.
func NewTiles(h int, oldTreeSize, newTreeSize int64) []Tile {
if h <= 0 {
panic(fmt.Sprintf("NewTiles: invalid height %d", h))
@@ -272,7 +272,7 @@ type TileReader interface {
// TileHashReader returns a HashReader that satisfies requests
// by loading tiles of the given tree.
//
-// The returned HashReader checks that loaded tiles are
+// The returned [HashReader] checks that loaded tiles are
// valid for the given tree. Therefore, any hashes returned
// by the HashReader are already proven to be in the tree.
func TileHashReader(tree Tree, tr TileReader) HashReader {
diff --git a/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tlog.go b/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tlog.go
index ae065f8557..6a11a752f9 100644
--- a/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tlog.go
+++ b/src/cmd/vendor/golang.org/x/mod/sumdb/tlog/tlog.go
@@ -131,7 +131,7 @@ func StoredHashIndex(level int, n int64) int64 {
return i + int64(level)
}
-// SplitStoredHashIndex is the inverse of StoredHashIndex.
+// SplitStoredHashIndex is the inverse of [StoredHashIndex].
// That is, SplitStoredHashIndex(StoredHashIndex(level, n)) == level, n.
func SplitStoredHashIndex(index int64) (level int, n int64) {
// Determine level 0 record before index.
@@ -183,7 +183,7 @@ func StoredHashes(n int64, data []byte, r HashReader) ([]Hash, error) {
return StoredHashesForRecordHash(n, RecordHash(data), r)
}
-// StoredHashesForRecordHash is like StoredHashes but takes
+// StoredHashesForRecordHash is like [StoredHashes] but takes
// as its second argument RecordHash(data) instead of data itself.
func StoredHashesForRecordHash(n int64, h Hash, r HashReader) ([]Hash, error) {
// Start with the record hash.
@@ -227,7 +227,7 @@ type HashReader interface {
ReadHashes(indexes []int64) ([]Hash, error)
}
-// A HashReaderFunc is a function implementing HashReader.
+// A HashReaderFunc is a function implementing [HashReader].
type HashReaderFunc func([]int64) ([]Hash, error)
func (f HashReaderFunc) ReadHashes(indexes []int64) ([]Hash, error) {
diff --git a/src/cmd/vendor/golang.org/x/mod/zip/zip.go b/src/cmd/vendor/golang.org/x/mod/zip/zip.go
index 7b48a2a2f0..574f83f220 100644
--- a/src/cmd/vendor/golang.org/x/mod/zip/zip.go
+++ b/src/cmd/vendor/golang.org/x/mod/zip/zip.go
@@ -10,31 +10,31 @@
//
// • All file paths within a zip file must start with "<module>@<version>/",
// where "<module>" is the module path and "<version>" is the version.
-// The module path must be valid (see golang.org/x/mod/module.CheckPath).
+// The module path must be valid (see [golang.org/x/mod/module.CheckPath]).
// The version must be valid and canonical (see
-// golang.org/x/mod/module.CanonicalVersion). The path must have a major
+// [golang.org/x/mod/module.CanonicalVersion]). The path must have a major
// version suffix consistent with the version (see
-// golang.org/x/mod/module.Check). The part of the file path after the
+// [golang.org/x/mod/module.Check]). The part of the file path after the
// "<module>@<version>/" prefix must be valid (see
-// golang.org/x/mod/module.CheckFilePath).
+// [golang.org/x/mod/module.CheckFilePath]).
//
// • No two file paths may be equal under Unicode case-folding (see
-// strings.EqualFold).
+// [strings.EqualFold]).
//
// • A go.mod file may or may not appear in the top-level directory. If present,
// it must be named "go.mod", not any other case. Files named "go.mod"
// are not allowed in any other directory.
//
-// • The total size in bytes of a module zip file may be at most MaxZipFile
+// • The total size in bytes of a module zip file may be at most [MaxZipFile]
// bytes (500 MiB). The total uncompressed size of the files within the
-// zip may also be at most MaxZipFile bytes.
+// zip may also be at most [MaxZipFile] bytes.
//
// • Each file's uncompressed size must match its declared 64-bit uncompressed
// size in the zip file header.
//
// • If the zip contains files named "<module>@<version>/go.mod" or
// "<module>@<version>/LICENSE", their sizes in bytes may be at most
-// MaxGoMod or MaxLICENSE, respectively (both are 16 MiB).
+// [MaxGoMod] or [MaxLICENSE], respectively (both are 16 MiB).
//
// • Empty directories are ignored. File permissions and timestamps are also
// ignored.
@@ -42,7 +42,7 @@
// • Symbolic links and other irregular files are not allowed.
//
// Note that this package does not provide hashing functionality. See
-// golang.org/x/mod/sumdb/dirhash.
+// [golang.org/x/mod/sumdb/dirhash].
package zip
import (
@@ -56,6 +56,7 @@ import (
"path"
"path/filepath"
"strings"
+ "time"
"unicode"
"unicode/utf8"
@@ -117,8 +118,9 @@ type CheckedFiles struct {
SizeError error
}
-// Err returns an error if CheckedFiles does not describe a valid module zip
-// file. SizeError is returned if that field is set. A FileErrorList is returned
+// Err returns an error if [CheckedFiles] does not describe a valid module zip
+// file. [CheckedFiles.SizeError] is returned if that field is set.
+// A [FileErrorList] is returned
// if there are one or more invalid files. Other errors may be returned in the
// future.
func (cf CheckedFiles) Err() error {
@@ -321,17 +323,17 @@ func checkFiles(files []File) (cf CheckedFiles, validFiles []File, validSizes []
}
// CheckDir reports whether the files in dir satisfy the name and size
-// constraints listed in the package documentation. The returned CheckedFiles
+// constraints listed in the package documentation. The returned [CheckedFiles]
// record contains lists of valid, invalid, and omitted files. If a directory is
// omitted (for example, a nested module or vendor directory), it will appear in
// the omitted list, but its files won't be listed.
//
// CheckDir returns an error if it encounters an I/O error or if the returned
-// CheckedFiles does not describe a valid module zip file (according to
-// CheckedFiles.Err). The returned CheckedFiles is still populated when such
+// [CheckedFiles] does not describe a valid module zip file (according to
+// [CheckedFiles.Err]). The returned [CheckedFiles] is still populated when such
// an error is returned.
//
-// Note that CheckDir will not open any files, so CreateFromDir may still fail
+// Note that CheckDir will not open any files, so [CreateFromDir] may still fail
// when CheckDir is successful due to I/O errors.
func CheckDir(dir string) (CheckedFiles, error) {
// List files (as CreateFromDir would) and check which ones are omitted
@@ -362,13 +364,13 @@ func CheckDir(dir string) (CheckedFiles, error) {
// CheckZip reports whether the files contained in a zip file satisfy the name
// and size constraints listed in the package documentation.
//
-// CheckZip returns an error if the returned CheckedFiles does not describe
-// a valid module zip file (according to CheckedFiles.Err). The returned
+// CheckZip returns an error if the returned [CheckedFiles] does not describe
+// a valid module zip file (according to [CheckedFiles.Err]). The returned
// CheckedFiles is still populated when an error is returned. CheckZip will
// also return an error if the module path or version is malformed or if it
// encounters an error reading the zip file.
//
-// Note that CheckZip does not read individual files, so Unzip may still fail
+// Note that CheckZip does not read individual files, so [Unzip] may still fail
// when CheckZip is successful due to I/O errors.
func CheckZip(m module.Version, zipFile string) (CheckedFiles, error) {
f, err := os.Open(zipFile)
@@ -476,7 +478,7 @@ func checkZip(m module.Version, f *os.File) (*zip.Reader, CheckedFiles, error) {
// and writes it to w.
//
// Create verifies the restrictions described in the package documentation
-// and should not produce an archive that Unzip cannot extract. Create does not
+// and should not produce an archive that [Unzip] cannot extract. Create does not
// include files in the output archive if they don't belong in the module zip.
// In particular, Create will not include files in modules found in
// subdirectories, most files in vendor directories, or irregular files (such
@@ -543,12 +545,12 @@ func Create(w io.Writer, m module.Version, files []File) (err error) {
// a directory, dir. The zip content is written to w.
//
// CreateFromDir verifies the restrictions described in the package
-// documentation and should not produce an archive that Unzip cannot extract.
+// documentation and should not produce an archive that [Unzip] cannot extract.
// CreateFromDir does not include files in the output archive if they don't
// belong in the module zip. In particular, CreateFromDir will not include
// files in modules found in subdirectories, most files in vendor directories,
// or irregular files (such as symbolic links) in the output archive.
-// Additionally, unlike Create, CreateFromDir will not include directories
+// Additionally, unlike [Create], CreateFromDir will not include directories
// named ".bzr", ".git", ".hg", or ".svn".
func CreateFromDir(w io.Writer, m module.Version, dir string) (err error) {
defer func() {
@@ -580,8 +582,8 @@ func CreateFromDir(w io.Writer, m module.Version, dir string) (err error) {
// "sub/dir". To create a zip from the base of the repository, pass an empty
// string.
//
-// If CreateFromVCS returns ErrUnrecognizedVCS, consider falling back to
-// CreateFromDir.
+// If CreateFromVCS returns [UnrecognizedVCSError], consider falling back to
+// [CreateFromDir].
func CreateFromVCS(w io.Writer, m module.Version, repoRoot, revision, subdir string) (err error) {
defer func() {
if zerr, ok := err.(*zipError); ok {
@@ -653,6 +655,7 @@ func filesInGitRepo(dir, rev, subdir string) ([]File, error) {
return nil, err
}
+ haveLICENSE := false
var fs []File
for _, zf := range zipReader.File {
if !strings.HasPrefix(zf.Name, subdir) || strings.HasSuffix(zf.Name, "/") {
@@ -669,6 +672,23 @@ func filesInGitRepo(dir, rev, subdir string) ([]File, error) {
name: n,
f: zf,
})
+ if n == "LICENSE" {
+ haveLICENSE = true
+ }
+ }
+
+ if !haveLICENSE && subdir != "" {
+ // Note: this method of extracting the license from the root copied from
+ // https://go.googlesource.com/go/+/refs/tags/go1.20.4/src/cmd/go/internal/modfetch/coderepo.go#1118
+ // https://go.googlesource.com/go/+/refs/tags/go1.20.4/src/cmd/go/internal/modfetch/codehost/git.go#657
+ cmd := exec.Command("git", "cat-file", "blob", rev+":LICENSE")
+ cmd.Dir = dir
+ cmd.Env = append(os.Environ(), "PWD="+dir)
+ stdout := bytes.Buffer{}
+ cmd.Stdout = &stdout
+ if err := cmd.Run(); err == nil {
+ fs = append(fs, dataFile{name: "LICENSE", data: stdout.Bytes()})
+ }
}
return fs, nil
@@ -710,6 +730,26 @@ func (f zipFile) Path() string { return f.name }
func (f zipFile) Lstat() (os.FileInfo, error) { return f.f.FileInfo(), nil }
func (f zipFile) Open() (io.ReadCloser, error) { return f.f.Open() }
+type dataFile struct {
+ name string
+ data []byte
+}
+
+func (f dataFile) Path() string { return f.name }
+func (f dataFile) Lstat() (os.FileInfo, error) { return dataFileInfo{f}, nil }
+func (f dataFile) Open() (io.ReadCloser, error) { return io.NopCloser(bytes.NewReader(f.data)), nil }
+
+type dataFileInfo struct {
+ f dataFile
+}
+
+func (fi dataFileInfo) Name() string { return path.Base(fi.f.name) }
+func (fi dataFileInfo) Size() int64 { return int64(len(fi.f.data)) }
+func (fi dataFileInfo) Mode() os.FileMode { return 0644 }
+func (fi dataFileInfo) ModTime() time.Time { return time.Time{} }
+func (fi dataFileInfo) IsDir() bool { return false }
+func (fi dataFileInfo) Sys() interface{} { return nil }
+
// isVendoredPackage attempts to report whether the given filename is contained
// in a package whose import path contains (but does not end with) the component
// "vendor".
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh
index 3156462715..0c4d14929a 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh
+++ b/src/cmd/vendor/golang.org/x/sys/unix/mkerrors.sh
@@ -519,7 +519,7 @@ ccflags="$@"
$2 ~ /^LOCK_(SH|EX|NB|UN)$/ ||
$2 ~ /^LO_(KEY|NAME)_SIZE$/ ||
$2 ~ /^LOOP_(CLR|CTL|GET|SET)_/ ||
- $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
+ $2 ~ /^(AF|SOCK|SO|SOL|IPPROTO|IP|IPV6|TCP|MCAST|EVFILT|NOTE|SHUT|PROT|MAP|MREMAP|MFD|T?PACKET|MSG|SCM|MCL|DT|MADV|PR|LOCAL|TCPOPT|UDP)_/ ||
$2 ~ /^NFC_(GENL|PROTO|COMM|RF|SE|DIRECTION|LLCP|SOCKPROTO)_/ ||
$2 ~ /^NFC_.*_(MAX)?SIZE$/ ||
$2 ~ /^RAW_PAYLOAD_/ ||
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/mremap.go b/src/cmd/vendor/golang.org/x/sys/unix/mremap.go
new file mode 100644
index 0000000000..86213c05d6
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/sys/unix/mremap.go
@@ -0,0 +1,40 @@
+// 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 linux
+// +build linux
+
+package unix
+
+import "unsafe"
+
+type mremapMmapper struct {
+ mmapper
+ mremap func(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error)
+}
+
+func (m *mremapMmapper) Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
+ if newLength <= 0 || len(oldData) == 0 || len(oldData) != cap(oldData) || flags&MREMAP_FIXED != 0 {
+ return nil, EINVAL
+ }
+
+ pOld := &oldData[cap(oldData)-1]
+ m.Lock()
+ defer m.Unlock()
+ bOld := m.active[pOld]
+ if bOld == nil || &bOld[0] != &oldData[0] {
+ return nil, EINVAL
+ }
+ newAddr, errno := m.mremap(uintptr(unsafe.Pointer(&bOld[0])), uintptr(len(bOld)), uintptr(newLength), flags, 0)
+ if errno != nil {
+ return nil, errno
+ }
+ bNew := unsafe.Slice((*byte)(unsafe.Pointer(newAddr)), newLength)
+ pNew := &bNew[cap(bNew)-1]
+ if flags&MREMAP_DONTUNMAP == 0 {
+ delete(m.active, pOld)
+ }
+ m.active[pNew] = bNew
+ return bNew, nil
+}
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go
index 6de486befe..39de5f1430 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_linux.go
@@ -2124,11 +2124,15 @@ func writevRacedetect(iovecs []Iovec, n int) {
// mmap varies by architecture; see syscall_linux_*.go.
//sys munmap(addr uintptr, length uintptr) (err error)
+//sys mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error)
-var mapper = &mmapper{
- active: make(map[*byte][]byte),
- mmap: mmap,
- munmap: munmap,
+var mapper = &mremapMmapper{
+ mmapper: mmapper{
+ active: make(map[*byte][]byte),
+ mmap: mmap,
+ munmap: munmap,
+ },
+ mremap: mremap,
}
func Mmap(fd int, offset int64, length int, prot int, flags int) (data []byte, err error) {
@@ -2139,6 +2143,10 @@ func Munmap(b []byte) (err error) {
return mapper.Munmap(b)
}
+func Mremap(oldData []byte, newLength int, flags int) (data []byte, err error) {
+ return mapper.Mremap(oldData, newLength, flags)
+}
+
//sys Madvise(b []byte, advice int) (err error)
//sys Mprotect(b []byte, prot int) (err error)
//sys Mlock(b []byte) (err error)
@@ -2487,7 +2495,6 @@ func Getresgid() (rgid, egid, sgid int) {
// MqTimedreceive
// MqTimedsend
// MqUnlink
-// Mremap
// Msgctl
// Msgget
// Msgrcv
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go
index de936b677b..3784f402e5 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux.go
@@ -493,6 +493,7 @@ const (
BPF_F_TEST_RUN_ON_CPU = 0x1
BPF_F_TEST_STATE_FREQ = 0x8
BPF_F_TEST_XDP_LIVE_FRAMES = 0x2
+ BPF_F_XDP_DEV_BOUND_ONLY = 0x40
BPF_F_XDP_HAS_FRAGS = 0x20
BPF_H = 0x8
BPF_IMM = 0x0
@@ -826,9 +827,9 @@ const (
DM_UUID_FLAG = 0x4000
DM_UUID_LEN = 0x81
DM_VERSION = 0xc138fd00
- DM_VERSION_EXTRA = "-ioctl (2022-07-28)"
+ DM_VERSION_EXTRA = "-ioctl (2023-03-01)"
DM_VERSION_MAJOR = 0x4
- DM_VERSION_MINOR = 0x2f
+ DM_VERSION_MINOR = 0x30
DM_VERSION_PATCHLEVEL = 0x0
DT_BLK = 0x6
DT_CHR = 0x2
@@ -1197,6 +1198,7 @@ const (
FAN_EVENT_METADATA_LEN = 0x18
FAN_EVENT_ON_CHILD = 0x8000000
FAN_FS_ERROR = 0x8000
+ FAN_INFO = 0x20
FAN_MARK_ADD = 0x1
FAN_MARK_DONT_FOLLOW = 0x4
FAN_MARK_EVICTABLE = 0x200
@@ -1233,6 +1235,8 @@ const (
FAN_REPORT_PIDFD = 0x80
FAN_REPORT_TARGET_FID = 0x1000
FAN_REPORT_TID = 0x100
+ FAN_RESPONSE_INFO_AUDIT_RULE = 0x1
+ FAN_RESPONSE_INFO_NONE = 0x0
FAN_UNLIMITED_MARKS = 0x20
FAN_UNLIMITED_QUEUE = 0x10
FD_CLOEXEC = 0x1
@@ -1860,6 +1864,7 @@ const (
MEMWRITEOOB64 = 0xc0184d15
MFD_ALLOW_SEALING = 0x2
MFD_CLOEXEC = 0x1
+ MFD_EXEC = 0x10
MFD_HUGETLB = 0x4
MFD_HUGE_16GB = 0x88000000
MFD_HUGE_16MB = 0x60000000
@@ -1875,6 +1880,7 @@ const (
MFD_HUGE_8MB = 0x5c000000
MFD_HUGE_MASK = 0x3f
MFD_HUGE_SHIFT = 0x1a
+ MFD_NOEXEC_SEAL = 0x8
MINIX2_SUPER_MAGIC = 0x2468
MINIX2_SUPER_MAGIC2 = 0x2478
MINIX3_SUPER_MAGIC = 0x4d5a
@@ -1898,6 +1904,9 @@ const (
MOUNT_ATTR_SIZE_VER0 = 0x20
MOUNT_ATTR_STRICTATIME = 0x20
MOUNT_ATTR__ATIME = 0x70
+ MREMAP_DONTUNMAP = 0x4
+ MREMAP_FIXED = 0x2
+ MREMAP_MAYMOVE = 0x1
MSDOS_SUPER_MAGIC = 0x4d44
MSG_BATCH = 0x40000
MSG_CMSG_CLOEXEC = 0x40000000
@@ -2204,6 +2213,7 @@ const (
PACKET_USER = 0x6
PACKET_VERSION = 0xa
PACKET_VNET_HDR = 0xf
+ PACKET_VNET_HDR_SZ = 0x18
PARITY_CRC16_PR0 = 0x2
PARITY_CRC16_PR0_CCITT = 0x4
PARITY_CRC16_PR1 = 0x3
@@ -2221,6 +2231,7 @@ const (
PERF_ATTR_SIZE_VER5 = 0x70
PERF_ATTR_SIZE_VER6 = 0x78
PERF_ATTR_SIZE_VER7 = 0x80
+ PERF_ATTR_SIZE_VER8 = 0x88
PERF_AUX_FLAG_COLLISION = 0x8
PERF_AUX_FLAG_CORESIGHT_FORMAT_CORESIGHT = 0x0
PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW = 0x100
@@ -2361,6 +2372,7 @@ const (
PR_FP_EXC_UND = 0x40000
PR_FP_MODE_FR = 0x1
PR_FP_MODE_FRE = 0x2
+ PR_GET_AUXV = 0x41555856
PR_GET_CHILD_SUBREAPER = 0x25
PR_GET_DUMPABLE = 0x3
PR_GET_ENDIAN = 0x13
@@ -2369,6 +2381,8 @@ const (
PR_GET_FP_MODE = 0x2e
PR_GET_IO_FLUSHER = 0x3a
PR_GET_KEEPCAPS = 0x7
+ PR_GET_MDWE = 0x42
+ PR_GET_MEMORY_MERGE = 0x44
PR_GET_NAME = 0x10
PR_GET_NO_NEW_PRIVS = 0x27
PR_GET_PDEATHSIG = 0x2
@@ -2389,6 +2403,7 @@ const (
PR_MCE_KILL_GET = 0x22
PR_MCE_KILL_LATE = 0x0
PR_MCE_KILL_SET = 0x1
+ PR_MDWE_REFUSE_EXEC_GAIN = 0x1
PR_MPX_DISABLE_MANAGEMENT = 0x2c
PR_MPX_ENABLE_MANAGEMENT = 0x2b
PR_MTE_TAG_MASK = 0x7fff8
@@ -2423,6 +2438,8 @@ const (
PR_SET_FP_MODE = 0x2d
PR_SET_IO_FLUSHER = 0x39
PR_SET_KEEPCAPS = 0x8
+ PR_SET_MDWE = 0x41
+ PR_SET_MEMORY_MERGE = 0x43
PR_SET_MM = 0x23
PR_SET_MM_ARG_END = 0x9
PR_SET_MM_ARG_START = 0x8
@@ -2506,6 +2523,7 @@ const (
PTRACE_GETSIGMASK = 0x420a
PTRACE_GET_RSEQ_CONFIGURATION = 0x420f
PTRACE_GET_SYSCALL_INFO = 0x420e
+ PTRACE_GET_SYSCALL_USER_DISPATCH_CONFIG = 0x4211
PTRACE_INTERRUPT = 0x4207
PTRACE_KILL = 0x8
PTRACE_LISTEN = 0x4208
@@ -2536,6 +2554,7 @@ const (
PTRACE_SETREGSET = 0x4205
PTRACE_SETSIGINFO = 0x4203
PTRACE_SETSIGMASK = 0x420b
+ PTRACE_SET_SYSCALL_USER_DISPATCH_CONFIG = 0x4210
PTRACE_SINGLESTEP = 0x9
PTRACE_SYSCALL = 0x18
PTRACE_SYSCALL_INFO_ENTRY = 0x1
@@ -3072,7 +3091,7 @@ const (
TASKSTATS_GENL_NAME = "TASKSTATS"
TASKSTATS_GENL_VERSION = 0x1
TASKSTATS_TYPE_MAX = 0x6
- TASKSTATS_VERSION = 0xd
+ TASKSTATS_VERSION = 0xe
TCIFLUSH = 0x0
TCIOFF = 0x2
TCIOFLUSH = 0x2
@@ -3238,6 +3257,7 @@ const (
TP_STATUS_COPY = 0x2
TP_STATUS_CSUMNOTREADY = 0x8
TP_STATUS_CSUM_VALID = 0x80
+ TP_STATUS_GSO_TCP = 0x100
TP_STATUS_KERNEL = 0x0
TP_STATUS_LOSING = 0x4
TP_STATUS_SENDING = 0x2
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
index 9d5352c3e4..12a9a1389e 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go
@@ -443,6 +443,7 @@ const (
TIOCSWINSZ = 0x5414
TIOCVHANGUP = 0x5437
TOSTOP = 0x100
+ TPIDR2_MAGIC = 0x54504902
TUNATTACHFILTER = 0x401054d5
TUNDETACHFILTER = 0x401054d6
TUNGETDEVNETNS = 0x54e3
@@ -515,6 +516,7 @@ const (
XCASE = 0x4
XTABS = 0x1800
ZA_MAGIC = 0x54366345
+ ZT_MAGIC = 0x5a544e01
_HIDIOCGRAWNAME = 0x80804804
_HIDIOCGRAWPHYS = 0x80404805
_HIDIOCGRAWUNIQ = 0x80404808
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go
index 722c29a008..7ceec233fb 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_linux.go
@@ -1868,6 +1868,17 @@ func munmap(addr uintptr, length uintptr) (err error) {
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+func mremap(oldaddr uintptr, oldlength uintptr, newlength uintptr, flags int, newaddr uintptr) (xaddr uintptr, err error) {
+ r0, _, e1 := Syscall6(SYS_MREMAP, uintptr(oldaddr), uintptr(oldlength), uintptr(newlength), uintptr(flags), uintptr(newaddr), 0)
+ xaddr = uintptr(r0)
+ if e1 != 0 {
+ err = errnoErr(e1)
+ }
+ return
+}
+
+// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
+
func Madvise(b []byte, advice int) (err error) {
var _p0 unsafe.Pointer
if len(b) > 0 {
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go
index 7ea465204b..e6ed7d637d 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/zsysnum_linux_s390x.go
@@ -372,6 +372,7 @@ const (
SYS_LANDLOCK_CREATE_RULESET = 444
SYS_LANDLOCK_ADD_RULE = 445
SYS_LANDLOCK_RESTRICT_SELF = 446
+ SYS_MEMFD_SECRET = 447
SYS_PROCESS_MRELEASE = 448
SYS_FUTEX_WAITV = 449
SYS_SET_MEMPOLICY_HOME_NODE = 450
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go
index 00c3b8c20f..02e2462c8f 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux.go
@@ -1538,6 +1538,10 @@ const (
IFLA_GRO_MAX_SIZE = 0x3a
IFLA_TSO_MAX_SIZE = 0x3b
IFLA_TSO_MAX_SEGS = 0x3c
+ IFLA_ALLMULTI = 0x3d
+ IFLA_DEVLINK_PORT = 0x3e
+ IFLA_GSO_IPV4_MAX_SIZE = 0x3f
+ IFLA_GRO_IPV4_MAX_SIZE = 0x40
IFLA_PROTO_DOWN_REASON_UNSPEC = 0x0
IFLA_PROTO_DOWN_REASON_MASK = 0x1
IFLA_PROTO_DOWN_REASON_VALUE = 0x2
@@ -1968,7 +1972,7 @@ const (
NFT_MSG_GETFLOWTABLE = 0x17
NFT_MSG_DELFLOWTABLE = 0x18
NFT_MSG_GETRULE_RESET = 0x19
- NFT_MSG_MAX = 0x1a
+ NFT_MSG_MAX = 0x21
NFTA_LIST_UNSPEC = 0x0
NFTA_LIST_ELEM = 0x1
NFTA_HOOK_UNSPEC = 0x0
@@ -3651,7 +3655,7 @@ const (
ETHTOOL_MSG_PSE_GET = 0x24
ETHTOOL_MSG_PSE_SET = 0x25
ETHTOOL_MSG_RSS_GET = 0x26
- ETHTOOL_MSG_USER_MAX = 0x26
+ ETHTOOL_MSG_USER_MAX = 0x2b
ETHTOOL_MSG_KERNEL_NONE = 0x0
ETHTOOL_MSG_STRSET_GET_REPLY = 0x1
ETHTOOL_MSG_LINKINFO_GET_REPLY = 0x2
@@ -3691,7 +3695,7 @@ const (
ETHTOOL_MSG_MODULE_NTF = 0x24
ETHTOOL_MSG_PSE_GET_REPLY = 0x25
ETHTOOL_MSG_RSS_GET_REPLY = 0x26
- ETHTOOL_MSG_KERNEL_MAX = 0x26
+ ETHTOOL_MSG_KERNEL_MAX = 0x2b
ETHTOOL_A_HEADER_UNSPEC = 0x0
ETHTOOL_A_HEADER_DEV_INDEX = 0x1
ETHTOOL_A_HEADER_DEV_NAME = 0x2
@@ -3795,7 +3799,7 @@ const (
ETHTOOL_A_RINGS_TCP_DATA_SPLIT = 0xb
ETHTOOL_A_RINGS_CQE_SIZE = 0xc
ETHTOOL_A_RINGS_TX_PUSH = 0xd
- ETHTOOL_A_RINGS_MAX = 0xd
+ ETHTOOL_A_RINGS_MAX = 0x10
ETHTOOL_A_CHANNELS_UNSPEC = 0x0
ETHTOOL_A_CHANNELS_HEADER = 0x1
ETHTOOL_A_CHANNELS_RX_MAX = 0x2
@@ -3833,14 +3837,14 @@ const (
ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL = 0x17
ETHTOOL_A_COALESCE_USE_CQE_MODE_TX = 0x18
ETHTOOL_A_COALESCE_USE_CQE_MODE_RX = 0x19
- ETHTOOL_A_COALESCE_MAX = 0x19
+ ETHTOOL_A_COALESCE_MAX = 0x1c
ETHTOOL_A_PAUSE_UNSPEC = 0x0
ETHTOOL_A_PAUSE_HEADER = 0x1
ETHTOOL_A_PAUSE_AUTONEG = 0x2
ETHTOOL_A_PAUSE_RX = 0x3
ETHTOOL_A_PAUSE_TX = 0x4
ETHTOOL_A_PAUSE_STATS = 0x5
- ETHTOOL_A_PAUSE_MAX = 0x5
+ ETHTOOL_A_PAUSE_MAX = 0x6
ETHTOOL_A_PAUSE_STAT_UNSPEC = 0x0
ETHTOOL_A_PAUSE_STAT_PAD = 0x1
ETHTOOL_A_PAUSE_STAT_TX_FRAMES = 0x2
@@ -4490,7 +4494,7 @@ const (
NL80211_ATTR_MAC_HINT = 0xc8
NL80211_ATTR_MAC_MASK = 0xd7
NL80211_ATTR_MAX_AP_ASSOC_STA = 0xca
- NL80211_ATTR_MAX = 0x141
+ NL80211_ATTR_MAX = 0x145
NL80211_ATTR_MAX_CRIT_PROT_DURATION = 0xb4
NL80211_ATTR_MAX_CSA_COUNTERS = 0xce
NL80211_ATTR_MAX_MATCH_SETS = 0x85
@@ -4719,7 +4723,7 @@ const (
NL80211_BAND_ATTR_HT_CAPA = 0x4
NL80211_BAND_ATTR_HT_MCS_SET = 0x3
NL80211_BAND_ATTR_IFTYPE_DATA = 0x9
- NL80211_BAND_ATTR_MAX = 0xb
+ NL80211_BAND_ATTR_MAX = 0xd
NL80211_BAND_ATTR_RATES = 0x2
NL80211_BAND_ATTR_VHT_CAPA = 0x8
NL80211_BAND_ATTR_VHT_MCS_SET = 0x7
@@ -4860,7 +4864,7 @@ const (
NL80211_CMD_LEAVE_IBSS = 0x2c
NL80211_CMD_LEAVE_MESH = 0x45
NL80211_CMD_LEAVE_OCB = 0x6d
- NL80211_CMD_MAX = 0x98
+ NL80211_CMD_MAX = 0x99
NL80211_CMD_MICHAEL_MIC_FAILURE = 0x29
NL80211_CMD_MODIFY_LINK_STA = 0x97
NL80211_CMD_NAN_MATCH = 0x78
@@ -5841,6 +5845,8 @@ const (
TUN_F_TSO6 = 0x4
TUN_F_TSO_ECN = 0x8
TUN_F_UFO = 0x10
+ TUN_F_USO4 = 0x20
+ TUN_F_USO6 = 0x40
)
const (
@@ -5850,9 +5856,10 @@ const (
)
const (
- VIRTIO_NET_HDR_GSO_NONE = 0x0
- VIRTIO_NET_HDR_GSO_TCPV4 = 0x1
- VIRTIO_NET_HDR_GSO_UDP = 0x3
- VIRTIO_NET_HDR_GSO_TCPV6 = 0x4
- VIRTIO_NET_HDR_GSO_ECN = 0x80
+ VIRTIO_NET_HDR_GSO_NONE = 0x0
+ VIRTIO_NET_HDR_GSO_TCPV4 = 0x1
+ VIRTIO_NET_HDR_GSO_UDP = 0x3
+ VIRTIO_NET_HDR_GSO_TCPV6 = 0x4
+ VIRTIO_NET_HDR_GSO_UDP_L4 = 0x5
+ VIRTIO_NET_HDR_GSO_ECN = 0x80
)
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go
index 4ecc1495cd..6d8acbcc57 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go
@@ -337,6 +337,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint32
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
index 34fddff964..59293c6884 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go
@@ -350,6 +350,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint64
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
index 3b14a6031f..40cfa38c29 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go
@@ -328,6 +328,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint32
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
index 0517651ab3..055bc4216d 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go
@@ -329,6 +329,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint64
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go
index 3b0c518134..f28affbc60 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go
@@ -330,6 +330,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint64
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
index fccdf4dd0f..9d71e7ccd8 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go
@@ -333,6 +333,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint32
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
index 500de8fc07..fd5ccd332a 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go
@@ -332,6 +332,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint64
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
index d0434cd2c6..7704de77a2 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go
@@ -332,6 +332,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint64
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
index 84206ba534..df00b87571 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go
@@ -333,6 +333,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint32
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go
index ab078cf1f5..0942840db6 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go
@@ -340,6 +340,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint32
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
index 42eb2c4cef..0348743950 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go
@@ -339,6 +339,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint64
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
index 31304a4e8b..bad0670475 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go
@@ -339,6 +339,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint64
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
index c311f9612d..9ea54b7b86 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
@@ -357,6 +357,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint64
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
index bba3cefac1..aa268d025c 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go
@@ -352,6 +352,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint64
diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go
index ad8a013804..444045b6c5 100644
--- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go
+++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go
@@ -334,6 +334,8 @@ type Taskstats struct {
Ac_exe_inode uint64
Wpcopy_count uint64
Wpcopy_delay_total uint64
+ Irq_count uint64
+ Irq_delay_total uint64
}
type cpuMask uint64
diff --git a/src/cmd/vendor/golang.org/x/sys/windows/service.go b/src/cmd/vendor/golang.org/x/sys/windows/service.go
index c964b6848d..c44a1b9636 100644
--- a/src/cmd/vendor/golang.org/x/sys/windows/service.go
+++ b/src/cmd/vendor/golang.org/x/sys/windows/service.go
@@ -218,6 +218,10 @@ type SERVICE_FAILURE_ACTIONS struct {
Actions *SC_ACTION
}
+type SERVICE_FAILURE_ACTIONS_FLAG struct {
+ FailureActionsOnNonCrashFailures int32
+}
+
type SC_ACTION struct {
Type uint32
Delay uint32
diff --git a/src/cmd/vendor/golang.org/x/term/term_unix.go b/src/cmd/vendor/golang.org/x/term/term_unix.go
index a4e31ab1b2..62c2b3f41f 100644
--- a/src/cmd/vendor/golang.org/x/term/term_unix.go
+++ b/src/cmd/vendor/golang.org/x/term/term_unix.go
@@ -60,7 +60,7 @@ func restore(fd int, state *State) error {
func getSize(fd int) (width, height int, err error) {
ws, err := unix.IoctlGetWinsize(fd, unix.TIOCGWINSZ)
if err != nil {
- return -1, -1, err
+ return 0, 0, err
}
return int(ws.Col), int(ws.Row), nil
}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go
index afff0d82d8..c18b84b714 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall.go
@@ -271,6 +271,7 @@ func typeCheckCgoSourceFiles(fset *token.FileSet, pkg *types.Package, files []*a
Sizes: sizes,
Error: func(error) {}, // ignore errors (e.g. unused import)
}
+ setGoVersion(tc, pkg)
// It's tempting to record the new types in the
// existing pass.TypesInfo, but we don't own it.
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall_go120.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall_go120.go
new file mode 100644
index 0000000000..06b54946d7
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall_go120.go
@@ -0,0 +1,13 @@
+// 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.21
+
+package cgocall
+
+import "go/types"
+
+func setGoVersion(tc *types.Config, pkg *types.Package) {
+ // no types.Package.GoVersion until Go 1.21
+}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall_go121.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall_go121.go
new file mode 100644
index 0000000000..2a3e1fad22
--- /dev/null
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/cgocall/cgocall_go121.go
@@ -0,0 +1,13 @@
+// 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.21
+
+package cgocall
+
+import "go/types"
+
+func setGoVersion(tc *types.Config, pkg *types.Package) {
+ tc.GoVersion = pkg.GoVersion()
+}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go
index 6d8039fe2b..ac37e4784e 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/internal/analysisutil/util.go
@@ -118,12 +118,3 @@ func Imports(pkg *types.Package, path string) bool {
}
return false
}
-
-// IsNamed reports whether t is exactly a named type in a package with a given path.
-func IsNamed(t types.Type, path, name string) bool {
- if n, ok := t.(*types.Named); ok {
- obj := n.Obj()
- return obj.Pkg().Path() == path && obj.Name() == name
- }
- return false
-}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/slog/slog.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/slog/slog.go
index 8429eab935..92c1da8ef4 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/slog/slog.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/slog/slog.go
@@ -139,7 +139,7 @@ func run(pass *analysis.Pass) (any, error) {
}
func isAttr(t types.Type) bool {
- return analysisutil.IsNamed(t, "log/slog", "Attr")
+ return isNamed(t, "log/slog", "Attr")
}
// shortName returns a name for the function that is shorter than FullName.
@@ -195,28 +195,28 @@ func kvFuncSkipArgs(fn *types.Func) (int, bool) {
// The first key is the dereferenced receiver type name, or "" for a function.
var kvFuncs = map[string]map[string]int{
"": map[string]int{
- "Debug": 1,
- "Info": 1,
- "Warn": 1,
- "Error": 1,
- "DebugCtx": 2,
- "InfoCtx": 2,
- "WarnCtx": 2,
- "ErrorCtx": 2,
- "Log": 3,
- "Group": 1,
+ "Debug": 1,
+ "Info": 1,
+ "Warn": 1,
+ "Error": 1,
+ "DebugContext": 2,
+ "InfoContext": 2,
+ "WarnContext": 2,
+ "ErrorContext": 2,
+ "Log": 3,
+ "Group": 1,
},
"Logger": map[string]int{
- "Debug": 1,
- "Info": 1,
- "Warn": 1,
- "Error": 1,
- "DebugCtx": 2,
- "InfoCtx": 2,
- "WarnCtx": 2,
- "ErrorCtx": 2,
- "Log": 3,
- "With": 0,
+ "Debug": 1,
+ "Info": 1,
+ "Warn": 1,
+ "Error": 1,
+ "DebugContext": 2,
+ "InfoContext": 2,
+ "WarnContext": 2,
+ "ErrorContext": 2,
+ "Log": 3,
+ "With": 0,
},
"Record": map[string]int{
"Add": 0,
@@ -232,3 +232,12 @@ func isMethodExpr(info *types.Info, c *ast.CallExpr) bool {
sel := info.Selections[s]
return sel != nil && sel.Kind() == types.MethodExpr
}
+
+// isNamed reports whether t is exactly a named type in a package with a given path.
+func isNamed(t types.Type, path, name string) bool {
+ if n, ok := t.(*types.Named); ok {
+ obj := n.Obj()
+ return obj.Pkg() != nil && obj.Pkg().Path() == path && obj.Name() == name
+ }
+ return false
+}
diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go
index ff22d23ce5..10c76bc627 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/unitchecker/unitchecker.go
@@ -62,6 +62,7 @@ type Config struct {
Compiler string
Dir string
ImportPath string
+ GoVersion string // minimum required Go version, such as "go1.21.0"
GoFiles []string
NonGoFiles []string
IgnoredFiles []string
@@ -217,8 +218,9 @@ func run(fset *token.FileSet, cfg *Config, analyzers []*analysis.Analyzer) ([]re
return compilerImporter.Import(path)
})
tc := &types.Config{
- Importer: importer,
- Sizes: types.SizesFor("gc", build.Default.GOARCH), // assume gccgo ≡ gc?
+ Importer: importer,
+ Sizes: types.SizesFor("gc", build.Default.GOARCH), // assume gccgo ≡ gc?
+ GoVersion: cfg.GoVersion,
}
info := &types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
diff --git a/src/cmd/vendor/golang.org/x/tools/go/ast/inspector/inspector.go b/src/cmd/vendor/golang.org/x/tools/go/ast/inspector/inspector.go
index 3fbfebf369..1fc1de0bd1 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/ast/inspector/inspector.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/ast/inspector/inspector.go
@@ -64,8 +64,9 @@ type event struct {
// depth-first order. It calls f(n) for each node n before it visits
// n's children.
//
+// The complete traversal sequence is determined by ast.Inspect.
// The types argument, if non-empty, enables type-based filtering of
-// events. The function f if is called only for nodes whose type
+// events. The function f is called only for nodes whose type
// matches an element of the types slice.
func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) {
// Because it avoids postorder calls to f, and the pruning
@@ -97,6 +98,7 @@ func (in *Inspector) Preorder(types []ast.Node, f func(ast.Node)) {
// of the non-nil children of the node, followed by a call of
// f(n, false).
//
+// The complete traversal sequence is determined by ast.Inspect.
// The types argument, if non-empty, enables type-based filtering of
// events. The function f if is called only for nodes whose type
// matches an element of the types slice.
diff --git a/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go b/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
index 549aa9e54c..f2ce77fd59 100644
--- a/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
+++ b/src/cmd/vendor/golang.org/x/tools/go/types/objectpath/objectpath.go
@@ -137,6 +137,17 @@ type Encoder struct {
// These objects are sufficient to define the API of their package.
// The objects described by a package's export data are drawn from this set.
//
+// The set of objects accessible from a package's Scope depends on
+// whether the package was produced by type-checking syntax, or
+// reading export data; the latter may have a smaller Scope since
+// export data trims objects that are not reachable from an exported
+// declaration. For example, the For function will return a path for
+// an exported method of an unexported type that is not reachable
+// from any public declaration; this path will cause the Object
+// function to fail if called on a package loaded from export data.
+// TODO(adonovan): is this a bug or feature? Should this package
+// compute accessibility in the same way?
+//
// For does not return a path for predeclared names, imported package
// names, local names, and unexported package-level names (except
// types).
diff --git a/src/cmd/vendor/golang.org/x/tools/internal/facts/facts.go b/src/cmd/vendor/golang.org/x/tools/internal/facts/facts.go
index 81df45161a..954b42d696 100644
--- a/src/cmd/vendor/golang.org/x/tools/internal/facts/facts.go
+++ b/src/cmd/vendor/golang.org/x/tools/internal/facts/facts.go
@@ -158,24 +158,52 @@ type gobFact struct {
// for the same package. Each call to Decode returns an independent
// fact set.
type Decoder struct {
- pkg *types.Package
- packages map[string]*types.Package
+ pkg *types.Package
+ getPackage GetPackageFunc
}
// NewDecoder returns a fact decoder for the specified package.
+//
+// It uses a brute-force recursive approach to enumerate all objects
+// defined by dependencies of pkg, so that it can learn the set of
+// package paths that may be mentioned in the fact encoding. This does
+// not scale well; use [NewDecoderFunc] where possible.
func NewDecoder(pkg *types.Package) *Decoder {
// Compute the import map for this package.
// See the package doc comment.
- return &Decoder{pkg, importMap(pkg.Imports())}
+ m := importMap(pkg.Imports())
+ getPackageFunc := func(path string) *types.Package { return m[path] }
+ return NewDecoderFunc(pkg, getPackageFunc)
+}
+
+// NewDecoderFunc returns a fact decoder for the specified package.
+//
+// It calls the getPackage function for the package path string of
+// each dependency (perhaps indirect) that it encounters in the
+// encoding. If the function returns nil, the fact is discarded.
+//
+// This function is preferred over [NewDecoder] when the client is
+// capable of efficient look-up of packages by package path.
+func NewDecoderFunc(pkg *types.Package, getPackage GetPackageFunc) *Decoder {
+ return &Decoder{
+ pkg: pkg,
+ getPackage: getPackage,
+ }
}
-// Decode decodes all the facts relevant to the analysis of package pkg.
-// The read function reads serialized fact data from an external source
-// for one of of pkg's direct imports. The empty file is a valid
-// encoding of an empty fact set.
+// A GetPackageFunc function returns the package denoted by a package path.
+type GetPackageFunc = func(pkgPath string) *types.Package
+
+// Decode decodes all the facts relevant to the analysis of package
+// pkg. The read function reads serialized fact data from an external
+// source for one of pkg's direct imports, identified by package path.
+// The empty file is a valid encoding of an empty fact set.
//
// It is the caller's responsibility to call gob.Register on all
// necessary fact types.
+//
+// Concurrent calls to Decode are safe, so long as the
+// [GetPackageFunc] (if any) is also concurrency-safe.
func (d *Decoder) Decode(read func(*types.Package) ([]byte, error)) (*Set, error) {
// Read facts from imported packages.
// Facts may describe indirectly imported packages, or their objects.
@@ -202,13 +230,11 @@ func (d *Decoder) Decode(read func(*types.Package) ([]byte, error)) (*Set, error
if err := gob.NewDecoder(bytes.NewReader(data)).Decode(&gobFacts); err != nil {
return nil, fmt.Errorf("decoding facts for %q: %v", imp.Path(), err)
}
- if debug {
- logf("decoded %d facts: %v", len(gobFacts), gobFacts)
- }
+ logf("decoded %d facts: %v", len(gobFacts), gobFacts)
// Parse each one into a key and a Fact.
for _, f := range gobFacts {
- factPkg := d.packages[f.PkgPath]
+ factPkg := d.getPackage(f.PkgPath) // possibly an indirect dependency
if factPkg == nil {
// Fact relates to a dependency that was
// unused in this translation unit. Skip.
diff --git a/src/cmd/vendor/golang.org/x/tools/internal/facts/imports.go b/src/cmd/vendor/golang.org/x/tools/internal/facts/imports.go
index 7b21668660..b18e62d1d7 100644
--- a/src/cmd/vendor/golang.org/x/tools/internal/facts/imports.go
+++ b/src/cmd/vendor/golang.org/x/tools/internal/facts/imports.go
@@ -21,6 +21,10 @@ import (
// Packages in the map that are only indirectly imported may be
// incomplete (!pkg.Complete()).
//
+// This function scales very poorly with packages' transitive object
+// references, which can be more than a million for each package near
+// the top of a large project. (This was a significant contributor to
+// #60621.)
// TODO(adonovan): opt: compute this information more efficiently
// by obtaining it from the internals of the gcexportdata decoder.
func importMap(imports []*types.Package) map[string]*types.Package {
diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt
index f3bdde6b54..fe71cb4d3b 100644
--- a/src/cmd/vendor/modules.txt
+++ b/src/cmd/vendor/modules.txt
@@ -17,13 +17,13 @@ github.com/google/pprof/third_party/svgpan
# github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2
## explicit; go 1.12
github.com/ianlancetaylor/demangle
-# golang.org/x/arch v0.3.0
+# golang.org/x/arch v0.4.0
## explicit; go 1.17
golang.org/x/arch/arm/armasm
golang.org/x/arch/arm64/arm64asm
golang.org/x/arch/ppc64/ppc64asm
golang.org/x/arch/x86/x86asm
-# golang.org/x/mod v0.10.1-0.20230606122920-62c7e578f1a7
+# golang.org/x/mod v0.12.0
## explicit; go 1.17
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/modfile
@@ -34,19 +34,19 @@ golang.org/x/mod/sumdb/dirhash
golang.org/x/mod/sumdb/note
golang.org/x/mod/sumdb/tlog
golang.org/x/mod/zip
-# golang.org/x/sync v0.2.1-0.20230601203510-93782cc822b6
+# golang.org/x/sync v0.3.0
## explicit; go 1.17
golang.org/x/sync/semaphore
-# golang.org/x/sys v0.9.0
+# golang.org/x/sys v0.10.0
## explicit; go 1.17
golang.org/x/sys/internal/unsafeheader
golang.org/x/sys/plan9
golang.org/x/sys/unix
golang.org/x/sys/windows
-# golang.org/x/term v0.9.0
+# golang.org/x/term v0.10.0
## explicit; go 1.17
golang.org/x/term
-# golang.org/x/tools v0.9.4-0.20230613194514-c6c983054920
+# golang.org/x/tools v0.11.1-0.20230712164437-1ca21856af7b
## explicit; go 1.18
golang.org/x/tools/cmd/bisect
golang.org/x/tools/cover
diff --git a/src/crypto/ecdh/ecdh.go b/src/crypto/ecdh/ecdh.go
index 74420559b5..b86f521787 100644
--- a/src/crypto/ecdh/ecdh.go
+++ b/src/crypto/ecdh/ecdh.go
@@ -16,7 +16,11 @@ import (
)
type Curve interface {
- // GenerateKey generates a new PrivateKey from rand.
+ // GenerateKey generates a random PrivateKey.
+ //
+ // Most applications should use [crypto/rand.Reader] as rand. Note that the
+ // returned key does not depend deterministically on the bytes read from rand,
+ // and may change between calls and/or between versions.
GenerateKey(rand io.Reader) (*PrivateKey, error)
// NewPrivateKey checks that key is valid and returns a PrivateKey.
diff --git a/src/crypto/ecdsa/ecdsa.go b/src/crypto/ecdsa/ecdsa.go
index 1c93cefdbf..e1503779ae 100644
--- a/src/crypto/ecdsa/ecdsa.go
+++ b/src/crypto/ecdsa/ecdsa.go
@@ -150,7 +150,11 @@ func (priv *PrivateKey) Sign(rand io.Reader, digest []byte, opts crypto.SignerOp
return SignASN1(rand, priv, digest)
}
-// GenerateKey generates a public and private key pair.
+// GenerateKey generates a new ECDSA private key for the specified curve.
+//
+// Most applications should use [crypto/rand.Reader] as rand. Note that the
+// returned key does not depend deterministically on the bytes read from rand,
+// and may change between calls and/or between versions.
func GenerateKey(c elliptic.Curve, rand io.Reader) (*PrivateKey, error) {
randutil.MaybeReadByte(rand)
@@ -245,6 +249,10 @@ var errNoAsm = errors.New("no assembly implementation available")
// using the private key, priv. If the hash is longer than the bit-length of the
// private key's curve order, the hash will be truncated to that length. It
// returns the ASN.1 encoded signature.
+//
+// The signature is randomized. Most applications should use [crypto/rand.Reader]
+// as rand. Note that the returned signature does not depend deterministically on
+// the bytes read from rand, and may change between calls and/or between versions.
func SignASN1(rand io.Reader, priv *PrivateKey, hash []byte) ([]byte, error) {
randutil.MaybeReadByte(rand)
diff --git a/src/crypto/ed25519/ed25519.go b/src/crypto/ed25519/ed25519.go
index 32a8d9e86c..1dda9e5e9a 100644
--- a/src/crypto/ed25519/ed25519.go
+++ b/src/crypto/ed25519/ed25519.go
@@ -76,7 +76,7 @@ func (priv PrivateKey) Seed() []byte {
return bytes.Clone(priv[:SeedSize])
}
-// Sign signs the given message with priv. rand is ignored.
+// Sign signs the given message with priv. rand is ignored and can be nil.
//
// If opts.HashFunc() is [crypto.SHA512], the pre-hashed variant Ed25519ph is used
// and message is expected to be a SHA-512 hash, otherwise opts.HashFunc() must
@@ -132,6 +132,9 @@ func (o *Options) HashFunc() crypto.Hash { return o.Hash }
// GenerateKey generates a public/private key pair using entropy from rand.
// If rand is nil, [crypto/rand.Reader] will be used.
+//
+// The output of this function is deterministic, and equivalent to reading
+// [SeedSize] bytes from rand, and passing them to [NewKeyFromSeed].
func GenerateKey(rand io.Reader) (PublicKey, PrivateKey, error) {
if rand == nil {
rand = cryptorand.Reader
diff --git a/src/crypto/rsa/pkcs1v15.go b/src/crypto/rsa/pkcs1v15.go
index 489555358d..55fea1ab93 100644
--- a/src/crypto/rsa/pkcs1v15.go
+++ b/src/crypto/rsa/pkcs1v15.go
@@ -31,7 +31,10 @@ type PKCS1v15DecryptOptions struct {
//
// The random parameter is used as a source of entropy to ensure that
// encrypting the same message twice doesn't result in the same
-// ciphertext.
+// ciphertext. Most applications should use [crypto/rand.Reader]
+// as random. Note that the returned ciphertext does not depend
+// deterministically on the bytes read from random, and may change
+// between calls and/or between versions.
//
// WARNING: use of this function to encrypt plaintexts other than
// session keys is dangerous. Use RSA OAEP in new protocols.
@@ -79,7 +82,7 @@ func EncryptPKCS1v15(random io.Reader, pub *PublicKey, msg []byte) ([]byte, erro
}
// DecryptPKCS1v15 decrypts a plaintext using RSA and the padding scheme from PKCS #1 v1.5.
-// The random parameter is legacy and ignored, and it can be as nil.
+// The random parameter is legacy and ignored, and it can be nil.
//
// Note that whether this function returns an error or not discloses secret
// information. If an attacker can cause this function to run repeatedly and
@@ -275,7 +278,7 @@ var hashPrefixes = map[crypto.Hash][]byte{
// function. If hash is zero, hashed is signed directly. This isn't
// advisable except for interoperability.
//
-// The random parameter is legacy and ignored, and it can be as nil.
+// The random parameter is legacy and ignored, and it can be nil.
//
// This function is deterministic. Thus, if the set of possible
// messages is small, an attacker may be able to build a map from
diff --git a/src/crypto/rsa/pss.go b/src/crypto/rsa/pss.go
index f7d23b55ef..3a377cc9db 100644
--- a/src/crypto/rsa/pss.go
+++ b/src/crypto/rsa/pss.go
@@ -285,7 +285,17 @@ var invalidSaltLenErr = errors.New("crypto/rsa: PSSOptions.SaltLength cannot be
// digest must be the result of hashing the input message using the given hash
// function. The opts argument may be nil, in which case sensible defaults are
// used. If opts.Hash is set, it overrides hash.
+//
+// The signature is randomized depending on the message, key, and salt size,
+// using bytes from rand. Most applications should use [crypto/rand.Reader] as
+// rand.
func SignPSS(rand io.Reader, priv *PrivateKey, hash crypto.Hash, digest []byte, opts *PSSOptions) ([]byte, error) {
+ // Note that while we don't commit to deterministic execution with respect
+ // to the rand stream, we also don't apply MaybeReadByte, so per Hyrum's Law
+ // it's probably relied upon by some. It's a tolerable promise because a
+ // well-specified number of random bytes is included in the signature, in a
+ // well-specified way.
+
if boring.Enabled && rand == boring.RandReader {
bkey, err := boringPrivateKey(priv)
if err != nil {
diff --git a/src/crypto/rsa/rsa.go b/src/crypto/rsa/rsa.go
index 88e44508cd..f0aef1f542 100644
--- a/src/crypto/rsa/rsa.go
+++ b/src/crypto/rsa/rsa.go
@@ -263,8 +263,11 @@ func (priv *PrivateKey) Validate() error {
return nil
}
-// GenerateKey generates an RSA keypair of the given bit size using the
-// random source random (for example, crypto/rand.Reader).
+// GenerateKey generates a random RSA private key of the given bit size.
+//
+// Most applications should use [crypto/rand.Reader] as rand. Note that the
+// returned key does not depend deterministically on the bytes read from rand,
+// and may change between calls and/or between versions.
func GenerateKey(random io.Reader, bits int) (*PrivateKey, error) {
return GenerateMultiPrimeKey(random, 2, bits)
}
@@ -500,6 +503,7 @@ func encrypt(pub *PublicKey, plaintext []byte) ([]byte, error) {
//
// The random parameter is used as a source of entropy to ensure that
// encrypting the same message twice doesn't result in the same ciphertext.
+// Most applications should use [crypto/rand.Reader] as random.
//
// The label parameter may contain arbitrary data that will not be encrypted,
// but which gives important context to the message. For example, if a given
@@ -510,6 +514,12 @@ func encrypt(pub *PublicKey, plaintext []byte) ([]byte, error) {
// The message must be no longer than the length of the public modulus minus
// twice the hash length, minus a further 2.
func EncryptOAEP(hash hash.Hash, random io.Reader, pub *PublicKey, msg []byte, label []byte) ([]byte, error) {
+ // Note that while we don't commit to deterministic execution with respect
+ // to the random stream, we also don't apply MaybeReadByte, so per Hyrum's
+ // Law it's probably relied upon by some. It's a tolerable promise because a
+ // well-specified number of random bytes is included in the ciphertext, in a
+ // well-specified way.
+
if err := checkPub(pub); err != nil {
return nil, err
}
@@ -691,7 +701,7 @@ func decrypt(priv *PrivateKey, ciphertext []byte, check bool) ([]byte, error) {
// Encryption and decryption of a given message must use the same hash function
// and sha256.New() is a reasonable choice.
//
-// The random parameter is legacy and ignored, and it can be as nil.
+// The random parameter is legacy and ignored, and it can be nil.
//
// The label parameter must match the value given when encrypting. See
// EncryptOAEP for details.
diff --git a/src/crypto/x509/root_darwin_test.go b/src/crypto/x509/root_darwin_test.go
index df7ca99308..e6b52e9f91 100644
--- a/src/crypto/x509/root_darwin_test.go
+++ b/src/crypto/x509/root_darwin_test.go
@@ -12,7 +12,9 @@ import (
"time"
)
-func TestPlatformVerifier(t *testing.T) {
+func TestPlatformVerifierLegacy(t *testing.T) {
+ // TODO(#52108): This can be removed once the synthetic test root is deployed on
+ // builders.
if !testenv.HasExternalNetwork() {
t.Skip()
}
diff --git a/src/crypto/x509/root_windows_test.go b/src/crypto/x509/root_windows_test.go
index 54dbc161dc..1372c043b2 100644
--- a/src/crypto/x509/root_windows_test.go
+++ b/src/crypto/x509/root_windows_test.go
@@ -16,7 +16,9 @@ import (
"time"
)
-func TestPlatformVerifier(t *testing.T) {
+func TestPlatformVerifierLegacy(t *testing.T) {
+ // TODO(#52108): This can be removed once the synthetic test root is deployed on
+ // builders.
if !testenv.HasExternalNetwork() {
t.Skip()
}
diff --git a/src/crypto/x509/verify_test.go b/src/crypto/x509/verify_test.go
index ce6605d972..3551b470ce 100644
--- a/src/crypto/x509/verify_test.go
+++ b/src/crypto/x509/verify_test.go
@@ -512,22 +512,21 @@ func testVerify(t *testing.T, test verifyTest, useSystemRoots bool) {
return true
}
- // Every expected chain should match 1 returned chain
+ // Every expected chain should match one (or more) returned chain. We tolerate multiple
+ // matches, as due to root store semantics it is plausible that (at least on the system
+ // verifiers) multiple identical (looking) chains may be returned when two roots with the
+ // same subject are present.
for _, expectedChain := range test.expectedChains {
- nChainMatched := 0
+ var match bool
for _, chain := range chains {
if doesMatch(expectedChain, chain) {
- nChainMatched++
+ match = true
+ break
}
}
- if nChainMatched != 1 {
- t.Errorf("Got %v matches instead of %v for expected chain %v", nChainMatched, 1, expectedChain)
- for _, chain := range chains {
- if doesMatch(expectedChain, chain) {
- t.Errorf("\t matched %v", chainToDebugString(chain))
- }
- }
+ if !match {
+ t.Errorf("No match found for %v", expectedChain)
}
}
diff --git a/src/database/sql/sql.go b/src/database/sql/sql.go
index a77d63dc5e..836fe83e2e 100644
--- a/src/database/sql/sql.go
+++ b/src/database/sql/sql.go
@@ -2944,15 +2944,17 @@ func (rs *Rows) initContextClose(ctx, txctx context.Context) {
if bypassRowsAwaitDone {
return
}
- ctx, rs.cancel = context.WithCancel(ctx)
- go rs.awaitDone(ctx, txctx)
+ closectx, cancel := context.WithCancel(ctx)
+ rs.cancel = cancel
+ go rs.awaitDone(ctx, txctx, closectx)
}
-// awaitDone blocks until either ctx or txctx is canceled. The ctx is provided
-// from the query context and is canceled when the query Rows is closed.
+// awaitDone blocks until ctx, txctx, or closectx is canceled.
+// The ctx is provided from the query context.
// If the query was issued in a transaction, the transaction's context
-// is also provided in txctx to ensure Rows is closed if the Tx is closed.
-func (rs *Rows) awaitDone(ctx, txctx context.Context) {
+// is also provided in txctx, to ensure Rows is closed if the Tx is closed.
+// The closectx is closed by an explicit call to rs.Close.
+func (rs *Rows) awaitDone(ctx, txctx, closectx context.Context) {
var txctxDone <-chan struct{}
if txctx != nil {
txctxDone = txctx.Done()
@@ -2964,6 +2966,9 @@ func (rs *Rows) awaitDone(ctx, txctx context.Context) {
case <-txctxDone:
err := txctx.Err()
rs.contextDone.Store(&err)
+ case <-closectx.Done():
+ // rs.cancel was called via Close(); don't store this into contextDone
+ // to ensure Err() is unaffected.
}
rs.close(ctx.Err())
}
diff --git a/src/database/sql/sql_test.go b/src/database/sql/sql_test.go
index 718056c351..e6a5cd912a 100644
--- a/src/database/sql/sql_test.go
+++ b/src/database/sql/sql_test.go
@@ -4493,6 +4493,31 @@ func TestContextCancelBetweenNextAndErr(t *testing.T) {
}
}
+func TestNilErrorAfterClose(t *testing.T) {
+ db := newTestDB(t, "people")
+ defer closeDB(t, db)
+
+ // This WithCancel is important; Rows contains an optimization to avoid
+ // spawning a goroutine when the query/transaction context cannot be
+ // canceled, but this test tests a bug which is caused by said goroutine.
+ ctx, cancel := context.WithCancel(context.Background())
+ defer cancel()
+
+ r, err := db.QueryContext(ctx, "SELECT|people|name|")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ if err := r.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ time.Sleep(10 * time.Millisecond) // increase odds of seeing failure
+ if err := r.Err(); err != nil {
+ t.Fatal(err)
+ }
+}
+
// badConn implements a bad driver.Conn, for TestBadDriver.
// The Exec method panics.
type badConn struct{}
diff --git a/src/encoding/base32/base32.go b/src/encoding/base32/base32.go
index 41d343aaac..3dc37b0aa7 100644
--- a/src/encoding/base32/base32.go
+++ b/src/encoding/base32/base32.go
@@ -50,7 +50,8 @@ const encodeStd = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
const encodeHex = "0123456789ABCDEFGHIJKLMNOPQRSTUV"
// NewEncoding returns a new Encoding defined by the given alphabet,
-// which must be a 32-byte string.
+// which must be a 32-byte string. The alphabet is treated as sequence
+// of byte values without any special treatment for multi-byte UTF-8.
func NewEncoding(encoder string) *Encoding {
if len(encoder) != 32 {
panic("encoding alphabet is not 32-bytes long")
@@ -80,6 +81,8 @@ var HexEncoding = NewEncoding(encodeHex)
// The padding character must not be '\r' or '\n', must not
// be contained in the encoding's alphabet and must be a rune equal or
// below '\xff'.
+// Padding characters above '\x7f' are encoded as their exact byte value
+// rather than using the UTF-8 representation of the codepoint.
func (enc Encoding) WithPadding(padding rune) *Encoding {
if padding == '\r' || padding == '\n' || padding > 0xff {
panic("invalid padding")
diff --git a/src/encoding/base64/base64.go b/src/encoding/base64/base64.go
index 0e12d90d29..6aa8a15bdc 100644
--- a/src/encoding/base64/base64.go
+++ b/src/encoding/base64/base64.go
@@ -54,7 +54,8 @@ const encodeURL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz012345678
// NewEncoding returns a new padded Encoding defined by the given alphabet,
// which must be a 64-byte string that does not contain the padding character
-// or CR / LF ('\r', '\n').
+// or CR / LF ('\r', '\n'). The alphabet is treated as sequence of byte values
+// without any special treatment for multi-byte UTF-8.
// The resulting Encoding uses the default padding character ('='),
// which may be changed or disabled via WithPadding.
func NewEncoding(encoder string) *Encoding {
@@ -83,6 +84,8 @@ func NewEncoding(encoder string) *Encoding {
// The padding character must not be '\r' or '\n', must not
// be contained in the encoding's alphabet and must be a rune equal or
// below '\xff'.
+// Padding characters above '\x7f' are encoded as their exact byte value
+// rather than using the UTF-8 representation of the codepoint.
func (enc Encoding) WithPadding(padding rune) *Encoding {
if padding == '\r' || padding == '\n' || padding > 0xff {
panic("invalid padding")
diff --git a/src/encoding/binary/binary.go b/src/encoding/binary/binary.go
index 158e3e9d7f..3fb18a7a03 100644
--- a/src/encoding/binary/binary.go
+++ b/src/encoding/binary/binary.go
@@ -479,7 +479,6 @@ func dataSize(v reflect.Value) int {
if s := sizeof(v.Type().Elem()); s >= 0 {
return s * v.Len()
}
- return -1
case reflect.Struct:
t := v.Type()
@@ -491,8 +490,12 @@ func dataSize(v reflect.Value) int {
return size
default:
- return sizeof(v.Type())
+ if v.IsValid() {
+ return sizeof(v.Type())
+ }
}
+
+ return -1
}
// sizeof returns the size >= 0 of variables for the given type or -1 if the type is not acceptable.
diff --git a/src/encoding/binary/binary_test.go b/src/encoding/binary/binary_test.go
index 4e1fb59f03..4b22b28843 100644
--- a/src/encoding/binary/binary_test.go
+++ b/src/encoding/binary/binary_test.go
@@ -351,6 +351,26 @@ func TestSizeStructCache(t *testing.T) {
}
}
+func TestSizeInvalid(t *testing.T) {
+ testcases := []any{
+ int(0),
+ new(int),
+ (*int)(nil),
+ [1]uint{},
+ new([1]uint),
+ (*[1]uint)(nil),
+ []int{},
+ []int(nil),
+ new([]int),
+ (*[]int)(nil),
+ }
+ for _, tc := range testcases {
+ if got := Size(tc); got != -1 {
+ t.Errorf("Size(%T) = %d, want -1", tc, got)
+ }
+ }
+}
+
// An attempt to read into a struct with an unexported field will
// panic. This is probably not the best choice, but at this point
// anything else would be an API change.
diff --git a/src/go.mod b/src/go.mod
index 5ef63d4e3b..25829e17f2 100644
--- a/src/go.mod
+++ b/src/go.mod
@@ -3,11 +3,11 @@ module std
go 1.21
require (
- golang.org/x/crypto v0.10.0
- golang.org/x/net v0.11.1-0.20230613203745-f5464ddb689c
+ golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d
+ golang.org/x/net v0.12.1-0.20230712162946-57553cbff163
)
require (
- golang.org/x/sys v0.9.0 // indirect
- golang.org/x/text v0.10.1-0.20230613190012-2df65d769a9e // indirect
+ golang.org/x/sys v0.10.0 // indirect
+ golang.org/x/text v0.11.0 // indirect
)
diff --git a/src/go.sum b/src/go.sum
index 93d34efbe8..e474b8be31 100644
--- a/src/go.sum
+++ b/src/go.sum
@@ -1,8 +1,8 @@
-golang.org/x/crypto v0.10.0 h1:LKqV2xt9+kDzSTfOhx4FrkEBcMrAgHSYgzywV9zcGmM=
-golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45I=
-golang.org/x/net v0.11.1-0.20230613203745-f5464ddb689c h1:icjsA5jFPWsTcuIb/yIeU6mgXRHPQBfo0Lzd1GQmKZI=
-golang.org/x/net v0.11.1-0.20230613203745-f5464ddb689c/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
-golang.org/x/sys v0.9.0 h1:KS/R3tvhPqvJvwcKfnBHJwwthS11LRhmM5D59eEXa0s=
-golang.org/x/sys v0.9.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/text v0.10.1-0.20230613190012-2df65d769a9e h1:GTf7SHdimRGQ2uYYuJ0eJUoAEJ9ufU2ocSTVWnbeVQc=
-golang.org/x/text v0.10.1-0.20230613190012-2df65d769a9e/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d h1:LiA25/KWKuXfIq5pMIBq1s5hz3HQxhJJSu/SUGlD+SM=
+golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
+golang.org/x/net v0.12.1-0.20230712162946-57553cbff163 h1:1EDKNuaCsog7zGLEml1qRuO4gt23jORUQX2f0IKZ860=
+golang.org/x/net v0.12.1-0.20230712162946-57553cbff163/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
+golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
+golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
+golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go
index be8ac30f9d..2f335068b8 100644
--- a/src/go/build/deps_test.go
+++ b/src/go/build/deps_test.go
@@ -286,7 +286,7 @@ var depsRules = `
math/big, go/token
< go/constant;
- container/heap, go/constant, go/parser, internal/types/errors
+ container/heap, go/constant, go/parser, internal/goversion, internal/types/errors
< go/types;
# The vast majority of standard library packages should not be resorting to regexp.
diff --git a/src/go/types/builtins.go b/src/go/types/builtins.go
index 837a9b5e14..7795f2552d 100644
--- a/src/go/types/builtins.go
+++ b/src/go/types/builtins.go
@@ -577,6 +577,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
x.mode = value
}
+ // Use the final type computed above for all arguments.
+ for _, a := range args {
+ check.updateExprType(a.expr, x.typ, true)
+ }
+
if check.recordTypes() && x.mode != constant_ {
types := make([]Type, nargs)
for i := range types {
diff --git a/src/go/types/check.go b/src/go/types/check.go
index 5381b5db68..3b0f5e4fdf 100644
--- a/src/go/types/check.go
+++ b/src/go/types/check.go
@@ -12,6 +12,7 @@ import (
"go/ast"
"go/constant"
"go/token"
+ "internal/goversion"
. "internal/types/errors"
)
@@ -233,20 +234,20 @@ func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Ch
info = new(Info)
}
- version, err := parseGoVersion(conf.GoVersion)
- if err != nil {
- panic(fmt.Sprintf("invalid Go version %q (%v)", conf.GoVersion, err))
- }
+ // Note: clients may call NewChecker with the Unsafe package, which is
+ // globally shared and must not be mutated. Therefore NewChecker must not
+ // mutate *pkg.
+ //
+ // (previously, pkg.goVersion was mutated here: go.dev/issue/61212)
return &Checker{
- conf: conf,
- ctxt: conf.Context,
- fset: fset,
- pkg: pkg,
- Info: info,
- version: version,
- objMap: make(map[Object]*declInfo),
- impMap: make(map[importKey]*Package),
+ conf: conf,
+ ctxt: conf.Context,
+ fset: fset,
+ pkg: pkg,
+ Info: info,
+ objMap: make(map[Object]*declInfo),
+ impMap: make(map[importKey]*Package),
}
}
@@ -342,6 +343,20 @@ func (check *Checker) Files(files []*ast.File) error { return check.checkFiles(f
var errBadCgo = errors.New("cannot use FakeImportC and go115UsesCgo together")
func (check *Checker) checkFiles(files []*ast.File) (err error) {
+ if check.pkg == Unsafe {
+ // Defensive handling for Unsafe, which cannot be type checked, and must
+ // not be mutated. See https://go.dev/issue/61212 for an example of where
+ // Unsafe is passed to NewChecker.
+ return nil
+ }
+
+ check.version, err = parseGoVersion(check.conf.GoVersion)
+ if err != nil {
+ return err
+ }
+ if check.version.after(version{1, goversion.Version}) {
+ return fmt.Errorf("package requires newer Go version %v", check.version)
+ }
if check.conf.FakeImportC && check.conf.go115UsesCgo {
return errBadCgo
}
@@ -386,6 +401,7 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) {
check.monomorph()
}
+ check.pkg.goVersion = check.conf.GoVersion
check.pkg.complete = true
// no longer needed - release memory
diff --git a/src/go/types/generate_test.go b/src/go/types/generate_test.go
index 05a848be31..75fda025ee 100644
--- a/src/go/types/generate_test.go
+++ b/src/go/types/generate_test.go
@@ -141,6 +141,7 @@ var filemap = map[string]action{
"universe.go": fixGlobalTypVarDecl,
"util_test.go": fixTokenPos,
"validtype.go": nil,
+ "version_test.go": nil,
}
// TODO(gri) We should be able to make these rewriters more configurable/composable.
diff --git a/src/go/types/index.go b/src/go/types/index.go
index 1bcfb38feb..c1c0f40e87 100644
--- a/src/go/types/index.go
+++ b/src/go/types/index.go
@@ -186,6 +186,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst
if !valid {
// types2 uses the position of '[' for the error
check.errorf(x, NonIndexableOperand, invalidOp+"cannot index %s", x)
+ check.use(e.Indices...)
x.mode = invalid
return false
}
diff --git a/src/go/types/package.go b/src/go/types/package.go
index 7aa62fb7a3..0f52d5f489 100644
--- a/src/go/types/package.go
+++ b/src/go/types/package.go
@@ -12,13 +12,14 @@ import (
// A Package describes a Go package.
type Package struct {
- path string
- name string
- scope *Scope
- imports []*Package
- complete bool
- fake bool // scope lookup errors are silently dropped if package is fake (internal use only)
- cgo bool // uses of this package will be rewritten into uses of declarations from _cgo_gotypes.go
+ path string
+ name string
+ scope *Scope
+ imports []*Package
+ complete bool
+ fake bool // scope lookup errors are silently dropped if package is fake (internal use only)
+ cgo bool // uses of this package will be rewritten into uses of declarations from _cgo_gotypes.go
+ goVersion string // minimum Go version required for package (by Config.GoVersion, typically from go.mod)
}
// NewPackage returns a new Package for the given package path and name.
@@ -37,6 +38,12 @@ func (pkg *Package) Name() string { return pkg.name }
// SetName sets the package name.
func (pkg *Package) SetName(name string) { pkg.name = name }
+// GoVersion returns the minimum Go version required by this package.
+// If the minimum version is unknown, GoVersion returns the empty string.
+// Individual source files may specify a different minimum Go version,
+// as reported in the [go/ast.File.GoVersion] field.
+func (pkg *Package) GoVersion() string { return pkg.goVersion }
+
// Scope returns the (complete or incomplete) package scope
// holding the objects declared at package level (TypeNames,
// Consts, Vars, and Funcs).
diff --git a/src/go/types/sizeof_test.go b/src/go/types/sizeof_test.go
index f17a1781f5..9e5b5f8b20 100644
--- a/src/go/types/sizeof_test.go
+++ b/src/go/types/sizeof_test.go
@@ -46,7 +46,7 @@ func TestSizeof(t *testing.T) {
// Misc
{Scope{}, 44, 88},
- {Package{}, 36, 72},
+ {Package{}, 44, 88},
{_TypeSet{}, 28, 56},
}
for _, test := range tests {
diff --git a/src/go/types/unify.go b/src/go/types/unify.go
index 3ecc80f161..bef851f423 100644
--- a/src/go/types/unify.go
+++ b/src/go/types/unify.go
@@ -126,6 +126,20 @@ const (
exact
)
+func (m unifyMode) String() string {
+ switch m {
+ case 0:
+ return "inexact"
+ case assign:
+ return "assign"
+ case exact:
+ return "exact"
+ case assign | exact:
+ return "assign, exact"
+ }
+ return fmt.Sprintf("mode %d", m)
+}
+
// unify attempts to unify x and y and reports whether it succeeded.
// As a side-effect, types may be inferred for type parameters.
// The mode parameter controls how types are compared.
@@ -258,6 +272,15 @@ func (u *unifier) inferred(tparams []*TypeParam) []Type {
return list
}
+// asInterface returns the underlying type of x as an interface if
+// it is a non-type parameter interface. Otherwise it returns nil.
+func asInterface(x Type) (i *Interface) {
+ if _, ok := x.(*TypeParam); !ok {
+ i, _ = under(x).(*Interface)
+ }
+ return i
+}
+
// nify implements the core unification algorithm which is an
// adapted version of Checker.identical. For changes to that
// code the corresponding changes should be made here.
@@ -265,7 +288,7 @@ func (u *unifier) inferred(tparams []*TypeParam) []Type {
func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
u.depth++
if traceInference {
- u.tracef("%s ≡ %s (mode %d)", x, y, mode)
+ u.tracef("%s ≡ %s\t// %s", x, y, mode)
}
defer func() {
if traceInference && !result {
@@ -296,7 +319,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
// - type parameter recorded with u, make sure one is in x
if _, ok := x.(*Named); ok || u.asTypeParam(y) != nil {
if traceInference {
- u.tracef("%s ≡ %s (swap)", y, x)
+ u.tracef("%s ≡ %s\t// swap", y, x)
}
x, y = y, x
}
@@ -352,11 +375,49 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
if x := u.at(px); x != nil {
// x has an inferred type which must match y
if u.nify(x, y, mode, p) {
- // If we have a match, possibly through underlying types,
- // and y is a defined type, make sure we record that type
+ // We have a match, possibly through underlying types.
+ xi := asInterface(x)
+ yi := asInterface(y)
+ _, xn := x.(*Named)
+ _, yn := y.(*Named)
+ // If we have two interfaces, what to do depends on
+ // whether they are named and their method sets.
+ if xi != nil && yi != nil {
+ // Both types are interfaces.
+ // If both types are defined types, they must be identical
+ // because unification doesn't know which type has the "right" name.
+ if xn && yn {
+ return Identical(x, y)
+ }
+ // In all other cases, the method sets must match.
+ // The types unified so we know that corresponding methods
+ // match and we can simply compare the number of methods.
+ // TODO(gri) We may be able to relax this rule and select
+ // the more general interface. But if one of them is a defined
+ // type, it's not clear how to choose and whether we introduce
+ // an order dependency or not. Requiring the same method set
+ // is conservative.
+ if len(xi.typeSet().methods) != len(yi.typeSet().methods) {
+ return false
+ }
+ } else if xi != nil || yi != nil {
+ // One but not both of them are interfaces.
+ // In this case, either x or y could be viable matches for the corresponding
+ // type parameter, which means choosing either introduces an order dependence.
+ // Therefore, we must fail unification (go.dev/issue/60933).
+ return false
+ }
+ // If y is a defined type, make sure we record that type
// for type parameter x, which may have until now only
// recorded an underlying type (go.dev/issue/43056).
- if _, ok := y.(*Named); ok {
+ // Either both types are interfaces, or neither type is.
+ // If both are interfaces, they have the same methods.
+ //
+ // Note: Changing the recorded type for a type parameter to
+ // a defined type is only ok when unification is inexact.
+ // But in exact unification, if we have a match, x and y must
+ // be identical, so changing the recorded type for x is a no-op.
+ if yn {
u.set(px, y)
}
return true
@@ -386,14 +447,8 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
if enableInterfaceInference && mode&exact == 0 {
// One or both interfaces may be defined types.
// Look under the name, but not under type parameters (go.dev/issue/60564).
- var xi *Interface
- if _, ok := x.(*TypeParam); !ok {
- xi, _ = under(x).(*Interface)
- }
- var yi *Interface
- if _, ok := y.(*TypeParam); !ok {
- yi, _ = under(y).(*Interface)
- }
+ xi := asInterface(x)
+ yi := asInterface(y)
// If we have two interfaces, check the type terms for equivalence,
// and unify common methods if possible.
if xi != nil && yi != nil {
@@ -494,7 +549,7 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) {
// TODO(gri) Factor out type parameter handling from the switch.
if isTypeParam(y) {
if traceInference {
- u.tracef("%s ≡ %s (swap)", y, x)
+ u.tracef("%s ≡ %s\t// swap", y, x)
}
x, y = y, x
}
diff --git a/src/go/types/version.go b/src/go/types/version.go
index 07a42a79ee..108d9b34a0 100644
--- a/src/go/types/version.go
+++ b/src/go/types/version.go
@@ -5,7 +5,6 @@
package types
import (
- "errors"
"fmt"
"go/ast"
"go/token"
@@ -45,23 +44,24 @@ var (
go1_21 = version{1, 21}
)
-var errVersionSyntax = errors.New("invalid Go version syntax")
-
// parseGoVersion parses a Go version string (such as "go1.12")
// and returns the version, or an error. If s is the empty
// string, the version is 0.0.
func parseGoVersion(s string) (v version, err error) {
+ bad := func() (version, error) {
+ return version{}, fmt.Errorf("invalid Go version syntax %q", s)
+ }
if s == "" {
return
}
if !strings.HasPrefix(s, "go") {
- return version{}, errVersionSyntax
+ return bad()
}
s = s[len("go"):]
i := 0
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
if i >= 10 || i == 0 && s[i] == '0' {
- return version{}, errVersionSyntax
+ return bad()
}
v.major = 10*v.major + int(s[i]) - '0'
}
@@ -69,7 +69,7 @@ func parseGoVersion(s string) (v version, err error) {
return
}
if i == 0 || s[i] != '.' {
- return version{}, errVersionSyntax
+ return bad()
}
s = s[i+1:]
if s == "0" {
@@ -82,14 +82,15 @@ func parseGoVersion(s string) (v version, err error) {
i = 0
for ; i < len(s) && '0' <= s[i] && s[i] <= '9'; i++ {
if i >= 10 || i == 0 && s[i] == '0' {
- return version{}, errVersionSyntax
+ return bad()
}
v.minor = 10*v.minor + int(s[i]) - '0'
}
- if i > 0 && i == len(s) {
- return
- }
- return version{}, errVersionSyntax
+ // Accept any suffix after the minor number.
+ // We are only looking for the language version (major.minor)
+ // but want to accept any valid Go version, like go1.21.0
+ // and go1.21rc2.
+ return
}
// langCompat reports an error if the representation of a numeric
diff --git a/src/go/types/version_test.go b/src/go/types/version_test.go
new file mode 100644
index 0000000000..d25f7f5e67
--- /dev/null
+++ b/src/go/types/version_test.go
@@ -0,0 +1,26 @@
+// Code generated by "go test -run=Generate -write=all"; DO NOT EDIT.
+
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types
+
+import "testing"
+
+var parseGoVersionTests = []struct {
+ in string
+ out version
+}{
+ {"go1.21", version{1, 21}},
+ {"go1.21.0", version{1, 21}},
+ {"go1.21rc2", version{1, 21}},
+}
+
+func TestParseGoVersion(t *testing.T) {
+ for _, tt := range parseGoVersionTests {
+ if out, err := parseGoVersion(tt.in); out != tt.out || err != nil {
+ t.Errorf("parseGoVersion(%q) = %v, %v, want %v, nil", tt.in, out, err, tt.out)
+ }
+ }
+}
diff --git a/src/internal/abi/funcpc.go b/src/internal/abi/funcpc.go
index 4db848ee15..e038d36584 100644
--- a/src/internal/abi/funcpc.go
+++ b/src/internal/abi/funcpc.go
@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:build !gccgo
+
package abi
// FuncPC* intrinsics.
diff --git a/src/internal/abi/funcpc_gccgo.go b/src/internal/abi/funcpc_gccgo.go
new file mode 100644
index 0000000000..ad5fa52c54
--- /dev/null
+++ b/src/internal/abi/funcpc_gccgo.go
@@ -0,0 +1,21 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// For bootstrapping with gccgo.
+
+//go:build gccgo
+
+package abi
+
+import "unsafe"
+
+func FuncPCABI0(f interface{}) uintptr {
+ words := (*[2]unsafe.Pointer)(unsafe.Pointer(&f))
+ return *(*uintptr)(unsafe.Pointer(words[1]))
+}
+
+func FuncPCABIInternal(f interface{}) uintptr {
+ words := (*[2]unsafe.Pointer)(unsafe.Pointer(&f))
+ return *(*uintptr)(unsafe.Pointer(words[1]))
+}
diff --git a/src/internal/bytealg/equal_riscv64.s b/src/internal/bytealg/equal_riscv64.s
index 3834083ec9..503aac5751 100644
--- a/src/internal/bytealg/equal_riscv64.s
+++ b/src/internal/bytealg/equal_riscv64.s
@@ -37,6 +37,8 @@ TEXT memequal<>(SB),NOSPLIT|NOFRAME,$0
BEQZ X9, loop32_check
// Check one byte at a time until we reach 8 byte alignment.
+ SUB X9, X0, X9
+ ADD $8, X9, X9
SUB X9, X12, X12
align:
ADD $-1, X9
diff --git a/src/internal/fuzz/counters_unsupported.go b/src/internal/fuzz/counters_unsupported.go
index 028065ce30..287bb4bd3c 100644
--- a/src/internal/fuzz/counters_unsupported.go
+++ b/src/internal/fuzz/counters_unsupported.go
@@ -6,7 +6,7 @@
// the instrumentation is OS specific, but only amd64 and arm64 are
// supported in the runtime. See src/runtime/libfuzzer*.
//
-// If you update this constraint, also update internal/platform.FuzzInstrumeted.
+// If you update this constraint, also update internal/platform.FuzzInstrumented.
//
//go:build !((darwin || linux || windows || freebsd) && (amd64 || arm64))
diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go
index 0fdd146b24..243f9efce1 100644
--- a/src/internal/godebugs/table.go
+++ b/src/internal/godebugs/table.go
@@ -37,6 +37,7 @@ var All = []Info{
//{Name: "multipartfiles", Package: "mime/multipart"},
{Name: "multipartmaxheaders", Package: "mime/multipart"},
{Name: "multipartmaxparts", Package: "mime/multipart"},
+ {Name: "multipathtcp", Package: "net"},
{Name: "netdns", Package: "net", Opaque: true},
{Name: "panicnil", Package: "runtime", Changed: 21, Old: "1"},
{Name: "randautoseed", Package: "math/rand"},
diff --git a/src/internal/platform/supported.go b/src/internal/platform/supported.go
index e762bb304e..230a952d2d 100644
--- a/src/internal/platform/supported.go
+++ b/src/internal/platform/supported.go
@@ -2,8 +2,19 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:generate go test . -run=TestGenerated -fix
+
package platform
+// An OSArch is a pair of GOOS and GOARCH values indicating a platform.
+type OSArch struct {
+ GOOS, GOARCH string
+}
+
+func (p OSArch) String() string {
+ return p.GOOS + "/" + p.GOARCH
+}
+
// RaceDetectorSupported reports whether goos/goarch supports the race
// detector. There is a copy of this function in cmd/dist/test.go.
// Race detector only supports 48-bit VMA on arm64. But it will always
@@ -123,11 +134,11 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool {
return true
}
- platform := goos + "/" + goarch
- if _, ok := osArchSupportsCgo[platform]; !ok {
+ if _, ok := distInfo[OSArch{goos, goarch}]; !ok {
return false // platform unrecognized
}
+ platform := goos + "/" + goarch
switch buildmode {
case "archive":
return true
@@ -239,11 +250,6 @@ func DefaultPIE(goos, goarch string, isRace bool) bool {
return false
}
-// CgoSupported reports whether goos/goarch supports cgo.
-func CgoSupported(goos, goarch string) bool {
- return osArchSupportsCgo[goos+"/"+goarch]
-}
-
// ExecutableHasDWARF reports whether the linked executable includes DWARF
// symbols on goos/goarch.
func ExecutableHasDWARF(goos, goarch string) bool {
@@ -253,3 +259,28 @@ func ExecutableHasDWARF(goos, goarch string) bool {
}
return true
}
+
+// osArchInfo describes information about an OSArch extracted from cmd/dist and
+// stored in the generated distInfo map.
+type osArchInfo struct {
+ CgoSupported bool
+ FirstClass bool
+ Broken bool
+}
+
+// CgoSupported reports whether goos/goarch supports cgo.
+func CgoSupported(goos, goarch string) bool {
+ return distInfo[OSArch{goos, goarch}].CgoSupported
+}
+
+// FirstClass reports whether goos/goarch is considered a “first class” port.
+// (See https://go.dev/wiki/PortingPolicy#first-class-ports.)
+func FirstClass(goos, goarch string) bool {
+ return distInfo[OSArch{goos, goarch}].FirstClass
+}
+
+// Broken reportsr whether goos/goarch is considered a broken port.
+// (See https://go.dev/wiki/PortingPolicy#broken-ports.)
+func Broken(goos, goarch string) bool {
+ return distInfo[OSArch{goos, goarch}].Broken
+}
diff --git a/src/internal/platform/zosarch.go b/src/internal/platform/zosarch.go
new file mode 100644
index 0000000000..7f5a290332
--- /dev/null
+++ b/src/internal/platform/zosarch.go
@@ -0,0 +1,114 @@
+// Code generated by go test internal/platform -fix. DO NOT EDIT.
+
+// To change the information in this file, edit the cgoEnabled and/or firstClass
+// maps in cmd/dist/build.go, then run 'go generate internal/platform'.
+
+package platform
+
+// List is the list of all valid GOOS/GOARCH combinations,
+// including known-broken ports.
+var List = []OSArch{
+ {"aix", "ppc64"},
+ {"android", "386"},
+ {"android", "amd64"},
+ {"android", "arm"},
+ {"android", "arm64"},
+ {"darwin", "amd64"},
+ {"darwin", "arm64"},
+ {"dragonfly", "amd64"},
+ {"freebsd", "386"},
+ {"freebsd", "amd64"},
+ {"freebsd", "arm"},
+ {"freebsd", "arm64"},
+ {"freebsd", "riscv64"},
+ {"illumos", "amd64"},
+ {"ios", "amd64"},
+ {"ios", "arm64"},
+ {"js", "wasm"},
+ {"linux", "386"},
+ {"linux", "amd64"},
+ {"linux", "arm"},
+ {"linux", "arm64"},
+ {"linux", "loong64"},
+ {"linux", "mips"},
+ {"linux", "mips64"},
+ {"linux", "mips64le"},
+ {"linux", "mipsle"},
+ {"linux", "ppc64"},
+ {"linux", "ppc64le"},
+ {"linux", "riscv64"},
+ {"linux", "s390x"},
+ {"linux", "sparc64"},
+ {"netbsd", "386"},
+ {"netbsd", "amd64"},
+ {"netbsd", "arm"},
+ {"netbsd", "arm64"},
+ {"openbsd", "386"},
+ {"openbsd", "amd64"},
+ {"openbsd", "arm"},
+ {"openbsd", "arm64"},
+ {"openbsd", "mips64"},
+ {"openbsd", "ppc64"},
+ {"plan9", "386"},
+ {"plan9", "amd64"},
+ {"plan9", "arm"},
+ {"solaris", "amd64"},
+ {"wasip1", "wasm"},
+ {"windows", "386"},
+ {"windows", "amd64"},
+ {"windows", "arm"},
+ {"windows", "arm64"},
+}
+
+var distInfo = map[OSArch]osArchInfo{
+ {"aix", "ppc64"}: {CgoSupported: true},
+ {"android", "386"}: {CgoSupported: true},
+ {"android", "amd64"}: {CgoSupported: true},
+ {"android", "arm"}: {CgoSupported: true},
+ {"android", "arm64"}: {CgoSupported: true},
+ {"darwin", "amd64"}: {CgoSupported: true, FirstClass: true},
+ {"darwin", "arm64"}: {CgoSupported: true, FirstClass: true},
+ {"dragonfly", "amd64"}: {CgoSupported: true},
+ {"freebsd", "386"}: {CgoSupported: true},
+ {"freebsd", "amd64"}: {CgoSupported: true},
+ {"freebsd", "arm"}: {CgoSupported: true},
+ {"freebsd", "arm64"}: {CgoSupported: true},
+ {"freebsd", "riscv64"}: {CgoSupported: true},
+ {"illumos", "amd64"}: {CgoSupported: true},
+ {"ios", "amd64"}: {CgoSupported: true},
+ {"ios", "arm64"}: {CgoSupported: true},
+ {"js", "wasm"}: {},
+ {"linux", "386"}: {CgoSupported: true, FirstClass: true},
+ {"linux", "amd64"}: {CgoSupported: true, FirstClass: true},
+ {"linux", "arm"}: {CgoSupported: true, FirstClass: true},
+ {"linux", "arm64"}: {CgoSupported: true, FirstClass: true},
+ {"linux", "loong64"}: {CgoSupported: true},
+ {"linux", "mips"}: {CgoSupported: true},
+ {"linux", "mips64"}: {CgoSupported: true},
+ {"linux", "mips64le"}: {CgoSupported: true},
+ {"linux", "mipsle"}: {CgoSupported: true},
+ {"linux", "ppc64"}: {},
+ {"linux", "ppc64le"}: {CgoSupported: true},
+ {"linux", "riscv64"}: {CgoSupported: true},
+ {"linux", "s390x"}: {CgoSupported: true},
+ {"linux", "sparc64"}: {CgoSupported: true, Broken: true},
+ {"netbsd", "386"}: {CgoSupported: true},
+ {"netbsd", "amd64"}: {CgoSupported: true},
+ {"netbsd", "arm"}: {CgoSupported: true},
+ {"netbsd", "arm64"}: {CgoSupported: true},
+ {"openbsd", "386"}: {CgoSupported: true},
+ {"openbsd", "amd64"}: {CgoSupported: true},
+ {"openbsd", "arm"}: {CgoSupported: true},
+ {"openbsd", "arm64"}: {CgoSupported: true},
+ {"openbsd", "mips64"}: {CgoSupported: true, Broken: true},
+ {"openbsd", "ppc64"}: {Broken: true},
+ {"plan9", "386"}: {},
+ {"plan9", "amd64"}: {},
+ {"plan9", "arm"}: {},
+ {"solaris", "amd64"}: {CgoSupported: true},
+ {"wasip1", "wasm"}: {},
+ {"windows", "386"}: {CgoSupported: true, FirstClass: true},
+ {"windows", "amd64"}: {CgoSupported: true, FirstClass: true},
+ {"windows", "arm"}: {},
+ {"windows", "arm64"}: {CgoSupported: true},
+}
diff --git a/src/internal/platform/zosarch_test.go b/src/internal/platform/zosarch_test.go
new file mode 100644
index 0000000000..e8ffe9e75d
--- /dev/null
+++ b/src/internal/platform/zosarch_test.go
@@ -0,0 +1,109 @@
+// 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 platform_test
+
+import (
+ "bytes"
+ "encoding/json"
+ "flag"
+ "internal/diff"
+ "internal/testenv"
+ "os"
+ "os/exec"
+ "testing"
+ "text/template"
+)
+
+var flagFix = flag.Bool("fix", false, "if true, fix out-of-date generated files")
+
+// TestGenerated verifies that zosarch.go is up to date,
+// or regenerates it if the -fix flag is set.
+func TestGenerated(t *testing.T) {
+ testenv.MustHaveGoRun(t)
+
+ // Here we use 'go run cmd/dist' instead of 'go tool dist' in case the
+ // installed cmd/dist is stale or missing. We don't want to miss a
+ // skew in the data due to a stale binary.
+ cmd := testenv.Command(t, "go", "run", "cmd/dist", "list", "-json", "-broken")
+
+ // cmd/dist requires GOROOT to be set explicitly in the environment.
+ cmd.Env = append(cmd.Environ(), "GOROOT="+testenv.GOROOT(t))
+
+ out, err := cmd.Output()
+ if err != nil {
+ if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
+ t.Logf("stderr:\n%s", ee.Stderr)
+ }
+ t.Fatalf("%v: %v", cmd, err)
+ }
+
+ type listEntry struct {
+ GOOS, GOARCH string
+ CgoSupported bool
+ FirstClass bool
+ Broken bool
+ }
+ var entries []listEntry
+ if err := json.Unmarshal(out, &entries); err != nil {
+ t.Fatal(err)
+ }
+
+ tmplOut := new(bytes.Buffer)
+ tmpl := template.Must(template.New("zosarch").Parse(zosarchTmpl))
+ err = tmpl.Execute(tmplOut, entries)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ cmd = testenv.Command(t, "gofmt")
+ cmd.Stdin = bytes.NewReader(tmplOut.Bytes())
+ want, err := cmd.Output()
+ if err != nil {
+ t.Logf("stdin:\n%s", tmplOut.Bytes())
+ if ee, ok := err.(*exec.ExitError); ok && len(ee.Stderr) > 0 {
+ t.Logf("stderr:\n%s", ee.Stderr)
+ }
+ t.Fatalf("%v: %v", cmd, err)
+ }
+
+ got, err := os.ReadFile("zosarch.go")
+ if err == nil && bytes.Equal(got, want) {
+ return
+ }
+
+ if !*flagFix {
+ if err != nil {
+ t.Log(err)
+ } else {
+ t.Logf("diff:\n%s", diff.Diff("zosarch.go", got, "want", want))
+ }
+ t.Fatalf("zosarch.go is missing or out of date; to regenerate, run\ngo generate internal/platform")
+ }
+
+ if err := os.WriteFile("zosarch.go", want, 0666); err != nil {
+ t.Fatal(err)
+ }
+}
+
+const zosarchTmpl = `// Code generated by go test internal/platform -fix. DO NOT EDIT.
+
+// To change the information in this file, edit the cgoEnabled and/or firstClass
+// maps in cmd/dist/build.go, then run 'go generate internal/platform'.
+
+package platform
+
+// List is the list of all valid GOOS/GOARCH combinations,
+// including known-broken ports.
+var List = []OSArch{
+{{range .}} { {{ printf "%q" .GOOS }}, {{ printf "%q" .GOARCH }} },
+{{end}}
+}
+
+var distInfo = map[OSArch]osArchInfo {
+{{range .}} { {{ printf "%q" .GOOS }}, {{ printf "%q" .GOARCH }} }:
+{ {{if .CgoSupported}}CgoSupported: true, {{end}}{{if .FirstClass}}FirstClass: true, {{end}}{{if .Broken}} Broken: true, {{end}} },
+{{end}}
+}
+`
diff --git a/src/internal/types/testdata/fixedbugs/issue60906.go b/src/internal/types/testdata/fixedbugs/issue60906.go
new file mode 100644
index 0000000000..2744e89455
--- /dev/null
+++ b/src/internal/types/testdata/fixedbugs/issue60906.go
@@ -0,0 +1,11 @@
+// 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 p
+
+func _() {
+ var x int
+ var f func() []int
+ _ = f /* ERROR "cannot index f" */ [x]
+}
diff --git a/src/internal/types/testdata/fixedbugs/issue60933.go b/src/internal/types/testdata/fixedbugs/issue60933.go
new file mode 100644
index 0000000000..9b10237e5d
--- /dev/null
+++ b/src/internal/types/testdata/fixedbugs/issue60933.go
@@ -0,0 +1,67 @@
+// 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 p
+
+import (
+ "io"
+ "os"
+)
+
+func g[T any](...T) {}
+
+// Interface and non-interface types do not match.
+func _() {
+ var file *os.File
+ g(file, io /* ERROR "type io.Writer of io.Discard does not match inferred type *os.File for T" */ .Discard)
+ g(file, os.Stdout)
+}
+
+func _() {
+ var a *os.File
+ var b any
+ g(a, a)
+ g(a, b /* ERROR "type any of b does not match inferred type *os.File for T" */)
+}
+
+var writer interface {
+ Write(p []byte) (n int, err error)
+}
+
+func _() {
+ var file *os.File
+ g(file, writer /* ERROR "type interface{Write(p []byte) (n int, err error)} of writer does not match inferred type *os.File for T" */)
+ g(writer, file /* ERROR "type *os.File of file does not match inferred type interface{Write(p []byte) (n int, err error)} for T" */)
+}
+
+// Different named interface types do not match.
+func _() {
+ g(io.ReadWriter(nil), io.ReadWriter(nil))
+ g(io.ReadWriter(nil), io /* ERROR "does not match" */ .Writer(nil))
+ g(io.Writer(nil), io /* ERROR "does not match" */ .ReadWriter(nil))
+}
+
+// Named and unnamed interface types match if they have the same methods.
+func _() {
+ g(io.Writer(nil), writer)
+ g(io.ReadWriter(nil), writer /* ERROR "does not match" */ )
+}
+
+// There must be no order dependency for named and unnamed interfaces.
+func f[T interface{ m(T) }](a, b T) {}
+
+type F interface {
+ m(F)
+}
+
+func _() {
+ var i F
+ var j interface {
+ m(F)
+ }
+
+ // order doesn't matter
+ f(i, j)
+ f(j, i)
+} \ No newline at end of file
diff --git a/src/internal/types/testdata/fixedbugs/issue60946.go b/src/internal/types/testdata/fixedbugs/issue60946.go
new file mode 100644
index 0000000000..a66254b6d0
--- /dev/null
+++ b/src/internal/types/testdata/fixedbugs/issue60946.go
@@ -0,0 +1,38 @@
+// 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 p
+
+type Tn interface{ m() }
+type T1 struct{}
+type T2 struct{}
+
+func (*T1) m() {}
+func (*T2) m() {}
+
+func g[P any](...P) {}
+
+func _() {
+ var t interface{ m() }
+ var tn Tn
+ var t1 *T1
+ var t2 *T2
+
+ // these are ok (interface types only)
+ g(t, t)
+ g(t, tn)
+ g(tn, t)
+ g(tn, tn)
+
+ // these are not ok (interface and non-interface types)
+ g(t, t1 /* ERROR "does not match" */)
+ g(t1, t /* ERROR "does not match" */)
+ g(tn, t1 /* ERROR "does not match" */)
+ g(t1, tn /* ERROR "does not match" */)
+
+ g(t, t1 /* ERROR "does not match" */, t2)
+ g(t1, t2 /* ERROR "does not match" */, t)
+ g(tn, t1 /* ERROR "does not match" */, t2)
+ g(t1, t2 /* ERROR "does not match" */, tn)
+}
diff --git a/src/log/slog/attr.go b/src/log/slog/attr.go
index a180d0e1d3..90e343b319 100644
--- a/src/log/slog/attr.go
+++ b/src/log/slog/attr.go
@@ -81,7 +81,7 @@ func argsToAttrSlice(args []any) []Attr {
}
// Any returns an Attr for the supplied value.
-// See [Value.AnyValue] for how values are treated.
+// See [AnyValue] for how values are treated.
func Any(key string, value any) Attr {
return Attr{key, AnyValue(value)}
}
diff --git a/src/log/slog/doc.go b/src/log/slog/doc.go
index 8237b4e3d5..088df61c6d 100644
--- a/src/log/slog/doc.go
+++ b/src/log/slog/doc.go
@@ -174,9 +174,9 @@ argument, as do their corresponding top-level functions.
Although the convenience methods on Logger (Info and so on) and the
corresponding top-level functions do not take a context, the alternatives ending
-in "Ctx" do. For example,
+in "Context" do. For example,
- slog.InfoCtx(ctx, "message")
+ slog.InfoContext(ctx, "message")
It is recommended to pass a context to an output method if one is available.
@@ -206,7 +206,7 @@ keys and values; this allows it, too, to avoid allocation.
The call
- logger.LogAttrs(nil, slog.LevelInfo, "hello", slog.Int("count", 3))
+ logger.LogAttrs(ctx, slog.LevelInfo, "hello", slog.Int("count", 3))
is the most efficient way to achieve the same output as
@@ -255,7 +255,7 @@ and hidden fields that refer to state (such as attributes) indirectly. This
means that modifying a simple copy of a Record (e.g. by calling
[Record.Add] or [Record.AddAttrs] to add attributes)
may have unexpected effects on the original.
-Before modifying a Record, use [Clone] to
+Before modifying a Record, use [Record.Clone] to
create a copy that shares no state with the original,
or create a new Record with [NewRecord]
and build up its Attrs by traversing the old ones with [Record.Attrs].
diff --git a/src/log/slog/example_custom_levels_test.go b/src/log/slog/example_custom_levels_test.go
index 2f230320bc..7351ca493b 100644
--- a/src/log/slog/example_custom_levels_test.go
+++ b/src/log/slog/example_custom_levels_test.go
@@ -5,6 +5,7 @@
package slog_test
import (
+ "context"
"log/slog"
"os"
)
@@ -72,13 +73,14 @@ func ExampleHandlerOptions_customLevels() {
})
logger := slog.New(th)
- logger.Log(nil, LevelEmergency, "missing pilots")
+ ctx := context.Background()
+ logger.Log(ctx, LevelEmergency, "missing pilots")
logger.Error("failed to start engines", "err", "missing fuel")
logger.Warn("falling back to default value")
- logger.Log(nil, LevelNotice, "all systems are running")
+ logger.Log(ctx, LevelNotice, "all systems are running")
logger.Info("initiating launch")
logger.Debug("starting background job")
- logger.Log(nil, LevelTrace, "button clicked")
+ logger.Log(ctx, LevelTrace, "button clicked")
// Output:
// sev=EMERGENCY msg="missing pilots"
diff --git a/src/log/slog/handler.go b/src/log/slog/handler.go
index 8cd1e563eb..e479ca8a4c 100644
--- a/src/log/slog/handler.go
+++ b/src/log/slog/handler.go
@@ -140,7 +140,7 @@ type HandlerOptions struct {
// ReplaceAttr is called to rewrite each non-group attribute before it is logged.
// The attribute's value has been resolved (see [Value.Resolve]).
- // If ReplaceAttr returns an Attr with Key == "", the attribute is discarded.
+ // If ReplaceAttr returns a zero Attr, the attribute is discarded.
//
// The built-in attributes with keys "time", "level", "source", and "msg"
// are passed to this function, except that time is omitted
@@ -221,6 +221,11 @@ func (h *commonHandler) enabled(l Level) bool {
}
func (h *commonHandler) withAttrs(as []Attr) *commonHandler {
+ // We are going to ignore empty groups, so if the entire slice consists of
+ // them, there is nothing to do.
+ if countEmptyGroups(as) == len(as) {
+ return h
+ }
h2 := h.clone()
// Pre-format the attributes as an optimization.
state := h2.newHandleState((*buffer.Buffer)(&h2.preformattedAttrs), false, "")
@@ -308,15 +313,20 @@ func (s *handleState) appendNonBuiltIns(r Record) {
}
// Attrs in Record -- unlike the built-in ones, they are in groups started
// from WithGroup.
- s.prefix.WriteString(s.h.groupPrefix)
- s.openGroups()
- r.Attrs(func(a Attr) bool {
- s.appendAttr(a)
- return true
- })
+ // If the record has no Attrs, don't output any groups.
+ nOpenGroups := s.h.nOpenGroups
+ if r.NumAttrs() > 0 {
+ s.prefix.WriteString(s.h.groupPrefix)
+ s.openGroups()
+ nOpenGroups = len(s.h.groups)
+ r.Attrs(func(a Attr) bool {
+ s.appendAttr(a)
+ return true
+ })
+ }
if s.h.json {
// Close all open groups.
- for range s.h.groups {
+ for range s.h.groups[:nOpenGroups] {
s.buf.WriteByte('}')
}
// Close the top-level object.
diff --git a/src/log/slog/handler_test.go b/src/log/slog/handler_test.go
index 741e86a826..3fb7360fc2 100644
--- a/src/log/slog/handler_test.go
+++ b/src/log/slog/handler_test.go
@@ -108,8 +108,6 @@ func TestDefaultHandle(t *testing.T) {
// Verify the common parts of TextHandler and JSONHandler.
func TestJSONAndTextHandlers(t *testing.T) {
- ctx := context.Background()
-
// remove all Attrs
removeAll := func(_ []string, a Attr) Attr { return Attr{} }
@@ -215,6 +213,28 @@ func TestJSONAndTextHandlers(t *testing.T) {
wantJSON: `{"msg":"message","h":{"a":1}}`,
},
{
+ name: "nested empty group",
+ replace: removeKeys(TimeKey, LevelKey),
+ attrs: []Attr{
+ Group("g",
+ Group("h",
+ Group("i"), Group("j"))),
+ },
+ wantText: `msg=message`,
+ wantJSON: `{"msg":"message"}`,
+ },
+ {
+ name: "nested non-empty group",
+ replace: removeKeys(TimeKey, LevelKey),
+ attrs: []Attr{
+ Group("g",
+ Group("h",
+ Group("i"), Group("j", Int("a", 1)))),
+ },
+ wantText: `msg=message g.h.j.a=1`,
+ wantJSON: `{"msg":"message","g":{"h":{"j":{"a":1}}}}`,
+ },
+ {
name: "escapes",
replace: removeKeys(TimeKey, LevelKey),
attrs: []Attr{
@@ -282,6 +302,34 @@ func TestJSONAndTextHandlers(t *testing.T) {
wantJSON: `{"msg":"message","p1":1,"s1":{"s2":{"a":"one","b":2}}}`,
},
{
+ name: "empty with-groups",
+ replace: removeKeys(TimeKey, LevelKey),
+ with: func(h Handler) Handler {
+ return h.WithGroup("x").WithGroup("y")
+ },
+ wantText: "msg=message",
+ wantJSON: `{"msg":"message"}`,
+ },
+ {
+ name: "empty with-groups, no non-empty attrs",
+ replace: removeKeys(TimeKey, LevelKey),
+ with: func(h Handler) Handler {
+ return h.WithGroup("x").WithAttrs([]Attr{Group("g")}).WithGroup("y")
+ },
+ wantText: "msg=message",
+ wantJSON: `{"msg":"message"}`,
+ },
+ {
+ name: "one empty with-group",
+ replace: removeKeys(TimeKey, LevelKey),
+ with: func(h Handler) Handler {
+ return h.WithGroup("x").WithAttrs([]Attr{Int("a", 1)}).WithGroup("y")
+ },
+ attrs: []Attr{Group("g", Group("h"))},
+ wantText: "msg=message x.a=1",
+ wantJSON: `{"msg":"message","x":{"a":1}}`,
+ },
+ {
name: "GroupValue as Attr value",
replace: removeKeys(TimeKey, LevelKey),
attrs: []Attr{{"v", AnyValue(IntValue(3))}},
@@ -362,7 +410,7 @@ func TestJSONAndTextHandlers(t *testing.T) {
h = test.with(h)
}
buf.Reset()
- if err := h.Handle(ctx, r); err != nil {
+ if err := h.Handle(nil, r); err != nil {
t.Fatal(err)
}
want := strings.ReplaceAll(handler.want, "$LINE", line)
diff --git a/src/log/slog/json_handler_test.go b/src/log/slog/json_handler_test.go
index dcfd701dd4..65130f2426 100644
--- a/src/log/slog/json_handler_test.go
+++ b/src/log/slog/json_handler_test.go
@@ -174,6 +174,7 @@ func BenchmarkJSONHandler(b *testing.B) {
}},
} {
b.Run(bench.name, func(b *testing.B) {
+ ctx := context.Background()
l := New(NewJSONHandler(io.Discard, &bench.opts)).With(
String("program", "my-test-program"),
String("package", "log/slog"),
@@ -182,7 +183,7 @@ func BenchmarkJSONHandler(b *testing.B) {
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
- l.LogAttrs(nil, LevelInfo, "this is a typical log message",
+ l.LogAttrs(ctx, LevelInfo, "this is a typical log message",
String("module", "github.com/google/go-cmp"),
String("version", "v1.23.4"),
Int("count", 23),
@@ -238,12 +239,13 @@ func BenchmarkPreformatting(b *testing.B) {
{"struct", io.Discard, structAttrs},
{"struct file", outFile, structAttrs},
} {
+ ctx := context.Background()
b.Run(bench.name, func(b *testing.B) {
l := New(NewJSONHandler(bench.wc, nil)).With(bench.attrs...)
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
- l.LogAttrs(nil, LevelInfo, "this is a typical log message",
+ l.LogAttrs(ctx, LevelInfo, "this is a typical log message",
String("module", "github.com/google/go-cmp"),
String("version", "v1.23.4"),
Int("count", 23),
diff --git a/src/log/slog/logger.go b/src/log/slog/logger.go
index 2bad5dfccc..a068085f47 100644
--- a/src/log/slog/logger.go
+++ b/src/log/slog/logger.go
@@ -165,41 +165,41 @@ func (l *Logger) LogAttrs(ctx context.Context, level Level, msg string, attrs ..
// Debug logs at LevelDebug.
func (l *Logger) Debug(msg string, args ...any) {
- l.log(nil, LevelDebug, msg, args...)
+ l.log(context.Background(), LevelDebug, msg, args...)
}
-// DebugCtx logs at LevelDebug with the given context.
-func (l *Logger) DebugCtx(ctx context.Context, msg string, args ...any) {
+// DebugContext logs at LevelDebug with the given context.
+func (l *Logger) DebugContext(ctx context.Context, msg string, args ...any) {
l.log(ctx, LevelDebug, msg, args...)
}
// Info logs at LevelInfo.
func (l *Logger) Info(msg string, args ...any) {
- l.log(nil, LevelInfo, msg, args...)
+ l.log(context.Background(), LevelInfo, msg, args...)
}
-// InfoCtx logs at LevelInfo with the given context.
-func (l *Logger) InfoCtx(ctx context.Context, msg string, args ...any) {
+// InfoContext logs at LevelInfo with the given context.
+func (l *Logger) InfoContext(ctx context.Context, msg string, args ...any) {
l.log(ctx, LevelInfo, msg, args...)
}
// Warn logs at LevelWarn.
func (l *Logger) Warn(msg string, args ...any) {
- l.log(nil, LevelWarn, msg, args...)
+ l.log(context.Background(), LevelWarn, msg, args...)
}
-// WarnCtx logs at LevelWarn with the given context.
-func (l *Logger) WarnCtx(ctx context.Context, msg string, args ...any) {
+// WarnContext logs at LevelWarn with the given context.
+func (l *Logger) WarnContext(ctx context.Context, msg string, args ...any) {
l.log(ctx, LevelWarn, msg, args...)
}
// Error logs at LevelError.
func (l *Logger) Error(msg string, args ...any) {
- l.log(nil, LevelError, msg, args...)
+ l.log(context.Background(), LevelError, msg, args...)
}
-// ErrorCtx logs at LevelError with the given context.
-func (l *Logger) ErrorCtx(ctx context.Context, msg string, args ...any) {
+// ErrorContext logs at LevelError with the given context.
+func (l *Logger) ErrorContext(ctx context.Context, msg string, args ...any) {
l.log(ctx, LevelError, msg, args...)
}
@@ -247,41 +247,41 @@ func (l *Logger) logAttrs(ctx context.Context, level Level, msg string, attrs ..
// Debug calls Logger.Debug on the default logger.
func Debug(msg string, args ...any) {
- Default().log(nil, LevelDebug, msg, args...)
+ Default().log(context.Background(), LevelDebug, msg, args...)
}
-// DebugCtx calls Logger.DebugCtx on the default logger.
-func DebugCtx(ctx context.Context, msg string, args ...any) {
+// DebugContext calls Logger.DebugContext on the default logger.
+func DebugContext(ctx context.Context, msg string, args ...any) {
Default().log(ctx, LevelDebug, msg, args...)
}
// Info calls Logger.Info on the default logger.
func Info(msg string, args ...any) {
- Default().log(nil, LevelInfo, msg, args...)
+ Default().log(context.Background(), LevelInfo, msg, args...)
}
-// InfoCtx calls Logger.InfoCtx on the default logger.
-func InfoCtx(ctx context.Context, msg string, args ...any) {
+// InfoContext calls Logger.InfoContext on the default logger.
+func InfoContext(ctx context.Context, msg string, args ...any) {
Default().log(ctx, LevelInfo, msg, args...)
}
// Warn calls Logger.Warn on the default logger.
func Warn(msg string, args ...any) {
- Default().log(nil, LevelWarn, msg, args...)
+ Default().log(context.Background(), LevelWarn, msg, args...)
}
-// WarnCtx calls Logger.WarnCtx on the default logger.
-func WarnCtx(ctx context.Context, msg string, args ...any) {
+// WarnContext calls Logger.WarnContext on the default logger.
+func WarnContext(ctx context.Context, msg string, args ...any) {
Default().log(ctx, LevelWarn, msg, args...)
}
// Error calls Logger.Error on the default logger.
func Error(msg string, args ...any) {
- Default().log(nil, LevelError, msg, args...)
+ Default().log(context.Background(), LevelError, msg, args...)
}
-// ErrorCtx calls Logger.ErrorCtx on the default logger.
-func ErrorCtx(ctx context.Context, msg string, args ...any) {
+// ErrorContext calls Logger.ErrorContext on the default logger.
+func ErrorContext(ctx context.Context, msg string, args ...any) {
Default().log(ctx, LevelError, msg, args...)
}
diff --git a/src/log/slog/logger_test.go b/src/log/slog/logger_test.go
index d151c0490c..2f5b31939c 100644
--- a/src/log/slog/logger_test.go
+++ b/src/log/slog/logger_test.go
@@ -25,6 +25,7 @@ import (
const timeRE = `\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}(Z|[+-]\d{2}:\d{2})`
func TestLogTextHandler(t *testing.T) {
+ ctx := context.Background()
var buf bytes.Buffer
l := New(NewTextHandler(&buf, nil))
@@ -51,10 +52,10 @@ func TestLogTextHandler(t *testing.T) {
l.Error("bad", "a", 1)
check(`level=ERROR msg=bad a=1`)
- l.Log(nil, LevelWarn+1, "w", Int("a", 1), String("b", "two"))
+ l.Log(ctx, LevelWarn+1, "w", Int("a", 1), String("b", "two"))
check(`level=WARN\+1 msg=w a=1 b=two`)
- l.LogAttrs(nil, LevelInfo+1, "a b c", Int("a", 1), String("b", "two"))
+ l.LogAttrs(ctx, LevelInfo+1, "a b c", Int("a", 1), String("b", "two"))
check(`level=INFO\+1 msg="a b c" a=1 b=two`)
l.Info("info", "a", []Attr{Int("i", 1)})
@@ -106,7 +107,7 @@ func TestConnections(t *testing.T) {
// log.Logger's output goes through the handler.
SetDefault(New(NewTextHandler(&slogbuf, &HandlerOptions{AddSource: true})))
log.Print("msg2")
- checkLogOutput(t, slogbuf.String(), "time="+timeRE+` level=INFO source=.*logger_test.go:\d{3} msg=msg2`)
+ checkLogOutput(t, slogbuf.String(), "time="+timeRE+` level=INFO source=.*logger_test.go:\d{3}"? msg=msg2`)
// The default log.Logger always outputs at Info level.
slogbuf.Reset()
@@ -156,6 +157,7 @@ func TestAttrs(t *testing.T) {
}
func TestCallDepth(t *testing.T) {
+ ctx := context.Background()
h := &captureHandler{}
var startLine int
@@ -181,9 +183,9 @@ func TestCallDepth(t *testing.T) {
startLine = f.Line + 4
// Do not change the number of lines between here and the call to check(0).
- logger.Log(nil, LevelInfo, "")
+ logger.Log(ctx, LevelInfo, "")
check(0)
- logger.LogAttrs(nil, LevelInfo, "")
+ logger.LogAttrs(ctx, LevelInfo, "")
check(1)
logger.Debug("")
check(2)
@@ -201,13 +203,14 @@ func TestCallDepth(t *testing.T) {
check(8)
Error("")
check(9)
- Log(nil, LevelInfo, "")
+ Log(ctx, LevelInfo, "")
check(10)
- LogAttrs(nil, LevelInfo, "")
+ LogAttrs(ctx, LevelInfo, "")
check(11)
}
func TestAlloc(t *testing.T) {
+ ctx := context.Background()
dl := New(discardHandler{})
defer SetDefault(Default()) // restore
SetDefault(dl)
@@ -222,7 +225,7 @@ func TestAlloc(t *testing.T) {
wantAllocs(t, 0, func() { dl.Info("hello") })
})
t.Run("logger.Log", func(t *testing.T) {
- wantAllocs(t, 0, func() { dl.Log(nil, LevelDebug, "hello") })
+ wantAllocs(t, 0, func() { dl.Log(ctx, LevelDebug, "hello") })
})
t.Run("2 pairs", func(t *testing.T) {
s := "abc"
@@ -239,7 +242,7 @@ func TestAlloc(t *testing.T) {
s := "abc"
i := 2000
wantAllocs(t, 2, func() {
- l.Log(nil, LevelInfo, "hello",
+ l.Log(ctx, LevelInfo, "hello",
"n", i,
"s", s,
)
@@ -250,8 +253,8 @@ func TestAlloc(t *testing.T) {
s := "abc"
i := 2000
wantAllocs(t, 0, func() {
- if l.Enabled(nil, LevelInfo) {
- l.Log(nil, LevelInfo, "hello",
+ if l.Enabled(ctx, LevelInfo) {
+ l.Log(ctx, LevelInfo, "hello",
"n", i,
"s", s,
)
@@ -273,30 +276,30 @@ func TestAlloc(t *testing.T) {
wantAllocs(t, 0, func() { dl.Info("", "error", io.EOF) })
})
t.Run("attrs1", func(t *testing.T) {
- wantAllocs(t, 0, func() { dl.LogAttrs(nil, LevelInfo, "", Int("a", 1)) })
- wantAllocs(t, 0, func() { dl.LogAttrs(nil, LevelInfo, "", Any("error", io.EOF)) })
+ wantAllocs(t, 0, func() { dl.LogAttrs(ctx, LevelInfo, "", Int("a", 1)) })
+ wantAllocs(t, 0, func() { dl.LogAttrs(ctx, LevelInfo, "", Any("error", io.EOF)) })
})
t.Run("attrs3", func(t *testing.T) {
wantAllocs(t, 0, func() {
- dl.LogAttrs(nil, LevelInfo, "hello", Int("a", 1), String("b", "two"), Duration("c", time.Second))
+ dl.LogAttrs(ctx, LevelInfo, "hello", Int("a", 1), String("b", "two"), Duration("c", time.Second))
})
})
t.Run("attrs3 disabled", func(t *testing.T) {
logger := New(discardHandler{disabled: true})
wantAllocs(t, 0, func() {
- logger.LogAttrs(nil, LevelInfo, "hello", Int("a", 1), String("b", "two"), Duration("c", time.Second))
+ logger.LogAttrs(ctx, LevelInfo, "hello", Int("a", 1), String("b", "two"), Duration("c", time.Second))
})
})
t.Run("attrs6", func(t *testing.T) {
wantAllocs(t, 1, func() {
- dl.LogAttrs(nil, LevelInfo, "hello",
+ dl.LogAttrs(ctx, LevelInfo, "hello",
Int("a", 1), String("b", "two"), Duration("c", time.Second),
Int("d", 1), String("e", "two"), Duration("f", time.Second))
})
})
t.Run("attrs9", func(t *testing.T) {
wantAllocs(t, 1, func() {
- dl.LogAttrs(nil, LevelInfo, "hello",
+ dl.LogAttrs(ctx, LevelInfo, "hello",
Int("a", 1), String("b", "two"), Duration("c", time.Second),
Int("d", 1), String("e", "two"), Duration("f", time.Second),
Int("d", 1), String("e", "two"), Duration("f", time.Second))
@@ -395,14 +398,14 @@ func TestContext(t *testing.T) {
f func(context.Context, string, ...any)
wantLevel Level
}{
- {l.DebugCtx, LevelDebug},
- {l.InfoCtx, LevelInfo},
- {l.WarnCtx, LevelWarn},
- {l.ErrorCtx, LevelError},
- {DebugCtx, LevelDebug},
- {InfoCtx, LevelInfo},
- {WarnCtx, LevelWarn},
- {ErrorCtx, LevelError},
+ {l.DebugContext, LevelDebug},
+ {l.InfoContext, LevelInfo},
+ {l.WarnContext, LevelWarn},
+ {l.ErrorContext, LevelError},
+ {DebugContext, LevelDebug},
+ {InfoContext, LevelInfo},
+ {WarnContext, LevelWarn},
+ {ErrorContext, LevelError},
} {
h.clear()
ctx := context.WithValue(context.Background(), "L", test.wantLevel)
@@ -511,27 +514,27 @@ func BenchmarkNopLog(b *testing.B) {
b.Run("no attrs", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
- l.LogAttrs(nil, LevelInfo, "msg")
+ l.LogAttrs(ctx, LevelInfo, "msg")
}
})
b.Run("attrs", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
- l.LogAttrs(nil, LevelInfo, "msg", Int("a", 1), String("b", "two"), Bool("c", true))
+ l.LogAttrs(ctx, LevelInfo, "msg", Int("a", 1), String("b", "two"), Bool("c", true))
}
})
b.Run("attrs-parallel", func(b *testing.B) {
b.ReportAllocs()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
- l.LogAttrs(nil, LevelInfo, "msg", Int("a", 1), String("b", "two"), Bool("c", true))
+ l.LogAttrs(ctx, LevelInfo, "msg", Int("a", 1), String("b", "two"), Bool("c", true))
}
})
})
b.Run("keys-values", func(b *testing.B) {
b.ReportAllocs()
for i := 0; i < b.N; i++ {
- l.Log(nil, LevelInfo, "msg", "a", 1, "b", "two", "c", true)
+ l.Log(ctx, LevelInfo, "msg", "a", 1, "b", "two", "c", true)
}
})
b.Run("WithContext", func(b *testing.B) {
diff --git a/src/log/slog/record.go b/src/log/slog/record.go
index 972552d519..67b76f34e1 100644
--- a/src/log/slog/record.go
+++ b/src/log/slog/record.go
@@ -93,9 +93,17 @@ func (r Record) Attrs(f func(Attr) bool) {
}
// AddAttrs appends the given Attrs to the Record's list of Attrs.
+// It omits empty groups.
func (r *Record) AddAttrs(attrs ...Attr) {
- n := copy(r.front[r.nFront:], attrs)
- r.nFront += n
+ var i int
+ for i = 0; i < len(attrs) && r.nFront < len(r.front); i++ {
+ a := attrs[i]
+ if a.Value.isEmptyGroup() {
+ continue
+ }
+ r.front[r.nFront] = a
+ r.nFront++
+ }
// Check if a copy was modified by slicing past the end
// and seeing if the Attr there is non-zero.
if cap(r.back) > len(r.back) {
@@ -104,15 +112,25 @@ func (r *Record) AddAttrs(attrs ...Attr) {
panic("copies of a slog.Record were both modified")
}
}
- r.back = append(r.back, attrs[n:]...)
+ ne := countEmptyGroups(attrs[i:])
+ r.back = slices.Grow(r.back, len(attrs[i:])-ne)
+ for _, a := range attrs[i:] {
+ if !a.Value.isEmptyGroup() {
+ r.back = append(r.back, a)
+ }
+ }
}
// Add converts the args to Attrs as described in [Logger.Log],
// then appends the Attrs to the Record's list of Attrs.
+// It omits empty groups.
func (r *Record) Add(args ...any) {
var a Attr
for len(args) > 0 {
a, args = argsToAttr(args)
+ if a.Value.isEmptyGroup() {
+ continue
+ }
if r.nFront < len(r.front) {
r.front[r.nFront] = a
r.nFront++
diff --git a/src/log/slog/value.go b/src/log/slog/value.go
index 71a59d2639..224848f695 100644
--- a/src/log/slog/value.go
+++ b/src/log/slog/value.go
@@ -164,9 +164,32 @@ func DurationValue(v time.Duration) Value {
// GroupValue returns a new Value for a list of Attrs.
// The caller must not subsequently mutate the argument slice.
func GroupValue(as ...Attr) Value {
+ // Remove empty groups.
+ // It is simpler overall to do this at construction than
+ // to check each Group recursively for emptiness.
+ if n := countEmptyGroups(as); n > 0 {
+ as2 := make([]Attr, 0, len(as)-n)
+ for _, a := range as {
+ if !a.Value.isEmptyGroup() {
+ as2 = append(as2, a)
+ }
+ }
+ as = as2
+ }
return Value{num: uint64(len(as)), any: groupptr(unsafe.SliceData(as))}
}
+// countEmptyGroups returns the number of empty group values in its argument.
+func countEmptyGroups(as []Attr) int {
+ n := 0
+ for _, a := range as {
+ if a.Value.isEmptyGroup() {
+ n++
+ }
+ }
+ return n
+}
+
// AnyValue returns a Value for the supplied value.
//
// If the supplied value is of type Value, it is returned
@@ -399,6 +422,17 @@ func (v Value) Equal(w Value) bool {
}
}
+// isEmptyGroup reports whether v is a group that has no attributes.
+func (v Value) isEmptyGroup() bool {
+ if v.Kind() != KindGroup {
+ return false
+ }
+ // We do not need to recursively examine the group's Attrs for emptiness,
+ // because GroupValue removed them when the group was constructed, and
+ // groups are immutable.
+ return len(v.group()) == 0
+}
+
// append appends a text representation of v to dst.
// v is formatted as with fmt.Sprint.
func (v Value) append(dst []byte) []byte {
diff --git a/src/log/slog/value_test.go b/src/log/slog/value_test.go
index 615bed79d9..923a4e0ccc 100644
--- a/src/log/slog/value_test.go
+++ b/src/log/slog/value_test.go
@@ -229,6 +229,18 @@ func TestZeroTime(t *testing.T) {
}
}
+func TestEmptyGroup(t *testing.T) {
+ g := GroupValue(
+ Int("a", 1),
+ Group("g1", Group("g2")),
+ Group("g3", Group("g4", Int("b", 2))))
+ got := g.Group()
+ want := []Attr{Int("a", 1), Group("g3", Group("g4", Int("b", 2)))}
+ if !attrsEqual(got, want) {
+ t.Errorf("\ngot %v\nwant %v", got, want)
+ }
+}
+
type replace struct {
v Value
}
diff --git a/src/maps/example_test.go b/src/maps/example_test.go
new file mode 100644
index 0000000000..779c66dcef
--- /dev/null
+++ b/src/maps/example_test.go
@@ -0,0 +1,45 @@
+// 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 maps_test
+
+import (
+ "fmt"
+ "maps"
+ "strings"
+)
+
+func ExampleDeleteFunc() {
+ m := map[string]int{
+ "one": 1,
+ "two": 2,
+ "three": 3,
+ "four": 4,
+ }
+ maps.DeleteFunc(m, func(k string, v int) bool {
+ return v%2 != 0 // delete odd values
+ })
+ fmt.Println(m)
+ // Output:
+ // map[four:4 two:2]
+}
+
+func ExampleEqualFunc() {
+ m1 := map[int]string{
+ 1: "one",
+ 10: "Ten",
+ 1000: "THOUSAND",
+ }
+ m2 := map[int][]byte{
+ 1: []byte("One"),
+ 10: []byte("Ten"),
+ 1000: []byte("Thousand"),
+ }
+ eq := maps.EqualFunc(m1, m2, func(v1 string, v2 []byte) bool {
+ return strings.ToLower(v1) == strings.ToLower(string(v2))
+ })
+ fmt.Println(eq)
+ // Output:
+ // true
+}
diff --git a/src/math/all_test.go b/src/math/all_test.go
index 886267bc17..af3c38c2a6 100644
--- a/src/math/all_test.go
+++ b/src/math/all_test.go
@@ -2059,6 +2059,9 @@ var fmaC = []struct{ x, y, z, want float64 }{
// Special
{0, 0, 0, 0},
+ {Copysign(0, -1), 0, 0, 0},
+ {0, 0, Copysign(0, -1), 0},
+ {Copysign(0, -1), 0, Copysign(0, -1), Copysign(0, -1)},
{-1.1754226043408471e-38, NaN(), Inf(0), NaN()},
{0, 0, 2.22507385643494e-308, 2.22507385643494e-308},
{-8.65697792e+09, NaN(), -7.516192799999999e+09, NaN()},
@@ -2077,6 +2080,10 @@ var fmaC = []struct{ x, y, z, want float64 }{
{4.612811918325842e+18, 1.4901161193847641e-08, 2.6077032311277997e-08, 6.873625395187494e+10},
{-9.094947033611148e-13, 4.450691014249257e-308, 2.086006742350485e-308, 2.086006742346437e-308},
{-7.751454006381804e-05, 5.588653777189071e-308, -2.2207280111272877e-308, -2.2211612130544025e-308},
+
+ // Issue #61130
+ {-1, 1, 1, 0},
+ {1, 1, -1, 0},
}
var sqrt32 = []float32{
@@ -3099,6 +3106,45 @@ func TestFMA(t *testing.T) {
}
}
+//go:noinline
+func fmsub(x, y, z float64) float64 {
+ return FMA(x, y, -z)
+}
+
+//go:noinline
+func fnmsub(x, y, z float64) float64 {
+ return FMA(-x, y, z)
+}
+
+//go:noinline
+func fnmadd(x, y, z float64) float64 {
+ return FMA(-x, y, -z)
+}
+
+func TestFMANegativeArgs(t *testing.T) {
+ // Some architectures have instructions for fused multiply-subtract and
+ // also negated variants of fused multiply-add and subtract. This test
+ // aims to check that the optimizations that generate those instructions
+ // are applied correctly, if they exist.
+ for _, c := range fmaC {
+ want := PortableFMA(c.x, c.y, -c.z)
+ got := fmsub(c.x, c.y, c.z)
+ if !alike(got, want) {
+ t.Errorf("FMA(%g, %g, -(%g)) == %g, want %g", c.x, c.y, c.z, got, want)
+ }
+ want = PortableFMA(-c.x, c.y, c.z)
+ got = fnmsub(c.x, c.y, c.z)
+ if !alike(got, want) {
+ t.Errorf("FMA(-(%g), %g, %g) == %g, want %g", c.x, c.y, c.z, got, want)
+ }
+ want = PortableFMA(-c.x, c.y, -c.z)
+ got = fnmadd(c.x, c.y, c.z)
+ if !alike(got, want) {
+ t.Errorf("FMA(-(%g), %g, -(%g)) == %g, want %g", c.x, c.y, c.z, got, want)
+ }
+ }
+}
+
// Check that math functions of high angle values
// return accurate results. [Since (vf[i] + large) - large != vf[i],
// testing for Trig(vf[i] + large) == Trig(vf[i]), where large is
diff --git a/src/math/fma.go b/src/math/fma.go
index ca0bf99f21..ba03fbe8a9 100644
--- a/src/math/fma.go
+++ b/src/math/fma.go
@@ -132,6 +132,11 @@ func FMA(x, y, z float64) float64 {
ps, pe, pm1, pm2, zs, ze, zm1, zm2 = zs, ze, zm1, zm2, ps, pe, pm1, pm2
}
+ // Special case: if p == -z the result is always +0 since neither operand is zero.
+ if ps != zs && pe == ze && pm1 == zm1 && pm2 == zm2 {
+ return 0
+ }
+
// Align significands
zm1, zm2 = shrcompress(zm1, zm2, uint(pe-ze))
diff --git a/src/net/cgo_stub.go b/src/net/cgo_stub.go
index bd483110b5..b26b11af8b 100644
--- a/src/net/cgo_stub.go
+++ b/src/net/cgo_stub.go
@@ -3,12 +3,13 @@
// license that can be found in the LICENSE file.
// This file holds stub versions of the cgo functions called on Unix systems.
-// We build this file if using the netgo build tag, or if cgo is not
-// enabled and we are using a Unix system other than Darwin.
-// Darwin is exempted because it always provides the cgo routines,
-// in cgo_unix_syscall.go.
+// We build this file:
+// - if using the netgo build tag on a Unix system
+// - on a Unix system without the cgo resolver functions
+// (Darwin always provides the cgo functions, in cgo_unix_syscall.go)
+// - on wasip1, where cgo is never available
-//go:build netgo || (!cgo && unix && !darwin)
+//go:build (netgo && unix) || (unix && !cgo && !darwin) || wasip1
package net
diff --git a/src/net/conf.go b/src/net/conf.go
index 1db166c9e3..77cc635592 100644
--- a/src/net/conf.go
+++ b/src/net/conf.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !js && !wasip1
+//go:build !js
package net
diff --git a/src/net/dial.go b/src/net/dial.go
index fd1da1ebef..79bc4958bb 100644
--- a/src/net/dial.go
+++ b/src/net/dial.go
@@ -6,6 +6,7 @@ package net
import (
"context"
+ "internal/godebug"
"internal/nettrace"
"syscall"
"time"
@@ -21,6 +22,8 @@ const (
defaultMPTCPEnabled = false
)
+var multipathtcp = godebug.New("multipathtcp")
+
// mptcpStatus is a tristate for Multipath TCP, see go.dev/issue/56539
type mptcpStatus uint8
@@ -39,6 +42,13 @@ func (m *mptcpStatus) get() bool {
return false
}
+ // If MPTCP is forced via GODEBUG=multipathtcp=1
+ if multipathtcp.Value() == "1" {
+ multipathtcp.IncNonDefault()
+
+ return true
+ }
+
return defaultMPTCPEnabled
}
@@ -329,7 +339,7 @@ func (d *Dialer) MultipathTCP() bool {
// SetMultipathTCP directs the Dial methods to use, or not use, MPTCP,
// if supported by the operating system. This method overrides the
-// system default.
+// system default and the GODEBUG=multipathtcp=... setting if any.
//
// If MPTCP is not available on the host or not supported by the server,
// the Dial methods will fall back to TCP.
@@ -690,7 +700,7 @@ func (lc *ListenConfig) MultipathTCP() bool {
// SetMultipathTCP directs the Listen method to use, or not use, MPTCP,
// if supported by the operating system. This method overrides the
-// system default.
+// system default and the GODEBUG=multipathtcp=... setting if any.
//
// If MPTCP is not available on the host or not supported by the client,
// the Listen method will fall back to TCP.
diff --git a/src/net/dnsclient_unix.go b/src/net/dnsclient_unix.go
index f3c075c83f..dab5144e5d 100644
--- a/src/net/dnsclient_unix.go
+++ b/src/net/dnsclient_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !js && !wasip1
+//go:build !js
// DNS client: see RFC 1035.
// Has to be linked into package net for Dial.
diff --git a/src/net/dnsconfig_unix.go b/src/net/dnsconfig_unix.go
index d5f34e5300..69b300410a 100644
--- a/src/net/dnsconfig_unix.go
+++ b/src/net/dnsconfig_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build !js && !wasip1 && !windows
+//go:build !js && !windows
// Read system DNS config from /etc/resolv.conf
diff --git a/src/net/http/fcgi/fcgi.go b/src/net/http/fcgi/fcgi.go
index fb822f8a6d..56f7d40789 100644
--- a/src/net/http/fcgi/fcgi.go
+++ b/src/net/http/fcgi/fcgi.go
@@ -99,8 +99,10 @@ func (h *header) init(recType recType, reqId uint16, contentLength int) {
// conn sends records over rwc
type conn struct {
- mutex sync.Mutex
- rwc io.ReadWriteCloser
+ mutex sync.Mutex
+ rwc io.ReadWriteCloser
+ closeErr error
+ closed bool
// to avoid allocations
buf bytes.Buffer
@@ -111,10 +113,15 @@ func newConn(rwc io.ReadWriteCloser) *conn {
return &conn{rwc: rwc}
}
+// Close closes the conn if it is not already closed.
func (c *conn) Close() error {
c.mutex.Lock()
defer c.mutex.Unlock()
- return c.rwc.Close()
+ if !c.closed {
+ c.closeErr = c.rwc.Close()
+ c.closed = true
+ }
+ return c.closeErr
}
type record struct {
diff --git a/src/net/http/fcgi/fcgi_test.go b/src/net/http/fcgi/fcgi_test.go
index 7a344ff31d..03c422420f 100644
--- a/src/net/http/fcgi/fcgi_test.go
+++ b/src/net/http/fcgi/fcgi_test.go
@@ -241,7 +241,7 @@ func TestChildServeCleansUp(t *testing.T) {
input := make([]byte, len(tt.input))
copy(input, tt.input)
rc := nopWriteCloser{bytes.NewReader(input)}
- done := make(chan bool)
+ done := make(chan struct{})
c := newChild(rc, http.HandlerFunc(func(
w http.ResponseWriter,
r *http.Request,
@@ -252,9 +252,9 @@ func TestChildServeCleansUp(t *testing.T) {
t.Errorf("Expected %#v, got %#v", tt.err, err)
}
// not reached if body of request isn't closed
- done <- true
+ close(done)
}))
- go c.serve()
+ c.serve()
// wait for body of request to be closed or all goroutines to block
<-done
}
@@ -331,7 +331,7 @@ func TestChildServeReadsEnvVars(t *testing.T) {
input := make([]byte, len(tt.input))
copy(input, tt.input)
rc := nopWriteCloser{bytes.NewReader(input)}
- done := make(chan bool)
+ done := make(chan struct{})
c := newChild(rc, http.HandlerFunc(func(
w http.ResponseWriter,
r *http.Request,
@@ -343,9 +343,9 @@ func TestChildServeReadsEnvVars(t *testing.T) {
} else if env[tt.envVar] != tt.expectedVal {
t.Errorf("Expected %s, got %s", tt.expectedVal, env[tt.envVar])
}
- done <- true
+ close(done)
}))
- go c.serve()
+ c.serve()
<-done
}
}
@@ -381,7 +381,7 @@ func TestResponseWriterSniffsContentType(t *testing.T) {
input := make([]byte, len(streamFullRequestStdin))
copy(input, streamFullRequestStdin)
rc := nopWriteCloser{bytes.NewReader(input)}
- done := make(chan bool)
+ done := make(chan struct{})
var resp *response
c := newChild(rc, http.HandlerFunc(func(
w http.ResponseWriter,
@@ -389,10 +389,9 @@ func TestResponseWriterSniffsContentType(t *testing.T) {
) {
io.WriteString(w, tt.body)
resp = w.(*response)
- done <- true
+ close(done)
}))
- defer c.cleanUp()
- go c.serve()
+ c.serve()
<-done
if got := resp.Header().Get("Content-Type"); got != tt.wantCT {
t.Errorf("got a Content-Type of %q; expected it to start with %q", got, tt.wantCT)
@@ -401,25 +400,27 @@ func TestResponseWriterSniffsContentType(t *testing.T) {
}
}
-type signalingNopCloser struct {
- io.Reader
+type signalingNopWriteCloser struct {
+ io.ReadCloser
closed chan bool
}
-func (*signalingNopCloser) Write(buf []byte) (int, error) {
+func (*signalingNopWriteCloser) Write(buf []byte) (int, error) {
return len(buf), nil
}
-func (rc *signalingNopCloser) Close() error {
+func (rc *signalingNopWriteCloser) Close() error {
close(rc.closed)
- return nil
+ return rc.ReadCloser.Close()
}
// Test whether server properly closes connection when processing slow
// requests
func TestSlowRequest(t *testing.T) {
pr, pw := io.Pipe()
- go func(w io.Writer) {
+
+ writerDone := make(chan struct{})
+ go func() {
for _, buf := range [][]byte{
streamBeginTypeStdin,
makeRecord(typeStdin, 1, nil),
@@ -427,9 +428,14 @@ func TestSlowRequest(t *testing.T) {
pw.Write(buf)
time.Sleep(100 * time.Millisecond)
}
- }(pw)
-
- rc := &signalingNopCloser{pr, make(chan bool)}
+ close(writerDone)
+ }()
+ defer func() {
+ <-writerDone
+ pw.Close()
+ }()
+
+ rc := &signalingNopWriteCloser{pr, make(chan bool)}
handlerDone := make(chan bool)
c := newChild(rc, http.HandlerFunc(func(
@@ -439,16 +445,9 @@ func TestSlowRequest(t *testing.T) {
w.WriteHeader(200)
close(handlerDone)
}))
- go c.serve()
- defer c.cleanUp()
-
- timeout := time.After(2 * time.Second)
+ c.serve()
<-handlerDone
- select {
- case <-rc.closed:
- t.Log("FastCGI child closed connection")
- case <-timeout:
- t.Error("FastCGI child did not close socket after handling request")
- }
+ <-rc.closed
+ t.Log("FastCGI child closed connection")
}
diff --git a/src/net/http/h2_bundle.go b/src/net/http/h2_bundle.go
index ebc004a30d..dc3e099c83 100644
--- a/src/net/http/h2_bundle.go
+++ b/src/net/http/h2_bundle.go
@@ -7540,11 +7540,14 @@ func (t *http2Transport) RoundTrip(req *Request) (*Response, error) {
func http2authorityAddr(scheme string, authority string) (addr string) {
host, port, err := net.SplitHostPort(authority)
if err != nil { // authority didn't have a port
+ host = authority
+ port = ""
+ }
+ if port == "" { // authority's port was empty
port = "443"
if scheme == "http" {
port = "80"
}
- host = authority
}
if a, err := idna.ToASCII(host); err == nil {
host = a
@@ -8290,22 +8293,7 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
cancelRequest := func(cs *http2clientStream, err error) error {
cs.cc.mu.Lock()
- cs.abortStreamLocked(err)
bodyClosed := cs.reqBodyClosed
- if cs.ID != 0 {
- // This request may have failed because of a problem with the connection,
- // or for some unrelated reason. (For example, the user might have canceled
- // the request without waiting for a response.) Mark the connection as
- // not reusable, since trying to reuse a dead connection is worse than
- // unnecessarily creating a new one.
- //
- // If cs.ID is 0, then the request was never allocated a stream ID and
- // whatever went wrong was unrelated to the connection. We might have
- // timed out waiting for a stream slot when StrictMaxConcurrentStreams
- // is set, for example, in which case retrying on a different connection
- // will not help.
- cs.cc.doNotReuse = true
- }
cs.cc.mu.Unlock()
// Wait for the request body to be closed.
//
@@ -8340,11 +8328,14 @@ func (cc *http2ClientConn) RoundTrip(req *Request) (*Response, error) {
return handleResponseHeaders()
default:
waitDone()
- return nil, cancelRequest(cs, cs.abortErr)
+ return nil, cs.abortErr
}
case <-ctx.Done():
- return nil, cancelRequest(cs, ctx.Err())
+ err := ctx.Err()
+ cs.abortStream(err)
+ return nil, cancelRequest(cs, err)
case <-cs.reqCancel:
+ cs.abortStream(http2errRequestCanceled)
return nil, cancelRequest(cs, http2errRequestCanceled)
}
}
@@ -8902,6 +8893,9 @@ func (cc *http2ClientConn) encodeHeaders(req *Request, addGzipHeader bool, trail
if err != nil {
return nil, err
}
+ if !httpguts.ValidHostHeader(host) {
+ return nil, errors.New("http2: invalid Host header")
+ }
var path string
if req.Method != "CONNECT" {
diff --git a/src/net/http/http_test.go b/src/net/http/http_test.go
index 1c9fb33b69..91bb1b2620 100644
--- a/src/net/http/http_test.go
+++ b/src/net/http/http_test.go
@@ -48,35 +48,6 @@ func TestForeachHeaderElement(t *testing.T) {
}
}
-func TestCleanHost(t *testing.T) {
- tests := []struct {
- in, want string
- }{
- {"www.google.com", "www.google.com"},
- {"www.google.com foo", "www.google.com"},
- {"www.google.com/foo", "www.google.com"},
- {" first character is a space", ""},
- {"[1::6]:8080", "[1::6]:8080"},
-
- // Punycode:
- {"гофер.рф/foo", "xn--c1ae0ajs.xn--p1ai"},
- {"bücher.de", "xn--bcher-kva.de"},
- {"bücher.de:8080", "xn--bcher-kva.de:8080"},
- // Verify we convert to lowercase before punycode:
- {"BÜCHER.de", "xn--bcher-kva.de"},
- {"BÜCHER.de:8080", "xn--bcher-kva.de:8080"},
- // Verify we normalize to NFC before punycode:
- {"gophér.nfc", "xn--gophr-esa.nfc"}, // NFC input; no work needed
- {"goph\u0065\u0301r.nfd", "xn--gophr-esa.nfd"}, // NFD input
- }
- for _, tt := range tests {
- got := cleanHost(tt.in)
- if tt.want != got {
- t.Errorf("cleanHost(%q) = %q, want %q", tt.in, got, tt.want)
- }
- }
-}
-
// Test that cmd/go doesn't link in the HTTP server.
//
// This catches accidental dependencies between the HTTP transport and
diff --git a/src/net/http/request.go b/src/net/http/request.go
index 4e9190493c..bd868373c5 100644
--- a/src/net/http/request.go
+++ b/src/net/http/request.go
@@ -17,7 +17,6 @@ import (
"io"
"mime"
"mime/multipart"
- "net"
"net/http/httptrace"
"net/http/internal/ascii"
"net/textproto"
@@ -27,6 +26,7 @@ import (
"strings"
"sync"
+ "golang.org/x/net/http/httpguts"
"golang.org/x/net/idna"
)
@@ -580,12 +580,19 @@ func (r *Request) write(w io.Writer, usingProxy bool, extraHeaders Header, waitF
// is not given, use the host from the request URL.
//
// Clean the host, in case it arrives with unexpected stuff in it.
- host := cleanHost(r.Host)
+ host := r.Host
if host == "" {
if r.URL == nil {
return errMissingHost
}
- host = cleanHost(r.URL.Host)
+ host = r.URL.Host
+ }
+ host, err = httpguts.PunycodeHostPort(host)
+ if err != nil {
+ return err
+ }
+ if !httpguts.ValidHostHeader(host) {
+ return errors.New("http: invalid Host header")
}
// According to RFC 6874, an HTTP client, proxy, or other
@@ -742,40 +749,6 @@ func idnaASCII(v string) (string, error) {
return idna.Lookup.ToASCII(v)
}
-// cleanHost cleans up the host sent in request's Host header.
-//
-// It both strips anything after '/' or ' ', and puts the value
-// into Punycode form, if necessary.
-//
-// Ideally we'd clean the Host header according to the spec:
-//
-// https://tools.ietf.org/html/rfc7230#section-5.4 (Host = uri-host [ ":" port ]")
-// https://tools.ietf.org/html/rfc7230#section-2.7 (uri-host -> rfc3986's host)
-// https://tools.ietf.org/html/rfc3986#section-3.2.2 (definition of host)
-//
-// But practically, what we are trying to avoid is the situation in
-// issue 11206, where a malformed Host header used in the proxy context
-// would create a bad request. So it is enough to just truncate at the
-// first offending character.
-func cleanHost(in string) string {
- if i := strings.IndexAny(in, " /"); i != -1 {
- in = in[:i]
- }
- host, port, err := net.SplitHostPort(in)
- if err != nil { // input was just a host
- a, err := idnaASCII(in)
- if err != nil {
- return in // garbage in, garbage out
- }
- return a
- }
- a, err := idnaASCII(host)
- if err != nil {
- return in // garbage in, garbage out
- }
- return net.JoinHostPort(a, port)
-}
-
// removeZone removes IPv6 zone identifier from host.
// E.g., "[fe80::1%en0]:8080" to "[fe80::1]:8080"
func removeZone(host string) string {
diff --git a/src/net/http/request_test.go b/src/net/http/request_test.go
index 78b968f23c..0892bc255f 100644
--- a/src/net/http/request_test.go
+++ b/src/net/http/request_test.go
@@ -775,15 +775,8 @@ func TestRequestBadHost(t *testing.T) {
}
req.Host = "foo.com with spaces"
req.URL.Host = "foo.com with spaces"
- req.Write(logWrites{t, &got})
- want := []string{
- "GET /after HTTP/1.1\r\n",
- "Host: foo.com\r\n",
- "User-Agent: " + DefaultUserAgent + "\r\n",
- "\r\n",
- }
- if !reflect.DeepEqual(got, want) {
- t.Errorf("Writes = %q\n Want = %q", got, want)
+ if err := req.Write(logWrites{t, &got}); err == nil {
+ t.Errorf("Writing request with invalid Host: succeded, want error")
}
}
diff --git a/src/net/http/transport_test.go b/src/net/http/transport_test.go
index 172aba679b..028fecc961 100644
--- a/src/net/http/transport_test.go
+++ b/src/net/http/transport_test.go
@@ -6731,3 +6731,22 @@ func testHandlerAbortRacesBodyRead(t *testing.T, mode testMode) {
}
wg.Wait()
}
+
+func TestRequestSanitization(t *testing.T) { run(t, testRequestSanitization) }
+func testRequestSanitization(t *testing.T, mode testMode) {
+ if mode == http2Mode {
+ // Remove this after updating x/net.
+ t.Skip("https://go.dev/issue/60374 test fails when run with HTTP/2")
+ }
+ ts := newClientServerTest(t, mode, HandlerFunc(func(rw ResponseWriter, req *Request) {
+ if h, ok := req.Header["X-Evil"]; ok {
+ t.Errorf("request has X-Evil header: %q", h)
+ }
+ })).ts
+ req, _ := NewRequest("GET", ts.URL, nil)
+ req.Host = "go.dev\r\nX-Evil:evil"
+ resp, _ := ts.Client().Do(req)
+ if resp != nil {
+ resp.Body.Close()
+ }
+}
diff --git a/src/net/lookup_fake.go b/src/net/lookup_fake.go
index 45146e1c95..c27eae4ba5 100644
--- a/src/net/lookup_fake.go
+++ b/src/net/lookup_fake.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build (js && wasm) || wasip1
+//go:build js && wasm
package net
diff --git a/src/net/lookup_unix.go b/src/net/lookup_unix.go
index dc75e0a3b6..56ae11e961 100644
--- a/src/net/lookup_unix.go
+++ b/src/net/lookup_unix.go
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build unix
+//go:build unix || wasip1
package net
diff --git a/src/net/mail/message.go b/src/net/mail/message.go
index a416007fdb..af516fc30f 100644
--- a/src/net/mail/message.go
+++ b/src/net/mail/message.go
@@ -14,6 +14,7 @@ Notable divergences:
such as breaking addresses across lines.
- No unicode normalization is performed.
- The special characters ()[]:;@\, are allowed to appear unquoted in names.
+ - A leading From line is permitted, as in mbox format (RFC 4155).
*/
package mail
@@ -53,7 +54,7 @@ type Message struct {
func ReadMessage(r io.Reader) (msg *Message, err error) {
tp := textproto.NewReader(bufio.NewReader(r))
- hdr, err := tp.ReadMIMEHeader()
+ hdr, err := readHeader(tp)
if err != nil && (err != io.EOF || len(hdr) == 0) {
return nil, err
}
@@ -64,6 +65,54 @@ func ReadMessage(r io.Reader) (msg *Message, err error) {
}, nil
}
+// readHeader reads the message headers from r.
+// This is like textproto.ReadMIMEHeader, but doesn't validate.
+// The fix for issue #53188 tightened up net/textproto to enforce
+// restrictions of RFC 7230.
+// This package implements RFC 5322, which does not have those restrictions.
+// This function copies the relevant code from net/textproto,
+// simplified for RFC 5322.
+func readHeader(r *textproto.Reader) (map[string][]string, error) {
+ m := make(map[string][]string)
+
+ // The first line cannot start with a leading space.
+ if buf, err := r.R.Peek(1); err == nil && (buf[0] == ' ' || buf[0] == '\t') {
+ line, err := r.ReadLine()
+ if err != nil {
+ return m, err
+ }
+ return m, errors.New("malformed initial line: " + line)
+ }
+
+ for {
+ kv, err := r.ReadContinuedLine()
+ if kv == "" {
+ return m, err
+ }
+
+ // Key ends at first colon.
+ k, v, ok := strings.Cut(kv, ":")
+ if !ok {
+ return m, errors.New("malformed header line: " + kv)
+ }
+ key := textproto.CanonicalMIMEHeaderKey(k)
+
+ // Permit empty key, because that is what we did in the past.
+ if key == "" {
+ continue
+ }
+
+ // Skip initial spaces in value.
+ value := strings.TrimLeft(v, " \t")
+
+ m[key] = append(m[key], value)
+
+ if err != nil {
+ return m, err
+ }
+ }
+}
+
// Layouts suitable for passing to time.Parse.
// These are tried in order.
var (
diff --git a/src/net/mail/message_test.go b/src/net/mail/message_test.go
index 4b581ccc73..1e1bb4092f 100644
--- a/src/net/mail/message_test.go
+++ b/src/net/mail/message_test.go
@@ -52,6 +52,34 @@ Version: 1
},
body: "",
},
+ {
+ // RFC 5322 permits any printable ASCII character,
+ // except colon, in a header key. Issue #58862.
+ in: `From: iant@golang.org
+Custom/Header: v
+
+Body
+`,
+ header: Header{
+ "From": []string{"iant@golang.org"},
+ "Custom/Header": []string{"v"},
+ },
+ body: "Body\n",
+ },
+ {
+ // RFC 4155 mbox format. We've historically permitted this,
+ // so we continue to permit it. Issue #60332.
+ in: `From iant@golang.org Mon Jun 19 00:00:00 2023
+From: iant@golang.org
+
+Hello, gophers!
+`,
+ header: Header{
+ "From": []string{"iant@golang.org"},
+ "From iant@golang.org Mon Jun 19 00": []string{"00:00 2023"},
+ },
+ body: "Hello, gophers!\n",
+ },
}
func TestParsing(t *testing.T) {
diff --git a/src/net/mptcpsock_linux_test.go b/src/net/mptcpsock_linux_test.go
index bf8fc951c5..5134aba75e 100644
--- a/src/net/mptcpsock_linux_test.go
+++ b/src/net/mptcpsock_linux_test.go
@@ -12,15 +12,22 @@ import (
"testing"
)
-func newLocalListenerMPTCP(t *testing.T) Listener {
+func newLocalListenerMPTCP(t *testing.T, envVar bool) Listener {
lc := &ListenConfig{}
- if lc.MultipathTCP() {
- t.Error("MultipathTCP should be off by default")
- }
- lc.SetMultipathTCP(true)
- if !lc.MultipathTCP() {
- t.Fatal("MultipathTCP is not on after having been forced to on")
+ if envVar {
+ if !lc.MultipathTCP() {
+ t.Fatal("MultipathTCP Listen is not on despite GODEBUG=multipathtcp=1")
+ }
+ } else {
+ if lc.MultipathTCP() {
+ t.Error("MultipathTCP should be off by default")
+ }
+
+ lc.SetMultipathTCP(true)
+ if !lc.MultipathTCP() {
+ t.Fatal("MultipathTCP is not on after having been forced to on")
+ }
}
ln, err := lc.Listen(context.Background(), "tcp", "127.0.0.1:0")
@@ -64,15 +71,22 @@ func postAcceptMPTCP(ls *localServer, ch chan<- error) {
}
}
-func dialerMPTCP(t *testing.T, addr string) {
+func dialerMPTCP(t *testing.T, addr string, envVar bool) {
d := &Dialer{}
- if d.MultipathTCP() {
- t.Error("MultipathTCP should be off by default")
- }
- d.SetMultipathTCP(true)
- if !d.MultipathTCP() {
- t.Fatal("MultipathTCP is not on after having been forced to on")
+ if envVar {
+ if !d.MultipathTCP() {
+ t.Fatal("MultipathTCP Dialer is not on despite GODEBUG=multipathtcp=1")
+ }
+ } else {
+ if d.MultipathTCP() {
+ t.Error("MultipathTCP should be off by default")
+ }
+
+ d.SetMultipathTCP(true)
+ if !d.MultipathTCP() {
+ t.Fatal("MultipathTCP is not on after having been forced to on")
+ }
}
c, err := d.Dial("tcp", addr)
@@ -128,12 +142,16 @@ func canCreateMPTCPSocket() bool {
return true
}
-func TestMultiPathTCP(t *testing.T) {
- if !canCreateMPTCPSocket() {
- t.Skip("Cannot create MPTCP sockets")
+func testMultiPathTCP(t *testing.T, envVar bool) {
+ if envVar {
+ t.Log("Test with GODEBUG=multipathtcp=1")
+ t.Setenv("GODEBUG", "multipathtcp=1")
+ } else {
+ t.Log("Test with GODEBUG=multipathtcp=0")
+ t.Setenv("GODEBUG", "multipathtcp=0")
}
- ln := newLocalListenerMPTCP(t)
+ ln := newLocalListenerMPTCP(t, envVar)
// similar to tcpsock_test:TestIPv6LinkLocalUnicastTCP
ls := (&streamListener{Listener: ln}).newLocalServer()
@@ -153,7 +171,7 @@ func TestMultiPathTCP(t *testing.T) {
t.Fatal(err)
}
- dialerMPTCP(t, ln.Addr().String())
+ dialerMPTCP(t, ln.Addr().String(), envVar)
if err := <-genericCh; err != nil {
t.Error(err)
@@ -162,3 +180,13 @@ func TestMultiPathTCP(t *testing.T) {
t.Error(err)
}
}
+
+func TestMultiPathTCP(t *testing.T) {
+ if !canCreateMPTCPSocket() {
+ t.Skip("Cannot create MPTCP sockets")
+ }
+
+ for _, envVar := range []bool{false, true} {
+ testMultiPathTCP(t, envVar)
+ }
+}
diff --git a/src/net/net_fake.go b/src/net/net_fake.go
index 68d36966ca..908767a1f6 100644
--- a/src/net/net_fake.go
+++ b/src/net/net_fake.go
@@ -15,8 +15,6 @@ import (
"sync"
"syscall"
"time"
-
- "golang.org/x/net/dns/dnsmessage"
)
var listenersMu sync.Mutex
@@ -406,7 +404,3 @@ func (fd *fakeNetFD) writeMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int,
func (fd *fakeNetFD) dup() (f *os.File, err error) {
return nil, syscall.ENOSYS
}
-
-func (r *Resolver) lookup(ctx context.Context, name string, qtype dnsmessage.Type, conf *dnsConfig) (dnsmessage.Parser, string, error) {
- panic("unreachable")
-}
diff --git a/src/net/net_fake_js.go b/src/net/net_fake_js.go
index 1fc0b50b7d..7ba108b664 100644
--- a/src/net/net_fake_js.go
+++ b/src/net/net_fake_js.go
@@ -8,7 +8,12 @@
package net
-import "internal/poll"
+import (
+ "context"
+ "internal/poll"
+
+ "golang.org/x/net/dns/dnsmessage"
+)
// Network file descriptor.
type netFD struct {
@@ -25,3 +30,7 @@ type netFD struct {
pfd poll.FD
isConnected bool // handshake completed or use of association with peer
}
+
+func (r *Resolver) lookup(ctx context.Context, name string, qtype dnsmessage.Type, conf *dnsConfig) (dnsmessage.Parser, string, error) {
+ panic("unreachable")
+}
diff --git a/src/os/dir_darwin.go b/src/os/dir_darwin.go
index deba3eb37f..e6d5bda24b 100644
--- a/src/os/dir_darwin.go
+++ b/src/os/dir_darwin.go
@@ -54,6 +54,15 @@ func (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEn
if entptr == nil { // EOF
break
}
+ // Darwin may return a zero inode when a directory entry has been
+ // deleted but not yet removed from the directory. The man page for
+ // getdirentries(2) states that programs are responsible for skipping
+ // those entries:
+ //
+ // Users of getdirentries() should skip entries with d_fileno = 0,
+ // as such entries represent files which have been deleted but not
+ // yet removed from the directory entry.
+ //
if dirent.Ino == 0 {
continue
}
diff --git a/src/os/dir_unix.go b/src/os/dir_unix.go
index 004b9fbb2b..266a78acaf 100644
--- a/src/os/dir_unix.go
+++ b/src/os/dir_unix.go
@@ -89,7 +89,11 @@ func (f *File) readdir(n int, mode readdirMode) (names []string, dirents []DirEn
if !ok {
break
}
- if ino == 0 {
+ // When building to wasip1, the host runtime might be running on Windows
+ // or might expose a remote file system which does not have the concept
+ // of inodes. Therefore, we cannot make the assumption that it is safe
+ // to skip entries with zero inodes.
+ if ino == 0 && runtime.GOOS != "wasip1" {
continue
}
const namoff = uint64(unsafe.Offsetof(syscall.Dirent{}.Name))
diff --git a/src/os/dir_windows.go b/src/os/dir_windows.go
index 7792d03040..1724af58d5 100644
--- a/src/os/dir_windows.go
+++ b/src/os/dir_windows.go
@@ -84,6 +84,18 @@ func (file *File) readdir(n int, mode readdirMode) (names []string, dirents []Di
if err == syscall.ERROR_NO_MORE_FILES {
break
}
+ if infoClass == windows.FileIdBothDirectoryRestartInfo && err == syscall.ERROR_FILE_NOT_FOUND {
+ // GetFileInformationByHandleEx doesn't document the return error codes when the info class is FileIdBothDirectoryRestartInfo,
+ // but MS-FSA 2.1.5.6.3 [1] specifies that the underlying file system driver should return STATUS_NO_SUCH_FILE when
+ // reading an empty root directory, which is mapped to ERROR_FILE_NOT_FOUND by Windows.
+ // Note that some file system drivers may never return this error code, as the spec allows to return the "." and ".."
+ // entries in such cases, making the directory appear non-empty.
+ // The chances of false positive are very low, as we know that the directory exists, else GetVolumeInformationByHandle
+ // would have failed, and that the handle is still valid, as we haven't closed it.
+ // See go.dev/issue/61159.
+ // [1] https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-fsa/fa8194e0-53ec-413b-8315-e8fa85396fd8
+ break
+ }
if s, _ := file.Stat(); s != nil && !s.IsDir() {
err = &PathError{Op: "readdir", Path: file.name, Err: syscall.ENOTDIR}
} else {
diff --git a/src/os/env_test.go b/src/os/env_test.go
index 1b9e26594c..5809f4b866 100644
--- a/src/os/env_test.go
+++ b/src/os/env_test.go
@@ -130,7 +130,7 @@ func TestClearenv(t *testing.T) {
defer func(origEnv []string) {
for _, pair := range origEnv {
// Environment variables on Windows can begin with =
- // https://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
+ // https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133
i := strings.Index(pair[1:], "=") + 1
if err := Setenv(pair[:i], pair[i+1:]); err != nil {
t.Errorf("Setenv(%q, %q) failed during reset: %v", pair[:i], pair[i+1:], err)
diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go
index 67cd446f42..473f92ba8e 100644
--- a/src/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -1708,3 +1708,77 @@ func TestCancelErrors(t *testing.T) {
}
})
}
+
+// TestConcurrentExec is a regression test for https://go.dev/issue/61080.
+//
+// Forking multiple child processes concurrently would sometimes hang on darwin.
+// (This test hung on a gomote with -count=100 after only a few iterations.)
+func TestConcurrentExec(t *testing.T) {
+ ctx, cancel := context.WithCancel(context.Background())
+
+ // This test will spawn nHangs subprocesses that hang reading from stdin,
+ // and nExits subprocesses that exit immediately.
+ //
+ // When issue #61080 was present, a long-lived "hang" subprocess would
+ // occasionally inherit the fork/exec status pipe from an "exit" subprocess,
+ // causing the parent process (which expects to see an EOF on that pipe almost
+ // immediately) to unexpectedly block on reading from the pipe.
+ var (
+ nHangs = runtime.GOMAXPROCS(0)
+ nExits = runtime.GOMAXPROCS(0)
+ hangs, exits sync.WaitGroup
+ )
+ hangs.Add(nHangs)
+ exits.Add(nExits)
+
+ // ready is done when the goroutines have done as much work as possible to
+ // prepare to create subprocesses. It isn't strictly necessary for the test,
+ // but helps to increase the repro rate by making it more likely that calls to
+ // syscall.StartProcess for the "hang" and "exit" goroutines overlap.
+ var ready sync.WaitGroup
+ ready.Add(nHangs + nExits)
+
+ for i := 0; i < nHangs; i++ {
+ go func() {
+ defer hangs.Done()
+
+ cmd := helperCommandContext(t, ctx, "pipetest")
+ stdin, err := cmd.StdinPipe()
+ if err != nil {
+ ready.Done()
+ t.Error(err)
+ return
+ }
+ cmd.Cancel = stdin.Close
+ ready.Done()
+
+ ready.Wait()
+ if err := cmd.Start(); err != nil {
+ if !errors.Is(err, context.Canceled) {
+ t.Error(err)
+ }
+ return
+ }
+
+ cmd.Wait()
+ }()
+ }
+
+ for i := 0; i < nExits; i++ {
+ go func() {
+ defer exits.Done()
+
+ cmd := helperCommandContext(t, ctx, "exit", "0")
+ ready.Done()
+
+ ready.Wait()
+ if err := cmd.Run(); err != nil {
+ t.Error(err)
+ }
+ }()
+ }
+
+ exits.Wait()
+ cancel()
+ hangs.Wait()
+}
diff --git a/src/runtime/crash_test.go b/src/runtime/crash_test.go
index cd978cc34b..8f11333b46 100644
--- a/src/runtime/crash_test.go
+++ b/src/runtime/crash_test.go
@@ -534,7 +534,7 @@ func TestMemPprof(t *testing.T) {
got, err := testenv.CleanCmdEnv(exec.Command(exe, "MemProf")).CombinedOutput()
if err != nil {
- t.Fatal(err)
+ t.Fatalf("testprog failed: %s, output:\n%s", err, got)
}
fn := strings.TrimSpace(string(got))
defer os.Remove(fn)
diff --git a/src/runtime/crash_unix_test.go b/src/runtime/crash_unix_test.go
index 07060b8fab..6bca2ac66e 100644
--- a/src/runtime/crash_unix_test.go
+++ b/src/runtime/crash_unix_test.go
@@ -76,7 +76,7 @@ func TestCrashDumpsAllThreads(t *testing.T) {
testenv.MustHaveGoBuild(t)
- if strings.Contains(os.Getenv("GCFLAGS"), "mayMoreStackPreempt") {
+ if strings.Contains(os.Getenv("GOFLAGS"), "mayMoreStackPreempt") {
// This test occasionally times out in this debug mode. This is probably
// revealing a real bug in the scheduler, but since it seems to only
// affect this test and this is itself a test of a debug mode, it's not
diff --git a/src/runtime/extern.go b/src/runtime/extern.go
index ac07119cb9..26dcf0bd52 100644
--- a/src/runtime/extern.go
+++ b/src/runtime/extern.go
@@ -87,7 +87,8 @@ It is a comma-separated list of name=val pairs setting these named variables:
gctrace: setting gctrace=1 causes the garbage collector to emit a single line to standard
error at each collection, summarizing the amount of memory collected and the
- length of the pause. The format of this line is subject to change.
+ length of the pause. The format of this line is subject to change. Included in
+ the explanation below is also the relevant runtime/metrics metric for each field.
Currently, it is:
gc # @#s #%: #+#+# ms clock, #+#/#/#+# ms cpu, #->#-># MB, # MB goal, # MB stacks, #MB globals, # P
where the fields are as follows:
@@ -95,11 +96,11 @@ It is a comma-separated list of name=val pairs setting these named variables:
@#s time in seconds since program start
#% percentage of time spent in GC since program start
#+...+# wall-clock/CPU times for the phases of the GC
- #->#-># MB heap size at GC start, at GC end, and live heap
- # MB goal goal heap size
- # MB stacks estimated scannable stack size
- # MB globals scannable global size
- # P number of processors used
+ #->#-># MB heap size at GC start, at GC end, and live heap, or /gc/scan/heap:bytes
+ # MB goal goal heap size, or /gc/heap/goal:bytes
+ # MB stacks estimated scannable stack size, or /gc/scan/stack:bytes
+ # MB globals scannable global size, or /gc/scan/globals:bytes
+ # P number of processors used, or /sched/gomaxprocs:threads
The phases are stop-the-world (STW) sweep termination, concurrent
mark and scan, and STW mark termination. The CPU times
for mark/scan are broken down in to assist time (GC performed in
diff --git a/src/runtime/internal/wasitest/nonblock_test.go b/src/runtime/internal/wasitest/nonblock_test.go
index 8fb2860e4b..3072b96ed8 100644
--- a/src/runtime/internal/wasitest/nonblock_test.go
+++ b/src/runtime/internal/wasitest/nonblock_test.go
@@ -37,8 +37,6 @@ func TestNonblock(t *testing.T) {
}
switch os.Getenv("GOWASIRUNTIME") {
- case "wazero", "":
- t.Skip("wazero does not support non-blocking I/O")
case "wasmer":
t.Skip("wasmer does not support non-blocking I/O")
}
diff --git a/src/runtime/internal/wasitest/tcpecho_test.go b/src/runtime/internal/wasitest/tcpecho_test.go
index 506e6fe40a..c56af2cc85 100644
--- a/src/runtime/internal/wasitest/tcpecho_test.go
+++ b/src/runtime/internal/wasitest/tcpecho_test.go
@@ -44,6 +44,8 @@ func TestTCPEcho(t *testing.T) {
subProcess.Env = append(os.Environ(), "GOOS=wasip1", "GOARCH=wasm")
switch os.Getenv("GOWASIRUNTIME") {
+ case "wazero", "":
+ subProcess.Env = append(subProcess.Env, "GOWASIRUNTIMEARGS=--listen="+host)
case "wasmtime":
subProcess.Env = append(subProcess.Env, "GOWASIRUNTIMEARGS=--tcplisten="+host)
default:
diff --git a/src/runtime/metrics/description.go b/src/runtime/metrics/description.go
index aea51c7f75..745691b24f 100644
--- a/src/runtime/metrics/description.go
+++ b/src/runtime/metrics/description.go
@@ -339,9 +339,11 @@ var allDesc = []Description{
Kind: KindUint64,
},
{
- Name: "/memory/classes/heap/stacks:bytes",
- Description: "Memory allocated from the heap that is reserved for stack space, whether or not it is currently in-use.",
- Kind: KindUint64,
+ Name: "/memory/classes/heap/stacks:bytes",
+ Description: "Memory allocated from the heap that is reserved for stack space, whether or not it is currently in-use. " +
+ "Currently, this represents all stack memory for goroutines. It also includes all OS thread stacks in non-cgo programs. " +
+ "Note that stacks may be allocated differently in the future, and this may change.",
+ Kind: KindUint64,
},
{
Name: "/memory/classes/heap/unused:bytes",
@@ -374,9 +376,13 @@ var allDesc = []Description{
Kind: KindUint64,
},
{
- Name: "/memory/classes/os-stacks:bytes",
- Description: "Stack memory allocated by the underlying operating system.",
- Kind: KindUint64,
+ Name: "/memory/classes/os-stacks:bytes",
+ Description: "Stack memory allocated by the underlying operating system. " +
+ "In non-cgo programs this metric is currently zero. This may change in the future." +
+ "In cgo programs this metric includes OS thread stacks allocated directly from the OS. " +
+ "Currently, this only accounts for one stack in c-shared and c-archive build modes, " +
+ "and other sources of stacks from the OS are not measured. This too may change in the future.",
+ Kind: KindUint64,
},
{
Name: "/memory/classes/other:bytes",
diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go
index 5238bcea8e..b4d32d135a 100644
--- a/src/runtime/metrics/doc.go
+++ b/src/runtime/metrics/doc.go
@@ -273,6 +273,10 @@ Below is the full list of supported metrics, ordered lexicographically.
the mime/multipart package due to a non-default
GODEBUG=multipartmaxparts=... setting.
+ /godebug/non-default-behavior/multipathtcp:events
+ The number of non-default behaviors executed by the net package
+ due to a non-default GODEBUG=multipathtcp=... setting.
+
/godebug/non-default-behavior/panicnil:events
The number of non-default behaviors executed by the runtime
package due to a non-default GODEBUG=panicnil=... setting.
@@ -318,7 +322,10 @@ Below is the full list of supported metrics, ordered lexicographically.
/memory/classes/heap/stacks:bytes
Memory allocated from the heap that is reserved for stack space,
- whether or not it is currently in-use.
+ whether or not it is currently in-use. Currently, this
+ represents all stack memory for goroutines. It also includes all
+ OS thread stacks in non-cgo programs. Note that stacks may be
+ allocated differently in the future, and this may change.
/memory/classes/heap/unused:bytes
Memory that is reserved for heap objects but is not currently
@@ -345,6 +352,12 @@ Below is the full list of supported metrics, ordered lexicographically.
/memory/classes/os-stacks:bytes
Stack memory allocated by the underlying operating system.
+ In non-cgo programs this metric is currently zero. This may
+ change in the future.In cgo programs this metric includes
+ OS thread stacks allocated directly from the OS. Currently,
+ this only accounts for one stack in c-shared and c-archive build
+ modes, and other sources of stacks from the OS are not measured.
+ This too may change in the future.
/memory/classes/other:bytes
Memory used by execution trace buffers, structures for debugging
diff --git a/src/runtime/mstats.go b/src/runtime/mstats.go
index ab383dd8e3..9cdc565137 100644
--- a/src/runtime/mstats.go
+++ b/src/runtime/mstats.go
@@ -199,7 +199,17 @@ type MemStats struct {
// StackSys is bytes of stack memory obtained from the OS.
//
// StackSys is StackInuse, plus any memory obtained directly
- // from the OS for OS thread stacks (which should be minimal).
+ // from the OS for OS thread stacks.
+ //
+ // In non-cgo programs this metric is currently equal to StackInuse
+ // (but this should not be relied upon, and the value may change in
+ // the future).
+ //
+ // In cgo programs this metric includes OS thread stacks allocated
+ // directly from the OS. Currently, this only accounts for one stack in
+ // c-shared and c-archive build modes and other sources of stacks from
+ // the OS (notably, any allocated by C code) are not currently measured.
+ // Note this too may change in the future.
StackSys uint64
// Off-heap memory statistics.
@@ -347,6 +357,7 @@ func init() {
// which is a snapshot as of the most recently completed garbage
// collection cycle.
func ReadMemStats(m *MemStats) {
+ _ = m.Alloc // nil check test before we switch stacks, see issue 61158
stopTheWorld(stwReadMemStats)
systemstack(func() {
diff --git a/src/runtime/proc.go b/src/runtime/proc.go
index 3cecd1a057..9fd200ea32 100644
--- a/src/runtime/proc.go
+++ b/src/runtime/proc.go
@@ -4570,6 +4570,7 @@ func newproc1(fn *funcval, callergp *g, callerpc uintptr) *g {
pp.goidcache++
if raceenabled {
newg.racectx = racegostart(callerpc)
+ newg.raceignore = 0
if newg.labels != nil {
// See note in proflabel.go on labelSync's role in synchronizing
// with the reads in the signal handler.
diff --git a/src/runtime/race/testdata/mop_test.go b/src/runtime/race/testdata/mop_test.go
index 0da539fc01..6b1069fcca 100644
--- a/src/runtime/race/testdata/mop_test.go
+++ b/src/runtime/race/testdata/mop_test.go
@@ -2093,3 +2093,40 @@ func TestNoRaceTinyAlloc(t *testing.T) {
<-done
}
}
+
+func TestNoRaceIssue60934(t *testing.T) {
+ // Test that runtime.RaceDisable state doesn't accidentally get applied to
+ // new goroutines.
+
+ // Create several goroutines that end after calling runtime.RaceDisable.
+ var wg sync.WaitGroup
+ ready := make(chan struct{})
+ wg.Add(32)
+ for i := 0; i < 32; i++ {
+ go func() {
+ <-ready // ensure we have multiple goroutines running at the same time
+ runtime.RaceDisable()
+ wg.Done()
+ }()
+ }
+ close(ready)
+ wg.Wait()
+
+ // Make sure race detector still works. If the runtime.RaceDisable state
+ // leaks, the happens-before edges here will be ignored and a race on x will
+ // be reported.
+ var x int
+ ch := make(chan struct{}, 0)
+ wg.Add(2)
+ go func() {
+ x = 1
+ ch <- struct{}{}
+ wg.Done()
+ }()
+ go func() {
+ <-ch
+ _ = x
+ wg.Done()
+ }()
+ wg.Wait()
+}
diff --git a/src/runtime/trace.go b/src/runtime/trace.go
index ac80ca2902..a4d50d77a0 100644
--- a/src/runtime/trace.go
+++ b/src/runtime/trace.go
@@ -453,12 +453,17 @@ func StopTrace() {
}
}
+ // Wait for startNanotime != endNanotime. On Windows the default interval between
+ // system clock ticks is typically between 1 and 15 milliseconds, which may not
+ // have passed since the trace started. Without nanotime moving forward, trace
+ // tooling has no way of identifying how much real time each cputicks time deltas
+ // represent.
for {
trace.endTime = traceClockNow()
trace.endTicks = cputicks()
trace.endNanotime = nanotime()
- // Windows time can tick only every 15ms, wait for at least one tick.
- if trace.endNanotime != trace.startNanotime {
+
+ if trace.endNanotime != trace.startNanotime || faketime != 0 {
break
}
osyield()
diff --git a/src/runtime/traceback.go b/src/runtime/traceback.go
index d6f89210a4..86df1155b5 100644
--- a/src/runtime/traceback.go
+++ b/src/runtime/traceback.go
@@ -1147,6 +1147,7 @@ func showfuncinfo(sf srcFunc, firstFrame bool, calleeID abi.FuncID) bool {
// isExportedRuntime reports whether name is an exported runtime function.
// It is only for runtime functions, so ASCII A-Z is fine.
+// TODO: this handles exported functions but not exported methods.
func isExportedRuntime(name string) bool {
const n = len("runtime.")
return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z'
diff --git a/src/slices/example_test.go b/src/slices/example_test.go
new file mode 100644
index 0000000000..3e76907bb7
--- /dev/null
+++ b/src/slices/example_test.go
@@ -0,0 +1,322 @@
+// 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 slices_test
+
+import (
+ "cmp"
+ "fmt"
+ "slices"
+ "strconv"
+ "strings"
+)
+
+func ExampleBinarySearch() {
+ names := []string{"Alice", "Bob", "Vera"}
+ n, found := slices.BinarySearch(names, "Vera")
+ fmt.Println("Vera:", n, found)
+ n, found = slices.BinarySearch(names, "Bill")
+ fmt.Println("Bill:", n, found)
+ // Output:
+ // Vera: 2 true
+ // Bill: 1 false
+}
+
+func ExampleBinarySearchFunc() {
+ type Person struct {
+ Name string
+ Age int
+ }
+ people := []Person{
+ {"Alice", 55},
+ {"Bob", 24},
+ {"Gopher", 13},
+ }
+ n, found := slices.BinarySearchFunc(people, Person{"Bob", 0}, func(a, b Person) int {
+ return cmp.Compare(a.Name, b.Name)
+ })
+ fmt.Println("Bob:", n, found)
+ // Output:
+ // Bob: 1 true
+}
+
+func ExampleCompact() {
+ seq := []int{0, 1, 1, 2, 3, 5, 8}
+ seq = slices.Compact(seq)
+ fmt.Println(seq)
+ // Output:
+ // [0 1 2 3 5 8]
+}
+
+func ExampleCompactFunc() {
+ names := []string{"bob", "Bob", "alice", "Vera", "VERA"}
+ names = slices.CompactFunc(names, func(a, b string) bool {
+ return strings.ToLower(a) == strings.ToLower(b)
+ })
+ fmt.Println(names)
+ // Output:
+ // [bob alice Vera]
+}
+
+func ExampleCompare() {
+ names := []string{"Alice", "Bob", "Vera"}
+ fmt.Println("Equal:", slices.Compare(names, []string{"Alice", "Bob", "Vera"}))
+ fmt.Println("V < X:", slices.Compare(names, []string{"Alice", "Bob", "Xena"}))
+ fmt.Println("V > C:", slices.Compare(names, []string{"Alice", "Bob", "Cat"}))
+ fmt.Println("3 > 2:", slices.Compare(names, []string{"Alice", "Bob"}))
+ // Output:
+ // Equal: 0
+ // V < X: -1
+ // V > C: 1
+ // 3 > 2: 1
+}
+
+func ExampleCompareFunc() {
+ numbers := []int{0, 43, 8}
+ strings := []string{"0", "0", "8"}
+ result := slices.CompareFunc(numbers, strings, func(n int, s string) int {
+ sn, err := strconv.Atoi(s)
+ if err != nil {
+ return 1
+ }
+ return cmp.Compare(n, sn)
+ })
+ fmt.Println(result)
+ // Output:
+ // 1
+}
+
+func ExampleContainsFunc() {
+ numbers := []int{0, 42, -10, 8}
+ hasNegative := slices.ContainsFunc(numbers, func(n int) bool {
+ return n < 0
+ })
+ fmt.Println("Has a negative:", hasNegative)
+ hasOdd := slices.ContainsFunc(numbers, func(n int) bool {
+ return n%2 != 0
+ })
+ fmt.Println("Has an odd number:", hasOdd)
+ // Output:
+ // Has a negative: true
+ // Has an odd number: false
+}
+
+func ExampleDelete() {
+ letters := []string{"a", "b", "c", "d", "e"}
+ letters = slices.Delete(letters, 1, 4)
+ fmt.Println(letters)
+ // Output:
+ // [a e]
+}
+
+func ExampleDeleteFunc() {
+ seq := []int{0, 1, 1, 2, 3, 5, 8}
+ seq = slices.DeleteFunc(seq, func(n int) bool {
+ return n%2 != 0 // delete the odd numbers
+ })
+ fmt.Println(seq)
+ // Output:
+ // [0 2 8]
+}
+
+func ExampleEqual() {
+ numbers := []int{0, 42, 8}
+ fmt.Println(slices.Equal(numbers, []int{0, 42, 8}))
+ fmt.Println(slices.Equal(numbers, []int{10}))
+ // Output:
+ // true
+ // false
+}
+
+func ExampleEqualFunc() {
+ numbers := []int{0, 42, 8}
+ strings := []string{"000", "42", "0o10"}
+ equal := slices.EqualFunc(numbers, strings, func(n int, s string) bool {
+ sn, err := strconv.ParseInt(s, 0, 64)
+ if err != nil {
+ return false
+ }
+ return n == int(sn)
+ })
+ fmt.Println(equal)
+ // Output:
+ // true
+}
+
+func ExampleIndex() {
+ numbers := []int{0, 42, 8}
+ fmt.Println(slices.Index(numbers, 8))
+ fmt.Println(slices.Index(numbers, 7))
+ // Output:
+ // 2
+ // -1
+}
+
+func ExampleIndexFunc() {
+ numbers := []int{0, 42, -10, 8}
+ i := slices.IndexFunc(numbers, func(n int) bool {
+ return n < 0
+ })
+ fmt.Println("First negative at index", i)
+ // Output:
+ // First negative at index 2
+}
+
+func ExampleInsert() {
+ names := []string{"Alice", "Bob", "Vera"}
+ names = slices.Insert(names, 1, "Bill", "Billie")
+ names = slices.Insert(names, len(names), "Zac")
+ fmt.Println(names)
+ // Output:
+ // [Alice Bill Billie Bob Vera Zac]
+}
+
+func ExampleIsSorted() {
+ fmt.Println(slices.IsSorted([]string{"Alice", "Bob", "Vera"}))
+ fmt.Println(slices.IsSorted([]int{0, 2, 1}))
+ // Output:
+ // true
+ // false
+}
+
+func ExampleIsSortedFunc() {
+ names := []string{"alice", "Bob", "VERA"}
+ isSortedInsensitive := slices.IsSortedFunc(names, func(a, b string) int {
+ return cmp.Compare(strings.ToLower(a), strings.ToLower(b))
+ })
+ fmt.Println(isSortedInsensitive)
+ fmt.Println(slices.IsSorted(names))
+ // Output:
+ // true
+ // false
+}
+
+func ExampleMax() {
+ numbers := []int{0, 42, -10, 8}
+ fmt.Println(slices.Max(numbers))
+ // Output:
+ // 42
+}
+
+func ExampleMaxFunc() {
+ type Person struct {
+ Name string
+ Age int
+ }
+ people := []Person{
+ {"Gopher", 13},
+ {"Alice", 55},
+ {"Vera", 24},
+ {"Bob", 55},
+ }
+ firstOldest := slices.MaxFunc(people, func(a, b Person) int {
+ return cmp.Compare(a.Age, b.Age)
+ })
+ fmt.Println(firstOldest.Name)
+ // Output:
+ // Alice
+}
+
+func ExampleMin() {
+ numbers := []int{0, 42, -10, 8}
+ fmt.Println(slices.Min(numbers))
+ // Output:
+ // -10
+}
+
+func ExampleMinFunc() {
+ type Person struct {
+ Name string
+ Age int
+ }
+ people := []Person{
+ {"Gopher", 13},
+ {"Bob", 5},
+ {"Vera", 24},
+ {"Bill", 5},
+ }
+ firstYoungest := slices.MinFunc(people, func(a, b Person) int {
+ return cmp.Compare(a.Age, b.Age)
+ })
+ fmt.Println(firstYoungest.Name)
+ // Output:
+ // Bob
+}
+
+func ExampleReplace() {
+ names := []string{"Alice", "Bob", "Vera", "Zac"}
+ names = slices.Replace(names, 1, 3, "Bill", "Billie", "Cat")
+ fmt.Println(names)
+ // Output:
+ // [Alice Bill Billie Cat Zac]
+}
+
+func ExampleReverse() {
+ names := []string{"alice", "Bob", "VERA"}
+ slices.Reverse(names)
+ fmt.Println(names)
+ // Output:
+ // [VERA Bob alice]
+}
+
+func ExampleSort() {
+ smallInts := []int8{0, 42, -10, 8}
+ slices.Sort(smallInts)
+ fmt.Println(smallInts)
+ // Output:
+ // [-10 0 8 42]
+}
+
+func ExampleSortFunc_caseInsensitive() {
+ names := []string{"Bob", "alice", "VERA"}
+ slices.SortFunc(names, func(a, b string) int {
+ return cmp.Compare(strings.ToLower(a), strings.ToLower(b))
+ })
+ fmt.Println(names)
+ // Output:
+ // [alice Bob VERA]
+}
+
+func ExampleSortFunc_multiField() {
+ type Person struct {
+ Name string
+ Age int
+ }
+ people := []Person{
+ {"Gopher", 13},
+ {"Alice", 55},
+ {"Bob", 24},
+ {"Alice", 20},
+ }
+ slices.SortFunc(people, func(a, b Person) int {
+ if n := cmp.Compare(a.Name, b.Name); n != 0 {
+ return n
+ }
+ // If names are equal, order by age
+ return cmp.Compare(a.Age, b.Age)
+ })
+ fmt.Println(people)
+ // Output:
+ // [{Alice 20} {Alice 55} {Bob 24} {Gopher 13}]
+}
+
+func ExampleSortStableFunc() {
+ type Person struct {
+ Name string
+ Age int
+ }
+ people := []Person{
+ {"Gopher", 13},
+ {"Alice", 20},
+ {"Bob", 24},
+ {"Alice", 55},
+ }
+ // Stable sort by name, keeping age ordering of Alices intact
+ slices.SortStableFunc(people, func(a, b Person) int {
+ return cmp.Compare(a.Name, b.Name)
+ })
+ fmt.Println(people)
+ // Output:
+ // [{Alice 20} {Alice 55} {Bob 24} {Gopher 13}]
+}
diff --git a/src/slices/slices.go b/src/slices/slices.go
index c8eacae90e..afeed0afb5 100644
--- a/src/slices/slices.go
+++ b/src/slices/slices.go
@@ -27,7 +27,7 @@ func Equal[S ~[]E, E comparable](s1, s2 S) bool {
return true
}
-// EqualFunc reports whether two slices are equal using a comparison
+// EqualFunc reports whether two slices are equal using an equality
// function on each pair of elements. If the lengths are different,
// EqualFunc returns false. Otherwise, the elements are compared in
// increasing index order, and the comparison stops at the first index
@@ -68,7 +68,7 @@ func Compare[S ~[]E, E cmp.Ordered](s1, s2 S) int {
return 0
}
-// CompareFunc is like Compare but uses a custom comparison function on each
+// CompareFunc is like [Compare] but uses a custom comparison function on each
// pair of elements.
// The result is the first non-zero result of cmp; if cmp always
// returns 0 the result is 0 if len(s1) == len(s2), -1 if len(s1) < len(s2),
@@ -210,7 +210,6 @@ func Insert[S ~[]E, E any](s S, i int, v ...E) S {
// Delete removes the elements s[i:j] from s, returning the modified slice.
// Delete panics if s[i:j] is not a valid slice of s.
-// Delete modifies the contents of the slice s; it does not create a new slice.
// Delete is O(len(s)-j), so if many items must be deleted, it is better to
// make a single call deleting them all together than to delete one at a time.
// Delete might not modify the elements s[len(s)-(j-i):len(s)]. If those
@@ -224,8 +223,6 @@ func Delete[S ~[]E, E any](s S, i, j int) S {
// DeleteFunc removes any elements from s for which del returns true,
// returning the modified slice.
-// DeleteFunc modifies the contents of the slice s;
-// it does not create a new slice.
// When DeleteFunc removes m elements, it might not modify the elements
// s[len(s)-m:len(s)]. If those elements contain pointers you might consider
// zeroing those elements so that objects they reference can be garbage
@@ -348,7 +345,8 @@ func Clone[S ~[]E, E any](s S) S {
// Compact replaces consecutive runs of equal elements with a single copy.
// This is like the uniq command found on Unix.
-// Compact modifies the contents of the slice s; it does not create a new slice.
+// Compact modifies the contents of the slice s and returns the modified slice,
+// which may have a smaller length.
// When Compact discards m elements in total, it might not modify the elements
// s[len(s)-m:len(s)]. If those elements contain pointers you might consider
// zeroing those elements so that objects they reference can be garbage collected.
@@ -368,7 +366,8 @@ func Compact[S ~[]E, E comparable](s S) S {
return s[:i]
}
-// CompactFunc is like Compact but uses a comparison function.
+// CompactFunc is like [Compact] but uses an equality function to compare elements.
+// For runs of elements that compare equal, CompactFunc keeps the first one.
func CompactFunc[S ~[]E, E any](s S, eq func(E, E) bool) S {
if len(s) < 2 {
return s
diff --git a/src/slices/sort.go b/src/slices/sort.go
index 24fc6e26b6..822f2fceb4 100644
--- a/src/slices/sort.go
+++ b/src/slices/sort.go
@@ -29,7 +29,7 @@ func SortFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
}
// SortStableFunc sorts the slice x while keeping the original order of equal
-// elements, using cmp to compare elements.
+// elements, using cmp to compare elements in the same way as [SortFunc].
func SortStableFunc[S ~[]E, E any](x S, cmp func(a, b E) int) {
stableCmpFunc(x, len(x), cmp)
}
@@ -45,7 +45,7 @@ func IsSorted[S ~[]E, E cmp.Ordered](x S) bool {
}
// IsSortedFunc reports whether x is sorted in ascending order, with cmp as the
-// comparison function.
+// comparison function as defined by [SortFunc].
func IsSortedFunc[S ~[]E, E any](x S, cmp func(a, b E) int) bool {
for i := len(x) - 1; i > 0; i-- {
if cmp(x[i], x[i-1]) < 0 {
@@ -70,7 +70,8 @@ func Min[S ~[]E, E cmp.Ordered](x S) E {
}
// MinFunc returns the minimal value in x, using cmp to compare elements.
-// It panics if x is empty.
+// It panics if x is empty. If there is more than one minimal element
+// according to the cmp function, MinFunc returns the first one.
func MinFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
if len(x) < 1 {
panic("slices.MinFunc: empty list")
@@ -99,7 +100,8 @@ func Max[S ~[]E, E cmp.Ordered](x S) E {
}
// MaxFunc returns the maximal value in x, using cmp to compare elements.
-// It panics if x is empty.
+// It panics if x is empty. If there is more than one maximal element
+// according to the cmp function, MaxFunc returns the first one.
func MaxFunc[S ~[]E, E any](x S, cmp func(a, b E) int) E {
if len(x) < 1 {
panic("slices.MaxFunc: empty list")
@@ -136,7 +138,7 @@ func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool) {
return i, i < n && (x[i] == target || (isNaN(x[i]) && isNaN(target)))
}
-// BinarySearchFunc works like BinarySearch, but uses a custom comparison
+// BinarySearchFunc works like [BinarySearch], but uses a custom comparison
// function. The slice must be sorted in increasing order, where "increasing"
// is defined by cmp. cmp should return 0 if the slice element matches
// the target, a negative number if the slice element precedes the target,
diff --git a/src/slices/sort_test.go b/src/slices/sort_test.go
index 0e9df92b63..af0585935d 100644
--- a/src/slices/sort_test.go
+++ b/src/slices/sort_test.go
@@ -173,6 +173,15 @@ func TestStability(t *testing.T) {
}
}
+type S struct {
+ a int
+ b string
+}
+
+func cmpS(s1, s2 S) int {
+ return cmp.Compare(s1.a, s2.a)
+}
+
func TestMinMax(t *testing.T) {
intCmp := func(a, b int) int { return a - b }
@@ -214,6 +223,25 @@ func TestMinMax(t *testing.T) {
}
})
}
+
+ svals := []S{
+ {1, "a"},
+ {2, "a"},
+ {1, "b"},
+ {2, "b"},
+ }
+
+ gotMin := MinFunc(svals, cmpS)
+ wantMin := S{1, "a"}
+ if gotMin != wantMin {
+ t.Errorf("MinFunc(%v) = %v, want %v", svals, gotMin, wantMin)
+ }
+
+ gotMax := MaxFunc(svals, cmpS)
+ wantMax := S{2, "a"}
+ if gotMax != wantMax {
+ t.Errorf("MaxFunc(%v) = %v, want %v", svals, gotMax, wantMax)
+ }
}
func TestMinMaxNaNs(t *testing.T) {
diff --git a/src/syscall/dirent.go b/src/syscall/dirent.go
index eee94bf73c..1a0f1eec11 100644
--- a/src/syscall/dirent.go
+++ b/src/syscall/dirent.go
@@ -6,7 +6,10 @@
package syscall
-import "unsafe"
+import (
+ "runtime"
+ "unsafe"
+)
// readInt returns the size-bytes unsigned integer in native byte order at offset off.
func readInt(b []byte, off, size uintptr) (u uint64, ok bool) {
@@ -75,7 +78,9 @@ func ParseDirent(buf []byte, max int, names []string) (consumed int, count int,
if !ok {
break
}
- if ino == 0 { // File absent in directory.
+ // See src/os/dir_unix.go for the reason why this condition is
+ // excluded on wasip1.
+ if ino == 0 && runtime.GOOS != "wasip1" { // File absent in directory.
continue
}
const namoff = uint64(unsafe.Offsetof(Dirent{}.Name))
diff --git a/src/syscall/env_windows.go b/src/syscall/env_windows.go
index 20d74b51e0..220a005e1a 100644
--- a/src/syscall/env_windows.go
+++ b/src/syscall/env_windows.go
@@ -62,7 +62,7 @@ func Clearenv() {
for _, s := range Environ() {
// Environment variables can begin with =
// so start looking for the separator = at j=1.
- // https://blogs.msdn.com/b/oldnewthing/archive/2010/05/06/10008132.aspx
+ // https://devblogs.microsoft.com/oldnewthing/20100506-00/?p=14133
for j := 1; j < len(s); j++ {
if s[j] == '=' {
Unsetenv(s[0:j])
diff --git a/src/syscall/exec_linux.go b/src/syscall/exec_linux.go
index feb1e26432..dfbb38ac16 100644
--- a/src/syscall/exec_linux.go
+++ b/src/syscall/exec_linux.go
@@ -641,11 +641,6 @@ childerror:
}
}
-// Try to open a pipe with O_CLOEXEC set on both file descriptors.
-func forkExecPipe(p []int) (err error) {
- return Pipe2(p, O_CLOEXEC)
-}
-
func formatIDMappings(idMap []SysProcIDMap) []byte {
var data []byte
for _, im := range idMap {
diff --git a/src/syscall/exec_unix.go b/src/syscall/exec_unix.go
index 14edd023d3..9a5f2d3295 100644
--- a/src/syscall/exec_unix.go
+++ b/src/syscall/exec_unix.go
@@ -241,89 +241,6 @@ func forkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error)
return pid, nil
}
-var (
- // Guard the forking variable.
- forkingLock sync.Mutex
- // Number of goroutines currently forking, and thus the
- // number of goroutines holding a conceptual write lock
- // on ForkLock.
- forking int
-)
-
-// hasWaitingReaders reports whether any goroutine is waiting
-// to acquire a read lock on rw. It is defined in the sync package.
-func hasWaitingReaders(rw *sync.RWMutex) bool
-
-// acquireForkLock acquires a write lock on ForkLock.
-// ForkLock is exported and we've promised that during a fork
-// we will call ForkLock.Lock, so that no other threads create
-// new fds that are not yet close-on-exec before we fork.
-// But that forces all fork calls to be serialized, which is bad.
-// But we haven't promised that serialization, and it is essentially
-// undetectable by other users of ForkLock, which is good.
-// Avoid the serialization by ensuring that ForkLock is locked
-// at the first fork and unlocked when there are no more forks.
-func acquireForkLock() {
- forkingLock.Lock()
- defer forkingLock.Unlock()
-
- if forking == 0 {
- // There is no current write lock on ForkLock.
- ForkLock.Lock()
- forking++
- return
- }
-
- // ForkLock is currently locked for writing.
-
- if hasWaitingReaders(&ForkLock) {
- // ForkLock is locked for writing, and at least one
- // goroutine is waiting to read from it.
- // To avoid lock starvation, allow readers to proceed.
- // The simple way to do this is for us to acquire a
- // read lock. That will block us until all current
- // conceptual write locks are released.
- //
- // Note that this case is unusual on modern systems
- // with O_CLOEXEC and SOCK_CLOEXEC. On those systems
- // the standard library should never take a read
- // lock on ForkLock.
-
- forkingLock.Unlock()
-
- ForkLock.RLock()
- ForkLock.RUnlock()
-
- forkingLock.Lock()
-
- // Readers got a chance, so now take the write lock.
-
- if forking == 0 {
- ForkLock.Lock()
- }
- }
-
- forking++
-}
-
-// releaseForkLock releases the conceptual write lock on ForkLock
-// acquired by acquireForkLock.
-func releaseForkLock() {
- forkingLock.Lock()
- defer forkingLock.Unlock()
-
- if forking <= 0 {
- panic("syscall.releaseForkLock: negative count")
- }
-
- forking--
-
- if forking == 0 {
- // No more conceptual write locks.
- ForkLock.Unlock()
- }
-}
-
// Combination of fork and exec, careful to be thread safe.
func ForkExec(argv0 string, argv []string, attr *ProcAttr) (pid int, err error) {
return forkExec(argv0, argv, attr)
diff --git a/src/syscall/exec_windows.go b/src/syscall/exec_windows.go
index 45295dedff..0a93bc0a80 100644
--- a/src/syscall/exec_windows.go
+++ b/src/syscall/exec_windows.go
@@ -247,7 +247,7 @@ type SysProcAttr struct {
Token Token // if set, runs new process in the security context represented by the token
ProcessAttributes *SecurityAttributes // if set, applies these security attributes as the descriptor for the new process
ThreadAttributes *SecurityAttributes // if set, applies these security attributes as the descriptor for the main thread of the new process
- NoInheritHandles bool // if set, each inheritable handle in the calling process is not inherited by the new process
+ NoInheritHandles bool // if set, no handles are inherited by the new process, not even the standard handles, contained in ProcAttr.Files, nor the ones contained in AdditionalInheritedHandles
AdditionalInheritedHandles []Handle // a list of additional handles, already marked as inheritable, that will be inherited by the new process
ParentProcess Handle // if non-zero, the new process regards the process given by this handle as its parent process, and AdditionalInheritedHandles, if set, should exist in this parent process
}
diff --git a/src/syscall/forkpipe.go b/src/syscall/forkpipe.go
index 5082abc41c..1f4292f686 100644
--- a/src/syscall/forkpipe.go
+++ b/src/syscall/forkpipe.go
@@ -6,7 +6,8 @@
package syscall
-// Try to open a pipe with O_CLOEXEC set on both file descriptors.
+// forkExecPipe opens a pipe and non-atomically sets O_CLOEXEC on both file
+// descriptors.
func forkExecPipe(p []int) error {
err := Pipe(p)
if err != nil {
@@ -19,3 +20,11 @@ func forkExecPipe(p []int) error {
_, err = fcntl(p[1], F_SETFD, FD_CLOEXEC)
return err
}
+
+func acquireForkLock() {
+ ForkLock.Lock()
+}
+
+func releaseForkLock() {
+ ForkLock.Unlock()
+}
diff --git a/src/syscall/forkpipe2.go b/src/syscall/forkpipe2.go
index 6ab1391c12..bbecfdabf8 100644
--- a/src/syscall/forkpipe2.go
+++ b/src/syscall/forkpipe2.go
@@ -2,10 +2,97 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-//go:build dragonfly || freebsd || netbsd || openbsd || solaris
+//go:build dragonfly || freebsd || linux || netbsd || openbsd || solaris
package syscall
+import "sync"
+
+// forkExecPipe atomically opens a pipe with O_CLOEXEC set on both file
+// descriptors.
func forkExecPipe(p []int) error {
return Pipe2(p, O_CLOEXEC)
}
+
+var (
+ // Guard the forking variable.
+ forkingLock sync.Mutex
+ // Number of goroutines currently forking, and thus the
+ // number of goroutines holding a conceptual write lock
+ // on ForkLock.
+ forking int
+)
+
+// hasWaitingReaders reports whether any goroutine is waiting
+// to acquire a read lock on rw. It is defined in the sync package.
+func hasWaitingReaders(rw *sync.RWMutex) bool
+
+// acquireForkLock acquires a write lock on ForkLock.
+// ForkLock is exported and we've promised that during a fork
+// we will call ForkLock.Lock, so that no other threads create
+// new fds that are not yet close-on-exec before we fork.
+// But that forces all fork calls to be serialized, which is bad.
+// But we haven't promised that serialization, and it is essentially
+// undetectable by other users of ForkLock, which is good.
+// Avoid the serialization by ensuring that ForkLock is locked
+// at the first fork and unlocked when there are no more forks.
+func acquireForkLock() {
+ forkingLock.Lock()
+ defer forkingLock.Unlock()
+
+ if forking == 0 {
+ // There is no current write lock on ForkLock.
+ ForkLock.Lock()
+ forking++
+ return
+ }
+
+ // ForkLock is currently locked for writing.
+
+ if hasWaitingReaders(&ForkLock) {
+ // ForkLock is locked for writing, and at least one
+ // goroutine is waiting to read from it.
+ // To avoid lock starvation, allow readers to proceed.
+ // The simple way to do this is for us to acquire a
+ // read lock. That will block us until all current
+ // conceptual write locks are released.
+ //
+ // Note that this case is unusual on modern systems
+ // with O_CLOEXEC and SOCK_CLOEXEC. On those systems
+ // the standard library should never take a read
+ // lock on ForkLock.
+
+ forkingLock.Unlock()
+
+ ForkLock.RLock()
+ ForkLock.RUnlock()
+
+ forkingLock.Lock()
+
+ // Readers got a chance, so now take the write lock.
+
+ if forking == 0 {
+ ForkLock.Lock()
+ }
+ }
+
+ forking++
+}
+
+// releaseForkLock releases the conceptual write lock on ForkLock
+// acquired by acquireForkLock.
+func releaseForkLock() {
+ forkingLock.Lock()
+ defer forkingLock.Unlock()
+
+ if forking <= 0 {
+ panic("syscall.releaseForkLock: negative count")
+ }
+
+ forking--
+
+ if forking == 0 {
+ // No more conceptual write locks.
+ ForkLock.Unlock()
+ }
+}
diff --git a/src/syscall/fs_wasip1.go b/src/syscall/fs_wasip1.go
index d60ab0b53e..4ad3f9610b 100644
--- a/src/syscall/fs_wasip1.go
+++ b/src/syscall/fs_wasip1.go
@@ -11,6 +11,20 @@ import (
"unsafe"
)
+func init() {
+ // Try to set stdio to non-blocking mode before the os package
+ // calls NewFile for each fd. NewFile queries the non-blocking flag
+ // but doesn't change it, even if the runtime supports non-blocking
+ // stdio. Since WebAssembly modules are single-threaded, blocking
+ // system calls temporarily halt execution of the module. If the
+ // runtime supports non-blocking stdio, the Go runtime is able to
+ // use the WASI net poller to poll for read/write readiness and is
+ // able to schedule goroutines while waiting.
+ SetNonblock(0, true)
+ SetNonblock(1, true)
+ SetNonblock(2, true)
+}
+
type uintptr32 = uint32
type size = uint32
type fdflags = uint32
diff --git a/src/syscall/syscall_wasip1.go b/src/syscall/syscall_wasip1.go
index 5d19c000ae..e66afee5e9 100644
--- a/src/syscall/syscall_wasip1.go
+++ b/src/syscall/syscall_wasip1.go
@@ -478,3 +478,16 @@ func SetNonblock(fd int, nonblocking bool) error {
errno := fd_fdstat_set_flags(int32(fd), flags)
return errnoErr(errno)
}
+
+type Rlimit struct {
+ Cur uint64
+ Max uint64
+}
+
+const (
+ RLIMIT_NOFILE = iota
+)
+
+func Getrlimit(which int, lim *Rlimit) error {
+ return ENOSYS
+}
diff --git a/src/testing/slogtest/slogtest.go b/src/testing/slogtest/slogtest.go
index 71076e52f4..b16d1227dc 100644
--- a/src/testing/slogtest/slogtest.go
+++ b/src/testing/slogtest/slogtest.go
@@ -163,6 +163,20 @@ func TestHandler(h slog.Handler, results func() []map[string]any) error {
},
},
{
+ explanation: withSource("a Handler should not output groups for an empty Record"),
+ f: func(l *slog.Logger) {
+ l.With("a", "b").WithGroup("G").With("c", "d").WithGroup("H").Info("msg")
+ },
+ checks: []check{
+ hasKey(slog.TimeKey),
+ hasKey(slog.LevelKey),
+ hasAttr(slog.MessageKey, "msg"),
+ hasAttr("a", "b"),
+ inGroup("G", hasAttr("c", "d")),
+ inGroup("G", missingKey("H")),
+ },
+ },
+ {
explanation: withSource("a Handler should call Resolve on attribute values"),
f: func(l *slog.Logger) {
l.Info("msg", "k", &replace{"replaced"})
diff --git a/src/time/sleep_test.go b/src/time/sleep_test.go
index 8aac3b68f6..2f791240f9 100644
--- a/src/time/sleep_test.go
+++ b/src/time/sleep_test.go
@@ -418,22 +418,22 @@ func TestReset(t *testing.T) {
// We try to run this test with increasingly larger multiples
// until one works so slow, loaded hardware isn't as flaky,
// but without slowing down fast machines unnecessarily.
- const unit = 25 * Millisecond
- tries := []Duration{
- 1 * unit,
- 3 * unit,
- 7 * unit,
- 15 * unit,
- }
- var err error
- for _, d := range tries {
- err = testReset(d)
+ //
+ // (maxDuration is several orders of magnitude longer than we
+ // expect this test to actually take on a fast, unloaded machine.)
+ d := 1 * Millisecond
+ const maxDuration = 10 * Second
+ for {
+ err := testReset(d)
if err == nil {
- t.Logf("passed using duration %v", d)
- return
+ break
}
+ d *= 2
+ if d > maxDuration {
+ t.Error(err)
+ }
+ t.Logf("%v; trying duration %v", err, d)
}
- t.Error(err)
}
// Test that sleeping (via Sleep or Timer) for an interval so large it
diff --git a/src/vendor/golang.org/x/net/dns/dnsmessage/message.go b/src/vendor/golang.org/x/net/dns/dnsmessage/message.go
index 1577d4a19d..37da3de4d3 100644
--- a/src/vendor/golang.org/x/net/dns/dnsmessage/message.go
+++ b/src/vendor/golang.org/x/net/dns/dnsmessage/message.go
@@ -527,12 +527,14 @@ func (r *Resource) pack(msg []byte, compression map[string]int, compressionOff i
// When parsing is started, the Header is parsed. Next, each Question can be
// either parsed or skipped. Alternatively, all Questions can be skipped at
// once. When all Questions have been parsed, attempting to parse Questions
-// will return (nil, nil) and attempting to skip Questions will return
-// (true, nil). After all Questions have been either parsed or skipped, all
+// will return the [ErrSectionDone] error.
+// After all Questions have been either parsed or skipped, all
// Answers, Authorities and Additionals can be either parsed or skipped in the
// same way, and each type of Resource must be fully parsed or skipped before
// proceeding to the next type of Resource.
//
+// Parser is safe to copy to preserve the parsing state.
+//
// Note that there is no requirement to fully skip or parse the message.
type Parser struct {
msg []byte
diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt
index 88d2554c04..2b5f965f8f 100644
--- a/src/vendor/modules.txt
+++ b/src/vendor/modules.txt
@@ -1,4 +1,4 @@
-# golang.org/x/crypto v0.10.0
+# golang.org/x/crypto v0.11.1-0.20230711161743-2e82bdd1719d
## explicit; go 1.17
golang.org/x/crypto/chacha20
golang.org/x/crypto/chacha20poly1305
@@ -7,7 +7,7 @@ golang.org/x/crypto/cryptobyte/asn1
golang.org/x/crypto/hkdf
golang.org/x/crypto/internal/alias
golang.org/x/crypto/internal/poly1305
-# golang.org/x/net v0.11.1-0.20230613203745-f5464ddb689c
+# golang.org/x/net v0.12.1-0.20230712162946-57553cbff163
## explicit; go 1.17
golang.org/x/net/dns/dnsmessage
golang.org/x/net/http/httpguts
@@ -17,10 +17,10 @@ golang.org/x/net/idna
golang.org/x/net/lif
golang.org/x/net/nettest
golang.org/x/net/route
-# golang.org/x/sys v0.9.0
+# golang.org/x/sys v0.10.0
## explicit; go 1.17
golang.org/x/sys/cpu
-# golang.org/x/text v0.10.1-0.20230613190012-2df65d769a9e
+# golang.org/x/text v0.11.0
## explicit; go 1.17
golang.org/x/text/secure/bidirule
golang.org/x/text/transform
diff --git a/test/codegen/bits.go b/test/codegen/bits.go
index 4f70627c25..018f5b909e 100644
--- a/test/codegen/bits.go
+++ b/test/codegen/bits.go
@@ -374,3 +374,23 @@ func foldConstOutOfRange(a uint64) uint64 {
// arm64: "MOVD\t[$]19088744",-"ADD\t[$]19088744"
return a + 0x1234568
}
+
+// Verify sign-extended values are not zero-extended under a bit mask (#61297)
+func signextendAndMask8to64(a int8) (s, z uint64) {
+ // ppc64x: "MOVB", "ANDCC\t[$]1015,"
+ s = uint64(a) & 0x3F7
+ // ppc64x: -"MOVB", "ANDCC\t[$]247,"
+ z = uint64(uint8(a)) & 0x3F7
+ return
+
+}
+
+// Verify zero-extended values are not sign-extended under a bit mask (#61297)
+func zeroextendAndMask8to64(a int8, b int16) (x, y uint64) {
+ // ppc64x: -"MOVB\t", -"ANDCC", "MOVBZ"
+ x = uint64(a) & 0xFF
+ // ppc64x: -"MOVH\t", -"ANDCC", "MOVHZ"
+ y = uint64(b) & 0xFFFF
+ return
+
+}
diff --git a/test/codegen/floats.go b/test/codegen/floats.go
index 81471082d4..9cb62e031a 100644
--- a/test/codegen/floats.go
+++ b/test/codegen/floats.go
@@ -20,6 +20,7 @@ func Mul2(f float64) float64 {
// arm/7:"ADDD",-"MULD"
// arm64:"FADDD",-"FMULD"
// ppc64x:"FADD",-"FMUL"
+ // riscv64:"FADDD",-"FMULD"
return f * 2.0
}
@@ -29,6 +30,7 @@ func DivPow2(f1, f2, f3 float64) (float64, float64, float64) {
// arm/7:"MULD",-"DIVD"
// arm64:"FMULD",-"FDIVD"
// ppc64x:"FMUL",-"FDIV"
+ // riscv64:"FMULD",-"FDIVD"
x := f1 / 16.0
// 386/sse2:"MULSD",-"DIVSD"
@@ -36,6 +38,7 @@ func DivPow2(f1, f2, f3 float64) (float64, float64, float64) {
// arm/7:"MULD",-"DIVD"
// arm64:"FMULD",-"FDIVD"
// ppc64x:"FMUL",-"FDIVD"
+ // riscv64:"FMULD",-"FDIVD"
y := f2 / 0.125
// 386/sse2:"ADDSD",-"DIVSD",-"MULSD"
@@ -43,6 +46,7 @@ func DivPow2(f1, f2, f3 float64) (float64, float64, float64) {
// arm/7:"ADDD",-"MULD",-"DIVD"
// arm64:"FADDD",-"FMULD",-"FDIVD"
// ppc64x:"FADD",-"FMUL",-"FDIV"
+ // riscv64:"FADDD",-"FMULD",-"FDIVD"
z := f3 / 0.5
return x, y, z
diff --git a/test/codegen/math.go b/test/codegen/math.go
index 6a7d304afd..331ebbe609 100644
--- a/test/codegen/math.go
+++ b/test/codegen/math.go
@@ -143,13 +143,13 @@ func fms(x, y, z float64) float64 {
return math.FMA(x, y, -z)
}
-func fnma(x, y, z float64) float64 {
- // riscv64:"FNMADDD"
+func fnms(x, y, z float64) float64 {
+ // riscv64:"FNMSUBD",-"FNMADDD"
return math.FMA(-x, y, z)
}
-func fnms(x, y, z float64) float64 {
- // riscv64:"FNMSUBD"
+func fnma(x, y, z float64) float64 {
+ // riscv64:"FNMADDD",-"FNMSUBD"
return math.FMA(x, -y, -z)
}
diff --git a/test/fixedbugs/bug516.go b/test/fixedbugs/bug516.go
new file mode 100644
index 0000000000..e52eb215ef
--- /dev/null
+++ b/test/fixedbugs/bug516.go
@@ -0,0 +1,13 @@
+// compile
+
+// 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.
+
+// Caused a gofrontend crash.
+
+package p
+
+func F(b []byte, i int) {
+ *(*[1]byte)(b[i*2:]) = [1]byte{}
+}
diff --git a/test/fixedbugs/issue60945.dir/a.go b/test/fixedbugs/issue60945.dir/a.go
new file mode 100644
index 0000000000..663a0cfc69
--- /dev/null
+++ b/test/fixedbugs/issue60945.dir/a.go
@@ -0,0 +1,22 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type S struct{}
+
+func callClosure(closure func()) {
+ closure()
+}
+
+func (s *S) M() {
+ callClosure(func() {
+ defer f(s.m) // prevent closures to be inlined.
+ })
+}
+
+func (s *S) m() {}
+
+//go:noinline
+func f(a ...any) {}
diff --git a/test/fixedbugs/issue60945.dir/b.go b/test/fixedbugs/issue60945.dir/b.go
new file mode 100644
index 0000000000..e60d9dc7c1
--- /dev/null
+++ b/test/fixedbugs/issue60945.dir/b.go
@@ -0,0 +1,9 @@
+// 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 b
+
+import "./a"
+
+var _ = (&a.S{}).M
diff --git a/test/fixedbugs/issue60945.go b/test/fixedbugs/issue60945.go
new file mode 100644
index 0000000000..5c4c5c0a8f
--- /dev/null
+++ b/test/fixedbugs/issue60945.go
@@ -0,0 +1,7 @@
+// compiledir
+
+// 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 ignored
diff --git a/test/fixedbugs/issue60982.go b/test/fixedbugs/issue60982.go
new file mode 100644
index 0000000000..4e5fc34646
--- /dev/null
+++ b/test/fixedbugs/issue60982.go
@@ -0,0 +1,2023 @@
+// compile
+
+// 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 main
+
+func f(x int, b bool) int {
+ if x >= 1000 {
+ if b { // from #61041
+ var a struct{ f int64 }
+ _ = max(0, a.f)
+ }
+
+ return max(x, 2000)
+ }
+ // generate 1000 basic blocks to put this function
+ // well into the "large function" phi generation algorithm.
+ switch x {
+ case 0:
+ return 0
+ case 1:
+ return 1
+ case 2:
+ return 2
+ case 3:
+ return 3
+ case 4:
+ return 4
+ case 5:
+ return 5
+ case 6:
+ return 6
+ case 7:
+ return 7
+ case 8:
+ return 8
+ case 9:
+ return 9
+ case 10:
+ return 10
+ case 11:
+ return 11
+ case 12:
+ return 12
+ case 13:
+ return 13
+ case 14:
+ return 14
+ case 15:
+ return 15
+ case 16:
+ return 16
+ case 17:
+ return 17
+ case 18:
+ return 18
+ case 19:
+ return 19
+ case 20:
+ return 20
+ case 21:
+ return 21
+ case 22:
+ return 22
+ case 23:
+ return 23
+ case 24:
+ return 24
+ case 25:
+ return 25
+ case 26:
+ return 26
+ case 27:
+ return 27
+ case 28:
+ return 28
+ case 29:
+ return 29
+ case 30:
+ return 30
+ case 31:
+ return 31
+ case 32:
+ return 32
+ case 33:
+ return 33
+ case 34:
+ return 34
+ case 35:
+ return 35
+ case 36:
+ return 36
+ case 37:
+ return 37
+ case 38:
+ return 38
+ case 39:
+ return 39
+ case 40:
+ return 40
+ case 41:
+ return 41
+ case 42:
+ return 42
+ case 43:
+ return 43
+ case 44:
+ return 44
+ case 45:
+ return 45
+ case 46:
+ return 46
+ case 47:
+ return 47
+ case 48:
+ return 48
+ case 49:
+ return 49
+ case 50:
+ return 50
+ case 51:
+ return 51
+ case 52:
+ return 52
+ case 53:
+ return 53
+ case 54:
+ return 54
+ case 55:
+ return 55
+ case 56:
+ return 56
+ case 57:
+ return 57
+ case 58:
+ return 58
+ case 59:
+ return 59
+ case 60:
+ return 60
+ case 61:
+ return 61
+ case 62:
+ return 62
+ case 63:
+ return 63
+ case 64:
+ return 64
+ case 65:
+ return 65
+ case 66:
+ return 66
+ case 67:
+ return 67
+ case 68:
+ return 68
+ case 69:
+ return 69
+ case 70:
+ return 70
+ case 71:
+ return 71
+ case 72:
+ return 72
+ case 73:
+ return 73
+ case 74:
+ return 74
+ case 75:
+ return 75
+ case 76:
+ return 76
+ case 77:
+ return 77
+ case 78:
+ return 78
+ case 79:
+ return 79
+ case 80:
+ return 80
+ case 81:
+ return 81
+ case 82:
+ return 82
+ case 83:
+ return 83
+ case 84:
+ return 84
+ case 85:
+ return 85
+ case 86:
+ return 86
+ case 87:
+ return 87
+ case 88:
+ return 88
+ case 89:
+ return 89
+ case 90:
+ return 90
+ case 91:
+ return 91
+ case 92:
+ return 92
+ case 93:
+ return 93
+ case 94:
+ return 94
+ case 95:
+ return 95
+ case 96:
+ return 96
+ case 97:
+ return 97
+ case 98:
+ return 98
+ case 99:
+ return 99
+ case 100:
+ return 100
+ case 101:
+ return 101
+ case 102:
+ return 102
+ case 103:
+ return 103
+ case 104:
+ return 104
+ case 105:
+ return 105
+ case 106:
+ return 106
+ case 107:
+ return 107
+ case 108:
+ return 108
+ case 109:
+ return 109
+ case 110:
+ return 110
+ case 111:
+ return 111
+ case 112:
+ return 112
+ case 113:
+ return 113
+ case 114:
+ return 114
+ case 115:
+ return 115
+ case 116:
+ return 116
+ case 117:
+ return 117
+ case 118:
+ return 118
+ case 119:
+ return 119
+ case 120:
+ return 120
+ case 121:
+ return 121
+ case 122:
+ return 122
+ case 123:
+ return 123
+ case 124:
+ return 124
+ case 125:
+ return 125
+ case 126:
+ return 126
+ case 127:
+ return 127
+ case 128:
+ return 128
+ case 129:
+ return 129
+ case 130:
+ return 130
+ case 131:
+ return 131
+ case 132:
+ return 132
+ case 133:
+ return 133
+ case 134:
+ return 134
+ case 135:
+ return 135
+ case 136:
+ return 136
+ case 137:
+ return 137
+ case 138:
+ return 138
+ case 139:
+ return 139
+ case 140:
+ return 140
+ case 141:
+ return 141
+ case 142:
+ return 142
+ case 143:
+ return 143
+ case 144:
+ return 144
+ case 145:
+ return 145
+ case 146:
+ return 146
+ case 147:
+ return 147
+ case 148:
+ return 148
+ case 149:
+ return 149
+ case 150:
+ return 150
+ case 151:
+ return 151
+ case 152:
+ return 152
+ case 153:
+ return 153
+ case 154:
+ return 154
+ case 155:
+ return 155
+ case 156:
+ return 156
+ case 157:
+ return 157
+ case 158:
+ return 158
+ case 159:
+ return 159
+ case 160:
+ return 160
+ case 161:
+ return 161
+ case 162:
+ return 162
+ case 163:
+ return 163
+ case 164:
+ return 164
+ case 165:
+ return 165
+ case 166:
+ return 166
+ case 167:
+ return 167
+ case 168:
+ return 168
+ case 169:
+ return 169
+ case 170:
+ return 170
+ case 171:
+ return 171
+ case 172:
+ return 172
+ case 173:
+ return 173
+ case 174:
+ return 174
+ case 175:
+ return 175
+ case 176:
+ return 176
+ case 177:
+ return 177
+ case 178:
+ return 178
+ case 179:
+ return 179
+ case 180:
+ return 180
+ case 181:
+ return 181
+ case 182:
+ return 182
+ case 183:
+ return 183
+ case 184:
+ return 184
+ case 185:
+ return 185
+ case 186:
+ return 186
+ case 187:
+ return 187
+ case 188:
+ return 188
+ case 189:
+ return 189
+ case 190:
+ return 190
+ case 191:
+ return 191
+ case 192:
+ return 192
+ case 193:
+ return 193
+ case 194:
+ return 194
+ case 195:
+ return 195
+ case 196:
+ return 196
+ case 197:
+ return 197
+ case 198:
+ return 198
+ case 199:
+ return 199
+ case 200:
+ return 200
+ case 201:
+ return 201
+ case 202:
+ return 202
+ case 203:
+ return 203
+ case 204:
+ return 204
+ case 205:
+ return 205
+ case 206:
+ return 206
+ case 207:
+ return 207
+ case 208:
+ return 208
+ case 209:
+ return 209
+ case 210:
+ return 210
+ case 211:
+ return 211
+ case 212:
+ return 212
+ case 213:
+ return 213
+ case 214:
+ return 214
+ case 215:
+ return 215
+ case 216:
+ return 216
+ case 217:
+ return 217
+ case 218:
+ return 218
+ case 219:
+ return 219
+ case 220:
+ return 220
+ case 221:
+ return 221
+ case 222:
+ return 222
+ case 223:
+ return 223
+ case 224:
+ return 224
+ case 225:
+ return 225
+ case 226:
+ return 226
+ case 227:
+ return 227
+ case 228:
+ return 228
+ case 229:
+ return 229
+ case 230:
+ return 230
+ case 231:
+ return 231
+ case 232:
+ return 232
+ case 233:
+ return 233
+ case 234:
+ return 234
+ case 235:
+ return 235
+ case 236:
+ return 236
+ case 237:
+ return 237
+ case 238:
+ return 238
+ case 239:
+ return 239
+ case 240:
+ return 240
+ case 241:
+ return 241
+ case 242:
+ return 242
+ case 243:
+ return 243
+ case 244:
+ return 244
+ case 245:
+ return 245
+ case 246:
+ return 246
+ case 247:
+ return 247
+ case 248:
+ return 248
+ case 249:
+ return 249
+ case 250:
+ return 250
+ case 251:
+ return 251
+ case 252:
+ return 252
+ case 253:
+ return 253
+ case 254:
+ return 254
+ case 255:
+ return 255
+ case 256:
+ return 256
+ case 257:
+ return 257
+ case 258:
+ return 258
+ case 259:
+ return 259
+ case 260:
+ return 260
+ case 261:
+ return 261
+ case 262:
+ return 262
+ case 263:
+ return 263
+ case 264:
+ return 264
+ case 265:
+ return 265
+ case 266:
+ return 266
+ case 267:
+ return 267
+ case 268:
+ return 268
+ case 269:
+ return 269
+ case 270:
+ return 270
+ case 271:
+ return 271
+ case 272:
+ return 272
+ case 273:
+ return 273
+ case 274:
+ return 274
+ case 275:
+ return 275
+ case 276:
+ return 276
+ case 277:
+ return 277
+ case 278:
+ return 278
+ case 279:
+ return 279
+ case 280:
+ return 280
+ case 281:
+ return 281
+ case 282:
+ return 282
+ case 283:
+ return 283
+ case 284:
+ return 284
+ case 285:
+ return 285
+ case 286:
+ return 286
+ case 287:
+ return 287
+ case 288:
+ return 288
+ case 289:
+ return 289
+ case 290:
+ return 290
+ case 291:
+ return 291
+ case 292:
+ return 292
+ case 293:
+ return 293
+ case 294:
+ return 294
+ case 295:
+ return 295
+ case 296:
+ return 296
+ case 297:
+ return 297
+ case 298:
+ return 298
+ case 299:
+ return 299
+ case 300:
+ return 300
+ case 301:
+ return 301
+ case 302:
+ return 302
+ case 303:
+ return 303
+ case 304:
+ return 304
+ case 305:
+ return 305
+ case 306:
+ return 306
+ case 307:
+ return 307
+ case 308:
+ return 308
+ case 309:
+ return 309
+ case 310:
+ return 310
+ case 311:
+ return 311
+ case 312:
+ return 312
+ case 313:
+ return 313
+ case 314:
+ return 314
+ case 315:
+ return 315
+ case 316:
+ return 316
+ case 317:
+ return 317
+ case 318:
+ return 318
+ case 319:
+ return 319
+ case 320:
+ return 320
+ case 321:
+ return 321
+ case 322:
+ return 322
+ case 323:
+ return 323
+ case 324:
+ return 324
+ case 325:
+ return 325
+ case 326:
+ return 326
+ case 327:
+ return 327
+ case 328:
+ return 328
+ case 329:
+ return 329
+ case 330:
+ return 330
+ case 331:
+ return 331
+ case 332:
+ return 332
+ case 333:
+ return 333
+ case 334:
+ return 334
+ case 335:
+ return 335
+ case 336:
+ return 336
+ case 337:
+ return 337
+ case 338:
+ return 338
+ case 339:
+ return 339
+ case 340:
+ return 340
+ case 341:
+ return 341
+ case 342:
+ return 342
+ case 343:
+ return 343
+ case 344:
+ return 344
+ case 345:
+ return 345
+ case 346:
+ return 346
+ case 347:
+ return 347
+ case 348:
+ return 348
+ case 349:
+ return 349
+ case 350:
+ return 350
+ case 351:
+ return 351
+ case 352:
+ return 352
+ case 353:
+ return 353
+ case 354:
+ return 354
+ case 355:
+ return 355
+ case 356:
+ return 356
+ case 357:
+ return 357
+ case 358:
+ return 358
+ case 359:
+ return 359
+ case 360:
+ return 360
+ case 361:
+ return 361
+ case 362:
+ return 362
+ case 363:
+ return 363
+ case 364:
+ return 364
+ case 365:
+ return 365
+ case 366:
+ return 366
+ case 367:
+ return 367
+ case 368:
+ return 368
+ case 369:
+ return 369
+ case 370:
+ return 370
+ case 371:
+ return 371
+ case 372:
+ return 372
+ case 373:
+ return 373
+ case 374:
+ return 374
+ case 375:
+ return 375
+ case 376:
+ return 376
+ case 377:
+ return 377
+ case 378:
+ return 378
+ case 379:
+ return 379
+ case 380:
+ return 380
+ case 381:
+ return 381
+ case 382:
+ return 382
+ case 383:
+ return 383
+ case 384:
+ return 384
+ case 385:
+ return 385
+ case 386:
+ return 386
+ case 387:
+ return 387
+ case 388:
+ return 388
+ case 389:
+ return 389
+ case 390:
+ return 390
+ case 391:
+ return 391
+ case 392:
+ return 392
+ case 393:
+ return 393
+ case 394:
+ return 394
+ case 395:
+ return 395
+ case 396:
+ return 396
+ case 397:
+ return 397
+ case 398:
+ return 398
+ case 399:
+ return 399
+ case 400:
+ return 400
+ case 401:
+ return 401
+ case 402:
+ return 402
+ case 403:
+ return 403
+ case 404:
+ return 404
+ case 405:
+ return 405
+ case 406:
+ return 406
+ case 407:
+ return 407
+ case 408:
+ return 408
+ case 409:
+ return 409
+ case 410:
+ return 410
+ case 411:
+ return 411
+ case 412:
+ return 412
+ case 413:
+ return 413
+ case 414:
+ return 414
+ case 415:
+ return 415
+ case 416:
+ return 416
+ case 417:
+ return 417
+ case 418:
+ return 418
+ case 419:
+ return 419
+ case 420:
+ return 420
+ case 421:
+ return 421
+ case 422:
+ return 422
+ case 423:
+ return 423
+ case 424:
+ return 424
+ case 425:
+ return 425
+ case 426:
+ return 426
+ case 427:
+ return 427
+ case 428:
+ return 428
+ case 429:
+ return 429
+ case 430:
+ return 430
+ case 431:
+ return 431
+ case 432:
+ return 432
+ case 433:
+ return 433
+ case 434:
+ return 434
+ case 435:
+ return 435
+ case 436:
+ return 436
+ case 437:
+ return 437
+ case 438:
+ return 438
+ case 439:
+ return 439
+ case 440:
+ return 440
+ case 441:
+ return 441
+ case 442:
+ return 442
+ case 443:
+ return 443
+ case 444:
+ return 444
+ case 445:
+ return 445
+ case 446:
+ return 446
+ case 447:
+ return 447
+ case 448:
+ return 448
+ case 449:
+ return 449
+ case 450:
+ return 450
+ case 451:
+ return 451
+ case 452:
+ return 452
+ case 453:
+ return 453
+ case 454:
+ return 454
+ case 455:
+ return 455
+ case 456:
+ return 456
+ case 457:
+ return 457
+ case 458:
+ return 458
+ case 459:
+ return 459
+ case 460:
+ return 460
+ case 461:
+ return 461
+ case 462:
+ return 462
+ case 463:
+ return 463
+ case 464:
+ return 464
+ case 465:
+ return 465
+ case 466:
+ return 466
+ case 467:
+ return 467
+ case 468:
+ return 468
+ case 469:
+ return 469
+ case 470:
+ return 470
+ case 471:
+ return 471
+ case 472:
+ return 472
+ case 473:
+ return 473
+ case 474:
+ return 474
+ case 475:
+ return 475
+ case 476:
+ return 476
+ case 477:
+ return 477
+ case 478:
+ return 478
+ case 479:
+ return 479
+ case 480:
+ return 480
+ case 481:
+ return 481
+ case 482:
+ return 482
+ case 483:
+ return 483
+ case 484:
+ return 484
+ case 485:
+ return 485
+ case 486:
+ return 486
+ case 487:
+ return 487
+ case 488:
+ return 488
+ case 489:
+ return 489
+ case 490:
+ return 490
+ case 491:
+ return 491
+ case 492:
+ return 492
+ case 493:
+ return 493
+ case 494:
+ return 494
+ case 495:
+ return 495
+ case 496:
+ return 496
+ case 497:
+ return 497
+ case 498:
+ return 498
+ case 499:
+ return 499
+ case 500:
+ return 500
+ case 501:
+ return 501
+ case 502:
+ return 502
+ case 503:
+ return 503
+ case 504:
+ return 504
+ case 505:
+ return 505
+ case 506:
+ return 506
+ case 507:
+ return 507
+ case 508:
+ return 508
+ case 509:
+ return 509
+ case 510:
+ return 510
+ case 511:
+ return 511
+ case 512:
+ return 512
+ case 513:
+ return 513
+ case 514:
+ return 514
+ case 515:
+ return 515
+ case 516:
+ return 516
+ case 517:
+ return 517
+ case 518:
+ return 518
+ case 519:
+ return 519
+ case 520:
+ return 520
+ case 521:
+ return 521
+ case 522:
+ return 522
+ case 523:
+ return 523
+ case 524:
+ return 524
+ case 525:
+ return 525
+ case 526:
+ return 526
+ case 527:
+ return 527
+ case 528:
+ return 528
+ case 529:
+ return 529
+ case 530:
+ return 530
+ case 531:
+ return 531
+ case 532:
+ return 532
+ case 533:
+ return 533
+ case 534:
+ return 534
+ case 535:
+ return 535
+ case 536:
+ return 536
+ case 537:
+ return 537
+ case 538:
+ return 538
+ case 539:
+ return 539
+ case 540:
+ return 540
+ case 541:
+ return 541
+ case 542:
+ return 542
+ case 543:
+ return 543
+ case 544:
+ return 544
+ case 545:
+ return 545
+ case 546:
+ return 546
+ case 547:
+ return 547
+ case 548:
+ return 548
+ case 549:
+ return 549
+ case 550:
+ return 550
+ case 551:
+ return 551
+ case 552:
+ return 552
+ case 553:
+ return 553
+ case 554:
+ return 554
+ case 555:
+ return 555
+ case 556:
+ return 556
+ case 557:
+ return 557
+ case 558:
+ return 558
+ case 559:
+ return 559
+ case 560:
+ return 560
+ case 561:
+ return 561
+ case 562:
+ return 562
+ case 563:
+ return 563
+ case 564:
+ return 564
+ case 565:
+ return 565
+ case 566:
+ return 566
+ case 567:
+ return 567
+ case 568:
+ return 568
+ case 569:
+ return 569
+ case 570:
+ return 570
+ case 571:
+ return 571
+ case 572:
+ return 572
+ case 573:
+ return 573
+ case 574:
+ return 574
+ case 575:
+ return 575
+ case 576:
+ return 576
+ case 577:
+ return 577
+ case 578:
+ return 578
+ case 579:
+ return 579
+ case 580:
+ return 580
+ case 581:
+ return 581
+ case 582:
+ return 582
+ case 583:
+ return 583
+ case 584:
+ return 584
+ case 585:
+ return 585
+ case 586:
+ return 586
+ case 587:
+ return 587
+ case 588:
+ return 588
+ case 589:
+ return 589
+ case 590:
+ return 590
+ case 591:
+ return 591
+ case 592:
+ return 592
+ case 593:
+ return 593
+ case 594:
+ return 594
+ case 595:
+ return 595
+ case 596:
+ return 596
+ case 597:
+ return 597
+ case 598:
+ return 598
+ case 599:
+ return 599
+ case 600:
+ return 600
+ case 601:
+ return 601
+ case 602:
+ return 602
+ case 603:
+ return 603
+ case 604:
+ return 604
+ case 605:
+ return 605
+ case 606:
+ return 606
+ case 607:
+ return 607
+ case 608:
+ return 608
+ case 609:
+ return 609
+ case 610:
+ return 610
+ case 611:
+ return 611
+ case 612:
+ return 612
+ case 613:
+ return 613
+ case 614:
+ return 614
+ case 615:
+ return 615
+ case 616:
+ return 616
+ case 617:
+ return 617
+ case 618:
+ return 618
+ case 619:
+ return 619
+ case 620:
+ return 620
+ case 621:
+ return 621
+ case 622:
+ return 622
+ case 623:
+ return 623
+ case 624:
+ return 624
+ case 625:
+ return 625
+ case 626:
+ return 626
+ case 627:
+ return 627
+ case 628:
+ return 628
+ case 629:
+ return 629
+ case 630:
+ return 630
+ case 631:
+ return 631
+ case 632:
+ return 632
+ case 633:
+ return 633
+ case 634:
+ return 634
+ case 635:
+ return 635
+ case 636:
+ return 636
+ case 637:
+ return 637
+ case 638:
+ return 638
+ case 639:
+ return 639
+ case 640:
+ return 640
+ case 641:
+ return 641
+ case 642:
+ return 642
+ case 643:
+ return 643
+ case 644:
+ return 644
+ case 645:
+ return 645
+ case 646:
+ return 646
+ case 647:
+ return 647
+ case 648:
+ return 648
+ case 649:
+ return 649
+ case 650:
+ return 650
+ case 651:
+ return 651
+ case 652:
+ return 652
+ case 653:
+ return 653
+ case 654:
+ return 654
+ case 655:
+ return 655
+ case 656:
+ return 656
+ case 657:
+ return 657
+ case 658:
+ return 658
+ case 659:
+ return 659
+ case 660:
+ return 660
+ case 661:
+ return 661
+ case 662:
+ return 662
+ case 663:
+ return 663
+ case 664:
+ return 664
+ case 665:
+ return 665
+ case 666:
+ return 666
+ case 667:
+ return 667
+ case 668:
+ return 668
+ case 669:
+ return 669
+ case 670:
+ return 670
+ case 671:
+ return 671
+ case 672:
+ return 672
+ case 673:
+ return 673
+ case 674:
+ return 674
+ case 675:
+ return 675
+ case 676:
+ return 676
+ case 677:
+ return 677
+ case 678:
+ return 678
+ case 679:
+ return 679
+ case 680:
+ return 680
+ case 681:
+ return 681
+ case 682:
+ return 682
+ case 683:
+ return 683
+ case 684:
+ return 684
+ case 685:
+ return 685
+ case 686:
+ return 686
+ case 687:
+ return 687
+ case 688:
+ return 688
+ case 689:
+ return 689
+ case 690:
+ return 690
+ case 691:
+ return 691
+ case 692:
+ return 692
+ case 693:
+ return 693
+ case 694:
+ return 694
+ case 695:
+ return 695
+ case 696:
+ return 696
+ case 697:
+ return 697
+ case 698:
+ return 698
+ case 699:
+ return 699
+ case 700:
+ return 700
+ case 701:
+ return 701
+ case 702:
+ return 702
+ case 703:
+ return 703
+ case 704:
+ return 704
+ case 705:
+ return 705
+ case 706:
+ return 706
+ case 707:
+ return 707
+ case 708:
+ return 708
+ case 709:
+ return 709
+ case 710:
+ return 710
+ case 711:
+ return 711
+ case 712:
+ return 712
+ case 713:
+ return 713
+ case 714:
+ return 714
+ case 715:
+ return 715
+ case 716:
+ return 716
+ case 717:
+ return 717
+ case 718:
+ return 718
+ case 719:
+ return 719
+ case 720:
+ return 720
+ case 721:
+ return 721
+ case 722:
+ return 722
+ case 723:
+ return 723
+ case 724:
+ return 724
+ case 725:
+ return 725
+ case 726:
+ return 726
+ case 727:
+ return 727
+ case 728:
+ return 728
+ case 729:
+ return 729
+ case 730:
+ return 730
+ case 731:
+ return 731
+ case 732:
+ return 732
+ case 733:
+ return 733
+ case 734:
+ return 734
+ case 735:
+ return 735
+ case 736:
+ return 736
+ case 737:
+ return 737
+ case 738:
+ return 738
+ case 739:
+ return 739
+ case 740:
+ return 740
+ case 741:
+ return 741
+ case 742:
+ return 742
+ case 743:
+ return 743
+ case 744:
+ return 744
+ case 745:
+ return 745
+ case 746:
+ return 746
+ case 747:
+ return 747
+ case 748:
+ return 748
+ case 749:
+ return 749
+ case 750:
+ return 750
+ case 751:
+ return 751
+ case 752:
+ return 752
+ case 753:
+ return 753
+ case 754:
+ return 754
+ case 755:
+ return 755
+ case 756:
+ return 756
+ case 757:
+ return 757
+ case 758:
+ return 758
+ case 759:
+ return 759
+ case 760:
+ return 760
+ case 761:
+ return 761
+ case 762:
+ return 762
+ case 763:
+ return 763
+ case 764:
+ return 764
+ case 765:
+ return 765
+ case 766:
+ return 766
+ case 767:
+ return 767
+ case 768:
+ return 768
+ case 769:
+ return 769
+ case 770:
+ return 770
+ case 771:
+ return 771
+ case 772:
+ return 772
+ case 773:
+ return 773
+ case 774:
+ return 774
+ case 775:
+ return 775
+ case 776:
+ return 776
+ case 777:
+ return 777
+ case 778:
+ return 778
+ case 779:
+ return 779
+ case 780:
+ return 780
+ case 781:
+ return 781
+ case 782:
+ return 782
+ case 783:
+ return 783
+ case 784:
+ return 784
+ case 785:
+ return 785
+ case 786:
+ return 786
+ case 787:
+ return 787
+ case 788:
+ return 788
+ case 789:
+ return 789
+ case 790:
+ return 790
+ case 791:
+ return 791
+ case 792:
+ return 792
+ case 793:
+ return 793
+ case 794:
+ return 794
+ case 795:
+ return 795
+ case 796:
+ return 796
+ case 797:
+ return 797
+ case 798:
+ return 798
+ case 799:
+ return 799
+ case 800:
+ return 800
+ case 801:
+ return 801
+ case 802:
+ return 802
+ case 803:
+ return 803
+ case 804:
+ return 804
+ case 805:
+ return 805
+ case 806:
+ return 806
+ case 807:
+ return 807
+ case 808:
+ return 808
+ case 809:
+ return 809
+ case 810:
+ return 810
+ case 811:
+ return 811
+ case 812:
+ return 812
+ case 813:
+ return 813
+ case 814:
+ return 814
+ case 815:
+ return 815
+ case 816:
+ return 816
+ case 817:
+ return 817
+ case 818:
+ return 818
+ case 819:
+ return 819
+ case 820:
+ return 820
+ case 821:
+ return 821
+ case 822:
+ return 822
+ case 823:
+ return 823
+ case 824:
+ return 824
+ case 825:
+ return 825
+ case 826:
+ return 826
+ case 827:
+ return 827
+ case 828:
+ return 828
+ case 829:
+ return 829
+ case 830:
+ return 830
+ case 831:
+ return 831
+ case 832:
+ return 832
+ case 833:
+ return 833
+ case 834:
+ return 834
+ case 835:
+ return 835
+ case 836:
+ return 836
+ case 837:
+ return 837
+ case 838:
+ return 838
+ case 839:
+ return 839
+ case 840:
+ return 840
+ case 841:
+ return 841
+ case 842:
+ return 842
+ case 843:
+ return 843
+ case 844:
+ return 844
+ case 845:
+ return 845
+ case 846:
+ return 846
+ case 847:
+ return 847
+ case 848:
+ return 848
+ case 849:
+ return 849
+ case 850:
+ return 850
+ case 851:
+ return 851
+ case 852:
+ return 852
+ case 853:
+ return 853
+ case 854:
+ return 854
+ case 855:
+ return 855
+ case 856:
+ return 856
+ case 857:
+ return 857
+ case 858:
+ return 858
+ case 859:
+ return 859
+ case 860:
+ return 860
+ case 861:
+ return 861
+ case 862:
+ return 862
+ case 863:
+ return 863
+ case 864:
+ return 864
+ case 865:
+ return 865
+ case 866:
+ return 866
+ case 867:
+ return 867
+ case 868:
+ return 868
+ case 869:
+ return 869
+ case 870:
+ return 870
+ case 871:
+ return 871
+ case 872:
+ return 872
+ case 873:
+ return 873
+ case 874:
+ return 874
+ case 875:
+ return 875
+ case 876:
+ return 876
+ case 877:
+ return 877
+ case 878:
+ return 878
+ case 879:
+ return 879
+ case 880:
+ return 880
+ case 881:
+ return 881
+ case 882:
+ return 882
+ case 883:
+ return 883
+ case 884:
+ return 884
+ case 885:
+ return 885
+ case 886:
+ return 886
+ case 887:
+ return 887
+ case 888:
+ return 888
+ case 889:
+ return 889
+ case 890:
+ return 890
+ case 891:
+ return 891
+ case 892:
+ return 892
+ case 893:
+ return 893
+ case 894:
+ return 894
+ case 895:
+ return 895
+ case 896:
+ return 896
+ case 897:
+ return 897
+ case 898:
+ return 898
+ case 899:
+ return 899
+ case 900:
+ return 900
+ case 901:
+ return 901
+ case 902:
+ return 902
+ case 903:
+ return 903
+ case 904:
+ return 904
+ case 905:
+ return 905
+ case 906:
+ return 906
+ case 907:
+ return 907
+ case 908:
+ return 908
+ case 909:
+ return 909
+ case 910:
+ return 910
+ case 911:
+ return 911
+ case 912:
+ return 912
+ case 913:
+ return 913
+ case 914:
+ return 914
+ case 915:
+ return 915
+ case 916:
+ return 916
+ case 917:
+ return 917
+ case 918:
+ return 918
+ case 919:
+ return 919
+ case 920:
+ return 920
+ case 921:
+ return 921
+ case 922:
+ return 922
+ case 923:
+ return 923
+ case 924:
+ return 924
+ case 925:
+ return 925
+ case 926:
+ return 926
+ case 927:
+ return 927
+ case 928:
+ return 928
+ case 929:
+ return 929
+ case 930:
+ return 930
+ case 931:
+ return 931
+ case 932:
+ return 932
+ case 933:
+ return 933
+ case 934:
+ return 934
+ case 935:
+ return 935
+ case 936:
+ return 936
+ case 937:
+ return 937
+ case 938:
+ return 938
+ case 939:
+ return 939
+ case 940:
+ return 940
+ case 941:
+ return 941
+ case 942:
+ return 942
+ case 943:
+ return 943
+ case 944:
+ return 944
+ case 945:
+ return 945
+ case 946:
+ return 946
+ case 947:
+ return 947
+ case 948:
+ return 948
+ case 949:
+ return 949
+ case 950:
+ return 950
+ case 951:
+ return 951
+ case 952:
+ return 952
+ case 953:
+ return 953
+ case 954:
+ return 954
+ case 955:
+ return 955
+ case 956:
+ return 956
+ case 957:
+ return 957
+ case 958:
+ return 958
+ case 959:
+ return 959
+ case 960:
+ return 960
+ case 961:
+ return 961
+ case 962:
+ return 962
+ case 963:
+ return 963
+ case 964:
+ return 964
+ case 965:
+ return 965
+ case 966:
+ return 966
+ case 967:
+ return 967
+ case 968:
+ return 968
+ case 969:
+ return 969
+ case 970:
+ return 970
+ case 971:
+ return 971
+ case 972:
+ return 972
+ case 973:
+ return 973
+ case 974:
+ return 974
+ case 975:
+ return 975
+ case 976:
+ return 976
+ case 977:
+ return 977
+ case 978:
+ return 978
+ case 979:
+ return 979
+ case 980:
+ return 980
+ case 981:
+ return 981
+ case 982:
+ return 982
+ case 983:
+ return 983
+ case 984:
+ return 984
+ case 985:
+ return 985
+ case 986:
+ return 986
+ case 987:
+ return 987
+ case 988:
+ return 988
+ case 989:
+ return 989
+ case 990:
+ return 990
+ case 991:
+ return 991
+ case 992:
+ return 992
+ case 993:
+ return 993
+ case 994:
+ return 994
+ case 995:
+ return 995
+ case 996:
+ return 996
+ case 997:
+ return 997
+ case 998:
+ return 998
+ case 999:
+ return 999
+ }
+ return 0
+}
diff --git a/test/fixedbugs/issue60990.go b/test/fixedbugs/issue60990.go
new file mode 100644
index 0000000000..ce94fa7197
--- /dev/null
+++ b/test/fixedbugs/issue60990.go
@@ -0,0 +1,31 @@
+// compile
+
+// 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 p
+
+type T struct{ _, _ []int }
+
+func F[_ int]() {
+ var f0, f1 float64
+ var b bool
+ _ = func(T, float64) bool {
+ b = deepEqual(0, 1)
+ return func() bool {
+ f1 = min(f0, 0)
+ return b
+ }()
+ }(T{nil, nil}, min(0, f1))
+ f0 = min(0, 1)
+}
+
+//go:noinline
+func deepEqual(x, y any) bool {
+ return x == y
+}
+
+func init() {
+ F[int]()
+}
diff --git a/test/fixedbugs/issue60991.go b/test/fixedbugs/issue60991.go
new file mode 100644
index 0000000000..e1d51e4300
--- /dev/null
+++ b/test/fixedbugs/issue60991.go
@@ -0,0 +1,13 @@
+// build
+
+// 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 p
+
+import "math"
+
+func f() {
+ _ = min(0.1, 0.2, math.Sqrt(1))
+}
diff --git a/test/fixedbugs/issue61127.go b/test/fixedbugs/issue61127.go
new file mode 100644
index 0000000000..c8ee5c5ee4
--- /dev/null
+++ b/test/fixedbugs/issue61127.go
@@ -0,0 +1,13 @@
+// compile
+
+// 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 main
+
+var V = []struct{}{}
+
+func main() {
+ clear(V)
+}
diff --git a/test/fixedbugs/issue61187.go b/test/fixedbugs/issue61187.go
new file mode 100644
index 0000000000..5e1762808d
--- /dev/null
+++ b/test/fixedbugs/issue61187.go
@@ -0,0 +1,22 @@
+// compile
+
+// 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 main
+
+import (
+ "fmt"
+ "reflect"
+ "unsafe"
+)
+
+var slice = []byte{'H', 'e', 'l', 'l', 'o', ','}
+
+func main() {
+ ptr := uintptr(unsafe.Pointer(&slice)) + 100
+ header := (*reflect.SliceHeader)(unsafe.Pointer(ptr))
+ header.Data += 1
+ fmt.Printf("%d %d\n", cap(slice), header.Cap)
+}
diff --git a/test/for.go b/test/for.go
index 8a50090657..cfb7f6dad2 100644
--- a/test/for.go
+++ b/test/for.go
@@ -44,15 +44,33 @@ func main() {
for sum < 100 {
sum = sum + 9
}
- assertequal(sum, 99 + 9, "only one")
+ assertequal(sum, 99+9, "only one")
sum = 0
for i := 0; i <= 10; i++ {
- if i % 2 == 0 {
+ if i%2 == 0 {
continue
}
sum = sum + i
}
assertequal(sum, 1+3+5+7+9, "continue")
+ i = 0
+ for i = range [5]struct{}{} {
+ }
+ assertequal(i, 4, " incorrect index value after range loop")
+
+ i = 0
+ var a1 [5]struct{}
+ for i = range a1 {
+ a1[i] = struct{}{}
+ }
+ assertequal(i, 4, " incorrect index value after array with zero size elem range clear")
+
+ i = 0
+ var a2 [5]int
+ for i = range a2 {
+ a2[i] = 0
+ }
+ assertequal(i, 4, " incorrect index value after array range clear")
}