From b691da9f788f27eb3d5035f3dbdc15c107d71ef9 Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Fri, 31 May 2024 15:08:45 +0000 Subject: [PATCH 01/41] Revert "crypto/x509: reject serial numbers longer than 20 octets" This reverts commit 8524931a2cdc6a57afdf6f4b3375cb261c2557da. Reason for revert: It turns out, basically no one in private PKIs can get this right. It causes way too much breakage, and every other impl also ignores it, so we'll continue to be in good company. Change-Id: I2da808b411ec12f72112c49079faf9f68ae465c9 Reviewed-on: https://go-review.googlesource.com/c/go/+/589615 LUCI-TryBot-Result: Go LUCI Reviewed-by: Damien Neil --- doc/godebug.md | 5 ----- src/crypto/x509/parser.go | 24 +----------------------- src/crypto/x509/x509_test.go | 23 ----------------------- src/internal/godebugs/table.go | 1 - src/runtime/metrics/doc.go | 5 ----- 5 files changed, 1 insertion(+), 57 deletions(-) diff --git a/doc/godebug.md b/doc/godebug.md index 41f88caa013606..86e02e820cd855 100644 --- a/doc/godebug.md +++ b/doc/godebug.md @@ -185,11 +185,6 @@ Go 1.23 changed the behavior of serial numbers that are negative. This change can be reverted with the [`x509negativeserial` setting](/pkg/crypto/x509/#ParseCertificate). -Go 1.23 changed the behavior of -[crypto/x509.ParseCertificate](/pkg/crypto/x509/#ParseCertificate) to reject -serial numbers that are longer than 20 octets. This change can be reverted with -the [`x509seriallength` setting](/pkg/crypto/x509/#ParseCertificate). - Go 1.23 re-enabled support in html/template for ECMAScript 6 template literals by default. The [`jstmpllitinterp` setting](/pkg/html/template#hdr-Security_Model) no longer has any effect. diff --git a/src/crypto/x509/parser.go b/src/crypto/x509/parser.go index 5cc0c7742e44df..3ba5f6a4e1dc61 100644 --- a/src/crypto/x509/parser.go +++ b/src/crypto/x509/parser.go @@ -825,7 +825,6 @@ func processExtensions(out *Certificate) error { } var x509negativeserial = godebug.New("x509negativeserial") -var x509seriallength = godebug.New("x509seriallength") func parseCertificate(der []byte) (*Certificate, error) { cert := &Certificate{} @@ -866,27 +865,10 @@ func parseCertificate(der []byte) (*Certificate, error) { return nil, errors.New("x509: invalid version") } - var serialBytes cryptobyte.String - if !tbs.ReadASN1Element(&serialBytes, cryptobyte_asn1.INTEGER) { - return nil, errors.New("x509: malformed serial number") - } - // We add two bytes for the tag and length (if the length was multi-byte, - // which is possible, the length of the serial would be more than 256 bytes, - // so this condition would trigger anyway). - if len(serialBytes) > 20+2 { - if x509seriallength.Value() != "1" { - return nil, errors.New("x509: serial number too long (>20 octets)") - } else { - x509seriallength.IncNonDefault() - } - } serial := new(big.Int) - if !serialBytes.ReadASN1Integer(serial) { + if !tbs.ReadASN1Integer(serial) { return nil, errors.New("x509: malformed serial number") } - // We do not reject zero serials, because they are unfortunately common - // in important root certificates which will not expire for a number of - // years. if serial.Sign() == -1 { if x509negativeserial.Value() != "1" { return nil, errors.New("x509: negative serial number") @@ -1034,10 +1016,6 @@ func parseCertificate(der []byte) (*Certificate, error) { // Before Go 1.23, ParseCertificate accepted certificates with negative serial // numbers. This behavior can be restored by including "x509negativeserial=1" in // the GODEBUG environment variable. -// -// Before Go 1.23, ParseCertificate accepted certificates with serial numbers -// longer than 20 octets. This behavior can be restored by including -// "x509seriallength=1" in the GODEBUG environment variable. func ParseCertificate(der []byte) (*Certificate, error) { cert, err := parseCertificate(der) if err != nil { diff --git a/src/crypto/x509/x509_test.go b/src/crypto/x509/x509_test.go index d40fd836e01960..a9483b7091acc5 100644 --- a/src/crypto/x509/x509_test.go +++ b/src/crypto/x509/x509_test.go @@ -4086,26 +4086,3 @@ func TestRejectCriticalSKI(t *testing.T) { t.Fatalf("ParseCertificate() unexpected error: %v, want: %s", err, expectedErr) } } - -func TestSerialTooLong(t *testing.T) { - template := Certificate{ - Subject: pkix.Name{CommonName: "Cert"}, - NotBefore: time.Unix(1000, 0), - NotAfter: time.Unix(100000, 0), - } - for _, serial := range []*big.Int{ - big.NewInt(0).SetBytes(bytes.Repeat([]byte{5}, 21)), - big.NewInt(0).SetBytes(bytes.Repeat([]byte{255}, 20)), - } { - template.SerialNumber = serial - certDER, err := CreateCertificate(rand.Reader, &template, &template, rsaPrivateKey.Public(), rsaPrivateKey) - if err != nil { - t.Fatalf("CreateCertificate() unexpected error: %v", err) - } - expectedErr := "x509: serial number too long (>20 octets)" - _, err = ParseCertificate(certDER) - if err == nil || err.Error() != expectedErr { - t.Fatalf("ParseCertificate() unexpected error: %v, want: %s", err, expectedErr) - } - } -} diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go index b44fc7874f02a6..eb512559168c32 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go @@ -57,7 +57,6 @@ var All = []Info{ {Name: "winsymlink", Package: "os", Changed: 22, Old: "0"}, {Name: "x509keypairleaf", Package: "crypto/tls", Changed: 23, Old: "0"}, {Name: "x509negativeserial", Package: "crypto/x509", Changed: 23, Old: "1"}, - {Name: "x509seriallength", Package: "crypto/x509", Changed: 23, Old: "1"}, {Name: "x509sha1", Package: "crypto/x509"}, {Name: "x509usefallbackroots", Package: "crypto/x509"}, {Name: "x509usepolicies", Package: "crypto/x509"}, diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go index 85db5742d9defc..c1d0ca90727e84 100644 --- a/src/runtime/metrics/doc.go +++ b/src/runtime/metrics/doc.go @@ -340,11 +340,6 @@ Below is the full list of supported metrics, ordered lexicographically. package due to a non-default GODEBUG=x509negativeserial=... setting. - /godebug/non-default-behavior/x509seriallength:events - The number of non-default behaviors executed by the crypto/x509 - package due to a non-default GODEBUG=x509seriallength=... - setting. - /godebug/non-default-behavior/x509sha1:events The number of non-default behaviors executed by the crypto/x509 package due to a non-default GODEBUG=x509sha1=... setting. From e44fa1c1a9139ad457d8fa84a68afa3f40e7732a Mon Sep 17 00:00:00 2001 From: Sam Thanawalla Date: Mon, 20 May 2024 20:43:39 +0000 Subject: [PATCH 02/41] cmd/go: fix go list -u -m all with too new retractions dependency Previously, go would not report retractions of dependencies that have a newer version of Go. With this change, we will still display retractions despite a version difference when go list -u -m is used. Fixes: #66403 Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest,gotip-windows-amd64-longtest Change-Id: I6406680235e294269836ae4cbe3d5680ca10eea0 Reviewed-on: https://go-review.googlesource.com/c/go/+/588775 Auto-Submit: Sam Thanawalla Reviewed-by: Michael Matloob LUCI-TryBot-Result: Go LUCI --- src/cmd/go/internal/modload/modfile.go | 23 ++++++++++++------- ...mple.com_retract_newergoversion_v1.0.0.txt | 10 ++++++++ ...mple.com_retract_newergoversion_v1.2.0.txt | 12 ++++++++++ .../script/list_retractions_issue66403.txt | 20 ++++++++++++++++ 4 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 src/cmd/go/testdata/mod/example.com_retract_newergoversion_v1.0.0.txt create mode 100644 src/cmd/go/testdata/mod/example.com_retract_newergoversion_v1.2.0.txt create mode 100644 src/cmd/go/testdata/script/list_retractions_issue66403.txt diff --git a/src/cmd/go/internal/modload/modfile.go b/src/cmd/go/internal/modload/modfile.go index 899f1b3d09aca5..1d6b28db19ebd6 100644 --- a/src/cmd/go/internal/modload/modfile.go +++ b/src/cmd/go/internal/modload/modfile.go @@ -190,7 +190,7 @@ func CheckRetractions(ctx context.Context, m module.Version) (err error) { return err } summary, err := rawGoModSummary(rm) - if err != nil { + if err != nil && !errors.Is(err, gover.ErrTooNew) { return err } @@ -298,7 +298,7 @@ func CheckDeprecation(ctx context.Context, m module.Version) (deprecation string return "", err } summary, err := rawGoModSummary(latest) - if err != nil { + if err != nil && !errors.Is(err, gover.ErrTooNew) { return "", err } return summary.deprecated, nil @@ -644,6 +644,8 @@ func goModSummary(m module.Version) (*modFileSummary, error) { // its dependencies. // // rawGoModSummary cannot be used on the main module outside of workspace mode. +// The modFileSummary can still be used for retractions and deprecations +// even if a TooNewError is returned. func rawGoModSummary(m module.Version) (*modFileSummary, error) { if gover.IsToolchain(m.Path) { if m.Path == "go" && gover.Compare(m.Version, gover.GoStrictVersion) >= 0 { @@ -698,12 +700,7 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) { summary.require = append(summary.require, req.Mod) } } - if summary.goVersion != "" && gover.Compare(summary.goVersion, gover.GoStrictVersion) >= 0 { - if gover.Compare(summary.goVersion, gover.Local()) > 0 { - return nil, &gover.TooNewError{What: "module " + m.String(), GoVersion: summary.goVersion} - } - summary.require = append(summary.require, module.Version{Path: "go", Version: summary.goVersion}) - } + if len(f.Retract) > 0 { summary.retract = make([]retraction, 0, len(f.Retract)) for _, ret := range f.Retract { @@ -714,6 +711,16 @@ func rawGoModSummary(m module.Version) (*modFileSummary, error) { } } + // This block must be kept at the end of the function because the summary may + // be used for reading retractions or deprecations even if a TooNewError is + // returned. + if summary.goVersion != "" && gover.Compare(summary.goVersion, gover.GoStrictVersion) >= 0 { + summary.require = append(summary.require, module.Version{Path: "go", Version: summary.goVersion}) + if gover.Compare(summary.goVersion, gover.Local()) > 0 { + return summary, &gover.TooNewError{What: "module " + m.String(), GoVersion: summary.goVersion} + } + } + return summary, nil }) } diff --git a/src/cmd/go/testdata/mod/example.com_retract_newergoversion_v1.0.0.txt b/src/cmd/go/testdata/mod/example.com_retract_newergoversion_v1.0.0.txt new file mode 100644 index 00000000000000..21d53529842e8e --- /dev/null +++ b/src/cmd/go/testdata/mod/example.com_retract_newergoversion_v1.0.0.txt @@ -0,0 +1,10 @@ +-- .mod -- +module example.com/retract/newergoversion + +go 1.21 + +-- .info -- +{"Version":"v1.0.0"} + +-- retract.go -- +package newergoversion \ No newline at end of file diff --git a/src/cmd/go/testdata/mod/example.com_retract_newergoversion_v1.2.0.txt b/src/cmd/go/testdata/mod/example.com_retract_newergoversion_v1.2.0.txt new file mode 100644 index 00000000000000..7aa28b90e3ab9b --- /dev/null +++ b/src/cmd/go/testdata/mod/example.com_retract_newergoversion_v1.2.0.txt @@ -0,0 +1,12 @@ +-- .mod -- +module example.com/retract/newergoversion + +go 1.23 + +retract v1.2.0 + +-- .info -- +{"Version":"v1.2.0"} + +-- retract.go -- +package newergoversion diff --git a/src/cmd/go/testdata/script/list_retractions_issue66403.txt b/src/cmd/go/testdata/script/list_retractions_issue66403.txt new file mode 100644 index 00000000000000..717d129d4cd4fa --- /dev/null +++ b/src/cmd/go/testdata/script/list_retractions_issue66403.txt @@ -0,0 +1,20 @@ +# For issue #66403, go list -u -m all should not fail if a module +# with retractions has a newer version. + +env TESTGO_VERSION=go1.21 +env TESTGO_VERSION_SWITCH=switch +go list -u -m example.com/retract/newergoversion +stdout 'example.com/retract/newergoversion v1.0.0' +! stdout 'v1.2.0' + +-- go.mod -- +module example.com/m + +go 1.22 + +require example.com/retract/newergoversion v1.0.0 + +-- main.go -- +package main + +import _ "example.com/retract/newergoversion" \ No newline at end of file From 4cf2b02548e7c85d57b35a23c7fda96b44f2cbfc Mon Sep 17 00:00:00 2001 From: Roland Shoemaker Date: Wed, 20 Mar 2024 16:09:10 -0700 Subject: [PATCH 03/41] misc/ios: rework exec wrapper to only support simulator This updates the tools used to execute Go binaries on the Apple iOS Simulator to (a) work with newer arm64 macOS, (b) remove support for running binaries on physical devices, and (c) remove the reliance on LLDB and third-party Python packages. This makes the wrapper somewhat simpler, and easier to understand and maintain. Additionally clangwrap.sh is updated to reflect dropping support for targeting physical devices. This smoothes out the path for #66360. Change-Id: I769127e65f5e8c6c727841168890fd8557fb0e1d Reviewed-on: https://go-review.googlesource.com/c/go/+/573175 Reviewed-by: Michael Knyszek LUCI-TryBot-Result: Go LUCI Reviewed-by: Cherry Mui --- misc/ios/clangwrap.sh | 19 +- misc/ios/go_ios_exec.go | 569 +--------------------------------------- 2 files changed, 23 insertions(+), 565 deletions(-) diff --git a/misc/ios/clangwrap.sh b/misc/ios/clangwrap.sh index 8f7b439315bff7..16a35f409e7f4e 100755 --- a/misc/ios/clangwrap.sh +++ b/misc/ios/clangwrap.sh @@ -1,19 +1,22 @@ #!/bin/sh -# This uses the latest available iOS SDK, which is recommended. -# To select a specific SDK, run 'xcodebuild -showsdks' -# to see the available SDKs and replace iphoneos with one of them. + +# This script configures clang to target the iOS simulator. If you'd like to +# build for real iOS devices, change SDK to "iphoneos" and PLATFORM to "ios". +# This uses the latest available iOS SDK, which is recommended. To select a +# specific SDK, run 'xcodebuild -showsdks' to see the available SDKs and replace +# iphonesimulator with one of them. + +SDK=iphonesimulator +PLATFORM=ios-simulator + if [ "$GOARCH" == "arm64" ]; then - SDK=iphoneos - PLATFORM=ios CLANGARCH="arm64" else - SDK=iphonesimulator - PLATFORM=ios-simulator CLANGARCH="x86_64" fi SDK_PATH=`xcrun --sdk $SDK --show-sdk-path` -export IPHONEOS_DEPLOYMENT_TARGET=5.1 + # cmd/cgo doesn't support llvm-gcc-4.2, so we have to use clang. CLANG=`xcrun --sdk $SDK --find clang` diff --git a/misc/ios/go_ios_exec.go b/misc/ios/go_ios_exec.go index c275dd339cc9bd..b21ce1aaf3f0cc 100644 --- a/misc/ios/go_ios_exec.go +++ b/misc/ios/go_ios_exec.go @@ -1,44 +1,21 @@ -// Copyright 2015 The Go Authors. All rights reserved. +// Copyright 2024 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -// This program can be used as go_ios_$GOARCH_exec by the Go tool. -// It executes binaries on an iOS device using the XCode toolchain -// and the ios-deploy program: https://github.com/phonegap/ios-deploy -// -// This script supports an extra flag, -lldb, that pauses execution -// just before the main program begins and allows the user to control -// the remote lldb session. This flag is appended to the end of the -// script's arguments and is not passed through to the underlying -// binary. -// -// This script requires that three environment variables be set: -// -// GOIOS_DEV_ID: The codesigning developer id or certificate identifier -// GOIOS_APP_ID: The provisioning app id prefix. Must support wildcard app ids. -// GOIOS_TEAM_ID: The team id that owns the app id prefix. -// -// $GOROOT/misc/ios contains a script, detect.go, that attempts to autodetect these. +// This program can be used as go_ios_$GOARCH_exec by the Go tool. It executes +// binaries on the iOS Simulator using the XCode toolchain. package main import ( - "bytes" - "encoding/xml" - "errors" "fmt" "go/build" - "io" "log" - "net" "os" "os/exec" - "os/signal" "path/filepath" "runtime" - "strconv" "strings" "syscall" - "time" ) const debug = false @@ -110,18 +87,8 @@ func runMain() (int, error) { return 1, err } - if goarch := os.Getenv("GOARCH"); goarch == "arm64" { - err = runOnDevice(appdir) - } else { - err = runOnSimulator(appdir) - } + err = runOnSimulator(appdir) if err != nil { - // If the lldb driver completed with an exit code, use that. - if err, ok := err.(*exec.ExitError); ok { - if ws, ok := err.Sys().(interface{ ExitStatus() int }); ok { - return ws.ExitStatus(), nil - } - } return 1, err } return 0, nil @@ -135,61 +102,6 @@ func runOnSimulator(appdir string) error { return runSimulator(appdir, bundleID, os.Args[2:]) } -func runOnDevice(appdir string) error { - // e.g. B393DDEB490947F5A463FD074299B6C0AXXXXXXX - devID = getenv("GOIOS_DEV_ID") - - // e.g. Z8B3JBXXXX.org.golang.sample, Z8B3JBXXXX prefix is available at - // https://developer.apple.com/membercenter/index.action#accountSummary as Team ID. - appID = getenv("GOIOS_APP_ID") - - // e.g. Z8B3JBXXXX, available at - // https://developer.apple.com/membercenter/index.action#accountSummary as Team ID. - teamID = getenv("GOIOS_TEAM_ID") - - // Device IDs as listed with ios-deploy -c. - deviceID = os.Getenv("GOIOS_DEVICE_ID") - - if _, id, ok := strings.Cut(appID, "."); ok { - bundleID = id - } - - if err := signApp(appdir); err != nil { - return err - } - - if err := uninstallDevice(bundleID); err != nil { - return err - } - - if err := installDevice(appdir); err != nil { - return err - } - - if err := mountDevImage(); err != nil { - return err - } - - // Kill any hanging debug bridges that might take up port 3222. - exec.Command("killall", "idevicedebugserverproxy").Run() - - closer, err := startDebugBridge() - if err != nil { - return err - } - defer closer() - - return runDevice(appdir, bundleID, os.Args[2:]) -} - -func getenv(envvar string) string { - s := os.Getenv(envvar) - if s == "" { - log.Fatalf("%s not set\nrun $GOROOT/misc/ios/detect.go to attempt to autodetect", envvar) - } - return s -} - func assembleApp(appdir, bin string) error { if err := os.MkdirAll(appdir, 0755); err != nil { return err @@ -217,236 +129,6 @@ func assembleApp(appdir, bin string) error { return nil } -func signApp(appdir string) error { - entitlementsPath := filepath.Join(tmpdir, "Entitlements.plist") - cmd := exec.Command( - "codesign", - "-f", - "-s", devID, - "--entitlements", entitlementsPath, - appdir, - ) - if debug { - log.Println(strings.Join(cmd.Args, " ")) - } - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - return fmt.Errorf("codesign: %v", err) - } - return nil -} - -// mountDevImage ensures a developer image is mounted on the device. -// The image contains the device lldb server for idevicedebugserverproxy -// to connect to. -func mountDevImage() error { - // Check for existing mount. - cmd := idevCmd(exec.Command("ideviceimagemounter", "-l", "-x")) - out, err := cmd.CombinedOutput() - if err != nil { - os.Stderr.Write(out) - return fmt.Errorf("ideviceimagemounter: %v", err) - } - var info struct { - Dict struct { - Data []byte `xml:",innerxml"` - } `xml:"dict"` - } - if err := xml.Unmarshal(out, &info); err != nil { - return fmt.Errorf("mountDevImage: failed to decode mount information: %v", err) - } - dict, err := parsePlistDict(info.Dict.Data) - if err != nil { - return fmt.Errorf("mountDevImage: failed to parse mount information: %v", err) - } - if dict["ImagePresent"] == "true" && dict["Status"] == "Complete" { - return nil - } - // Some devices only give us an ImageSignature key. - if _, exists := dict["ImageSignature"]; exists { - return nil - } - // No image is mounted. Find a suitable image. - imgPath, err := findDevImage() - if err != nil { - return err - } - sigPath := imgPath + ".signature" - cmd = idevCmd(exec.Command("ideviceimagemounter", imgPath, sigPath)) - if out, err := cmd.CombinedOutput(); err != nil { - os.Stderr.Write(out) - return fmt.Errorf("ideviceimagemounter: %v", err) - } - return nil -} - -// findDevImage use the device iOS version and build to locate a suitable -// developer image. -func findDevImage() (string, error) { - cmd := idevCmd(exec.Command("ideviceinfo")) - out, err := cmd.Output() - if err != nil { - return "", fmt.Errorf("ideviceinfo: %v", err) - } - var iosVer, buildVer string - lines := bytes.Split(out, []byte("\n")) - for _, line := range lines { - key, val, ok := strings.Cut(string(line), ": ") - if !ok { - continue - } - switch key { - case "ProductVersion": - iosVer = val - case "BuildVersion": - buildVer = val - } - } - if iosVer == "" || buildVer == "" { - return "", errors.New("failed to parse ideviceinfo output") - } - verSplit := strings.Split(iosVer, ".") - if len(verSplit) > 2 { - // Developer images are specific to major.minor ios version. - // Cut off the patch version. - iosVer = strings.Join(verSplit[:2], ".") - } - sdkBase := "/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport" - patterns := []string{fmt.Sprintf("%s (%s)", iosVer, buildVer), fmt.Sprintf("%s (*)", iosVer), fmt.Sprintf("%s*", iosVer)} - for _, pattern := range patterns { - matches, err := filepath.Glob(filepath.Join(sdkBase, pattern, "DeveloperDiskImage.dmg")) - if err != nil { - return "", fmt.Errorf("findDevImage: %v", err) - } - if len(matches) > 0 { - return matches[0], nil - } - } - return "", fmt.Errorf("failed to find matching developer image for iOS version %s build %s", iosVer, buildVer) -} - -// startDebugBridge ensures that the idevicedebugserverproxy runs on -// port 3222. -func startDebugBridge() (func(), error) { - errChan := make(chan error, 1) - cmd := idevCmd(exec.Command("idevicedebugserverproxy", "3222")) - var stderr bytes.Buffer - cmd.Stderr = &stderr - if err := cmd.Start(); err != nil { - return nil, fmt.Errorf("idevicedebugserverproxy: %v", err) - } - go func() { - if err := cmd.Wait(); err != nil { - if _, ok := err.(*exec.ExitError); ok { - errChan <- fmt.Errorf("idevicedebugserverproxy: %s", stderr.Bytes()) - } else { - errChan <- fmt.Errorf("idevicedebugserverproxy: %v", err) - } - } - errChan <- nil - }() - closer := func() { - cmd.Process.Kill() - <-errChan - } - // Dial localhost:3222 to ensure the proxy is ready. - delay := time.Second / 4 - for attempt := 0; attempt < 5; attempt++ { - conn, err := net.DialTimeout("tcp", "localhost:3222", 5*time.Second) - if err == nil { - conn.Close() - return closer, nil - } - select { - case <-time.After(delay): - delay *= 2 - case err := <-errChan: - return nil, err - } - } - closer() - return nil, errors.New("failed to set up idevicedebugserverproxy") -} - -// findDeviceAppPath returns the device path to the app with the -// given bundle ID. It parses the output of ideviceinstaller -l -o xml, -// looking for the bundle ID and the corresponding Path value. -func findDeviceAppPath(bundleID string) (string, error) { - cmd := idevCmd(exec.Command("ideviceinstaller", "-l", "-o", "xml")) - out, err := cmd.CombinedOutput() - if err != nil { - os.Stderr.Write(out) - return "", fmt.Errorf("ideviceinstaller: -l -o xml %v", err) - } - var list struct { - Apps []struct { - Data []byte `xml:",innerxml"` - } `xml:"array>dict"` - } - if err := xml.Unmarshal(out, &list); err != nil { - return "", fmt.Errorf("failed to parse ideviceinstaller output: %v", err) - } - for _, app := range list.Apps { - values, err := parsePlistDict(app.Data) - if err != nil { - return "", fmt.Errorf("findDeviceAppPath: failed to parse app dict: %v", err) - } - if values["CFBundleIdentifier"] == bundleID { - if path, ok := values["Path"]; ok { - return path, nil - } - } - } - return "", fmt.Errorf("failed to find device path for bundle: %s", bundleID) -} - -// Parse an xml encoded plist. Plist values are mapped to string. -func parsePlistDict(dict []byte) (map[string]string, error) { - d := xml.NewDecoder(bytes.NewReader(dict)) - values := make(map[string]string) - var key string - var hasKey bool - for { - tok, err := d.Token() - if err == io.EOF { - break - } - if err != nil { - return nil, err - } - if tok, ok := tok.(xml.StartElement); ok { - if tok.Name.Local == "key" { - if err := d.DecodeElement(&key, &tok); err != nil { - return nil, err - } - hasKey = true - } else if hasKey { - var val string - var err error - switch n := tok.Name.Local; n { - case "true", "false": - // Bools are represented as and . - val = n - err = d.Skip() - default: - err = d.DecodeElement(&val, &tok) - } - if err != nil { - return nil, err - } - values[key] = val - hasKey = false - } else { - if err := d.Skip(); err != nil { - return nil, err - } - } - } - } - return values, nil -} - func installSimulator(appdir string) error { cmd := exec.Command( "xcrun", "simctl", "install", @@ -460,138 +142,20 @@ func installSimulator(appdir string) error { return nil } -func uninstallDevice(bundleID string) error { - cmd := idevCmd(exec.Command( - "ideviceinstaller", - "-U", bundleID, - )) - if out, err := cmd.CombinedOutput(); err != nil { - os.Stderr.Write(out) - return fmt.Errorf("ideviceinstaller -U %q: %s", bundleID, err) - } - return nil -} - -func installDevice(appdir string) error { - attempt := 0 - for { - cmd := idevCmd(exec.Command( - "ideviceinstaller", - "-i", appdir, - )) - if out, err := cmd.CombinedOutput(); err != nil { - // Sometimes, installing the app fails for some reason. - // Give the device a few seconds and try again. - if attempt < 5 { - time.Sleep(5 * time.Second) - attempt++ - continue - } - os.Stderr.Write(out) - return fmt.Errorf("ideviceinstaller -i %q: %v (%d attempts)", appdir, err, attempt) - } - return nil - } -} - -func idevCmd(cmd *exec.Cmd) *exec.Cmd { - if deviceID != "" { - // Inject -u device_id after the executable, but before the arguments. - args := []string{cmd.Args[0], "-u", deviceID} - cmd.Args = append(args, cmd.Args[1:]...) - } - return cmd -} - func runSimulator(appdir, bundleID string, args []string) error { - cmd := exec.Command( - "xcrun", "simctl", "launch", - "--wait-for-debugger", + xcrunArgs := []string{"simctl", "spawn", "booted", - bundleID, - ) - out, err := cmd.CombinedOutput() + appdir + "/gotest", + } + xcrunArgs = append(xcrunArgs, args...) + cmd := exec.Command("xcrun", xcrunArgs...) + cmd.Stdout, cmd.Stderr = os.Stdout, os.Stderr + err := cmd.Run() if err != nil { - os.Stderr.Write(out) return fmt.Errorf("xcrun simctl launch booted %q: %v", bundleID, err) } - var processID int - var ignore string - if _, err := fmt.Sscanf(string(out), "%s %d", &ignore, &processID); err != nil { - return fmt.Errorf("runSimulator: couldn't find processID from `simctl launch`: %v (%q)", err, out) - } - _, err = runLLDB("ios-simulator", appdir, strconv.Itoa(processID), args) - return err -} - -func runDevice(appdir, bundleID string, args []string) error { - attempt := 0 - for { - // The device app path reported by the device might be stale, so retry - // the lookup of the device path along with the lldb launching below. - deviceapp, err := findDeviceAppPath(bundleID) - if err != nil { - // The device app path might not yet exist for a newly installed app. - if attempt == 5 { - return err - } - attempt++ - time.Sleep(5 * time.Second) - continue - } - out, err := runLLDB("remote-ios", appdir, deviceapp, args) - // If the program was not started it can be retried without papering over - // real test failures. - started := bytes.HasPrefix(out, []byte("lldb: running program")) - if started || err == nil || attempt == 5 { - return err - } - // Sometimes, the app was not yet ready to launch or the device path was - // stale. Retry. - attempt++ - time.Sleep(5 * time.Second) - } -} -func runLLDB(target, appdir, deviceapp string, args []string) ([]byte, error) { - var env []string - for _, e := range os.Environ() { - // Don't override TMPDIR, HOME, GOCACHE on the device. - if strings.HasPrefix(e, "TMPDIR=") || strings.HasPrefix(e, "HOME=") || strings.HasPrefix(e, "GOCACHE=") { - continue - } - env = append(env, e) - } - lldb := exec.Command( - "python", - "-", // Read script from stdin. - target, - appdir, - deviceapp, - ) - lldb.Args = append(lldb.Args, args...) - lldb.Env = env - lldb.Stdin = strings.NewReader(lldbDriver) - lldb.Stdout = os.Stdout - var out bytes.Buffer - lldb.Stderr = io.MultiWriter(&out, os.Stderr) - err := lldb.Start() - if err == nil { - // Forward SIGQUIT to the lldb driver which in turn will forward - // to the running program. - sigs := make(chan os.Signal, 1) - signal.Notify(sigs, syscall.SIGQUIT) - proc := lldb.Process - go func() { - for sig := range sigs { - proc.Signal(sig) - } - }() - err = lldb.Wait() - signal.Stop(sigs) - close(sigs) - } - return out.Bytes(), err + return nil } func copyLocalDir(dst, src string) error { @@ -800,112 +364,3 @@ const resourceRules = ` ` - -const lldbDriver = ` -import sys -import os -import signal - -platform, exe, device_exe_or_pid, args = sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4:] - -env = [] -for k, v in os.environ.items(): - env.append(k + "=" + v) - -sys.path.append('/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python') - -import lldb - -debugger = lldb.SBDebugger.Create() -debugger.SetAsync(True) -debugger.SkipLLDBInitFiles(True) - -err = lldb.SBError() -target = debugger.CreateTarget(exe, None, platform, True, err) -if not target.IsValid() or not err.Success(): - sys.stderr.write("lldb: failed to setup up target: %s\n" % (err)) - sys.exit(1) - -listener = debugger.GetListener() - -if platform == 'remote-ios': - target.modules[0].SetPlatformFileSpec(lldb.SBFileSpec(device_exe_or_pid)) - process = target.ConnectRemote(listener, 'connect://localhost:3222', None, err) -else: - process = target.AttachToProcessWithID(listener, int(device_exe_or_pid), err) - -if not err.Success(): - sys.stderr.write("lldb: failed to connect to remote target %s: %s\n" % (device_exe_or_pid, err)) - sys.exit(1) - -# Don't stop on signals. -sigs = process.GetUnixSignals() -for i in range(0, sigs.GetNumSignals()): - sig = sigs.GetSignalAtIndex(i) - sigs.SetShouldStop(sig, False) - sigs.SetShouldNotify(sig, False) - -event = lldb.SBEvent() -running = False -prev_handler = None - -def signal_handler(signal, frame): - process.Signal(signal) - -def run_program(): - # Forward SIGQUIT to the program. - prev_handler = signal.signal(signal.SIGQUIT, signal_handler) - # Tell the Go driver that the program is running and should not be retried. - sys.stderr.write("lldb: running program\n") - running = True - # Process is stopped at attach/launch. Let it run. - process.Continue() - -if platform != 'remote-ios': - # For the local emulator the program is ready to run. - # For remote device runs, we need to wait for eStateConnected, - # below. - run_program() - -while True: - if not listener.WaitForEvent(1, event): - continue - if not lldb.SBProcess.EventIsProcessEvent(event): - continue - if running: - # Pass through stdout and stderr. - while True: - out = process.GetSTDOUT(8192) - if not out: - break - sys.stdout.write(out) - while True: - out = process.GetSTDERR(8192) - if not out: - break - sys.stderr.write(out) - state = process.GetStateFromEvent(event) - if state in [lldb.eStateCrashed, lldb.eStateDetached, lldb.eStateUnloaded, lldb.eStateExited]: - if running: - signal.signal(signal.SIGQUIT, prev_handler) - break - elif state == lldb.eStateConnected: - if platform == 'remote-ios': - process.RemoteLaunch(args, env, None, None, None, None, 0, False, err) - if not err.Success(): - sys.stderr.write("lldb: failed to launch remote process: %s\n" % (err)) - process.Kill() - debugger.Terminate() - sys.exit(1) - run_program() - -exitStatus = process.GetExitStatus() -exitDesc = process.GetExitDescription() -process.Kill() -debugger.Terminate() -if exitStatus == 0 and exitDesc is not None: - # Ensure tests fail when killed by a signal. - exitStatus = 123 - -sys.exit(exitStatus) -` From 2ade9856f17668b9d06d05e17e8f15701f8ac771 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 7 Jun 2024 18:13:06 -0400 Subject: [PATCH 04/41] doc/next: add release notes for telemetry and the godebug directive For #65614 Change-Id: I6274bdaba970cfb085af500fdaf8ed078202bfdc Reviewed-on: https://go-review.googlesource.com/c/go/+/591380 Reviewed-by: David Chase Reviewed-by: Russ Cox Reviewed-by: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI --- doc/next/3-tools.md | 41 +++++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/doc/next/3-tools.md b/doc/next/3-tools.md index e73e8a73a39bd9..73f931c102d6b9 100644 --- a/doc/next/3-tools.md +++ b/doc/next/3-tools.md @@ -1,5 +1,31 @@ ## Tools {#tools} +### Telemetry + + +Starting in Go 1.23, the Go toolchain can collect usage and breakage +statistics that help the Go team understand how the Go toolchain is +used and how well it is working. We refer to these statistics as +[Go telemetry](/doc/telemetry). + +Go telemetry is an _opt-in system_, controlled by the +[`go` `telemetry` command](/cmd/go/#hdr-Manage_telemetry_data_and_settings). +By default, the toolchain programs +collect statistics in counter files that can be inspected locally +but are otherwise unused (`go` `telemetry` `local`). + +To help us keep Go working well and understand Go usage, +please consider opting in to Go telemetry by running +`go` `telemetry` `on`. +In that mode, +anonymous counter reports are uploaded to +[telemetry.go.dev](https://telemetry.go.dev) weekly, +where they are aggregated into graphs and also made +available for download by any Go contributors or users +wanting to analyze the data. +See “[Go Telemetry](/doc/telemetry)” for more details +about the Go Telemetry system. + ### Go command {#go-command} Setting the `GOROOT_FINAL` environment variable no longer has an effect @@ -23,18 +49,9 @@ It exits with a non-zero code if updates are needed. The `go` `list` `-m` `-json` command now includes new `Sum` and `GoModSum` fields. This is similar to the existing behavior of the `go` `mod` `download` `-json` command. - -The new `go` `telemetry` command can be used to view and configure the telemetry collection -mode. Without arguments, it displays the current mode. With `local`, `on`, or `off`, it sets -the collection mode. `go` `env` now lists two values: the `GOTELEMETRY` value, which -contains the telemetry collection mode, and the `GOTELEMETRYDIR` value setting which contains -the directory telemetry data and configuration are written to. - - - - - +The new `godebug` directive in `go.mod` and `go.work` declares a +[GODEBUG setting](/doc/godebug) to apply for the work module or workspace in use. ### Vet {#vet} @@ -44,7 +61,7 @@ The `go vet` subcommand now includes the analyzer, which flags references to symbols that are too new for the version of Go in effect in the referring file. (The effective version is determined by the `go` directive in the file's enclosing `go.mod` file, and -by any [`//go:build` constraints](https://pkg.go.dev/cmd/go#hdr-Build_constraints) +by any [`//go:build` constraints](/cmd/go#hdr-Build_constraints) in the file.) For example, it will report a diagnostic for a reference to the From cef0a2ecfbd8dfe48434e28fc8b6f584a0212637 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Tue, 18 Jun 2024 14:21:13 -0400 Subject: [PATCH 05/41] all: update vendored golang.org/x/tools Pull in CL 593297: f2d2ebe4 go/analysis/passes/buildtag: retire Go 1.15 support Along with other changes that have landed into x/tools. This fixes a vet failure reported on longtest builders. For #66092. Change-Id: I549cc3f8e2c2033fe961bf014ff8cc1998021538 Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest Reviewed-on: https://go-review.googlesource.com/c/go/+/593376 Reviewed-by: Dmitri Shuralyov TryBot-Bypass: Dmitri Shuralyov Reviewed-by: David Chase Auto-Submit: Dmitri Shuralyov --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +- .../x/tools/go/analysis/diagnostic.go | 17 +- .../go/analysis/passes/buildtag/buildtag.go | 3 - .../analysis/passes/buildtag/buildtag_old.go | 174 ------------------ .../analysis/passes/stringintconv/string.go | 86 +++++++-- .../internal/analysisinternal/analysis.go | 81 ++++++++ .../x/tools/internal/stdlib/manifest.go | 111 +++++++++++ src/cmd/vendor/modules.txt | 2 +- 9 files changed, 280 insertions(+), 200 deletions(-) delete mode 100644 src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go diff --git a/src/cmd/go.mod b/src/cmd/go.mod index e9e742d7e3a903..559ffd1ccdc5b5 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -11,7 +11,7 @@ require ( golang.org/x/sys v0.21.0 golang.org/x/telemetry v0.0.0-20240612191826-8cad58b3fcbb golang.org/x/term v0.20.0 - golang.org/x/tools v0.21.1-0.20240604144337-208808308b70 + golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72 ) require ( diff --git a/src/cmd/go.sum b/src/cmd/go.sum index e6f1abd80ffd97..8f9517bc624754 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -22,7 +22,7 @@ golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/tools v0.21.1-0.20240604144337-208808308b70 h1:UmSJS6pdDoRwdDCbOwHnsOCHhVUhmdhF0m1Cfb82ts8= -golang.org/x/tools v0.21.1-0.20240604144337-208808308b70/go.mod h1:bqv7PJ/TtlrzgJKhOAGdDUkUltQapRik/UEHubLVBWo= +golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72 h1:YEy0SBExcUlHkZSzP6yv3BTwAUH6FK1XWDyC27AE+0I= +golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef h1:mqLYrXCXYEZOop9/Dbo6RPX11539nwiCNBb1icVPmw8= rsc.io/markdown v0.0.0-20240306144322-0bf8f97ee8ef/go.mod h1:8xcPgWmwlZONN1D9bjxtHEjrUtSEa3fakVF8iaewYKQ= diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/diagnostic.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/diagnostic.go index 4eb90599808e67..ee083a2d686723 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/diagnostic.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/diagnostic.go @@ -33,8 +33,17 @@ type Diagnostic struct { URL string // SuggestedFixes is an optional list of fixes to address the - // problem described by the diagnostic, each one representing + // problem described by the diagnostic. Each one represents // an alternative strategy; at most one may be applied. + // + // Fixes for different diagnostics should be treated as + // independent changes to the same baseline file state, + // analogous to a set of git commits all with the same parent. + // Combining fixes requires resolving any conflicts that + // arise, analogous to a git merge. + // Any conflicts that remain may be dealt with, depending on + // the tool, by discarding fixes, consulting the user, or + // aborting the operation. SuggestedFixes []SuggestedFix // Related contains optional secondary positions and messages @@ -58,8 +67,10 @@ type RelatedInformation struct { // // The TextEdits must not overlap, nor contain edits for other packages. type SuggestedFix struct { - // A description for this suggested fix to be shown to a user deciding - // whether to accept it. + // A verb phrase describing the fix, to be shown to + // a user trying to decide whether to accept it. + // + // Example: "Remove the surplus argument" Message string TextEdits []TextEdit } diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go index 51ba2a91e5b94d..5b4cf9d9edcdd4 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag.go @@ -2,9 +2,6 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build go1.16 -// +build go1.16 - // Package buildtag defines an Analyzer that checks build tags. package buildtag diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go deleted file mode 100644 index 19ef6b9bce401d..00000000000000 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/buildtag/buildtag_old.go +++ /dev/null @@ -1,174 +0,0 @@ -// Copyright 2013 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. - -// TODO(rsc): Delete this file once Go 1.17 comes out and we can retire Go 1.15 support. - -//go:build !go1.16 -// +build !go1.16 - -// Package buildtag defines an Analyzer that checks build tags. -package buildtag - -import ( - "bytes" - "fmt" - "go/ast" - "go/parser" - "strings" - "unicode" - - "golang.org/x/tools/go/analysis" - "golang.org/x/tools/go/analysis/passes/internal/analysisutil" -) - -const Doc = "check // +build directives" - -var Analyzer = &analysis.Analyzer{ - Name: "buildtag", - Doc: Doc, - Run: runBuildTag, -} - -func runBuildTag(pass *analysis.Pass) (interface{}, error) { - for _, f := range pass.Files { - checkGoFile(pass, f) - } - for _, name := range pass.OtherFiles { - if err := checkOtherFile(pass, name); err != nil { - return nil, err - } - } - for _, name := range pass.IgnoredFiles { - if strings.HasSuffix(name, ".go") { - f, err := parser.ParseFile(pass.Fset, name, nil, parser.ParseComments) - if err != nil { - // Not valid Go source code - not our job to diagnose, so ignore. - return nil, nil - } - checkGoFile(pass, f) - } else { - if err := checkOtherFile(pass, name); err != nil { - return nil, err - } - } - } - return nil, nil -} - -func checkGoFile(pass *analysis.Pass, f *ast.File) { - pastCutoff := false - for _, group := range f.Comments { - // A +build comment is ignored after or adjoining the package declaration. - if group.End()+1 >= f.Package { - pastCutoff = true - } - - // "+build" is ignored within or after a /*...*/ comment. - if !strings.HasPrefix(group.List[0].Text, "//") { - pastCutoff = true - continue - } - - // Check each line of a //-comment. - for _, c := range group.List { - if !strings.Contains(c.Text, "+build") { - continue - } - if err := checkLine(c.Text, pastCutoff); err != nil { - pass.Reportf(c.Pos(), "%s", err) - } - } - } -} - -func checkOtherFile(pass *analysis.Pass, filename string) error { - content, tf, err := analysisutil.ReadFile(pass, filename) - if err != nil { - return err - } - - // We must look at the raw lines, as build tags may appear in non-Go - // files such as assembly files. - lines := bytes.SplitAfter(content, nl) - - // Determine cutpoint where +build comments are no longer valid. - // They are valid in leading // comments in the file followed by - // a blank line. - // - // This must be done as a separate pass because of the - // requirement that the comment be followed by a blank line. - var cutoff int - for i, line := range lines { - line = bytes.TrimSpace(line) - if !bytes.HasPrefix(line, slashSlash) { - if len(line) > 0 { - break - } - cutoff = i - } - } - - for i, line := range lines { - line = bytes.TrimSpace(line) - if !bytes.HasPrefix(line, slashSlash) { - continue - } - if !bytes.Contains(line, []byte("+build")) { - continue - } - if err := checkLine(string(line), i >= cutoff); err != nil { - pass.Reportf(analysisutil.LineStart(tf, i+1), "%s", err) - continue - } - } - return nil -} - -// checkLine checks a line that starts with "//" and contains "+build". -func checkLine(line string, pastCutoff bool) error { - line = strings.TrimPrefix(line, "//") - line = strings.TrimSpace(line) - - if strings.HasPrefix(line, "+build") { - fields := strings.Fields(line) - if fields[0] != "+build" { - // Comment is something like +buildasdf not +build. - return fmt.Errorf("possible malformed +build comment") - } - if pastCutoff { - return fmt.Errorf("+build comment must appear before package clause and be followed by a blank line") - } - if err := checkArguments(fields); err != nil { - return err - } - } else { - // Comment with +build but not at beginning. - if !pastCutoff { - return fmt.Errorf("possible malformed +build comment") - } - } - return nil -} - -func checkArguments(fields []string) error { - for _, arg := range fields[1:] { - for _, elem := range strings.Split(arg, ",") { - if strings.HasPrefix(elem, "!!") { - return fmt.Errorf("invalid double negative in build constraint: %s", arg) - } - elem = strings.TrimPrefix(elem, "!") - for _, c := range elem { - if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' { - return fmt.Errorf("invalid non-alphanumeric build constraint: %s", arg) - } - } - } - } - return nil -} - -var ( - nl = []byte("\n") - slashSlash = []byte("//") -) diff --git a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go index c77182daef6633..c91f6bc4745f52 100644 --- a/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go +++ b/src/cmd/vendor/golang.org/x/tools/go/analysis/passes/stringintconv/string.go @@ -16,6 +16,7 @@ import ( "golang.org/x/tools/go/analysis/passes/internal/analysisutil" "golang.org/x/tools/go/ast/inspector" "golang.org/x/tools/internal/aliases" + "golang.org/x/tools/internal/analysisinternal" "golang.org/x/tools/internal/typeparams" ) @@ -73,9 +74,15 @@ func typeName(t types.Type) string { func run(pass *analysis.Pass) (interface{}, error) { inspect := pass.ResultOf[inspect.Analyzer].(*inspector.Inspector) nodeFilter := []ast.Node{ + (*ast.File)(nil), (*ast.CallExpr)(nil), } + var file *ast.File inspect.Preorder(nodeFilter, func(n ast.Node) { + if n, ok := n.(*ast.File); ok { + file = n + return + } call := n.(*ast.CallExpr) if len(call.Args) != 1 { @@ -167,27 +174,74 @@ func run(pass *analysis.Pass) (interface{}, error) { diag := analysis.Diagnostic{ Pos: n.Pos(), - Message: fmt.Sprintf("conversion from %s to %s yields a string of one rune, not a string of digits (did you mean fmt.Sprint(x)?)", source, target), + Message: fmt.Sprintf("conversion from %s to %s yields a string of one rune, not a string of digits", source, target), + } + addFix := func(message string, edits []analysis.TextEdit) { + diag.SuggestedFixes = append(diag.SuggestedFixes, analysis.SuggestedFix{ + Message: message, + TextEdits: edits, + }) } + // Fix 1: use fmt.Sprint(x) + // + // Prefer fmt.Sprint over strconv.Itoa, FormatInt, + // or FormatUint, as it works for any type. + // Add an import of "fmt" as needed. + // + // Unless the type is exactly string, we must retain the conversion. + // + // Do not offer this fix if type parameters are involved, + // as there are too many combinations and subtleties. + // Consider x = rune | int16 | []byte: in all cases, + // string(x) is legal, but the appropriate diagnostic + // and fix differs. Similarly, don't offer the fix if + // the type has methods, as some {String,GoString,Format} + // may change the behavior of fmt.Sprint. + if len(ttypes) == 1 && len(vtypes) == 1 && types.NewMethodSet(V0).Len() == 0 { + fmtName, importEdit := analysisinternal.AddImport(pass.TypesInfo, file, arg.Pos(), "fmt", "fmt") + if types.Identical(T0, types.Typ[types.String]) { + // string(x) -> fmt.Sprint(x) + addFix("Format the number as a decimal", []analysis.TextEdit{ + importEdit, + { + Pos: call.Fun.Pos(), + End: call.Fun.End(), + NewText: []byte(fmtName + ".Sprint"), + }, + }) + } else { + // mystring(x) -> mystring(fmt.Sprint(x)) + addFix("Format the number as a decimal", []analysis.TextEdit{ + importEdit, + { + Pos: call.Lparen + 1, + End: call.Lparen + 1, + NewText: []byte(fmtName + ".Sprint("), + }, + { + Pos: call.Rparen, + End: call.Rparen, + NewText: []byte(")"), + }, + }) + } + } + + // Fix 2: use string(rune(x)) if convertibleToRune { - diag.SuggestedFixes = []analysis.SuggestedFix{ + addFix("Convert a single rune to a string", []analysis.TextEdit{ { - Message: "Did you mean to convert a rune to a string?", - TextEdits: []analysis.TextEdit{ - { - Pos: arg.Pos(), - End: arg.Pos(), - NewText: []byte("rune("), - }, - { - Pos: arg.End(), - End: arg.End(), - NewText: []byte(")"), - }, - }, + Pos: arg.Pos(), + End: arg.Pos(), + NewText: []byte("rune("), }, - } + { + Pos: arg.End(), + End: arg.End(), + NewText: []byte(")"), + }, + }) } pass.Report(diag) }) diff --git a/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go b/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go index 9ba3a8efb9eea0..4000d27d8ee73e 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/analysisinternal/analysis.go @@ -13,6 +13,7 @@ import ( "go/token" "go/types" "os" + pathpkg "path" "strconv" "golang.org/x/tools/go/analysis" @@ -269,6 +270,8 @@ func StmtToInsertVarBefore(path []ast.Node) ast.Stmt { if expr.Init == enclosingStmt || expr.Post == enclosingStmt { return expr } + case *ast.SwitchStmt, *ast.TypeSwitchStmt: + return expr.(ast.Stmt) } return enclosingStmt.(ast.Stmt) } @@ -430,3 +433,81 @@ func slicesContains[S ~[]E, E comparable](slice S, x E) bool { } return false } + +// AddImport checks whether this file already imports pkgpath and +// that import is in scope at pos. If so, it returns the name under +// which it was imported and a zero edit. Otherwise, it adds a new +// import of pkgpath, using a name derived from the preferred name, +// and returns the chosen name along with the edit for the new import. +// +// It does not mutate its arguments. +func AddImport(info *types.Info, file *ast.File, pos token.Pos, pkgpath, preferredName string) (name string, newImport analysis.TextEdit) { + // Find innermost enclosing lexical block. + scope := info.Scopes[file].Innermost(pos) + if scope == nil { + panic("no enclosing lexical block") + } + + // Is there an existing import of this package? + // If so, are we in its scope? (not shadowed) + for _, spec := range file.Imports { + pkgname, ok := importedPkgName(info, spec) + if ok && pkgname.Imported().Path() == pkgpath { + if _, obj := scope.LookupParent(pkgname.Name(), pos); obj == pkgname { + return pkgname.Name(), analysis.TextEdit{} + } + } + } + + // We must add a new import. + // Ensure we have a fresh name. + newName := preferredName + for i := 0; ; i++ { + if _, obj := scope.LookupParent(newName, pos); obj == nil { + break // fresh + } + newName = fmt.Sprintf("%s%d", preferredName, i) + } + + // For now, keep it real simple: create a new import + // declaration before the first existing declaration (which + // must exist), including its comments, and let goimports tidy it up. + // + // Use a renaming import whenever the preferred name is not + // available, or the chosen name does not match the last + // segment of its path. + newText := fmt.Sprintf("import %q\n\n", pkgpath) + if newName != preferredName || newName != pathpkg.Base(pkgpath) { + newText = fmt.Sprintf("import %s %q\n\n", newName, pkgpath) + } + decl0 := file.Decls[0] + var before ast.Node = decl0 + switch decl0 := decl0.(type) { + case *ast.GenDecl: + if decl0.Doc != nil { + before = decl0.Doc + } + case *ast.FuncDecl: + if decl0.Doc != nil { + before = decl0.Doc + } + } + return newName, analysis.TextEdit{ + Pos: before.Pos(), + End: before.Pos(), + NewText: []byte(newText), + } +} + +// importedPkgName returns the PkgName object declared by an ImportSpec. +// TODO(adonovan): use go1.22's Info.PkgNameOf. +func importedPkgName(info *types.Info, imp *ast.ImportSpec) (*types.PkgName, bool) { + var obj types.Object + if imp.Name != nil { + obj = info.Defs[imp.Name] + } else { + obj = info.Implicits[imp] + } + pkgname, ok := obj.(*types.PkgName) + return pkgname, ok +} diff --git a/src/cmd/vendor/golang.org/x/tools/internal/stdlib/manifest.go b/src/cmd/vendor/golang.org/x/tools/internal/stdlib/manifest.go index fd6892075ee4be..a928acf29facfe 100644 --- a/src/cmd/vendor/golang.org/x/tools/internal/stdlib/manifest.go +++ b/src/cmd/vendor/golang.org/x/tools/internal/stdlib/manifest.go @@ -23,6 +23,7 @@ var PackageSymbols = map[string][]Symbol{ {"ErrWriteAfterClose", Var, 0}, {"ErrWriteTooLong", Var, 0}, {"FileInfoHeader", Func, 1}, + {"FileInfoNames", Type, 23}, {"Format", Type, 10}, {"FormatGNU", Const, 10}, {"FormatPAX", Const, 10}, @@ -820,6 +821,7 @@ var PackageSymbols = map[string][]Symbol{ {"(*ConnectionState).ExportKeyingMaterial", Method, 11}, {"(*Dialer).Dial", Method, 15}, {"(*Dialer).DialContext", Method, 15}, + {"(*ECHRejectionError).Error", Method, 23}, {"(*QUICConn).Close", Method, 21}, {"(*QUICConn).ConnectionState", Method, 21}, {"(*QUICConn).HandleData", Method, 21}, @@ -827,6 +829,7 @@ var PackageSymbols = map[string][]Symbol{ {"(*QUICConn).SendSessionTicket", Method, 21}, {"(*QUICConn).SetTransportParameters", Method, 21}, {"(*QUICConn).Start", Method, 21}, + {"(*QUICConn).StoreSession", Method, 23}, {"(*SessionState).Bytes", Method, 21}, {"(AlertError).Error", Method, 21}, {"(ClientAuthType).String", Method, 15}, @@ -877,6 +880,8 @@ var PackageSymbols = map[string][]Symbol{ {"Config.ClientSessionCache", Field, 3}, {"Config.CurvePreferences", Field, 3}, {"Config.DynamicRecordSizingDisabled", Field, 7}, + {"Config.EncryptedClientHelloConfigList", Field, 23}, + {"Config.EncryptedClientHelloRejectionVerify", Field, 23}, {"Config.GetCertificate", Field, 4}, {"Config.GetClientCertificate", Field, 8}, {"Config.GetConfigForClient", Field, 8}, @@ -902,6 +907,7 @@ var PackageSymbols = map[string][]Symbol{ {"ConnectionState", Type, 0}, {"ConnectionState.CipherSuite", Field, 0}, {"ConnectionState.DidResume", Field, 1}, + {"ConnectionState.ECHAccepted", Field, 23}, {"ConnectionState.HandshakeComplete", Field, 0}, {"ConnectionState.NegotiatedProtocol", Field, 0}, {"ConnectionState.NegotiatedProtocolIsMutual", Field, 0}, @@ -925,6 +931,8 @@ var PackageSymbols = map[string][]Symbol{ {"ECDSAWithP384AndSHA384", Const, 8}, {"ECDSAWithP521AndSHA512", Const, 8}, {"ECDSAWithSHA1", Const, 10}, + {"ECHRejectionError", Type, 23}, + {"ECHRejectionError.RetryConfigList", Field, 23}, {"Ed25519", Const, 13}, {"InsecureCipherSuites", Func, 14}, {"Listen", Func, 0}, @@ -943,6 +951,7 @@ var PackageSymbols = map[string][]Symbol{ {"ParseSessionState", Func, 21}, {"QUICClient", Func, 21}, {"QUICConfig", Type, 21}, + {"QUICConfig.EnableStoreSessionEvent", Field, 23}, {"QUICConfig.TLSConfig", Field, 21}, {"QUICConn", Type, 21}, {"QUICEncryptionLevel", Type, 21}, @@ -954,16 +963,20 @@ var PackageSymbols = map[string][]Symbol{ {"QUICEvent.Data", Field, 21}, {"QUICEvent.Kind", Field, 21}, {"QUICEvent.Level", Field, 21}, + {"QUICEvent.SessionState", Field, 23}, {"QUICEvent.Suite", Field, 21}, {"QUICEventKind", Type, 21}, {"QUICHandshakeDone", Const, 21}, {"QUICNoEvent", Const, 21}, {"QUICRejectedEarlyData", Const, 21}, + {"QUICResumeSession", Const, 23}, {"QUICServer", Func, 21}, {"QUICSessionTicketOptions", Type, 21}, {"QUICSessionTicketOptions.EarlyData", Field, 21}, + {"QUICSessionTicketOptions.Extra", Field, 23}, {"QUICSetReadSecret", Const, 21}, {"QUICSetWriteSecret", Const, 21}, + {"QUICStoreSession", Const, 23}, {"QUICTransportParameters", Const, 21}, {"QUICTransportParametersRequired", Const, 21}, {"QUICWriteData", Const, 21}, @@ -1036,6 +1049,8 @@ var PackageSymbols = map[string][]Symbol{ {"(*Certificate).Verify", Method, 0}, {"(*Certificate).VerifyHostname", Method, 0}, {"(*CertificateRequest).CheckSignature", Method, 5}, + {"(*OID).UnmarshalBinary", Method, 23}, + {"(*OID).UnmarshalText", Method, 23}, {"(*RevocationList).CheckSignatureFrom", Method, 19}, {"(CertificateInvalidError).Error", Method, 0}, {"(ConstraintViolationError).Error", Method, 0}, @@ -1043,6 +1058,8 @@ var PackageSymbols = map[string][]Symbol{ {"(InsecureAlgorithmError).Error", Method, 6}, {"(OID).Equal", Method, 22}, {"(OID).EqualASN1OID", Method, 22}, + {"(OID).MarshalBinary", Method, 23}, + {"(OID).MarshalText", Method, 23}, {"(OID).String", Method, 22}, {"(PublicKeyAlgorithm).String", Method, 10}, {"(SignatureAlgorithm).String", Method, 6}, @@ -1196,6 +1213,7 @@ var PackageSymbols = map[string][]Symbol{ {"ParseCertificates", Func, 0}, {"ParseDERCRL", Func, 0}, {"ParseECPrivateKey", Func, 1}, + {"ParseOID", Func, 23}, {"ParsePKCS1PrivateKey", Func, 0}, {"ParsePKCS1PublicKey", Func, 10}, {"ParsePKCS8PrivateKey", Func, 0}, @@ -2541,6 +2559,7 @@ var PackageSymbols = map[string][]Symbol{ {"PT_NOTE", Const, 0}, {"PT_NULL", Const, 0}, {"PT_OPENBSD_BOOTDATA", Const, 16}, + {"PT_OPENBSD_NOBTCFI", Const, 23}, {"PT_OPENBSD_RANDOMIZE", Const, 16}, {"PT_OPENBSD_WXNEEDED", Const, 16}, {"PT_PAX_FLAGS", Const, 16}, @@ -3620,13 +3639,16 @@ var PackageSymbols = map[string][]Symbol{ {"STT_COMMON", Const, 0}, {"STT_FILE", Const, 0}, {"STT_FUNC", Const, 0}, + {"STT_GNU_IFUNC", Const, 23}, {"STT_HIOS", Const, 0}, {"STT_HIPROC", Const, 0}, {"STT_LOOS", Const, 0}, {"STT_LOPROC", Const, 0}, {"STT_NOTYPE", Const, 0}, {"STT_OBJECT", Const, 0}, + {"STT_RELC", Const, 23}, {"STT_SECTION", Const, 0}, + {"STT_SRELC", Const, 23}, {"STT_TLS", Const, 0}, {"STV_DEFAULT", Const, 0}, {"STV_HIDDEN", Const, 0}, @@ -4544,11 +4566,14 @@ var PackageSymbols = map[string][]Symbol{ {"URLEncoding", Var, 0}, }, "encoding/binary": { + {"Append", Func, 23}, {"AppendByteOrder", Type, 19}, {"AppendUvarint", Func, 19}, {"AppendVarint", Func, 19}, {"BigEndian", Var, 0}, {"ByteOrder", Type, 0}, + {"Decode", Func, 23}, + {"Encode", Func, 23}, {"LittleEndian", Var, 0}, {"MaxVarintLen16", Const, 0}, {"MaxVarintLen32", Const, 0}, @@ -5308,6 +5333,7 @@ var PackageSymbols = map[string][]Symbol{ {"ParenExpr.Rparen", Field, 0}, {"ParenExpr.X", Field, 0}, {"Pkg", Const, 0}, + {"Preorder", Func, 23}, {"Print", Func, 0}, {"RECV", Const, 0}, {"RangeStmt", Type, 0}, @@ -5898,7 +5924,12 @@ var PackageSymbols = map[string][]Symbol{ }, "go/types": { {"(*Alias).Obj", Method, 22}, + {"(*Alias).Origin", Method, 23}, + {"(*Alias).Rhs", Method, 23}, + {"(*Alias).SetTypeParams", Method, 23}, {"(*Alias).String", Method, 22}, + {"(*Alias).TypeArgs", Method, 23}, + {"(*Alias).TypeParams", Method, 23}, {"(*Alias).Underlying", Method, 22}, {"(*ArgumentError).Error", Method, 18}, {"(*ArgumentError).Unwrap", Method, 18}, @@ -5943,6 +5974,7 @@ var PackageSymbols = map[string][]Symbol{ {"(*Func).Pkg", Method, 5}, {"(*Func).Pos", Method, 5}, {"(*Func).Scope", Method, 5}, + {"(*Func).Signature", Method, 23}, {"(*Func).String", Method, 5}, {"(*Func).Type", Method, 5}, {"(*Info).ObjectOf", Method, 5}, @@ -6992,6 +7024,12 @@ var PackageSymbols = map[string][]Symbol{ {"TempFile", Func, 0}, {"WriteFile", Func, 0}, }, + "iter": { + {"Pull", Func, 23}, + {"Pull2", Func, 23}, + {"Seq", Type, 23}, + {"Seq2", Type, 23}, + }, "log": { {"(*Logger).Fatal", Method, 0}, {"(*Logger).Fatalf", Method, 0}, @@ -7222,11 +7260,16 @@ var PackageSymbols = map[string][]Symbol{ {"Writer", Type, 0}, }, "maps": { + {"All", Func, 23}, {"Clone", Func, 21}, + {"Collect", Func, 23}, {"Copy", Func, 21}, {"DeleteFunc", Func, 21}, {"Equal", Func, 21}, {"EqualFunc", Func, 21}, + {"Insert", Func, 23}, + {"Keys", Func, 23}, + {"Values", Func, 23}, }, "math": { {"Abs", Func, 0}, @@ -7617,6 +7660,7 @@ var PackageSymbols = map[string][]Symbol{ }, "math/rand/v2": { {"(*ChaCha8).MarshalBinary", Method, 22}, + {"(*ChaCha8).Read", Method, 23}, {"(*ChaCha8).Seed", Method, 22}, {"(*ChaCha8).Uint64", Method, 22}, {"(*ChaCha8).UnmarshalBinary", Method, 22}, @@ -7636,6 +7680,7 @@ var PackageSymbols = map[string][]Symbol{ {"(*Rand).NormFloat64", Method, 22}, {"(*Rand).Perm", Method, 22}, {"(*Rand).Shuffle", Method, 22}, + {"(*Rand).Uint", Method, 23}, {"(*Rand).Uint32", Method, 22}, {"(*Rand).Uint32N", Method, 22}, {"(*Rand).Uint64", Method, 22}, @@ -7663,6 +7708,7 @@ var PackageSymbols = map[string][]Symbol{ {"Rand", Type, 22}, {"Shuffle", Func, 22}, {"Source", Type, 22}, + {"Uint", Func, 23}, {"Uint32", Func, 22}, {"Uint32N", Func, 22}, {"Uint64", Func, 22}, @@ -7743,6 +7789,7 @@ var PackageSymbols = map[string][]Symbol{ {"(*DNSError).Error", Method, 0}, {"(*DNSError).Temporary", Method, 0}, {"(*DNSError).Timeout", Method, 0}, + {"(*DNSError).Unwrap", Method, 23}, {"(*Dialer).Dial", Method, 1}, {"(*Dialer).DialContext", Method, 7}, {"(*Dialer).MultipathTCP", Method, 21}, @@ -7809,6 +7856,7 @@ var PackageSymbols = map[string][]Symbol{ {"(*TCPConn).RemoteAddr", Method, 0}, {"(*TCPConn).SetDeadline", Method, 0}, {"(*TCPConn).SetKeepAlive", Method, 0}, + {"(*TCPConn).SetKeepAliveConfig", Method, 23}, {"(*TCPConn).SetKeepAlivePeriod", Method, 2}, {"(*TCPConn).SetLinger", Method, 0}, {"(*TCPConn).SetNoDelay", Method, 0}, @@ -7922,6 +7970,7 @@ var PackageSymbols = map[string][]Symbol{ {"DNSError.IsTimeout", Field, 0}, {"DNSError.Name", Field, 0}, {"DNSError.Server", Field, 0}, + {"DNSError.UnwrapErr", Field, 23}, {"DefaultResolver", Var, 8}, {"Dial", Func, 0}, {"DialIP", Func, 0}, @@ -7937,6 +7986,7 @@ var PackageSymbols = map[string][]Symbol{ {"Dialer.DualStack", Field, 2}, {"Dialer.FallbackDelay", Field, 5}, {"Dialer.KeepAlive", Field, 3}, + {"Dialer.KeepAliveConfig", Field, 23}, {"Dialer.LocalAddr", Field, 1}, {"Dialer.Resolver", Field, 8}, {"Dialer.Timeout", Field, 1}, @@ -7989,10 +8039,16 @@ var PackageSymbols = map[string][]Symbol{ {"Interfaces", Func, 0}, {"InvalidAddrError", Type, 0}, {"JoinHostPort", Func, 0}, + {"KeepAliveConfig", Type, 23}, + {"KeepAliveConfig.Count", Field, 23}, + {"KeepAliveConfig.Enable", Field, 23}, + {"KeepAliveConfig.Idle", Field, 23}, + {"KeepAliveConfig.Interval", Field, 23}, {"Listen", Func, 0}, {"ListenConfig", Type, 11}, {"ListenConfig.Control", Field, 11}, {"ListenConfig.KeepAlive", Field, 13}, + {"ListenConfig.KeepAliveConfig", Field, 23}, {"ListenIP", Func, 0}, {"ListenMulticastUDP", Func, 0}, {"ListenPacket", Func, 0}, @@ -8081,6 +8137,7 @@ var PackageSymbols = map[string][]Symbol{ {"(*Request).Context", Method, 7}, {"(*Request).Cookie", Method, 0}, {"(*Request).Cookies", Method, 0}, + {"(*Request).CookiesNamed", Method, 23}, {"(*Request).FormFile", Method, 0}, {"(*Request).FormValue", Method, 0}, {"(*Request).MultipartReader", Method, 0}, @@ -8148,7 +8205,9 @@ var PackageSymbols = map[string][]Symbol{ {"Cookie.HttpOnly", Field, 0}, {"Cookie.MaxAge", Field, 0}, {"Cookie.Name", Field, 0}, + {"Cookie.Partitioned", Field, 23}, {"Cookie.Path", Field, 0}, + {"Cookie.Quoted", Field, 23}, {"Cookie.Raw", Field, 0}, {"Cookie.RawExpires", Field, 0}, {"Cookie.SameSite", Field, 11}, @@ -8225,7 +8284,9 @@ var PackageSymbols = map[string][]Symbol{ {"NoBody", Var, 8}, {"NotFound", Func, 0}, {"NotFoundHandler", Func, 0}, + {"ParseCookie", Func, 23}, {"ParseHTTPVersion", Func, 0}, + {"ParseSetCookie", Func, 23}, {"ParseTime", Func, 1}, {"Post", Func, 0}, {"PostForm", Func, 0}, @@ -8252,6 +8313,7 @@ var PackageSymbols = map[string][]Symbol{ {"Request.Host", Field, 0}, {"Request.Method", Field, 0}, {"Request.MultipartForm", Field, 0}, + {"Request.Pattern", Field, 23}, {"Request.PostForm", Field, 1}, {"Request.Proto", Field, 0}, {"Request.ProtoMajor", Field, 0}, @@ -8453,6 +8515,7 @@ var PackageSymbols = map[string][]Symbol{ {"DefaultRemoteAddr", Const, 0}, {"NewRecorder", Func, 0}, {"NewRequest", Func, 7}, + {"NewRequestWithContext", Func, 23}, {"NewServer", Func, 0}, {"NewTLSServer", Func, 0}, {"NewUnstartedServer", Func, 0}, @@ -8917,6 +8980,7 @@ var PackageSymbols = map[string][]Symbol{ {"Chown", Func, 0}, {"Chtimes", Func, 0}, {"Clearenv", Func, 0}, + {"CopyFS", Func, 23}, {"Create", Func, 0}, {"CreateTemp", Func, 16}, {"DevNull", Const, 0}, @@ -9150,6 +9214,7 @@ var PackageSymbols = map[string][]Symbol{ {"IsLocal", Func, 20}, {"Join", Func, 0}, {"ListSeparator", Const, 0}, + {"Localize", Func, 23}, {"Match", Func, 0}, {"Rel", Func, 0}, {"Separator", Const, 0}, @@ -9232,6 +9297,8 @@ var PackageSymbols = map[string][]Symbol{ {"(Value).Pointer", Method, 0}, {"(Value).Recv", Method, 0}, {"(Value).Send", Method, 0}, + {"(Value).Seq", Method, 23}, + {"(Value).Seq2", Method, 23}, {"(Value).Set", Method, 0}, {"(Value).SetBool", Method, 0}, {"(Value).SetBytes", Method, 0}, @@ -9314,6 +9381,7 @@ var PackageSymbols = map[string][]Symbol{ {"SelectSend", Const, 1}, {"SendDir", Const, 0}, {"Slice", Const, 0}, + {"SliceAt", Func, 23}, {"SliceHeader", Type, 0}, {"SliceHeader.Cap", Field, 0}, {"SliceHeader.Data", Field, 0}, @@ -9655,6 +9723,7 @@ var PackageSymbols = map[string][]Symbol{ {"BuildSetting", Type, 18}, {"BuildSetting.Key", Field, 18}, {"BuildSetting.Value", Field, 18}, + {"CrashOptions", Type, 23}, {"FreeOSMemory", Func, 1}, {"GCStats", Type, 1}, {"GCStats.LastGC", Field, 1}, @@ -9672,6 +9741,7 @@ var PackageSymbols = map[string][]Symbol{ {"PrintStack", Func, 0}, {"ReadBuildInfo", Func, 12}, {"ReadGCStats", Func, 1}, + {"SetCrashOutput", Func, 23}, {"SetGCPercent", Func, 1}, {"SetMaxStack", Func, 2}, {"SetMaxThreads", Func, 2}, @@ -9742,10 +9812,15 @@ var PackageSymbols = map[string][]Symbol{ {"WithRegion", Func, 11}, }, "slices": { + {"All", Func, 23}, + {"AppendSeq", Func, 23}, + {"Backward", Func, 23}, {"BinarySearch", Func, 21}, {"BinarySearchFunc", Func, 21}, + {"Chunk", Func, 23}, {"Clip", Func, 21}, {"Clone", Func, 21}, + {"Collect", Func, 23}, {"Compact", Func, 21}, {"CompactFunc", Func, 21}, {"Compare", Func, 21}, @@ -9767,11 +9842,16 @@ var PackageSymbols = map[string][]Symbol{ {"MaxFunc", Func, 21}, {"Min", Func, 21}, {"MinFunc", Func, 21}, + {"Repeat", Func, 23}, {"Replace", Func, 21}, {"Reverse", Func, 21}, {"Sort", Func, 21}, {"SortFunc", Func, 21}, {"SortStableFunc", Func, 21}, + {"Sorted", Func, 23}, + {"SortedFunc", Func, 23}, + {"SortedStableFunc", Func, 23}, + {"Values", Func, 23}, }, "sort": { {"(Float64Slice).Len", Method, 0}, @@ -9936,10 +10016,14 @@ var PackageSymbols = map[string][]Symbol{ {"TrimSpace", Func, 0}, {"TrimSuffix", Func, 1}, }, + "structs": { + {"HostLayout", Type, 23}, + }, "sync": { {"(*Cond).Broadcast", Method, 0}, {"(*Cond).Signal", Method, 0}, {"(*Cond).Wait", Method, 0}, + {"(*Map).Clear", Method, 23}, {"(*Map).CompareAndDelete", Method, 20}, {"(*Map).CompareAndSwap", Method, 20}, {"(*Map).Delete", Method, 9}, @@ -9986,13 +10070,17 @@ var PackageSymbols = map[string][]Symbol{ {"(*Bool).Store", Method, 19}, {"(*Bool).Swap", Method, 19}, {"(*Int32).Add", Method, 19}, + {"(*Int32).And", Method, 23}, {"(*Int32).CompareAndSwap", Method, 19}, {"(*Int32).Load", Method, 19}, + {"(*Int32).Or", Method, 23}, {"(*Int32).Store", Method, 19}, {"(*Int32).Swap", Method, 19}, {"(*Int64).Add", Method, 19}, + {"(*Int64).And", Method, 23}, {"(*Int64).CompareAndSwap", Method, 19}, {"(*Int64).Load", Method, 19}, + {"(*Int64).Or", Method, 23}, {"(*Int64).Store", Method, 19}, {"(*Int64).Swap", Method, 19}, {"(*Pointer).CompareAndSwap", Method, 19}, @@ -10000,18 +10088,24 @@ var PackageSymbols = map[string][]Symbol{ {"(*Pointer).Store", Method, 19}, {"(*Pointer).Swap", Method, 19}, {"(*Uint32).Add", Method, 19}, + {"(*Uint32).And", Method, 23}, {"(*Uint32).CompareAndSwap", Method, 19}, {"(*Uint32).Load", Method, 19}, + {"(*Uint32).Or", Method, 23}, {"(*Uint32).Store", Method, 19}, {"(*Uint32).Swap", Method, 19}, {"(*Uint64).Add", Method, 19}, + {"(*Uint64).And", Method, 23}, {"(*Uint64).CompareAndSwap", Method, 19}, {"(*Uint64).Load", Method, 19}, + {"(*Uint64).Or", Method, 23}, {"(*Uint64).Store", Method, 19}, {"(*Uint64).Swap", Method, 19}, {"(*Uintptr).Add", Method, 19}, + {"(*Uintptr).And", Method, 23}, {"(*Uintptr).CompareAndSwap", Method, 19}, {"(*Uintptr).Load", Method, 19}, + {"(*Uintptr).Or", Method, 23}, {"(*Uintptr).Store", Method, 19}, {"(*Uintptr).Swap", Method, 19}, {"(*Value).CompareAndSwap", Method, 17}, @@ -10023,6 +10117,11 @@ var PackageSymbols = map[string][]Symbol{ {"AddUint32", Func, 0}, {"AddUint64", Func, 0}, {"AddUintptr", Func, 0}, + {"AndInt32", Func, 23}, + {"AndInt64", Func, 23}, + {"AndUint32", Func, 23}, + {"AndUint64", Func, 23}, + {"AndUintptr", Func, 23}, {"Bool", Type, 19}, {"CompareAndSwapInt32", Func, 0}, {"CompareAndSwapInt64", Func, 0}, @@ -10038,6 +10137,11 @@ var PackageSymbols = map[string][]Symbol{ {"LoadUint32", Func, 0}, {"LoadUint64", Func, 0}, {"LoadUintptr", Func, 0}, + {"OrInt32", Func, 23}, + {"OrInt64", Func, 23}, + {"OrUint32", Func, 23}, + {"OrUint64", Func, 23}, + {"OrUintptr", Func, 23}, {"Pointer", Type, 19}, {"StoreInt32", Func, 0}, {"StoreInt64", Func, 0}, @@ -16200,6 +16304,7 @@ var PackageSymbols = map[string][]Symbol{ {"WSAEACCES", Const, 2}, {"WSAECONNABORTED", Const, 9}, {"WSAECONNRESET", Const, 3}, + {"WSAENOPROTOOPT", Const, 23}, {"WSAEnumProtocols", Func, 2}, {"WSAID_CONNECTEX", Var, 1}, {"WSAIoctl", Func, 0}, @@ -17284,6 +17389,7 @@ var PackageSymbols = map[string][]Symbol{ {"Encode", Func, 0}, {"EncodeRune", Func, 0}, {"IsSurrogate", Func, 0}, + {"RuneLen", Func, 23}, }, "unicode/utf8": { {"AppendRune", Func, 18}, @@ -17306,6 +17412,11 @@ var PackageSymbols = map[string][]Symbol{ {"ValidRune", Func, 1}, {"ValidString", Func, 0}, }, + "unique": { + {"(Handle).Value", Method, 23}, + {"Handle", Type, 23}, + {"Make", Func, 23}, + }, "unsafe": { {"Add", Func, 0}, {"Alignof", Func, 0}, diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 14c7a3edb459c4..8ba7df290fa0c1 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -70,7 +70,7 @@ golang.org/x/text/internal/tag golang.org/x/text/language golang.org/x/text/transform golang.org/x/text/unicode/norm -# golang.org/x/tools v0.21.1-0.20240604144337-208808308b70 +# golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72 ## explicit; go 1.19 golang.org/x/tools/cmd/bisect golang.org/x/tools/cover From 2b12bbcb4561a6f45e8036e71c8440b7bca50de6 Mon Sep 17 00:00:00 2001 From: Sam Thanawalla Date: Tue, 18 Jun 2024 18:48:57 +0000 Subject: [PATCH 06/41] doc/next: update release notes for go list -m -json For #65614 Change-Id: I49921aefb79efbc012e745cc2abd9ff36c0a9149 Reviewed-on: https://go-review.googlesource.com/c/go/+/593495 Reviewed-by: Dmitri Shuralyov Auto-Submit: Sam Thanawalla LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov --- doc/next/3-tools.md | 1 - 1 file changed, 1 deletion(-) diff --git a/doc/next/3-tools.md b/doc/next/3-tools.md index 73f931c102d6b9..7ae651e0b4e61f 100644 --- a/doc/next/3-tools.md +++ b/doc/next/3-tools.md @@ -45,7 +45,6 @@ the files but instead print the necessary changes as a unified diff. It exits with a non-zero code if updates are needed. - The `go` `list` `-m` `-json` command now includes new `Sum` and `GoModSum` fields. This is similar to the existing behavior of the `go` `mod` `download` `-json` command. From 879ace143490dba75a8499c7f4cea43926423c0f Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 17 Jun 2024 12:30:19 -0700 Subject: [PATCH 07/41] net/http: keep Content-Encoding in Error, add GODEBUG for ServeContent This reverts the changes to Error from CL 571995, and adds a GODEBUG controlling the changes to ServeContent/ServeFile/ServeFS. The change to remove the Content-Encoding header when serving an error breaks middleware which sets Content-Encoding: gzip and wraps a ResponseWriter in one which compresses the response body. This middleware already breaks when ServeContent handles a Range request. Correct uses of ServeContent which serve pre-compressed content with a Content-Encoding: gzip header break if we don't remove that header when serving errors. Therefore, we keep the change to ServeContent/ ServeFile/ServeFS, but we add the ability to disable the new behavior by setting GODEBUG=httpservecontentkeepheaders=1. We revert the change to Error, because users who don't want to include a Content-Encoding header in errors can simply remove the header themselves, or not add it in the first place. Fixes #66343 Change-Id: Ic19a24b73624a5ac1a258ed7a8fe7d9bf86c6a38 Reviewed-on: https://go-review.googlesource.com/c/go/+/593157 Reviewed-by: Russ Cox LUCI-TryBot-Result: Go LUCI --- doc/godebug.md | 9 ++++ doc/next/6-stdlib/99-minor/net/http/66343.md | 17 ++++++- src/internal/godebugs/table.go | 1 + src/net/http/fs.go | 37 +++++++++++++-- src/net/http/fs_test.go | 49 ++++++++++++++++---- src/net/http/serve_test.go | 3 +- src/net/http/server.go | 13 ++++-- src/runtime/metrics/doc.go | 5 ++ 8 files changed, 115 insertions(+), 19 deletions(-) diff --git a/doc/godebug.md b/doc/godebug.md index 86e02e820cd855..b3a43664c42cd4 100644 --- a/doc/godebug.md +++ b/doc/godebug.md @@ -200,6 +200,15 @@ This behavior is controlled by the `x509keypairleaf` setting. For Go 1.23, it defaults to `x509keypairleaf=1`. Previous versions default to `x509keypairleaf=0`. +Go 1.23 changed +[`net/http.ServeContent`](/pkg/net/http#ServeContent), +[`net/http.ServeFile`](/pkg/net/http#ServeFile), and +[`net/http.ServeFS`](/pkg/net/http#ServeFS) to +remove Cache-Control, Content-Encoding, Etag, and Last-Modified headers +when serving an error. This behavior is controlled by +the [`httpservecontentkeepheaders` setting](/pkg/net/http#ServeContent). +Using `httpservecontentkeepheaders=1` restores the pre-Go 1.23 behavior. + ### Go 1.22 Go 1.22 adds a configurable limit to control the maximum acceptable RSA key size diff --git a/doc/next/6-stdlib/99-minor/net/http/66343.md b/doc/next/6-stdlib/99-minor/net/http/66343.md index 128ce68d45ebeb..b39e8624e7def1 100644 --- a/doc/next/6-stdlib/99-minor/net/http/66343.md +++ b/doc/next/6-stdlib/99-minor/net/http/66343.md @@ -1 +1,16 @@ -[Error] now removes misleading response headers. +[ServeContent], [ServeFile], and [ServeFileFS] now remove +the `Cache-Control`, `Content-Encoding`, `Etag`, and `Last-Modified` +headers when serving an error. These headers usually apply to the +non-error content, but not to the text of errors. + +Middleware which wraps a [ResponseWriter] and applies on-the-fly +encoding, such as `Content-Encoding: gzip`, will not function after +this change. The previous behavior of [ServeContent], [ServeFile], +and [ServeFileFS] may be restored by setting +`GODEBUG=httpservecontentkeepheaders=1`. + +Note that middleware which changes the size of the served content +(such as by compressing it) already does not function properly when +[ServeContent] handles a Range request. On-the-fly compression +should use the `Transfer-Encoding` header instead of `Content-Encoding`. + diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go index eb512559168c32..f4262b6695d032 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go @@ -36,6 +36,7 @@ var All = []Info{ {Name: "http2server", Package: "net/http"}, {Name: "httplaxcontentlength", Package: "net/http", Changed: 22, Old: "1"}, {Name: "httpmuxgo121", Package: "net/http", Changed: 22, Old: "1"}, + {Name: "httpservecontentkeepheaders", Package: "net/http", Changed: 23, Old: "0"}, {Name: "installgoroot", Package: "go/build"}, {Name: "jstmpllitinterp", Package: "html/template", Opaque: true}, // bug #66217: remove Opaque //{Name: "multipartfiles", Package: "mime/multipart"}, diff --git a/src/net/http/fs.go b/src/net/http/fs.go index c213d8a328564c..70653550f027f6 100644 --- a/src/net/http/fs.go +++ b/src/net/http/fs.go @@ -9,6 +9,7 @@ package http import ( "errors" "fmt" + "internal/godebug" "io" "io/fs" "mime" @@ -171,15 +172,37 @@ func dirList(w ResponseWriter, r *Request, f File) { fmt.Fprintf(w, "\n") } +// GODEBUG=httpservecontentkeepheaders=1 restores the pre-1.23 behavior of not deleting +// Cache-Control, Content-Encoding, Etag, or Last-Modified headers on ServeContent errors. +var httpservecontentkeepheaders = godebug.New("httpservecontentkeepheaders") + // serveError serves an error from ServeFile, ServeFileFS, and ServeContent. // Because those can all be configured by the caller by setting headers like // Etag, Last-Modified, and Cache-Control to send on a successful response, // the error path needs to clear them, since they may not be meant for errors. func serveError(w ResponseWriter, text string, code int) { h := w.Header() - h.Del("Etag") - h.Del("Last-Modified") - h.Del("Cache-Control") + + nonDefault := false + for _, k := range []string{ + "Cache-Control", + "Content-Encoding", + "Etag", + "Last-Modified", + } { + if !h.has(k) { + continue + } + if httpservecontentkeepheaders.Value() == "1" { + nonDefault = true + } else { + h.Del(k) + } + } + if nonDefault { + httpservecontentkeepheaders.IncNonDefault() + } + Error(w, text, code) } @@ -203,11 +226,17 @@ func serveError(w ResponseWriter, text string, code int) { // // The content's Seek method must work: ServeContent uses // a seek to the end of the content to determine its size. +// Note that [*os.File] implements the [io.ReadSeeker] interface. // // If the caller has set w's ETag header formatted per RFC 7232, section 2.3, // ServeContent uses it to handle requests using If-Match, If-None-Match, or If-Range. // -// Note that [*os.File] implements the [io.ReadSeeker] interface. +// If an error occurs when serving the request (for example, when +// handling an invalid range request), ServeContent responds with an +// error message. By default, ServeContent strips the Cache-Control, +// Content-Encoding, ETag, and Last-Modified headers from error responses. +// The GODEBUG setting httpservecontentkeepheaders=1 causes ServeContent +// to preserve these headers. func ServeContent(w ResponseWriter, req *Request, name string, modtime time.Time, content io.ReadSeeker) { sizeFunc := func() (int64, error) { size, err := content.Seek(0, io.SeekEnd) diff --git a/src/net/http/fs_test.go b/src/net/http/fs_test.go index 2c3426f735271f..2ffffbf0b33c97 100644 --- a/src/net/http/fs_test.go +++ b/src/net/http/fs_test.go @@ -1223,8 +1223,20 @@ type issue12991File struct{ File } func (issue12991File) Stat() (fs.FileInfo, error) { return nil, fs.ErrPermission } func (issue12991File) Close() error { return nil } -func TestFileServerErrorMessages(t *testing.T) { run(t, testFileServerErrorMessages) } -func testFileServerErrorMessages(t *testing.T, mode testMode) { +func TestFileServerErrorMessages(t *testing.T) { + run(t, func(t *testing.T, mode testMode) { + t.Run("keepheaders=0", func(t *testing.T) { + testFileServerErrorMessages(t, mode, false) + }) + t.Run("keepheaders=1", func(t *testing.T) { + testFileServerErrorMessages(t, mode, true) + }) + }, testNotParallel) +} +func testFileServerErrorMessages(t *testing.T, mode testMode, keepHeaders bool) { + if keepHeaders { + t.Setenv("GODEBUG", "httpservecontentkeepheaders=1") + } fs := fakeFS{ "/500": &fakeFileInfo{ err: errors.New("random error"), @@ -1254,8 +1266,12 @@ func testFileServerErrorMessages(t *testing.T, mode testMode) { t.Errorf("GET /%d: StatusCode = %d; want %d", code, res.StatusCode, code) } for _, hdr := range []string{"Etag", "Last-Modified", "Cache-Control"} { - if v, ok := res.Header[hdr]; ok { - t.Errorf("GET /%d: Header[%q] = %q, want not present", code, hdr, v) + if v, got := res.Header[hdr]; got != keepHeaders { + want := "not present" + if keepHeaders { + want = "present" + } + t.Errorf("GET /%d: Header[%q] = %q, want %v", code, hdr, v, want) } } } @@ -1710,6 +1726,17 @@ func testFileServerDirWithRootFile(t *testing.T, mode testMode) { } func TestServeContentHeadersWithError(t *testing.T) { + t.Run("keepheaders=0", func(t *testing.T) { + testServeContentHeadersWithError(t, false) + }) + t.Run("keepheaders=1", func(t *testing.T) { + testServeContentHeadersWithError(t, true) + }) +} +func testServeContentHeadersWithError(t *testing.T, keepHeaders bool) { + if keepHeaders { + t.Setenv("GODEBUG", "httpservecontentkeepheaders=1") + } contents := []byte("content") ts := newClientServerTest(t, http1Mode, HandlerFunc(func(w ResponseWriter, r *Request) { w.Header().Set("Content-Type", "application/octet-stream") @@ -1738,6 +1765,12 @@ func TestServeContentHeadersWithError(t *testing.T) { out, _ := io.ReadAll(res.Body) res.Body.Close() + ifKept := func(s string) string { + if keepHeaders { + return s + } + return "" + } if g, e := res.StatusCode, 416; g != e { t.Errorf("got status = %d; want %d", g, e) } @@ -1750,16 +1783,16 @@ func TestServeContentHeadersWithError(t *testing.T) { if g, e := res.Header.Get("Content-Length"), strconv.Itoa(len(out)); g != e { t.Errorf("got content-length = %q, want %q", g, e) } - if g, e := res.Header.Get("Content-Encoding"), ""; g != e { + if g, e := res.Header.Get("Content-Encoding"), ifKept("gzip"); g != e { t.Errorf("got content-encoding = %q, want %q", g, e) } - if g, e := res.Header.Get("Etag"), ""; g != e { + if g, e := res.Header.Get("Etag"), ifKept(`"abcdefgh"`); g != e { t.Errorf("got etag = %q, want %q", g, e) } - if g, e := res.Header.Get("Last-Modified"), ""; g != e { + if g, e := res.Header.Get("Last-Modified"), ifKept("Wed, 21 Oct 2015 07:28:00 GMT"); g != e { t.Errorf("got last-modified = %q, want %q", g, e) } - if g, e := res.Header.Get("Cache-Control"), ""; g != e { + if g, e := res.Header.Get("Cache-Control"), ifKept("immutable"); g != e { t.Errorf("got cache-control = %q, want %q", g, e) } if g, e := res.Header.Get("Content-Range"), "bytes */7"; g != e { diff --git a/src/net/http/serve_test.go b/src/net/http/serve_test.go index 06bf5089d8fe63..3ec10c2f14da56 100644 --- a/src/net/http/serve_test.go +++ b/src/net/http/serve_test.go @@ -7166,13 +7166,12 @@ func testErrorContentLength(t *testing.T, mode testMode) { func TestError(t *testing.T) { w := httptest.NewRecorder() w.Header().Set("Content-Length", "1") - w.Header().Set("Content-Encoding", "ascii") w.Header().Set("X-Content-Type-Options", "scratch and sniff") w.Header().Set("Other", "foo") Error(w, "oops", 432) h := w.Header() - for _, hdr := range []string{"Content-Length", "Content-Encoding"} { + for _, hdr := range []string{"Content-Length"} { if v, ok := h[hdr]; ok { t.Errorf("%s: %q, want not present", hdr, v) } diff --git a/src/net/http/server.go b/src/net/http/server.go index 190f56501379b0..a5e98f1d957dcb 100644 --- a/src/net/http/server.go +++ b/src/net/http/server.go @@ -2226,17 +2226,22 @@ func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) { // writes are done to w. // The error message should be plain text. // -// Error deletes the Content-Length and Content-Encoding headers, +// Error deletes the Content-Length header, // sets Content-Type to “text/plain; charset=utf-8”, // and sets X-Content-Type-Options to “nosniff”. // This configures the header properly for the error message, // in case the caller had set it up expecting a successful output. func Error(w ResponseWriter, error string, code int) { h := w.Header() - // We delete headers which might be valid for some other content, - // but not anymore for the error content. + + // Delete the Content-Length header, which might be for some other content. + // Assuming the error string fits in the writer's buffer, we'll figure + // out the correct Content-Length for it later. + // + // We don't delete Content-Encoding, because some middleware sets + // Content-Encoding: gzip and wraps the ResponseWriter to compress on-the-fly. + // See https://go.dev/issue/66343. h.Del("Content-Length") - h.Del("Content-Encoding") // There might be content type already set, but we reset it to // text/plain for the error message. diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go index c1d0ca90727e84..b8be9f8272ba76 100644 --- a/src/runtime/metrics/doc.go +++ b/src/runtime/metrics/doc.go @@ -267,6 +267,11 @@ Below is the full list of supported metrics, ordered lexicographically. The number of non-default behaviors executed by the net/http package due to a non-default GODEBUG=httpmuxgo121=... setting. + /godebug/non-default-behavior/httpservecontentkeepheaders:events + The number of non-default behaviors executed + by the net/http package due to a non-default + GODEBUG=httpservecontentkeepheaders=... setting. + /godebug/non-default-behavior/installgoroot:events The number of non-default behaviors executed by the go/build package due to a non-default GODEBUG=installgoroot=... setting. From 4f77a83589baa5a3038cc6e35615084dc7e5f0c1 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Thu, 30 May 2024 14:31:40 -0700 Subject: [PATCH 08/41] internal/syscall/unix: fix UTIME_OMIT for dragonfly CL 219638 added UTIME_OMIT values for various systems. The value for DragonFly BSD appears to be incorrect. The correct value is -2 (see references below), while -1 is used for UTIME_NOW. As a result, timestamp is changed to the current time instead of not touching. This should have been caught by the accompanying test case, TestChtimesWithZeroTimes, but its failures are essentially skipped on dragonfly (this is being fixed separately in a followup CL 591535). Improve formatting while at it. References: - https://github.com/DragonFlyBSD/DragonFlyBSD/blob/965b380e9609/sys/sys/stat.h#L284 - https://go.googlesource.com/sys/+/refs/tags/v0.20.0/unix/zerrors_dragonfly_amd64.go#1421 Change-Id: I432360ca982c84b7cd70d0cf01d860af9ff985fa Reviewed-on: https://go-review.googlesource.com/c/go/+/589496 LUCI-TryBot-Result: Go LUCI Reviewed-by: Cherry Mui Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Commit-Queue: Ian Lance Taylor --- src/internal/syscall/unix/at_sysnum_dragonfly.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/internal/syscall/unix/at_sysnum_dragonfly.go b/src/internal/syscall/unix/at_sysnum_dragonfly.go index 9ac1f919f147a5..a8164dcc8ec7be 100644 --- a/src/internal/syscall/unix/at_sysnum_dragonfly.go +++ b/src/internal/syscall/unix/at_sysnum_dragonfly.go @@ -6,15 +6,15 @@ package unix import "syscall" -const unlinkatTrap uintptr = syscall.SYS_UNLINKAT -const openatTrap uintptr = syscall.SYS_OPENAT -const fstatatTrap uintptr = syscall.SYS_FSTATAT - const ( + unlinkatTrap uintptr = syscall.SYS_UNLINKAT + openatTrap uintptr = syscall.SYS_OPENAT + fstatatTrap uintptr = syscall.SYS_FSTATAT + AT_EACCESS = 0x4 AT_FDCWD = 0xfffafdcd AT_REMOVEDIR = 0x2 AT_SYMLINK_NOFOLLOW = 0x1 - UTIME_OMIT = -0x1 + UTIME_OMIT = -0x2 ) From 477ad7dd5151a2cb54fb68aa84ccbe9bb96ffbee Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 20 Jun 2024 22:58:24 +0700 Subject: [PATCH 09/41] cmd/compile: support generic alias type Type parameters on aliases are now allowed after #46477 accepted. Updates #46477 Fixes #68054 Change-Id: Ic2e3b6f960a898163f47666e3a6bfe43b8cc22e2 Reviewed-on: https://go-review.googlesource.com/c/go/+/593715 Reviewed-by: Robert Griesemer Reviewed-by: Matthew Dempsky LUCI-TryBot-Result: Go LUCI Auto-Submit: Robert Griesemer --- src/cmd/compile/internal/noder/writer.go | 13 ++++++++++++- test/fixedbugs/issue68054.go | 23 +++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 test/fixedbugs/issue68054.go diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go index 9b33fb7c6dcaa5..fe8f8f2a351394 100644 --- a/src/cmd/compile/internal/noder/writer.go +++ b/src/cmd/compile/internal/noder/writer.go @@ -543,7 +543,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo { case *types2.Alias: w.Code(pkgbits.TypeNamed) - w.namedType(typ.Obj(), nil) + w.namedType(splitAlias(typ)) case *types2.TypeParam: w.derived = true @@ -2958,6 +2958,9 @@ func objTypeParams(obj types2.Object) *types2.TypeParamList { if !obj.IsAlias() { return obj.Type().(*types2.Named).TypeParams() } + if alias, ok := obj.Type().(*types2.Alias); ok { + return alias.TypeParams() + } } return nil } @@ -2974,6 +2977,14 @@ func splitNamed(typ *types2.Named) (*types2.TypeName, *types2.TypeList) { return typ.Obj(), typ.TypeArgs() } +// splitAlias is like splitNamed, but for an alias type. +func splitAlias(typ *types2.Alias) (*types2.TypeName, *types2.TypeList) { + orig := typ.Origin() + base.Assertf(typ.Obj() == orig.Obj(), "alias type %v has object %v, but %v has object %v", typ, typ.Obj(), orig, orig.Obj()) + + return typ.Obj(), typ.TypeArgs() +} + func asPragmaFlag(p syntax.Pragma) ir.PragmaFlag { if p == nil { return 0 diff --git a/test/fixedbugs/issue68054.go b/test/fixedbugs/issue68054.go new file mode 100644 index 00000000000000..5409fc90818003 --- /dev/null +++ b/test/fixedbugs/issue68054.go @@ -0,0 +1,23 @@ +// compile -goexperiment aliastypeparams + +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +type Seq[V any] = func(yield func(V) bool) + +func f[E any](seq Seq[E]) { + return +} + +func g() { + f(Seq[int](nil)) +} + +type T[P any] struct{} + +type A[P any] = T[P] + +var _ A[int] From 9d33956503c0d96c0c5666d374173f7ac9756d98 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Thu, 20 Jun 2024 10:23:42 -0700 Subject: [PATCH 10/41] internal/godebugs: fix old value for httpservecontentkeepheaders The pre-Go 1.23 behavior is httpservecontentkeepheaders=1. For #66343 Change-Id: If6f92853b38522f19a8908ff11ac49b12f3dc3e0 Reviewed-on: https://go-review.googlesource.com/c/go/+/593775 Reviewed-by: David Chase Auto-Submit: Damien Neil LUCI-TryBot-Result: Go LUCI --- src/internal/godebugs/table.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go index f4262b6695d032..4c084635fbe1b0 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go @@ -36,7 +36,7 @@ var All = []Info{ {Name: "http2server", Package: "net/http"}, {Name: "httplaxcontentlength", Package: "net/http", Changed: 22, Old: "1"}, {Name: "httpmuxgo121", Package: "net/http", Changed: 22, Old: "1"}, - {Name: "httpservecontentkeepheaders", Package: "net/http", Changed: 23, Old: "0"}, + {Name: "httpservecontentkeepheaders", Package: "net/http", Changed: 23, Old: "1"}, {Name: "installgoroot", Package: "go/build"}, {Name: "jstmpllitinterp", Package: "html/template", Opaque: true}, // bug #66217: remove Opaque //{Name: "multipartfiles", Package: "mime/multipart"}, From 20b79fd5775c39061d949569743912ad5e58b0e7 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Thu, 2 May 2024 14:29:16 -0400 Subject: [PATCH 11/41] time: provide non-default metric for asynctimerchan The original implementation could not support a non-default metric, but now that it is set during package time, we can. Do that. Change-Id: If7929b0afa5b0142d299718d9bd811c5a8d1cf93 Reviewed-on: https://go-review.googlesource.com/c/go/+/589058 Reviewed-by: Michael Knyszek LUCI-TryBot-Result: Go LUCI --- src/internal/godebugs/table.go | 2 +- src/runtime/metrics/doc.go | 4 ++++ src/time/sleep.go | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/internal/godebugs/table.go b/src/internal/godebugs/table.go index 4c084635fbe1b0..a802ac9c3708d1 100644 --- a/src/internal/godebugs/table.go +++ b/src/internal/godebugs/table.go @@ -25,7 +25,7 @@ type Info struct { // Note: After adding entries to this table, update the list in doc/godebug.md as well. // (Otherwise the test in this package will fail.) var All = []Info{ - {Name: "asynctimerchan", Package: "time", Changed: 23, Old: "1", Opaque: true}, + {Name: "asynctimerchan", Package: "time", Changed: 23, Old: "1"}, {Name: "execerrdot", Package: "os/exec"}, {Name: "gocachehash", Package: "cmd/go"}, {Name: "gocachetest", Package: "cmd/go"}, diff --git a/src/runtime/metrics/doc.go b/src/runtime/metrics/doc.go index b8be9f8272ba76..da3d956d480beb 100644 --- a/src/runtime/metrics/doc.go +++ b/src/runtime/metrics/doc.go @@ -230,6 +230,10 @@ Below is the full list of supported metrics, ordered lexicographically. /gc/stack/starting-size:bytes The stack size of new goroutines. + /godebug/non-default-behavior/asynctimerchan:events + The number of non-default behaviors executed by the time package + due to a non-default GODEBUG=asynctimerchan=... setting. + /godebug/non-default-behavior/execerrdot:events The number of non-default behaviors executed by the os/exec package due to a non-default GODEBUG=execerrdot=... setting. diff --git a/src/time/sleep.go b/src/time/sleep.go index 2c6495d93a704d..7e2fa0c20af46e 100644 --- a/src/time/sleep.go +++ b/src/time/sleep.go @@ -23,6 +23,7 @@ func syncTimer(c chan Time) unsafe.Pointer { // If asynctimerchan=1, we don't even tell the runtime // about channel timers, so that we get the pre-Go 1.23 code paths. if asynctimerchan.Value() == "1" { + asynctimerchan.IncNonDefault() return nil } From 201129414ffc72ce05c170ef2a4627768e890f24 Mon Sep 17 00:00:00 2001 From: Austin Clements Date: Tue, 18 Jun 2024 22:12:35 -0400 Subject: [PATCH 12/41] sync/atomic: correct result names for Or methods A few of the new Or methods of the atomic types use "new" as the name for the result value, but it actually returns the old value. Fix this by renaming the result values to "old". Updates #61395. Change-Id: Ib08db9964f5dfe91929f216d50ff0c9cc891ee49 Reviewed-on: https://go-review.googlesource.com/c/go/+/593855 Reviewed-by: Keith Randall Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI Auto-Submit: Austin Clements Reviewed-by: Mauri de Souza Meneguzzo --- src/sync/atomic/type.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sync/atomic/type.go b/src/sync/atomic/type.go index 7d2b6805bca85d..f487cb9c5f7eaa 100644 --- a/src/sync/atomic/type.go +++ b/src/sync/atomic/type.go @@ -156,7 +156,7 @@ func (x *Uint32) And(mask uint32) (old uint32) { return AndUint32(&x.v, mask) } // Or atomically performs a bitwise OR operation on x using the bitmask // provided as mask and returns the old value. -func (x *Uint32) Or(mask uint32) (new uint32) { return OrUint32(&x.v, mask) } +func (x *Uint32) Or(mask uint32) (old uint32) { return OrUint32(&x.v, mask) } // A Uint64 is an atomic uint64. The zero value is zero. type Uint64 struct { @@ -188,7 +188,7 @@ func (x *Uint64) And(mask uint64) (old uint64) { return AndUint64(&x.v, mask) } // Or atomically performs a bitwise OR operation on x using the bitmask // provided as mask and returns the old value. -func (x *Uint64) Or(mask uint64) (new uint64) { return OrUint64(&x.v, mask) } +func (x *Uint64) Or(mask uint64) (old uint64) { return OrUint64(&x.v, mask) } // A Uintptr is an atomic uintptr. The zero value is zero. type Uintptr struct { From d67839f58af518bfa32e27962059291362186e1c Mon Sep 17 00:00:00 2001 From: Clide Stefani Date: Thu, 13 Jun 2024 14:57:12 -0400 Subject: [PATCH 13/41] crypto/tls: add support for -expect-version to bogo_shim_test The existing implementation of bogo_shim_test does not support tests that use the expect-version flag. This change adds support for this flag. Updates #51434. Change-Id: Ie23fdb06d15ec0593ca58f28144e83f93ef7f200 Reviewed-on: https://go-review.googlesource.com/c/go/+/592635 Auto-Submit: Roland Shoemaker LUCI-TryBot-Result: Go LUCI Reviewed-by: Roland Shoemaker Reviewed-by: David Chase --- src/crypto/tls/bogo_shim_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/crypto/tls/bogo_shim_test.go b/src/crypto/tls/bogo_shim_test.go index 5dc3b7c13ea791..2d8100d1bbf36a 100644 --- a/src/crypto/tls/bogo_shim_test.go +++ b/src/crypto/tls/bogo_shim_test.go @@ -33,8 +33,9 @@ var ( trustCert = flag.String("trust-cert", "", "") - minVersion = flag.Int("min-version", VersionSSL30, "") - maxVersion = flag.Int("max-version", VersionTLS13, "") + minVersion = flag.Int("min-version", VersionSSL30, "") + maxVersion = flag.Int("max-version", VersionTLS13, "") + expectVersion = flag.Int("expect-version", 0, "") noTLS13 = flag.Bool("no-tls13", false, "") @@ -252,7 +253,9 @@ func bogoShim() { if *expectALPN != "" && cs.NegotiatedProtocol != *expectALPN { log.Fatalf("unexpected protocol negotiated: want %q, got %q", *expectALPN, cs.NegotiatedProtocol) } - + if *expectVersion != 0 && cs.Version != uint16(*expectVersion) { + log.Fatalf("expected ssl version %q, got %q", uint16(*expectVersion), cs.Version) + } if *expectECHAccepted && !cs.ECHAccepted { log.Fatal("expected ECH to be accepted, but connection state shows it was not") } else if i == 0 && *onInitialExpectECHAccepted && !cs.ECHAccepted { From 6fea4094242fe4e7be8bd7ec0b55df9f6df3f025 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Fri, 14 Jun 2024 09:48:09 +1000 Subject: [PATCH 14/41] text/template/parse: fix handling of assignment/declaration in PipeNode.String The String method for Pipes assumed all variables were declared. Easy fix: check the IsAssign bit. Fixes #65382 Change-Id: I58f2760c1a8bb2821c3538645d893f58fd76ae73 Reviewed-on: https://go-review.googlesource.com/c/go/+/592695 Run-TryBot: Rob Pike Reviewed-by: David Chase Reviewed-by: Ian Lance Taylor Auto-Submit: Rob Pike TryBot-Result: Gopher Robot LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor --- src/text/template/parse/node.go | 6 +++++- src/text/template/parse/parse_test.go | 3 +++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/src/text/template/parse/node.go b/src/text/template/parse/node.go index 23ba9aec2be841..a31309874d9da3 100644 --- a/src/text/template/parse/node.go +++ b/src/text/template/parse/node.go @@ -217,7 +217,11 @@ func (p *PipeNode) writeTo(sb *strings.Builder) { } v.writeTo(sb) } - sb.WriteString(" := ") + if p.IsAssign { + sb.WriteString(" = ") + } else { + sb.WriteString(" := ") + } } for i, c := range p.Cmds { if i > 0 { diff --git a/src/text/template/parse/parse_test.go b/src/text/template/parse/parse_test.go index faf226d1c3cac2..26aff330fe8a27 100644 --- a/src/text/template/parse/parse_test.go +++ b/src/text/template/parse/parse_test.go @@ -306,6 +306,9 @@ var parseTests = []parseTest{ {"bug1a", "{{$x:=.}}{{$x!2}}", hasError, ""}, // ! is just illegal here. {"bug1b", "{{$x:=.}}{{$x+2}}", hasError, ""}, // $x+2 should not parse as ($x) (+2). {"bug1c", "{{$x:=.}}{{$x +2}}", noError, "{{$x := .}}{{$x +2}}"}, // It's OK with a space. + // Check the range handles assignment vs. declaration properly. + {"bug2a", "{{range $x := 0}}{{$x}}{{end}}", noError, "{{range $x := 0}}{{$x}}{{end}}"}, + {"bug2b", "{{range $x = 0}}{{$x}}{{end}}", noError, "{{range $x = 0}}{{$x}}{{end}}"}, // dot following a literal value {"dot after integer", "{{1.E}}", hasError, ""}, {"dot after float", "{{0.1.E}}", hasError, ""}, From e9a306e004fb6e9c6ca6045151be0ca8bddd242b Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Fri, 21 Jun 2024 14:45:26 +0700 Subject: [PATCH 15/41] types2, go/types: correct NewTypeParam documentation Signature type does not have SetTypeParams method, only Named type. Change-Id: Ic7a25c24cb821540d921eb2c94dfff31f28f7aa4 Reviewed-on: https://go-review.googlesource.com/c/go/+/593955 Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI Reviewed-by: Robert Findley Auto-Submit: Cuong Manh Le --- src/cmd/compile/internal/types2/typeparam.go | 4 ++-- src/go/types/typeparam.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 9ad064906fb25b..e22981e1ad0c00 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -25,8 +25,8 @@ type TypeParam struct { } // NewTypeParam returns a new TypeParam. Type parameters may be set on a Named -// or Signature type by calling SetTypeParams. Setting a type parameter on more -// than one type will result in a panic. +// type by calling SetTypeParams. Setting a type parameter on more than one type +// will result in a panic. // // The constraint argument can be nil, and set later via SetConstraint. If the // constraint is non-nil, it must be fully defined. diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 58a02de86029b1..789b63d7a15aae 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -28,8 +28,8 @@ type TypeParam struct { } // NewTypeParam returns a new TypeParam. Type parameters may be set on a Named -// or Signature type by calling SetTypeParams. Setting a type parameter on more -// than one type will result in a panic. +// type by calling SetTypeParams. Setting a type parameter on more than one type +// will result in a panic. // // The constraint argument can be nil, and set later via SetConstraint. If the // constraint is non-nil, it must be fully defined. From 72e2220b50db5179ddca2226a64bf1d3aa94f49a Mon Sep 17 00:00:00 2001 From: Jes Cok Date: Tue, 18 Jun 2024 23:43:21 +0800 Subject: [PATCH 16/41] encoding/json: clarify the map's key type for Unmarshal While here, also fix doc link for encoding.TextMarshaler. Fixes #67495 Change-Id: Ia2a674c5c35b5a849ce8f5eef3d34d165b3195b6 Reviewed-on: https://go-review.googlesource.com/c/go/+/593335 LUCI-TryBot-Result: Go LUCI Reviewed-by: Joseph Tsai Reviewed-by: David Chase Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor --- src/encoding/json/decode.go | 3 +-- src/encoding/json/encode.go | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/encoding/json/decode.go b/src/encoding/json/decode.go index efceecdf82b04d..f8205704e38b7f 100644 --- a/src/encoding/json/decode.go +++ b/src/encoding/json/decode.go @@ -73,8 +73,7 @@ import ( // use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal // reuses the existing map, keeping existing entries. Unmarshal then stores // key-value pairs from the JSON object into the map. The map's key type must -// either be any string type, an integer, implement [json.Unmarshaler], or -// implement [encoding.TextUnmarshaler]. +// either be any string type, an integer, or implement [encoding.TextUnmarshaler]. // // If the JSON-encoded data contain a syntax error, Unmarshal returns a [SyntaxError]. // diff --git a/src/encoding/json/encode.go b/src/encoding/json/encode.go index cb28feb279f6c0..7bee1a6805f4dc 100644 --- a/src/encoding/json/encode.go +++ b/src/encoding/json/encode.go @@ -141,7 +141,7 @@ import ( // are sorted and used as JSON object keys by applying the following rules, // subject to the UTF-8 coercion described for string values above: // - keys of any string type are used directly -// - [encoding.TextMarshalers] are marshaled +// - keys that implement [encoding.TextMarshaler] are marshaled // - integer keys are converted to strings // // Pointer values encode as the value pointed to. From 1b4f1dc95d221c1e9d0afb9067fd6a09f12dd061 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Tue, 11 Jun 2024 17:25:06 -0700 Subject: [PATCH 17/41] os: improve newFile, rm newDir 1. Assuming that CI environments do not use NFS (and if they do, they have TMPDIR set pointing to a local file system), we can - remove localTmp; - remove newDir, replacing calls to it with t.TempDir; - remove repeated comments about NFS. 2. Use t.Name, t.Cleanup and t.Helper to improve newFile and simplify its usage. Ensure the cleanup reports all errors. Change-Id: I0a79a6a3d52faa323ed2658ef73f8802847f3c09 Reviewed-on: https://go-review.googlesource.com/c/go/+/592096 Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot Run-TryBot: Kirill Kolyshkin Reviewed-by: David Chase Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI --- src/os/os_test.go | 101 +++++++++++------------------------------ src/os/os_unix_test.go | 30 ++---------- 2 files changed, 32 insertions(+), 99 deletions(-) diff --git a/src/os/os_test.go b/src/os/os_test.go index 7348a9f01caa11..2a6b1bf9f5e104 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -158,28 +158,20 @@ func equal(name1, name2 string) (r bool) { return } -// localTmp returns a local temporary directory not on NFS. -func localTmp() string { - switch runtime.GOOS { - case "android", "ios", "windows": - return TempDir() - } - return "/tmp" -} - -func newFile(testName string, t *testing.T) (f *File) { - f, err := CreateTemp(localTmp(), "_Go_"+testName) - if err != nil { - t.Fatalf("TempFile %s: %s", testName, err) - } - return -} - -func newDir(testName string, t *testing.T) (name string) { - name, err := MkdirTemp(localTmp(), "_Go_"+testName) +func newFile(t *testing.T) (f *File) { + t.Helper() + f, err := CreateTemp("", "_Go_"+t.Name()) if err != nil { - t.Fatalf("TempDir %s: %s", testName, err) + t.Fatal(err) } + t.Cleanup(func() { + if err := f.Close(); err != nil && !errors.Is(err, ErrClosed) { + t.Fatal(err) + } + if err := Remove(f.Name()); err != nil { + t.Fatal(err) + } + }) return } @@ -1276,9 +1268,7 @@ func TestChmod(t *testing.T) { } t.Parallel() - f := newFile("TestChmod", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) // Creation mode is read write fm := FileMode(0456) @@ -1314,9 +1304,7 @@ func checkSize(t *testing.T, f *File, size int64) { func TestFTruncate(t *testing.T) { t.Parallel() - f := newFile("TestFTruncate", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) checkSize(t, f, 0) f.Write([]byte("hello, world\n")) @@ -1336,9 +1324,7 @@ func TestFTruncate(t *testing.T) { func TestTruncate(t *testing.T) { t.Parallel() - f := newFile("TestTruncate", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) checkSize(t, f, 0) f.Write([]byte("hello, world\n")) @@ -1375,15 +1361,10 @@ func TestTruncateNonexistentFile(t *testing.T) { assertPathError(t, path, err) } -// Use TempDir (via newFile) to make sure we're on a local file system, -// so that timings are not distorted by latency and caching. -// On NFS, timings can be off due to caching of meta-data on -// NFS servers (Issue 848). func TestChtimes(t *testing.T) { t.Parallel() - f := newFile("TestChtimes", t) - defer Remove(f.Name()) + f := newFile(t) f.Write([]byte("hello, world\n")) f.Close() @@ -1392,13 +1373,12 @@ func TestChtimes(t *testing.T) { } func TestChtimesWithZeroTimes(t *testing.T) { - file := newFile("chtimes-with-zero", t) + file := newFile(t) _, err := file.Write([]byte("hello, world\n")) if err != nil { t.Fatalf("Write: %s", err) } fName := file.Name() - defer Remove(file.Name()) err = file.Close() if err != nil { t.Errorf("%v", err) @@ -1513,17 +1493,10 @@ func TestChtimesWithZeroTimes(t *testing.T) { } } -// Use TempDir (via newDir) to make sure we're on a local file system, -// so that timings are not distorted by latency and caching. -// On NFS, timings can be off due to caching of meta-data on -// NFS servers (Issue 848). func TestChtimesDir(t *testing.T) { t.Parallel() - name := newDir("TestChtimes", t) - defer RemoveAll(name) - - testChtimes(t, name) + testChtimes(t, t.TempDir()) } func testChtimes(t *testing.T, name string) { @@ -1574,9 +1547,8 @@ func testChtimes(t *testing.T, name string) { } func TestChtimesToUnixZero(t *testing.T) { - file := newFile("chtimes-to-unix-zero", t) + file := newFile(t) fn := file.Name() - defer Remove(fn) if _, err := file.Write([]byte("hi")); err != nil { t.Fatal(err) } @@ -1796,9 +1768,7 @@ func TestProgWideChdir(t *testing.T) { func TestSeek(t *testing.T) { t.Parallel() - f := newFile("TestSeek", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) const data = "hello, world\n" io.WriteString(f, data) @@ -2040,9 +2010,7 @@ func TestHostname(t *testing.T) { func TestReadAt(t *testing.T) { t.Parallel() - f := newFile("TestReadAt", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) const data = "hello, world\n" io.WriteString(f, data) @@ -2064,9 +2032,7 @@ func TestReadAt(t *testing.T) { func TestReadAtOffset(t *testing.T) { t.Parallel() - f := newFile("TestReadAtOffset", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) const data = "hello, world\n" io.WriteString(f, data) @@ -2095,9 +2061,7 @@ func TestReadAtOffset(t *testing.T) { func TestReadAtNegativeOffset(t *testing.T) { t.Parallel() - f := newFile("TestReadAtNegativeOffset", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) const data = "hello, world\n" io.WriteString(f, data) @@ -2116,9 +2080,7 @@ func TestReadAtNegativeOffset(t *testing.T) { func TestWriteAt(t *testing.T) { t.Parallel() - f := newFile("TestWriteAt", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) const data = "hello, world\n" io.WriteString(f, data) @@ -2141,9 +2103,7 @@ func TestWriteAt(t *testing.T) { func TestWriteAtNegativeOffset(t *testing.T) { t.Parallel() - f := newFile("TestWriteAtNegativeOffset", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) n, err := f.WriteAt([]byte("WORLD"), -10) @@ -2477,9 +2437,7 @@ func TestStatRelativeSymlink(t *testing.T) { func TestReadAtEOF(t *testing.T) { t.Parallel() - f := newFile("TestReadAtEOF", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) _, err := f.ReadAt(make([]byte, 10), 0) switch err { @@ -2495,12 +2453,7 @@ func TestReadAtEOF(t *testing.T) { func TestLongPath(t *testing.T) { t.Parallel() - tmpdir := newDir("TestLongPath", t) - defer func(d string) { - if err := RemoveAll(d); err != nil { - t.Fatalf("RemoveAll failed: %v", err) - } - }(tmpdir) + tmpdir := t.TempDir() // Test the boundary of 247 and fewer bytes (normal) and 248 and more bytes (adjusted). sizes := []int{247, 248, 249, 400} diff --git a/src/os/os_unix_test.go b/src/os/os_unix_test.go index 98e436fae6640a..6cbeae1b786d44 100644 --- a/src/os/os_unix_test.go +++ b/src/os/os_unix_test.go @@ -45,13 +45,7 @@ func TestChown(t *testing.T) { } t.Parallel() - // Use TempDir() to make sure we're on a local file system, - // so that the group ids returned by Getgroups will be allowed - // on the file. On NFS, the Getgroups groups are - // basically useless. - f := newFile("TestChown", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) dir, err := f.Stat() if err != nil { t.Fatalf("stat %s: %s", f.Name(), err) @@ -99,13 +93,7 @@ func TestFileChown(t *testing.T) { } t.Parallel() - // Use TempDir() to make sure we're on a local file system, - // so that the group ids returned by Getgroups will be allowed - // on the file. On NFS, the Getgroups groups are - // basically useless. - f := newFile("TestFileChown", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) dir, err := f.Stat() if err != nil { t.Fatalf("stat %s: %s", f.Name(), err) @@ -151,13 +139,7 @@ func TestLchown(t *testing.T) { testenv.MustHaveSymlink(t) t.Parallel() - // Use TempDir() to make sure we're on a local file system, - // so that the group ids returned by Getgroups will be allowed - // on the file. On NFS, the Getgroups groups are - // basically useless. - f := newFile("TestLchown", t) - defer Remove(f.Name()) - defer f.Close() + f := newFile(t) dir, err := f.Stat() if err != nil { t.Fatalf("stat %s: %s", f.Name(), err) @@ -223,8 +205,7 @@ func TestReaddirRemoveRace(t *testing.T) { } return oldStat(name) } - dir := newDir("TestReaddirRemoveRace", t) - defer RemoveAll(dir) + dir := t.TempDir() if err := WriteFile(filepath.Join(dir, "some-file"), []byte("hello"), 0644); err != nil { t.Fatal(err) } @@ -255,8 +236,7 @@ func TestMkdirStickyUmask(t *testing.T) { t.Parallel() const umask = 0077 - dir := newDir("TestMkdirStickyUmask", t) - defer RemoveAll(dir) + dir := t.TempDir() oldUmask := syscall.Umask(umask) defer syscall.Umask(oldUmask) From d73a8a206a7d3c179cdc498a29be215fa48a1ec2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 30 May 2024 22:29:35 -0700 Subject: [PATCH 18/41] cmd/cgo: fail on v, err := C.fn when fn is a builtin function We were already checking for _CMalloc, but in fact none of the builtin functions support returning an error. Fixes #67707 Change-Id: I0ee432a9f13ace472c3f36f641efc7d18eda0631 Reviewed-on: https://go-review.googlesource.com/c/go/+/589575 Auto-Submit: Ian Lance Taylor Reviewed-by: Damien Neil Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI --- src/cmd/cgo/gcc.go | 4 ++-- src/cmd/cgo/internal/testerrors/errors_test.go | 1 + .../internal/testerrors/testdata/issue67707.go | 15 +++++++++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/cmd/cgo/internal/testerrors/testdata/issue67707.go diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index b596477b0a65f1..6c23e59adf19eb 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -1601,8 +1601,8 @@ func (p *Package) rewriteName(f *File, r *Ref, addPosition bool) ast.Expr { break } if r.Context == ctxCall2 { - if r.Name.Go == "_CMalloc" { - error_(r.Pos(), "no two-result form for C.malloc") + if builtinDefs[r.Name.Go] != "" { + error_(r.Pos(), "no two-result form for C.%s", r.Name.Go) break } // Invent new Name for the two-result function. diff --git a/src/cmd/cgo/internal/testerrors/errors_test.go b/src/cmd/cgo/internal/testerrors/errors_test.go index 07556007a84fe8..eddfb6583b9e77 100644 --- a/src/cmd/cgo/internal/testerrors/errors_test.go +++ b/src/cmd/cgo/internal/testerrors/errors_test.go @@ -127,6 +127,7 @@ func TestReportsTypeErrors(t *testing.T) { "issue33061.go", "issue50710.go", "issue67517.go", + "issue67707.go", } { check(t, file) } diff --git a/src/cmd/cgo/internal/testerrors/testdata/issue67707.go b/src/cmd/cgo/internal/testerrors/testdata/issue67707.go new file mode 100644 index 00000000000000..4f80de165e3b19 --- /dev/null +++ b/src/cmd/cgo/internal/testerrors/testdata/issue67707.go @@ -0,0 +1,15 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "C" + +func F() *C.char { + s, err := C.CString("hi") // ERROR HERE: no two-result form + if err != nil { + println(err) + } + return s +} From fed2c11d67dbe6d8179cd411b4bb7761d034e9d2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 18 Jun 2024 17:49:10 -0700 Subject: [PATCH 19/41] iter: minor doc comment updates Remove old return value. Use single variable range for iter.Seq[V]. Rewrite Pairs implementation to not loop forever. Fixes #68056 Fixes #68073 Change-Id: I7ede0fe8ed058bbd57869d87e17b7f2c3641f7dd Reviewed-on: https://go-review.googlesource.com/c/go/+/593555 LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Reviewed-by: Damien Neil Auto-Submit: Ian Lance Taylor Commit-Queue: Ian Lance Taylor Reviewed-by: Mauri de Souza Meneguzzo --- src/iter/iter.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/src/iter/iter.go b/src/iter/iter.go index 4ea919b0724f6d..14fd8f8115f3f6 100644 --- a/src/iter/iter.go +++ b/src/iter/iter.go @@ -31,7 +31,7 @@ element in the sequence, false if it should stop. Iterator functions are most often called by a range loop, as in: func PrintAll[V any](seq iter.Seq[V]) { - for _, v := range seq { + for v := range seq { fmt.Println(v) } } @@ -92,9 +92,8 @@ sequence only once. These “single-use iterators” typically report values from a data stream that cannot be rewound to start over. Calling the iterator again after stopping early may continue the stream, but calling it again after the sequence is finished will yield -no values at all, immediately returning true. Doc comments for -functions or methods that return single-use iterators should document -this fact: +no values at all. Doc comments for functions or methods that return +single-use iterators should document this fact: // Lines returns an iterator over lines read from r. // It returns a single-use iterator. @@ -119,17 +118,24 @@ For example: // Pairs returns an iterator over successive pairs of values from seq. func Pairs[V any](seq iter.Seq[V]) iter.Seq2[V, V] { - return func(yield func(V, V) bool) bool { + return func(yield func(V, V) bool) { next, stop := iter.Pull(seq) defer stop() - v1, ok1 := next() - v2, ok2 := next() - for ok1 || ok2 { + for { + v1, ok1 := next() + if !ok1 { + return + } + v2, ok2 := next() + // If ok2 is false, v2 should be the + // zero value; yield one last pair. if !yield(v1, v2) { - return false + return + } + if !ok2 { + return } } - return true } } From 52ce25b44e8c21f62e95b12497db3036c5bd27c3 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 21 Jun 2024 14:49:21 -0400 Subject: [PATCH 20/41] cmd/vendor: pull in golang.org/x/telemetry@b4de734 Commands run: go get golang.org/x/telemetry@b4de734 go mod tidy go mod vendor For #68109 Change-Id: Ied81cbb111ed66f9bbc94f0db09b5f2430fbff6f Reviewed-on: https://go-review.googlesource.com/c/go/+/594015 Reviewed-by: Robert Findley LUCI-TryBot-Result: Go LUCI --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 ++-- .../golang.org/x/telemetry/counter/counter.go | 18 +++++++++++++++++- src/cmd/vendor/modules.txt | 2 +- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 559ffd1ccdc5b5..0625195931d7bf 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -9,7 +9,7 @@ require ( golang.org/x/mod v0.18.0 golang.org/x/sync v0.7.0 golang.org/x/sys v0.21.0 - golang.org/x/telemetry v0.0.0-20240612191826-8cad58b3fcbb + golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 golang.org/x/term v0.20.0 golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 8f9517bc624754..25276c92b2e8b9 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -16,8 +16,8 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240612191826-8cad58b3fcbb h1:0Ge50tvTqbHEyuQDgCYypgL2afqNjRNdl4GHPJuN9QY= -golang.org/x/telemetry v0.0.0-20240612191826-8cad58b3fcbb/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= +golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 h1:2+8QyQRLYDeEKd+CM/BsuaBaLdhAsNdasS/SnZfPS9g= +golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= diff --git a/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go b/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go index ba1c68889e1ec0..7a7e66b22d1714 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go +++ b/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go @@ -15,6 +15,7 @@ import ( "runtime/debug" "golang.org/x/telemetry/internal/counter" + "golang.org/x/telemetry/internal/telemetry" ) // Inc increments the counter with the given name. @@ -83,11 +84,26 @@ func NewStack(name string, depth int) *StackCounter { // counter file on disk and starts to mmap telemetry counters to the file. // Open also persists any counters already created in the current process. // -// Programs using telemetry should call Open exactly once. +// Programs using telemetry should call either Open or OpenDir exactly once. func Open() { counter.Open() } +// OpenDir prepares telemetry counters for recording to the file system, using +// the specified telemetry directory, if it is not the empty string. +// +// If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the +// counter file on disk and starts to mmap telemetry counters to the file. +// Open also persists any counters already created in the current process. +// +// Programs using telemetry should call either Open or OpenDir exactly once. +func OpenDir(telemetryDir string) { + if telemetryDir != "" { + telemetry.Default = telemetry.NewDir(telemetryDir) + } + counter.Open() +} + // CountFlags creates a counter for every flag that is set // and increments the counter. The name of the counter is // the concatenation of prefix and the flag name. diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 8ba7df290fa0c1..fc1f25588a8363 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -45,7 +45,7 @@ golang.org/x/sync/semaphore golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/telemetry v0.0.0-20240612191826-8cad58b3fcbb +# golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 ## explicit; go 1.20 golang.org/x/telemetry golang.org/x/telemetry/counter From d79c350916c637de911d93af689a5e4e7ab5a5bb Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 21 Jun 2024 14:35:14 -0400 Subject: [PATCH 21/41] cmd/internal: separate counter package from telemetry package Move the code that opens and increments counters out of the cmd/internal/telemetry package into cmd/internal/telemetry/counter. The telemetry package has dependencies on the upload code, which we do not want to pull into the rest of the go toolchain. For #68109 Change-Id: I463c106819b169177a783de4a7d93377e81f4e3e Reviewed-on: https://go-review.googlesource.com/c/go/+/593976 LUCI-TryBot-Result: Go LUCI Reviewed-by: Robert Findley --- src/cmd/addr2line/main.go | 8 +-- src/cmd/asm/main.go | 8 +-- src/cmd/buildid/buildid.go | 8 +-- src/cmd/cgo/main.go | 8 +-- src/cmd/compile/internal/base/flag.go | 4 +- src/cmd/compile/internal/base/print.go | 4 +- src/cmd/compile/internal/gc/main.go | 6 +- src/cmd/covdata/covdata.go | 8 +-- src/cmd/cover/cover.go | 8 +-- src/cmd/dist/buildtool.go | 1 + src/cmd/distpack/pack.go | 8 +-- src/cmd/doc/main.go | 8 +-- src/cmd/fix/main.go | 8 +-- src/cmd/go/internal/help/help.go | 4 +- src/cmd/go/internal/modfetch/cache.go | 4 +- .../internal/telemetrystats/telemetrystats.go | 28 ++++----- .../internal/telemetrystats/version_other.go | 4 +- .../internal/telemetrystats/version_unix.go | 10 +-- .../telemetrystats/version_windows.go | 8 +-- src/cmd/go/internal/tool/tool.go | 10 +-- src/cmd/go/internal/toolchain/select.go | 6 +- src/cmd/go/internal/toolchain/switch.go | 4 +- src/cmd/go/internal/work/buildid.go | 8 +-- src/cmd/go/main.go | 37 +++++------ src/cmd/gofmt/gofmt.go | 8 +-- src/cmd/internal/telemetry/counter/counter.go | 62 +++++++++++++++++++ .../telemetry/counter/counter_bootstrap.go | 20 ++++++ src/cmd/internal/telemetry/telemetry.go | 52 +--------------- .../internal/telemetry/telemetry_bootstrap.go | 22 ++----- src/cmd/link/internal/ld/main.go | 8 +-- src/cmd/nm/nm.go | 8 +-- src/cmd/objdump/main.go | 8 +-- src/cmd/pack/pack.go | 8 +-- src/cmd/pprof/pprof.go | 8 +-- src/cmd/preprofile/main.go | 8 +-- src/cmd/test2json/main.go | 8 +-- src/cmd/trace/main.go | 8 +-- src/cmd/vet/main.go | 8 +-- 38 files changed, 236 insertions(+), 210 deletions(-) create mode 100644 src/cmd/internal/telemetry/counter/counter.go create mode 100644 src/cmd/internal/telemetry/counter/counter_bootstrap.go diff --git a/src/cmd/addr2line/main.go b/src/cmd/addr2line/main.go index b1ec4e02785d73..500da717ff3f2d 100644 --- a/src/cmd/addr2line/main.go +++ b/src/cmd/addr2line/main.go @@ -28,7 +28,7 @@ import ( "strings" "cmd/internal/objfile" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func printUsage(w *os.File) { @@ -46,7 +46,7 @@ func usage() { func main() { log.SetFlags(0) log.SetPrefix("addr2line: ") - telemetry.OpenCounters() + counter.Open() // pprof expects this behavior when checking for addr2line if len(os.Args) > 1 && os.Args[1] == "--help" { @@ -56,8 +56,8 @@ func main() { flag.Usage = usage flag.Parse() - telemetry.Inc("addr2line/invocations") - telemetry.CountFlags("addr2line/flag:", *flag.CommandLine) + counter.Inc("addr2line/invocations") + counter.CountFlags("addr2line/flag:", *flag.CommandLine) if flag.NArg() != 1 { usage() } diff --git a/src/cmd/asm/main.go b/src/cmd/asm/main.go index ca4e25d047c4a9..9fdb7c49a2bb56 100644 --- a/src/cmd/asm/main.go +++ b/src/cmd/asm/main.go @@ -20,20 +20,20 @@ import ( "cmd/internal/bio" "cmd/internal/obj" "cmd/internal/objabi" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func main() { log.SetFlags(0) log.SetPrefix("asm: ") - telemetry.OpenCounters() + counter.Open() buildcfg.Check() GOARCH := buildcfg.GOARCH flags.Parse() - telemetry.Inc("asm/invocations") - telemetry.CountFlags("asm/flag:", *flag.CommandLine) + counter.Inc("asm/invocations") + counter.CountFlags("asm/flag:", *flag.CommandLine) architecture := arch.Set(GOARCH, *flags.Shared || *flags.Dynlink) if architecture == nil { diff --git a/src/cmd/buildid/buildid.go b/src/cmd/buildid/buildid.go index a008122a0aa743..a16b96f677a676 100644 --- a/src/cmd/buildid/buildid.go +++ b/src/cmd/buildid/buildid.go @@ -12,7 +12,7 @@ import ( "strings" "cmd/internal/buildid" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func usage() { @@ -26,11 +26,11 @@ var wflag = flag.Bool("w", false, "write build ID") func main() { log.SetPrefix("buildid: ") log.SetFlags(0) - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("buildid/invocations") - telemetry.CountFlags("buildid/flag:", *flag.CommandLine) + counter.Inc("buildid/invocations") + counter.CountFlags("buildid/flag:", *flag.CommandLine) if flag.NArg() != 1 { usage() } diff --git a/src/cmd/cgo/main.go b/src/cmd/cgo/main.go index bf879be814fe99..156038b33b410c 100644 --- a/src/cmd/cgo/main.go +++ b/src/cmd/cgo/main.go @@ -28,7 +28,7 @@ import ( "cmd/internal/edit" "cmd/internal/notsha256" "cmd/internal/objabi" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) // A Package collects information about the package we're going to write. @@ -258,11 +258,11 @@ var goarch, goos, gomips, gomips64 string var gccBaseCmd []string func main() { - telemetry.OpenCounters() + counter.Open() objabi.AddVersionFlag() // -V objabi.Flagparse(usage) - telemetry.Inc("cgo/invocations") - telemetry.CountFlags("cgo/flag:", *flag.CommandLine) + counter.Inc("cgo/invocations") + counter.CountFlags("cgo/flag:", *flag.CommandLine) if *gccgoDefineCgoIncomplete { if !*gccgo { diff --git a/src/cmd/compile/internal/base/flag.go b/src/cmd/compile/internal/base/flag.go index 8c17c5f27d8802..b296f3666cf475 100644 --- a/src/cmd/compile/internal/base/flag.go +++ b/src/cmd/compile/internal/base/flag.go @@ -6,7 +6,7 @@ package base import ( "cmd/internal/cov/covcmd" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "encoding/json" "flag" "fmt" @@ -195,7 +195,7 @@ func ParseFlags() { objabi.AddVersionFlag() // -V registerFlags() objabi.Flagparse(usage) - telemetry.CountFlags("compile/flag:", *flag.CommandLine) + counter.CountFlags("compile/flag:", *flag.CommandLine) if gcd := os.Getenv("GOCOMPILEDEBUG"); gcd != "" { // This will only override the flags set in gcd; diff --git a/src/cmd/compile/internal/base/print.go b/src/cmd/compile/internal/base/print.go index 15256186afe4dc..119f06fbc03351 100644 --- a/src/cmd/compile/internal/base/print.go +++ b/src/cmd/compile/internal/base/print.go @@ -14,7 +14,7 @@ import ( "strings" "cmd/internal/src" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) // An errorMsg is a queued error message, waiting to be printed. @@ -195,7 +195,7 @@ func Fatalf(format string, args ...interface{}) { FatalfAt(Pos, format, args...) } -var bugStack = telemetry.NewStackCounter("compile/bug", 16) // 16 is arbitrary; used by gopls and crashmonitor +var bugStack = counter.NewStack("compile/bug", 16) // 16 is arbitrary; used by gopls and crashmonitor // FatalfAt reports a fatal error - an internal problem - at pos and exits. // If other errors have already been printed, then FatalfAt just quietly exits. diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index 3887d4156d6e3f..f68cf4deaf041a 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -30,7 +30,7 @@ import ( "cmd/internal/obj" "cmd/internal/objabi" "cmd/internal/src" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "flag" "fmt" "internal/buildcfg" @@ -59,8 +59,8 @@ func handlePanic() { // code, and finally writes the compiled package definition to disk. func Main(archInit func(*ssagen.ArchInfo)) { base.Timer.Start("fe", "init") - telemetry.OpenCounters() - telemetry.Inc("compile/invocations") + counter.Open() + counter.Inc("compile/invocations") defer handlePanic() diff --git a/src/cmd/covdata/covdata.go b/src/cmd/covdata/covdata.go index 48d7b9ed08915a..122ad28b5cafce 100644 --- a/src/cmd/covdata/covdata.go +++ b/src/cmd/covdata/covdata.go @@ -7,7 +7,7 @@ package main import ( "cmd/internal/cov" "cmd/internal/pkgpattern" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "flag" "fmt" "os" @@ -109,7 +109,7 @@ const ( ) func main() { - telemetry.OpenCounters() + counter.Open() // First argument should be mode/subcommand. if len(os.Args) < 2 { @@ -146,8 +146,8 @@ func main() { op.Usage("") } flag.Parse() - telemetry.Inc("covdata/invocations") - telemetry.CountFlags("covdata/flag:", *flag.CommandLine) + counter.Inc("covdata/invocations") + counter.CountFlags("covdata/flag:", *flag.CommandLine) // Mode-independent flag setup dbgtrace(1, "starting mode-independent setup") diff --git a/src/cmd/cover/cover.go b/src/cmd/cover/cover.go index 47eebaadd3a1ce..d8bb989bcce244 100644 --- a/src/cmd/cover/cover.go +++ b/src/cmd/cover/cover.go @@ -26,7 +26,7 @@ import ( "cmd/internal/edit" "cmd/internal/objabi" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) const usageMessage = "" + @@ -87,13 +87,13 @@ const ( ) func main() { - telemetry.OpenCounters() + counter.Open() objabi.AddVersionFlag() flag.Usage = usage objabi.Flagparse(usage) - telemetry.Inc("cover/invocations") - telemetry.CountFlags("cover/flag:", *flag.CommandLine) + counter.Inc("cover/invocations") + counter.CountFlags("cover/flag:", *flag.CommandLine) // Usage information when no arguments. if flag.NFlag() == 0 && flag.NArg() == 0 { diff --git a/src/cmd/dist/buildtool.go b/src/cmd/dist/buildtool.go index 62f9693210230a..9ca8fc539c43d4 100644 --- a/src/cmd/dist/buildtool.go +++ b/src/cmd/dist/buildtool.go @@ -53,6 +53,7 @@ var bootstrapDirs = []string{ "cmd/internal/src", "cmd/internal/sys", "cmd/internal/telemetry", + "cmd/internal/telemetry/counter", "cmd/link", "cmd/link/internal/...", "compress/flate", diff --git a/src/cmd/distpack/pack.go b/src/cmd/distpack/pack.go index 9ad33ee589cc8b..552524936699f7 100644 --- a/src/cmd/distpack/pack.go +++ b/src/cmd/distpack/pack.go @@ -45,7 +45,7 @@ import ( "strings" "time" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func usage() { @@ -69,11 +69,11 @@ var ( func main() { log.SetPrefix("distpack: ") log.SetFlags(0) - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("distpack/invocations") - telemetry.CountFlags("distpack/flag:", *flag.CommandLine) + counter.Inc("distpack/invocations") + counter.CountFlags("distpack/flag:", *flag.CommandLine) if flag.NArg() != 0 { usage() } diff --git a/src/cmd/doc/main.go b/src/cmd/doc/main.go index 4dbddcb79fcd21..502de097f50688 100644 --- a/src/cmd/doc/main.go +++ b/src/cmd/doc/main.go @@ -55,7 +55,7 @@ import ( "path/filepath" "strings" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) var ( @@ -87,7 +87,7 @@ func usage() { func main() { log.SetFlags(0) log.SetPrefix("doc: ") - telemetry.OpenCounters() + counter.Open() dirsInit() err := do(os.Stdout, flag.CommandLine, os.Args[1:]) if err != nil { @@ -108,8 +108,8 @@ func do(writer io.Writer, flagSet *flag.FlagSet, args []string) (err error) { flagSet.BoolVar(&showSrc, "src", false, "show source code for symbol") flagSet.BoolVar(&short, "short", false, "one-line representation for each symbol") flagSet.Parse(args) - telemetry.Inc("doc/invocations") - telemetry.CountFlags("doc/flag:", *flag.CommandLine) + counter.Inc("doc/invocations") + counter.CountFlags("doc/flag:", *flag.CommandLine) if chdir != "" { if err := os.Chdir(chdir); err != nil { return err diff --git a/src/cmd/fix/main.go b/src/cmd/fix/main.go index d915ece4ceb839..6f1ff120da1057 100644 --- a/src/cmd/fix/main.go +++ b/src/cmd/fix/main.go @@ -22,7 +22,7 @@ import ( "sort" "strings" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) var ( @@ -65,11 +65,11 @@ func usage() { } func main() { - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("fix/invocations") - telemetry.CountFlags("fix/flag:", *flag.CommandLine) + counter.Inc("fix/invocations") + counter.CountFlags("fix/flag:", *flag.CommandLine) if !version.IsValid(*goVersion) { report(fmt.Errorf("invalid -go=%s", *goVersion)) diff --git a/src/cmd/go/internal/help/help.go b/src/cmd/go/internal/help/help.go index 98382f2423ad15..4f2607fef2b89f 100644 --- a/src/cmd/go/internal/help/help.go +++ b/src/cmd/go/internal/help/help.go @@ -16,10 +16,10 @@ import ( "unicode/utf8" "cmd/go/internal/base" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) -var counterErrorsHelpUnknownTopic = telemetry.NewCounter("go/errors:help-unknown-topic") +var counterErrorsHelpUnknownTopic = counter.New("go/errors:help-unknown-topic") // Help implements the 'help' command. func Help(w io.Writer, args []string) { diff --git a/src/cmd/go/internal/modfetch/cache.go b/src/cmd/go/internal/modfetch/cache.go index 75b28b9bbc7f5d..02c4833a1b8010 100644 --- a/src/cmd/go/internal/modfetch/cache.go +++ b/src/cmd/go/internal/modfetch/cache.go @@ -26,7 +26,7 @@ import ( "cmd/go/internal/modfetch/codehost" "cmd/go/internal/par" "cmd/go/internal/robustio" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "golang.org/x/mod/module" "golang.org/x/mod/semver" @@ -779,7 +779,7 @@ var ( statCacheOnce sync.Once statCacheErr error - counterErrorsGOMODCACHEEntryRelative = telemetry.NewCounter("go/errors:gomodcache-entry-relative") + counterErrorsGOMODCACHEEntryRelative = counter.New("go/errors:gomodcache-entry-relative") ) // checkCacheDir checks if the directory specified by GOMODCACHE exists. An diff --git a/src/cmd/go/internal/telemetrystats/telemetrystats.go b/src/cmd/go/internal/telemetrystats/telemetrystats.go index 610c4a22e85a73..950453fa951374 100644 --- a/src/cmd/go/internal/telemetrystats/telemetrystats.go +++ b/src/cmd/go/internal/telemetrystats/telemetrystats.go @@ -10,7 +10,7 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cfg" "cmd/go/internal/modload" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func Increment() { @@ -22,30 +22,30 @@ func Increment() { // the command is running in. func incrementConfig() { if !modload.WillBeEnabled() { - telemetry.Inc("go/mode:gopath") + counter.Inc("go/mode:gopath") } else if workfile := modload.FindGoWork(base.Cwd()); workfile != "" { - telemetry.Inc("go/mode:workspace") + counter.Inc("go/mode:workspace") } else { - telemetry.Inc("go/mode:module") + counter.Inc("go/mode:module") } - telemetry.Inc("go/platform/target/goos:" + cfg.Goos) - telemetry.Inc("go/platform/target/goarch:" + cfg.Goarch) + counter.Inc("go/platform/target/goos:" + cfg.Goos) + counter.Inc("go/platform/target/goarch:" + cfg.Goarch) switch cfg.Goarch { case "386": - telemetry.Inc("go/platform/target/go386:" + cfg.GO386) + counter.Inc("go/platform/target/go386:" + cfg.GO386) case "amd64": - telemetry.Inc("go/platform/target/goamd64:" + cfg.GOAMD64) + counter.Inc("go/platform/target/goamd64:" + cfg.GOAMD64) case "arm": - telemetry.Inc("go/platform/target/goarm:" + cfg.GOARM) + counter.Inc("go/platform/target/goarm:" + cfg.GOARM) case "arm64": - telemetry.Inc("go/platform/target/goarm64:" + cfg.GOARM64) + counter.Inc("go/platform/target/goarm64:" + cfg.GOARM64) case "mips": - telemetry.Inc("go/platform/target/gomips:" + cfg.GOMIPS) + counter.Inc("go/platform/target/gomips:" + cfg.GOMIPS) case "ppc64": - telemetry.Inc("go/platform/target/goppc64:" + cfg.GOPPC64) + counter.Inc("go/platform/target/goppc64:" + cfg.GOPPC64) case "riscv64": - telemetry.Inc("go/platform/target/goriscv64:" + cfg.GORISCV64) + counter.Inc("go/platform/target/goriscv64:" + cfg.GORISCV64) case "wasm": - telemetry.Inc("go/platform/target/gowasm:" + cfg.GOWASM) + counter.Inc("go/platform/target/gowasm:" + cfg.GOWASM) } } diff --git a/src/cmd/go/internal/telemetrystats/version_other.go b/src/cmd/go/internal/telemetrystats/version_other.go index b20294e2237f32..efce5fcf362985 100644 --- a/src/cmd/go/internal/telemetrystats/version_other.go +++ b/src/cmd/go/internal/telemetrystats/version_other.go @@ -6,8 +6,8 @@ package telemetrystats -import "cmd/internal/telemetry" +import "cmd/internal/telemetry/counter" func incrementVersionCounters() { - telemetry.Inc("go/platform:version-not-supported") + counter.Inc("go/platform:version-not-supported") } diff --git a/src/cmd/go/internal/telemetrystats/version_unix.go b/src/cmd/go/internal/telemetrystats/version_unix.go index 08259b7c89655e..517e7829b68ef4 100644 --- a/src/cmd/go/internal/telemetrystats/version_unix.go +++ b/src/cmd/go/internal/telemetrystats/version_unix.go @@ -12,7 +12,7 @@ import ( "runtime" "strings" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "golang.org/x/sys/unix" ) @@ -29,7 +29,7 @@ func incrementVersionCounters() { var v unix.Utsname err := unix.Uname(&v) if err != nil { - telemetry.Inc(fmt.Sprintf("go/platform/host/%s/version:unknown-uname-error", runtime.GOOS)) + counter.Inc(fmt.Sprintf("go/platform/host/%s/version:unknown-uname-error", runtime.GOOS)) return } major, minor, ok := majorMinor(convert(v.Release[:])) @@ -37,11 +37,11 @@ func incrementVersionCounters() { major, minor, ok = convert(v.Version[:]), convert(v.Release[:]), true } if !ok { - telemetry.Inc(fmt.Sprintf("go/platform/host/%s/version:unknown-bad-format", runtime.GOOS)) + counter.Inc(fmt.Sprintf("go/platform/host/%s/version:unknown-bad-format", runtime.GOOS)) return } - telemetry.Inc(fmt.Sprintf("go/platform/host/%s/major-version:%s", runtime.GOOS, major)) - telemetry.Inc(fmt.Sprintf("go/platform/host/%s/version:%s-%s", runtime.GOOS, major, minor)) + counter.Inc(fmt.Sprintf("go/platform/host/%s/major-version:%s", runtime.GOOS, major)) + counter.Inc(fmt.Sprintf("go/platform/host/%s/version:%s-%s", runtime.GOOS, major, minor)) } func majorMinor(v string) (string, string, bool) { diff --git a/src/cmd/go/internal/telemetrystats/version_windows.go b/src/cmd/go/internal/telemetrystats/version_windows.go index e6a33e00cdc568..7de87193c67236 100644 --- a/src/cmd/go/internal/telemetrystats/version_windows.go +++ b/src/cmd/go/internal/telemetrystats/version_windows.go @@ -9,14 +9,14 @@ package telemetrystats import ( "fmt" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "golang.org/x/sys/windows" ) func incrementVersionCounters() { v := windows.RtlGetVersion() - telemetry.Inc(fmt.Sprintf("go/platform/host/windows/major-version:%d", v.MajorVersion)) - telemetry.Inc(fmt.Sprintf("go/platform/host/windows/version:%d-%d", v.MajorVersion, v.MinorVersion)) - telemetry.Inc(fmt.Sprintf("go/platform/host/windows/build:%d", v.BuildNumber)) + counter.Inc(fmt.Sprintf("go/platform/host/windows/major-version:%d", v.MajorVersion)) + counter.Inc(fmt.Sprintf("go/platform/host/windows/version:%d-%d", v.MajorVersion, v.MinorVersion)) + counter.Inc(fmt.Sprintf("go/platform/host/windows/build:%d", v.BuildNumber)) } diff --git a/src/cmd/go/internal/tool/tool.go b/src/cmd/go/internal/tool/tool.go index da219f041cf548..77cee564b3d557 100644 --- a/src/cmd/go/internal/tool/tool.go +++ b/src/cmd/go/internal/tool/tool.go @@ -6,7 +6,7 @@ package tool import ( - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "context" "encoding/json" "flag" @@ -58,7 +58,7 @@ func init() { func runTool(ctx context.Context, cmd *base.Command, args []string) { if len(args) == 0 { - telemetry.Inc("go/subcommand:tool") + counter.Inc("go/subcommand:tool") listTools() return } @@ -86,17 +86,17 @@ func runTool(ctx context.Context, cmd *base.Command, args []string) { if impersonateDistList(args[2:]) { // If it becomes necessary, we could increment an additional counter to indicate // that we're impersonating dist list if knowing that becomes important? - telemetry.Inc("go/subcommand:tool-dist") + counter.Inc("go/subcommand:tool-dist") return } } - telemetry.Inc("go/subcommand:tool-unknown") + counter.Inc("go/subcommand:tool-unknown") // Emit the usual error for the missing tool. _ = base.Tool(toolName) } else { // Increment a counter for the tool subcommand with the tool name. - telemetry.Inc("go/subcommand:tool-" + toolName) + counter.Inc("go/subcommand:tool-" + toolName) } if toolN { diff --git a/src/cmd/go/internal/toolchain/select.go b/src/cmd/go/internal/toolchain/select.go index d4787a844f0730..8e93e6c9033087 100644 --- a/src/cmd/go/internal/toolchain/select.go +++ b/src/cmd/go/internal/toolchain/select.go @@ -26,7 +26,7 @@ import ( "cmd/go/internal/modload" "cmd/go/internal/run" "cmd/go/internal/work" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "golang.org/x/mod/module" ) @@ -82,7 +82,7 @@ func FilterEnv(env []string) []string { return out } -var counterErrorsInvalidToolchainInFile = telemetry.NewCounter("go/errors:invalid-toolchain-in-file") +var counterErrorsInvalidToolchainInFile = counter.New("go/errors:invalid-toolchain-in-file") // Select invokes a different Go toolchain if directed by // the GOTOOLCHAIN environment variable or the user's configuration @@ -253,7 +253,7 @@ func Select() { Exec(gotoolchain) } -var counterSelectExec = telemetry.NewCounter("go/toolchain/select-exec") +var counterSelectExec = counter.New("go/toolchain/select-exec") // TestVersionSwitch is set in the test go binary to the value in $TESTGO_VERSION_SWITCH. // Valid settings are: diff --git a/src/cmd/go/internal/toolchain/switch.go b/src/cmd/go/internal/toolchain/switch.go index ba1e6973cf4186..37c1bcdcbec656 100644 --- a/src/cmd/go/internal/toolchain/switch.go +++ b/src/cmd/go/internal/toolchain/switch.go @@ -16,7 +16,7 @@ import ( "cmd/go/internal/cfg" "cmd/go/internal/gover" "cmd/go/internal/modfetch" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) // A Switcher collects errors to be reported and then decides @@ -104,7 +104,7 @@ func (s *Switcher) Switch(ctx context.Context) { panic("unreachable") } -var counterSwitchExec = telemetry.NewCounter("go/toolchain/switch-exec") +var counterSwitchExec = counter.New("go/toolchain/switch-exec") // SwitchOrFatal attempts a toolchain switch based on the information in err // and otherwise falls back to base.Fatal(err). diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 889cc6ca508ef7..4ee43e24369286 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -19,7 +19,7 @@ import ( "cmd/go/internal/str" "cmd/internal/buildid" "cmd/internal/quoted" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) // Build IDs @@ -406,11 +406,11 @@ func (b *Builder) fileHash(file string) string { } var ( - counterCacheHit = telemetry.NewCounter("go/buildcache/hit") - counterCacheMiss = telemetry.NewCounter("go/buildcache/miss") + counterCacheHit = counter.New("go/buildcache/hit") + counterCacheMiss = counter.New("go/buildcache/miss") onceIncStdlibRecompiled sync.Once - stdlibRecompiled = telemetry.NewCounter("go/buildcache/stdlib-recompiled") + stdlibRecompiled = counter.New("go/buildcache/stdlib-recompiled") ) // useCache tries to satisfy the action a, which has action ID actionHash, diff --git a/src/cmd/go/main.go b/src/cmd/go/main.go index eb33df1ad4c929..1c58232a6621b9 100644 --- a/src/cmd/go/main.go +++ b/src/cmd/go/main.go @@ -45,6 +45,7 @@ import ( "cmd/go/internal/work" "cmd/go/internal/workcmd" "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) func init() { @@ -91,20 +92,20 @@ func init() { var _ = go11tag -var counterErrorsGOPATHEntryRelative = telemetry.NewCounter("go/errors:gopath-entry-relative") +var counterErrorsGOPATHEntryRelative = counter.New("go/errors:gopath-entry-relative") func main() { log.SetFlags(0) - telemetry.MaybeChild() // Run in child mode if this is the telemetry sidecar child process. - telemetry.OpenCounters() // Open the telemetry counter file so counters can be written to it. + telemetry.MaybeChild() // Run in child mode if this is the telemetry sidecar child process. + counter.Open() // Open the telemetry counter file so counters can be written to it. handleChdirFlag() toolchain.Select() telemetry.MaybeParent() // Run the upload process. Opening the counter file is idempotent. flag.Usage = base.Usage flag.Parse() - telemetry.Inc("go/invocations") - telemetry.CountFlags("go/flag:", *flag.CommandLine) + counter.Inc("go/invocations") + counter.CountFlags("go/flag:", *flag.CommandLine) args := flag.Args() if len(args) < 1 { @@ -113,7 +114,7 @@ func main() { cfg.CmdName = args[0] // for error messages if args[0] == "help" { - telemetry.Inc("go/subcommand:" + strings.Join(append([]string{"help"}, args[1:]...), "-")) + counter.Inc("go/subcommand:" + strings.Join(append([]string{"help"}, args[1:]...), "-")) help.Help(os.Stdout, args[1:]) return } @@ -128,17 +129,17 @@ func main() { } switch strings.ToLower(cfg.GOROOT) { case "/usr/local/go": // Location recommended for installation on Linux and Darwin and used by Mac installer. - telemetry.Inc("go/goroot:usr-local-go") + counter.Inc("go/goroot:usr-local-go") case "/usr/lib/go": // A typical location used by Linux package managers. - telemetry.Inc("go/goroot:usr-lib-go") + counter.Inc("go/goroot:usr-lib-go") case "/usr/lib/golang": // Another typical location used by Linux package managers. - telemetry.Inc("go/goroot:usr-lib-golang") + counter.Inc("go/goroot:usr-lib-golang") case `c:\program files\go`: // Location used by Windows installer. - telemetry.Inc("go/goroot:program-files-go") + counter.Inc("go/goroot:program-files-go") case `c:\program files (x86)\go`: // Location used by 386 Windows installer on amd64 platform. - telemetry.Inc("go/goroot:program-files-x86-go") + counter.Inc("go/goroot:program-files-x86-go") default: - telemetry.Inc("go/goroot:other") + counter.Inc("go/goroot:other") } // Diagnose common mistake: GOPATH==GOROOT. @@ -184,7 +185,7 @@ func main() { } if args[used] == "help" { // Accept 'go mod help' and 'go mod help foo' for 'go help mod' and 'go help mod foo'. - telemetry.Inc("go/subcommand:" + strings.ReplaceAll(cfg.CmdName, " ", "-") + "-" + strings.Join(args[used:], "-")) + counter.Inc("go/subcommand:" + strings.ReplaceAll(cfg.CmdName, " ", "-") + "-" + strings.Join(args[used:], "-")) help.Help(os.Stdout, append(slices.Clip(args[:used]), args[used+1:]...)) base.Exit() } @@ -196,7 +197,7 @@ func main() { if cmdName == "" { cmdName = args[0] } - telemetry.Inc("go/subcommand:unknown") + counter.Inc("go/subcommand:unknown") fmt.Fprintf(os.Stderr, "go %s: unknown command\nRun 'go help%s' for usage.\n", cmdName, helpArg) base.SetExitStatus(2) base.Exit() @@ -206,7 +207,7 @@ func main() { // increment in the tool subcommand's Run function because we need // to do the flag processing in invoke first. if cfg.CmdName != "tool" { - telemetry.Inc("go/subcommand:" + strings.ReplaceAll(cfg.CmdName, " ", "-")) + counter.Inc("go/subcommand:" + strings.ReplaceAll(cfg.CmdName, " ", "-")) } telemetrystats.Increment() invoke(cmd, args[used-1:]) @@ -274,8 +275,8 @@ func invoke(cmd *base.Command, args []string) { base.SetFromGOFLAGS(&cmd.Flag) cmd.Flag.Parse(args[1:]) flagCounterPrefix := "go/" + strings.ReplaceAll(cfg.CmdName, " ", "-") + "/flag" - telemetry.CountFlags(flagCounterPrefix+":", cmd.Flag) - telemetry.CountFlagValue(flagCounterPrefix+"/", cmd.Flag, "buildmode") + counter.CountFlags(flagCounterPrefix+":", cmd.Flag) + counter.CountFlagValue(flagCounterPrefix+"/", cmd.Flag, "buildmode") args = cmd.Flag.Args() } @@ -361,7 +362,7 @@ func handleChdirFlag() { _, dir, _ = strings.Cut(a, "=") os.Args = slices.Delete(os.Args, used, used+1) } - telemetry.Inc("go/flag:C") + counter.Inc("go/flag:C") if err := os.Chdir(dir); err != nil { base.Fatalf("go: %v", err) diff --git a/src/cmd/gofmt/gofmt.go b/src/cmd/gofmt/gofmt.go index d6721f9327316d..d91a75b1050e20 100644 --- a/src/cmd/gofmt/gofmt.go +++ b/src/cmd/gofmt/gofmt.go @@ -25,7 +25,7 @@ import ( "strconv" "strings" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "golang.org/x/sync/semaphore" ) @@ -374,11 +374,11 @@ func main() { } func gofmtMain(s *sequencer) { - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("gofmt/invocations") - telemetry.CountFlags("gofmt/flag:", *flag.CommandLine) + counter.Inc("gofmt/invocations") + counter.CountFlags("gofmt/flag:", *flag.CommandLine) if *cpuprofile != "" { fdSem <- true diff --git a/src/cmd/internal/telemetry/counter/counter.go b/src/cmd/internal/telemetry/counter/counter.go new file mode 100644 index 00000000000000..5cef0b0041551a --- /dev/null +++ b/src/cmd/internal/telemetry/counter/counter.go @@ -0,0 +1,62 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build !cmd_go_bootstrap && !compiler_bootstrap + +package counter + +import ( + "flag" + "os" + + "golang.org/x/telemetry/counter" +) + +var openCalled bool + +func OpenCalled() bool { return openCalled } + +// Open opens the counter files for writing if telemetry is supported +// on the current platform (and does nothing otherwise). +func Open() { + openCalled = true + counter.OpenDir(os.Getenv("TEST_TELEMETRY_DIR")) +} + +// Inc increments the counter with the given name. +func Inc(name string) { + counter.Inc(name) +} + +// New returns a counter with the given name. +func New(name string) *counter.Counter { + return counter.New(name) +} + +// NewStack returns a new stack counter with the given name and depth. +func NewStack(name string, depth int) *counter.StackCounter { + return counter.NewStack(name, depth) +} + +// CountFlags creates a counter for every flag that is set +// and increments the counter. The name of the counter is +// the concatenation of prefix and the flag name. +func CountFlags(prefix string, flagSet flag.FlagSet) { + counter.CountFlags(prefix, flagSet) +} + +// CountFlagValue creates a counter for the flag value +// if it is set and increments the counter. The name of the +// counter is the concatenation of prefix, the flagName, ":", +// and value.String() for the flag's value. +func CountFlagValue(prefix string, flagSet flag.FlagSet, flagName string) { + // TODO(matloob): Maybe pass in a list of flagNames if we end up counting + // values for more than one? + // TODO(matloob): Add this to x/telemetry? + flagSet.Visit(func(f *flag.Flag) { + if f.Name == flagName { + counter.New(prefix + f.Name + ":" + f.Value.String()).Inc() + } + }) +} diff --git a/src/cmd/internal/telemetry/counter/counter_bootstrap.go b/src/cmd/internal/telemetry/counter/counter_bootstrap.go new file mode 100644 index 00000000000000..00808294053c23 --- /dev/null +++ b/src/cmd/internal/telemetry/counter/counter_bootstrap.go @@ -0,0 +1,20 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +//go:build cmd_go_bootstrap || compiler_bootstrap + +package counter + +import "flag" + +type dummyCounter struct{} + +func (dc dummyCounter) Inc() {} + +func Open() {} +func Inc(name string) {} +func New(name string) dummyCounter { return dummyCounter{} } +func NewStack(name string, depth int) dummyCounter { return dummyCounter{} } +func CountFlags(name string, flagSet flag.FlagSet) {} +func CountFlagValue(prefix string, flagSet flag.FlagSet, flagName string) {} diff --git a/src/cmd/internal/telemetry/telemetry.go b/src/cmd/internal/telemetry/telemetry.go index b0c864a1a95ec6..ca84fe39b18438 100644 --- a/src/cmd/internal/telemetry/telemetry.go +++ b/src/cmd/internal/telemetry/telemetry.go @@ -12,30 +12,21 @@ package telemetry import ( - "flag" "os" + "cmd/internal/telemetry/counter" + "golang.org/x/telemetry" - "golang.org/x/telemetry/counter" ) var openCountersCalled, maybeChildCalled bool -// OpenCounters opens the counter files for writing if telemetry is supported -// on the current platform (and does nothing otherwise). -func OpenCounters() { - openCountersCalled = true - telemetry.Start(telemetry.Config{ - TelemetryDir: os.Getenv("TEST_TELEMETRY_DIR"), - }) -} - // MaybeParent does a once a day check to see if the weekly reports are // ready to be processed or uploaded, and if so, starts the telemetry child to // do so. It should only be called by cmd/go, and only after OpenCounters and MaybeChild // have already been called. func MaybeParent() { - if !openCountersCalled || !maybeChildCalled { + if !counter.OpenCalled() || !maybeChildCalled { panic("MaybeParent must be called after OpenCounters and MaybeChild") } telemetry.Start(telemetry.Config{ @@ -56,43 +47,6 @@ func MaybeChild() { }) } -// Inc increments the counter with the given name. -func Inc(name string) { - counter.Inc(name) -} - -// NewCounter returns a counter with the given name. -func NewCounter(name string) *counter.Counter { - return counter.New(name) -} - -// NewStackCounter returns a new stack counter with the given name and depth. -func NewStackCounter(name string, depth int) *counter.StackCounter { - return counter.NewStack(name, depth) -} - -// CountFlags creates a counter for every flag that is set -// and increments the counter. The name of the counter is -// the concatenation of prefix and the flag name. -func CountFlags(prefix string, flagSet flag.FlagSet) { - counter.CountFlags(prefix, flagSet) -} - -// CountFlagValue creates a counter for the flag value -// if it is set and increments the counter. The name of the -// counter is the concatenation of prefix, the flagName, ":", -// and value.String() for the flag's value. -func CountFlagValue(prefix string, flagSet flag.FlagSet, flagName string) { - // TODO(matloob): Maybe pass in a list of flagNames if we end up counting - // values for more than one? - // TODO(matloob): Add this to x/telemetry? - flagSet.Visit(func(f *flag.Flag) { - if f.Name == flagName { - counter.New(prefix + f.Name + ":" + f.Value.String()).Inc() - } - }) -} - // Mode returns the current telemetry mode. // // The telemetry mode is a global value that controls both the local collection diff --git a/src/cmd/internal/telemetry/telemetry_bootstrap.go b/src/cmd/internal/telemetry/telemetry_bootstrap.go index 05c0ee1c56e9c9..e301e30cc8175f 100644 --- a/src/cmd/internal/telemetry/telemetry_bootstrap.go +++ b/src/cmd/internal/telemetry/telemetry_bootstrap.go @@ -6,20 +6,8 @@ package telemetry -import "flag" - -type dummyCounter struct{} - -func (dc dummyCounter) Inc() {} - -func OpenCounters() {} -func MaybeParent() {} -func MaybeChild() {} -func Inc(name string) {} -func NewCounter(name string) dummyCounter { return dummyCounter{} } -func NewStackCounter(name string, depth int) dummyCounter { return dummyCounter{} } -func CountFlags(name string, flagSet flag.FlagSet) {} -func CountFlagValue(prefix string, flagSet flag.FlagSet, flagName string) {} -func Mode() string { return "" } -func SetMode(mode string) error { return nil } -func Dir() string { return "" } +func MaybeParent() {} +func MaybeChild() {} +func Mode() string { return "" } +func SetMode(mode string) error { return nil } +func Dir() string { return "" } diff --git a/src/cmd/link/internal/ld/main.go b/src/cmd/link/internal/ld/main.go index 3183e1a13ed866..56e865d8a53287 100644 --- a/src/cmd/link/internal/ld/main.go +++ b/src/cmd/link/internal/ld/main.go @@ -36,7 +36,7 @@ import ( "cmd/internal/objabi" "cmd/internal/quoted" "cmd/internal/sys" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "cmd/link/internal/benchmark" "flag" "internal/buildcfg" @@ -157,8 +157,8 @@ func (t *ternaryFlag) IsBoolFlag() bool { return true } // parse like a boolean func Main(arch *sys.Arch, theArch Arch) { log.SetPrefix("link: ") log.SetFlags(0) - telemetry.OpenCounters() - telemetry.Inc("link/invocations") + counter.Open() + counter.Inc("link/invocations") thearch = theArch ctxt := linknew(arch) @@ -204,7 +204,7 @@ func Main(arch *sys.Arch, theArch Arch) { objabi.Flagfn1("importcfg", "read import configuration from `file`", ctxt.readImportCfg) objabi.Flagparse(usage) - telemetry.CountFlags("link/flag:", *flag.CommandLine) + counter.CountFlags("link/flag:", *flag.CommandLine) if ctxt.Debugvlog > 0 { // dump symbol info on crash diff --git a/src/cmd/nm/nm.go b/src/cmd/nm/nm.go index e0d98d5f6c67d0..752870654d5ccd 100644 --- a/src/cmd/nm/nm.go +++ b/src/cmd/nm/nm.go @@ -13,7 +13,7 @@ import ( "sort" "cmd/internal/objfile" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) const helpText = `usage: go tool nm [options] file... @@ -68,11 +68,11 @@ func (nflag) String() string { func main() { log.SetFlags(0) - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("nm/invocations") - telemetry.CountFlags("nm/flag:", *flag.CommandLine) + counter.Inc("nm/invocations") + counter.CountFlags("nm/flag:", *flag.CommandLine) switch *sortOrder { case "address", "name", "none", "size": diff --git a/src/cmd/objdump/main.go b/src/cmd/objdump/main.go index 7554b5500c1216..b5b0d7f5178d5b 100644 --- a/src/cmd/objdump/main.go +++ b/src/cmd/objdump/main.go @@ -41,7 +41,7 @@ import ( "strings" "cmd/internal/objfile" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" ) var printCode = flag.Bool("S", false, "print Go code alongside assembly") @@ -58,12 +58,12 @@ func usage() { func main() { log.SetFlags(0) log.SetPrefix("objdump: ") - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("objdump/invocations") - telemetry.CountFlags("objdump/flag:", *flag.CommandLine) + counter.Inc("objdump/invocations") + counter.CountFlags("objdump/flag:", *flag.CommandLine) if flag.NArg() != 1 && flag.NArg() != 3 { usage() } diff --git a/src/cmd/pack/pack.go b/src/cmd/pack/pack.go index 28f217ace1b57e..4ac6ce995fe918 100644 --- a/src/cmd/pack/pack.go +++ b/src/cmd/pack/pack.go @@ -6,7 +6,7 @@ package main import ( "cmd/internal/archive" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "fmt" "io" "io/fs" @@ -31,7 +31,7 @@ func usage() { func main() { log.SetFlags(0) log.SetPrefix("pack: ") - telemetry.OpenCounters() + counter.Open() // need "pack op archive" at least. if len(os.Args) < 3 { log.Print("not enough arguments") @@ -39,8 +39,8 @@ func main() { usage() } setOp(os.Args[1]) - telemetry.Inc("pack/invocations") - telemetry.Inc("pack/op:" + string(op)) + counter.Inc("pack/invocations") + counter.Inc("pack/op:" + string(op)) var ar *Archive switch op { case 'p': diff --git a/src/cmd/pprof/pprof.go b/src/cmd/pprof/pprof.go index 722b745287eec1..a1c2cd210f8dba 100644 --- a/src/cmd/pprof/pprof.go +++ b/src/cmd/pprof/pprof.go @@ -25,22 +25,22 @@ import ( "time" "cmd/internal/objfile" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "github.com/google/pprof/driver" "github.com/google/pprof/profile" ) func main() { - telemetry.OpenCounters() - telemetry.Inc("pprof/invocations") + counter.Open() + counter.Inc("pprof/invocations") options := &driver.Options{ Fetch: new(fetcher), Obj: new(objTool), UI: newUI(), } err := driver.PProf(options) - telemetry.CountFlags("pprof/flag:", *flag.CommandLine) // pprof will use the flag package as its default + counter.CountFlags("pprof/flag:", *flag.CommandLine) // pprof will use the flag package as its default if err != nil { fmt.Fprintf(os.Stderr, "%v\n", err) os.Exit(2) diff --git a/src/cmd/preprofile/main.go b/src/cmd/preprofile/main.go index 1260eed10471ee..60aa1f7cc6cdd6 100644 --- a/src/cmd/preprofile/main.go +++ b/src/cmd/preprofile/main.go @@ -18,7 +18,7 @@ import ( "bufio" "cmd/internal/objabi" "cmd/internal/pgo" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "flag" "fmt" "log" @@ -73,12 +73,12 @@ func main() { log.SetFlags(0) log.SetPrefix("preprofile: ") - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("preprofile/invocations") - telemetry.CountFlags("preprofile/flag:", *flag.CommandLine) + counter.Inc("preprofile/invocations") + counter.CountFlags("preprofile/flag:", *flag.CommandLine) if *input == "" { log.Print("Input pprof path required (-i)") usage() diff --git a/src/cmd/test2json/main.go b/src/cmd/test2json/main.go index 844ee5aa6c6cc1..b704dd4d31a5e5 100644 --- a/src/cmd/test2json/main.go +++ b/src/cmd/test2json/main.go @@ -96,7 +96,7 @@ import ( "os/exec" "os/signal" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "cmd/internal/test2json" ) @@ -116,12 +116,12 @@ func ignoreSignals() { } func main() { - telemetry.OpenCounters() + counter.Open() flag.Usage = usage flag.Parse() - telemetry.Inc("test2json/invocations") - telemetry.CountFlags("test2json/flag:", *flag.CommandLine) + counter.Inc("test2json/invocations") + counter.CountFlags("test2json/flag:", *flag.CommandLine) var mode test2json.Mode if *flagT { diff --git a/src/cmd/trace/main.go b/src/cmd/trace/main.go index e48048b9f257ca..d51ee5816456bf 100644 --- a/src/cmd/trace/main.go +++ b/src/cmd/trace/main.go @@ -6,7 +6,7 @@ package main import ( "cmd/internal/browser" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "flag" "fmt" "internal/trace" @@ -64,14 +64,14 @@ var ( ) func main() { - telemetry.OpenCounters() + counter.Open() flag.Usage = func() { fmt.Fprint(os.Stderr, usageMessage) os.Exit(2) } flag.Parse() - telemetry.Inc("trace/invocations") - telemetry.CountFlags("trace/flag:", *flag.CommandLine) + counter.Inc("trace/invocations") + counter.CountFlags("trace/flag:", *flag.CommandLine) // Go 1.7 traces embed symbol info and does not require the binary. // But we optionally accept binary as first arg for Go 1.5 traces. diff --git a/src/cmd/vet/main.go b/src/cmd/vet/main.go index 84821d43fcb149..3ace8ad6897b88 100644 --- a/src/cmd/vet/main.go +++ b/src/cmd/vet/main.go @@ -6,7 +6,7 @@ package main import ( "cmd/internal/objabi" - "cmd/internal/telemetry" + "cmd/internal/telemetry/counter" "flag" "golang.org/x/tools/go/analysis/unitchecker" @@ -47,10 +47,10 @@ import ( ) func main() { - telemetry.OpenCounters() + counter.Open() objabi.AddVersionFlag() - telemetry.Inc("vet/invocations") + counter.Inc("vet/invocations") unitchecker.Main( appends.Analyzer, asmdecl.Analyzer, @@ -89,5 +89,5 @@ func main() { // It's possible that unitchecker will exit early. In // those cases the flags won't be counted. - telemetry.CountFlags("vet/flag:", *flag.CommandLine) + counter.CountFlags("vet/flag:", *flag.CommandLine) } From cb3b34349b4608a8eb5107159db74cbe472744b2 Mon Sep 17 00:00:00 2001 From: Gopher Robot Date: Fri, 21 Jun 2024 19:19:05 +0000 Subject: [PATCH 22/41] doc/next: delete The release note fragments have been merged and added as _content/doc/go1.23.md in x/website in CL 594035. For #65614. Change-Id: I7c8c718bc065024b6bdca93ce9bcc3c5d8b2dbc7 Reviewed-on: https://go-review.googlesource.com/c/go/+/594036 LUCI-TryBot-Result: Go LUCI Reviewed-by: Dmitri Shuralyov Auto-Submit: Dmitri Shuralyov Reviewed-by: David Chase Reviewed-by: Dmitri Shuralyov --- doc/next/1-intro.md | 14 ---- doc/next/2-language.md | 18 ---- doc/next/3-tools.md | 84 ------------------- doc/next/4-runtime.md | 7 -- doc/next/5-toolchain.md | 38 --------- doc/next/6-stdlib/0-heading.md | 2 - doc/next/6-stdlib/1-time.md | 32 ------- doc/next/6-stdlib/2-unique.md | 13 --- doc/next/6-stdlib/3-iter.md | 29 ------- doc/next/6-stdlib/4-structs.md | 11 --- doc/next/6-stdlib/99-minor/0-heading.md | 3 - doc/next/6-stdlib/99-minor/README | 1 - .../6-stdlib/99-minor/archive/tar/50102.md | 4 - .../6-stdlib/99-minor/crypto/tls/63369.md | 3 - .../6-stdlib/99-minor/crypto/tls/63691.md | 3 - .../6-stdlib/99-minor/crypto/tls/66214.md | 3 - .../6-stdlib/99-minor/crypto/tls/67061.md | 3 - .../6-stdlib/99-minor/crypto/tls/67065.md | 3 - .../6-stdlib/99-minor/crypto/x509/45990.md | 3 - .../6-stdlib/99-minor/crypto/x509/62048.md | 4 - .../6-stdlib/99-minor/crypto/x509/66249.md | 3 - .../6-stdlib/99-minor/database/sql/64707.md | 3 - doc/next/6-stdlib/99-minor/debug/elf/66054.md | 3 - doc/next/6-stdlib/99-minor/debug/elf/66836.md | 2 - .../99-minor/encoding/binary/60023.md | 3 - doc/next/6-stdlib/99-minor/go/ast/66339.md | 2 - doc/next/6-stdlib/99-minor/go/types/46477.md | 1 - doc/next/6-stdlib/99-minor/go/types/65772.md | 3 - doc/next/6-stdlib/99-minor/go/types/66559.md | 3 - doc/next/6-stdlib/99-minor/go/types/67143.md | 2 - .../6-stdlib/99-minor/go/types/cl-577715.md | 4 - doc/next/6-stdlib/99-minor/iter/61897.md | 1 - doc/next/6-stdlib/99-minor/maps/61900.md | 1 - .../6-stdlib/99-minor/math/rand/v2/61716.md | 2 - .../6-stdlib/99-minor/math/rand/v2/67059.md | 1 - doc/next/6-stdlib/99-minor/net/62254.md | 3 - doc/next/6-stdlib/99-minor/net/63116.md | 3 - doc/next/6-stdlib/99-minor/net/67925.md | 3 - doc/next/6-stdlib/99-minor/net/http/46443.md | 3 - doc/next/6-stdlib/99-minor/net/http/61472.md | 1 - doc/next/6-stdlib/99-minor/net/http/62490.md | 1 - doc/next/6-stdlib/99-minor/net/http/64910.md | 2 - doc/next/6-stdlib/99-minor/net/http/66008.md | 7 -- doc/next/6-stdlib/99-minor/net/http/66343.md | 16 ---- doc/next/6-stdlib/99-minor/net/http/66405.md | 3 - .../99-minor/net/http/httptest/59473.md | 2 - doc/next/6-stdlib/99-minor/os/33357.md | 3 - doc/next/6-stdlib/99-minor/os/61893.md | 7 -- doc/next/6-stdlib/99-minor/os/62484.md | 1 - doc/next/6-stdlib/99-minor/os/63703.md | 5 -- .../6-stdlib/99-minor/path/filepath/57151.md | 2 - .../6-stdlib/99-minor/path/filepath/63703.md | 11 --- doc/next/6-stdlib/99-minor/reflect/60427.md | 6 -- doc/next/6-stdlib/99-minor/reflect/61308.md | 3 - doc/next/6-stdlib/99-minor/reflect/66056.md | 4 - .../6-stdlib/99-minor/runtime/debug/42888.md | 5 -- .../6-stdlib/99-minor/runtime/debug/67182.md | 1 - .../6-stdlib/99-minor/runtime/pprof/43669.md | 2 - .../6-stdlib/99-minor/runtime/trace/65319.md | 4 - doc/next/6-stdlib/99-minor/slices/53987.md | 1 - doc/next/6-stdlib/99-minor/slices/61899.md | 1 - doc/next/6-stdlib/99-minor/slices/65238.md | 2 - doc/next/6-stdlib/99-minor/structs/66408.md | 1 - doc/next/6-stdlib/99-minor/sync/61696.md | 2 - .../6-stdlib/99-minor/sync/atomic/61395.md | 3 - doc/next/6-stdlib/99-minor/syscall/62254.md | 1 - doc/next/6-stdlib/99-minor/syscall/65817.md | 1 - .../6-stdlib/99-minor/testing/fstest/63675.md | 3 - .../6-stdlib/99-minor/text/template/57646.md | 1 - doc/next/6-stdlib/99-minor/time/67470.md | 2 - .../6-stdlib/99-minor/unicode/utf16/44940.md | 3 - doc/next/6-stdlib/99-minor/unique/62483.md | 1 - doc/next/7-ports.md | 38 --------- doc/next/9-todo.md | 51 ----------- 74 files changed, 521 deletions(-) delete mode 100644 doc/next/1-intro.md delete mode 100644 doc/next/2-language.md delete mode 100644 doc/next/3-tools.md delete mode 100644 doc/next/4-runtime.md delete mode 100644 doc/next/5-toolchain.md delete mode 100644 doc/next/6-stdlib/0-heading.md delete mode 100644 doc/next/6-stdlib/1-time.md delete mode 100644 doc/next/6-stdlib/2-unique.md delete mode 100644 doc/next/6-stdlib/3-iter.md delete mode 100644 doc/next/6-stdlib/4-structs.md delete mode 100644 doc/next/6-stdlib/99-minor/0-heading.md delete mode 100644 doc/next/6-stdlib/99-minor/README delete mode 100644 doc/next/6-stdlib/99-minor/archive/tar/50102.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/tls/63369.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/tls/63691.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/tls/66214.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/tls/67061.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/tls/67065.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/x509/45990.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/x509/62048.md delete mode 100644 doc/next/6-stdlib/99-minor/crypto/x509/66249.md delete mode 100644 doc/next/6-stdlib/99-minor/database/sql/64707.md delete mode 100644 doc/next/6-stdlib/99-minor/debug/elf/66054.md delete mode 100644 doc/next/6-stdlib/99-minor/debug/elf/66836.md delete mode 100644 doc/next/6-stdlib/99-minor/encoding/binary/60023.md delete mode 100644 doc/next/6-stdlib/99-minor/go/ast/66339.md delete mode 100644 doc/next/6-stdlib/99-minor/go/types/46477.md delete mode 100644 doc/next/6-stdlib/99-minor/go/types/65772.md delete mode 100644 doc/next/6-stdlib/99-minor/go/types/66559.md delete mode 100644 doc/next/6-stdlib/99-minor/go/types/67143.md delete mode 100644 doc/next/6-stdlib/99-minor/go/types/cl-577715.md delete mode 100644 doc/next/6-stdlib/99-minor/iter/61897.md delete mode 100644 doc/next/6-stdlib/99-minor/maps/61900.md delete mode 100644 doc/next/6-stdlib/99-minor/math/rand/v2/61716.md delete mode 100644 doc/next/6-stdlib/99-minor/math/rand/v2/67059.md delete mode 100644 doc/next/6-stdlib/99-minor/net/62254.md delete mode 100644 doc/next/6-stdlib/99-minor/net/63116.md delete mode 100644 doc/next/6-stdlib/99-minor/net/67925.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/46443.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/61472.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/62490.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/64910.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/66008.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/66343.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/66405.md delete mode 100644 doc/next/6-stdlib/99-minor/net/http/httptest/59473.md delete mode 100644 doc/next/6-stdlib/99-minor/os/33357.md delete mode 100644 doc/next/6-stdlib/99-minor/os/61893.md delete mode 100644 doc/next/6-stdlib/99-minor/os/62484.md delete mode 100644 doc/next/6-stdlib/99-minor/os/63703.md delete mode 100644 doc/next/6-stdlib/99-minor/path/filepath/57151.md delete mode 100644 doc/next/6-stdlib/99-minor/path/filepath/63703.md delete mode 100644 doc/next/6-stdlib/99-minor/reflect/60427.md delete mode 100644 doc/next/6-stdlib/99-minor/reflect/61308.md delete mode 100644 doc/next/6-stdlib/99-minor/reflect/66056.md delete mode 100644 doc/next/6-stdlib/99-minor/runtime/debug/42888.md delete mode 100644 doc/next/6-stdlib/99-minor/runtime/debug/67182.md delete mode 100644 doc/next/6-stdlib/99-minor/runtime/pprof/43669.md delete mode 100644 doc/next/6-stdlib/99-minor/runtime/trace/65319.md delete mode 100644 doc/next/6-stdlib/99-minor/slices/53987.md delete mode 100644 doc/next/6-stdlib/99-minor/slices/61899.md delete mode 100644 doc/next/6-stdlib/99-minor/slices/65238.md delete mode 100644 doc/next/6-stdlib/99-minor/structs/66408.md delete mode 100644 doc/next/6-stdlib/99-minor/sync/61696.md delete mode 100644 doc/next/6-stdlib/99-minor/sync/atomic/61395.md delete mode 100644 doc/next/6-stdlib/99-minor/syscall/62254.md delete mode 100644 doc/next/6-stdlib/99-minor/syscall/65817.md delete mode 100644 doc/next/6-stdlib/99-minor/testing/fstest/63675.md delete mode 100644 doc/next/6-stdlib/99-minor/text/template/57646.md delete mode 100644 doc/next/6-stdlib/99-minor/time/67470.md delete mode 100644 doc/next/6-stdlib/99-minor/unicode/utf16/44940.md delete mode 100644 doc/next/6-stdlib/99-minor/unique/62483.md delete mode 100644 doc/next/7-ports.md delete mode 100644 doc/next/9-todo.md diff --git a/doc/next/1-intro.md b/doc/next/1-intro.md deleted file mode 100644 index 585c6c8e52c32e..00000000000000 --- a/doc/next/1-intro.md +++ /dev/null @@ -1,14 +0,0 @@ - - - - -## DRAFT RELEASE NOTES — Introduction to Go 1.23 {#introduction} - -**Go 1.23 is not yet released. These are work-in-progress release notes. -Go 1.23 is expected to be released in August 2024.** diff --git a/doc/next/2-language.md b/doc/next/2-language.md deleted file mode 100644 index 83e3a51437e547..00000000000000 --- a/doc/next/2-language.md +++ /dev/null @@ -1,18 +0,0 @@ -## Changes to the language {#language} - - -Go 1.23 makes the (Go 1.22) ["range-over-func" experiment](/wiki/RangefuncExperiment) a part of the language. -The "range" clause in a "for-range" loop now accepts iterator functions of the following types - - func(func() bool) - func(func(K) bool) - func(func(K, V) bool) - -as range expressions. -Calls of the iterator argument function produce the iteration values for the "for-range" loop. -For details see the [iter] package documentation and the [language spec](/ref/spec#For_range). -For motivation see the 2022 ["range-over-func" discussion](/issue/56413). - - -Go 1.23 includes preview support for [generic type aliases](/issue/46477). -Building the toolchain with `GOEXPERIMENT=aliastypeparams` enables this feature. diff --git a/doc/next/3-tools.md b/doc/next/3-tools.md deleted file mode 100644 index 7ae651e0b4e61f..00000000000000 --- a/doc/next/3-tools.md +++ /dev/null @@ -1,84 +0,0 @@ -## Tools {#tools} - -### Telemetry - - -Starting in Go 1.23, the Go toolchain can collect usage and breakage -statistics that help the Go team understand how the Go toolchain is -used and how well it is working. We refer to these statistics as -[Go telemetry](/doc/telemetry). - -Go telemetry is an _opt-in system_, controlled by the -[`go` `telemetry` command](/cmd/go/#hdr-Manage_telemetry_data_and_settings). -By default, the toolchain programs -collect statistics in counter files that can be inspected locally -but are otherwise unused (`go` `telemetry` `local`). - -To help us keep Go working well and understand Go usage, -please consider opting in to Go telemetry by running -`go` `telemetry` `on`. -In that mode, -anonymous counter reports are uploaded to -[telemetry.go.dev](https://telemetry.go.dev) weekly, -where they are aggregated into graphs and also made -available for download by any Go contributors or users -wanting to analyze the data. -See “[Go Telemetry](/doc/telemetry)” for more details -about the Go Telemetry system. - -### Go command {#go-command} - -Setting the `GOROOT_FINAL` environment variable no longer has an effect -([#62047](/issue/62047)). -Distributions that install the `go` command to a location other than -`$GOROOT/bin/go` should install a symlink instead of relocating -or copying the `go` binary. - - -The new `go` `env` `-changed` flag causes the command to print only -those settings whose effective value differs from the default value -that would be obtained in an empty environment with no prior uses of the `-w` flag. - - -The new `go` `mod` `tidy` `-diff` flag causes the command not to modify -the files but instead print the necessary changes as a unified diff. -It exits with a non-zero code if updates are needed. - - -The `go` `list` `-m` `-json` command now includes new `Sum` and `GoModSum` fields. -This is similar to the existing behavior of the `go` `mod` `download` `-json` command. - - -The new `godebug` directive in `go.mod` and `go.work` declares a -[GODEBUG setting](/doc/godebug) to apply for the work module or workspace in use. - -### Vet {#vet} - - -The `go vet` subcommand now includes the -[stdversion](https://pkg.go.dev/golang.org/x/tools/go/analysis/passes/stdversion) -analyzer, which flags references to symbols that are too new for the version -of Go in effect in the referring file. (The effective version is determined -by the `go` directive in the file's enclosing `go.mod` file, and -by any [`//go:build` constraints](/cmd/go#hdr-Build_constraints) -in the file.) - -For example, it will report a diagnostic for a reference to the -`reflect.TypeFor` function (introduced in go1.22) from a file in a -module whose go.mod file specifies `go 1.21`. - -### Cgo {#cgo} - - -[cmd/cgo] supports the new `-ldflags` flag for passing flags to the C linker. -The `go` command uses it automatically, avoiding "argument list too long" -errors with a very large `CGO_LDFLAGS`. - -### Trace {#trace} - - -The `trace` tool now better tolerates partially broken traces by attempting to -recover what trace data it can. This functionality is particularly helpful when -viewing a trace that was collected during a program crash, since the trace data -leading up to the crash will now [be recoverable](/issue/65319) under most -circumstances. diff --git a/doc/next/4-runtime.md b/doc/next/4-runtime.md deleted file mode 100644 index 7553154a162b07..00000000000000 --- a/doc/next/4-runtime.md +++ /dev/null @@ -1,7 +0,0 @@ -## Runtime {#runtime} - -The traceback printed by the runtime after an unhandled panic or other -fatal error now indents the second and subsequent lines of the error -message (for example, the argument to panic) by a single tab, so that -it can be unambiguously distinguished from the stack trace of the -first goroutine. See [#64590](/issue/64590) for discussion. diff --git a/doc/next/5-toolchain.md b/doc/next/5-toolchain.md deleted file mode 100644 index 51a1dbfbdf3f8f..00000000000000 --- a/doc/next/5-toolchain.md +++ /dev/null @@ -1,38 +0,0 @@ -## Compiler {#compiler} - -The build time overhead to building with [Profile Guided Optimization](/doc/pgo) has been reduced significantly. -Previously, large builds could see 100%+ build time increase from enabling PGO. -In Go 1.23, overhead should be in the single digit percentages. - - -The compiler in Go 1.23 can now overlap the stack frame slots of local variables -accessed in disjoint regions of a function, which reduces stack usage -for Go applications. - - -For 386 and amd64, the compiler will use information from PGO to align certain -hot blocks in loops. This improves performance an additional 1-1.5% at -a cost of an additional 0.1% text and binary size. This is currently only implemented -on 386 and amd64 because it has not shown an improvement on other platforms. -Hot block alignment can be disabled with `-gcflags=[=]-d=alignhot=0` - -## Assembler {#assembler} - -## Linker {#linker} - - -The linker now disallows using a `//go:linkname` directive to refer to -internal symbols in the standard library (including the runtime) that -are not marked with `//go:linkname` on their definitions. -Similarly, the linker disallows references to such symbols from assembly -code. -For backward compatibility, existing usages of `//go:linkname` found in -a large open-source code corpus remain supported. -Any new references to standard library internal symbols will be disallowed. - -A linker command line flag `-checklinkname=0` can be used to disable -this check, for debugging and experimenting purposes. - - -When building a dynamically linked ELF binary (including PIE binary), the -new `-bindnow` flag enables immediate function binding. diff --git a/doc/next/6-stdlib/0-heading.md b/doc/next/6-stdlib/0-heading.md deleted file mode 100644 index 02351ce1c091ad..00000000000000 --- a/doc/next/6-stdlib/0-heading.md +++ /dev/null @@ -1,2 +0,0 @@ -## Core library {#library} - diff --git a/doc/next/6-stdlib/1-time.md b/doc/next/6-stdlib/1-time.md deleted file mode 100644 index 6046ac53501dc4..00000000000000 --- a/doc/next/6-stdlib/1-time.md +++ /dev/null @@ -1,32 +0,0 @@ -### Timer changes - -Go 1.23 makes two significant changes to the implementation of -[time.Timer] and [time.Ticker]. - - -First, `Timer`s and `Ticker`s that are no longer referred to by the program -become eligible for garbage collection immediately, even if their -`Stop` methods have not been called. -Earlier versions of Go did not collect unstopped `Timer`s until after -they had fired and never collected unstopped `Ticker`s. - - -Second, the timer channel associated with a `Timer` or `Ticker` is -now unbuffered, with capacity 0. -The main effect of this change is that Go now guarantees -that for any call to a `Reset` or `Stop` method, no stale values -prepared before that call will be sent or received after the call. -Earlier versions of Go used channels with a one-element buffer, -making it difficult to use `Reset` and `Stop` correctly. -A visible effect of this change is that `len` and `cap` of timer channels -now returns 0 instead of 1, which may affect programs that -poll the length to decide whether a receive on the timer channel -will succeed. -Such code should use a non-blocking receive instead. - -These new behaviors are only enabled when the main Go program -is in a module with a `go.mod` `go` line using Go 1.23.0 or later. -When Go 1.23 builds older programs, the old behaviors remain in effect. -The new [GODEBUG setting](/doc/godebug) [`asynctimerchan=1`](/pkg/time/#NewTimer) -can be used to revert back to asynchronous channel behaviors -even when a program names Go 1.23.0 or later in its `go.mod` file. diff --git a/doc/next/6-stdlib/2-unique.md b/doc/next/6-stdlib/2-unique.md deleted file mode 100644 index 42737a52fa3618..00000000000000 --- a/doc/next/6-stdlib/2-unique.md +++ /dev/null @@ -1,13 +0,0 @@ -### New unique package - -The new [unique] package provides facilities for -canonicalizing values (like "interning" or "hash-consing"). - -Any value of comparable type may be canonicalized with the new -`Make[T]` function, which produces a reference to a canonical copy of -the value in the form of a `Handle[T]`. -Two `Handle[T]` are equal if and only if the values used to produce the -handles are equal, allowing programs to deduplicate values and reduce -their memory footprint. -Comparing two `Handle[T]` values is efficient, reducing down to a simple -pointer comparison. diff --git a/doc/next/6-stdlib/3-iter.md b/doc/next/6-stdlib/3-iter.md deleted file mode 100644 index bbb3bbbd8f23e8..00000000000000 --- a/doc/next/6-stdlib/3-iter.md +++ /dev/null @@ -1,29 +0,0 @@ -### Iterators - -The new [iter] package provides the basic definitions for working with -user-defined iterators. - -The [slices] package adds several functions that work with iterators: -- [All](/pkg/slices#All) returns an iterator over slice indexes and values. -- [Values](/pkg/slices#Values) returns an iterator over slice elements. -- [Backward](/pkg/slices#Backward) returns an iterator that loops over - a slice backward. -- [Collect](/pkg/slices#Collect) collects values from an iterator into - a new slice. -- [AppendSeq](/pkg/slices#AppendSeq) appends values from an iterator to - an existing slice. -- [Sorted](/pkg/slices#Sorted) collects values from an iterator into a - new slice, and then sorts the slice. -- [SortedFunc](/pkg/slices#SortedFunc) is like `Sorted` but with a - comparison function. -- [SortedStableFunc](/pkg/slices#SortedStableFunc) is like `SortFunc` - but uses a stable sort algorithm. -- [Chunk](/pkg/slices#Chunk) returns an iterator over consecutive - sub-slices of up to n elements of a slice. - -The [maps] package adds several functions that work with iterators: -- [All](/pkg/maps#All) returns an iterator over key-value pairs from a map. -- [Keys](/pkg/maps#Keys) returns an iterator over keys in a map. -- [Values](/pkg/maps#Values) returns an iterator over values in a map. -- [Insert](/pkg/maps#Insert) adds the key-value pairs from an iterator to an existing map. -- [Collect](/pkg/maps#Collect) collects key-value pairs from an iterator into a new map and returns it. diff --git a/doc/next/6-stdlib/4-structs.md b/doc/next/6-stdlib/4-structs.md deleted file mode 100644 index adf42f1b375cf7..00000000000000 --- a/doc/next/6-stdlib/4-structs.md +++ /dev/null @@ -1,11 +0,0 @@ -### New structs package - -The new [structs] package provides -types for struct fields that modify properties of -the containing struct type such as memory layout. - -In this release, the only such type is -[`HostLayout`](/pkg/structs#HostLayout) -which indicates that a structure with a field of that -type has a layout that conforms to host platform -expectations. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/0-heading.md b/doc/next/6-stdlib/99-minor/0-heading.md deleted file mode 100644 index a98105e8ccba7f..00000000000000 --- a/doc/next/6-stdlib/99-minor/0-heading.md +++ /dev/null @@ -1,3 +0,0 @@ -### Minor changes to the library {#minor_library_changes} - - diff --git a/doc/next/6-stdlib/99-minor/README b/doc/next/6-stdlib/99-minor/README deleted file mode 100644 index fac778de050642..00000000000000 --- a/doc/next/6-stdlib/99-minor/README +++ /dev/null @@ -1 +0,0 @@ -API changes and other small changes to the standard library go here. diff --git a/doc/next/6-stdlib/99-minor/archive/tar/50102.md b/doc/next/6-stdlib/99-minor/archive/tar/50102.md deleted file mode 100644 index ed8675f6933ffc..00000000000000 --- a/doc/next/6-stdlib/99-minor/archive/tar/50102.md +++ /dev/null @@ -1,4 +0,0 @@ -If the argument to [FileInfoHeader] implements the new [FileInfoNames] -interface, then the interface methods will be used to set the Uname/Gname -of the file header. This allows applications to override the system-dependent -Uname/Gname lookup. diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/63369.md b/doc/next/6-stdlib/99-minor/crypto/tls/63369.md deleted file mode 100644 index 6ec5b5bdf62d3e..00000000000000 --- a/doc/next/6-stdlib/99-minor/crypto/tls/63369.md +++ /dev/null @@ -1,3 +0,0 @@ -The TLS client now supports the Encrypted Client Hello [draft specification](https://www.ietf.org/archive/id/draft-ietf-tls-esni-18.html). -This feature can be enabled by setting the [Config.EncryptedClientHelloConfigList] -field to an encoded ECHConfigList for the host that is being connected to. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/63691.md b/doc/next/6-stdlib/99-minor/crypto/tls/63691.md deleted file mode 100644 index 67ed04cf00d84f..00000000000000 --- a/doc/next/6-stdlib/99-minor/crypto/tls/63691.md +++ /dev/null @@ -1,3 +0,0 @@ -The [QUICConn] type used by QUIC implementations includes new events -reporting on the state of session resumption, and provides a way for -the QUIC layer to add data to session tickets and session cache entries. diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/66214.md b/doc/next/6-stdlib/99-minor/crypto/tls/66214.md deleted file mode 100644 index ebe1b490f57851..00000000000000 --- a/doc/next/6-stdlib/99-minor/crypto/tls/66214.md +++ /dev/null @@ -1,3 +0,0 @@ -3DES cipher suites were removed from the default list used when -[Config.CipherSuites] is nil. The default can be reverted by adding `tls3des=1` to -the GODEBUG environment variable. diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/67061.md b/doc/next/6-stdlib/99-minor/crypto/tls/67061.md deleted file mode 100644 index fe3620ed6d25b5..00000000000000 --- a/doc/next/6-stdlib/99-minor/crypto/tls/67061.md +++ /dev/null @@ -1,3 +0,0 @@ -The experimental post-quantum key exchange mechanism X25519Kyber768Draft00 -is now enabled by default when [Config.CurvePreferences] is nil. -The default can be reverted by adding `tlskyber=0` to the GODEBUG environment variable. diff --git a/doc/next/6-stdlib/99-minor/crypto/tls/67065.md b/doc/next/6-stdlib/99-minor/crypto/tls/67065.md deleted file mode 100644 index 3fcc8d53093683..00000000000000 --- a/doc/next/6-stdlib/99-minor/crypto/tls/67065.md +++ /dev/null @@ -1,3 +0,0 @@ -Go 1.23 changed the behavior of [X509KeyPair] and [LoadX509KeyPair] -to populate the [Certificate.Leaf] field of the returned [Certificate]. -The new `x509keypairleaf` [GODEBUG setting](/doc/godebug) is added for this behavior. diff --git a/doc/next/6-stdlib/99-minor/crypto/x509/45990.md b/doc/next/6-stdlib/99-minor/crypto/x509/45990.md deleted file mode 100644 index 2eda8476a9a687..00000000000000 --- a/doc/next/6-stdlib/99-minor/crypto/x509/45990.md +++ /dev/null @@ -1,3 +0,0 @@ -[CreateCertificateRequest] now correct supports RSA-PSS signature algorithms. - -[CreateCertificateRequest] and [CreateRevocationList] now verify the generated signature using the signer’s public key. If the signature is invalid, an error is returned. This has been the behavior of [CreateCertificate] since Go 1.16. diff --git a/doc/next/6-stdlib/99-minor/crypto/x509/62048.md b/doc/next/6-stdlib/99-minor/crypto/x509/62048.md deleted file mode 100644 index aaa8c5e3506fb0..00000000000000 --- a/doc/next/6-stdlib/99-minor/crypto/x509/62048.md +++ /dev/null @@ -1,4 +0,0 @@ -The [`x509sha1` GODEBUG setting](/pkg/crypto/x509#InsecureAlgorithmError) will -be removed in the next Go major release (Go 1.24). This will mean that crypto/x509 -will no longer support verifying signatures on certificates that use SHA-1 based -signature algorithms. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/crypto/x509/66249.md b/doc/next/6-stdlib/99-minor/crypto/x509/66249.md deleted file mode 100644 index d449e74d66364b..00000000000000 --- a/doc/next/6-stdlib/99-minor/crypto/x509/66249.md +++ /dev/null @@ -1,3 +0,0 @@ -The new [ParseOID] function parses a dot-encoded ASN.1 Object Identifier string. -The [OID] type now implements the [encoding.BinaryMarshaler], -[encoding.BinaryUnmarshaler], [encoding.TextMarshaler], [encoding.TextUnmarshaler] interfaces. diff --git a/doc/next/6-stdlib/99-minor/database/sql/64707.md b/doc/next/6-stdlib/99-minor/database/sql/64707.md deleted file mode 100644 index 17d4516ba8a0b3..00000000000000 --- a/doc/next/6-stdlib/99-minor/database/sql/64707.md +++ /dev/null @@ -1,3 +0,0 @@ -Errors returned by [driver.Valuer] implementations are now wrapped for -improved error handling during operations like [DB.Query], [DB.Exec], -and [DB.QueryRow]. diff --git a/doc/next/6-stdlib/99-minor/debug/elf/66054.md b/doc/next/6-stdlib/99-minor/debug/elf/66054.md deleted file mode 100644 index 0b3443f7d4034b..00000000000000 --- a/doc/next/6-stdlib/99-minor/debug/elf/66054.md +++ /dev/null @@ -1,3 +0,0 @@ -The `debug/elf` package now defines [PT_OPENBSD_NOBTCFI]. This [ProgType] is -used to disable Branch Tracking Control Flow Integrity (BTCFI) enforcement -on OpenBSD binaries. diff --git a/doc/next/6-stdlib/99-minor/debug/elf/66836.md b/doc/next/6-stdlib/99-minor/debug/elf/66836.md deleted file mode 100644 index 4aad5798dd4687..00000000000000 --- a/doc/next/6-stdlib/99-minor/debug/elf/66836.md +++ /dev/null @@ -1,2 +0,0 @@ -Now defines the symbol type constants [STT_RELC], [STT_SRELC], and -[STT_GNU_IFUNC]. diff --git a/doc/next/6-stdlib/99-minor/encoding/binary/60023.md b/doc/next/6-stdlib/99-minor/encoding/binary/60023.md deleted file mode 100644 index 015bfc380314a1..00000000000000 --- a/doc/next/6-stdlib/99-minor/encoding/binary/60023.md +++ /dev/null @@ -1,3 +0,0 @@ -The new [Encode] and [Decode] functions are byte slice equivalents -to [Read] and [Write]. -[Append] allows marshaling multiple data into the same byte slice. diff --git a/doc/next/6-stdlib/99-minor/go/ast/66339.md b/doc/next/6-stdlib/99-minor/go/ast/66339.md deleted file mode 100644 index 0eec51ecd69390..00000000000000 --- a/doc/next/6-stdlib/99-minor/go/ast/66339.md +++ /dev/null @@ -1,2 +0,0 @@ -The new [Preorder] function returns a convenient iterator over all the -nodes of a syntax tree. diff --git a/doc/next/6-stdlib/99-minor/go/types/46477.md b/doc/next/6-stdlib/99-minor/go/types/46477.md deleted file mode 100644 index 7f744dc6ae4eee..00000000000000 --- a/doc/next/6-stdlib/99-minor/go/types/46477.md +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/go/types/65772.md b/doc/next/6-stdlib/99-minor/go/types/65772.md deleted file mode 100644 index ec7f0b0e59bc0e..00000000000000 --- a/doc/next/6-stdlib/99-minor/go/types/65772.md +++ /dev/null @@ -1,3 +0,0 @@ -The [Func] type, which represents a function or method symbol, now -has a [Func.Signature] method that returns the function's type, which -is always a `Signature`. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/go/types/66559.md b/doc/next/6-stdlib/99-minor/go/types/66559.md deleted file mode 100644 index e3884594fa204d..00000000000000 --- a/doc/next/6-stdlib/99-minor/go/types/66559.md +++ /dev/null @@ -1,3 +0,0 @@ -The [Alias] type now has an [Rhs] method that returns the type on the -right-hand side of its declaration: given `type A = B`, the `Rhs` of A -is B. ([#66559](/issue/66559)) diff --git a/doc/next/6-stdlib/99-minor/go/types/67143.md b/doc/next/6-stdlib/99-minor/go/types/67143.md deleted file mode 100644 index 405c679378e8d7..00000000000000 --- a/doc/next/6-stdlib/99-minor/go/types/67143.md +++ /dev/null @@ -1,2 +0,0 @@ -The methods [Alias.Origin], [Alias.SetTypeParams], [Alias.TypeParams], -and [Alias.TypeArgs] have been added. They are needed for generic alias types. diff --git a/doc/next/6-stdlib/99-minor/go/types/cl-577715.md b/doc/next/6-stdlib/99-minor/go/types/cl-577715.md deleted file mode 100644 index 939d5ac46c6578..00000000000000 --- a/doc/next/6-stdlib/99-minor/go/types/cl-577715.md +++ /dev/null @@ -1,4 +0,0 @@ - -By default, go/types now produces [Alias] type nodes for type aliases. -This behavior can be controlled by the `GODEBUG` `gotypesalias` flag. -Its default has changed from 0 in Go 1.22 to 1 in Go 1.23. diff --git a/doc/next/6-stdlib/99-minor/iter/61897.md b/doc/next/6-stdlib/99-minor/iter/61897.md deleted file mode 100644 index 02d77cd11df35e..00000000000000 --- a/doc/next/6-stdlib/99-minor/iter/61897.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/6-stdlib/99-minor/maps/61900.md b/doc/next/6-stdlib/99-minor/maps/61900.md deleted file mode 100644 index 02d77cd11df35e..00000000000000 --- a/doc/next/6-stdlib/99-minor/maps/61900.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/6-stdlib/99-minor/math/rand/v2/61716.md b/doc/next/6-stdlib/99-minor/math/rand/v2/61716.md deleted file mode 100644 index 68ff614ee5c0d6..00000000000000 --- a/doc/next/6-stdlib/99-minor/math/rand/v2/61716.md +++ /dev/null @@ -1,2 +0,0 @@ -The [Uint] function and [Rand.Uint] method have been added. -They were inadvertently left out of Go 1.22. diff --git a/doc/next/6-stdlib/99-minor/math/rand/v2/67059.md b/doc/next/6-stdlib/99-minor/math/rand/v2/67059.md deleted file mode 100644 index c66110c7a4453b..00000000000000 --- a/doc/next/6-stdlib/99-minor/math/rand/v2/67059.md +++ /dev/null @@ -1 +0,0 @@ -The new [ChaCha8.Read] method implements the [io.Reader] interface. diff --git a/doc/next/6-stdlib/99-minor/net/62254.md b/doc/next/6-stdlib/99-minor/net/62254.md deleted file mode 100644 index 639140bbec1f2d..00000000000000 --- a/doc/next/6-stdlib/99-minor/net/62254.md +++ /dev/null @@ -1,3 +0,0 @@ -The new type [KeepAliveConfig] permits fine-tuning the keep-alive -options for TCP connections, via a new [TCPConn.SetKeepAliveConfig] -method and new KeepAliveConfig fields for [Dialer] and [ListenConfig]. diff --git a/doc/next/6-stdlib/99-minor/net/63116.md b/doc/next/6-stdlib/99-minor/net/63116.md deleted file mode 100644 index 87a098374927b3..00000000000000 --- a/doc/next/6-stdlib/99-minor/net/63116.md +++ /dev/null @@ -1,3 +0,0 @@ -The [DNSError] type now wraps errors caused by timeouts or cancellation. -For example, `errors.Is(someDNSErr, context.DeadlineExceedeed)` -will now report whether a DNS error was caused by a timeout. diff --git a/doc/next/6-stdlib/99-minor/net/67925.md b/doc/next/6-stdlib/99-minor/net/67925.md deleted file mode 100644 index e43f0cd644e243..00000000000000 --- a/doc/next/6-stdlib/99-minor/net/67925.md +++ /dev/null @@ -1,3 +0,0 @@ -The new `GODEBUG` setting `netedns0=0` disables sending EDNS0 -additional headers on DNS requests, as they reportedly break the DNS -server on some modems. diff --git a/doc/next/6-stdlib/99-minor/net/http/46443.md b/doc/next/6-stdlib/99-minor/net/http/46443.md deleted file mode 100644 index 37ceae9eddd33b..00000000000000 --- a/doc/next/6-stdlib/99-minor/net/http/46443.md +++ /dev/null @@ -1,3 +0,0 @@ -[Cookie] now preserves double quotes surrounding a cookie value. -The new [Cookie.Quoted] field indicates whether the [Cookie.Value] -was originally quoted. diff --git a/doc/next/6-stdlib/99-minor/net/http/61472.md b/doc/next/6-stdlib/99-minor/net/http/61472.md deleted file mode 100644 index b3c2fd54094652..00000000000000 --- a/doc/next/6-stdlib/99-minor/net/http/61472.md +++ /dev/null @@ -1 +0,0 @@ -The new [Request.CookiesNamed] method retrieves all cookies that match the given name. diff --git a/doc/next/6-stdlib/99-minor/net/http/62490.md b/doc/next/6-stdlib/99-minor/net/http/62490.md deleted file mode 100644 index 891eb45daea337..00000000000000 --- a/doc/next/6-stdlib/99-minor/net/http/62490.md +++ /dev/null @@ -1 +0,0 @@ -The new [Cookie.Partitioned] field identifies cookies with the Partitioned attribute. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/net/http/64910.md b/doc/next/6-stdlib/99-minor/net/http/64910.md deleted file mode 100644 index 28452ee9327a38..00000000000000 --- a/doc/next/6-stdlib/99-minor/net/http/64910.md +++ /dev/null @@ -1,2 +0,0 @@ -The patterns used by [ServeMux] now allow one or more spaces or tabs after the method name. -Previously, only a single space was permitted. diff --git a/doc/next/6-stdlib/99-minor/net/http/66008.md b/doc/next/6-stdlib/99-minor/net/http/66008.md deleted file mode 100644 index e8603707ef3150..00000000000000 --- a/doc/next/6-stdlib/99-minor/net/http/66008.md +++ /dev/null @@ -1,7 +0,0 @@ -The new [ParseCookie] function parses a Cookie header value and -returns all the cookies which were set in it. Since the same cookie -name can appear multiple times the returned Values can contain -more than one value for a given key. - -The new [ParseSetCookie] function parses a Set-Cookie header value and -returns a cookie. It returns an error on syntax error. diff --git a/doc/next/6-stdlib/99-minor/net/http/66343.md b/doc/next/6-stdlib/99-minor/net/http/66343.md deleted file mode 100644 index b39e8624e7def1..00000000000000 --- a/doc/next/6-stdlib/99-minor/net/http/66343.md +++ /dev/null @@ -1,16 +0,0 @@ -[ServeContent], [ServeFile], and [ServeFileFS] now remove -the `Cache-Control`, `Content-Encoding`, `Etag`, and `Last-Modified` -headers when serving an error. These headers usually apply to the -non-error content, but not to the text of errors. - -Middleware which wraps a [ResponseWriter] and applies on-the-fly -encoding, such as `Content-Encoding: gzip`, will not function after -this change. The previous behavior of [ServeContent], [ServeFile], -and [ServeFileFS] may be restored by setting -`GODEBUG=httpservecontentkeepheaders=1`. - -Note that middleware which changes the size of the served content -(such as by compressing it) already does not function properly when -[ServeContent] handles a Range request. On-the-fly compression -should use the `Transfer-Encoding` header instead of `Content-Encoding`. - diff --git a/doc/next/6-stdlib/99-minor/net/http/66405.md b/doc/next/6-stdlib/99-minor/net/http/66405.md deleted file mode 100644 index c827b4b2192b87..00000000000000 --- a/doc/next/6-stdlib/99-minor/net/http/66405.md +++ /dev/null @@ -1,3 +0,0 @@ -For inbound requests, the new [Request.Pattern] field contains the [ServeMux] -pattern (if any) that matched the request. This field is not set when -`GODEBUG=httpmuxgo121=1` is set. diff --git a/doc/next/6-stdlib/99-minor/net/http/httptest/59473.md b/doc/next/6-stdlib/99-minor/net/http/httptest/59473.md deleted file mode 100644 index a640bbd0e4b08f..00000000000000 --- a/doc/next/6-stdlib/99-minor/net/http/httptest/59473.md +++ /dev/null @@ -1,2 +0,0 @@ -The new [NewRequestWithContext] method creates an incoming request with -a [context.Context]. diff --git a/doc/next/6-stdlib/99-minor/os/33357.md b/doc/next/6-stdlib/99-minor/os/33357.md deleted file mode 100644 index bd542d9d77ac0e..00000000000000 --- a/doc/next/6-stdlib/99-minor/os/33357.md +++ /dev/null @@ -1,3 +0,0 @@ -The [Stat] function now sets the [ModeSocket] bit for -files that are Unix sockets on Windows. These files are identified -by having a reparse tag set to `IO_REPARSE_TAG_AF_UNIX`. diff --git a/doc/next/6-stdlib/99-minor/os/61893.md b/doc/next/6-stdlib/99-minor/os/61893.md deleted file mode 100644 index d22060c8698017..00000000000000 --- a/doc/next/6-stdlib/99-minor/os/61893.md +++ /dev/null @@ -1,7 +0,0 @@ -On Windows, the mode bits reported by [Lstat] and [Stat] for -reparse points changed. Mount points no longer have [ModeSymlink] set, -and reparse points that are not symlinks, Unix sockets, or dedup files -now always have [ModeIrregular] set. -This behavior is controlled by the `winsymlink` setting. -For Go 1.23, it defaults to `winsymlink=1`. -Previous versions default to `winsymlink=0`. diff --git a/doc/next/6-stdlib/99-minor/os/62484.md b/doc/next/6-stdlib/99-minor/os/62484.md deleted file mode 100644 index c99801bb6c7d9b..00000000000000 --- a/doc/next/6-stdlib/99-minor/os/62484.md +++ /dev/null @@ -1 +0,0 @@ -The [CopyFS] function copies an [io/fs.FS] into the local filesystem. diff --git a/doc/next/6-stdlib/99-minor/os/63703.md b/doc/next/6-stdlib/99-minor/os/63703.md deleted file mode 100644 index 3fbb2594cf7953..00000000000000 --- a/doc/next/6-stdlib/99-minor/os/63703.md +++ /dev/null @@ -1,5 +0,0 @@ -On Windows, [Readlink] no longer tries to normalize volumes -to drive letters, which was not always even possible. -This behavior is controlled by the `winreadlinkvolume` setting. -For Go 1.23, it defaults to `winreadlinkvolume=1`. -Previous versions default to `winreadlinkvolume=0`. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/path/filepath/57151.md b/doc/next/6-stdlib/99-minor/path/filepath/57151.md deleted file mode 100644 index 5a99e3a4f2cffa..00000000000000 --- a/doc/next/6-stdlib/99-minor/path/filepath/57151.md +++ /dev/null @@ -1,2 +0,0 @@ -The new [Localize] function safely converts a slash-separated -path into an operating system path. diff --git a/doc/next/6-stdlib/99-minor/path/filepath/63703.md b/doc/next/6-stdlib/99-minor/path/filepath/63703.md deleted file mode 100644 index da2b132d8b3a7d..00000000000000 --- a/doc/next/6-stdlib/99-minor/path/filepath/63703.md +++ /dev/null @@ -1,11 +0,0 @@ -On Windows, [EvalSymlinks] no longer evaluates mount points, -which was a source of many inconsistencies and bugs. -This behavior is controlled by the `winsymlink` setting. -For Go 1.23, it defaults to `winsymlink=1`. -Previous versions default to `winsymlink=0`. - -On Windows, [EvalSymlinks] no longer tries to normalize -volumes to drive letters, which was not always even possible. -This behavior is controlled by the `winreadlinkvolume` setting. -For Go 1.23, it defaults to `winreadlinkvolume=1`. -Previous versions default to `winreadlinkvolume=0`. \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/reflect/60427.md b/doc/next/6-stdlib/99-minor/reflect/60427.md deleted file mode 100644 index bca13607346e56..00000000000000 --- a/doc/next/6-stdlib/99-minor/reflect/60427.md +++ /dev/null @@ -1,6 +0,0 @@ -The new methods synonymous with the method of the same name -in [Value] are added to [Type]: -1. [Type.OverflowComplex] -2. [Type.OverflowFloat] -3. [Type.OverflowInt] -4. [Type.OverflowUint] diff --git a/doc/next/6-stdlib/99-minor/reflect/61308.md b/doc/next/6-stdlib/99-minor/reflect/61308.md deleted file mode 100644 index ec24655dce2c65..00000000000000 --- a/doc/next/6-stdlib/99-minor/reflect/61308.md +++ /dev/null @@ -1,3 +0,0 @@ -The new [SliceAt] function is analogous to [NewAt], but for slices. - -The [Value.Pointer] and [Value.UnsafePointer] methods now support values of kind [String]. diff --git a/doc/next/6-stdlib/99-minor/reflect/66056.md b/doc/next/6-stdlib/99-minor/reflect/66056.md deleted file mode 100644 index b5f39349df1aa5..00000000000000 --- a/doc/next/6-stdlib/99-minor/reflect/66056.md +++ /dev/null @@ -1,4 +0,0 @@ -The new methods [Value.Seq] and [Value.Seq2] return sequences that iterate over the value -as though it were used in a for/range loop. -The new methods [Type.CanSeq] and [Type.CanSeq2] report whether calling -[Value.Seq] and [Value.Seq2], respectively, will succeed without panicking. diff --git a/doc/next/6-stdlib/99-minor/runtime/debug/42888.md b/doc/next/6-stdlib/99-minor/runtime/debug/42888.md deleted file mode 100644 index f10753d25c20a9..00000000000000 --- a/doc/next/6-stdlib/99-minor/runtime/debug/42888.md +++ /dev/null @@ -1,5 +0,0 @@ -The [SetCrashOutput] function allows the user to specify an alternate -file to which the runtime should write its fatal crash report. -It may be used to construct an automated reporting mechanism for all -unexpected crashes, not just those in goroutines that explicitly use -`recover`. diff --git a/doc/next/6-stdlib/99-minor/runtime/debug/67182.md b/doc/next/6-stdlib/99-minor/runtime/debug/67182.md deleted file mode 100644 index d83864a3dbbcb8..00000000000000 --- a/doc/next/6-stdlib/99-minor/runtime/debug/67182.md +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/doc/next/6-stdlib/99-minor/runtime/pprof/43669.md b/doc/next/6-stdlib/99-minor/runtime/pprof/43669.md deleted file mode 100644 index 119308b46a2d6b..00000000000000 --- a/doc/next/6-stdlib/99-minor/runtime/pprof/43669.md +++ /dev/null @@ -1,2 +0,0 @@ -The maximum stack depth for alloc, mutex, block, threadcreate and goroutine -profiles has been raised from 32 to 128 frames. diff --git a/doc/next/6-stdlib/99-minor/runtime/trace/65319.md b/doc/next/6-stdlib/99-minor/runtime/trace/65319.md deleted file mode 100644 index b180368e00b0a8..00000000000000 --- a/doc/next/6-stdlib/99-minor/runtime/trace/65319.md +++ /dev/null @@ -1,4 +0,0 @@ - -The runtime now explicitly flushes trace data when a program crashes due to an -uncaught panic. This means that more complete trace data will be available in a -trace if the program crashes while tracing is active. diff --git a/doc/next/6-stdlib/99-minor/slices/53987.md b/doc/next/6-stdlib/99-minor/slices/53987.md deleted file mode 100644 index 02d77cd11df35e..00000000000000 --- a/doc/next/6-stdlib/99-minor/slices/53987.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/6-stdlib/99-minor/slices/61899.md b/doc/next/6-stdlib/99-minor/slices/61899.md deleted file mode 100644 index 02d77cd11df35e..00000000000000 --- a/doc/next/6-stdlib/99-minor/slices/61899.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/6-stdlib/99-minor/slices/65238.md b/doc/next/6-stdlib/99-minor/slices/65238.md deleted file mode 100644 index 34ef66a2dd1d7a..00000000000000 --- a/doc/next/6-stdlib/99-minor/slices/65238.md +++ /dev/null @@ -1,2 +0,0 @@ -The [Repeat] function returns a new slice that repeats the -provided slice the given number of times. diff --git a/doc/next/6-stdlib/99-minor/structs/66408.md b/doc/next/6-stdlib/99-minor/structs/66408.md deleted file mode 100644 index 810a09e3ca825c..00000000000000 --- a/doc/next/6-stdlib/99-minor/structs/66408.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/6-stdlib/99-minor/sync/61696.md b/doc/next/6-stdlib/99-minor/sync/61696.md deleted file mode 100644 index 59584301f3dd94..00000000000000 --- a/doc/next/6-stdlib/99-minor/sync/61696.md +++ /dev/null @@ -1,2 +0,0 @@ -The [Map.Clear] method deletes all the entries, resulting in -an empty [Map]. It is analogous to `clear`. diff --git a/doc/next/6-stdlib/99-minor/sync/atomic/61395.md b/doc/next/6-stdlib/99-minor/sync/atomic/61395.md deleted file mode 100644 index 8aea9d6bf3a77a..00000000000000 --- a/doc/next/6-stdlib/99-minor/sync/atomic/61395.md +++ /dev/null @@ -1,3 +0,0 @@ - -The new [And] and [Or] operators apply a bitwise `AND` or `OR` to -the given input, returning the old value. diff --git a/doc/next/6-stdlib/99-minor/syscall/62254.md b/doc/next/6-stdlib/99-minor/syscall/62254.md deleted file mode 100644 index 1d463e5ea8127f..00000000000000 --- a/doc/next/6-stdlib/99-minor/syscall/62254.md +++ /dev/null @@ -1 +0,0 @@ -The syscall package now defines [WSAENOPROTOOPT] on Windows. diff --git a/doc/next/6-stdlib/99-minor/syscall/65817.md b/doc/next/6-stdlib/99-minor/syscall/65817.md deleted file mode 100644 index 9a2d12c0741e49..00000000000000 --- a/doc/next/6-stdlib/99-minor/syscall/65817.md +++ /dev/null @@ -1 +0,0 @@ -The [GetsockoptInt] function is now supported on Windows. diff --git a/doc/next/6-stdlib/99-minor/testing/fstest/63675.md b/doc/next/6-stdlib/99-minor/testing/fstest/63675.md deleted file mode 100644 index cea9ae3dc2e1a0..00000000000000 --- a/doc/next/6-stdlib/99-minor/testing/fstest/63675.md +++ /dev/null @@ -1,3 +0,0 @@ -[TestFS] now returns a structured error that can be unwrapped -(via method `Unwrap() []error`). This allows inspecting errors -using [errors.Is] or [errors.As]. diff --git a/doc/next/6-stdlib/99-minor/text/template/57646.md b/doc/next/6-stdlib/99-minor/text/template/57646.md deleted file mode 100644 index 5b8f031432d1a6..00000000000000 --- a/doc/next/6-stdlib/99-minor/text/template/57646.md +++ /dev/null @@ -1 +0,0 @@ -Templates now support the new "else with" action, which reduces template complexity in some use cases. diff --git a/doc/next/6-stdlib/99-minor/time/67470.md b/doc/next/6-stdlib/99-minor/time/67470.md deleted file mode 100644 index 8cfcc0aa9da31b..00000000000000 --- a/doc/next/6-stdlib/99-minor/time/67470.md +++ /dev/null @@ -1,2 +0,0 @@ -[Parse] and [ParseInLocation] now return an error if the time zone -offset is out of range. diff --git a/doc/next/6-stdlib/99-minor/unicode/utf16/44940.md b/doc/next/6-stdlib/99-minor/unicode/utf16/44940.md deleted file mode 100644 index e0667845883d3e..00000000000000 --- a/doc/next/6-stdlib/99-minor/unicode/utf16/44940.md +++ /dev/null @@ -1,3 +0,0 @@ -The [RuneLen] function returns the number of 16-bit words in -the UTF-16 encoding of the rune. It returns -1 if the rune -is not a valid value to encode in UTF-16. diff --git a/doc/next/6-stdlib/99-minor/unique/62483.md b/doc/next/6-stdlib/99-minor/unique/62483.md deleted file mode 100644 index d281ab290e361d..00000000000000 --- a/doc/next/6-stdlib/99-minor/unique/62483.md +++ /dev/null @@ -1 +0,0 @@ - diff --git a/doc/next/7-ports.md b/doc/next/7-ports.md deleted file mode 100644 index 51e0ac7441ad4e..00000000000000 --- a/doc/next/7-ports.md +++ /dev/null @@ -1,38 +0,0 @@ -## Ports {#ports} - -### Darwin {#darwin} - - -As [announced](go1.22#darwin) in the Go 1.22 release notes, -Go 1.23 requires macOS 11 Big Sur or later; -support for previous versions has been discontinued. - -### Linux {#linux} - - -Go 1.23 is the last release that requires Linux kernel version 2.6.32 or later. Go 1.24 will require Linux kernel version 3.17 or later, with an exception that systems running 3.10 or later will continue to be supported if the kernel has been patched to support the getrandom system call. - -### OpenBSD {#openbsd} - - -Go 1.23 adds experimental support for OpenBSD on 64-bit RISC-V (`GOOS=openbsd`, `GOARCH=riscv64`). - -### ARM64 {#arm64} - - -Go 1.23 introduces a new `GOARM64` environment variable, which specifies the minimum target version of the ARM64 architecture at compile time. Allowed values are `v8.{0-9}` and `v9.{0-5}`. This may be followed by an option specifying extensions implemented by target hardware. Valid options are `,lse` and `,crypto`. - -The `GOARM64` environment variable defaults to `v8.0`. - -### RISC-V {#riscv} - - -Go 1.23 introduces a new `GORISCV64` environment variable, which selects the [RISC-V user-mode application profile](https://github.com/riscv/riscv-profiles/blob/main/src/profiles.adoc) for which to compile. Allowed values are `rva20u64` and `rva22u64`. - -The `GORISCV64` environment variable defaults to `rva20u64`. - -### Wasm {#wasm} - - -The `go_wasip1_wasm_exec` script in `GOROOT/misc/wasm` has dropped support -for versions of `wasmtime` < 14.0.0. diff --git a/doc/next/9-todo.md b/doc/next/9-todo.md deleted file mode 100644 index 424780cd7d85cf..00000000000000 --- a/doc/next/9-todo.md +++ /dev/null @@ -1,51 +0,0 @@ - - - - - - - From 0af2148fdcd047e5aa15776a54ccc29d9aa36f7f Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Fri, 21 Jun 2024 16:32:37 -0400 Subject: [PATCH 23/41] cmd: vendor golang.org/x/telemetry@a740542 Commands run: go get golang.org/x/telemetry@a740542 go mod tidy go mod vendor Change-Id: I8b1a71adc05f3c54f9492dfb9cfd1873727e5680 Reviewed-on: https://go-review.googlesource.com/c/go/+/594017 Reviewed-by: Robert Findley LUCI-TryBot-Result: Go LUCI --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +-- .../golang.org/x/telemetry/counter/counter.go | 4 --- .../x/telemetry/internal/counter/file.go | 35 +++++++++++-------- src/cmd/vendor/modules.txt | 2 +- 5 files changed, 25 insertions(+), 22 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 0625195931d7bf..0a17a414b5fa9f 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -9,7 +9,7 @@ require ( golang.org/x/mod v0.18.0 golang.org/x/sync v0.7.0 golang.org/x/sys v0.21.0 - golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 + golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c golang.org/x/term v0.20.0 golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 25276c92b2e8b9..49849d10b4e171 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -16,8 +16,8 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 h1:2+8QyQRLYDeEKd+CM/BsuaBaLdhAsNdasS/SnZfPS9g= -golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= +golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c h1:zNxtD9mZQCgRwCNanVRlJ/XlOyATHcbR+09LzoArRl4= +golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= diff --git a/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go b/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go index 7a7e66b22d1714..ff727ad97ce508 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go +++ b/src/cmd/vendor/golang.org/x/telemetry/counter/counter.go @@ -83,8 +83,6 @@ func NewStack(name string, depth int) *StackCounter { // If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the // counter file on disk and starts to mmap telemetry counters to the file. // Open also persists any counters already created in the current process. -// -// Programs using telemetry should call either Open or OpenDir exactly once. func Open() { counter.Open() } @@ -95,8 +93,6 @@ func Open() { // If the telemetry mode is "off", Open is a no-op. Otherwise, it opens the // counter file on disk and starts to mmap telemetry counters to the file. // Open also persists any counters already created in the current process. -// -// Programs using telemetry should call either Open or OpenDir exactly once. func OpenDir(telemetryDir string) { if telemetryDir != "" { telemetry.Default = telemetry.NewDir(telemetryDir) diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go b/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go index 0cb6cc22de3095..e3c574dcb46d60 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/counter/file.go @@ -340,6 +340,8 @@ func (f *file) newCounter1(name string) (v *atomic.Uint64, cleanup func()) { return v, cleanup } +var openOnce sync.Once + // Open associates counting with the defaultFile. // The returned function is for testing only, and should // be called after all Inc()s are finished, but before @@ -349,22 +351,27 @@ func Open() func() { if telemetry.DisabledOnPlatform { return func() {} } - if mode, _ := telemetry.Default.Mode(); mode == "off" { - // Don't open the file when telemetry is off. - defaultFile.err = ErrDisabled - return func() {} // No need to clean up. - } - debugPrintf("Open") - defaultFile.rotate() - return func() { - // Once this has been called, the defaultFile is no longer usable. - mf := defaultFile.current.Load() - if mf == nil { - // telemetry might have been off + close := func() {} + openOnce.Do(func() { + if mode, _ := telemetry.Default.Mode(); mode == "off" { + // Don't open the file when telemetry is off. + defaultFile.err = ErrDisabled + // No need to clean up. return } - mf.close() - } + debugPrintf("Open") + defaultFile.rotate() + close = func() { + // Once this has been called, the defaultFile is no longer usable. + mf := defaultFile.current.Load() + if mf == nil { + // telemetry might have been off + return + } + mf.close() + } + }) + return close } // A mappedFile is a counter file mmapped into memory. diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index fc1f25588a8363..5184adb1f2a1af 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -45,7 +45,7 @@ golang.org/x/sync/semaphore golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/telemetry v0.0.0-20240621183135-b4de734908f6 +# golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c ## explicit; go 1.20 golang.org/x/telemetry golang.org/x/telemetry/counter From 44f18706661db8b865719d15a5cfa0515d1a4fca Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Mon, 17 Jun 2024 14:44:42 -0400 Subject: [PATCH 24/41] cmd/link: handle dynamic import variables on Darwin in plugin mode CL 501855 added support for cgo_dynamic_import variables on Darwin. But it didn't support the plugin build mode on amd64, where the assembler turns a direct load (R_PCREL) to a load via GOT (R_GOTPCREL). This CL adds the support. We just need to handle external linking mode, as this can only occur in plugin or shared build mode, which requires external linking. Fixes #67976. Updates #50891. Change-Id: I0f56265d50bfcb36047fa5538ad7a5ec77e7ef96 Reviewed-on: https://go-review.googlesource.com/c/go/+/592499 Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI --- src/cmd/cgo/internal/testplugin/plugin_test.go | 8 ++++++++ .../testplugin/testdata/issue67976/plugin.go | 16 ++++++++++++++++ src/cmd/link/internal/amd64/asm.go | 7 +++++++ 3 files changed, 31 insertions(+) create mode 100644 src/cmd/cgo/internal/testplugin/testdata/issue67976/plugin.go diff --git a/src/cmd/cgo/internal/testplugin/plugin_test.go b/src/cmd/cgo/internal/testplugin/plugin_test.go index 4900ada1820156..85dfd31123b5de 100644 --- a/src/cmd/cgo/internal/testplugin/plugin_test.go +++ b/src/cmd/cgo/internal/testplugin/plugin_test.go @@ -414,3 +414,11 @@ func TestTextSectionSplit(t *testing.T) { t.Errorf("runtime.text.1 not found, text section not split?") } } + +func TestIssue67976(t *testing.T) { + // Issue 67976: build failure with loading a dynimport variable (the runtime/pprof + // package does this on darwin) in a plugin on darwin/amd64. + // The test program uses runtime/pprof in a plugin. + globalSkip(t) + goCmd(t, "build", "-buildmode=plugin", "-o", "issue67976.so", "./issue67976/plugin.go") +} diff --git a/src/cmd/cgo/internal/testplugin/testdata/issue67976/plugin.go b/src/cmd/cgo/internal/testplugin/testdata/issue67976/plugin.go new file mode 100644 index 00000000000000..502ecc5c4750f4 --- /dev/null +++ b/src/cmd/cgo/internal/testplugin/testdata/issue67976/plugin.go @@ -0,0 +1,16 @@ +// Copyright 2024 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +import ( + "io" + "runtime/pprof" +) + +func main() {} + +func Start() { + pprof.StartCPUProfile(io.Discard) +} diff --git a/src/cmd/link/internal/amd64/asm.go b/src/cmd/link/internal/amd64/asm.go index f86d22493227ac..9da0541f5263c2 100644 --- a/src/cmd/link/internal/amd64/asm.go +++ b/src/cmd/link/internal/amd64/asm.go @@ -398,6 +398,13 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade // (e.g. go version). return true } + case objabi.R_GOTPCREL: + if target.IsExternal() { + // External linker will do this relocation. + return true + } + // We only need to handle external linking mode, as R_GOTPCREL can + // only occur in plugin or shared build modes. } return false From e8ee1dc4f9e2632ba1018610d1a1187743ae397f Mon Sep 17 00:00:00 2001 From: Davis Goodin Date: Fri, 21 Jun 2024 16:44:44 -0700 Subject: [PATCH 25/41] cmd/link/internal/ld: handle "\r" in MinGW "--print-prog-name" output Fix the "gcc --print-prog-name" output parser to handle "\r\n", not only "\n". The MinGW compiler on Windows uses "\r\n" as line endings, causing the existing parser to create paths like ".../x86_64-w64-mingw32/bin/ar.exe\r", which is not correct. By trimming the "\r\n" cutset, both types of line endings are handled correctly. Fixes #68121 Change-Id: I04b8bf9b6a5b29a1e59a6aa07fa4faa4c5bdeee6 Reviewed-on: https://go-review.googlesource.com/c/go/+/593916 LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Reviewed-by: Cherry Mui Commit-Queue: Ian Lance Taylor --- src/cmd/link/internal/ld/lib.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 3bec04e0b8d41c..c29a532bfd2973 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -2917,6 +2917,6 @@ func (ctxt *Link) findExtLinkTool(toolname string) string { if err != nil { Exitf("%s: finding %s failed: %v\n%s", os.Args[0], toolname, err, out) } - cmdpath := strings.TrimSuffix(string(out), "\n") + cmdpath := strings.TrimRight(string(out), "\r\n") return cmdpath } From 740043f516f716fe359ffd3bd76f1a30a9aa5eec Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sun, 23 Jun 2024 15:21:28 -0700 Subject: [PATCH 26/41] net/netip: unexport fields of addrDetail For #68113 Change-Id: I19c7d8eff8e3a7a1b6c8e28cb867edeca6be237d Reviewed-on: https://go-review.googlesource.com/c/go/+/593737 Auto-Submit: Ian Lance Taylor Reviewed-by: Michael Knyszek Commit-Queue: Ian Lance Taylor Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor --- src/net/netip/export_test.go | 4 ++++ src/net/netip/netip.go | 10 +++++----- src/net/netip/netip_test.go | 8 ++++---- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/net/netip/export_test.go b/src/net/netip/export_test.go index 4febcad8936544..b2fae1aa47eedc 100644 --- a/src/net/netip/export_test.go +++ b/src/net/netip/export_test.go @@ -16,6 +16,10 @@ type Uint128 = uint128 type AddrDetail = addrDetail +func MakeAddrDetail(isV6 bool, zoneV6 string) AddrDetail { + return AddrDetail{isV6: isV6, zoneV6: zoneV6} +} + func Mk128(hi, lo uint64) Uint128 { return uint128{hi, lo} } diff --git a/src/net/netip/netip.go b/src/net/netip/netip.go index 57063eeb718a27..a1e93cb29bfbd9 100644 --- a/src/net/netip/netip.go +++ b/src/net/netip/netip.go @@ -59,8 +59,8 @@ type Addr struct { // addrDetail represents the details of an Addr, like address family and IPv6 zone. type addrDetail struct { - IsV6 bool // IPv4 is false, IPv6 is true. - ZoneV6 string // != "" only if IsV6 is true. + isV6 bool // IPv4 is false, IPv6 is true. + zoneV6 string // != "" only if IsV6 is true. } // z0, z4, and z6noz are sentinel Addr.z values. @@ -68,7 +68,7 @@ type addrDetail struct { var ( z0 unique.Handle[addrDetail] z4 = unique.Make(addrDetail{}) - z6noz = unique.Make(addrDetail{IsV6: true}) + z6noz = unique.Make(addrDetail{isV6: true}) ) // IPv6LinkLocalAllNodes returns the IPv6 link-local all nodes multicast @@ -410,7 +410,7 @@ func (ip Addr) Zone() string { if ip.z == z0 { return "" } - return ip.z.Value().ZoneV6 + return ip.z.Value().zoneV6 } // Compare returns an integer comparing two IPs. @@ -495,7 +495,7 @@ func (ip Addr) WithZone(zone string) Addr { ip.z = z6noz return ip } - ip.z = unique.Make(addrDetail{IsV6: true, ZoneV6: zone}) + ip.z = unique.Make(addrDetail{isV6: true, zoneV6: zone}) return ip } diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index ad0e7542082a23..94c70f2290ea4f 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -112,18 +112,18 @@ func TestParseAddr(t *testing.T) { // IPv6 with a zone specifier. { in: "fd7a:115c:a1e0:ab12:4843:cd96:626b:430b%eth0", - ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd96626b430b), unique.Make(AddrDetail{IsV6: true, ZoneV6: "eth0"})), + ip: MkAddr(Mk128(0xfd7a115ca1e0ab12, 0x4843cd96626b430b), unique.Make(MakeAddrDetail(true, "eth0"))), }, // IPv6 with dotted decimal and zone specifier. { in: "1:2::ffff:192.168.140.255%eth1", - ip: MkAddr(Mk128(0x0001000200000000, 0x0000ffffc0a88cff), unique.Make(AddrDetail{IsV6: true, ZoneV6: "eth1"})), + ip: MkAddr(Mk128(0x0001000200000000, 0x0000ffffc0a88cff), unique.Make(MakeAddrDetail(true, "eth1"))), str: "1:2::ffff:c0a8:8cff%eth1", }, // 4-in-6 with zone { in: "::ffff:192.168.140.255%eth1", - ip: MkAddr(Mk128(0, 0x0000ffffc0a88cff), unique.Make(AddrDetail{IsV6: true, ZoneV6: "eth1"})), + ip: MkAddr(Mk128(0, 0x0000ffffc0a88cff), unique.Make(MakeAddrDetail(true, "eth1"))), str: "::ffff:192.168.140.255%eth1", }, // IPv6 with capital letters. @@ -1723,7 +1723,7 @@ var parseBenchInputs = []struct { } func BenchmarkParseAddr(b *testing.B) { - sinkInternValue = unique.Make(AddrDetail{IsV6: true, ZoneV6: "eth1"}) // Pin to not benchmark the intern package + sinkInternValue = unique.Make(MakeAddrDetail(true, "eth1")) // Pin to not benchmark the intern package for _, test := range parseBenchInputs { b.Run(test.name, func(b *testing.B) { b.ReportAllocs() From 085cf0fcdc4faa2f473839f8cc1860ec5bcf97a3 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 24 Jun 2024 07:57:45 -0700 Subject: [PATCH 27/41] net/netip: add test that Compare and reflect.DeepEqual match Updates #68113 Change-Id: I1107686ef364f77f48f55534ea8ec68d1785e1e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/594375 Auto-Submit: Brad Fitzpatrick LUCI-TryBot-Result: Go LUCI Reviewed-by: Ian Lance Taylor Reviewed-by: Michael Knyszek --- src/net/netip/netip_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/net/netip/netip_test.go b/src/net/netip/netip_test.go index 94c70f2290ea4f..e1a0a83f64511d 100644 --- a/src/net/netip/netip_test.go +++ b/src/net/netip/netip_test.go @@ -893,6 +893,15 @@ func TestAddrLessCompare(t *testing.T) { {mustIP("::1%a"), mustIP("::1%b"), true}, {mustIP("::1%a"), mustIP("::1%a"), false}, {mustIP("::1%b"), mustIP("::1%a"), false}, + + // For Issue 68113, verify that an IPv4 address and a + // v4-mapped-IPv6 address differing only in their zone + // pointer are unequal via all three of + // ==/Compare/reflect.DeepEqual. In Go 1.22 and + // earlier, these were accidentally equal via + // DeepEqual due to their zone pointers (z) differing + // but pointing to identical structures. + {mustIP("::ffff:11.1.1.12"), mustIP("11.1.1.12"), false}, } for _, tt := range tests { got := tt.a.Less(tt.b) @@ -920,6 +929,12 @@ func TestAddrLessCompare(t *testing.T) { t.Errorf("Less(%q, %q) was correctly %v, but so was Less(%q, %q)", tt.a, tt.b, got, tt.b, tt.a) } } + + // Also check reflect.DeepEqual. See issue 68113. + deepEq := reflect.DeepEqual(tt.a, tt.b) + if (cmp == 0) != deepEq { + t.Errorf("%q and %q differ in == (%v) vs reflect.DeepEqual (%v)", tt.a, tt.b, cmp == 0, deepEq) + } } // And just sort. From 0def9d5c02166b50a011b4cc8d4c1d891a04f89d Mon Sep 17 00:00:00 2001 From: Sebastian Nickolls Date: Thu, 25 Apr 2024 17:19:20 +0100 Subject: [PATCH 28/41] cmd/internal/obj/arm64: Enable arm64 assembler tests for cross-compiler builds Some of the tests for the arm64 assembler are not running for cross-compiled arm64 builds with GOARCH=arm64. This patch allows the tests to run for all architectures and moves the test that can only run on arm64 into its own conditionally compiled file. Updates #44734 Change-Id: I045870d47cdc1280bfacc1ef275f34504278ed89 Reviewed-on: https://go-review.googlesource.com/c/go/+/587315 Reviewed-by: Cherry Mui LUCI-TryBot-Result: Go LUCI Reviewed-by: David Chase Reviewed-by: Sebastian Nickolls --- src/cmd/internal/obj/arm64/asm_arm64_test.go | 297 +------------------ src/cmd/internal/obj/arm64/asm_test.go | 258 ++++++++++++++++ 2 files changed, 259 insertions(+), 296 deletions(-) create mode 100644 src/cmd/internal/obj/arm64/asm_test.go diff --git a/src/cmd/internal/obj/arm64/asm_arm64_test.go b/src/cmd/internal/obj/arm64/asm_arm64_test.go index 068039496a23f6..83d137a08466bd 100644 --- a/src/cmd/internal/obj/arm64/asm_arm64_test.go +++ b/src/cmd/internal/obj/arm64/asm_arm64_test.go @@ -4,302 +4,7 @@ package arm64 -import ( - "bytes" - "fmt" - "internal/testenv" - "os" - "path/filepath" - "regexp" - "testing" -) - -func TestSplitImm24uScaled(t *testing.T) { - tests := []struct { - v int32 - shift int - wantErr bool - wantHi int32 - wantLo int32 - }{ - { - v: 0, - shift: 0, - wantHi: 0, - wantLo: 0, - }, - { - v: 0x1001, - shift: 0, - wantHi: 0x1000, - wantLo: 0x1, - }, - { - v: 0xffffff, - shift: 0, - wantHi: 0xfff000, - wantLo: 0xfff, - }, - { - v: 0xffffff, - shift: 1, - wantErr: true, - }, - { - v: 0xfe, - shift: 1, - wantHi: 0x0, - wantLo: 0x7f, - }, - { - v: 0x10fe, - shift: 1, - wantHi: 0x0, - wantLo: 0x87f, - }, - { - v: 0x2002, - shift: 1, - wantHi: 0x2000, - wantLo: 0x1, - }, - { - v: 0xfffffe, - shift: 1, - wantHi: 0xffe000, - wantLo: 0xfff, - }, - { - v: 0x1000ffe, - shift: 1, - wantHi: 0xfff000, - wantLo: 0xfff, - }, - { - v: 0x1001000, - shift: 1, - wantErr: true, - }, - { - v: 0xfffffe, - shift: 2, - wantErr: true, - }, - { - v: 0x4004, - shift: 2, - wantHi: 0x4000, - wantLo: 0x1, - }, - { - v: 0xfffffc, - shift: 2, - wantHi: 0xffc000, - wantLo: 0xfff, - }, - { - v: 0x1002ffc, - shift: 2, - wantHi: 0xfff000, - wantLo: 0xfff, - }, - { - v: 0x1003000, - shift: 2, - wantErr: true, - }, - { - v: 0xfffffe, - shift: 3, - wantErr: true, - }, - { - v: 0x8008, - shift: 3, - wantHi: 0x8000, - wantLo: 0x1, - }, - { - v: 0xfffff8, - shift: 3, - wantHi: 0xff8000, - wantLo: 0xfff, - }, - { - v: 0x1006ff8, - shift: 3, - wantHi: 0xfff000, - wantLo: 0xfff, - }, - { - v: 0x1007000, - shift: 3, - wantErr: true, - }, - } - for _, test := range tests { - hi, lo, err := splitImm24uScaled(test.v, test.shift) - switch { - case err == nil && test.wantErr: - t.Errorf("splitImm24uScaled(%v, %v) succeeded, want error", test.v, test.shift) - case err != nil && !test.wantErr: - t.Errorf("splitImm24uScaled(%v, %v) failed: %v", test.v, test.shift, err) - case !test.wantErr: - if got, want := hi, test.wantHi; got != want { - t.Errorf("splitImm24uScaled(%x, %x) - got hi %x, want %x", test.v, test.shift, got, want) - } - if got, want := lo, test.wantLo; got != want { - t.Errorf("splitImm24uScaled(%x, %x) - got lo %x, want %x", test.v, test.shift, got, want) - } - } - } - for shift := 0; shift <= 3; shift++ { - for v := int32(0); v < 0xfff000+0xfff< Date: Fri, 21 Jun 2024 16:59:21 -0700 Subject: [PATCH 29/41] os: TestChtimes: separate hasNoatime Move the noatime check to a separate function (to be used by CL 91535), adding some documentation along the way. Unify the atime error message. Change-Id: I5f75a4399f6e1b16ae20438003de5460f3eeb5aa Reviewed-on: https://go-review.googlesource.com/c/go/+/594075 Reviewed-by: Ian Lance Taylor Reviewed-by: Joedian Reid LUCI-TryBot-Result: Go LUCI Auto-Submit: Ian Lance Taylor --- src/os/os_test.go | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/os/os_test.go b/src/os/os_test.go index 2a6b1bf9f5e104..b3fbe42ba788b8 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -1361,6 +1361,17 @@ func TestTruncateNonexistentFile(t *testing.T) { assertPathError(t, path, err) } +var hasNoatime = sync.OnceValue(func() bool { + // A sloppy way to check if noatime flag is set (as all filesystems are + // checked, not just the one we're interested in). A correct way + // would be to use statvfs syscall and check if flags has ST_NOATIME, + // but the syscall is OS-specific and is not even wired into Go stdlib. + // + // Only used on NetBSD (which ignores explicit atime updates with noatime). + mounts, _ := ReadFile("/proc/mounts") + return bytes.Contains(mounts, []byte("noatime")) +}) + func TestChtimes(t *testing.T) { t.Parallel() @@ -1523,6 +1534,7 @@ func testChtimes(t *testing.T, name string) { pat := Atime(postStat) pmt := postStat.ModTime() if !pat.Before(at) { + errormsg := fmt.Sprintf("AccessTime didn't go backwards; was=%v, after=%v", at, pat) switch runtime.GOOS { case "plan9": // Mtime is the time of the last change of @@ -1530,14 +1542,14 @@ func testChtimes(t *testing.T, name string) { // the contents are accessed; also, it is set // whenever mtime is set. case "netbsd": - mounts, _ := ReadFile("/proc/mounts") - if strings.Contains(string(mounts), "noatime") { - t.Logf("AccessTime didn't go backwards, but see a filesystem mounted noatime; ignoring. Issue 19293.") + if hasNoatime() { + t.Log(errormsg) + t.Log("Known NetBSD issue (atime not changed on fs mounted with noatime); ignoring.") } else { - t.Logf("AccessTime didn't go backwards; was=%v, after=%v (Ignoring on NetBSD, assuming noatime, Issue 19293)", at, pat) + t.Errorf(errormsg) } default: - t.Errorf("AccessTime didn't go backwards; was=%v, after=%v", at, pat) + t.Errorf(errormsg) } } From cf54a3d11469e3e9bd531ee2cdeaf613467923f1 Mon Sep 17 00:00:00 2001 From: Filippo Valsorda Date: Sun, 23 Jun 2024 14:10:14 +0200 Subject: [PATCH 30/41] crypto/tls: replay test recordings without network There is no reason to go across a pipe when replaying a conn recording. This avoids the complexity of using localPipe and goroutines, and makes handshake benchmarks more accurate, as we don't measure network overhead. Also note how it removes the need for -fast: operating locally we know when the flow is over and can error out immediately, without waiting for a read from the feeder on the other side of the pipe to timeout. Avoids some noise in #67979, but doesn't fix the two root causes: localPipe flakes and testing.B races. Updates #67979 Change-Id: I153d3fa5a24847f3947823e8c3a7bc639f89bc1d Reviewed-on: https://go-review.googlesource.com/c/go/+/594255 Auto-Submit: Filippo Valsorda LUCI-TryBot-Result: Go LUCI Reviewed-by: Roland Shoemaker Reviewed-by: Joedian Reid --- src/crypto/tls/handshake_client_test.go | 232 ++++++++++-------------- src/crypto/tls/handshake_server_test.go | 95 +++------- src/crypto/tls/handshake_test.go | 72 +++++++- 3 files changed, 188 insertions(+), 211 deletions(-) diff --git a/src/crypto/tls/handshake_client_test.go b/src/crypto/tls/handshake_client_test.go index 4570f5b05edfdd..501f9c6755f9e3 100644 --- a/src/crypto/tls/handshake_client_test.go +++ b/src/crypto/tls/handshake_client_test.go @@ -283,7 +283,7 @@ func (test *clientTest) loadData() (flows [][]byte, err error) { } func (test *clientTest) run(t *testing.T, write bool) { - var clientConn, serverConn net.Conn + var clientConn net.Conn var recordingConn *recordingConn var childProcess *exec.Cmd var stdin opensslInput @@ -302,178 +302,138 @@ func (test *clientTest) run(t *testing.T, write bool) { } }() } else { - clientConn, serverConn = localPipe(t) + flows, err := test.loadData() + if err != nil { + t.Fatalf("failed to load data from %s: %v", test.dataPath(), err) + } + clientConn = &replayingConn{t: t, flows: flows, reading: false} } - doneChan := make(chan bool) - defer func() { - clientConn.Close() - <-doneChan - }() - go func() { - defer close(doneChan) + config := test.config + if config == nil { + config = testConfig + } + client := Client(clientConn, config) + defer client.Close() - config := test.config - if config == nil { - config = testConfig - } - client := Client(clientConn, config) - defer client.Close() + if _, err := client.Write([]byte("hello\n")); err != nil { + t.Errorf("Client.Write failed: %s", err) + return + } - if _, err := client.Write([]byte("hello\n")); err != nil { - t.Errorf("Client.Write failed: %s", err) - return + for i := 1; i <= test.numRenegotiations; i++ { + // The initial handshake will generate a + // handshakeComplete signal which needs to be quashed. + if i == 1 && write { + <-stdout.handshakeComplete } - for i := 1; i <= test.numRenegotiations; i++ { - // The initial handshake will generate a - // handshakeComplete signal which needs to be quashed. - if i == 1 && write { - <-stdout.handshakeComplete - } - - // OpenSSL will try to interleave application data and - // a renegotiation if we send both concurrently. - // Therefore: ask OpensSSL to start a renegotiation, run - // a goroutine to call client.Read and thus process the - // renegotiation request, watch for OpenSSL's stdout to - // indicate that the handshake is complete and, - // finally, have OpenSSL write something to cause - // client.Read to complete. - if write { - stdin <- opensslRenegotiate - } - - signalChan := make(chan struct{}) + // OpenSSL will try to interleave application data and + // a renegotiation if we send both concurrently. + // Therefore: ask OpensSSL to start a renegotiation, run + // a goroutine to call client.Read and thus process the + // renegotiation request, watch for OpenSSL's stdout to + // indicate that the handshake is complete and, + // finally, have OpenSSL write something to cause + // client.Read to complete. + if write { + stdin <- opensslRenegotiate + } - go func() { - defer close(signalChan) + signalChan := make(chan struct{}) - buf := make([]byte, 256) - n, err := client.Read(buf) + go func() { + defer close(signalChan) - if test.checkRenegotiationError != nil { - newErr := test.checkRenegotiationError(i, err) - if err != nil && newErr == nil { - return - } - err = newErr - } + buf := make([]byte, 256) + n, err := client.Read(buf) - if err != nil { - t.Errorf("Client.Read failed after renegotiation #%d: %s", i, err) + if test.checkRenegotiationError != nil { + newErr := test.checkRenegotiationError(i, err) + if err != nil && newErr == nil { return } + err = newErr + } - buf = buf[:n] - if !bytes.Equal([]byte(opensslSentinel), buf) { - t.Errorf("Client.Read returned %q, but wanted %q", string(buf), opensslSentinel) - } - - if expected := i + 1; client.handshakes != expected { - t.Errorf("client should have recorded %d handshakes, but believes that %d have occurred", expected, client.handshakes) - } - }() - - if write && test.renegotiationExpectedToFail != i { - <-stdout.handshakeComplete - stdin <- opensslSendSentinel + if err != nil { + t.Errorf("Client.Read failed after renegotiation #%d: %s", i, err) + return } - <-signalChan - } - if test.sendKeyUpdate { - if write { - <-stdout.handshakeComplete - stdin <- opensslKeyUpdate + buf = buf[:n] + if !bytes.Equal([]byte(opensslSentinel), buf) { + t.Errorf("Client.Read returned %q, but wanted %q", string(buf), opensslSentinel) } - doneRead := make(chan struct{}) + if expected := i + 1; client.handshakes != expected { + t.Errorf("client should have recorded %d handshakes, but believes that %d have occurred", expected, client.handshakes) + } + }() - go func() { - defer close(doneRead) + if write && test.renegotiationExpectedToFail != i { + <-stdout.handshakeComplete + stdin <- opensslSendSentinel + } + <-signalChan + } - buf := make([]byte, 256) - n, err := client.Read(buf) + if test.sendKeyUpdate { + if write { + <-stdout.handshakeComplete + stdin <- opensslKeyUpdate + } - if err != nil { - t.Errorf("Client.Read failed after KeyUpdate: %s", err) - return - } + doneRead := make(chan struct{}) - buf = buf[:n] - if !bytes.Equal([]byte(opensslSentinel), buf) { - t.Errorf("Client.Read returned %q, but wanted %q", string(buf), opensslSentinel) - } - }() + go func() { + defer close(doneRead) - if write { - // There's no real reason to wait for the client KeyUpdate to - // send data with the new server keys, except that s_server - // drops writes if they are sent at the wrong time. - <-stdout.readKeyUpdate - stdin <- opensslSendSentinel - } - <-doneRead + buf := make([]byte, 256) + n, err := client.Read(buf) - if _, err := client.Write([]byte("hello again\n")); err != nil { - t.Errorf("Client.Write failed: %s", err) + if err != nil { + t.Errorf("Client.Read failed after KeyUpdate: %s", err) return } - } - if test.validate != nil { - if err := test.validate(client.ConnectionState()); err != nil { - t.Errorf("validate callback returned error: %s", err) + buf = buf[:n] + if !bytes.Equal([]byte(opensslSentinel), buf) { + t.Errorf("Client.Read returned %q, but wanted %q", string(buf), opensslSentinel) } - } + }() - // If the server sent us an alert after our last flight, give it a - // chance to arrive. - if write && test.renegotiationExpectedToFail == 0 { - if err := peekError(client); err != nil { - t.Errorf("final Read returned an error: %s", err) - } + if write { + // There's no real reason to wait for the client KeyUpdate to + // send data with the new server keys, except that s_server + // drops writes if they are sent at the wrong time. + <-stdout.readKeyUpdate + stdin <- opensslSendSentinel } - }() + <-doneRead - if !write { - flows, err := test.loadData() - if err != nil { - t.Fatalf("%s: failed to load data from %s: %v", test.name, test.dataPath(), err) + if _, err := client.Write([]byte("hello again\n")); err != nil { + t.Errorf("Client.Write failed: %s", err) + return } - for i, b := range flows { - if i%2 == 1 { - if *fast { - serverConn.SetWriteDeadline(time.Now().Add(1 * time.Second)) - } else { - serverConn.SetWriteDeadline(time.Now().Add(1 * time.Minute)) - } - serverConn.Write(b) - continue - } - bb := make([]byte, len(b)) - if *fast { - serverConn.SetReadDeadline(time.Now().Add(1 * time.Second)) - } else { - serverConn.SetReadDeadline(time.Now().Add(1 * time.Minute)) - } - _, err := io.ReadFull(serverConn, bb) - if err != nil { - t.Fatalf("%s, flow %d: %s", test.name, i+1, err) - } - if !bytes.Equal(b, bb) { - t.Fatalf("%s, flow %d: mismatch on read: got:%x want:%x", test.name, i+1, bb, b) - } + } + + if test.validate != nil { + if err := test.validate(client.ConnectionState()); err != nil { + t.Errorf("validate callback returned error: %s", err) } } - <-doneChan - if !write { - serverConn.Close() + // If the server sent us an alert after our last flight, give it a + // chance to arrive. + if write && test.renegotiationExpectedToFail == 0 { + if err := peekError(client); err != nil { + t.Errorf("final Read returned an error: %s", err) + } } if write { + clientConn.Close() path := test.dataPath() out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { diff --git a/src/crypto/tls/handshake_server_test.go b/src/crypto/tls/handshake_server_test.go index 44bc8f1bb7442a..94d3d0f6dc87bc 100644 --- a/src/crypto/tls/handshake_server_test.go +++ b/src/crypto/tls/handshake_server_test.go @@ -21,6 +21,7 @@ import ( "os/exec" "path/filepath" "runtime" + "slices" "strings" "testing" "time" @@ -659,7 +660,7 @@ func (test *serverTest) loadData() (flows [][]byte, err error) { } func (test *serverTest) run(t *testing.T, write bool) { - var clientConn, serverConn net.Conn + var serverConn net.Conn var recordingConn *recordingConn var childProcess *exec.Cmd @@ -676,65 +677,33 @@ func (test *serverTest) run(t *testing.T, write bool) { } }() } else { - clientConn, serverConn = localPipe(t) + flows, err := test.loadData() + if err != nil { + t.Fatalf("Failed to load data from %s", test.dataPath()) + } + serverConn = &replayingConn{t: t, flows: flows, reading: true} } config := test.config if config == nil { config = testConfig } server := Server(serverConn, config) - connStateChan := make(chan ConnectionState, 1) - go func() { - _, err := server.Write([]byte("hello, world\n")) - if len(test.expectHandshakeErrorIncluding) > 0 { - if err == nil { - t.Errorf("Error expected, but no error returned") - } else if s := err.Error(); !strings.Contains(s, test.expectHandshakeErrorIncluding) { - t.Errorf("Error expected containing '%s' but got '%s'", test.expectHandshakeErrorIncluding, s) - } - } else { - if err != nil { - t.Logf("Error from Server.Write: '%s'", err) - } - } - server.Close() - serverConn.Close() - connStateChan <- server.ConnectionState() - }() - if !write { - flows, err := test.loadData() - if err != nil { - t.Fatalf("%s: failed to load data from %s", test.name, test.dataPath()) + _, err := server.Write([]byte("hello, world\n")) + if len(test.expectHandshakeErrorIncluding) > 0 { + if err == nil { + t.Errorf("Error expected, but no error returned") + } else if s := err.Error(); !strings.Contains(s, test.expectHandshakeErrorIncluding) { + t.Errorf("Error expected containing '%s' but got '%s'", test.expectHandshakeErrorIncluding, s) } - for i, b := range flows { - if i%2 == 0 { - if *fast { - clientConn.SetWriteDeadline(time.Now().Add(1 * time.Second)) - } else { - clientConn.SetWriteDeadline(time.Now().Add(1 * time.Minute)) - } - clientConn.Write(b) - continue - } - bb := make([]byte, len(b)) - if *fast { - clientConn.SetReadDeadline(time.Now().Add(1 * time.Second)) - } else { - clientConn.SetReadDeadline(time.Now().Add(1 * time.Minute)) - } - n, err := io.ReadFull(clientConn, bb) - if err != nil { - t.Fatalf("%s #%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", test.name, i+1, err, n, len(bb), bb[:n], b) - } - if !bytes.Equal(b, bb) { - t.Fatalf("%s #%d: mismatch on read: got:%x want:%x", test.name, i+1, bb, b) - } + } else { + if err != nil { + t.Logf("Error from Server.Write: '%s'", err) } - clientConn.Close() } + server.Close() - connState := <-connStateChan + connState := server.ConnectionState() peerCerts := connState.PeerCertificates if len(peerCerts) == len(test.expectedPeerCerts) { for i, peerCert := range peerCerts { @@ -754,6 +723,7 @@ func (test *serverTest) run(t *testing.T, write bool) { } if write { + serverConn.Close() path := test.dataPath() out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { @@ -1330,37 +1300,14 @@ func benchmarkHandshakeServer(b *testing.B, version uint16, cipherSuite uint16, serverConn.Close() flows := serverConn.(*recordingConn).flows - feeder := make(chan struct{}) - clientConn, serverConn = localPipe(b) - - go func() { - for range feeder { - for i, f := range flows { - if i%2 == 0 { - clientConn.Write(f) - continue - } - ff := make([]byte, len(f)) - n, err := io.ReadFull(clientConn, ff) - if err != nil { - b.Errorf("#%d: %s\nRead %d, wanted %d, got %x, wanted %x\n", i+1, err, n, len(ff), ff[:n], f) - } - if !bytes.Equal(f, ff) { - b.Errorf("#%d: mismatch on read: got:%x want:%x", i+1, ff, f) - } - } - } - }() - b.ResetTimer() for i := 0; i < b.N; i++ { - feeder <- struct{}{} - server := Server(serverConn, config) + replay := &replayingConn{t: b, flows: slices.Clone(flows), reading: true} + server := Server(replay, config) if err := server.Handshake(); err != nil { b.Fatalf("handshake failed: %v", err) } } - close(feeder) } func BenchmarkHandshakeServer(b *testing.B) { diff --git a/src/crypto/tls/handshake_test.go b/src/crypto/tls/handshake_test.go index 57fc761dbb8108..bc3d23d5adc24e 100644 --- a/src/crypto/tls/handshake_test.go +++ b/src/crypto/tls/handshake_test.go @@ -6,6 +6,7 @@ package tls import ( "bufio" + "bytes" "crypto/ed25519" "crypto/x509" "encoding/hex" @@ -42,7 +43,6 @@ import ( var ( update = flag.Bool("update", false, "update golden files on failure") - fast = flag.Bool("fast", false, "impose a quick, possibly flaky timeout on recorded tests") keyFile = flag.String("keylog", "", "destination file for KeyLogWriter") bogoMode = flag.Bool("bogo-mode", false, "Enabled bogo shim mode, ignore everything else") bogoFilter = flag.String("bogo-filter", "", "BoGo test filter") @@ -223,6 +223,76 @@ func parseTestData(r io.Reader) (flows [][]byte, err error) { return flows, nil } +// replayingConn is a net.Conn that replays flows recorded by recordingConn. +type replayingConn struct { + t testing.TB + sync.Mutex + flows [][]byte + reading bool +} + +var _ net.Conn = (*replayingConn)(nil) + +func (r *replayingConn) Read(b []byte) (n int, err error) { + r.Lock() + defer r.Unlock() + + if !r.reading { + r.t.Errorf("expected write, got read") + return 0, fmt.Errorf("recording expected write, got read") + } + + n = copy(b, r.flows[0]) + r.flows[0] = r.flows[0][n:] + if len(r.flows[0]) == 0 { + r.flows = r.flows[1:] + if len(r.flows) == 0 { + return n, io.EOF + } else { + r.reading = false + } + } + return n, nil +} + +func (r *replayingConn) Write(b []byte) (n int, err error) { + r.Lock() + defer r.Unlock() + + if r.reading { + r.t.Errorf("expected read, got write") + return 0, fmt.Errorf("recording expected read, got write") + } + + if !bytes.HasPrefix(r.flows[0], b) { + r.t.Errorf("write mismatch: expected %x, got %x", r.flows[0], b) + return 0, fmt.Errorf("write mismatch") + } + r.flows[0] = r.flows[0][len(b):] + if len(r.flows[0]) == 0 { + r.flows = r.flows[1:] + r.reading = true + } + return len(b), nil +} + +func (r *replayingConn) Close() error { + r.Lock() + defer r.Unlock() + + if len(r.flows) > 0 { + r.t.Errorf("closed with unfinished flows") + return fmt.Errorf("unexpected close") + } + return nil +} + +func (r *replayingConn) LocalAddr() net.Addr { return nil } +func (r *replayingConn) RemoteAddr() net.Addr { return nil } +func (r *replayingConn) SetDeadline(t time.Time) error { return nil } +func (r *replayingConn) SetReadDeadline(t time.Time) error { return nil } +func (r *replayingConn) SetWriteDeadline(t time.Time) error { return nil } + // tempFile creates a temp file containing contents and returns its path. func tempFile(contents string) string { file, err := os.CreateTemp("", "go-tls-test") From 29b1a6765fb5f124171d94f157b6d6c3b2687468 Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 17 Jun 2024 14:54:22 -0700 Subject: [PATCH 31/41] net/http: document that Request.Clone does not deep copy Body Fixes #36095 Change-Id: I94ae014b0ee45b4aeb38cb247e42cfc13f663ded Reviewed-on: https://go-review.googlesource.com/c/go/+/593175 LUCI-TryBot-Result: Go LUCI Reviewed-by: Jonathan Amsterdam --- src/net/http/request.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/net/http/request.go b/src/net/http/request.go index 456615a79ad59b..ad1b5a620b07ae 100644 --- a/src/net/http/request.go +++ b/src/net/http/request.go @@ -377,6 +377,8 @@ func (r *Request) WithContext(ctx context.Context) *Request { // Clone returns a deep copy of r with its context changed to ctx. // The provided ctx must be non-nil. // +// Clone only makes a shallow copy of the Body field. +// // For an outgoing client request, the context controls the entire // lifetime of a request and its response: obtaining a connection, // sending the request, and reading the response headers and body. From f214a760754ac0584999fb8098ce6172181ed791 Mon Sep 17 00:00:00 2001 From: "Hana (Hyang-Ah) Kim" Date: Mon, 24 Jun 2024 11:45:12 -0400 Subject: [PATCH 32/41] cmd/vendor: vendor x/telemetry@38a4430 For #68109 Change-Id: I73a3d23dd6c15ff4954ebe7a52c6c308fea947ae Reviewed-on: https://go-review.googlesource.com/c/go/+/593684 Reviewed-by: Michael Matloob LUCI-TryBot-Result: Go LUCI Auto-Submit: Hyang-Ah Hana Kim --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 2 ++ .../x/telemetry/internal/telemetry/proginfo.go | 11 +++++++---- src/cmd/vendor/modules.txt | 2 +- 4 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 0a17a414b5fa9f..3058165dbf312c 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -9,7 +9,7 @@ require ( golang.org/x/mod v0.18.0 golang.org/x/sync v0.7.0 golang.org/x/sys v0.21.0 - golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c + golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05 golang.org/x/term v0.20.0 golang.org/x/tools v0.22.1-0.20240618181713-f2d2ebe43e72 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 49849d10b4e171..4449bb0b2c05db 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -18,6 +18,8 @@ golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c h1:zNxtD9mZQCgRwCNanVRlJ/XlOyATHcbR+09LzoArRl4= golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= +golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05 h1:fzUVo05u80jHc31RGqQsPYEAGMXS8tyK5azYUK2sSms= +golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= diff --git a/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go b/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go index 20be9664fc8cd1..60cb0edc792a59 100644 --- a/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go +++ b/src/cmd/vendor/golang.org/x/telemetry/internal/telemetry/proginfo.go @@ -9,8 +9,6 @@ import ( "path/filepath" "runtime/debug" "strings" - - "golang.org/x/mod/module" ) // IsToolchainProgram reports whether a program with the given path is a Go @@ -43,8 +41,13 @@ func ProgramInfo(info *debug.BuildInfo) (goVers, progPath, progVers string) { progVers = goVers } else { progVers = info.Main.Version - if strings.Contains(progVers, "devel") || module.IsPseudoVersion(progVers) { - // We don't want to track pseudo versions, but may want to track prereleases. + if strings.Contains(progVers, "devel") || strings.Count(progVers, "-") > 1 { + // Heuristically mark all pseudo-version-like version strings as "devel" + // to avoid creating too many counter files. + // We should not use regexp that pulls in large dependencies. + // Pseudo-versions have at least three parts (https://go.dev/ref/mod#pseudo-versions). + // This heuristic still allows use to track prerelease + // versions (e.g. gopls@v0.16.0-pre.1, vscgo@v0.42.0-rc.1). progVers = "devel" } } diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 5184adb1f2a1af..f4eefe4a1d5615 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -45,7 +45,7 @@ golang.org/x/sync/semaphore golang.org/x/sys/plan9 golang.org/x/sys/unix golang.org/x/sys/windows -# golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c +# golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05 ## explicit; go 1.20 golang.org/x/telemetry golang.org/x/telemetry/counter From 68315bc8ce8c7fd1a9e47e73b2d18ef21f8c6d9a Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Mon, 24 Jun 2024 16:39:21 -0400 Subject: [PATCH 33/41] cmd: run go mod tidy after CL 593684 Reported by TestAllDependencies/cmd(thorough) in cmd/internal/moddeps. Change-Id: I897baf00efbfebd07abe387f54c7ce4fc14444e6 Cq-Include-Trybots: luci.golang.try:gotip-linux-amd64-longtest Reviewed-on: https://go-review.googlesource.com/c/go/+/594536 Auto-Submit: Dmitri Shuralyov Reviewed-by: Hyang-Ah Hana Kim Reviewed-by: Dmitri Shuralyov LUCI-TryBot-Result: Go LUCI --- src/cmd/go.sum | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index 4449bb0b2c05db..081ced64dc99b9 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -16,8 +16,6 @@ golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws= golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c h1:zNxtD9mZQCgRwCNanVRlJ/XlOyATHcbR+09LzoArRl4= -golang.org/x/telemetry v0.0.0-20240621194115-a740542b267c/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05 h1:fzUVo05u80jHc31RGqQsPYEAGMXS8tyK5azYUK2sSms= golang.org/x/telemetry v0.0.0-20240624145040-38a44306ed05/go.mod h1:n38mvGdgc4dA684EC4NwQwoPKSw4jyKw8/DgZHDA1Dk= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= From b3b4556c245c8f21872910ee866133428bbb5a60 Mon Sep 17 00:00:00 2001 From: func25 Date: Sun, 23 Jun 2024 05:53:47 +0000 Subject: [PATCH 34/41] cmd/compile: update README to reflect dead code elimination changes The description of middle-end dead code elimination is inconsistent with the current implementation. The early dead code elimination pass of IR nodes is no longer located in cmd/compile/internal/deadcode and is no longer called by gc/main.go:Main. It has been moved to the unified IR writer phase. This update modifies the README to reflect this architectural change. Change-Id: I78bd486edefd6b02948fee7de9ce6c83b147bc1d GitHub-Last-Rev: 76493ce8b08cd585d761d65d29b984360f7ee628 GitHub-Pull-Request: golang/go#68134 Reviewed-on: https://go-review.googlesource.com/c/go/+/593638 Reviewed-by: Robert Griesemer Reviewed-by: Keith Randall Reviewed-by: Keith Randall LUCI-TryBot-Result: Go LUCI Auto-Submit: Keith Randall --- src/cmd/compile/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/cmd/compile/README.md b/src/cmd/compile/README.md index 3fc7ca6ec6699b..cffb4e7a80fa93 100644 --- a/src/cmd/compile/README.md +++ b/src/cmd/compile/README.md @@ -63,7 +63,6 @@ Unified IR is also involved in import/export of packages and inlining. ### 4. Middle end -* `cmd/compile/internal/deadcode` (dead code elimination) * `cmd/compile/internal/inline` (function call inlining) * `cmd/compile/internal/devirtualize` (devirtualization of known interface method calls) * `cmd/compile/internal/escape` (escape analysis) @@ -72,6 +71,8 @@ Several optimization passes are performed on the IR representation: dead code elimination, (early) devirtualization, function call inlining, and escape analysis. +The early dead code elimination pass is integrated into the unified IR writer phase. + ### 5. Walk * `cmd/compile/internal/walk` (order of evaluation, desugaring) From b1fd047508aad9f5038dc04d78146cc582328bf5 Mon Sep 17 00:00:00 2001 From: Joel Sing Date: Sat, 15 Jun 2024 01:28:46 +1000 Subject: [PATCH 35/41] cmd/internal/obj/arm64: fix return with register ARM64 allows for a register to be specified with a return instruction. While the assembler parsing and encoding currently supports this, the preprocess function uses LR unconditionally. Correct this such that if a register is specified, the register is used. Change-Id: I708f6c7e910d141559b60d2d5ee76ae2e1dc3a0e Reviewed-on: https://go-review.googlesource.com/c/go/+/592796 Reviewed-by: Cherry Mui Reviewed-by: David Chase LUCI-TryBot-Result: Go LUCI --- src/cmd/asm/internal/asm/testdata/arm64.s | 6 +++++- src/cmd/internal/obj/arm64/obj7.go | 12 +++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/cmd/asm/internal/asm/testdata/arm64.s b/src/cmd/asm/internal/asm/testdata/arm64.s index ecad08b37aa021..f12cdaf921fc44 100644 --- a/src/cmd/asm/internal/asm/testdata/arm64.s +++ b/src/cmd/asm/internal/asm/testdata/arm64.s @@ -961,7 +961,11 @@ again: CASPD (R2, R3), (R2), (R8, R9) // 487c2248 // RET - RET + RET // c0035fd6 + RET R0 // 00005fd6 + RET R6 // c0005fd6 + RET R27 // 60035fd6 + RET R30 // c0035fd6 RET foo(SB) // B/BL/B.cond cases, and canonical names JMP, CALL. diff --git a/src/cmd/internal/obj/arm64/obj7.go b/src/cmd/internal/obj/arm64/obj7.go index 0ab5939b842910..20498bc2c67da7 100644 --- a/src/cmd/internal/obj/arm64/obj7.go +++ b/src/cmd/internal/obj/arm64/obj7.go @@ -552,7 +552,6 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { var q *obj.Prog var q1 *obj.Prog - var retjmp *obj.LSym for p := c.cursym.Func().Text; p != nil; p = p.Link { o := p.As switch o { @@ -846,7 +845,10 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { break } - retjmp = p.To.Sym + retJMP, retReg := p.To.Sym, p.To.Reg + if retReg == 0 { + retReg = REGLINK + } p.To = obj.Addr{} if c.cursym.Func().Text.Mark&LEAF != 0 { if c.autosize != 0 { @@ -924,10 +926,10 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { p = q } - if retjmp != nil { // retjmp + if retJMP != nil { p.As = AB p.To.Type = obj.TYPE_BRANCH - p.To.Sym = retjmp + p.To.Sym = retJMP p.Spadj = +c.autosize break } @@ -935,7 +937,7 @@ func preprocess(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) { p.As = obj.ARET p.To.Type = obj.TYPE_MEM p.To.Offset = 0 - p.To.Reg = REGLINK + p.To.Reg = retReg p.Spadj = +c.autosize case AADD, ASUB: From 90bcc552c0347948166817a602f612f219bc980c Mon Sep 17 00:00:00 2001 From: Damien Neil Date: Mon, 24 Jun 2024 10:01:47 -0700 Subject: [PATCH 36/41] crypto/tls: apply QUIC session event flag to QUICResumeSession events Go 1.23 adds two new events to QUICConns: QUICStoreSessionEvent and QUICResumeSessionEvent. We added a QUICConfig.EnableStoreSessionEvent flag to control whether the store-session event is provided or not, because receiving this event requires additional action from the caller: the session must be explicitly stored with QUICConn.StoreSession. We did not add a control for whether the resume-session event is provided, because this event requires no action and the caller is expected to ignore unknown events. However, we never documented the expectation that callers ignore unknown events, and quic-go produces an error when receiving an unexpected event. So change the EnableStoreSessionEvent flag to apply to both new events. Fixes #68124 For #63691 Change-Id: I84af487e52b3815f7b648e09884608f8915cd645 Reviewed-on: https://go-review.googlesource.com/c/go/+/594475 Reviewed-by: Marten Seemann LUCI-TryBot-Result: Go LUCI Reviewed-by: Roland Shoemaker --- api/go1.23.txt | 2 +- src/crypto/tls/handshake_client.go | 4 +- src/crypto/tls/handshake_client_tls13.go | 2 +- src/crypto/tls/handshake_server_tls13.go | 2 +- src/crypto/tls/quic.go | 16 +-- src/crypto/tls/quic_test.go | 158 ++++++++++++----------- 6 files changed, 100 insertions(+), 84 deletions(-) diff --git a/api/go1.23.txt b/api/go1.23.txt index dc92d3fe56b137..9363bd41f3ce46 100644 --- a/api/go1.23.txt +++ b/api/go1.23.txt @@ -18,7 +18,7 @@ pkg crypto/tls, type Config struct, EncryptedClientHelloRejectionVerify func(Con pkg crypto/tls, type ConnectionState struct, ECHAccepted bool #63369 pkg crypto/tls, type ECHRejectionError struct #63369 pkg crypto/tls, type ECHRejectionError struct, RetryConfigList []uint8 #63369 -pkg crypto/tls, type QUICConfig struct, EnableStoreSessionEvent bool #63691 +pkg crypto/tls, type QUICConfig struct, EnableSessionEvents bool #63691 pkg crypto/tls, type QUICEvent struct, SessionState *SessionState #63691 pkg crypto/tls, type QUICSessionTicketOptions struct, Extra [][]uint8 #63691 pkg crypto/x509, func ParseOID(string) (OID, error) #66249 diff --git a/src/crypto/tls/handshake_client.go b/src/crypto/tls/handshake_client.go index 553d2dde01de2d..5025657590d32c 100644 --- a/src/crypto/tls/handshake_client.go +++ b/src/crypto/tls/handshake_client.go @@ -478,7 +478,9 @@ func (c *Conn) loadSession(hello *clientHelloMsg) ( } if c.quic != nil { - c.quicResumeSession(session) + if c.quic.enableSessionEvents { + c.quicResumeSession(session) + } // For 0-RTT, the cipher suite has to match exactly, and we need to be // offering the same ALPN. diff --git a/src/crypto/tls/handshake_client_tls13.go b/src/crypto/tls/handshake_client_tls13.go index 6744e713c9ffa8..db5e35d9a46c2e 100644 --- a/src/crypto/tls/handshake_client_tls13.go +++ b/src/crypto/tls/handshake_client_tls13.go @@ -900,7 +900,7 @@ func (c *Conn) handleNewSessionTicket(msg *newSessionTicketMsgTLS13) error { session.ageAdd = msg.ageAdd session.EarlyData = c.quic != nil && msg.maxEarlyData == 0xffffffff // RFC 9001, Section 4.6.1 session.ticket = msg.label - if c.quic != nil && c.quic.enableStoreSessionEvent { + if c.quic != nil && c.quic.enableSessionEvents { c.quicStoreSession(session) return nil } diff --git a/src/crypto/tls/handshake_server_tls13.go b/src/crypto/tls/handshake_server_tls13.go index f24c2671acd435..503a732e05765e 100644 --- a/src/crypto/tls/handshake_server_tls13.go +++ b/src/crypto/tls/handshake_server_tls13.go @@ -377,7 +377,7 @@ func (hs *serverHandshakeStateTLS13) checkForResumption() error { continue } - if c.quic != nil { + if c.quic != nil && c.quic.enableSessionEvents { if err := c.quicResumeSession(sessionState); err != nil { return err } diff --git a/src/crypto/tls/quic.go b/src/crypto/tls/quic.go index 8e722c6a590578..9dd6168b62356e 100644 --- a/src/crypto/tls/quic.go +++ b/src/crypto/tls/quic.go @@ -50,12 +50,12 @@ type QUICConn struct { type QUICConfig struct { TLSConfig *Config - // EnableStoreSessionEvent may be set to true to enable the - // [QUICStoreSession] event for client connections. + // EnableSessionEvents may be set to true to enable the + // [QUICStoreSession] and [QUICResumeSession] events for client connections. // When this event is enabled, sessions are not automatically // stored in the client session cache. // The application should use [QUICConn.StoreSession] to store sessions. - EnableStoreSessionEvent bool + EnableSessionEvents bool } // A QUICEventKind is a type of operation on a QUIC connection. @@ -113,7 +113,7 @@ const ( // QUICStoreSession indicates that the server has provided state permitting // the client to resume the session. // [QUICEvent.SessionState] is set. - // The application should use [QUICConn.Store] session to store the [SessionState]. + // The application should use [QUICConn.StoreSession] session to store the [SessionState]. // The application may modify the [SessionState] before storing it. // This event only occurs on client connections. QUICStoreSession @@ -165,7 +165,7 @@ type quicState struct { transportParams []byte // to send to the peer - enableStoreSessionEvent bool + enableSessionEvents bool } // QUICClient returns a new TLS client side connection using QUICTransport as the @@ -186,9 +186,9 @@ func QUICServer(config *QUICConfig) *QUICConn { func newQUICConn(conn *Conn, config *QUICConfig) *QUICConn { conn.quic = &quicState{ - signalc: make(chan struct{}), - blockedc: make(chan struct{}), - enableStoreSessionEvent: config.EnableStoreSessionEvent, + signalc: make(chan struct{}), + blockedc: make(chan struct{}), + enableSessionEvents: config.EnableSessionEvents, } conn.quic.events = conn.quic.eventArr[:0] return &QUICConn{ diff --git a/src/crypto/tls/quic_test.go b/src/crypto/tls/quic_test.go index 5a6f66e4deaeb4..1bb2e55bddcbea 100644 --- a/src/crypto/tls/quic_test.go +++ b/src/crypto/tls/quic_test.go @@ -24,22 +24,22 @@ type testQUICConn struct { complete bool } -func newTestQUICClient(t *testing.T, config *Config) *testQUICConn { - q := &testQUICConn{t: t} - q.conn = QUICClient(&QUICConfig{ - TLSConfig: config, - }) +func newTestQUICClient(t *testing.T, config *QUICConfig) *testQUICConn { + q := &testQUICConn{ + t: t, + conn: QUICClient(config), + } t.Cleanup(func() { q.conn.Close() }) return q } -func newTestQUICServer(t *testing.T, config *Config) *testQUICConn { - q := &testQUICConn{t: t} - q.conn = QUICServer(&QUICConfig{ - TLSConfig: config, - }) +func newTestQUICServer(t *testing.T, config *QUICConfig) *testQUICConn { + q := &testQUICConn{ + t: t, + conn: QUICServer(config), + } t.Cleanup(func() { q.conn.Close() }) @@ -140,6 +140,11 @@ func runTestQUICConnection(ctx context.Context, cli, srv *testQUICConn, onEvent return err } } + case QUICStoreSession: + if a != cli { + return errors.New("unexpected QUICStoreSession event received by server") + } + a.conn.StoreSession(e.SessionState) case QUICResumeSession: if a.onResumeSession != nil { a.onResumeSession(e.SessionState) @@ -154,8 +159,8 @@ func runTestQUICConnection(ctx context.Context, cli, srv *testQUICConn, onEvent } func TestQUICConnection(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) @@ -196,13 +201,13 @@ func TestQUICConnection(t *testing.T) { } func TestQUICSessionResumption(t *testing.T) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) - clientConfig.ServerName = "example.go.dev" + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1) + clientConfig.TLSConfig.ServerName = "example.go.dev" - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, clientConfig) cli.conn.SetTransportParameters(nil) @@ -228,13 +233,13 @@ func TestQUICSessionResumption(t *testing.T) { } func TestQUICFragmentaryData(t *testing.T) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) - clientConfig.ServerName = "example.go.dev" + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1) + clientConfig.TLSConfig.ServerName = "example.go.dev" - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, clientConfig) cli.conn.SetTransportParameters(nil) @@ -260,8 +265,8 @@ func TestQUICFragmentaryData(t *testing.T) { func TestQUICPostHandshakeClientAuthentication(t *testing.T) { // RFC 9001, Section 4.4. - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) srv := newTestQUICServer(t, config) @@ -288,8 +293,8 @@ func TestQUICPostHandshakeClientAuthentication(t *testing.T) { func TestQUICPostHandshakeKeyUpdate(t *testing.T) { // RFC 9001, Section 6. - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) srv := newTestQUICServer(t, config) @@ -312,8 +317,8 @@ func TestQUICPostHandshakeKeyUpdate(t *testing.T) { } func TestQUICPostHandshakeMessageTooLarge(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) srv := newTestQUICServer(t, config) @@ -334,13 +339,13 @@ func TestQUICPostHandshakeMessageTooLarge(t *testing.T) { } func TestQUICHandshakeError(t *testing.T) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.InsecureSkipVerify = false - clientConfig.ServerName = "name" + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.InsecureSkipVerify = false + clientConfig.TLSConfig.ServerName = "name" - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, clientConfig) cli.conn.SetTransportParameters(nil) @@ -360,9 +365,9 @@ func TestQUICHandshakeError(t *testing.T) { // and that it reports the application protocol as soon as it has been // negotiated. func TestQUICConnectionState(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 - config.NextProtos = []string{"h3"} + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 + config.TLSConfig.NextProtos = []string{"h3"} cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) srv := newTestQUICServer(t, config) @@ -391,10 +396,10 @@ func TestQUICStartContextPropagation(t *testing.T) { const key = "key" const value = "value" ctx := context.WithValue(context.Background(), key, value) - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 calls := 0 - config.GetConfigForClient = func(info *ClientHelloInfo) (*Config, error) { + config.TLSConfig.GetConfigForClient = func(info *ClientHelloInfo) (*Config, error) { calls++ got, _ := info.Context().Value(key).(string) if got != value { @@ -415,13 +420,13 @@ func TestQUICStartContextPropagation(t *testing.T) { } func TestQUICDelayedTransportParameters(t *testing.T) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) - clientConfig.ServerName = "example.go.dev" + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1) + clientConfig.TLSConfig.ServerName = "example.go.dev" - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.TLSConfig.MinVersion = VersionTLS13 cliParams := "client params" srvParams := "server params" @@ -449,8 +454,8 @@ func TestQUICDelayedTransportParameters(t *testing.T) { } func TestQUICEmptyTransportParameters(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) @@ -475,8 +480,8 @@ func TestQUICEmptyTransportParameters(t *testing.T) { } func TestQUICCanceledWaitingForData(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.SetTransportParameters(nil) cli.conn.Start(context.Background()) @@ -489,8 +494,8 @@ func TestQUICCanceledWaitingForData(t *testing.T) { } func TestQUICCanceledWaitingForTransportParams(t *testing.T) { - config := testConfig.Clone() - config.MinVersion = VersionTLS13 + config := &QUICConfig{TLSConfig: testConfig.Clone()} + config.TLSConfig.MinVersion = VersionTLS13 cli := newTestQUICClient(t, config) cli.conn.Start(context.Background()) for cli.conn.NextEvent().Kind != QUICTransportParametersRequired { @@ -502,15 +507,15 @@ func TestQUICCanceledWaitingForTransportParams(t *testing.T) { } func TestQUICEarlyData(t *testing.T) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) - clientConfig.ServerName = "example.go.dev" - clientConfig.NextProtos = []string{"h3"} + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1) + clientConfig.TLSConfig.ServerName = "example.go.dev" + clientConfig.TLSConfig.NextProtos = []string{"h3"} - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 - serverConfig.NextProtos = []string{"h3"} + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.TLSConfig.MinVersion = VersionTLS13 + serverConfig.TLSConfig.NextProtos = []string{"h3"} cli := newTestQUICClient(t, clientConfig) cli.conn.SetTransportParameters(nil) @@ -528,7 +533,14 @@ func TestQUICEarlyData(t *testing.T) { cli2.conn.SetTransportParameters(nil) srv2 := newTestQUICServer(t, serverConfig) srv2.conn.SetTransportParameters(nil) - if err := runTestQUICConnection(context.Background(), cli2, srv2, nil); err != nil { + onEvent := func(e QUICEvent, src, dst *testQUICConn) bool { + switch e.Kind { + case QUICStoreSession, QUICResumeSession: + t.Errorf("with EnableSessionEvents=false, got unexpected event %v", e.Kind) + } + return false + } + if err := runTestQUICConnection(context.Background(), cli2, srv2, onEvent); err != nil { t.Fatalf("error during second connection handshake: %v", err) } if !cli2.conn.ConnectionState().DidResume { @@ -557,15 +569,17 @@ func TestQUICEarlyDataDeclined(t *testing.T) { } func testQUICEarlyDataDeclined(t *testing.T, server bool) { - clientConfig := testConfig.Clone() - clientConfig.MinVersion = VersionTLS13 - clientConfig.ClientSessionCache = NewLRUClientSessionCache(1) - clientConfig.ServerName = "example.go.dev" - clientConfig.NextProtos = []string{"h3"} - - serverConfig := testConfig.Clone() - serverConfig.MinVersion = VersionTLS13 - serverConfig.NextProtos = []string{"h3"} + clientConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + clientConfig.EnableSessionEvents = true + clientConfig.TLSConfig.MinVersion = VersionTLS13 + clientConfig.TLSConfig.ClientSessionCache = NewLRUClientSessionCache(1) + clientConfig.TLSConfig.ServerName = "example.go.dev" + clientConfig.TLSConfig.NextProtos = []string{"h3"} + + serverConfig := &QUICConfig{TLSConfig: testConfig.Clone()} + serverConfig.EnableSessionEvents = true + serverConfig.TLSConfig.MinVersion = VersionTLS13 + serverConfig.TLSConfig.NextProtos = []string{"h3"} cli := newTestQUICClient(t, clientConfig) cli.conn.SetTransportParameters(nil) From a2e90be996fb0e75966b1e1097dd20aa07eebc37 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Sun, 9 Jun 2024 12:47:23 -0700 Subject: [PATCH 37/41] os: rewrite TestChtimesWithZeroTimes First, this enables checks on DragonFly BSD, which partially works since CL 589496 (except two things: atime is not supported on hammer2 fs, and when both times are omitted, it doesn't work due to a kernel bug). Second, there are a few problems with TestChtimesWithZeroTimes: - test cases are interdependent (former cases influence the latter ones), making the test using too many different times and also hard to read; - time is changed forward not backward which could be racy; - if the test has failed, it hard to see which exact case is failing. Plus, there are issues with the error exclusion code in TestChtimesWithZeroTimes: - the atime comparison is done twice for the default ("unix") case; - the atime exclusion caused by noatime mount flag applies to all unixes rather than netbsd only as it should; - the atime exclusion tries to read wrong files (/bin/mounts and /etc/mtab instead of /proc/mounts); - the exclusion for netbsd is only applied for 64-bit arches, which seems wrong (and I've reproduced noatime issue on NetBSD 9.4/i386). Let's rewrite it, fixing all these issues, and rename to TestChtimesOmit. NB: TestChtimes can now be removed. Change-Id: If9020256ca920b4db836a1f0b2e055b5fce4a552 Reviewed-on: https://go-review.googlesource.com/c/go/+/591535 Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Reviewed-by: Joedian Reid LUCI-TryBot-Result: Go LUCI --- src/os/os_test.go | 173 +++++++++++++++++++++------------------------- 1 file changed, 79 insertions(+), 94 deletions(-) diff --git a/src/os/os_test.go b/src/os/os_test.go index b3fbe42ba788b8..9519aa0fc69787 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -1383,123 +1383,108 @@ func TestChtimes(t *testing.T) { testChtimes(t, f.Name()) } -func TestChtimesWithZeroTimes(t *testing.T) { +func TestChtimesOmit(t *testing.T) { + t.Parallel() + + testChtimesOmit(t, true, false) + testChtimesOmit(t, false, true) + testChtimesOmit(t, true, true) + testChtimesOmit(t, false, false) // Same as TestChtimes. +} + +func testChtimesOmit(t *testing.T, omitAt, omitMt bool) { + t.Logf("omit atime: %v, mtime: %v", omitAt, omitMt) file := newFile(t) _, err := file.Write([]byte("hello, world\n")) if err != nil { - t.Fatalf("Write: %s", err) + t.Fatal(err) } - fName := file.Name() + name := file.Name() err = file.Close() if err != nil { - t.Errorf("%v", err) + t.Error(err) } - fs, err := Stat(fName) + fs, err := Stat(name) if err != nil { t.Fatal(err) } - startAtime := Atime(fs) - startMtime := fs.ModTime() + + wantAtime := Atime(fs) + wantMtime := fs.ModTime() switch runtime.GOOS { case "js": - startAtime = startAtime.Truncate(time.Second) - startMtime = startMtime.Truncate(time.Second) + wantAtime = wantAtime.Truncate(time.Second) + wantMtime = wantMtime.Truncate(time.Second) } - at0 := startAtime - mt0 := startMtime - t0 := startMtime.Truncate(time.Second).Add(1 * time.Hour) - tests := []struct { - aTime time.Time - mTime time.Time - wantATime time.Time - wantMTime time.Time - }{ - { - aTime: time.Time{}, - mTime: time.Time{}, - wantATime: startAtime, - wantMTime: startMtime, - }, - { - aTime: t0.Add(200 * time.Second), - mTime: time.Time{}, - wantATime: t0.Add(200 * time.Second), - wantMTime: startMtime, - }, - { - aTime: time.Time{}, - mTime: t0.Add(100 * time.Second), - wantATime: t0.Add(200 * time.Second), - wantMTime: t0.Add(100 * time.Second), - }, - { - aTime: t0.Add(300 * time.Second), - mTime: t0.Add(100 * time.Second), - wantATime: t0.Add(300 * time.Second), - wantMTime: t0.Add(100 * time.Second), - }, + var setAtime, setMtime time.Time // Zero value means omit. + if !omitAt { + wantAtime = wantAtime.Add(-1 * time.Second) + setAtime = wantAtime + } + if !omitMt { + wantMtime = wantMtime.Add(-1 * time.Second) + setMtime = wantMtime } - for _, tt := range tests { - // Now change the times accordingly. - if err := Chtimes(fName, tt.aTime, tt.mTime); err != nil { - t.Error(err) - } + // Change the times accordingly. + if err := Chtimes(name, setAtime, setMtime); err != nil { + t.Error(err) + } - // Finally verify the expectations. - fs, err = Stat(fName) - if err != nil { - t.Error(err) - } - at0 = Atime(fs) - mt0 = fs.ModTime() - - if got, want := at0, tt.wantATime; !got.Equal(want) { - errormsg := fmt.Sprintf("AccessTime mismatch with values ATime:%q-MTime:%q\ngot: %q\nwant: %q", tt.aTime, tt.mTime, got, want) - switch runtime.GOOS { - case "plan9": - // Mtime is the time of the last change of - // content. Similarly, atime is set whenever - // the contents are accessed; also, it is set - // whenever mtime is set. - case "windows": + // Verify the expectations. + fs, err = Stat(name) + if err != nil { + t.Error(err) + } + gotAtime := Atime(fs) + gotMtime := fs.ModTime() + + if !gotAtime.Equal(wantAtime) { + errormsg := fmt.Sprintf("atime mismatch, got: %q, want: %q", gotAtime, wantAtime) + switch runtime.GOOS { + case "plan9": + // Mtime is the time of the last change of content. + // Similarly, atime is set whenever the contents are + // accessed; also, it is set whenever mtime is set. + case "dragonfly": + if omitAt && omitMt { + t.Log(errormsg) + t.Log("Known DragonFly BSD issue (won't work when both times are omitted); ignoring.") + } else { + // Assume hammer2 fs; https://www.dragonflybsd.org/hammer/ says: + // > Because HAMMER2 is a block copy-on-write filesystem, + // > the "atime" field is not supported and will typically + // > just reflect local system in-memory caches or mtime. + // + // TODO: if only can CI define TMPDIR to point to a tmpfs + // (e.g. /var/run/shm), this exception can be removed. + t.Log(errormsg) + t.Log("Known DragonFly BSD issue (atime not supported on hammer2); ignoring.") + } + case "netbsd": + if !omitAt && hasNoatime() { + t.Log(errormsg) + t.Log("Known NetBSD issue (atime not changed on fs mounted with noatime); ignoring.") + } else { t.Error(errormsg) - default: // unix's - if got, want := at0, tt.wantATime; !got.Equal(want) { - mounts, err := ReadFile("/bin/mounts") - if err != nil { - mounts, err = ReadFile("/etc/mtab") - } - if strings.Contains(string(mounts), "noatime") { - t.Log(errormsg) - t.Log("A filesystem is mounted with noatime; ignoring.") - } else { - switch runtime.GOOS { - case "netbsd", "dragonfly": - // On a 64-bit implementation, birth time is generally supported and cannot be changed. - // When supported, atime update is restricted and depends on the file system and on the - // OS configuration. - if strings.Contains(runtime.GOARCH, "64") { - t.Log(errormsg) - t.Log("Filesystem might not support atime changes; ignoring.") - } - default: - t.Error(errormsg) - } - } - } } + default: + t.Error(errormsg) } - if got, want := mt0, tt.wantMTime; !got.Equal(want) { - errormsg := fmt.Sprintf("ModTime mismatch with values ATime:%q-MTime:%q\ngot: %q\nwant: %q", tt.aTime, tt.mTime, got, want) - switch runtime.GOOS { - case "dragonfly": + } + if !gotMtime.Equal(wantMtime) { + errormsg := fmt.Sprintf("mtime mismatch, got: %q, want: %q", gotMtime, wantMtime) + switch runtime.GOOS { + case "dragonfly": + if omitAt && omitMt { t.Log(errormsg) - t.Log("Mtime is always updated; ignoring.") - default: + t.Log("Known DragonFly BSD issue (won't work when both times are omitted); ignoring.") + } else { t.Error(errormsg) } + default: + t.Error(errormsg) } } } From 5f319b75075a62ab176ab8c25f0e45f2ae4f0704 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 21 Jun 2024 11:56:45 -0400 Subject: [PATCH 38/41] cmd/link: don't let dsymutil delete our temp directory To work around #59026, where dsymutil may not clean up its temp directory at exit, we set DSYMUTIL_REPRODUCER_PATH to our temp directory so it uses that, and we can delete it at the end. In Xcode 16 beta, dsymutil deletes the DSYMUTIL_REPRODUCER_PATH directory even if it is not empty. We still need our tmpdir at the point, so give a subdirectory to dsymutil instead. For #68088. Change-Id: I18759cc39512819bbd0511793ce917eae72245d6 Reviewed-on: https://go-review.googlesource.com/c/go/+/593659 Reviewed-by: Than McIntosh LUCI-TryBot-Result: Go LUCI --- src/cmd/link/internal/ld/lib.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index c29a532bfd2973..fee7888b7cf982 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -2009,7 +2009,15 @@ func (ctxt *Link) hostlink() { cmd := exec.Command(dsymutilCmd, "-f", *flagOutfile, "-o", dsym) // dsymutil may not clean up its temp directory at exit. // Set DSYMUTIL_REPRODUCER_PATH to work around. see issue 59026. - cmd.Env = append(os.Environ(), "DSYMUTIL_REPRODUCER_PATH="+*flagTmpdir) + // dsymutil (Apple LLVM version 16.0.0) deletes the directory + // even if it is not empty. We still need our tmpdir, so give a + // subdirectory to dsymutil. + dsymDir := filepath.Join(*flagTmpdir, "dsymutil") + err := os.MkdirAll(dsymDir, 0777) + if err != nil { + Exitf("fail to create temp dir: %v", err) + } + cmd.Env = append(os.Environ(), "DSYMUTIL_REPRODUCER_PATH="+dsymDir) if ctxt.Debugvlog != 0 { ctxt.Logf("host link dsymutil:") for _, v := range cmd.Args { From 5a18e79687dea15680ff5f799b549fa0efd0cad9 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 21 Jun 2024 12:20:38 -0400 Subject: [PATCH 39/41] cmd/link: don't skip code sign even if dsymutil didn't generate a file Even if dsymutil didn't generate a file (which should not happen with the Apple toolchain with the correct setup), we should not skip next steps, e.g. code sign. A return statement makes it exit too early. Updates #68088. Change-Id: Ic1271ed1b7fe5bdee5a25cc5d669a105173b389e Reviewed-on: https://go-review.googlesource.com/c/go/+/593660 LUCI-TryBot-Result: Go LUCI Reviewed-by: Than McIntosh --- src/cmd/link/internal/ld/lib.go | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index fee7888b7cf982..4f1eebb9e36656 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -2050,14 +2050,13 @@ func (ctxt *Link) hostlink() { Exitf("%s: running strip failed: %v\n%s\n%s", os.Args[0], err, cmd, out) } // Skip combining if `dsymutil` didn't generate a file. See #11994. - if _, err := os.Stat(dsym); os.IsNotExist(err) { - return + if _, err := os.Stat(dsym); err == nil { + updateMachoOutFile("combining dwarf", + func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error { + return machoCombineDwarf(ctxt, exef, exem, dsym, outexe) + }) + uuidUpdated = true } - updateMachoOutFile("combining dwarf", - func(ctxt *Link, exef *os.File, exem *macho.File, outexe string) error { - return machoCombineDwarf(ctxt, exef, exem, dsym, outexe) - }) - uuidUpdated = true } if ctxt.IsDarwin() && !uuidUpdated && *flagBuildid != "" { updateMachoOutFile("rewriting uuid", From b0927fdd494a79458ff151ce8db59963f67b80be Mon Sep 17 00:00:00 2001 From: Jes Cok Date: Fri, 28 Jun 2024 00:00:00 +0800 Subject: [PATCH 40/41] slices: update docs for All, Backward, Values For #61899 Change-Id: I3586b9b59e87159d21e1a270dabb3af213592739 Reviewed-on: https://go-review.googlesource.com/c/go/+/595515 Auto-Submit: Ian Lance Taylor LUCI-TryBot-Result: Go LUCI Reviewed-by: Alan Donovan Reviewed-by: Ian Lance Taylor --- src/slices/iter.go | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/slices/iter.go b/src/slices/iter.go index 131cece3a06ff4..cd8f308ca08ece 100644 --- a/src/slices/iter.go +++ b/src/slices/iter.go @@ -9,8 +9,8 @@ import ( "iter" ) -// All returns an iterator over index-value pairs in the slice. -// The indexes range in the usual order, from 0 through len(s)-1. +// All returns an iterator over index-value pairs in the slice +// in the usual order. func All[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] { return func(yield func(int, E) bool) { for i, v := range s { @@ -22,7 +22,7 @@ func All[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] { } // Backward returns an iterator over index-value pairs in the slice, -// traversing it backward. The indexes range from len(s)-1 down to 0. +// traversing it backward with descending indices. func Backward[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] { return func(yield func(int, E) bool) { for i := len(s) - 1; i >= 0; i-- { @@ -33,8 +33,7 @@ func Backward[Slice ~[]E, E any](s Slice) iter.Seq2[int, E] { } } -// Values returns an iterator over the slice elements, -// starting with s[0]. +// Values returns an iterator that yields the slice elements in order. func Values[Slice ~[]E, E any](s Slice) iter.Seq[E] { return func(yield func(E) bool) { for _, v := range s { From ea537cca314d9da5365eeefcc375410c76e93b36 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Thu, 27 Jun 2024 11:16:30 -0400 Subject: [PATCH 41/41] cmd/go/internal/help: add documentation for language version downgrading This change adds documentation for language version downgrading using build constraints. Fixes #68161 For #61894 Change-Id: I283a51afd7020c9fd1f5469a6a93fd814ba32f7e Reviewed-on: https://go-review.googlesource.com/c/go/+/595475 Reviewed-by: Robert Findley LUCI-TryBot-Result: Go LUCI --- src/cmd/go/alldocs.go | 7 +++++++ src/cmd/go/internal/help/helpdoc.go | 7 +++++++ 2 files changed, 14 insertions(+) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index 972f9e111f6db1..e87e6ebe465587 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -1994,6 +1994,9 @@ // // //go:build // +// Build constraints can also be used to downgrade the language version +// used to compile a file. +// // Constraints may appear in any kind of source file (not just Go), but // they must appear near the top of the file, preceded // only by blank lines and other comments. These rules mean that in Go @@ -2116,6 +2119,10 @@ // with a "// +build" prefix. The gofmt command will add an equivalent //go:build // constraint when encountering the older syntax. // +// In modules with a Go version of 1.21 or later, if a file's build constraint +// has a term for a Go major release, the language version used when compiling +// the file will be the minimum version implied by the build constraint. +// // # Build modes // // The 'go build' and 'go install' commands take a -buildmode argument which diff --git a/src/cmd/go/internal/help/helpdoc.go b/src/cmd/go/internal/help/helpdoc.go index 791013dbfeaa38..29c0a56321a602 100644 --- a/src/cmd/go/internal/help/helpdoc.go +++ b/src/cmd/go/internal/help/helpdoc.go @@ -835,6 +835,9 @@ line comment that begins //go:build +Build constraints can also be used to downgrade the language version +used to compile a file. + Constraints may appear in any kind of source file (not just Go), but they must appear near the top of the file, preceded only by blank lines and other comments. These rules mean that in Go @@ -954,5 +957,9 @@ only when building the package for 32-bit x86. Go versions 1.16 and earlier used a different syntax for build constraints, with a "// +build" prefix. The gofmt command will add an equivalent //go:build constraint when encountering the older syntax. + +In modules with a Go version of 1.21 or later, if a file's build constraint +has a term for a Go major release, the language version used when compiling +the file will be the minimum version implied by the build constraint. `, }