From f38a580a51cd2fc072aabc9dd45b9e0a85064c81 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Tue, 5 Apr 2022 18:47:23 -0400 Subject: [PATCH 01/38] cmd/go: add more tracing Change-Id: I26ed64c097533ee9276e598653db72efc053c4e5 Reviewed-on: https://go-review.googlesource.com/c/go/+/403156 TryBot-Result: Gopher Robot Reviewed-by: Michael Matloob Run-TryBot: Michael Matloob Reviewed-by: Bryan Mills --- src/cmd/go/internal/load/pkg.go | 6 ++++++ src/cmd/go/internal/modload/query.go | 3 +++ src/cmd/go/internal/modload/search.go | 7 +++++++ 3 files changed, 16 insertions(+) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index fe4a82472d..1a7b9d235d 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -686,6 +686,9 @@ func LoadImport(ctx context.Context, opts PackageOpts, path, srcDir string, pare } func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package { + ctx, span := trace.StartSpan(ctx, "modload.loadImport "+path) + defer span.Done() + if path == "" { panic("LoadImport called with empty package path") } @@ -801,6 +804,9 @@ func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDi // loadPackageData returns a boolean, loaded, which is true if this is the // first time the package was loaded. Callers may preload imports in this case. func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) { + ctx, span := trace.StartSpan(ctx, "load.loadPackageData "+path) + defer span.Done() + if path == "" { panic("loadPackageData called with empty package path") } diff --git a/src/cmd/go/internal/modload/query.go b/src/cmd/go/internal/modload/query.go index 27af78d99e..69e5fbd93b 100644 --- a/src/cmd/go/internal/modload/query.go +++ b/src/cmd/go/internal/modload/query.go @@ -74,6 +74,9 @@ import ( // If path is the path of the main module and the query is "latest", // Query returns Target.Version as the version. func Query(ctx context.Context, path, query, current string, allowed AllowedFunc) (*modfetch.RevInfo, error) { + ctx, span := trace.StartSpan(ctx, "modload.Query "+path) + defer span.Done() + var info *modfetch.RevInfo err := modfetch.TryProxies(func(proxy string) (err error) { info, err = queryProxy(ctx, proxy, path, query, current, allowed) diff --git a/src/cmd/go/internal/modload/search.go b/src/cmd/go/internal/modload/search.go index 4b90392d94..d9d7711d06 100644 --- a/src/cmd/go/internal/modload/search.go +++ b/src/cmd/go/internal/modload/search.go @@ -23,6 +23,7 @@ import ( "cmd/go/internal/modindex" "cmd/go/internal/par" "cmd/go/internal/search" + "cmd/go/internal/trace" "golang.org/x/mod/module" ) @@ -38,6 +39,9 @@ const ( // a global) for tags, can include or exclude packages in the standard library, // and is restricted to the given list of modules. func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, filter stdFilter, modules []module.Version) { + ctx, span := trace.StartSpan(ctx, "modload.matchPackages") + defer span.Done() + m.Pkgs = []string{} isMatch := func(string) bool { return true } @@ -69,6 +73,9 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f q := par.NewQueue(runtime.GOMAXPROCS(0)) walkPkgs := func(root, importPathRoot string, prune pruning) { + _, span := trace.StartSpan(ctx, "walkPkgs "+root) + defer span.Done() + root = filepath.Clean(root) err := fsys.Walk(root, func(path string, fi fs.FileInfo, err error) error { if err != nil { From 7bad61554ec6da4ba4cbad443074360408890603 Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Thu, 16 Jun 2022 20:33:35 +0000 Subject: [PATCH 02/38] runtime: write much more direct test for semaphore waiter scalability This test originally existed as two tests in test/locklinear.go, but this checked against actual locks and was flaky. The test was checking a property of a deep part of the runtime but from a much higher level, and it's easy for nondeterminism due to scheduling to completely mess that up, especially on an oversubscribed system. That test was then moved to the sync package with a more rigorous testing methodology, but it could still flake pretty easily. Finally, this CL makes semtable more testable, exports it in export_test.go, then writes a very direct scalability test for exactly the situation the original test described. As far as I can tell, this is much, much more stable, because it's single-threaded and is just checking exactly the algorithm we need to check. Don't bother trying to bring in a test that checks for O(log n) behavior on the other kind of iteration. It'll be perpetually flaky because the underlying data structure is a treap, so it's only _expected_ to be O(log n), but it's very easy for it to get unlucky without a large number of iterations that's too much for a simple test. Fixes #53381. Change-Id: Ia1cd2d2b0e36d552d5a8ae137077260a16016602 Reviewed-on: https://go-review.googlesource.com/c/go/+/412875 Reviewed-by: Michael Pratt --- src/runtime/export_test.go | 30 +++++++++- src/runtime/sema.go | 18 +++--- src/runtime/sema_test.go | 44 +++++++++++++++ src/sync/mutex_test.go | 112 ------------------------------------- 4 files changed, 83 insertions(+), 121 deletions(-) diff --git a/src/runtime/export_test.go b/src/runtime/export_test.go index b9f0990d8c..1626f99336 100644 --- a/src/runtime/export_test.go +++ b/src/runtime/export_test.go @@ -1163,10 +1163,38 @@ var Semacquire = semacquire var Semrelease1 = semrelease1 func SemNwait(addr *uint32) uint32 { - root := semroot(addr) + root := semtable.rootFor(addr) return atomic.Load(&root.nwait) } +const SemTableSize = semTabSize + +// SemTable is a wrapper around semTable exported for testing. +type SemTable struct { + semTable +} + +// Enqueue simulates enqueuing a waiter for a semaphore (or lock) at addr. +func (t *SemTable) Enqueue(addr *uint32) { + s := acquireSudog() + s.releasetime = 0 + s.acquiretime = 0 + s.ticket = 0 + t.semTable.rootFor(addr).queue(addr, s, false) +} + +// Dequeue simulates dequeuing a waiter for a semaphore (or lock) at addr. +// +// Returns true if there actually was a waiter to be dequeued. +func (t *SemTable) Dequeue(addr *uint32) bool { + s, _ := t.semTable.rootFor(addr).dequeue(addr) + if s != nil { + releaseSudog(s) + return true + } + return false +} + // mspan wrapper for testing. // //go:notinheap diff --git a/src/runtime/sema.go b/src/runtime/sema.go index e83deee083..c7a1a76e28 100644 --- a/src/runtime/sema.go +++ b/src/runtime/sema.go @@ -35,7 +35,7 @@ import ( // where n is the number of distinct addresses with goroutines blocked // on them that hash to the given semaRoot. // See golang.org/issue/17953 for a program that worked badly -// before we introduced the second level of list, and test/locklinear.go +// before we introduced the second level of list, and TestSemTableOneAddrCollisionLinear // for a test that exercises this. type semaRoot struct { lock mutex @@ -43,14 +43,20 @@ type semaRoot struct { nwait uint32 // Number of waiters. Read w/o the lock. } +var semtable semTable + // Prime to not correlate with any user patterns. const semTabSize = 251 -var semtable [semTabSize]struct { +type semTable [semTabSize]struct { root semaRoot pad [cpu.CacheLinePadSize - unsafe.Sizeof(semaRoot{})]byte } +func (t *semTable) rootFor(addr *uint32) *semaRoot { + return &t[(uintptr(unsafe.Pointer(addr))>>3)%semTabSize].root +} + //go:linkname sync_runtime_Semacquire sync.runtime_Semacquire func sync_runtime_Semacquire(addr *uint32) { semacquire1(addr, false, semaBlockProfile, 0) @@ -113,7 +119,7 @@ func semacquire1(addr *uint32, lifo bool, profile semaProfileFlags, skipframes i // sleep // (waiter descriptor is dequeued by signaler) s := acquireSudog() - root := semroot(addr) + root := semtable.rootFor(addr) t0 := int64(0) s.releasetime = 0 s.acquiretime = 0 @@ -157,7 +163,7 @@ func semrelease(addr *uint32) { } func semrelease1(addr *uint32, handoff bool, skipframes int) { - root := semroot(addr) + root := semtable.rootFor(addr) atomic.Xadd(addr, 1) // Easy case: no waiters? @@ -214,10 +220,6 @@ func semrelease1(addr *uint32, handoff bool, skipframes int) { } } -func semroot(addr *uint32) *semaRoot { - return &semtable[(uintptr(unsafe.Pointer(addr))>>3)%semTabSize].root -} - func cansemacquire(addr *uint32) bool { for { v := atomic.Load(addr) diff --git a/src/runtime/sema_test.go b/src/runtime/sema_test.go index cf3de0a190..f3e95d10be 100644 --- a/src/runtime/sema_test.go +++ b/src/runtime/sema_test.go @@ -5,6 +5,7 @@ package runtime_test import ( + "internal/testenv" . "runtime" "sync" "sync/atomic" @@ -101,3 +102,46 @@ func testSemaHandoff() bool { return res == 1 // did the waiter run first? } + +func TestSemTableOneAddrCollisionLinear(t *testing.T) { + testenv.CheckLinear(t, func(scale float64) func(*testing.B) { + n := int(1000 * scale) + return func(b *testing.B) { + tab := Escape(new(SemTable)) + u := make([]uint32, SemTableSize+1) + + b.ResetTimer() + + // Simulate two locks colliding on the same semaRoot. + // + // Specifically enqueue all the waiters for the first lock, + // then all the waiters for the second lock. + // + // Then, dequeue all the waiters from the first lock, then + // the second. + // + // Each enqueue/dequeue operation should be O(1), because + // there are exactly 2 locks. This could be O(n) if all + // the waiters for both locks are on the same list, as it + // once was. + for i := 0; i < n; i++ { + if i < n/2 { + tab.Enqueue(&u[0]) + } else { + tab.Enqueue(&u[SemTableSize]) + } + } + for i := 0; i < n; i++ { + var ok bool + if i < n/2 { + ok = tab.Dequeue(&u[0]) + } else { + ok = tab.Dequeue(&u[SemTableSize]) + } + if !ok { + b.Fatal("failed to dequeue") + } + } + } + }) +} diff --git a/src/sync/mutex_test.go b/src/sync/mutex_test.go index 8e34b02459..cca0986a30 100644 --- a/src/sync/mutex_test.go +++ b/src/sync/mutex_test.go @@ -333,115 +333,3 @@ func BenchmarkMutexSpin(b *testing.B) { } }) } - -const runtimeSemaHashTableSize = 251 // known size of runtime hash table - -func TestMutexLinearOne(t *testing.T) { - testenv.CheckLinear(t, func(scale float64) func(*testing.B) { - n := int(1000 * scale) - return func(b *testing.B) { - ch := make(chan struct{}) - locks := make([]RWMutex, runtimeSemaHashTableSize+1) - - b.ResetTimer() - - var wgStart, wgFinish WaitGroup - for i := 0; i < n; i++ { - wgStart.Add(1) - wgFinish.Add(1) - go func() { - wgStart.Done() - locks[0].Lock() - ch <- struct{}{} - wgFinish.Done() - }() - } - wgStart.Wait() - - wgFinish.Add(1) - go func() { - for j := 0; j < n; j++ { - locks[1].Lock() - locks[runtimeSemaHashTableSize].Lock() - locks[1].Unlock() - runtime.Gosched() - locks[runtimeSemaHashTableSize].Unlock() - } - wgFinish.Done() - }() - - for j := 0; j < n; j++ { - locks[1].Lock() - locks[runtimeSemaHashTableSize].Lock() - locks[1].Unlock() - runtime.Gosched() - locks[runtimeSemaHashTableSize].Unlock() - } - - b.StopTimer() - - for i := 0; i < n; i++ { - <-ch - locks[0].Unlock() - } - - wgFinish.Wait() - } - }) -} - -func TestMutexLinearMany(t *testing.T) { - if runtime.GOARCH == "arm" && os.Getenv("GOARM") == "5" { - // stressLockMany reliably fails on the linux-arm-arm5spacemonkey - // builder. See https://golang.org/issue/24221. - return - } - testenv.CheckLinear(t, func(scale float64) func(*testing.B) { - n := int(1000 * scale) - return func(b *testing.B) { - locks := make([]RWMutex, n*runtimeSemaHashTableSize+1) - - b.ResetTimer() - - var wgStart, wgFinish WaitGroup - for i := 0; i < n; i++ { - wgStart.Add(1) - wgFinish.Add(1) - go func(i int) { - locks[(i+1)*runtimeSemaHashTableSize].Lock() - wgStart.Done() - locks[(i+1)*runtimeSemaHashTableSize].Lock() - locks[(i+1)*runtimeSemaHashTableSize].Unlock() - wgFinish.Done() - }(i) - } - wgStart.Wait() - - go func() { - for j := 0; j < n; j++ { - locks[1].Lock() - locks[0].Lock() - locks[1].Unlock() - runtime.Gosched() - locks[0].Unlock() - } - }() - - for j := 0; j < n; j++ { - locks[1].Lock() - locks[0].Lock() - locks[1].Unlock() - runtime.Gosched() - locks[0].Unlock() - } - - b.StopTimer() - - for i := 0; i < n; i++ { - locks[(i+1)*runtimeSemaHashTableSize].Unlock() - } - - wgFinish.Wait() - } - }) -} From 9068c6844dc0f0100bd810ad73dbf877bb92507b Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 16 Jun 2022 15:45:25 -0400 Subject: [PATCH 03/38] cmd/dist: add package . to 'go test' commands This suppresses verbose output if the test passes, eliminating some "hello from C" noise for the ../misc/cgo test. Change-Id: I6324bfb4b3633c20e0eb0ae03aa25d40fab9fcfb Reviewed-on: https://go-review.googlesource.com/c/go/+/412776 Reviewed-by: Ian Lance Taylor Run-TryBot: Bryan Mills Auto-Submit: Bryan Mills TryBot-Result: Gopher Robot --- src/cmd/dist/test.go | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go index 26d7fe0f73..846d0c0d85 100644 --- a/src/cmd/dist/test.go +++ b/src/cmd/dist/test.go @@ -766,7 +766,7 @@ func (t *tester) registerTests() { name: "swig_stdio", heading: "../misc/swig/stdio", fn: func(dt *distTest) error { - t.addCmd(dt, "misc/swig/stdio", t.goTest()) + t.addCmd(dt, "misc/swig/stdio", t.goTest(), ".") return nil }, }) @@ -776,7 +776,7 @@ func (t *tester) registerTests() { name: "swig_callback", heading: "../misc/swig/callback", fn: func(dt *distTest) error { - t.addCmd(dt, "misc/swig/callback", t.goTest()) + t.addCmd(dt, "misc/swig/callback", t.goTest(), ".") return nil }, }, @@ -784,7 +784,7 @@ func (t *tester) registerTests() { name: "swig_callback_lto", heading: "../misc/swig/callback", fn: func(dt *distTest) error { - cmd := t.addCmd(dt, "misc/swig/callback", t.goTest()) + cmd := t.addCmd(dt, "misc/swig/callback", t.goTest(), ".") setEnv(cmd, "CGO_CFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option") setEnv(cmd, "CGO_CXXFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option") setEnv(cmd, "CGO_LDFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option") @@ -1185,11 +1185,11 @@ func (t *tester) runHostTest(dir, pkg string) error { } func (t *tester) cgoTest(dt *distTest) error { - cmd := t.addCmd(dt, "misc/cgo/test", t.goTest()) + cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), ".") setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=auto") if t.internalLink() { - cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=internal") + cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=internal", ".") setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=internal") } @@ -1201,15 +1201,15 @@ func (t *tester) cgoTest(dt *distTest) error { if !t.extLink() { break } - cmd := t.addCmd(dt, "misc/cgo/test", t.goTest()) + cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), ".") setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external") - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s", ".") if t.supportedBuildmode("pie") { - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", ".") if t.internalLink() && t.internalLinkPIE() { - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie", ".") } } @@ -1221,14 +1221,14 @@ func (t *tester) cgoTest(dt *distTest) error { "netbsd-386", "netbsd-amd64", "openbsd-386", "openbsd-amd64", "openbsd-arm", "openbsd-arm64", "openbsd-mips64": - cmd := t.addCmd(dt, "misc/cgo/test", t.goTest()) + cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), ".") setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external") // cgo should be able to cope with both -g arguments and colored // diagnostics. setEnv(cmd, "CGO_CFLAGS", "-g0 -fdiagnostics-color") - t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=auto") - t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=external") + t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=auto", ".") + t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=external", ".") switch pair { case "aix-ppc64", "netbsd-386", "netbsd-amd64": @@ -1247,28 +1247,28 @@ func (t *tester) cgoTest(dt *distTest) error { fmt.Println("No support for static linking found (lacks libc.a?), skip cgo static linking test.") } else { if goos != "android" { - t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`) + t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`, ".") } - t.addCmd(dt, "misc/cgo/nocgo", t.goTest()) - t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external`) + t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), ".") + t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external`, ".") if goos != "android" { - t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`) - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`) + t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`, ".") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`, ".") // -static in CGO_LDFLAGS triggers a different code path // than -static in -extldflags, so test both. // See issue #16651. - cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static") + cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static", ".") setEnv(cmd, "CGO_LDFLAGS", "-static -pthread") } } if t.supportedBuildmode("pie") { - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", ".") if t.internalLink() && t.internalLinkPIE() { - t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie") + t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie", ".") } - t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie") - t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie") + t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie", ".") + t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie", ".") } } } From 6c25ba624fd032a20dcfa94f9f9f0ae32c57c54b Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Wed, 1 Jun 2022 12:54:00 -0400 Subject: [PATCH 04/38] go/token: delete unused File.set field This field is only used for a sanity check in a test. Change-Id: I868ed10131ec33994ebb1b1d88f6740956824bd7 Reviewed-on: https://go-review.googlesource.com/c/go/+/409834 Run-TryBot: Robert Findley TryBot-Result: Gopher Robot Reviewed-by: Robert Findley Reviewed-by: Robert Griesemer --- src/go/token/position.go | 3 +-- src/go/token/serialize.go | 1 - src/go/token/serialize_test.go | 6 ------ 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/go/token/position.go b/src/go/token/position.go index 00f24535bf..bd9ae07b28 100644 --- a/src/go/token/position.go +++ b/src/go/token/position.go @@ -92,7 +92,6 @@ func (p Pos) IsValid() bool { // A File is a handle for a file belonging to a FileSet. // A File has a name, size, and line offset table. type File struct { - set *FileSet name string // file name as provided to AddFile base int // Pos value range for this file is [base...base+size] size int // file size as provided to AddFile @@ -418,7 +417,7 @@ func (s *FileSet) AddFile(filename string, base, size int) *File { panic(fmt.Sprintf("invalid size %d (should be >= 0)", size)) } // base >= s.base && size >= 0 - f := &File{set: s, name: filename, base: base, size: size, lines: []int{0}} + f := &File{name: filename, base: base, size: size, lines: []int{0}} base += size + 1 // +1 because EOF also has a position if base < 0 { panic("token.Pos offset overflow (> 2G of source code in file set)") diff --git a/src/go/token/serialize.go b/src/go/token/serialize.go index ffb69908b9..38c10ebd47 100644 --- a/src/go/token/serialize.go +++ b/src/go/token/serialize.go @@ -31,7 +31,6 @@ func (s *FileSet) Read(decode func(any) error) error { for i := 0; i < len(ss.Files); i++ { f := &ss.Files[i] files[i] = &File{ - set: s, name: f.Name, base: f.Base, size: f.Size, diff --git a/src/go/token/serialize_test.go b/src/go/token/serialize_test.go index 4aa0b0da26..8d9799547a 100644 --- a/src/go/token/serialize_test.go +++ b/src/go/token/serialize_test.go @@ -35,12 +35,6 @@ func equal(p, q *FileSet) error { for i, f := range p.files { g := q.files[i] - if f.set != p { - return fmt.Errorf("wrong fileset for %q", f.name) - } - if g.set != q { - return fmt.Errorf("wrong fileset for %q", g.name) - } if f.name != g.name { return fmt.Errorf("different filenames: %q != %q", f.name, g.name) } From dd2d00f9d57ba6aafb084d83ffc7fb35f97b8c84 Mon Sep 17 00:00:00 2001 From: Dmitri Goutnik Date: Fri, 17 Jun 2022 12:10:09 -0500 Subject: [PATCH 05/38] net: fix flaky *TimeoutMustNotReturn tests The tester goroutine doesn't always gets a chance to run before the timeout expires. Wait for the goroutine to start and set deadlines before staring the timer. Fixes #36796 Change-Id: Iffed6259de31340c3f66e34da473826a1d09fcde Reviewed-on: https://go-review.googlesource.com/c/go/+/412858 Reviewed-by: Damien Neil Run-TryBot: Bryan Mills Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- src/net/timeout_test.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/net/timeout_test.go b/src/net/timeout_test.go index d1cfbf853c..3ad026c490 100644 --- a/src/net/timeout_test.go +++ b/src/net/timeout_test.go @@ -243,8 +243,7 @@ func TestAcceptTimeoutMustNotReturn(t *testing.T) { ln := newLocalListener(t, "tcp") defer ln.Close() - max := time.NewTimer(100 * time.Millisecond) - defer max.Stop() + maxch := make(chan *time.Timer) ch := make(chan error) go func() { if err := ln.(*TCPListener).SetDeadline(time.Now().Add(-5 * time.Second)); err != nil { @@ -253,10 +252,14 @@ func TestAcceptTimeoutMustNotReturn(t *testing.T) { if err := ln.(*TCPListener).SetDeadline(noDeadline); err != nil { t.Error(err) } + maxch <- time.NewTimer(100 * time.Millisecond) _, err := ln.Accept() ch <- err }() + max := <-maxch + defer max.Stop() + select { case err := <-ch: if perr := parseAcceptError(err); perr != nil { @@ -348,8 +351,7 @@ func TestReadTimeoutMustNotReturn(t *testing.T) { } defer c.Close() - max := time.NewTimer(100 * time.Millisecond) - defer max.Stop() + maxch := make(chan *time.Timer) ch := make(chan error) go func() { if err := c.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil { @@ -361,11 +363,15 @@ func TestReadTimeoutMustNotReturn(t *testing.T) { if err := c.SetReadDeadline(noDeadline); err != nil { t.Error(err) } + maxch <- time.NewTimer(100 * time.Millisecond) var b [1]byte _, err := c.Read(b[:]) ch <- err }() + max := <-maxch + defer max.Stop() + select { case err := <-ch: if perr := parseReadError(err); perr != nil { @@ -517,8 +523,7 @@ func TestWriteTimeoutMustNotReturn(t *testing.T) { } defer c.Close() - max := time.NewTimer(100 * time.Millisecond) - defer max.Stop() + maxch := make(chan *time.Timer) ch := make(chan error) go func() { if err := c.SetDeadline(time.Now().Add(-5 * time.Second)); err != nil { @@ -530,6 +535,7 @@ func TestWriteTimeoutMustNotReturn(t *testing.T) { if err := c.SetWriteDeadline(noDeadline); err != nil { t.Error(err) } + maxch <- time.NewTimer(100 * time.Millisecond) var b [1]byte for { if _, err := c.Write(b[:]); err != nil { @@ -539,6 +545,9 @@ func TestWriteTimeoutMustNotReturn(t *testing.T) { } }() + max := <-maxch + defer max.Stop() + select { case err := <-ch: if perr := parseWriteError(err); perr != nil { From 9e2f2897546c51863bf860c30622fbe9e3359391 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Fri, 17 Jun 2022 12:34:30 -0400 Subject: [PATCH 06/38] cmd/go/internal/work: log clearer detail for subprocess errors in (*Builder).toolID For #52647. Change-Id: Ic12123769d339c2df677500ed59f15a4ee5037d3 Reviewed-on: https://go-review.googlesource.com/c/go/+/412954 Run-TryBot: Bryan Mills TryBot-Result: Gopher Robot Auto-Submit: Bryan Mills Reviewed-by: Ian Lance Taylor --- src/cmd/go/internal/work/buildid.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/cmd/go/internal/work/buildid.go b/src/cmd/go/internal/work/buildid.go index 846e2c8b77..a5b5570e05 100644 --- a/src/cmd/go/internal/work/buildid.go +++ b/src/cmd/go/internal/work/buildid.go @@ -164,13 +164,16 @@ func (b *Builder) toolID(name string) string { cmd.Stdout = &stdout cmd.Stderr = &stderr if err := cmd.Run(); err != nil { - base.Fatalf("%s: %v\n%s%s", desc, err, stdout.Bytes(), stderr.Bytes()) + if stderr.Len() > 0 { + os.Stderr.Write(stderr.Bytes()) + } + base.Fatalf("go: error obtaining buildID for %s: %v", desc, err) } line := stdout.String() f := strings.Fields(line) if len(f) < 3 || f[0] != name && path != VetTool || f[1] != "version" || f[2] == "devel" && !strings.HasPrefix(f[len(f)-1], "buildID=") { - base.Fatalf("%s -V=full: unexpected output:\n\t%s", desc, line) + base.Fatalf("go: parsing buildID from %s -V=full: unexpected output:\n\t%s", desc, line) } if f[2] == "devel" { // On the development branch, use the content ID part of the build ID. From d42a48828f3cff4e57cefaf72bc88cef7d355fd6 Mon Sep 17 00:00:00 2001 From: Kevin Burke Date: Tue, 14 Jun 2022 21:29:36 -0700 Subject: [PATCH 07/38] sync: add more notes about Cond behavior Cond is difficult to use correctly (I was just bitten by it in a production app that I inherited). While several proposals have come up to improve or remove sync.Cond, no action has so far been taken. Update the documentation to discourage use of sync.Cond, and point people in the direction of preferred alternatives. I believe this will help encourage behavior we want (less use of sync.Cond and more use of channels), while also paving the way for, potentially, removing Cond in a future version of the language. Thanks very much to Bryan Mills and Sean Liao for discussion and recommendations. Updates #20491. Updates #21165. Change-Id: Ib4d0631c79d4c4d0a30027255cd43bc47cddebd3 Reviewed-on: https://go-review.googlesource.com/c/go/+/412237 Run-TryBot: Ian Lance Taylor Auto-Submit: Ian Lance Taylor Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/sync/cond.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/sync/cond.go b/src/sync/cond.go index 19f986e478..cbf5ba6071 100644 --- a/src/sync/cond.go +++ b/src/sync/cond.go @@ -22,6 +22,17 @@ import ( // In the terminology of the Go memory model, Cond arranges that // a call to Broadcast or Signal “synchronizes before” any Wait call // that it unblocks. +// +// For many simple use cases, users will be better off using channels than a +// Cond (Broadcast corresponds to closing a channel, and Signal corresponds to +// sending on a channel). +// +// For more on replacements for sync.Cond, see [Roberto Clapis's series on +// advanced concurrency patterns], as well as [Bryan Mills's talk on concurrency +// patterns]. +// +// [Roberto Clapis's series on advanced concurrency patterns]: https://blogtitle.github.io/categories/concurrency/ +// [Bryan Mills's talk on concurrency patterns]: https://drive.google.com/file/d/1nPdvhB0PutEJzdCq5ms6UI58dp50fcAN/view type Cond struct { noCopy noCopy @@ -64,6 +75,9 @@ func (c *Cond) Wait() { // // It is allowed but not required for the caller to hold c.L // during the call. +// +// Signal() does not affect goroutine scheduling priority; if other goroutines +// are attempting to lock c.L, they may be awoken before a "waiting" goroutine. func (c *Cond) Signal() { c.checker.check() runtime_notifyListNotifyOne(&c.notify) From 103cc661f1906837d02133e9c65d0475ac49799c Mon Sep 17 00:00:00 2001 From: Josh Powers Date: Fri, 17 Jun 2022 18:22:12 +0000 Subject: [PATCH 08/38] cmd/go/internal/modfetch: prevent duplicate hashes in go.sum To write go.sum, each module and then each hash is looped through. The hashes are kept in a slice and there is no check to ensure that hashes were not added or already exist in the file. Therefore, unique the hashes of each module before writing to prevent duplicates. Fixes: #28456 Change-Id: I1cf7e7cdee3e7530a0ee605cd76d738627be1e0d GitHub-Last-Rev: 0ed02e9591e966fe5f6ba275635c3974daa2656e GitHub-Pull-Request: golang/go#53291 Reviewed-on: https://go-review.googlesource.com/c/go/+/411154 Auto-Submit: Bryan Mills Run-TryBot: Bryan Mills Reviewed-by: Ian Lance Taylor Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- src/cmd/go/internal/modfetch/fetch.go | 1 + .../testdata/script/mod_tidy_duplicates.txt | 38 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 src/cmd/go/testdata/script/mod_tidy_duplicates.txt diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index a7c8c2c769..426df9bc04 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -833,6 +833,7 @@ Outer: for _, m := range mods { list := goSum.m[m] sort.Strings(list) + str.Uniq(&list) for _, h := range list { st := goSum.status[modSum{m, h}] if (!st.dirty || (st.used && keep[m])) && !sumInWorkspaceModulesLocked(m) { diff --git a/src/cmd/go/testdata/script/mod_tidy_duplicates.txt b/src/cmd/go/testdata/script/mod_tidy_duplicates.txt new file mode 100644 index 0000000000..d454c8dc82 --- /dev/null +++ b/src/cmd/go/testdata/script/mod_tidy_duplicates.txt @@ -0,0 +1,38 @@ +env GO111MODULE=on + +# Regression test for golang.org/issue/28456: +# 'go mod tidy' should not leave duplicate lines when re-writing the file. + +go mod tidy +cmp go.sum golden.sum + +-- go.mod -- +module use + +go 1.16 + +require rsc.io/quote v1.5.2 + +-- go.sum -- +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64= +rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY= +-- golden.sum -- +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw= +golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0= +rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0= +rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII= +rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= +rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64= +rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY= +-- main.go -- +package use + +import _ "rsc.io/quote" From ec58e3f3271de385cf976a805e611d3da09c3a0e Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Fri, 17 Jun 2022 15:19:59 -0700 Subject: [PATCH 09/38] test: add regress test for #53419 This currently works with GOEXPERIMENT=unified. Add a regress test to make sure it stays that way. Updates #53419. Change-Id: I2ea1f9039c59807fbd497d69a0420771f8d6d035 Reviewed-on: https://go-review.googlesource.com/c/go/+/413014 Run-TryBot: Matthew Dempsky Auto-Submit: Matthew Dempsky Reviewed-by: Robert Griesemer TryBot-Result: Gopher Robot --- src/go/internal/gcimporter/gcimporter_test.go | 1 + test/run.go | 1 + test/typeparam/issue53419.go | 28 +++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 test/typeparam/issue53419.go diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 6dced31ffb..9aca6216a7 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -177,6 +177,7 @@ func TestImportTypeparamTests(t *testing.T) { "equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this. "nested.go": "fails to compile", // TODO(rfindley): investigate this. "issue50417.go": "inconsistent interface member sorting", + "issue53419.go": "fails to compile", } for _, entry := range list { diff --git a/test/run.go b/test/run.go index cb1622ccc9..8934e23b38 100644 --- a/test/run.go +++ b/test/run.go @@ -1966,6 +1966,7 @@ var types2Failures32Bit = setOf( var go118Failures = setOf( "typeparam/nested.go", // 1.18 compiler doesn't support function-local types with generics "typeparam/issue51521.go", // 1.18 compiler produces bad panic message and link error + "typeparam/issue53419.go", // 1.18 compiler mishandles generic selector resolution ) // In all of these cases, the 1.17 compiler reports reasonable errors, but either the diff --git a/test/typeparam/issue53419.go b/test/typeparam/issue53419.go new file mode 100644 index 0000000000..62a226ff9f --- /dev/null +++ b/test/typeparam/issue53419.go @@ -0,0 +1,28 @@ +// run + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type T1 struct{} +type T2 struct{} +type Both struct { + T1 + T2 +} + +func (T1) m() { panic("FAIL") } +func (T2) m() { panic("FAIL") } +func (Both) m() {} + +func f[T interface{ m() }](c T) { + c.m() +} + +func main() { + var b Both + b.m() + f(b) +} From 527ace0ffa81d59698d3a78ac3545de7295ea76b Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 16 Jun 2022 23:04:25 +0700 Subject: [PATCH 10/38] cmd/compile: skip substituting closures in unsafe builtins arguments For unsafe.{Alignof,Offsetof,Sizeof}, subster will transform them them to OLITERAL nodes, and discard their arguments. However, any closure in their children nodes were already processed and added to declaration queue. Thus, we lack of information for generating instantiation for the closure. To fix it, just skip substituting the closures if we are going to edit the children nodes of unsafe builtins. Fixes #53390 Change-Id: Ia815cd05af9dc0491f10faac4399f378ac53dec6 Reviewed-on: https://go-review.googlesource.com/c/go/+/412794 Reviewed-by: Keith Randall TryBot-Result: Gopher Robot Reviewed-by: Keith Randall Run-TryBot: Cuong Manh Le Reviewed-by: Matthew Dempsky --- src/cmd/compile/internal/noder/stencil.go | 27 ++++++++++++++++++----- test/typeparam/issue53390.go | 20 +++++++++++++++++ 2 files changed, 42 insertions(+), 5 deletions(-) create mode 100644 test/typeparam/issue53390.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 3f12aa3cbd..eeb503811c 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -721,11 +721,12 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe // Struct containing info needed for doing the substitution as we create the // instantiation of a generic function with specified type arguments. type subster struct { - g *genInst - isMethod bool // If a method is being instantiated - newf *ir.Func // Func node for the new stenciled function - ts typecheck.Tsubster - info *instInfo // Place to put extra info in the instantiation + g *genInst + isMethod bool // If a method is being instantiated + newf *ir.Func // Func node for the new stenciled function + ts typecheck.Tsubster + info *instInfo // Place to put extra info in the instantiation + skipClosure bool // Skip substituting closures // Map from non-nil, non-ONAME node n to slice of all m, where m.Defn = n defnMap map[ir.Node][]**ir.Name @@ -978,7 +979,20 @@ func (subst *subster) node(n ir.Node) ir.Node { } } + old := subst.skipClosure + // For unsafe.{Alignof,Offsetof,Sizeof}, subster will transform them to OLITERAL nodes, + // and discard their arguments. However, their children nodes were already process before, + // thus if they contain any closure, the closure was still be added to package declarations + // queue for processing later. Thus, genInst will fail to generate instantiation for the + // closure because of lacking dictionary information, see issue #53390. + if call, ok := m.(*ir.CallExpr); ok && call.X.Op() == ir.ONAME { + switch call.X.Name().BuiltinOp { + case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: + subst.skipClosure = true + } + } ir.EditChildren(m, edit) + subst.skipClosure = old m.SetTypecheck(1) @@ -1123,6 +1137,9 @@ func (subst *subster) node(n ir.Node) ir.Node { } case ir.OCLOSURE: + if subst.skipClosure { + break + } // We're going to create a new closure from scratch, so clear m // to avoid using the ir.Copy by accident until we reassign it. m = nil diff --git a/test/typeparam/issue53390.go b/test/typeparam/issue53390.go new file mode 100644 index 0000000000..52098c520b --- /dev/null +++ b/test/typeparam/issue53390.go @@ -0,0 +1,20 @@ +// compile + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +import "unsafe" + +func F[T any](v T) uintptr { + return unsafe.Alignof(func() T { + func(any) {}(struct{ _ T }{}) + return v + }()) +} + +func f() { + F(0) +} From 3fcbfb07a82c5332e6b50cddba333af6e6e3e488 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 20 Jun 2022 11:42:07 +0200 Subject: [PATCH 11/38] doc/go1.19: fix HTML validation issues Avoid duplicating tag ID runtime and remove a superflous tag. Found by https://validator.w3.org Change-Id: I9c84b8257acbb6d3d6817192bb8d355207944b9a Reviewed-on: https://go-review.googlesource.com/c/go/+/413254 Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Dmitri Shuralyov Run-TryBot: Ian Lance Taylor --- doc/go1.19.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/go1.19.html b/doc/go1.19.html index 50bc973c13..4495c1d3e0 100644 --- a/doc/go1.19.html +++ b/doc/go1.19.html @@ -741,7 +741,7 @@ as well as support for rendering them to HTML, Markdown, and text. -
runtime
+
runtime

The GOROOT function now returns the empty string @@ -847,7 +847,6 @@ as well as support for rendering them to HTML, Markdown, and text. but often easier to use: it returns an additional boolean reporting whether an equal value was found.

-
strconv
From 19ed442807499080cf9c31ac883d4195db5415c9 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 21 Jun 2022 07:15:33 -0700 Subject: [PATCH 12/38] test: add regress test for #53477 This test already passes for GOEXPERIMENT=unified; add regress test to ensure it stays that way. Updates #53477. Change-Id: Ib7aa7428260595077052207899edcc044a6ab1c8 Reviewed-on: https://go-review.googlesource.com/c/go/+/413394 Run-TryBot: Matthew Dempsky Auto-Submit: Matthew Dempsky Reviewed-by: David Chase --- src/go/internal/gcimporter/gcimporter_test.go | 1 + test/run.go | 1 + test/typeparam/issue53477.go | 34 +++++++++++++++++++ 3 files changed, 36 insertions(+) create mode 100644 test/typeparam/issue53477.go diff --git a/src/go/internal/gcimporter/gcimporter_test.go b/src/go/internal/gcimporter/gcimporter_test.go index 9aca6216a7..b32de17910 100644 --- a/src/go/internal/gcimporter/gcimporter_test.go +++ b/src/go/internal/gcimporter/gcimporter_test.go @@ -178,6 +178,7 @@ func TestImportTypeparamTests(t *testing.T) { "nested.go": "fails to compile", // TODO(rfindley): investigate this. "issue50417.go": "inconsistent interface member sorting", "issue53419.go": "fails to compile", + "issue53477.go": "fails to compile", } for _, entry := range list { diff --git a/test/run.go b/test/run.go index 8934e23b38..224d24db90 100644 --- a/test/run.go +++ b/test/run.go @@ -1967,6 +1967,7 @@ var go118Failures = setOf( "typeparam/nested.go", // 1.18 compiler doesn't support function-local types with generics "typeparam/issue51521.go", // 1.18 compiler produces bad panic message and link error "typeparam/issue53419.go", // 1.18 compiler mishandles generic selector resolution + "typeparam/issue53477.go", // 1.18 compiler mishandles generic interface-interface comparisons from value switch statements ) // In all of these cases, the 1.17 compiler reports reasonable errors, but either the diff --git a/test/typeparam/issue53477.go b/test/typeparam/issue53477.go new file mode 100644 index 0000000000..d128a7e848 --- /dev/null +++ b/test/typeparam/issue53477.go @@ -0,0 +1,34 @@ +// run + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test that generic interface-interface comparisons resulting from +// value switch statements are handled correctly. + +package main + +func main() { + f[X](0) +} + +type Mer[T any] interface{ M(T) } +type MNer[T any] interface { + Mer[T] + N() +} + +type X int + +func (X) M(X) {} +func (X) N() {} + +func f[T MNer[T]](t T) { + switch Mer[T](t) { + case MNer[T](t): + // ok + default: + panic("FAIL") + } +} From c2d373d5d1802d7479f3c81dcf01d41bef3646dd Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Mon, 20 Jun 2022 17:06:09 -0700 Subject: [PATCH 13/38] cmd/compile: allow 128-bit values to be spilled We sometimes use 16-byte load+store to move values around in memory. In rare circumstances, the loaded value must be spilled because the store can't happen yet. In that case, we need to be able to spill the 16-byte value. Fixes #53454 Change-Id: I09fd08e11a63c6ba3ef781d3f5ede237e9b0132e Reviewed-on: https://go-review.googlesource.com/c/go/+/413294 Reviewed-by: Keith Randall TryBot-Result: Gopher Robot Reviewed-by: David Chase Run-TryBot: Keith Randall Reviewed-by: Keith Randall --- src/cmd/compile/internal/amd64/ssa.go | 2 + src/cmd/compile/internal/dwarfgen/dwarf.go | 5 ++ src/cmd/compile/internal/types/size.go | 6 ++ src/cmd/compile/internal/types/type.go | 5 ++ test/fixedbugs/issue53454.go | 89 ++++++++++++++++++++++ 5 files changed, 107 insertions(+) create mode 100644 test/fixedbugs/issue53454.go diff --git a/src/cmd/compile/internal/amd64/ssa.go b/src/cmd/compile/internal/amd64/ssa.go index c9667bd04a..0a95aaabd7 100644 --- a/src/cmd/compile/internal/amd64/ssa.go +++ b/src/cmd/compile/internal/amd64/ssa.go @@ -78,6 +78,8 @@ func storeByType(t *types.Type) obj.As { return x86.AMOVL case 8: return x86.AMOVQ + case 16: + return x86.AMOVUPS } } panic(fmt.Sprintf("bad store type %v", t)) diff --git a/src/cmd/compile/internal/dwarfgen/dwarf.go b/src/cmd/compile/internal/dwarfgen/dwarf.go index f84368ece3..4bbc04826a 100644 --- a/src/cmd/compile/internal/dwarfgen/dwarf.go +++ b/src/cmd/compile/internal/dwarfgen/dwarf.go @@ -91,6 +91,11 @@ func Info(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.Scope, continue } apdecls = append(apdecls, n) + if n.Type().Kind() == types.TSSA { + // Can happen for TypeInt128 types. This only happens for + // spill locations, so not a huge deal. + continue + } fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type())) } } diff --git a/src/cmd/compile/internal/types/size.go b/src/cmd/compile/internal/types/size.go index a5a5c0b5b1..68b9ac3ff3 100644 --- a/src/cmd/compile/internal/types/size.go +++ b/src/cmd/compile/internal/types/size.go @@ -590,6 +590,12 @@ func PtrDataSize(t *Type) int64 { } return 0 + case TSSA: + if t != TypeInt128 { + base.Fatalf("PtrDataSize: unexpected ssa type %v", t) + } + return 0 + default: base.Fatalf("PtrDataSize: unexpected type, %v", t) return 0 diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 1ea239ea32..9e229a59c6 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -1705,6 +1705,11 @@ var ( TypeResultMem = newResults([]*Type{TypeMem}) ) +func init() { + TypeInt128.width = 16 + TypeInt128.align = 8 +} + // NewNamed returns a new named type for the given type name. obj should be an // ir.Name. The new type is incomplete (marked as TFORW kind), and the underlying // type should be set later via SetUnderlying(). References to the type are diff --git a/test/fixedbugs/issue53454.go b/test/fixedbugs/issue53454.go new file mode 100644 index 0000000000..8b16d81839 --- /dev/null +++ b/test/fixedbugs/issue53454.go @@ -0,0 +1,89 @@ +// compile + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type T1 struct { + A T5 + B T2 + C T7 + D T4 +} + +type T2 struct { + T3 + A float64 + E float64 + C float64 +} + +type T3 struct { + F float64 + G float64 + H float64 + I float64 + J float64 + K float64 + L float64 +} + +type T4 struct { + M float64 + N float64 + O float64 + P float64 +} + +type T5 struct { + Q float64 + R float64 + S float64 + T float64 + U float64 + V float64 +} + +type T6 struct { + T9 + C T10 +} + +type T7 struct { + T10 + T11 +} + +type T8 struct { + T9 + C T7 +} + +type T9 struct { + A T5 + B T3 + D T4 +} + +type T10 struct { + W float64 +} + +type T11 struct { + X float64 + Y float64 +} + +func MainTest(x T1, y T8, z T6) float64 { + return Test(x.B, x.A, x.D, x.C, y.B, y.A, y.D, y.C, z.B, z.A, z.D, + T7{ + T10: T10{ + W: z.C.W, + }, + T11: T11{}, + }, + ) +} +func Test(a T2, b T5, c T4, d T7, e T3, f T5, g T4, h T7, i T3, j T5, k T4, l T7) float64 From 530511bacccdea0bb8a0fec644887c2613535c50 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 16 Jun 2022 18:02:11 -0400 Subject: [PATCH 14/38] cmd/go/internal/modindex: avoid walking modules when not needed Due to a missed condition in CL 412394, we were walking all modules (instead of just the ones contained in GOROOT) at each invocation of a devel version of cmd/go. Moreover, while we were running cmd/go tests, we were re-walking GOROOT at each 'go' invocation in the test even though we expect GOROOT to be stable within a test run. This change always avoids walking non-GOROOT modules, and also adds a salt (configurable via GODEBUG) and uses it to avoid walking GOROOT modules when GOROOT is known to be stable (such as over the course of a 'cmd/go' test run). This should fix the cmd/go test timeouts that are currently occurring on the dragonfly-amd64 builder, such as this one: https://build.golang.org/log/21c01c3ae5490d387d84abeaf872b3a0a76ab8e5 Updates #53290. Change-Id: Ic807d215831a3cd21c63e0bccd3d7acd10d8f2b7 Reviewed-on: https://go-review.googlesource.com/c/go/+/412779 TryBot-Result: Gopher Robot Run-TryBot: Bryan Mills Auto-Submit: Bryan Mills Reviewed-by: Michael Matloob --- src/cmd/go/go_test.go | 14 +++++++++ src/cmd/go/internal/modindex/read.go | 44 ++++++++++++++-------------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index b39a62f3e4..bbcecf2b2e 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -18,6 +18,7 @@ import ( "io" "io/fs" "log" + "math/rand" "os" "os/exec" "path/filepath" @@ -128,6 +129,19 @@ func TestMain(m *testing.M) { } os.Setenv("CMDGO_TEST_RUN_MAIN", "true") + if strings.HasPrefix(runtime.Version(), "devel ") && godebug.Get("goindexsalt") == "" { + // We're going to execute a lot of cmd/go tests, so set a consistent salt + // via GODEBUG so that the modindex package can avoid walking an entire + // GOROOT module whenever it tries to use an index for that module. + indexSalt := rand.Int63() + v := os.Getenv("GODEBUG") + if v == "" { + os.Setenv("GODEBUG", fmt.Sprintf("goindexsalt=%d", indexSalt)) + } else { + os.Setenv("GODEBUG", fmt.Sprintf("%s,goindexsalt=%d", v, indexSalt)) + } + } + // $GO_GCFLAGS a compiler debug flag known to cmd/dist, make.bash, etc. // It is not a standard go command flag; use os.Getenv, not cfg.Getenv. if os.Getenv("GO_GCFLAGS") != "" { diff --git a/src/cmd/go/internal/modindex/read.go b/src/cmd/go/internal/modindex/read.go index ffa091df41..e5761af679 100644 --- a/src/cmd/go/internal/modindex/read.go +++ b/src/cmd/go/internal/modindex/read.go @@ -12,11 +12,11 @@ import ( "go/build" "go/build/constraint" "go/token" + "internal/godebug" "internal/goroot" "internal/unsafeheader" "io/fs" "math" - "os" "path" "path/filepath" "runtime" @@ -39,15 +39,7 @@ import ( // It will be removed before the release. // TODO(matloob): Remove enabled once we have more confidence on the // module index. -var enabled = func() bool { - debug := strings.Split(os.Getenv("GODEBUG"), ",") - for _, f := range debug { - if f == "goindex=0" { - return false - } - } - return true -}() +var enabled bool = godebug.Get("goindex") != "0" // ModuleIndex represents and encoded module index file. It is used to // do the equivalent of build.Import of packages in the module and answer other @@ -61,26 +53,34 @@ type ModuleIndex struct { var fcache par.Cache +var salt = godebug.Get("goindexsalt") + func moduleHash(modroot string, ismodcache bool) (cache.ActionID, error) { // We expect modules stored within the module cache to be checksummed and - // immutable, and we expect released Go modules to change only infrequently - // (when the Go version changes). - if !ismodcache || !str.HasFilePathPrefix(modroot, cfg.GOROOT) { + // immutable, and we expect released modules within GOROOT to change only + // infrequently (when the Go version changes). + if !ismodcache && !str.HasFilePathPrefix(modroot, cfg.GOROOT) { + // The contents of this module may change over time. We don't want to pay + // the cost to detect changes and re-index whenever they occur, so just + // don't index it at all. return cache.ActionID{}, ErrNotIndexed } h := cache.NewHash("moduleIndex") - fmt.Fprintf(h, "module index %s %s %v\n", runtime.Version(), indexVersion, modroot) + fmt.Fprintf(h, "module index %s %s %s %v\n", runtime.Version(), salt, indexVersion, modroot) - if strings.HasPrefix(runtime.Version(), "devel ") { + if str.HasFilePathPrefix(modroot, cfg.GOROOT) && strings.HasPrefix(runtime.Version(), "devel ") && salt == "" { // This copy of the standard library is a development version, not a - // release. It could be based on a Git commit (like "devel go1.19-2a78e8afc0 - // Wed Jun 15 00:06:24 2022 +0000") with or without changes on top of that - // commit, or it could be completly artificial due to lacking a `git` binary - // (like "devel gomote.XXXXX", as synthesized by "gomote push" as of - // 2022-06-15). Compute an inexpensive hash of its files using mtimes so - // that during development we can continue to exercise the logic for cached - // GOROOT indexes. + // release. It could be based on a Git commit (like + // "devel go1.19-2a78e8afc0 Wed Jun 15 00:06:24 2022 +0000") with or + // without changes on top of that commit, or it could be completly + // artificial due to lacking a `git` binary (like "devel gomote.XXXXX", as + // synthesized by "gomote push" as of 2022-06-15). + // + // If the user provided a unique salt via GODEBUG, we can trust that it is + // unique and just go with it. Otherwise, we compute an inexpensive hash of + // its files using mtimes so that during development we can continue to + // exercise the logic for cached GOROOT indexes. // // mtimes may be granular, imprecise, and loosely updated (see // https://apenwarr.ca/log/20181113), but we don't expect Go contributors to From 4b236b45d0bb659a447dcfc02ebd431587b52e2b Mon Sep 17 00:00:00 2001 From: Michael Anthony Knyszek Date: Fri, 17 Jun 2022 19:56:27 +0000 Subject: [PATCH 15/38] runtime: convert flaky semaphore linearity test into benchmark Also, add a benchmark for another case that was originally tested. Also also, remove all the dead code this now creates. Fixes #53428. Change-Id: Idbba88d3d31d38a8854fd5ed99001e394da27300 Reviewed-on: https://go-review.googlesource.com/c/go/+/412878 TryBot-Result: Gopher Robot Reviewed-by: Bryan Mills Reviewed-by: Michael Pratt Run-TryBot: Michael Knyszek Auto-Submit: Michael Knyszek --- src/go/build/deps_test.go | 5 +- src/internal/testenv/testenv.go | 65 ---------- src/internal/testmath/bench.go | 38 ------ src/internal/testmath/ttest.go | 213 -------------------------------- src/runtime/sema.go | 4 +- src/runtime/sema_test.go | 87 ++++++++----- 6 files changed, 58 insertions(+), 354 deletions(-) delete mode 100644 src/internal/testmath/bench.go delete mode 100644 src/internal/testmath/ttest.go diff --git a/src/go/build/deps_test.go b/src/go/build/deps_test.go index 1ddf8f69be..5b971b93e2 100644 --- a/src/go/build/deps_test.go +++ b/src/go/build/deps_test.go @@ -543,10 +543,7 @@ var depsRules = ` internal/fuzz, internal/testlog, runtime/pprof, regexp < testing/internal/testdeps; - MATH, errors, testing - < internal/testmath; - - OS, flag, testing, internal/cfg, internal/testmath + OS, flag, testing, internal/cfg < internal/testenv; OS, encoding/base64 diff --git a/src/internal/testenv/testenv.go b/src/internal/testenv/testenv.go index b7cb95063b..1feb630cf5 100644 --- a/src/internal/testenv/testenv.go +++ b/src/internal/testenv/testenv.go @@ -16,7 +16,6 @@ import ( "flag" "fmt" "internal/cfg" - "internal/testmath" "os" "os/exec" "path/filepath" @@ -464,67 +463,3 @@ func RunWithTimeout(t testing.TB, cmd *exec.Cmd) ([]byte, error) { return b.Bytes(), err } - -// CheckLinear checks if the function produced by f scales linearly. -// -// f must accept a scale factor which causes the input to the function it -// produces to scale by that factor. -func CheckLinear(t *testing.T, f func(scale float64) func(*testing.B)) { - MustHaveExec(t) - - if os.Getenv("GO_PERF_UNIT_TEST") == "" { - // Invoke the same test as a subprocess with the GO_PERF_UNIT_TEST environment variable set. - // We create a subprocess for two reasons: - // - // 1. There's no other way to set the benchmarking parameters of testing.Benchmark. - // 2. Since we're effectively running a performance test, running in a subprocess grants - // us a little bit more isolation than using the same process. - // - // As an alternative, we could fairly easily reimplement the timing code in testing.Benchmark, - // but a subprocess is just as easy to create. - - selfCmd := CleanCmdEnv(exec.Command(os.Args[0], "-test.v", fmt.Sprintf("-test.run=^%s$", t.Name()), "-test.benchtime=1x")) - selfCmd.Env = append(selfCmd.Env, "GO_PERF_UNIT_TEST=1") - output, err := RunWithTimeout(t, selfCmd) - if err != nil { - t.Error(err) - t.Logf("--- subprocess output ---\n%s", string(output)) - } - if bytes.Contains(output, []byte("insignificant result")) { - t.Skip("insignificant result") - } - return - } - - // Pick a reasonable sample count. - const count = 10 - - // Collect samples for scale factor 1. - x1 := make([]testing.BenchmarkResult, 0, count) - for i := 0; i < count; i++ { - x1 = append(x1, testing.Benchmark(f(1.0))) - } - - // Collect samples for scale factor 2. - x2 := make([]testing.BenchmarkResult, 0, count) - for i := 0; i < count; i++ { - x2 = append(x2, testing.Benchmark(f(2.0))) - } - - // Run a t-test on the results. - r1 := testmath.BenchmarkResults(x1) - r2 := testmath.BenchmarkResults(x2) - result, err := testmath.TwoSampleWelchTTest(r1, r2, testmath.LocationDiffers) - if err != nil { - t.Fatalf("failed to run t-test: %v", err) - } - if result.P > 0.005 { - // Insignificant result. - t.Skip("insignificant result") - } - - // Let ourselves be within 3x; 2x is too strict. - if m1, m2 := r1.Mean(), r2.Mean(); 3.0*m1 < m2 { - t.Fatalf("failure to scale linearly: µ_1=%s µ_2=%s p=%f", time.Duration(m1), time.Duration(m2), result.P) - } -} diff --git a/src/internal/testmath/bench.go b/src/internal/testmath/bench.go deleted file mode 100644 index 6f034b4685..0000000000 --- a/src/internal/testmath/bench.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package testmath - -import ( - "math" - "testing" - "time" -) - -type BenchmarkResults []testing.BenchmarkResult - -func (b BenchmarkResults) Weight() float64 { - var weight int - for _, r := range b { - weight += r.N - } - return float64(weight) -} - -func (b BenchmarkResults) Mean() float64 { - var dur time.Duration - for _, r := range b { - dur += r.T * time.Duration(r.N) - } - return float64(dur) / b.Weight() -} - -func (b BenchmarkResults) Variance() float64 { - var num float64 - mean := b.Mean() - for _, r := range b { - num += math.Pow(float64(r.T)-mean, 2) * float64(r.N) - } - return float64(num) / b.Weight() -} diff --git a/src/internal/testmath/ttest.go b/src/internal/testmath/ttest.go deleted file mode 100644 index d15d2deebb..0000000000 --- a/src/internal/testmath/ttest.go +++ /dev/null @@ -1,213 +0,0 @@ -// Copyright 2022 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -package testmath - -import ( - "errors" - "math" -) - -// A TTestSample is a sample that can be used for a one or two sample -// t-test. -type TTestSample interface { - Weight() float64 - Mean() float64 - Variance() float64 -} - -var ( - ErrSampleSize = errors.New("sample is too small") - ErrZeroVariance = errors.New("sample has zero variance") - ErrMismatchedSamples = errors.New("samples have different lengths") -) - -// TwoSampleWelchTTest performs a two-sample (unpaired) Welch's t-test -// on samples x1 and x2. This t-test does not assume the distributions -// have equal variance. -func TwoSampleWelchTTest(x1, x2 TTestSample, alt LocationHypothesis) (*TTestResult, error) { - n1, n2 := x1.Weight(), x2.Weight() - if n1 <= 1 || n2 <= 1 { - // TODO: Can we still do this with n == 1? - return nil, ErrSampleSize - } - v1, v2 := x1.Variance(), x2.Variance() - if v1 == 0 && v2 == 0 { - return nil, ErrZeroVariance - } - - dof := math.Pow(v1/n1+v2/n2, 2) / - (math.Pow(v1/n1, 2)/(n1-1) + math.Pow(v2/n2, 2)/(n2-1)) - s := math.Sqrt(v1/n1 + v2/n2) - t := (x1.Mean() - x2.Mean()) / s - return newTTestResult(int(n1), int(n2), t, dof, alt), nil -} - -// A TTestResult is the result of a t-test. -type TTestResult struct { - // N1 and N2 are the sizes of the input samples. For a - // one-sample t-test, N2 is 0. - N1, N2 int - - // T is the value of the t-statistic for this t-test. - T float64 - - // DoF is the degrees of freedom for this t-test. - DoF float64 - - // AltHypothesis specifies the alternative hypothesis tested - // by this test against the null hypothesis that there is no - // difference in the means of the samples. - AltHypothesis LocationHypothesis - - // P is p-value for this t-test for the given null hypothesis. - P float64 -} - -func newTTestResult(n1, n2 int, t, dof float64, alt LocationHypothesis) *TTestResult { - dist := TDist{dof} - var p float64 - switch alt { - case LocationDiffers: - p = 2 * (1 - dist.CDF(math.Abs(t))) - case LocationLess: - p = dist.CDF(t) - case LocationGreater: - p = 1 - dist.CDF(t) - } - return &TTestResult{N1: n1, N2: n2, T: t, DoF: dof, AltHypothesis: alt, P: p} -} - -// A LocationHypothesis specifies the alternative hypothesis of a -// location test such as a t-test or a Mann-Whitney U-test. The -// default (zero) value is to test against the alternative hypothesis -// that they differ. -type LocationHypothesis int - -const ( - // LocationLess specifies the alternative hypothesis that the - // location of the first sample is less than the second. This - // is a one-tailed test. - LocationLess LocationHypothesis = -1 - - // LocationDiffers specifies the alternative hypothesis that - // the locations of the two samples are not equal. This is a - // two-tailed test. - LocationDiffers LocationHypothesis = 0 - - // LocationGreater specifies the alternative hypothesis that - // the location of the first sample is greater than the - // second. This is a one-tailed test. - LocationGreater LocationHypothesis = 1 -) - -// A TDist is a Student's t-distribution with V degrees of freedom. -type TDist struct { - V float64 -} - -// PDF returns the value at x of the probability distribution function for the -// distribution. -func (t TDist) PDF(x float64) float64 { - return math.Exp(lgamma((t.V+1)/2)-lgamma(t.V/2)) / - math.Sqrt(t.V*math.Pi) * math.Pow(1+(x*x)/t.V, -(t.V+1)/2) -} - -// CDF returns the value at x of the cumulative distribution function for the -// distribution. -func (t TDist) CDF(x float64) float64 { - if x == 0 { - return 0.5 - } else if x > 0 { - return 1 - 0.5*betaInc(t.V/(t.V+x*x), t.V/2, 0.5) - } else if x < 0 { - return 1 - t.CDF(-x) - } else { - return math.NaN() - } -} - -func (t TDist) Bounds() (float64, float64) { - return -4, 4 -} - -func lgamma(x float64) float64 { - y, _ := math.Lgamma(x) - return y -} - -// betaInc returns the value of the regularized incomplete beta -// function Iₓ(a, b) = 1 / B(a, b) * ∫₀ˣ tᵃ⁻¹ (1-t)ᵇ⁻¹ dt. -// -// This is not to be confused with the "incomplete beta function", -// which can be computed as BetaInc(x, a, b)*Beta(a, b). -// -// If x < 0 or x > 1, returns NaN. -func betaInc(x, a, b float64) float64 { - // Based on Numerical Recipes in C, section 6.4. This uses the - // continued fraction definition of I: - // - // (xᵃ*(1-x)ᵇ)/(a*B(a,b)) * (1/(1+(d₁/(1+(d₂/(1+...)))))) - // - // where B(a,b) is the beta function and - // - // d_{2m+1} = -(a+m)(a+b+m)x/((a+2m)(a+2m+1)) - // d_{2m} = m(b-m)x/((a+2m-1)(a+2m)) - if x < 0 || x > 1 { - return math.NaN() - } - bt := 0.0 - if 0 < x && x < 1 { - // Compute the coefficient before the continued - // fraction. - bt = math.Exp(lgamma(a+b) - lgamma(a) - lgamma(b) + - a*math.Log(x) + b*math.Log(1-x)) - } - if x < (a+1)/(a+b+2) { - // Compute continued fraction directly. - return bt * betacf(x, a, b) / a - } else { - // Compute continued fraction after symmetry transform. - return 1 - bt*betacf(1-x, b, a)/b - } -} - -// betacf is the continued fraction component of the regularized -// incomplete beta function Iₓ(a, b). -func betacf(x, a, b float64) float64 { - const maxIterations = 200 - const epsilon = 3e-14 - - raiseZero := func(z float64) float64 { - if math.Abs(z) < math.SmallestNonzeroFloat64 { - return math.SmallestNonzeroFloat64 - } - return z - } - - c := 1.0 - d := 1 / raiseZero(1-(a+b)*x/(a+1)) - h := d - for m := 1; m <= maxIterations; m++ { - mf := float64(m) - - // Even step of the recurrence. - numer := mf * (b - mf) * x / ((a + 2*mf - 1) * (a + 2*mf)) - d = 1 / raiseZero(1+numer*d) - c = raiseZero(1 + numer/c) - h *= d * c - - // Odd step of the recurrence. - numer = -(a + mf) * (a + b + mf) * x / ((a + 2*mf) * (a + 2*mf + 1)) - d = 1 / raiseZero(1+numer*d) - c = raiseZero(1 + numer/c) - hfac := d * c - h *= hfac - - if math.Abs(hfac-1) < epsilon { - return h - } - } - panic("betainc: a or b too big; failed to converge") -} diff --git a/src/runtime/sema.go b/src/runtime/sema.go index c7a1a76e28..39935f70a9 100644 --- a/src/runtime/sema.go +++ b/src/runtime/sema.go @@ -35,8 +35,8 @@ import ( // where n is the number of distinct addresses with goroutines blocked // on them that hash to the given semaRoot. // See golang.org/issue/17953 for a program that worked badly -// before we introduced the second level of list, and TestSemTableOneAddrCollisionLinear -// for a test that exercises this. +// before we introduced the second level of list, and +// BenchmarkSemTable/OneAddrCollision/* for a benchmark that exercises this. type semaRoot struct { lock mutex treap *sudog // root of balanced tree of unique waiters. diff --git a/src/runtime/sema_test.go b/src/runtime/sema_test.go index f3e95d10be..9943d2ed39 100644 --- a/src/runtime/sema_test.go +++ b/src/runtime/sema_test.go @@ -5,7 +5,7 @@ package runtime_test import ( - "internal/testenv" + "fmt" . "runtime" "sync" "sync/atomic" @@ -103,45 +103,68 @@ func testSemaHandoff() bool { return res == 1 // did the waiter run first? } -func TestSemTableOneAddrCollisionLinear(t *testing.T) { - testenv.CheckLinear(t, func(scale float64) func(*testing.B) { - n := int(1000 * scale) - return func(b *testing.B) { +func BenchmarkSemTable(b *testing.B) { + for _, n := range []int{1000, 2000, 4000, 8000} { + b.Run(fmt.Sprintf("OneAddrCollision/n=%d", n), func(b *testing.B) { tab := Escape(new(SemTable)) u := make([]uint32, SemTableSize+1) b.ResetTimer() - // Simulate two locks colliding on the same semaRoot. - // - // Specifically enqueue all the waiters for the first lock, - // then all the waiters for the second lock. - // - // Then, dequeue all the waiters from the first lock, then - // the second. - // - // Each enqueue/dequeue operation should be O(1), because - // there are exactly 2 locks. This could be O(n) if all - // the waiters for both locks are on the same list, as it - // once was. - for i := 0; i < n; i++ { - if i < n/2 { - tab.Enqueue(&u[0]) - } else { - tab.Enqueue(&u[SemTableSize]) + for j := 0; j < b.N; j++ { + // Simulate two locks colliding on the same semaRoot. + // + // Specifically enqueue all the waiters for the first lock, + // then all the waiters for the second lock. + // + // Then, dequeue all the waiters from the first lock, then + // the second. + // + // Each enqueue/dequeue operation should be O(1), because + // there are exactly 2 locks. This could be O(n) if all + // the waiters for both locks are on the same list, as it + // once was. + for i := 0; i < n; i++ { + if i < n/2 { + tab.Enqueue(&u[0]) + } else { + tab.Enqueue(&u[SemTableSize]) + } + } + for i := 0; i < n; i++ { + var ok bool + if i < n/2 { + ok = tab.Dequeue(&u[0]) + } else { + ok = tab.Dequeue(&u[SemTableSize]) + } + if !ok { + b.Fatal("failed to dequeue") + } } } - for i := 0; i < n; i++ { - var ok bool - if i < n/2 { - ok = tab.Dequeue(&u[0]) - } else { - ok = tab.Dequeue(&u[SemTableSize]) + }) + b.Run(fmt.Sprintf("ManyAddrCollision/n=%d", n), func(b *testing.B) { + tab := Escape(new(SemTable)) + u := make([]uint32, n*SemTableSize) + + b.ResetTimer() + + for j := 0; j < b.N; j++ { + // Simulate n locks colliding on the same semaRoot. + // + // Each enqueue/dequeue operation should be O(log n), because + // each semaRoot is a tree. This could be O(n) if it was + // some simpler data structure. + for i := 0; i < n; i++ { + tab.Enqueue(&u[i*SemTableSize]) } - if !ok { - b.Fatal("failed to dequeue") + for i := 0; i < n; i++ { + if !tab.Dequeue(&u[i*SemTableSize]) { + b.Fatal("failed to dequeue") + } } } - } - }) + }) + } } From 66685fb7dd72531aed6f1b3f4de43799bb26c052 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Sun, 19 Jun 2022 22:57:10 -0700 Subject: [PATCH 16/38] doc/go1.19: use correct link to sync/atomic docs For #51400 Fixes #53453 Change-Id: Ie11182a16299cf26d03970d6aa9bfe03caa56ea4 Reviewed-on: https://go-review.googlesource.com/c/go/+/413235 TryBot-Result: Gopher Robot Run-TryBot: Ian Lance Taylor Reviewed-by: Dmitri Shuralyov Reviewed-by: Dmitri Shuralyov Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor --- doc/go1.19.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.19.html b/doc/go1.19.html index 4495c1d3e0..b323b0d182 100644 --- a/doc/go1.19.html +++ b/doc/go1.19.html @@ -35,7 +35,7 @@ Do not send CLs removing the interior tags from such phrases. the memory model used by C, C++, Java, JavaScript, Rust, and Swift. Go only provides sequentially consistent atomics, not any of the more relaxed forms found in other languages. Along with the memory model update, - Go 1.19 introduces new types in the sync/atomic package + Go 1.19 introduces new types in the sync/atomic package that make it easier to use atomic values, such as atomic.Int64 and From ab422f2749bc21514cb22d444bae460f5fa22376 Mon Sep 17 00:00:00 2001 From: Rhys Hiltner Date: Tue, 21 Jun 2022 12:28:48 -0700 Subject: [PATCH 17/38] runtime/trace: ignore fallback stacks in test When runtime.sigprof encounters a stack that gentraceback is unable to process, it synthesizes a call stack with a sentinel function (such as runtime._System) at the leaf. The test to confirm that runtime/trace and runtime/pprof have similar views of CPU profile samples has trouble with those stacks. The test confirms that the samples match by confirming that their symbolized forms match, and the symbolization procedure is very different for the two packages. Skip the samples that the CPU profiler's view symbolizes to include one of runtime.sigprof's sentinel functions at the leaf. (The test design expects the CPU profiler to under-report samples relative to the execution tracer.) Fixes #53378 Change-Id: I60c27de4c69b454057d28a3b6e12d70369de4c4f Reviewed-on: https://go-review.googlesource.com/c/go/+/413457 Reviewed-by: Bryan Mills Run-TryBot: Rhys Hiltner TryBot-Result: Gopher Robot Reviewed-by: Michael Pratt --- src/runtime/trace/trace_test.go | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/runtime/trace/trace_test.go b/src/runtime/trace/trace_test.go index b1afd2b8bb..19f7dbe775 100644 --- a/src/runtime/trace/trace_test.go +++ b/src/runtime/trace/trace_test.go @@ -634,15 +634,29 @@ func TestTraceCPUProfile(t *testing.T) { pprofStacks := make(map[string]int) for _, s := range prof.Sample { if s.Label["tracing"] != nil { - samples := int(s.Value[0]) - pprofSamples += samples var fns []string + var leaf string for _, loc := range s.Location { for _, line := range loc.Line { fns = append(fns, fmt.Sprintf("%s:%d", line.Function.Name, line.Line)) + leaf = line.Function.Name } } + // runtime.sigprof synthesizes call stacks when "normal traceback is + // impossible or has failed", using particular placeholder functions + // to represent common failure cases. Look for those functions in + // the leaf position as a sign that the call stack and its + // symbolization are more complex than this test can handle. + // + // TODO: Make the symbolization done by the execution tracer and CPU + // profiler match up even in these harder cases. See #53378. + switch leaf { + case "runtime._System", "runtime._GC", "runtime._ExternalCode", "runtime._VDSO": + continue + } stack := strings.Join(fns, " ") + samples := int(s.Value[0]) + pprofSamples += samples pprofStacks[stack] += samples } } From f2c7e78592973436a55cdfc4bca2fc3bce526cad Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 14 Jun 2022 18:30:44 -0700 Subject: [PATCH 18/38] spec: document operations which accept []byte|string constrained types Pre-1.18, as special cases, the built-in operations append and copy accepted strings as second arguments if the first argument was a byte slice. With Go 1.18, these two built-ins as well as slice expressions rely on the notion of core types in their specification. Because we want to permit slice expressions, append, and copy to operate on (1st or 2nd operands) that are type parameters restricted by []byte | string (and variations thereof), the simple notion of core type is not sufficient for these three operations. (The compiler already permits such more relaxed operations). In the section on core types, add a paragraph and examples introducing the (artificial) core type "bypestring", which describes the core type of type sets whose underlying types are []byte or string. Adjust the rules for slice expressions, append, and copy accordingly. Also (unrelated): Adjust prose in the only paragraph where we used personal speech ("we") to impersonal speech, to match the rest of the spec. Fixes #52859. Change-Id: I1cbda3095a1136fb99334cc3a62a9a349a27ce1e Reviewed-on: https://go-review.googlesource.com/c/go/+/412234 Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Griesemer --- doc/go_spec.html | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index ab172ac40e..3e47ee7bad 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -1811,6 +1811,31 @@ interface{ chan int | chan<- string } // channels have different element interface{ <-chan int | chan<- int } // directional channels have different directions +

+Some operations (slice expressions, +append and copy) +rely on a slightly more loose form of core types which accept byte slices and strings. +Specifically, if there are exactly two types, []byte and string, +which are the underlying types of all types in the type set of interface T, +the core type of T is called bytestring. +

+ +

+Examples of interfaces with bytestring core types: +

+ +
+interface{ int }                          // int (same as ordinary core type)
+interface{ []byte | string }              // bytestring
+interface{ ~[]byte | myString }           // bytestring
+
+ +

+Note that bytestring is not a real type; it cannot be used to declare +variables are compose other types. It exists solely to describe the behavior of some +operations that read from a sequence of bytes, which may be a byte slice or a string. +

+

Type identity

@@ -3837,7 +3862,8 @@ a[low : high]

constructs a substring or slice. The core type of -a must be a string, array, pointer to array, or slice. +a must be a string, array, pointer to array, slice, or a +bytestring. The indices low and high select which elements of operand a appear in the result. The result has indices starting at 0 and length equal to @@ -5469,7 +5495,7 @@ string(runes{0x767d, 0x9d6c, 0x7fd4}) // "\u767d\u9d6c\u7fd4" == "白鵬翔" type myRune rune string([]myRune{0x266b, 0x266c}) // "\u266b\u266c" == "♫♬" -myString([]myRune{0x1F30E}) // "\U0001f30e" == "🌎" +myString([]myRune{0x1f30e}) // "\U0001f30e" == "🌎" @@ -7197,8 +7223,9 @@ The values x are passed to a parameter of type ...E and the respective parameter passing rules apply. As a special case, if the core type of s is []byte, -append also accepts a second argument with core type string -followed by .... This form appends the bytes of the string. +append also accepts a second argument with core type +bytestring followed by .... +This form appends the bytes of the byte slice or string.

@@ -7235,8 +7262,9 @@ with identical element type.
 The number of elements copied is the minimum of
 len(src) and len(dst).
 As a special case, if the destination's core type is []byte,
-copy also accepts a source argument with core type string.
-This form copies the bytes from the string into the byte slice.
+copy also accepts a source argument with core type
+ bytestring.
+This form copies the bytes from the byte slice or string into the byte slice.
 

@@ -7550,7 +7578,7 @@ and the Unicode replacement character U+FFFD.
 

-Assume we have compiled a package containing the package clause +Consider a compiled a package containing the package clause package math, which exports function Sin, and installed the compiled package in the file identified by "lib/math". From b004c739b525d354ea62f5caadd962de4569d96e Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 21 Jun 2022 15:56:16 -0700 Subject: [PATCH 19/38] go/types, types2: fix parameter order dependence in type inference If we have more than two function arguments to a generic function, we may have arguments with named and unnamed types. If that is the case, permutate params and args such that the arguments with named types are first in the list. This way, independent of parameter ordering, the type inference will produce the same result. This extra step is not explicitly outlined in the spec yet but we all agree that (parameter) order independence is an invariant that we should uphold for type inference. As we move towards less operational and more descriptive rules for type inference, we will incorporate this property as well. The actual fix for this bug existed before 1.18 but was not enabled. This CL merely enables the fix (switches a flag) and adjusts some tests. Fixes #43056. Change-Id: Ie4e40cf8438dfd82fa94b78068e4f6f6f53f83e6 Reviewed-on: https://go-review.googlesource.com/c/go/+/413459 Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/infer.go | 7 ++----- .../compile/internal/types2/testdata/examples/functions.go | 2 +- .../internal/types2/testdata/fixedbugs/issue43056.go | 4 ++-- src/go/types/infer.go | 7 ++----- src/go/types/testdata/examples/functions.go | 2 +- src/go/types/testdata/fixedbugs/issue43056.go | 4 ++-- 6 files changed, 10 insertions(+), 16 deletions(-) diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index b0c6a4fcea..8425cd6034 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -128,11 +128,8 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type, // named and unnamed types are passed to parameters with identical type, different types // (named vs underlying) may be inferred depending on the order of the arguments. // By ensuring that named types are seen first, order dependence is avoided and unification - // succeeds where it can. - // - // This code is disabled for now pending decision whether we want to address cases like - // these and make the spec on type inference more complicated (see issue #43056). - const enableArgSorting = false + // succeeds where it can (issue #43056). + const enableArgSorting = true if m := len(args); m >= 2 && enableArgSorting { // Determine indices of arguments with named and unnamed types. var named, unnamed []int diff --git a/src/cmd/compile/internal/types2/testdata/examples/functions.go b/src/cmd/compile/internal/types2/testdata/examples/functions.go index ef8953cb43..d50f79d11f 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/functions.go +++ b/src/cmd/compile/internal/types2/testdata/examples/functions.go @@ -182,7 +182,7 @@ func _() { type myString string var s1 string g3(nil, "1", myString("2"), "3") - g3(&s1, "1", myString /* ERROR does not match */ ("2"), "3") + g3(& /* ERROR does not match */ s1, "1", myString("2"), "3") _ = s1 type myStruct struct{x int} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43056.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43056.go index 35c7ef592d..8ff4e7f9b4 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43056.go +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue43056.go @@ -14,7 +14,7 @@ func _() { var j func(F) f(i, j) - // f(j, i) // disabled for now + f(j, i) } // example from issue @@ -27,5 +27,5 @@ func _() { var j interface{ Equal(I) bool } g(i, j) - // g(j, i) // disabled for now + g(j, i) } diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 1aa2612638..768efbf73b 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -128,11 +128,8 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type, // named and unnamed types are passed to parameters with identical type, different types // (named vs underlying) may be inferred depending on the order of the arguments. // By ensuring that named types are seen first, order dependence is avoided and unification - // succeeds where it can. - // - // This code is disabled for now pending decision whether we want to address cases like - // these and make the spec on type inference more complicated (see issue #43056). - const enableArgSorting = false + // succeeds where it can (issue #43056). + const enableArgSorting = true if m := len(args); m >= 2 && enableArgSorting { // Determine indices of arguments with named and unnamed types. var named, unnamed []int diff --git a/src/go/types/testdata/examples/functions.go b/src/go/types/testdata/examples/functions.go index 0af77267c5..1d30075c7c 100644 --- a/src/go/types/testdata/examples/functions.go +++ b/src/go/types/testdata/examples/functions.go @@ -182,7 +182,7 @@ func _() { type myString string var s1 string g3(nil, "1", myString("2"), "3") - g3(&s1, "1", myString /* ERROR does not match */ ("2"), "3") + g3(& /* ERROR does not match */ s1, "1", myString("2"), "3") type myStruct struct{x int} var s2 myStruct diff --git a/src/go/types/testdata/fixedbugs/issue43056.go b/src/go/types/testdata/fixedbugs/issue43056.go index 35c7ef592d..8ff4e7f9b4 100644 --- a/src/go/types/testdata/fixedbugs/issue43056.go +++ b/src/go/types/testdata/fixedbugs/issue43056.go @@ -14,7 +14,7 @@ func _() { var j func(F) f(i, j) - // f(j, i) // disabled for now + f(j, i) } // example from issue @@ -27,5 +27,5 @@ func _() { var j interface{ Equal(I) bool } g(i, j) - // g(j, i) // disabled for now + g(j, i) } From be0b2a393a5a7297a3c8f42ca7d5ad3e4b15dcbe Mon Sep 17 00:00:00 2001 From: Alan Donovan Date: Fri, 17 Jun 2022 10:32:52 -0400 Subject: [PATCH 20/38] cmd/trace: add basic documentation to main page This change adds rudimentary explanation of the various visualizations to main page of the trace server. There is clearly a vast amount one could write here, especially in the form of tutorials, but I've tried to restrict it to just basic conceptual overview. Change-Id: Id4dfe9d47f9b31ed5f8fe39f8b3a7c60c0ae8d5a Reviewed-on: https://go-review.googlesource.com/c/go/+/412876 Reviewed-by: Michael Pratt Run-TryBot: Alan Donovan TryBot-Result: Gopher Robot --- src/cmd/trace/main.go | 194 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 183 insertions(+), 11 deletions(-) diff --git a/src/cmd/trace/main.go b/src/cmd/trace/main.go index a30db9a012..11804d0b90 100644 --- a/src/cmd/trace/main.go +++ b/src/cmd/trace/main.go @@ -185,23 +185,195 @@ func httpMain(w http.ResponseWriter, r *http.Request) { var templMain = template.Must(template.New("").Parse(` + +

cmd/trace: the Go trace event viewer

+

+ This web server provides various visualizations of an event log gathered during + the execution of a Go program that uses the runtime/trace package. +

+ +

Event timelines for running goroutines

{{if $}} +

+ Large traces are split into multiple sections of equal data size + (not duration) to avoid overwhelming the visualizer. +

+ {{else}} - View trace
+ {{end}} -Goroutine analysis
-Network blocking profile ()
-Synchronization blocking profile ()
-Syscall blocking profile ()
-Scheduler latency profile ()
-User-defined tasks
-User-defined regions
-Minimum mutator utilization
+

+ This view displays a timeline for each of the GOMAXPROCS logical + processors, showing which goroutine (if any) was running on that + logical processor at each moment. + + Each goroutine has an identifying number (e.g. G123), main function, + and color. + + A colored bar represents an uninterrupted span of execution. + + Execution of a goroutine may migrate from one logical processor to another, + causing a single colored bar to be horizontally continuous but + vertically displaced. +

+

+ Clicking on a span reveals information about it, such as its + duration, its causal predecessors and successors, and the stack trace + at the final moment when it yielded the logical processor, for example + because it made a system call or tried to acquire a mutex. + + Directly underneath each bar, a smaller bar or more commonly a fine + vertical line indicates an event occuring during its execution. + Some of these are related to garbage collection; most indicate that + a goroutine yielded its logical processor but then immediately resumed execution + on the same logical processor. Clicking on the event displays the stack trace + at the moment it occurred. +

+

+ The causal relationships between spans of goroutine execution + can be displayed by clicking the Flow Events button at the top. +

+

+ At the top ("STATS"), there are three additional timelines that + display statistical information. + + "Goroutines" is a time series of the count of existing goroutines; + clicking on it displays their breakdown by state at that moment: + running, runnable, or waiting. + + "Heap" is a time series of the amount of heap memory allocated (in orange) + and (in green) the allocation limit at which the next GC cycle will begin. + + "Threads" shows the number of kernel threads in existence: there is + always one kernel thread per logical processor, and additional threads + are created for calls to non-Go code such as a system call or a + function written in C. +

+

+ Above the event trace for the first logical processor are + traces for various runtime-internal events. + + The "GC" bar shows when the garbage collector is running, and in which stage. + Garbage collection may temporarily affect all the logical processors + and the other metrics. + + The "Network", "Timers", and "Syscalls" traces indicate events in + the runtime that cause goroutines to wake up. +

+

+ The visualization allows you to navigate events at scales ranging from several + seconds to a handful of nanoseconds. + + Consult the documentation for the Chromium Trace Event Profiling Tool + for help navigating the view. +

+ + +

+ This view displays information about each set of goroutines that + shares the same main function. + + Clicking on a main function shows links to the four types of + blocking profile (see below) applied to that subset of goroutines. + + It also shows a table of specific goroutine instances, with various + execution statistics and a link to the event timeline for each one. + + The timeline displays only the selected goroutine and any others it + interacts with via block/unblock events. (The timeline is + goroutine-oriented rather than logical processor-oriented.) +

+ +

Profiles

+

+ Each link below displays a global profile in zoomable graph form as + produced by pprof's "web" command. + + In addition there is a link to download the profile for offline + analysis with pprof. + + All four profiles represent causes of delay that prevent a goroutine + from running on a logical processor: because it was waiting for the network, + for a synchronization operation on a mutex or channel, for a system call, + or for a logical processor to become available. +

+ + +

User-defined tasks and regions

+

+ The trace API allows a target program to annotate a region of code + within a goroutine, such as a key function, so that its performance + can be analyzed. + + Log events may be + associated with a region to record progress and relevant values. + + The API also allows annotation of higher-level + tasks, + which may involve work across many goroutines. +

+

+ The links below display, for each region and task, a histogram of its execution times. + + Each histogram bucket contains a sample trace that records the + sequence of events such as goroutine creations, log events, and + subregion start/end times. + + For each task, you can click through to a logical-processor or + goroutine-oriented view showing the tasks and regions on the + timeline. + + Such information may help uncover which steps in a region are + unexpectedly slow, or reveal relationships between the data values + logged in a request and its running time. +

+ + +

Garbage collection metrics

+ +

+ This chart indicates the maximum GC pause time (the largest x value + for which y is zero), and more generally, the fraction of time that + the processors are available to application goroutines ("mutators"), + for any time window of a specified size, in the worst case. +

`)) From 92c9b81447649d5a8ed38ca79b71640c099e0243 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 21 Jun 2022 15:17:22 -0700 Subject: [PATCH 21/38] net: don't set netGo = true on Windows with no cgo Windows can call the C DNS lookup routines even without cgo, so don't force it to use the Go routines in that scenario. No test because the test requires building the tools with CGO_ENABLED=0. For #33097 Fixes #53490 Change-Id: I3595a68e788be0d3bbd1bbd431836aca20a7d757 Reviewed-on: https://go-review.googlesource.com/c/go/+/413458 TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Reviewed-by: Bryan Mills Run-TryBot: Ian Lance Taylor Reviewed-by: Brad Fitzpatrick Run-TryBot: Ian Lance Taylor Auto-Submit: Ian Lance Taylor --- src/net/cgo_stub.go | 2 -- src/net/netgo.go | 6 +++++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/net/cgo_stub.go b/src/net/cgo_stub.go index cc84ca47ae..298d829f6f 100644 --- a/src/net/cgo_stub.go +++ b/src/net/cgo_stub.go @@ -8,8 +8,6 @@ package net import "context" -func init() { netGo = true } - type addrinfoErrno int func (eai addrinfoErrno) Error() string { return "" } diff --git a/src/net/netgo.go b/src/net/netgo.go index f91c91b614..75baa88035 100644 --- a/src/net/netgo.go +++ b/src/net/netgo.go @@ -2,7 +2,11 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. -//go:build netgo +// Default netGo to true if the netgo build tag is being used, or the +// C library DNS routines are not available. Note that the C library +// routines are always available on Windows. + +//go:build netgo || (!cgo && !windows) package net From f5715181392c68d928c3152f8cf90fa9d4ee9e4e Mon Sep 17 00:00:00 2001 From: kkHAIKE Date: Wed, 11 May 2022 02:27:21 +0000 Subject: [PATCH 22/38] cmd/cgo: dont override declared struct type Fixes #52611 Change-Id: I835df8d6a98a37482446ec00af768c96fd8ee4fe GitHub-Last-Rev: ea54dd69eef90eaf1641889039344fff70158ece GitHub-Pull-Request: golang/go#52733 Reviewed-on: https://go-review.googlesource.com/c/go/+/404497 Run-TryBot: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Reviewed-by: Dexter Ouyang Auto-Submit: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Alex Rakoczy TryBot-Result: Gopher Robot --- misc/cgo/test/testdata/issue52611.go | 13 +++++++++++++ misc/cgo/test/testdata/issue52611a/a.go | 16 ++++++++++++++++ misc/cgo/test/testdata/issue52611a/b.go | 11 +++++++++++ misc/cgo/test/testdata/issue52611b/a.go | 11 +++++++++++ misc/cgo/test/testdata/issue52611b/b.go | 16 ++++++++++++++++ src/cmd/cgo/gcc.go | 5 +++++ 6 files changed, 72 insertions(+) create mode 100644 misc/cgo/test/testdata/issue52611.go create mode 100644 misc/cgo/test/testdata/issue52611a/a.go create mode 100644 misc/cgo/test/testdata/issue52611a/b.go create mode 100644 misc/cgo/test/testdata/issue52611b/a.go create mode 100644 misc/cgo/test/testdata/issue52611b/b.go diff --git a/misc/cgo/test/testdata/issue52611.go b/misc/cgo/test/testdata/issue52611.go new file mode 100644 index 0000000000..32d22403ab --- /dev/null +++ b/misc/cgo/test/testdata/issue52611.go @@ -0,0 +1,13 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Issue 52611: inconsistent compiler behaviour when compiling a C.struct. +// No runtime test; just make sure it compiles. + +package cgotest + +import ( + _ "cgotest/issue52611a" + _ "cgotest/issue52611b" +) diff --git a/misc/cgo/test/testdata/issue52611a/a.go b/misc/cgo/test/testdata/issue52611a/a.go new file mode 100644 index 0000000000..0764688ec4 --- /dev/null +++ b/misc/cgo/test/testdata/issue52611a/a.go @@ -0,0 +1,16 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue52611a + +/* +typedef struct Foo { + int X; +} Foo; +*/ +import "C" + +func GetX1(foo *C.struct_Foo) int32 { + return int32(foo.X) +} diff --git a/misc/cgo/test/testdata/issue52611a/b.go b/misc/cgo/test/testdata/issue52611a/b.go new file mode 100644 index 0000000000..74a50c5dea --- /dev/null +++ b/misc/cgo/test/testdata/issue52611a/b.go @@ -0,0 +1,11 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue52611a + +import "C" + +func GetX2(foo *C.struct_Foo) int32 { + return int32(foo.X) +} diff --git a/misc/cgo/test/testdata/issue52611b/a.go b/misc/cgo/test/testdata/issue52611b/a.go new file mode 100644 index 0000000000..730b52f5e9 --- /dev/null +++ b/misc/cgo/test/testdata/issue52611b/a.go @@ -0,0 +1,11 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue52611b + +import "C" + +func GetX1(bar *C.struct_Bar) int32 { + return int32(bar.X) +} diff --git a/misc/cgo/test/testdata/issue52611b/b.go b/misc/cgo/test/testdata/issue52611b/b.go new file mode 100644 index 0000000000..d304175395 --- /dev/null +++ b/misc/cgo/test/testdata/issue52611b/b.go @@ -0,0 +1,16 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package issue52611b + +/* +typedef struct Bar { + int X; +} Bar; +*/ +import "C" + +func GetX2(bar *C.struct_Bar) int32 { + return int32(bar.X) +} diff --git a/src/cmd/cgo/gcc.go b/src/cmd/cgo/gcc.go index 4dff5e2b1c..3cb01ba382 100644 --- a/src/cmd/cgo/gcc.go +++ b/src/cmd/cgo/gcc.go @@ -2551,6 +2551,11 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ t.Go = name // publish before recursive calls goIdent[name.Name] = name if dt.ByteSize < 0 { + // Don't override old type + if _, ok := typedef[name.Name]; ok { + break + } + // Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown), // so execute the basic things that the struct case would do // other than try to determine a Go representation. From 606c6c371ad3d089d59d15393f7c49b063fc0eca Mon Sep 17 00:00:00 2001 From: shaoliming Date: Fri, 17 Jun 2022 05:01:26 +0000 Subject: [PATCH 23/38] encoding/xml: check nil pointer in DecodeElement Fixes #53350 Change-Id: Id5e1f4016db5f1d4349ee1a76a9dfe3aeae83cee GitHub-Last-Rev: 45add121612a8144c2525828bd7386c4adb05174 GitHub-Pull-Request: golang/go#53407 Reviewed-on: https://go-review.googlesource.com/c/go/+/412634 Auto-Submit: Ian Lance Taylor Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Alex Rakoczy --- src/encoding/xml/read.go | 4 ++++ src/encoding/xml/read_test.go | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/encoding/xml/read.go b/src/encoding/xml/read.go index 565d9a8bea..257591262f 100644 --- a/src/encoding/xml/read.go +++ b/src/encoding/xml/read.go @@ -148,6 +148,10 @@ func (d *Decoder) DecodeElement(v any, start *StartElement) error { if val.Kind() != reflect.Pointer { return errors.New("non-pointer passed to Unmarshal") } + + if val.IsNil() { + return errors.New("nil pointer passed to Unmarshal") + } return d.unmarshal(val.Elem(), start) } diff --git a/src/encoding/xml/read_test.go b/src/encoding/xml/read_test.go index 391fe731a8..6ef55de77b 100644 --- a/src/encoding/xml/read_test.go +++ b/src/encoding/xml/read_test.go @@ -1079,3 +1079,18 @@ func TestUnmarshalWhitespaceAttrs(t *testing.T) { t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want) } } + +// golang.org/issues/53350 +func TestUnmarshalIntoNil(t *testing.T) { + type T struct { + A int `xml:"A"` + } + + var nilPointer *T + err := Unmarshal([]byte("1"), nilPointer) + + if err == nil { + t.Fatalf("no error in unmarshalling") + } + +} From 6bad7e82430bb1eb927a2901f44f9664637db27d Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Fri, 17 Jun 2022 13:38:07 -0700 Subject: [PATCH 24/38] compress/gzip: always close bodyReader in Example_compressingReader For #53362 Fixes #53414 Change-Id: I352164e70c136eed210c7ee4ceba5dc631f81f94 Reviewed-on: https://go-review.googlesource.com/c/go/+/412955 Auto-Submit: Ian Lance Taylor Reviewed-by: Joseph Tsai Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Alex Rakoczy TryBot-Result: Gopher Robot --- src/compress/gzip/example_test.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compress/gzip/example_test.go b/src/compress/gzip/example_test.go index 27aae152d4..1ba4080ea0 100644 --- a/src/compress/gzip/example_test.go +++ b/src/compress/gzip/example_test.go @@ -160,6 +160,10 @@ func Example_compressingReader() { // httpWriter is the body of the HTTP request, as an io.Writer. bodyReader, httpWriter := io.Pipe() + // Make sure that bodyReader is always closed, so that the + // goroutine below will always exit. + defer bodyReader.Close() + // gzipWriter compresses data to httpWriter. gzipWriter := gzip.NewWriter(httpWriter) @@ -197,7 +201,6 @@ func Example_compressingReader() { // Note that passing req to http.Client.Do promises that it // will close the body, in this case bodyReader. - // That ensures that the goroutine will exit. resp, err := ts.Client().Do(req) if err != nil { log.Fatal(err) From 4045b1bc3f97a47274ef1da2bf6d29f5ce1c7b88 Mon Sep 17 00:00:00 2001 From: Wayne Zuo Date: Thu, 16 Jun 2022 11:05:39 +0800 Subject: [PATCH 25/38] cmd/compile: fix assert condition in generic method call Fixes #53406. Change-Id: If7ae39ec1042a792d82a0a2de96d168c22d8ab71 Reviewed-on: https://go-review.googlesource.com/c/go/+/412614 Reviewed-by: Keith Randall Reviewed-by: Cuong Manh Le TryBot-Result: Gopher Robot Reviewed-by: Alex Rakoczy Auto-Submit: Alex Rakoczy Reviewed-by: Keith Randall Run-TryBot: Wayne Zuo --- src/cmd/compile/internal/noder/stencil.go | 12 +++++++++--- test/typeparam/issue53406.go | 22 ++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 test/typeparam/issue53406.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index eeb503811c..d463c850f3 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -208,9 +208,15 @@ func (g *genInst) scanForGenCalls(decl ir.Node) { st := g.getInstantiation(gf, targs, true).fun dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true) - // We have to be using a subdictionary, since this is - // a generic method call. - assert(usingSubdict) + if hasShapeTypes(targs) { + // We have to be using a subdictionary, since this is + // a generic method call. + assert(usingSubdict) + } else { + // We should use main dictionary, because the receiver is + // an instantiation already, see issue #53406. + assert(!usingSubdict) + } // Transform to a function call, by appending the // dictionary and the receiver to the args. diff --git a/test/typeparam/issue53406.go b/test/typeparam/issue53406.go new file mode 100644 index 0000000000..90fe78fb6f --- /dev/null +++ b/test/typeparam/issue53406.go @@ -0,0 +1,22 @@ +// compile + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +func main() { + f[int]() +} + +func f[T1 any]() { + var x Outer[T1, int] + x.M() +} + +type Outer[T1, T2 any] struct{ Inner[T2] } + +type Inner[_ any] int + +func (Inner[_]) M() {} From 111cdb58487f1a3d2bd82be14a90837f31a3e320 Mon Sep 17 00:00:00 2001 From: Guoqi Chen Date: Wed, 15 Jun 2022 19:07:24 +0800 Subject: [PATCH 26/38] all: update to current golang.org/x/sys revision go get -d golang.org/x/sys@6c1b26c55098eae66ce95ab7c3712ab6cbfff2b7 go mod tidy go mod vendor This fixes the problem of the second return value in syscall on linux/loong64. Change-Id: I8018ae96f4e5ca9779b2c053cdccc6b2866bf0de Reviewed-on: https://go-review.googlesource.com/c/go/+/412274 Reviewed-by: Bryan Mills Reviewed-by: Ian Lance Taylor Run-TryBot: Bryan Mills Auto-Submit: Ian Lance Taylor TryBot-Result: Gopher Robot --- src/cmd/go.mod | 2 +- src/cmd/go.sum | 4 +-- .../golang.org/x/sys/unix/asm_linux_loong64.s | 4 +-- .../golang.org/x/sys/unix/ifreq_linux.go | 9 +----- .../golang.org/x/sys/unix/syscall_solaris.go | 1 + .../x/sys/unix/zerrors_linux_386.go | 2 +- .../x/sys/unix/zerrors_linux_amd64.go | 2 +- .../x/sys/unix/zerrors_linux_arm.go | 2 +- .../x/sys/unix/zerrors_linux_arm64.go | 2 +- .../x/sys/unix/zerrors_linux_loong64.go | 2 +- .../x/sys/unix/zerrors_linux_mips.go | 2 +- .../x/sys/unix/zerrors_linux_mips64.go | 2 +- .../x/sys/unix/zerrors_linux_mips64le.go | 2 +- .../x/sys/unix/zerrors_linux_mipsle.go | 2 +- .../x/sys/unix/zerrors_linux_ppc.go | 2 +- .../x/sys/unix/zerrors_linux_ppc64.go | 2 +- .../x/sys/unix/zerrors_linux_ppc64le.go | 2 +- .../x/sys/unix/zerrors_linux_riscv64.go | 2 +- .../x/sys/unix/zerrors_linux_s390x.go | 2 +- .../x/sys/unix/zerrors_linux_sparc64.go | 2 +- .../x/sys/unix/zsyscall_solaris_amd64.go | 14 +++++++++ .../golang.org/x/sys/unix/ztypes_linux_386.go | 2 +- .../x/sys/unix/ztypes_linux_amd64.go | 2 +- .../golang.org/x/sys/unix/ztypes_linux_arm.go | 2 +- .../x/sys/unix/ztypes_linux_arm64.go | 2 +- .../x/sys/unix/ztypes_linux_loong64.go | 2 +- .../x/sys/unix/ztypes_linux_mips.go | 2 +- .../x/sys/unix/ztypes_linux_mips64.go | 2 +- .../x/sys/unix/ztypes_linux_mips64le.go | 2 +- .../x/sys/unix/ztypes_linux_mipsle.go | 2 +- .../golang.org/x/sys/unix/ztypes_linux_ppc.go | 2 +- .../x/sys/unix/ztypes_linux_ppc64.go | 2 +- .../x/sys/unix/ztypes_linux_ppc64le.go | 2 +- .../x/sys/unix/ztypes_linux_riscv64.go | 2 +- .../x/sys/unix/ztypes_linux_s390x.go | 2 +- .../x/sys/unix/ztypes_linux_sparc64.go | 2 +- .../x/sys/unix/ztypes_openbsd_386.go | 8 ++--- .../x/sys/unix/ztypes_openbsd_amd64.go | 8 ++--- .../x/sys/unix/ztypes_openbsd_arm.go | 8 ++--- .../x/sys/unix/ztypes_openbsd_arm64.go | 8 ++--- .../x/sys/unix/ztypes_openbsd_mips64.go | 8 ++--- src/cmd/vendor/modules.txt | 2 +- src/go.mod | 2 +- src/go.sum | 4 +-- .../golang.org/x/sys/cpu/cpu_gccgo_x86.c | 29 ++++++++----------- src/vendor/modules.txt | 2 +- 46 files changed, 88 insertions(+), 85 deletions(-) diff --git a/src/cmd/go.mod b/src/cmd/go.mod index 04c2523a09..8230a3e453 100644 --- a/src/cmd/go.mod +++ b/src/cmd/go.mod @@ -7,7 +7,7 @@ require ( golang.org/x/arch v0.0.0-20220412001346-fc48f9fe4c15 golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 - golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a + golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 golang.org/x/tools v0.1.11-0.20220516163903-1e55371df567 ) diff --git a/src/cmd/go.sum b/src/cmd/go.sum index fc81e159e5..435c3cce3b 100644 --- a/src/cmd/go.sum +++ b/src/cmd/go.sum @@ -10,8 +10,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVD golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4= golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a h1:N2T1jUrTQE9Re6TFF5PhvEHXHCguynGhKjWVsIUt5cY= -golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA= +golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8= golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/tools v0.1.11-0.20220516163903-1e55371df567 h1:MksUZ/zlU+pMbsq1Sw16gK6E1aWzD0rLE+eS2SxF24Y= diff --git a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_loong64.s b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_loong64.s index 6abd48eef0..565357288a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_loong64.s +++ b/src/cmd/vendor/golang.org/x/sys/unix/asm_linux_loong64.s @@ -30,7 +30,7 @@ TEXT ·SyscallNoError(SB),NOSPLIT,$0-48 MOVV trap+0(FP), R11 // syscall entry SYSCALL MOVV R4, r1+32(FP) - MOVV R5, r2+40(FP) + MOVV R0, r2+40(FP) // r2 is not used. Always set to 0 JAL runtime·exitsyscall(SB) RET @@ -50,5 +50,5 @@ TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48 MOVV trap+0(FP), R11 // syscall entry SYSCALL MOVV R4, r1+32(FP) - MOVV R5, r2+40(FP) + MOVV R0, r2+40(FP) // r2 is not used. Always set to 0 RET diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go b/src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go index 934af313c3..15721a5104 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ifreq_linux.go @@ -8,7 +8,6 @@ package unix import ( - "bytes" "unsafe" ) @@ -45,13 +44,7 @@ func NewIfreq(name string) (*Ifreq, error) { // Name returns the interface name associated with the Ifreq. func (ifr *Ifreq) Name() string { - // BytePtrToString requires a NULL terminator or the program may crash. If - // one is not present, just return the empty string. - if !bytes.Contains(ifr.raw.Ifrn[:], []byte{0x00}) { - return "" - } - - return BytePtrToString(&ifr.raw.Ifrn[0]) + return ByteSliceToString(ifr.raw.Ifrn[:]) } // According to netdevice(7), only AF_INET addresses are returned for numerous diff --git a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go index 5c2003cec6..932996c75b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/syscall_solaris.go @@ -618,6 +618,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e //sys Getpriority(which int, who int) (n int, err error) //sysnb Getrlimit(which int, lim *Rlimit) (err error) //sysnb Getrusage(who int, rusage *Rusage) (err error) +//sysnb Getsid(pid int) (sid int, err error) //sysnb Gettimeofday(tv *Timeval) (err error) //sysnb Getuid() (uid int) //sys Kill(pid int, signum syscall.Signal) (err error) diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go index 234fd4a5d1..1b305fab1b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_386.go @@ -5,7 +5,7 @@ // +build 386,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go index 58619b7589..6bcdef5dd6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_amd64.go @@ -5,7 +5,7 @@ // +build amd64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go index 3a64ff59dc..e65df0f8d1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm.go @@ -5,7 +5,7 @@ // +build arm,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go index abe0b92578..c7021115aa 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_arm64.go @@ -5,7 +5,7 @@ // +build arm64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go index ebc5f3218e..0d83a1cd45 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_loong64.go @@ -5,7 +5,7 @@ // +build loong64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go index 14d7a84399..7f44a495b7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips.go @@ -5,7 +5,7 @@ // +build mips,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go index 99e7c4ac0b..2f92b4e48e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64.go @@ -5,7 +5,7 @@ // +build mips64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go index 496364c33c..f5367a966b 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mips64le.go @@ -5,7 +5,7 @@ // +build mips64le,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go index 3e40830857..2e22337d7c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_mipsle.go @@ -5,7 +5,7 @@ // +build mipsle,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go index 1151a7dfab..858c4f30f5 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc.go @@ -5,7 +5,7 @@ // +build ppc,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go index ed17f249e7..af2a7ba6e6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64.go @@ -5,7 +5,7 @@ // +build ppc64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go index d84a37c1ac..eaa2eb8e24 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_ppc64le.go @@ -5,7 +5,7 @@ // +build ppc64le,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go index 5cafba83f6..faaa9f0637 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_riscv64.go @@ -5,7 +5,7 @@ // +build riscv64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go index 6d122da41c..0d161f0b75 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_s390x.go @@ -5,7 +5,7 @@ // +build s390x,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go index 6bd19e51db..4fd497a3e3 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zerrors_linux_sparc64.go @@ -5,7 +5,7 @@ // +build sparc64,linux // Code generated by cmd/cgo -godefs; DO NOT EDIT. -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go package unix diff --git a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go index d12f4fbfea..fdf53f8daf 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/zsyscall_solaris_amd64.go @@ -66,6 +66,7 @@ import ( //go:cgo_import_dynamic libc_getpriority getpriority "libc.so" //go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so" //go:cgo_import_dynamic libc_getrusage getrusage "libc.so" +//go:cgo_import_dynamic libc_getsid getsid "libc.so" //go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so" //go:cgo_import_dynamic libc_getuid getuid "libc.so" //go:cgo_import_dynamic libc_kill kill "libc.so" @@ -202,6 +203,7 @@ import ( //go:linkname procGetpriority libc_getpriority //go:linkname procGetrlimit libc_getrlimit //go:linkname procGetrusage libc_getrusage +//go:linkname procGetsid libc_getsid //go:linkname procGettimeofday libc_gettimeofday //go:linkname procGetuid libc_getuid //go:linkname procKill libc_kill @@ -339,6 +341,7 @@ var ( procGetpriority, procGetrlimit, procGetrusage, + procGetsid, procGettimeofday, procGetuid, procKill, @@ -1044,6 +1047,17 @@ func Getrusage(who int, rusage *Rusage) (err error) { // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT +func Getsid(pid int) (sid int, err error) { + r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGetsid)), 1, uintptr(pid), 0, 0, 0, 0, 0) + sid = int(r0) + if e1 != 0 { + err = e1 + } + return +} + +// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT + func Gettimeofday(tv *Timeval) (err error) { _, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGettimeofday)), 1, uintptr(unsafe.Pointer(tv)), 0, 0, 0, 0, 0) if e1 != 0 { diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go index 5314092568..4948362f2c 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_386.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build 386 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go index b02ab83dbd..f64345e0e2 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_amd64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build amd64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go index 9e6871d2e0..72469c79e7 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go index b732d12559..68f072283a 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_arm64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build arm64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go index 61fbb24f8d..090ae46c67 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_loong64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build loong64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go index 5310f71ea5..03604cca13 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go index 219bbb1267..fe57a7b265 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go index be9432da54..3f0db4da81 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mips64le.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mips64le && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go index d0155a42e6..70ecd3b239 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_mipsle.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build mipsle && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go index 01c17bcc6f..4e700120db 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go index 944a9c3c78..34a57c6992 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go index 5d2c90e1ce..6b84a47296 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_ppc64le.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build ppc64le && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go index e173cb5157..c4a305fe2e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build riscv64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go index 6106715d5c..a1f1e4c9e1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_s390x.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build s390x && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go index ca7b37b4b5..df95ebf3a1 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_linux_sparc64.go @@ -1,4 +1,4 @@ -// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go +// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go // Code generated by the command above; see README.md. DO NOT EDIT. //go:build sparc64 && linux diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go index baf5fe6504..2ed718ca06 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_386.go @@ -94,10 +94,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte Pad_cgo_0 [2]byte Mount_info [160]byte } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go index e21ae8ecfa..b4fb97ebe6 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_amd64.go @@ -96,10 +96,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte _ [2]byte Mount_info [160]byte } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go index f190651cd9..2c4675040e 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm.go @@ -98,10 +98,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte _ [2]byte Mount_info [160]byte } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go index 84747c582c..ddee045147 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_arm64.go @@ -94,10 +94,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte _ [2]byte Mount_info [160]byte } diff --git a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go index ac5c8b6370..eb13d4e8bf 100644 --- a/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go +++ b/src/cmd/vendor/golang.org/x/sys/unix/ztypes_openbsd_mips64.go @@ -94,10 +94,10 @@ type Statfs_t struct { F_namemax uint32 F_owner uint32 F_ctime uint64 - F_fstypename [16]int8 - F_mntonname [90]int8 - F_mntfromname [90]int8 - F_mntfromspec [90]int8 + F_fstypename [16]byte + F_mntonname [90]byte + F_mntfromname [90]byte + F_mntfromspec [90]byte _ [2]byte Mount_info [160]byte } diff --git a/src/cmd/vendor/modules.txt b/src/cmd/vendor/modules.txt index 1280a9e701..4e4b5b6343 100644 --- a/src/cmd/vendor/modules.txt +++ b/src/cmd/vendor/modules.txt @@ -40,7 +40,7 @@ golang.org/x/mod/zip # golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 ## explicit golang.org/x/sync/semaphore -# golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a +# golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 ## explicit; go 1.17 golang.org/x/sys/internal/unsafeheader golang.org/x/sys/plan9 diff --git a/src/go.mod b/src/go.mod index 2b4d8b4b75..94380d6567 100644 --- a/src/go.mod +++ b/src/go.mod @@ -8,6 +8,6 @@ require ( ) require ( - golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a // indirect + golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 // indirect golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361 // indirect ) diff --git a/src/go.sum b/src/go.sum index 5c710268b8..a54b0565bd 100644 --- a/src/go.sum +++ b/src/go.sum @@ -2,7 +2,7 @@ golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8 h1:y+mHpWoQJNAHt26Nhh6JP7 golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/net v0.0.0-20220517181318-183a9ca12b87 h1:cCR+9mKLOGyX4Zx+uBZDXEDAQsvKQ/XbW4vreG5v1jU= golang.org/x/net v0.0.0-20220517181318-183a9ca12b87/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a h1:N2T1jUrTQE9Re6TFF5PhvEHXHCguynGhKjWVsIUt5cY= -golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA= +golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361 h1:h+pU/hCb7sEApigI6eII3/Emx5ZHaFWS+nulUp0Az/k= golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361/go.mod h1:5O0TPrbzDRCcAYs9rc2W4CFPmVHJfNFe8tESfECPJPE= diff --git a/src/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c b/src/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c index e363c7d131..a4605e6d12 100644 --- a/src/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c +++ b/src/vendor/golang.org/x/sys/cpu/cpu_gccgo_x86.c @@ -7,6 +7,7 @@ #include #include +#include // Need to wrap __get_cpuid_count because it's declared as static. int @@ -17,27 +18,21 @@ gccgoGetCpuidCount(uint32_t leaf, uint32_t subleaf, return __get_cpuid_count(leaf, subleaf, eax, ebx, ecx, edx); } +#pragma GCC diagnostic ignored "-Wunknown-pragmas" +#pragma GCC push_options +#pragma GCC target("xsave") +#pragma clang attribute push (__attribute__((target("xsave"))), apply_to=function) + // xgetbv reads the contents of an XCR (Extended Control Register) // specified in the ECX register into registers EDX:EAX. // Currently, the only supported value for XCR is 0. -// -// TODO: Replace with a better alternative: -// -// #include -// -// #pragma GCC target("xsave") -// -// void gccgoXgetbv(uint32_t *eax, uint32_t *edx) { -// unsigned long long x = _xgetbv(0); -// *eax = x & 0xffffffff; -// *edx = (x >> 32) & 0xffffffff; -// } -// -// Note that _xgetbv is defined starting with GCC 8. void gccgoXgetbv(uint32_t *eax, uint32_t *edx) { - __asm(" xorl %%ecx, %%ecx\n" - " xgetbv" - : "=a"(*eax), "=d"(*edx)); + uint64_t v = _xgetbv(0); + *eax = v & 0xffffffff; + *edx = v >> 32; } + +#pragma clang attribute pop +#pragma GCC pop_options diff --git a/src/vendor/modules.txt b/src/vendor/modules.txt index d0fe779a5c..dfb87abf13 100644 --- a/src/vendor/modules.txt +++ b/src/vendor/modules.txt @@ -19,7 +19,7 @@ golang.org/x/net/idna golang.org/x/net/lif golang.org/x/net/nettest golang.org/x/net/route -# golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a +# golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 ## explicit; go 1.17 golang.org/x/sys/cpu # golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361 From aca37d16a5a5c1d24e374245f0e5b6404379db96 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 22 Jun 2022 15:19:54 -0400 Subject: [PATCH 27/38] cmd/go: avoid indexing modules in GOROOT Scanning GOROOT modules for changes appears to be causing Windows builders to time out in x/tools tests. We may try a per-package index instead, but for now just skip GOROOT modules (as we do for main modules). Fixes #53493. Change-Id: Ic5bb90b4ce173a24fc6564e85fcde96e1f9b975f Reviewed-on: https://go-review.googlesource.com/c/go/+/413634 TryBot-Result: Gopher Robot Run-TryBot: Bryan Mills Reviewed-by: Michael Matloob --- src/cmd/go/go_test.go | 14 ------- src/cmd/go/internal/modindex/read.go | 58 ++++++---------------------- 2 files changed, 11 insertions(+), 61 deletions(-) diff --git a/src/cmd/go/go_test.go b/src/cmd/go/go_test.go index bbcecf2b2e..b39a62f3e4 100644 --- a/src/cmd/go/go_test.go +++ b/src/cmd/go/go_test.go @@ -18,7 +18,6 @@ import ( "io" "io/fs" "log" - "math/rand" "os" "os/exec" "path/filepath" @@ -129,19 +128,6 @@ func TestMain(m *testing.M) { } os.Setenv("CMDGO_TEST_RUN_MAIN", "true") - if strings.HasPrefix(runtime.Version(), "devel ") && godebug.Get("goindexsalt") == "" { - // We're going to execute a lot of cmd/go tests, so set a consistent salt - // via GODEBUG so that the modindex package can avoid walking an entire - // GOROOT module whenever it tries to use an index for that module. - indexSalt := rand.Int63() - v := os.Getenv("GODEBUG") - if v == "" { - os.Setenv("GODEBUG", fmt.Sprintf("goindexsalt=%d", indexSalt)) - } else { - os.Setenv("GODEBUG", fmt.Sprintf("%s,goindexsalt=%d", v, indexSalt)) - } - } - // $GO_GCFLAGS a compiler debug flag known to cmd/dist, make.bash, etc. // It is not a standard go command flag; use os.Getenv, not cfg.Getenv. if os.Getenv("GO_GCFLAGS") != "" { diff --git a/src/cmd/go/internal/modindex/read.go b/src/cmd/go/internal/modindex/read.go index e5761af679..ea1ebb07c2 100644 --- a/src/cmd/go/internal/modindex/read.go +++ b/src/cmd/go/internal/modindex/read.go @@ -15,7 +15,6 @@ import ( "internal/godebug" "internal/goroot" "internal/unsafeheader" - "io/fs" "math" "path" "path/filepath" @@ -29,7 +28,6 @@ import ( "cmd/go/internal/base" "cmd/go/internal/cache" "cmd/go/internal/cfg" - "cmd/go/internal/fsys" "cmd/go/internal/imports" "cmd/go/internal/par" "cmd/go/internal/str" @@ -55,63 +53,29 @@ var fcache par.Cache var salt = godebug.Get("goindexsalt") +// moduleHash returns an ActionID corresponding to the state of the module +// located at filesystem path modroot. func moduleHash(modroot string, ismodcache bool) (cache.ActionID, error) { // We expect modules stored within the module cache to be checksummed and // immutable, and we expect released modules within GOROOT to change only // infrequently (when the Go version changes). - if !ismodcache && !str.HasFilePathPrefix(modroot, cfg.GOROOT) { + if !ismodcache { // The contents of this module may change over time. We don't want to pay // the cost to detect changes and re-index whenever they occur, so just // don't index it at all. + // + // Note that this is true even for modules in GOROOT/src: non-release builds + // of the Go toolchain may have arbitrary development changes on top of the + // commit reported by runtime.Version, or could be completly artificial due + // to lacking a `git` binary (like "devel gomote.XXXXX", as synthesized by + // "gomote push" as of 2022-06-15). (Release builds shouldn't have + // modifications, but we don't want to use a behavior for releases that we + // haven't tested during development.) return cache.ActionID{}, ErrNotIndexed } h := cache.NewHash("moduleIndex") fmt.Fprintf(h, "module index %s %s %s %v\n", runtime.Version(), salt, indexVersion, modroot) - - if str.HasFilePathPrefix(modroot, cfg.GOROOT) && strings.HasPrefix(runtime.Version(), "devel ") && salt == "" { - // This copy of the standard library is a development version, not a - // release. It could be based on a Git commit (like - // "devel go1.19-2a78e8afc0 Wed Jun 15 00:06:24 2022 +0000") with or - // without changes on top of that commit, or it could be completly - // artificial due to lacking a `git` binary (like "devel gomote.XXXXX", as - // synthesized by "gomote push" as of 2022-06-15). - // - // If the user provided a unique salt via GODEBUG, we can trust that it is - // unique and just go with it. Otherwise, we compute an inexpensive hash of - // its files using mtimes so that during development we can continue to - // exercise the logic for cached GOROOT indexes. - // - // mtimes may be granular, imprecise, and loosely updated (see - // https://apenwarr.ca/log/20181113), but we don't expect Go contributors to - // be mucking around with the import graphs in GOROOT often enough for mtime - // collisions to matter essentially ever. - // - // Note that fsys.Walk walks paths in deterministic order, so this hash - // should be completely deterministic if the files are unchanged. - err := fsys.Walk(modroot, func(path string, info fs.FileInfo, err error) error { - if err := moduleWalkErr(modroot, path, info, err); err != nil { - return err - } - - if info.IsDir() { - return nil - } - fmt.Fprintf(h, "file %v %v\n", info.Name(), info.ModTime()) - if info.Mode()&fs.ModeSymlink != 0 { - targ, err := fsys.Stat(path) - if err != nil { - return err - } - fmt.Fprintf(h, "target %v %v\n", targ.Name(), targ.ModTime()) - } - return nil - }) - if err != nil { - return cache.ActionID{}, err - } - } - return h.Sum(), nil } From bdab4cf47a47b69caacad6fd7ff6ab27bb22ab1c Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 21 Jun 2022 18:11:32 -0700 Subject: [PATCH 28/38] cmd/go, cmd/link: support failure to create _cgo_import.go For a package that uses cgo, the file _cgo_import.go is created to record information required for internal linking: the non-Go dynamic symbols and libraries that the package depends on. Generating this information sometimes fails, because it can require recreating all the dependencies of all transitively imported packages. And the information is rarely needed, since by default we use external linking when there are packages outside of the standard library that use cgo. With this CL, if generating _cgo_import.go fails, we don't report an error. Instead, we mark the package as requiring external linking, by adding an empty file named "dynimportfail" into the generated archive. If the linker sees a file with that name, it rejects an attempt to use internal linking. Fixes #52863 Change-Id: Ie586e6753a5b67e49bb14533cd7603d9defcf0ea Reviewed-on: https://go-review.googlesource.com/c/go/+/413460 Run-TryBot: Ian Lance Taylor Reviewed-by: Bryan Mills Auto-Submit: Ian Lance Taylor Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot --- src/cmd/cgo/doc.go | 10 ++++ src/cmd/go/internal/work/exec.go | 45 ++++++++++++---- src/cmd/go/testdata/script/cgo_undef.txt | 68 ++++++++++++++++++++++++ src/cmd/link/internal/ld/config.go | 9 ++++ src/cmd/link/internal/ld/lib.go | 9 ++++ 5 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 src/cmd/go/testdata/script/cgo_undef.txt diff --git a/src/cmd/cgo/doc.go b/src/cmd/cgo/doc.go index 4c62c5d70e..7fb6179e26 100644 --- a/src/cmd/cgo/doc.go +++ b/src/cmd/cgo/doc.go @@ -753,6 +753,16 @@ presented to cmd/link as part of a larger program, contains: _go_.o # gc-compiled object for _cgo_gotypes.go, _cgo_import.go, *.cgo1.go _all.o # gcc-compiled object for _cgo_export.c, *.cgo2.c +If there is an error generating the _cgo_import.go file, then, instead +of adding _cgo_import.go to the package, the go tool adds an empty +file named dynimportfail. The _cgo_import.go file is only needed when +using internal linking mode, which is not the default when linking +programs that use cgo (as described below). If the linker sees a file +named dynimportfail it reports an error if it has been told to use +internal linking mode. This approach is taken because generating +_cgo_import.go requires doing a full C link of the package, which can +fail for reasons that are irrelevant when using external linking mode. + The final program will be a dynamic executable, so that cmd/link can avoid needing to process arbitrary .o files. It only needs to process the .o files generated from C files that cgo writes, and those are much more diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index 2becc6d946..c88b315d2c 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -2405,6 +2405,7 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s } // gccld runs the gcc linker to create an executable from a set of object files. +// Any error output is only displayed for BuildN or BuildX. func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flags []string, objs []string) error { var cmd []string if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 { @@ -2450,11 +2451,8 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag save = append(save, line) } out = bytes.Join(save, nil) - if len(out) > 0 { + if len(out) > 0 && (cfg.BuildN || cfg.BuildX) { b.showOutput(nil, dir, p.ImportPath, b.processOutput(out)) - if err != nil { - err = errPrintedOutput - } } } return err @@ -2913,10 +2911,16 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo switch cfg.BuildToolchainName { case "gc": importGo := objdir + "_cgo_import.go" - if err := b.dynimport(a, p, objdir, importGo, cgoExe, cflags, cgoLDFLAGS, outObj); err != nil { + dynOutGo, dynOutObj, err := b.dynimport(a, p, objdir, importGo, cgoExe, cflags, cgoLDFLAGS, outObj) + if err != nil { return nil, nil, err } - outGo = append(outGo, importGo) + if dynOutGo != "" { + outGo = append(outGo, dynOutGo) + } + if dynOutObj != "" { + outObj = append(outObj, dynOutObj) + } case "gccgo": defunC := objdir + "_cgo_defun.c" @@ -3011,11 +3015,13 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo // dynimport creates a Go source file named importGo containing // //go:cgo_import_dynamic directives for each symbol or library // dynamically imported by the object files outObj. -func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error { +// dynOutGo, if not empty, is a new Go file to build as part of the package. +// dynOutObj, if not empty, is a new file to add to the generated archive. +func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) (dynOutGo, dynOutObj string, err error) { cfile := objdir + "_cgo_main.c" ofile := objdir + "_cgo_main.o" if err := b.gcc(a, p, objdir, ofile, cflags, cfile); err != nil { - return err + return "", "", err } // Gather .syso files from this package and all (transitive) dependencies. @@ -3060,7 +3066,22 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe } } if err := b.gccld(a, p, objdir, dynobj, ldflags, linkobj); err != nil { - return err + // We only need this information for internal linking. + // If this link fails, mark the object as requiring + // external linking. This link can fail for things like + // syso files that have unexpected dependencies. + // cmd/link explicitly looks for the name "dynimportfail". + // See issue #52863. + fail := objdir + "dynimportfail" + if cfg.BuildN || cfg.BuildX { + b.Showcmd("", "echo > %s", fail) + } + if !cfg.BuildN { + if err := os.WriteFile(fail, nil, 0666); err != nil { + return "", "", err + } + } + return "", fail, nil } // cgo -dynimport @@ -3068,7 +3089,11 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe if p.Standard && p.ImportPath == "runtime/cgo" { cgoflags = []string{"-dynlinker"} // record path to dynamic linker } - return b.run(a, base.Cwd(), p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) + err = b.run(a, base.Cwd(), p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags) + if err != nil { + return "", "", err + } + return importGo, "", nil } // Run SWIG on all SWIG input files. diff --git a/src/cmd/go/testdata/script/cgo_undef.txt b/src/cmd/go/testdata/script/cgo_undef.txt new file mode 100644 index 0000000000..30034fbac1 --- /dev/null +++ b/src/cmd/go/testdata/script/cgo_undef.txt @@ -0,0 +1,68 @@ +# Issue 52863. + +# We manually create a .syso and a .a file in package a, +# such that the .syso file only works when linked against the .a file. +# Package a has #cgo LDFLAGS to make this happen. +# +# Package c imports package a, and uses cgo itself. +# The generation of the _cgo_import.go for package c will fail, +# because it won't know that it has to link against a/libb.a +# (because we don't gather the #cgo LDFLAGS from all transitively +# imported packages). +# +# The _cgo_import.go file is only needed for internal linking. +# When generating _cgo_import.go for package c fails, an ordinary +# external link should still work. But an internal link is expected +# to fail, because the failure to create _cgo_import.go should cause +# the linker to report an inability to internally link. + +[short] skip +[!cgo] skip +[!exec:ar] skip + +cc -c -o a/b.syso b/b.c +cc -c -o b/lib.o b/lib.c +exec ar rc a/libb.a b/lib.o +go build +! go build -ldflags=-linkmode=internal +stderr 'some packages could not be built to support internal linking.*m/c|requires external linking|does not support internal cgo' + +-- go.mod -- +module m + +-- a/a.go -- +package a + +// #cgo LDFLAGS: -L. -lb +// extern int CFn(int); +import "C" + +func GoFn(v int) int { return int(C.CFn(C.int(v))) } + +-- b/b.c -- +extern int LibFn(int); +int CFn(int i) { return LibFn(i); } + +-- b/lib.c -- +int LibFn(int i) { return i; } + +-- c/c.go -- +package c + +// static int D(int i) { return i; } +import "C" + +import "m/a" + +func Fn(i int) (int, int) { + return a.GoFn(i), int(C.D(C.int(i))) +} + +-- main.go -- +package main + +import "m/c" + +func main() { + println(c.Fn(0)) +} diff --git a/src/cmd/link/internal/ld/config.go b/src/cmd/link/internal/ld/config.go index 6d19b8b5bb..4dd43a16ab 100644 --- a/src/cmd/link/internal/ld/config.go +++ b/src/cmd/link/internal/ld/config.go @@ -246,6 +246,15 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) { return true, "some input objects have an unrecognized file format" } + if len(dynimportfail) > 0 { + // This error means that we were unable to generate + // the _cgo_import.go file for some packages. + // This typically means that there are some dependencies + // that the cgo tool could not figure out. + // See issue #52863. + return true, fmt.Sprintf("some packages could not be built to support internal linking (%v)", dynimportfail) + } + return false, "" } diff --git a/src/cmd/link/internal/ld/lib.go b/src/cmd/link/internal/ld/lib.go index 9a5d89a6f7..a3d8202e2c 100644 --- a/src/cmd/link/internal/ld/lib.go +++ b/src/cmd/link/internal/ld/lib.go @@ -344,6 +344,11 @@ var ( // to support internal linking mode. externalobj = false + // dynimportfail is a list of packages for which generating + // the dynimport file, _cgo_import.go, failed. If there are + // any of these objects, we must link externally. Issue 52863. + dynimportfail []string + // unknownObjFormat is set to true if we see an object whose // format we don't recognize. unknownObjFormat = false @@ -1030,6 +1035,10 @@ func loadobjfile(ctxt *Link, lib *sym.Library) { continue } + if arhdr.name == "dynimportfail" { + dynimportfail = append(dynimportfail, lib.Pkg) + } + // Skip other special (non-object-file) sections that // build tools may have added. Such sections must have // short names so that the suffix is not truncated. From 2a3b467d5f8de04a3493b7ab8cd886e109bd9283 Mon Sep 17 00:00:00 2001 From: Dmitri Goutnik Date: Sat, 7 May 2022 16:10:16 -0500 Subject: [PATCH 29/38] cmd/go: make module .zip files group/world readable os.CreateTemp in downloadZip leaves downloaded .zip files readable only by the owner. Make them group/world readable. Fixes #52765 Change-Id: Iace13e4ad813201a533a1a5fc0c6d9b2e5349a42 Reviewed-on: https://go-review.googlesource.com/c/go/+/404854 Reviewed-by: Ian Lance Taylor Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot Run-TryBot: Bryan Mills --- src/cmd/go/internal/modfetch/fetch.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd/go/internal/modfetch/fetch.go b/src/cmd/go/internal/modfetch/fetch.go index 426df9bc04..2e8c4c8aca 100644 --- a/src/cmd/go/internal/modfetch/fetch.go +++ b/src/cmd/go/internal/modfetch/fetch.go @@ -242,7 +242,7 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e // contents of the file (by hashing it) before we commit it. Because the file // is zip-compressed, we need an actual file — or at least an io.ReaderAt — to // validate it: we can't just tee the stream as we write it. - f, err := os.CreateTemp(filepath.Dir(zipfile), tmpPattern) + f, err := tempFile(filepath.Dir(zipfile), filepath.Base(zipfile), 0666) if err != nil { return err } From ff17b7d0d42af12ca1ad766a135d9951029027ea Mon Sep 17 00:00:00 2001 From: Wayne Zuo Date: Tue, 7 Jun 2022 09:12:21 +0800 Subject: [PATCH 30/38] cmd/compile: don't use dictionary convert to shaped empty interface Fixes: #53254 Change-Id: I3153d6ebb9f25957b09363f45c5cd4651ee84c2d Reviewed-on: https://go-review.googlesource.com/c/go/+/410655 Reviewed-by: Matthew Dempsky Run-TryBot: Wayne Zuo TryBot-Result: Gopher Robot Reviewed-by: Keith Randall Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 4 ++-- test/typeparam/issue53254.go | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 test/typeparam/issue53254.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index d463c850f3..89869c77d6 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1349,7 +1349,7 @@ func (g *genInst) dictPass(info *instInfo) { mce := m.(*ir.ConvExpr) // Note: x's argument is still typed as a type parameter. // m's argument now has an instantiated type. - if mce.X.Type().HasShape() || m.Type().HasShape() { + if mce.X.Type().HasShape() || (m.Type().HasShape() && !m.Type().IsEmptyInterface()) { m = convertUsingDictionary(info, info.dictParam, m.Pos(), mce.X, m, m.Type()) } case ir.ODOTTYPE, ir.ODOTTYPE2: @@ -1446,7 +1446,7 @@ func findDictType(info *instInfo, t *types.Type) int { // instantiated node of the CONVIFACE node or XDOT node (for a bound method call) that is causing the // conversion. func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type) ir.Node { - assert(v.Type().HasShape() || in.Type().HasShape()) + assert(v.Type().HasShape() || (in.Type().HasShape() && !in.Type().IsEmptyInterface())) assert(dst.IsInterface()) if v.Type().IsInterface() { diff --git a/test/typeparam/issue53254.go b/test/typeparam/issue53254.go new file mode 100644 index 0000000000..afc0f18471 --- /dev/null +++ b/test/typeparam/issue53254.go @@ -0,0 +1,19 @@ +// compile + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package main + +type Interface[T any] interface { +} + +func F[T any]() Interface[T] { + var i int + return i +} + +func main() { + F[int]() +} From 2e773a3894fba7af744090d7d42968f4993018e2 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 22 Jun 2022 16:02:45 -0700 Subject: [PATCH 31/38] test: add test that causes gofrontend crash For #52846 Change-Id: I763f81def97b53277396c123c524f7b8193ea35e Reviewed-on: https://go-review.googlesource.com/c/go/+/413694 Run-TryBot: Ian Lance Taylor Auto-Submit: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- test/fixedbugs/issue52846.go | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 test/fixedbugs/issue52846.go diff --git a/test/fixedbugs/issue52846.go b/test/fixedbugs/issue52846.go new file mode 100644 index 0000000000..747fc885b4 --- /dev/null +++ b/test/fixedbugs/issue52846.go @@ -0,0 +1,17 @@ +// compile + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Issue 52846: gofrontend crashed with alias as map key type + +package p + +type S struct { + F string +} + +type A = S + +var M = map[A]int{A{""}: 0} From 15605ca827723d568f780402d03b29842fd20eec Mon Sep 17 00:00:00 2001 From: tulip Date: Wed, 22 Jun 2022 00:42:29 +0800 Subject: [PATCH 32/38] embed: document additional file name restrictions For #44486 Change-Id: I66af9f7a9f95489a41fd6710e50bdd7878f78b85 Reviewed-on: https://go-review.googlesource.com/c/go/+/413494 Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Dmitri Shuralyov Reviewed-by: Ian Lance Taylor Auto-Submit: Ian Lance Taylor --- src/embed/embed.go | 1 + 1 file changed, 1 insertion(+) diff --git a/src/embed/embed.go b/src/embed/embed.go index cbe2d398fb..c54b961d15 100644 --- a/src/embed/embed.go +++ b/src/embed/embed.go @@ -91,6 +91,7 @@ // It can only be used with variables at package scope, not with local variables. // // Patterns must not match files outside the package's module, such as ‘.git/*’ or symbolic links. +// Patterns must not match files whose names include the special punctuation characters " * < > ? ` ' | / \ and :. // Matches for empty directories are ignored. After that, each pattern in a //go:embed line // must match at least one file or non-empty directory. // From de5329f1de4cd4a938323012910310e548b2d936 Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Thu, 23 Jun 2022 14:11:59 -0400 Subject: [PATCH 33/38] debug/dwarf: handle malformed line table with bad program offset Touch up the line table reader to ensure that it can detect and reject an invalid program offset field in the table header. Fixes #53329. Change-Id: Ia8d684e909af3aca3014b4a3d0dfd431e3f5a9f0 Reviewed-on: https://go-review.googlesource.com/c/go/+/413814 Run-TryBot: Than McIntosh TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/debug/dwarf/line.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/debug/dwarf/line.go b/src/debug/dwarf/line.go index bb281fbdd9..4df4a1751f 100644 --- a/src/debug/dwarf/line.go +++ b/src/debug/dwarf/line.go @@ -215,7 +215,11 @@ func (r *LineReader) readHeader(compDir string) error { } else { headerLength = Offset(buf.uint32()) } - r.programOffset = buf.off + headerLength + programOffset := buf.off + headerLength + if programOffset > r.endOffset { + return DecodeError{"line", hdrOffset, fmt.Sprintf("malformed line table: program offset %d exceeds end offset %d", programOffset, r.endOffset)} + } + r.programOffset = programOffset r.minInstructionLength = int(buf.uint8()) if r.version >= 4 { // [DWARF4 6.2.4] From d38f1d13fa413436d38d86fe86d6a146be44bb84 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Thu, 23 Jun 2022 17:23:39 -0700 Subject: [PATCH 34/38] doc/go1.19: Linux race detector now requires glibc 2.17 Fixes #53522 Change-Id: Ibed838d358a733d26a6c3d89446d7fadb1012961 Reviewed-on: https://go-review.googlesource.com/c/go/+/413876 Reviewed-by: Keith Randall Reviewed-by: Keith Randall Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor Auto-Submit: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot --- doc/go1.19.html | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/go1.19.html b/doc/go1.19.html index b323b0d182..53c11bd26e 100644 --- a/doc/go1.19.html +++ b/doc/go1.19.html @@ -807,6 +807,7 @@ as well as support for rendering them to HTML, Markdown, and text. Compared to v2, it is now typically 1.5x to 2x faster, uses half as much memory, and it supports an unlimited number of goroutines. + On Linux, the race detector now requires at least glibc version 2.17.

From 3e58ef6cc7dfaf2cf3b593e728f7f62391030114 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 23 Jun 2022 20:54:52 -0700 Subject: [PATCH 35/38] go/types, types2: better errors for == when type sets are empty For #51525. Change-Id: I3762bc4a48a1aaab3b006b1ad1400f866892243c Reviewed-on: https://go-review.googlesource.com/c/go/+/413934 TryBot-Result: Gopher Robot Run-TryBot: Robert Griesemer Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/predicates.go | 12 +++++++++++- .../types2/testdata/fixedbugs/issue48712.go | 14 +++++++------- .../types2/testdata/fixedbugs/issue51525.go | 16 ++++++++++++++++ .../internal/types2/testdata/spec/comparisons.go | 16 ++++++++-------- src/go/types/predicates.go | 12 +++++++++++- src/go/types/testdata/fixedbugs/issue48712.go | 14 +++++++------- src/go/types/testdata/fixedbugs/issue51525.go | 16 ++++++++++++++++ src/go/types/testdata/spec/comparisons.go | 16 ++++++++-------- 8 files changed, 84 insertions(+), 32 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue51525.go create mode 100644 src/go/types/testdata/fixedbugs/issue51525.go diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index f7b5b16204..c4d11dcac4 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -147,7 +147,17 @@ func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, . } return true case *Interface: - return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) + if dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) { + return true + } + if reportf != nil { + if t.typeSet().IsEmpty() { + reportf("empty type set") + } else { + reportf("incomparable types in type set") + } + } + // fallthrough } return false } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go index ab397560a8..63ce7bc510 100644 --- a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue48712.go @@ -23,18 +23,18 @@ func _[P comparable](x P, y any) { } func _[P any](x, y P) { - _ = x /* ERROR type parameter P is not comparable with == */ == x - _ = x /* ERROR type parameter P is not comparable with == */ == y - _ = y /* ERROR type parameter P is not comparable with == */ == x - _ = y /* ERROR type parameter P is not comparable with == */ == y + _ = x /* ERROR incomparable types in type set */ == x + _ = x /* ERROR incomparable types in type set */ == y + _ = y /* ERROR incomparable types in type set */ == x + _ = y /* ERROR incomparable types in type set */ == y _ = x /* ERROR type parameter P is not comparable with < */ < y } func _[P any](x P, y any) { - _ = x /* ERROR type parameter P is not comparable with == */ == x - _ = x /* ERROR type parameter P is not comparable with == */ == y - _ = y == x // ERROR type parameter P is not comparable with == + _ = x /* ERROR incomparable types in type set */ == x + _ = x /* ERROR incomparable types in type set */ == y + _ = y == x // ERROR incomparable types in type set _ = y == y _ = x /* ERROR type parameter P is not comparable with < */ < y diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51525.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51525.go new file mode 100644 index 0000000000..af1d1e6063 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51525.go @@ -0,0 +1,16 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _[T interface { + int + string +}](x T) { + _ = x /* ERROR empty type set */ == x +} + +func _[T interface{ int | []byte }](x T) { + _ = x /* ERROR incomparable types in type set */ == x +} diff --git a/src/cmd/compile/internal/types2/testdata/spec/comparisons.go b/src/cmd/compile/internal/types2/testdata/spec/comparisons.go index 62c95d47d7..2a7598a581 100644 --- a/src/cmd/compile/internal/types2/testdata/spec/comparisons.go +++ b/src/cmd/compile/internal/types2/testdata/spec/comparisons.go @@ -40,7 +40,7 @@ func _() { _ = m /* ERROR map can only be compared to nil */ == m _ = c == c - _ = b /* ERROR mismatched types */ == nil + _ = b /* ERROR mismatched types */ == nil _ = a /* ERROR mismatched types */ == nil _ = l == nil _ = s /* ERROR mismatched types */ == nil @@ -73,7 +73,7 @@ func _[ J comparable, M map[string]int, C chan int, -] ( +]( b B, a A, l L, @@ -86,14 +86,14 @@ func _[ c C, ) { _ = b == b - _ = a /* ERROR type parameter A is not comparable with == */ == a - _ = l /* ERROR type parameter L is not comparable with == */ == l - _ = s /* ERROR type parameter S is not comparable with == */ == s + _ = a /* ERROR incomparable types in type set */ == a + _ = l /* ERROR incomparable types in type set */ == l + _ = s /* ERROR incomparable types in type set */ == s _ = p == p - _ = f /* ERROR type parameter F is not comparable with == */ == f - _ = i /* ERROR type parameter I is not comparable with == */ == i + _ = f /* ERROR incomparable types in type set */ == f + _ = i /* ERROR incomparable types in type set */ == i _ = j == j - _ = m /* ERROR type parameter M is not comparable with == */ == m + _ = m /* ERROR incomparable types in type set */ == m _ = c == c _ = b /* ERROR mismatched types */ == nil diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 25db4acf4a..aaf4dd52fc 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -149,7 +149,17 @@ func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, . } return true case *Interface: - return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) + if dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) { + return true + } + if reportf != nil { + if t.typeSet().IsEmpty() { + reportf("empty type set") + } else { + reportf("incomparable types in type set") + } + } + // fallthrough } return false } diff --git a/src/go/types/testdata/fixedbugs/issue48712.go b/src/go/types/testdata/fixedbugs/issue48712.go index ab397560a8..63ce7bc510 100644 --- a/src/go/types/testdata/fixedbugs/issue48712.go +++ b/src/go/types/testdata/fixedbugs/issue48712.go @@ -23,18 +23,18 @@ func _[P comparable](x P, y any) { } func _[P any](x, y P) { - _ = x /* ERROR type parameter P is not comparable with == */ == x - _ = x /* ERROR type parameter P is not comparable with == */ == y - _ = y /* ERROR type parameter P is not comparable with == */ == x - _ = y /* ERROR type parameter P is not comparable with == */ == y + _ = x /* ERROR incomparable types in type set */ == x + _ = x /* ERROR incomparable types in type set */ == y + _ = y /* ERROR incomparable types in type set */ == x + _ = y /* ERROR incomparable types in type set */ == y _ = x /* ERROR type parameter P is not comparable with < */ < y } func _[P any](x P, y any) { - _ = x /* ERROR type parameter P is not comparable with == */ == x - _ = x /* ERROR type parameter P is not comparable with == */ == y - _ = y == x // ERROR type parameter P is not comparable with == + _ = x /* ERROR incomparable types in type set */ == x + _ = x /* ERROR incomparable types in type set */ == y + _ = y == x // ERROR incomparable types in type set _ = y == y _ = x /* ERROR type parameter P is not comparable with < */ < y diff --git a/src/go/types/testdata/fixedbugs/issue51525.go b/src/go/types/testdata/fixedbugs/issue51525.go new file mode 100644 index 0000000000..af1d1e6063 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue51525.go @@ -0,0 +1,16 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package p + +func _[T interface { + int + string +}](x T) { + _ = x /* ERROR empty type set */ == x +} + +func _[T interface{ int | []byte }](x T) { + _ = x /* ERROR incomparable types in type set */ == x +} diff --git a/src/go/types/testdata/spec/comparisons.go b/src/go/types/testdata/spec/comparisons.go index 62c95d47d7..2a7598a581 100644 --- a/src/go/types/testdata/spec/comparisons.go +++ b/src/go/types/testdata/spec/comparisons.go @@ -40,7 +40,7 @@ func _() { _ = m /* ERROR map can only be compared to nil */ == m _ = c == c - _ = b /* ERROR mismatched types */ == nil + _ = b /* ERROR mismatched types */ == nil _ = a /* ERROR mismatched types */ == nil _ = l == nil _ = s /* ERROR mismatched types */ == nil @@ -73,7 +73,7 @@ func _[ J comparable, M map[string]int, C chan int, -] ( +]( b B, a A, l L, @@ -86,14 +86,14 @@ func _[ c C, ) { _ = b == b - _ = a /* ERROR type parameter A is not comparable with == */ == a - _ = l /* ERROR type parameter L is not comparable with == */ == l - _ = s /* ERROR type parameter S is not comparable with == */ == s + _ = a /* ERROR incomparable types in type set */ == a + _ = l /* ERROR incomparable types in type set */ == l + _ = s /* ERROR incomparable types in type set */ == s _ = p == p - _ = f /* ERROR type parameter F is not comparable with == */ == f - _ = i /* ERROR type parameter I is not comparable with == */ == i + _ = f /* ERROR incomparable types in type set */ == f + _ = i /* ERROR incomparable types in type set */ == i _ = j == j - _ = m /* ERROR type parameter M is not comparable with == */ == m + _ = m /* ERROR incomparable types in type set */ == m _ = c == c _ = b /* ERROR mismatched types */ == nil From 73475ef0350e84b35a6aa1b593448a9497b62440 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 23 Jun 2022 17:53:01 -0700 Subject: [PATCH 36/38] go/types, types2: print qualified object names in cycle errors Fixes #50788. Change-Id: Id1ed7d9c0687e3005e28598373fd5634178c78ca Reviewed-on: https://go-review.googlesource.com/c/go/+/413895 Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/decl.go | 22 ++++++++++++++++++---- src/go/types/decl.go | 22 ++++++++++++++++++---- test/fixedbugs/issue50788.dir/a.go | 9 +++++++++ test/fixedbugs/issue50788.dir/b.go | 9 +++++++++ test/fixedbugs/issue50788.go | 7 +++++++ 5 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 test/fixedbugs/issue50788.dir/a.go create mode 100644 test/fixedbugs/issue50788.dir/b.go create mode 100644 test/fixedbugs/issue50788.go diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 0bc5f9f3e1..1db28fc002 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -5,6 +5,7 @@ package types2 import ( + "bytes" "cmd/compile/internal/syntax" "fmt" "go/constant" @@ -303,11 +304,23 @@ loop: // cycleError reports a declaration cycle starting with // the object in cycle that is "first" in the source. func (check *Checker) cycleError(cycle []Object) { + // name returns the (possibly qualified) object name. + // This is needed because with generic types, cycles + // may refer to imported types. See issue #50788. + // TODO(gri) Thus functionality is used elsewhere. Factor it out. + name := func(obj Object) string { + var buf bytes.Buffer + writePackage(&buf, obj.Pkg(), check.qualifier) + buf.WriteString(obj.Name()) + return buf.String() + } + // TODO(gri) Should we start with the last (rather than the first) object in the cycle // since that is the earliest point in the source where we start seeing the // cycle? That would be more consistent with other error messages. i := firstInSrc(cycle) obj := cycle[i] + objName := name(obj) // If obj is a type alias, mark it as valid (not broken) in order to avoid follow-on errors. tname, _ := obj.(*TypeName) if tname != nil && tname.IsAlias() { @@ -315,19 +328,20 @@ func (check *Checker) cycleError(cycle []Object) { } var err error_ if tname != nil && check.conf.CompilerErrorMessages { - err.errorf(obj, "invalid recursive type %s", obj.Name()) + err.errorf(obj, "invalid recursive type %s", objName) } else { - err.errorf(obj, "illegal cycle in declaration of %s", obj.Name()) + err.errorf(obj, "illegal cycle in declaration of %s", objName) } for range cycle { - err.errorf(obj, "%s refers to", obj.Name()) + err.errorf(obj, "%s refers to", objName) i++ if i >= len(cycle) { i = 0 } obj = cycle[i] + objName = name(obj) } - err.errorf(obj, "%s", obj.Name()) + err.errorf(obj, "%s", objName) check.report(&err) } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index c176042852..829aee74b3 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -5,6 +5,7 @@ package types import ( + "bytes" "fmt" "go/ast" "go/constant" @@ -302,30 +303,43 @@ loop: // cycleError reports a declaration cycle starting with // the object in cycle that is "first" in the source. func (check *Checker) cycleError(cycle []Object) { + // name returns the (possibly qualified) object name. + // This is needed because with generic types, cycles + // may refer to imported types. See issue #50788. + // TODO(gri) Thus functionality is used elsewhere. Factor it out. + name := func(obj Object) string { + var buf bytes.Buffer + writePackage(&buf, obj.Pkg(), check.qualifier) + buf.WriteString(obj.Name()) + return buf.String() + } + // TODO(gri) Should we start with the last (rather than the first) object in the cycle // since that is the earliest point in the source where we start seeing the // cycle? That would be more consistent with other error messages. i := firstInSrc(cycle) obj := cycle[i] + objName := name(obj) // If obj is a type alias, mark it as valid (not broken) in order to avoid follow-on errors. tname, _ := obj.(*TypeName) if tname != nil && tname.IsAlias() { check.validAlias(tname, Typ[Invalid]) } if tname != nil && compilerErrorMessages { - check.errorf(obj, _InvalidDeclCycle, "invalid recursive type %s", obj.Name()) + check.errorf(obj, _InvalidDeclCycle, "invalid recursive type %s", objName) } else { - check.errorf(obj, _InvalidDeclCycle, "illegal cycle in declaration of %s", obj.Name()) + check.errorf(obj, _InvalidDeclCycle, "illegal cycle in declaration of %s", objName) } for range cycle { - check.errorf(obj, _InvalidDeclCycle, "\t%s refers to", obj.Name()) // secondary error, \t indented + check.errorf(obj, _InvalidDeclCycle, "\t%s refers to", objName) // secondary error, \t indented i++ if i >= len(cycle) { i = 0 } obj = cycle[i] + objName = name(obj) } - check.errorf(obj, _InvalidDeclCycle, "\t%s", obj.Name()) + check.errorf(obj, _InvalidDeclCycle, "\t%s", objName) } // firstInSrc reports the index of the object with the "smallest" diff --git a/test/fixedbugs/issue50788.dir/a.go b/test/fixedbugs/issue50788.dir/a.go new file mode 100644 index 0000000000..0f786d494c --- /dev/null +++ b/test/fixedbugs/issue50788.dir/a.go @@ -0,0 +1,9 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package a + +type T[P any] struct { + _ P +} diff --git a/test/fixedbugs/issue50788.dir/b.go b/test/fixedbugs/issue50788.dir/b.go new file mode 100644 index 0000000000..e17afc7b43 --- /dev/null +++ b/test/fixedbugs/issue50788.dir/b.go @@ -0,0 +1,9 @@ +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package b + +import "./a" + +type T a.T[T] // ERROR "invalid recursive type T\n.*T refers to\n.*a\.T refers to\n.*T" diff --git a/test/fixedbugs/issue50788.go b/test/fixedbugs/issue50788.go new file mode 100644 index 0000000000..24d0eb002a --- /dev/null +++ b/test/fixedbugs/issue50788.go @@ -0,0 +1,7 @@ +// errorcheckdir + +// Copyright 2022 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package ignored From b9c4d94fdbe0c9e11a1e604cf321614b90a1d882 Mon Sep 17 00:00:00 2001 From: Sean Liao Date: Tue, 22 Mar 2022 22:00:22 +0000 Subject: [PATCH 37/38] cmd/go/internal/list: update help info with Deprecated field Also align Retracted documentation with actual type of []string Fixes #51876 Change-Id: I3b34e53424aa7ee5330eb71adac23510fff91798 Reviewed-on: https://go-review.googlesource.com/c/go/+/394677 Reviewed-by: Dmitri Shuralyov Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot Run-TryBot: Dmitri Shuralyov Reviewed-by: Dmitri Shuralyov --- src/cmd/go/alldocs.go | 27 ++++++++++++++------------- src/cmd/go/internal/list/list.go | 27 ++++++++++++++------------- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/cmd/go/alldocs.go b/src/cmd/go/alldocs.go index d770ad82e5..fdb7a085b0 100644 --- a/src/cmd/go/alldocs.go +++ b/src/cmd/go/alldocs.go @@ -930,19 +930,20 @@ // applied to a Go struct, but now a Module struct: // // type Module struct { -// Path string // module path -// Version string // module version -// Versions []string // available module versions (with -versions) -// Replace *Module // replaced by this module -// Time *time.Time // time version was created -// Update *Module // available update, if any (with -u) -// Main bool // is this the main module? -// Indirect bool // is this module only an indirect dependency of main module? -// Dir string // directory holding files for this module, if any -// GoMod string // path to go.mod file used when loading this module, if any -// GoVersion string // go version used in module -// Retracted string // retraction information, if any (with -retracted or -u) -// Error *ModuleError // error loading module +// Path string // module path +// Version string // module version +// Versions []string // available module versions +// Replace *Module // replaced by this module +// Time *time.Time // time version was created +// Update *Module // available update (with -u) +// Main bool // is this the main module? +// Indirect bool // module is only indirectly needed by main module +// Dir string // directory holding local copy of files, if any +// GoMod string // path to go.mod file describing module, if any +// GoVersion string // go version used in module +// Retracted []string // retraction information, if any (with -retracted or -u) +// Deprecated string // deprecation message, if any (with -u) +// Error *ModuleError // error loading module // } // // type ModuleError struct { diff --git a/src/cmd/go/internal/list/list.go b/src/cmd/go/internal/list/list.go index 770127c1cd..9c651f2bf3 100644 --- a/src/cmd/go/internal/list/list.go +++ b/src/cmd/go/internal/list/list.go @@ -222,19 +222,20 @@ When listing modules, the -f flag still specifies a format template applied to a Go struct, but now a Module struct: type Module struct { - Path string // module path - Version string // module version - Versions []string // available module versions (with -versions) - Replace *Module // replaced by this module - Time *time.Time // time version was created - Update *Module // available update, if any (with -u) - Main bool // is this the main module? - Indirect bool // is this module only an indirect dependency of main module? - Dir string // directory holding files for this module, if any - GoMod string // path to go.mod file used when loading this module, if any - GoVersion string // go version used in module - Retracted string // retraction information, if any (with -retracted or -u) - Error *ModuleError // error loading module + Path string // module path + Version string // module version + Versions []string // available module versions + Replace *Module // replaced by this module + Time *time.Time // time version was created + Update *Module // available update (with -u) + Main bool // is this the main module? + Indirect bool // module is only indirectly needed by main module + Dir string // directory holding local copy of files, if any + GoMod string // path to go.mod file describing module, if any + GoVersion string // go version used in module + Retracted []string // retraction information, if any (with -retracted or -u) + Deprecated string // deprecation message, if any (with -u) + Error *ModuleError // error loading module } type ModuleError struct { From 5a1c5b8ae741df2d5c53f328c57a84d85ae6c44a Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Thu, 23 Jun 2022 15:46:29 -0400 Subject: [PATCH 38/38] cmd/go: add per-package indexing for modules outside mod cache Packages outside the module cache including the standard library will be indexed individually rather than as a whole module. For #52876 Change-Id: I142dad6a790e9e8eb4dc6430a588fbfa86552e49 Reviewed-on: https://go-review.googlesource.com/c/go/+/413815 Reviewed-by: Michael Matloob Run-TryBot: Michael Matloob Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot --- src/cmd/go/internal/load/pkg.go | 4 +- src/cmd/go/internal/modindex/index_format.txt | 13 +- src/cmd/go/internal/modindex/read.go | 252 ++++++++++++++---- src/cmd/go/internal/modindex/scan.go | 10 +- src/cmd/go/internal/modindex/write.go | 18 +- src/cmd/go/internal/modload/import.go | 6 +- src/cmd/go/internal/modload/load.go | 4 +- src/cmd/go/internal/modload/search.go | 8 +- 8 files changed, 244 insertions(+), 71 deletions(-) diff --git a/src/cmd/go/internal/load/pkg.go b/src/cmd/go/internal/load/pkg.go index 1a7b9d235d..95a06a325d 100644 --- a/src/cmd/go/internal/load/pkg.go +++ b/src/cmd/go/internal/load/pkg.go @@ -878,8 +878,8 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo buildMode = build.ImportComment } if modroot := modload.PackageModRoot(ctx, r.path); modroot != "" { - if mi, err := modindex.Get(modroot); err == nil { - data.p, data.err = mi.Import(cfg.BuildContext, mi.RelPath(r.dir), buildMode) + if rp, err := modindex.GetPackage(modroot, r.dir); err == nil { + data.p, data.err = rp.Import(cfg.BuildContext, buildMode) goto Happy } else if !errors.Is(err, modindex.ErrNotIndexed) { base.Fatalf("go: %v", err) diff --git a/src/cmd/go/internal/modindex/index_format.txt b/src/cmd/go/internal/modindex/index_format.txt index 3768eea6c7..c74b1d458b 100644 --- a/src/cmd/go/internal/modindex/index_format.txt +++ b/src/cmd/go/internal/modindex/index_format.txt @@ -7,6 +7,8 @@ Strings are written into the string table at the end of the file. Each string is null-terminated. String offsets are relative to the start of the string table. Bools are written as uint32s: 0 for false and 1 for true. +The following is the format for a full module: + “go index v0\n” str uint32 - offset of string table n uint32 - number of packages @@ -40,7 +42,16 @@ for each RawPackage: position - file, offset, line, column - uint32 [string table] -// parseError struct +The following is the format for a single indexed package: + +“go index v0\n” +str uint32 - offset of string table +for the single RawPackage: + [same RawPackage format as above] +[string table] + +The following is the definition of the json-serialized parseError struct: + type parseError struct { ErrorList *scanner.ErrorList // non-nil if the error was an ErrorList, nil otherwise ErrorString string // non-empty for all other cases diff --git a/src/cmd/go/internal/modindex/read.go b/src/cmd/go/internal/modindex/read.go index ea1ebb07c2..65a1ecf6dc 100644 --- a/src/cmd/go/internal/modindex/read.go +++ b/src/cmd/go/internal/modindex/read.go @@ -23,11 +23,13 @@ import ( "sort" "strings" "sync" + "time" "unsafe" "cmd/go/internal/base" "cmd/go/internal/cache" "cmd/go/internal/cfg" + "cmd/go/internal/fsys" "cmd/go/internal/imports" "cmd/go/internal/par" "cmd/go/internal/str" @@ -39,20 +41,16 @@ import ( // module index. var enabled bool = godebug.Get("goindex") != "0" -// ModuleIndex represents and encoded module index file. It is used to +// Module represents and encoded module index file. It is used to // do the equivalent of build.Import of packages in the module and answer other // questions based on the index file's data. -type ModuleIndex struct { +type Module struct { modroot string od offsetDecoder packages map[string]int // offsets of each package packagePaths []string // paths to package directories relative to modroot; these are the keys of packages } -var fcache par.Cache - -var salt = godebug.Get("goindexsalt") - // moduleHash returns an ActionID corresponding to the state of the module // located at filesystem path modroot. func moduleHash(modroot string, ismodcache bool) (cache.ActionID, error) { @@ -75,7 +73,45 @@ func moduleHash(modroot string, ismodcache bool) (cache.ActionID, error) { } h := cache.NewHash("moduleIndex") - fmt.Fprintf(h, "module index %s %s %s %v\n", runtime.Version(), salt, indexVersion, modroot) + fmt.Fprintf(h, "module index %s %s %v\n", runtime.Version(), indexVersion, modroot) + return h.Sum(), nil +} + +const modTimeCutoff = 2 * time.Second + +// dirHash returns an ActionID corresponding to the state of the package +// located at filesystem path pkgdir. +func dirHash(pkgdir string) (cache.ActionID, error) { + h := cache.NewHash("moduleIndex") + fmt.Fprintf(h, "package %s %s %v\n", runtime.Version(), indexVersion, pkgdir) + entries, err := fsys.ReadDir(pkgdir) + if err != nil { + // pkgdir might not be a directory. give up on hashing. + return cache.ActionID{}, ErrNotIndexed + } + cutoff := time.Now().Add(-modTimeCutoff) + for _, info := range entries { + if info.IsDir() { + continue + } + + if !info.Mode().IsRegular() { + return cache.ActionID{}, ErrNotIndexed + } + // To avoid problems for very recent files where a new + // write might not change the mtime due to file system + // mtime precision, reject caching if a file was read that + // is less than modTimeCutoff old. + // + // This is the same strategy used for hashing test inputs. + // See hashOpen in cmd/go/internal/test/test.go for the + // corresponding code. + if info.ModTime().After(cutoff) { + return cache.ActionID{}, ErrNotIndexed + } + + fmt.Fprintf(h, "file %v %v %v\n", info.Name(), info.ModTime(), info.Size()) + } return h.Sum(), nil } @@ -83,31 +119,61 @@ var modrootCache par.Cache var ErrNotIndexed = errors.New("not in module index") -// Get returns the ModuleIndex for the module rooted at modroot. +var ( + errDisabled = fmt.Errorf("%w: module indexing disabled", ErrNotIndexed) + errNotFromModuleCache = fmt.Errorf("%w: not from module cache", ErrNotIndexed) +) + +// GetPackage returns the IndexPackage for the package at the given path. // It will return ErrNotIndexed if the directory should be read without // using the index, for instance because the index is disabled, or the packgae // is not in a module. -func Get(modroot string) (*ModuleIndex, error) { - if !enabled || cache.DefaultDir() == "off" || cfg.BuildMod == "vendor" { - return nil, ErrNotIndexed +func GetPackage(modroot, pkgdir string) (*IndexPackage, error) { + mi, err := GetModule(modroot) + if err == nil { + return mi.Package(relPath(pkgdir, modroot)), nil } - if modroot == "" { - panic("modindex.Get called with empty modroot") + if !errors.Is(err, errNotFromModuleCache) { + return nil, err } - modroot = filepath.Clean(modroot) - isModCache := str.HasFilePathPrefix(modroot, cfg.GOMODCACHE) - return openIndex(modroot, isModCache) + return openIndexPackage(modroot, pkgdir) } -// openIndex returns the module index for modPath. +// GetModule returns the Module for the given modroot. +// It will return ErrNotIndexed if the directory should be read without +// using the index, for instance because the index is disabled, or the packgae +// is not in a module. +func GetModule(modroot string) (*Module, error) { + if !enabled || cache.DefaultDir() == "off" { + return nil, errDisabled + } + if modroot == "" { + panic("modindex.GetPackage called with empty modroot") + } + if cfg.BuildMod == "vendor" { + // Even if the main module is in the module cache, + // its vendored dependencies are not loaded from their + // usual cached locations. + return nil, errNotFromModuleCache + } + modroot = filepath.Clean(modroot) + if !str.HasFilePathPrefix(modroot, cfg.GOMODCACHE) { + return nil, errNotFromModuleCache + } + return openIndexModule(modroot, true) +} + +var mcache par.Cache + +// openIndexModule returns the module index for modPath. // It will return ErrNotIndexed if the module can not be read // using the index because it contains symlinks. -func openIndex(modroot string, ismodcache bool) (*ModuleIndex, error) { +func openIndexModule(modroot string, ismodcache bool) (*Module, error) { type result struct { - mi *ModuleIndex + mi *Module err error } - r := fcache.Do(modroot, func() any { + r := mcache.Do(modroot, func() any { id, err := moduleHash(modroot, ismodcache) if err != nil { return result{nil, err} @@ -133,8 +199,38 @@ func openIndex(modroot string, ismodcache bool) (*ModuleIndex, error) { return r.mi, r.err } -// fromBytes returns a *ModuleIndex given the encoded representation. -func fromBytes(moddir string, data []byte) (mi *ModuleIndex, err error) { +var pcache par.Cache + +func openIndexPackage(modroot, pkgdir string) (*IndexPackage, error) { + type result struct { + pkg *IndexPackage + err error + } + r := pcache.Do(pkgdir, func() any { + id, err := dirHash(pkgdir) + if err != nil { + return result{nil, err} + } + data, _, err := cache.Default().GetMmap(id) + if err != nil { + // Couldn't read from index. Assume we couldn't read from + // the index because the package hasn't been indexed yet. + data = indexPackage(modroot, pkgdir) + if err = cache.Default().PutBytes(id, data); err != nil { + return result{nil, err} + } + } + pkg, err := packageFromBytes(modroot, data) + if err != nil { + return result{nil, err} + } + return result{pkg, nil} + }).(result) + return r.pkg, r.err +} + +// fromBytes returns a *Module given the encoded representation. +func fromBytes(moddir string, data []byte) (mi *Module, err error) { if !enabled { panic("use of index") } @@ -184,7 +280,7 @@ func fromBytes(moddir string, data []byte) (mi *ModuleIndex, err error) { packages[packagePaths[i]] = packageOffsets[i] } - return &ModuleIndex{ + return &Module{ moddir, offsetDecoder{data, st}, packages, @@ -192,21 +288,60 @@ func fromBytes(moddir string, data []byte) (mi *ModuleIndex, err error) { }, nil } +// packageFromBytes returns a *IndexPackage given the encoded representation. +func packageFromBytes(modroot string, data []byte) (p *IndexPackage, err error) { + if !enabled { + panic("use of package index when not enabled") + } + + // SetPanicOnFault's errors _may_ satisfy this interface. Even though it's not guaranteed + // that all its errors satisfy this interface, we'll only check for these errors so that + // we don't suppress panics that could have been produced from other sources. + type addrer interface { + Addr() uintptr + } + + // set PanicOnFault to true so that we can catch errors on the initial reads of the slice, + // in case it's mmapped (the common case). + old := debug.SetPanicOnFault(true) + defer func() { + debug.SetPanicOnFault(old) + if e := recover(); e != nil { + if _, ok := e.(addrer); ok { + // This panic was almost certainly caused by SetPanicOnFault. + err = fmt.Errorf("error reading module index: %v", e) + return + } + // The panic was likely not caused by SetPanicOnFault. + panic(e) + } + }() + + gotVersion, unread, _ := bytes.Cut(data, []byte{'\n'}) + if string(gotVersion) != indexVersion { + return nil, fmt.Errorf("bad index version string: %q", gotVersion) + } + stringTableOffset, unread := binary.LittleEndian.Uint32(unread[:4]), unread[4:] + st := newStringTable(data[stringTableOffset:]) + d := &decoder{unread, st} + p = decodePackage(d, offsetDecoder{data, st}) + p.modroot = modroot + return p, nil +} + // Returns a list of directory paths, relative to the modroot, for // packages contained in the module index. -func (mi *ModuleIndex) Packages() []string { +func (mi *Module) Packages() []string { return mi.packagePaths } -// RelPath returns the path relative to the module's root. -func (mi *ModuleIndex) RelPath(path string) string { - return str.TrimFilePathPrefix(filepath.Clean(path), mi.modroot) // mi.modroot is already clean +// relPath returns the path relative to the module's root. +func relPath(path, modroot string) string { + return str.TrimFilePathPrefix(filepath.Clean(path), filepath.Clean(modroot)) } -// ImportPackage is the equivalent of build.Import given the information in ModuleIndex. -func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.ImportMode) (p *build.Package, err error) { - rp := mi.indexPackage(relpath) - +// Import is the equivalent of build.Import given the information in Module. +func (rp *IndexPackage) Import(bctxt build.Context, mode build.ImportMode) (p *build.Package, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("error reading module index: %v", e) @@ -218,7 +353,7 @@ func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.Im p = &build.Package{} p.ImportPath = "." - p.Dir = filepath.Join(mi.modroot, rp.dir) + p.Dir = filepath.Join(rp.modroot, rp.dir) var pkgerr error switch ctxt.Compiler { @@ -236,7 +371,7 @@ func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.Im inTestdata := func(sub string) bool { return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || str.HasPathPrefix(sub, "testdata") } - if !inTestdata(relpath) { + if !inTestdata(rp.dir) { // In build.go, p.Root should only be set in the non-local-import case, or in // GOROOT or GOPATH. Since module mode only calls Import with path set to "." // and the module index doesn't apply outside modules, the GOROOT case is @@ -248,8 +383,8 @@ func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.Im if ctxt.GOROOT != "" && str.HasFilePathPrefix(p.Dir, cfg.GOROOTsrc) && p.Dir != cfg.GOROOTsrc { p.Root = ctxt.GOROOT p.Goroot = true - modprefix := str.TrimFilePathPrefix(mi.modroot, cfg.GOROOTsrc) - p.ImportPath = relpath + modprefix := str.TrimFilePathPrefix(rp.modroot, cfg.GOROOTsrc) + p.ImportPath = rp.dir if modprefix != "" { p.ImportPath = filepath.Join(modprefix, p.ImportPath) } @@ -521,20 +656,21 @@ func IsStandardPackage(goroot_, compiler, path string) bool { reldir = str.TrimFilePathPrefix(reldir, "cmd") modroot = filepath.Join(modroot, "cmd") } - mod, err := Get(modroot) - if err != nil { + if _, err := GetPackage(modroot, filepath.Join(modroot, reldir)); err == nil { + // Note that goroot.IsStandardPackage doesn't check that the directory + // actually contains any go files-- merely that it exists. GetPackage + // returning a nil error is enough for us to know the directory exists. + return true + } else if errors.Is(err, ErrNotIndexed) { + // Fall back because package isn't indexable. (Probably because + // a file was modified recently) return goroot.IsStandardPackage(goroot_, compiler, path) } - - pkgs := mod.Packages() - i := sort.SearchStrings(pkgs, reldir) - return i != len(pkgs) && pkgs[i] == reldir + return false } // IsDirWithGoFiles is the equivalent of fsys.IsDirWithGoFiles using the information in the index. -func (mi *ModuleIndex) IsDirWithGoFiles(relpath string) (_ bool, err error) { - rp := mi.indexPackage(relpath) - +func (rp *IndexPackage) IsDirWithGoFiles() (_ bool, err error) { defer func() { if e := recover(); e != nil { err = fmt.Errorf("error reading module index: %v", e) @@ -549,9 +685,7 @@ func (mi *ModuleIndex) IsDirWithGoFiles(relpath string) (_ bool, err error) { } // ScanDir implements imports.ScanDir using the information in the index. -func (mi *ModuleIndex) ScanDir(path string, tags map[string]bool) (sortedImports []string, sortedTestImports []string, err error) { - rp := mi.indexPackage(path) - +func (rp *IndexPackage) ScanDir(tags map[string]bool) (sortedImports []string, sortedTestImports []string, err error) { // TODO(matloob) dir should eventually be relative to indexed directory // TODO(matloob): skip reading raw package and jump straight to data we need? @@ -639,20 +773,22 @@ func shouldBuild(sf *sourceFile, tags map[string]bool) bool { return true } -// index package holds the information needed to access information in the -// index about a package. -type indexPackage struct { +// IndexPackage holds the information needed to access information in the +// index needed to load a package in a specific directory. +type IndexPackage struct { error error dir string // directory of the package relative to the modroot + modroot string + // Source files sourceFiles []*sourceFile } var errCannotFindPackage = errors.New("cannot find package") -// indexPackage returns an indexPackage constructed using the information in the ModuleIndex. -func (mi *ModuleIndex) indexPackage(path string) *indexPackage { +// Package returns an IndexPackage constructed using the information in the Module. +func (mi *Module) Package(path string) *IndexPackage { defer func() { if e := recover(); e != nil { base.Fatalf("error reading module index: %v", e) @@ -660,12 +796,18 @@ func (mi *ModuleIndex) indexPackage(path string) *indexPackage { }() offset, ok := mi.packages[path] if !ok { - return &indexPackage{error: fmt.Errorf("%w %q in:\n\t%s", errCannotFindPackage, path, filepath.Join(mi.modroot, path))} + return &IndexPackage{error: fmt.Errorf("%w %q in:\n\t%s", errCannotFindPackage, path, filepath.Join(mi.modroot, path))} } // TODO(matloob): do we want to lock on the module index? d := mi.od.decoderAt(offset) - rp := new(indexPackage) + p := decodePackage(d, mi.od) + p.modroot = mi.modroot + return p +} + +func decodePackage(d *decoder, od offsetDecoder) *IndexPackage { + rp := new(IndexPackage) if errstr := d.string(); errstr != "" { rp.error = errors.New(errstr) } @@ -675,7 +817,7 @@ func (mi *ModuleIndex) indexPackage(path string) *indexPackage { for i := uint32(0); i < numSourceFiles; i++ { offset := d.uint32() rp.sourceFiles[i] = &sourceFile{ - od: mi.od.offsetDecoderAt(offset), + od: od.offsetDecoderAt(offset), } } return rp diff --git a/src/cmd/go/internal/modindex/scan.go b/src/cmd/go/internal/modindex/scan.go index d1f73dbb53..eb84bf8d89 100644 --- a/src/cmd/go/internal/modindex/scan.go +++ b/src/cmd/go/internal/modindex/scan.go @@ -65,7 +65,15 @@ func indexModule(modroot string) ([]byte, error) { if err != nil { return nil, err } - return encodeModule(packages), nil + return encodeModuleBytes(packages), nil +} + +// indexModule indexes the package at the given directory and returns its +// encoded representation. It returns ErrNotIndexed if the package can't +// be indexed. +func indexPackage(modroot, pkgdir string) []byte { + p := importRaw(modroot, relPath(pkgdir, modroot)) + return encodePackageBytes(p) } // rawPackage holds the information from each package that's needed to diff --git a/src/cmd/go/internal/modindex/write.go b/src/cmd/go/internal/modindex/write.go index 0c3123a46f..3408248bd9 100644 --- a/src/cmd/go/internal/modindex/write.go +++ b/src/cmd/go/internal/modindex/write.go @@ -11,9 +11,9 @@ import ( const indexVersion = "go index v0" -// encodeModule produces the encoded representation of the module index. -// encodeModule may modify the packages slice. -func encodeModule(packages []*rawPackage) []byte { +// encodeModuleBytes produces the encoded representation of the module index. +// encodeModuleBytes may modify the packages slice. +func encodeModuleBytes(packages []*rawPackage) []byte { e := newEncoder() e.Bytes([]byte(indexVersion)) e.Bytes([]byte{'\n'}) @@ -39,6 +39,18 @@ func encodeModule(packages []*rawPackage) []byte { return e.b } +func encodePackageBytes(p *rawPackage) []byte { + e := newEncoder() + e.Bytes([]byte(indexVersion)) + e.Bytes([]byte{'\n'}) + stringTableOffsetPos := e.Pos() // fill this at the end + e.Uint32(0) // string table offset + encodePackage(e, p) + e.IntAt(e.Pos(), stringTableOffsetPos) + e.Bytes(e.stringTable) + return e.b +} + func encodePackage(e *encoder, p *rawPackage) { e.String(p.error) e.String(p.dir) diff --git a/src/cmd/go/internal/modload/import.go b/src/cmd/go/internal/modload/import.go index f7810ca5c6..f2c7592a28 100644 --- a/src/cmd/go/internal/modload/import.go +++ b/src/cmd/go/internal/modload/import.go @@ -657,11 +657,11 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile // We don't care about build tags, not even "+build ignore". // We're just looking for a plausible directory. res := haveGoFilesCache.Do(dir, func() any { - // modindex.Get will return ErrNotIndexed for any directories which + // modindex.GetPackage will return ErrNotIndexed for any directories which // are reached through a symlink, so that they will be handled by // fsys.IsDirWithGoFiles below. - if mi, err := modindex.Get(mdir); err == nil { - isDirWithGoFiles, err := mi.IsDirWithGoFiles(mi.RelPath(dir)) + if ip, err := modindex.GetPackage(mdir, dir); err == nil { + isDirWithGoFiles, err := ip.IsDirWithGoFiles() return goFilesEntry{isDirWithGoFiles, err} } else if !errors.Is(err, modindex.ErrNotIndexed) { return goFilesEntry{err: err} diff --git a/src/cmd/go/internal/modload/load.go b/src/cmd/go/internal/modload/load.go index b2c3ba2633..ba85dc2438 100644 --- a/src/cmd/go/internal/modload/load.go +++ b/src/cmd/go/internal/modload/load.go @@ -2102,8 +2102,8 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements) // may see these legacy imports. We drop them so that the module // search does not look for modules to try to satisfy them. func scanDir(modroot string, dir string, tags map[string]bool) (imports_, testImports []string, err error) { - if mi, mierr := modindex.Get(modroot); mierr == nil { - imports_, testImports, err = mi.ScanDir(mi.RelPath(dir), tags) + if ip, mierr := modindex.GetPackage(modroot, dir); mierr == nil { + imports_, testImports, err = ip.ScanDir(tags) goto Happy } else if !errors.Is(mierr, modindex.ErrNotIndexed) { return nil, nil, mierr diff --git a/src/cmd/go/internal/modload/search.go b/src/cmd/go/internal/modload/search.go index d9d7711d06..856390a0f2 100644 --- a/src/cmd/go/internal/modload/search.go +++ b/src/cmd/go/internal/modload/search.go @@ -195,7 +195,7 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f } modPrefix = mod.Path } - if mi, err := modindex.Get(root); err == nil { + if mi, err := modindex.GetModule(root); err == nil { walkFromIndex(mi, modPrefix, isMatch, treeCanMatch, tags, have, addPkg) continue } else if !errors.Is(err, modindex.ErrNotIndexed) { @@ -213,9 +213,9 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f } // walkFromIndex matches packages in a module using the module index. modroot -// is the module's root directory on disk, index is the ModuleIndex for the +// is the module's root directory on disk, index is the modindex.Module for the // module, and importPathRoot is the module's path prefix. -func walkFromIndex(index *modindex.ModuleIndex, importPathRoot string, isMatch, treeCanMatch func(string) bool, tags, have map[string]bool, addPkg func(string)) { +func walkFromIndex(index *modindex.Module, importPathRoot string, isMatch, treeCanMatch func(string) bool, tags, have map[string]bool, addPkg func(string)) { loopPackages: for _, reldir := range index.Packages() { // Avoid .foo, _foo, and testdata subdirectory trees. @@ -252,7 +252,7 @@ loopPackages: if !have[name] { have[name] = true if isMatch(name) { - if _, _, err := index.ScanDir(reldir, tags); err != imports.ErrNoGo { + if _, _, err := index.Package(reldir).ScanDir(tags); err != imports.ErrNoGo { addPkg(name) } }