From eaf040502b763a6f00dced35e4173c2ce90eb52f Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 16 Feb 2022 10:24:42 -0500 Subject: [PATCH 01/44] os: eliminate arbitrary sleep in Kill tests The test spawned a subprocess that arbitrarily slept for one second. However, on some platforms, longer than one second may elapse between starting the subprocess and sending the termination signal. Instead, the subprocess now closes stdout and reads stdin until EOF, eliminating the need for an arbitrary duration. (If the parent test times out, the stdin pipe will break, so the subprocess still won't leak forever.) This also makes the test much faster in the typical case: since it uses synchronization instead of sleeping, it can run as quickly as the host OS can start and kill the process. Fixes #44131 Change-Id: I9753571438380dc14fc3531efdaea84578a47fae Reviewed-on: https://go-review.googlesource.com/c/go/+/386174 Trust: Bryan Mills Run-TryBot: Bryan Mills Reviewed-by: Ian Lance Taylor TryBot-Result: Gopher Robot --- src/os/os_test.go | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/src/os/os_test.go b/src/os/os_test.go index 82ca6f987d..63427deb6e 100644 --- a/src/os/os_test.go +++ b/src/os/os_test.go @@ -28,6 +28,16 @@ import ( "time" ) +func TestMain(m *testing.M) { + if Getenv("GO_OS_TEST_DRAIN_STDIN") == "1" { + os.Stdout.Close() + io.Copy(io.Discard, os.Stdin) + Exit(0) + } + + Exit(m.Run()) +} + var dot = []string{ "dir_unix.go", "env.go", @@ -2259,9 +2269,18 @@ func testKillProcess(t *testing.T, processKiller func(p *Process)) { testenv.MustHaveExec(t) t.Parallel() - // Re-exec the test binary itself to emulate "sleep 1". - cmd := osexec.Command(Args[0], "-test.run", "TestSleep") - err := cmd.Start() + // Re-exec the test binary to start a process that hangs until stdin is closed. + cmd := osexec.Command(Args[0]) + cmd.Env = append(os.Environ(), "GO_OS_TEST_DRAIN_STDIN=1") + stdout, err := cmd.StdoutPipe() + if err != nil { + t.Fatal(err) + } + stdin, err := cmd.StdinPipe() + if err != nil { + t.Fatal(err) + } + err = cmd.Start() if err != nil { t.Fatalf("Failed to start test process: %v", err) } @@ -2270,19 +2289,14 @@ func testKillProcess(t *testing.T, processKiller func(p *Process)) { if err := cmd.Wait(); err == nil { t.Errorf("Test process succeeded, but expected to fail") } + stdin.Close() // Keep stdin alive until the process has finished dying. }() - time.Sleep(100 * time.Millisecond) - processKiller(cmd.Process) -} + // Wait for the process to be started. + // (It will close its stdout when it reaches TestMain.) + io.Copy(io.Discard, stdout) -// TestSleep emulates "sleep 1". It is a helper for testKillProcess, so we -// don't have to rely on an external "sleep" command being available. -func TestSleep(t *testing.T) { - if testing.Short() { - t.Skip("Skipping in short mode") - } - time.Sleep(time.Second) + processKiller(cmd.Process) } func TestKillStartProcess(t *testing.T) { From d35ed094864617d82c5701f56811ad68b37eda6e Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 16 Feb 2022 20:11:52 -0800 Subject: [PATCH 02/44] cmd/compile: fix importers to deal with recursion through type constraints The code for issue #51219 reveals bugs in the types1 and types2 importers that can occur for recursive types that are recursive through the type constraint. The crash in the issue is caused by the types1 bug, which leads to the production of a type1 type which is incomplete and improperly has the HasTParam flag set. The bug in the types1 importer is that we were not deferring type instantiations when reading the type parameters, but we need to do that exactly to correctly handle recursion through the type constraint. So, the fix is to move the start of the deferrals (in the 'U' section of doDecl in typecheck/iimport.go) above the code that reads the type params. Once that bug is fixed, the test still crashes due to a related types2 importer issues. The problem is that t.SetConstraint(c) requires c to be fully constructed (have its underlying type set). Since that may not be done yet in the 'U' case in (*importReader).obj() in importer/iimport.go, we need to defer the call to SetConstraint() in that case, until we are done importing all the types. I added a test case with recursion through a type constraint that causes a problem that is fixed by the types1 importer change, though the error is not the same as in the issue. I added more types in the test case (which try to imitate the issue types more closely) the types2 bug, but wasn't able to cause it yet with the smaller test case. Fixes #51219 Change-Id: I85d860c98c09dddc37f76ce87a78a6015ec6fd20 Reviewed-on: https://go-review.googlesource.com/c/go/+/386335 Reviewed-by: Matthew Dempsky Reviewed-by: Robert Findley Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Gopher Robot --- src/cmd/compile/internal/importer/iimport.go | 22 ++++++- src/cmd/compile/internal/typecheck/iimport.go | 11 ++-- src/go/internal/gcimporter/iimport.go | 23 +++++++- test/typeparam/issue51219.dir/a.go | 59 +++++++++++++++++++ test/typeparam/issue51219.dir/b.go | 11 ++++ test/typeparam/issue51219.dir/main.go | 18 ++++++ test/typeparam/issue51219.go | 7 +++ test/typeparam/issue51219.out | 1 + 8 files changed, 146 insertions(+), 6 deletions(-) create mode 100644 test/typeparam/issue51219.dir/a.go create mode 100644 test/typeparam/issue51219.dir/b.go create mode 100644 test/typeparam/issue51219.dir/main.go create mode 100644 test/typeparam/issue51219.go create mode 100644 test/typeparam/issue51219.out diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go index a827987a48..bed4fbb016 100644 --- a/src/cmd/compile/internal/importer/iimport.go +++ b/src/cmd/compile/internal/importer/iimport.go @@ -180,6 +180,14 @@ func ImportData(imports map[string]*types2.Package, data, path string) (pkg *typ p.doDecl(localpkg, name) } + // SetConstraint can't be called if the constraint type is not yet complete. + // When type params are created in the 'P' case of (*importReader).obj(), + // the associated constraint type may not be complete due to recursion. + // Therefore, we defer calling SetConstraint there, and call it here instead + // after all types are complete. + for _, d := range p.later { + d.t.SetConstraint(d.constraint) + } // record all referenced packages as imports list := append(([]*types2.Package)(nil), pkgList[1:]...) sort.Sort(byPath(list)) @@ -191,6 +199,11 @@ func ImportData(imports map[string]*types2.Package, data, path string) (pkg *typ return localpkg, nil } +type setConstraintArgs struct { + t *types2.TypeParam + constraint types2.Type +} + type iimporter struct { exportVersion int64 ipath string @@ -206,6 +219,9 @@ type iimporter struct { tparamIndex map[ident]*types2.TypeParam interfaceList []*types2.Interface + + // Arguments for calls to SetConstraint that are deferred due to recursive types + later []setConstraintArgs } func (p *iimporter) doDecl(pkg *types2.Package, name string) { @@ -401,7 +417,11 @@ func (r *importReader) obj(name string) { } iface.MarkImplicit() } - t.SetConstraint(constraint) + // The constraint type may not be complete, if we + // are in the middle of a type recursion involving type + // constraints. So, we defer SetConstraint until we have + // completely set up all types in ImportData. + r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint}) case 'V': typ := r.typ() diff --git a/src/cmd/compile/internal/typecheck/iimport.go b/src/cmd/compile/internal/typecheck/iimport.go index bc34d3933a..ef91f550a5 100644 --- a/src/cmd/compile/internal/typecheck/iimport.go +++ b/src/cmd/compile/internal/typecheck/iimport.go @@ -354,15 +354,18 @@ func (r *importReader) doDecl(sym *types.Sym) *ir.Name { // declaration before recursing. n := importtype(pos, sym) t := n.Type() + + // Because of recursion, we need to defer width calculations and + // instantiations on intermediate types until the top-level type is + // fully constructed. Note that we can have recursion via type + // constraints. + types.DeferCheckSize() + deferDoInst() if tag == 'U' { rparams := r.typeList() t.SetRParams(rparams) } - // We also need to defer width calculations until - // after the underlying type has been assigned. - types.DeferCheckSize() - deferDoInst() underlying := r.typ() t.SetUnderlying(underlying) diff --git a/src/go/internal/gcimporter/iimport.go b/src/go/internal/gcimporter/iimport.go index 8ec4c5413b..bff1c09cc9 100644 --- a/src/go/internal/gcimporter/iimport.go +++ b/src/go/internal/gcimporter/iimport.go @@ -181,6 +181,15 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea p.doDecl(localpkg, name) } + // SetConstraint can't be called if the constraint type is not yet complete. + // When type params are created in the 'P' case of (*importReader).obj(), + // the associated constraint type may not be complete due to recursion. + // Therefore, we defer calling SetConstraint there, and call it here instead + // after all types are complete. + for _, d := range p.later { + d.t.SetConstraint(d.constraint) + } + for _, typ := range p.interfaceList { typ.Complete() } @@ -195,6 +204,11 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataRea return localpkg, nil } +type setConstraintArgs struct { + t *types.TypeParam + constraint types.Type +} + type iimporter struct { exportVersion int64 ipath string @@ -211,6 +225,9 @@ type iimporter struct { fake fakeFileSet interfaceList []*types.Interface + + // Arguments for calls to SetConstraint that are deferred due to recursive types + later []setConstraintArgs } func (p *iimporter) doDecl(pkg *types.Package, name string) { @@ -391,7 +408,11 @@ func (r *importReader) obj(name string) { } iface.MarkImplicit() } - t.SetConstraint(constraint) + // The constraint type may not be complete, if we + // are in the middle of a type recursion involving type + // constraints. So, we defer SetConstraint until we have + // completely set up all types in ImportData. + r.p.later = append(r.p.later, setConstraintArgs{t: t, constraint: constraint}) case 'V': typ := r.typ() diff --git a/test/typeparam/issue51219.dir/a.go b/test/typeparam/issue51219.dir/a.go new file mode 100644 index 0000000000..3ed4322dbf --- /dev/null +++ b/test/typeparam/issue51219.dir/a.go @@ -0,0 +1,59 @@ +// 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 I is the first basic test for the issue, which relates to a type that is recursive +// via a type constraint. (In this test, I -> IConstraint -> MyStruct -> I.) +type JsonRaw []byte + +type MyStruct struct { + x *I[JsonRaw] +} + +type IConstraint interface { + JsonRaw | MyStruct +} + +type I[T IConstraint] struct { +} + +// The following types form an even more complex recursion (through two type +// constraints), and model the actual types in the issue (#51219) more closely. +// However, they don't reveal any new issue. But it seems useful to leave this +// complex set of types in a test in case it might be broken by future changes. + +type Message struct { + Interaction *Interaction[JsonRaw] `json:"interaction,omitempty"` +} + +type ResolvedDataConstraint interface { + User | Message +} + +type Snowflake uint64 + +type ResolvedData[T ResolvedDataConstraint] map[Snowflake]T + +type User struct { +} + +type Resolved struct { + Users ResolvedData[User] `json:"users,omitempty"` +} + +type resolvedInteractionWithOptions struct { + Resolved Resolved `json:"resolved,omitempty"` +} + +type UserCommandInteractionData struct { + resolvedInteractionWithOptions +} + +type InteractionDataConstraint interface { + JsonRaw | UserCommandInteractionData +} + +type Interaction[DataT InteractionDataConstraint] struct { +} diff --git a/test/typeparam/issue51219.dir/b.go b/test/typeparam/issue51219.dir/b.go new file mode 100644 index 0000000000..c1590725b0 --- /dev/null +++ b/test/typeparam/issue51219.dir/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 b + +import "a" + +type InteractionRequest[T a.InteractionDataConstraint] struct { + a.Interaction[T] +} diff --git a/test/typeparam/issue51219.dir/main.go b/test/typeparam/issue51219.dir/main.go new file mode 100644 index 0000000000..c5cffd111c --- /dev/null +++ b/test/typeparam/issue51219.dir/main.go @@ -0,0 +1,18 @@ +// 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 + +import ( + "a" + "b" + "fmt" +) + +func main() { + var x a.I[a.JsonRaw] + var y b.InteractionRequest[a.JsonRaw] + + fmt.Printf("%v %v\n", x, y) +} diff --git a/test/typeparam/issue51219.go b/test/typeparam/issue51219.go new file mode 100644 index 0000000000..642f4bf49f --- /dev/null +++ b/test/typeparam/issue51219.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// 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 diff --git a/test/typeparam/issue51219.out b/test/typeparam/issue51219.out new file mode 100644 index 0000000000..99c5b9aa9b --- /dev/null +++ b/test/typeparam/issue51219.out @@ -0,0 +1 @@ +{} {{}} From 20b177268fe6d5711a104e5fcd09b7b1ad6a561b Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 17 Feb 2022 19:28:19 -0500 Subject: [PATCH 03/44] reflect: call ABIInternal moveMakeFuncArgPtrs on ARM64 Save some stack space, to avoid nosplit overflow in -race -N -l build. For #51247. Change-Id: I7357d6227f816a612a64f55f7ca1b1384e9268e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/386714 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Gopher Robot Reviewed-by: Michael Knyszek --- src/reflect/asm_arm64.s | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/reflect/asm_arm64.s b/src/reflect/asm_arm64.s index 5b9b3573fa..812b8a02c3 100644 --- a/src/reflect/asm_arm64.s +++ b/src/reflect/asm_arm64.s @@ -33,9 +33,14 @@ TEXT ·makeFuncStub(SB),(NOSPLIT|WRAPPER),$432 ADD $LOCAL_REGARGS, RSP, R20 CALL runtime·spillArgs(SB) MOVD R26, 32(RSP) // outside of moveMakeFuncArgPtrs's arg area +#ifdef GOEXPERIMENT_regabiargs + MOVD R26, R0 + MOVD R20, R1 +#else MOVD R26, 8(RSP) MOVD R20, 16(RSP) - CALL ·moveMakeFuncArgPtrs(SB) +#endif + CALL ·moveMakeFuncArgPtrs(SB) MOVD 32(RSP), R26 MOVD R26, 8(RSP) MOVD $argframe+0(FP), R3 @@ -61,9 +66,14 @@ TEXT ·methodValueCall(SB),(NOSPLIT|WRAPPER),$432 ADD $LOCAL_REGARGS, RSP, R20 CALL runtime·spillArgs(SB) MOVD R26, 32(RSP) // outside of moveMakeFuncArgPtrs's arg area +#ifdef GOEXPERIMENT_regabiargs + MOVD R26, R0 + MOVD R20, R1 +#else MOVD R26, 8(RSP) MOVD R20, 16(RSP) - CALL ·moveMakeFuncArgPtrs(SB) +#endif + CALL ·moveMakeFuncArgPtrs(SB) MOVD 32(RSP), R26 MOVD R26, 8(RSP) MOVD $argframe+0(FP), R3 From d93cc8cb9639212ee674ecbc9149fb897dd8fd77 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 17 Feb 2022 19:43:49 -0500 Subject: [PATCH 04/44] runtime: define racefuncenter and racefuncexit as ABIInternal They are called from compiler instrumented code as ABIInternal. Define them as ABIInternal to avoid the wrappers and save some stack space, to avoid nosplit overflow in -race -N -l build. For #51247. Change-Id: Iadad7d6da8ac03780a7b02b03b004c52d34e020a Reviewed-on: https://go-review.googlesource.com/c/go/+/386715 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Gopher Robot Reviewed-by: Michael Knyszek --- src/runtime/race_arm64.s | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/runtime/race_arm64.s b/src/runtime/race_arm64.s index 798e23294a..59fade02ee 100644 --- a/src/runtime/race_arm64.s +++ b/src/runtime/race_arm64.s @@ -188,8 +188,12 @@ ret: // func runtime·racefuncenter(pc uintptr) // Called from instrumented code. -TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8 +TEXT runtime·racefuncenter(SB), NOSPLIT, $0-8 +#ifdef GOEXPERIMENT_regabiargs + MOVD R0, R9 // callpc +#else MOVD callpc+0(FP), R9 +#endif JMP racefuncenter<>(SB) // Common code for racefuncenter @@ -205,7 +209,7 @@ TEXT racefuncenter<>(SB), NOSPLIT, $0-0 // func runtime·racefuncexit() // Called from instrumented code. -TEXT runtime·racefuncexit(SB), NOSPLIT, $0-0 +TEXT runtime·racefuncexit(SB), NOSPLIT, $0-0 load_g MOVD g_racectx(g), R0 // race context // void __tsan_func_exit(ThreadState *thr); From d27248c52f8545aa3c3de07e3d2568da5c5df785 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 17 Feb 2022 19:45:50 -0500 Subject: [PATCH 05/44] runtime: save some stack space for racecall on ARM64 To avoid nosplit overflow in -race -N -l build. For #51247. Change-Id: I48426bbd4adefd18eaf26ed51b4113c6a28305b8 Reviewed-on: https://go-review.googlesource.com/c/go/+/386716 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Gopher Robot Reviewed-by: Michael Knyszek --- src/runtime/race_arm64.s | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/runtime/race_arm64.s b/src/runtime/race_arm64.s index 59fade02ee..95fec0b9c6 100644 --- a/src/runtime/race_arm64.s +++ b/src/runtime/race_arm64.s @@ -396,12 +396,12 @@ racecallatomic_ignore: // Addr is outside the good range. // Call __tsan_go_ignore_sync_begin to ignore synchronization during the atomic op. // An attempt to synchronize on the address would cause crash. - MOVD R9, R20 // remember the original function + MOVD R9, R21 // remember the original function MOVD $__tsan_go_ignore_sync_begin(SB), R9 load_g MOVD g_racectx(g), R0 // goroutine context BL racecall<>(SB) - MOVD R20, R9 // restore the original function + MOVD R21, R9 // restore the original function // Call the atomic function. // racecall will call LLVM race code which might clobber R28 (g) load_g @@ -428,10 +428,12 @@ TEXT runtime·racecall(SB), NOSPLIT, $0-0 JMP racecall<>(SB) // Switches SP to g0 stack and calls (R9). Arguments already set. -TEXT racecall<>(SB), NOSPLIT, $0-0 +// Clobbers R19, R20. +TEXT racecall<>(SB), NOSPLIT|NOFRAME, $0-0 MOVD g_m(g), R10 // Switch to g0 stack. MOVD RSP, R19 // callee-saved, preserved across the CALL + MOVD R30, R20 // callee-saved, preserved across the CALL MOVD m_g0(R10), R11 CMP R11, g BEQ call // already on g0 @@ -440,7 +442,7 @@ TEXT racecall<>(SB), NOSPLIT, $0-0 call: BL R9 MOVD R19, RSP - RET + JMP (R20) // C->Go callback thunk that allows to call runtime·racesymbolize from C code. // Direct Go->C race call has only switched SP, finish g->g0 switch by setting correct g. From 61b5c866a9507524d0a3d7a7e0c892c975ca081b Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Fri, 18 Feb 2022 14:51:58 -0500 Subject: [PATCH 06/44] doc/go1.18: document Go 1.17 bootstrap and //go:build fix For #44505 and #41184. Change-Id: I9503292dace1aa60de167ca5807bf131554465b9 Reviewed-on: https://go-review.googlesource.com/c/go/+/386774 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: Jeremy Faller --- doc/go1.18.html | 50 ++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index c75bfe9e5d..ce4030799a 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -250,6 +250,8 @@ Do not send CLs removing the interior tags from such phrases.

Go command

+

go get

+

go get no longer builds or installs packages in module-aware mode. go get is now dedicated to @@ -269,6 +271,8 @@ Do not send CLs removing the interior tags from such phrases. and installs packages, as before.

+

go version

+

The go command now embeds version control information in binaries including the currently checked-out revision, commit time, and a @@ -303,6 +307,8 @@ Do not send CLs removing the interior tags from such phrases. debug/buildinfo package from go 1.18+.

+

go mod download

+

If the main module's go.mod file specifies go 1.17 @@ -316,6 +322,8 @@ Do not send CLs removing the interior tags from such phrases. go mod download all.

+

go mod vendor

+

The go mod vendor subcommand now supports a -o flag to set the output directory. @@ -325,6 +333,8 @@ Do not send CLs removing the interior tags from such phrases. third-party tools that need to collect package source code.)

+

go build -asan

+

The go build command and related commands now support an -asan flag that enables interoperation @@ -332,6 +342,8 @@ Do not send CLs removing the interior tags from such phrases. option -fsanitize=address).

+

go mod tidy

+

The go mod tidy command now retains additional checksums in the go.sum file for modules whose source @@ -342,6 +354,8 @@ Do not send CLs removing the interior tags from such phrases. module's go.mod file.

+

go work

+

The go command now supports a "Workspace" mode. If a go.work file is found in the working directory or a @@ -355,6 +369,8 @@ Do not send CLs removing the interior tags from such phrases. documentation.

+

go test

+

The go command now supports additional command line options for the new fuzzing support described @@ -376,11 +392,28 @@ Do not send CLs removing the interior tags from such phrases.

+

//go:build lines

+

- TODO: https://golang.org/cl/240611: 240611: cmd/fix: add buildtag fix +Go 1.17 introduced //go:build lines as a more readable way to write build constraints, +instead of // +build lines. +As of Go 1.17, gofmt adds //go:build lines +to match existing +build lines and keeps them in sync, +while go vet diagnoses when they are out of sync.

-

gofmt

+

Since the release of Go 1.18 marks the end of support for Go 1.16, +all supported versions of Go now understand //go:build lines. +In Go 1.18, go fix now removes the now-obsolete +// +build lines in modules declaring +go 1.17 or later in their go.mod files. +

+ +

+For more information, see https://go.dev/design/draft-gobuild. +

+ +

Gofmt

gofmt now reads and formats input files concurrently, with a @@ -388,7 +421,7 @@ Do not send CLs removing the interior tags from such phrases. multiple CPUs, gofmt should now be significantly faster.

-

vet

+

Vet

Updates for Generics

@@ -510,10 +543,17 @@ Do not send CLs removing the interior tags from such phrases. new go command -asan option.

-

Build

+

Bootstrap

- TODO: https://golang.org/cl/369914: for default bootstrap, use Go 1.17 if present, falling back to Go 1.4 +When building a Go release from source and GOROOT_BOOTSTRAP +is not set, previous versions of Go looked for a Go 1.4 or later bootstrap toolchain +in the directory $HOME/go1.4 (%HOMEDRIVE%%HOMEPATH%\go1.4 on Windows). +Go now looks first for $HOME/go1.17 or $HOME/sdk/go1.17 +before falling back to $HOME/go1.4. +We intend for Go 1.19 to require Go 1.17 or later for bootstrap, +and this change should make the transition smoother. +For more details, see go.dev/issue/44505.

Core library

From e002cf4df7fcd9925916ed78df7ed2a49031ed2e Mon Sep 17 00:00:00 2001 From: George Looshch Date: Sat, 15 Jan 2022 21:43:05 +0200 Subject: [PATCH 07/44] strings: fix typo in comment Remove unnecessary whitespace in noescape comment Fixes #50634 Change-Id: I1c8d16c020b05678577d349470fac7e7ab8a10b7 Reviewed-on: https://go-review.googlesource.com/c/go/+/378815 Reviewed-by: Ian Lance Taylor Trust: Dmitri Shuralyov --- src/strings/builder.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/strings/builder.go b/src/strings/builder.go index 547e52e84d..ba4df618bf 100644 --- a/src/strings/builder.go +++ b/src/strings/builder.go @@ -17,10 +17,9 @@ type Builder struct { buf []byte } -// noescape hides a pointer from escape analysis. noescape is -// the identity function but escape analysis doesn't think the -// output depends on the input. noescape is inlined and currently -// compiles down to zero instructions. +// noescape hides a pointer from escape analysis. It is the identity function +// but escape analysis doesn't think the output depends on the input. +// noescape is inlined and currently compiles down to zero instructions. // USE CAREFULLY! // This was copied from the runtime; see issues 23382 and 7921. //go:nosplit From 903e7cc69971b2c7bf40a1e7ff2a9e3dd353dc5a Mon Sep 17 00:00:00 2001 From: Nick Sherron Date: Fri, 18 Feb 2022 22:43:31 +0000 Subject: [PATCH 08/44] doc/go1.18: fix grammar error sed 's/the/that/g' Change-Id: I3f539817b055d54b0ec99346555ac91b756d9ed6 GitHub-Last-Rev: 2e7df1c3462d4b3a17e9a05ff178341f4ee369b0 GitHub-Pull-Request: golang/go#51267 Reviewed-on: https://go-review.googlesource.com/c/go/+/386854 Reviewed-by: Ian Lance Taylor Trust: Dmitri Shuralyov --- doc/go1.18.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index ce4030799a..8a5c1d8fad 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -84,7 +84,7 @@ Do not send CLs removing the interior tags from such phrases.
  • The new predeclared identifier - comparable is an interface the denotes the set of all types which can be + comparable is an interface that denotes the set of all types which can be compared using == or !=. It may only be used as (or embedded in) a type constraint.
  • From 0261fa616a16dc37b862691f79c7b4d301dfbe4a Mon Sep 17 00:00:00 2001 From: hopehook Date: Sat, 19 Feb 2022 12:33:16 +0800 Subject: [PATCH 09/44] testdata: fix typo in comment Change-Id: If3d5884d9f3f32606c510af5597529b832a8f4a9 Reviewed-on: https://go-review.googlesource.com/c/go/+/386934 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Trust: Dmitri Shuralyov Auto-Submit: Dmitri Shuralyov --- src/cmd/compile/internal/types2/testdata/examples/methods.go2 | 2 +- src/go/types/testdata/examples/methods.go2 | 2 +- src/runtime/testdata/testprogcgo/aprof.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cmd/compile/internal/types2/testdata/examples/methods.go2 b/src/cmd/compile/internal/types2/testdata/examples/methods.go2 index 1d76d553dc..a46f789d60 100644 --- a/src/cmd/compile/internal/types2/testdata/examples/methods.go2 +++ b/src/cmd/compile/internal/types2/testdata/examples/methods.go2 @@ -35,7 +35,7 @@ func (t T1[[ /* ERROR must be an identifier */ ]int]) m2() {} // style. In m3 below, int is the name of the local receiver type parameter // and it shadows the predeclared identifier int which then cannot be used // anymore as expected. -// This is no different from locally redelaring a predeclared identifier +// This is no different from locally re-declaring a predeclared identifier // and usually should be avoided. There are some notable exceptions; e.g., // sometimes it makes sense to use the identifier "copy" which happens to // also be the name of a predeclared built-in function. diff --git a/src/go/types/testdata/examples/methods.go2 b/src/go/types/testdata/examples/methods.go2 index 1d76d553dc..a46f789d60 100644 --- a/src/go/types/testdata/examples/methods.go2 +++ b/src/go/types/testdata/examples/methods.go2 @@ -35,7 +35,7 @@ func (t T1[[ /* ERROR must be an identifier */ ]int]) m2() {} // style. In m3 below, int is the name of the local receiver type parameter // and it shadows the predeclared identifier int which then cannot be used // anymore as expected. -// This is no different from locally redelaring a predeclared identifier +// This is no different from locally re-declaring a predeclared identifier // and usually should be avoided. There are some notable exceptions; e.g., // sometimes it makes sense to use the identifier "copy" which happens to // also be the name of a predeclared built-in function. diff --git a/src/runtime/testdata/testprogcgo/aprof.go b/src/runtime/testdata/testprogcgo/aprof.go index c70d6333bb..16870144dd 100644 --- a/src/runtime/testdata/testprogcgo/aprof.go +++ b/src/runtime/testdata/testprogcgo/aprof.go @@ -10,7 +10,7 @@ package main // This is a regression test for issue 14599, where profiling fails when the // function is the first C function. Exported functions are the first C // functions, so we use an exported function. Exported functions are created in -// lexigraphical order of source files, so this file is named aprof.go to +// lexicographical order of source files, so this file is named aprof.go to // ensure its function is first. // extern void CallGoNop(); From 851ecea4cc99ab276109493477b2c7e30c253ea8 Mon Sep 17 00:00:00 2001 From: hopehook Date: Sun, 13 Feb 2022 22:03:56 +0800 Subject: [PATCH 10/44] encoding/xml: embedded reference to substruct causes XML marshaller to panic on encoding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When encoding a xml attribute is zero value (IsValid == false), we need a `continue` to jump over the attribute. If not, followed marshalAttr function will panic. Fixes: #50164 Change-Id: I42e064558e7becfbf47728b14cbf5c7afa1e8798 Reviewed-on: https://go-review.googlesource.com/c/go/+/385514 Reviewed-by: Daniel Martí Trust: Daniel Martí Run-TryBot: Daniel Martí TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor --- src/encoding/xml/marshal.go | 2 +- src/encoding/xml/marshal_test.go | 36 ++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/src/encoding/xml/marshal.go b/src/encoding/xml/marshal.go index 6859be04a2..7792ac77f8 100644 --- a/src/encoding/xml/marshal.go +++ b/src/encoding/xml/marshal.go @@ -512,7 +512,7 @@ func (p *printer) marshalValue(val reflect.Value, finfo *fieldInfo, startTemplat } fv := finfo.value(val, dontInitNilPointers) - if finfo.flags&fOmitEmpty != 0 && isEmptyValue(fv) { + if finfo.flags&fOmitEmpty != 0 && (!fv.IsValid() || isEmptyValue(fv)) { continue } diff --git a/src/encoding/xml/marshal_test.go b/src/encoding/xml/marshal_test.go index 5fdbae7ef0..3fe7e2dc00 100644 --- a/src/encoding/xml/marshal_test.go +++ b/src/encoding/xml/marshal_test.go @@ -2495,3 +2495,39 @@ func TestInvalidXMLName(t *testing.T) { t.Errorf("error %q does not contain %q", err, want) } } + +// Issue 50164. Crash on zero value XML attribute. +type LayerOne struct { + XMLName Name `xml:"l1"` + + Value *float64 `xml:"value,omitempty"` + *LayerTwo `xml:",omitempty"` +} + +type LayerTwo struct { + ValueTwo *int `xml:"value_two,attr,omitempty"` +} + +func TestMarshalZeroValue(t *testing.T) { + proofXml := `1.2345` + var l1 LayerOne + err := Unmarshal([]byte(proofXml), &l1) + if err != nil { + t.Fatalf("unmarshal XML error: %v", err) + } + want := float64(1.2345) + got := *l1.Value + if got != want { + t.Fatalf("unexpected unmarshal result, want %f but got %f", want, got) + } + + // Marshal again (or Encode again) + // In issue 50164, here `Marshal(l1)` will panic because of the zero value of xml attribute ValueTwo `value_two`. + anotherXML, err := Marshal(l1) + if err != nil { + t.Fatalf("marshal XML error: %v", err) + } + if string(anotherXML) != proofXml { + t.Fatalf("unexpected unmarshal result, want %q but got %q", proofXml, anotherXML) + } +} From c9fe126c8bf25d14b233f1ccaff12c1bffbd4971 Mon Sep 17 00:00:00 2001 From: Alberto Donizetti Date: Sat, 19 Feb 2022 18:13:52 +0100 Subject: [PATCH 11/44] doc/go1.18: fix a few small typos, add a few commas Updates #47694 Change-Id: I6c1c3698fdd55fe83c756f28776d1d26dba0a9df Reviewed-on: https://go-review.googlesource.com/c/go/+/386974 Trust: Alberto Donizetti Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 8a5c1d8fad..8617dd8fe1 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -137,7 +137,7 @@ Do not send CLs removing the interior tags from such phrases.
  • Embedding a type parameter, or a pointer to a type parameter, as - an unnamed field in a struct type is not permitted. Similarly + an unnamed field in a struct type is not permitted. Similarly, embedding a type parameter in an interface type is not permitted. Whether these will ever be permitted is unclear at present.
  • @@ -275,7 +275,7 @@ Do not send CLs removing the interior tags from such phrases.

    The go command now embeds version control information in - binaries including the currently checked-out revision, commit time, and a + binaries. It includes the currently checked-out revision, commit time, and a flag indicating whether edited or untracked files are present. Version control information is embedded if the go command is invoked in a directory within a Git, Mercurial, Fossil, or Bazaar repository, and the @@ -285,7 +285,7 @@ Do not send CLs removing the interior tags from such phrases.

    - Additionally, the go command embeds information about the build + Additionally, the go command embeds information about the build, including build and tool tags (set with -tags), compiler, assembler, and linker flags (like -gcflags), whether cgo was enabled, and if it was, the values of the cgo environment variables @@ -509,7 +509,7 @@ For more information, see https://

    - The new compiler -asan option supports the + The new -asan compiler option supports the new go command -asan option.

    @@ -539,7 +539,7 @@ For more information, see
    https://

    - The new linker -asan option supports the + The new -asan linker option supports the new go command -asan option.

    @@ -680,8 +680,8 @@ For more details, see
    go.dev/issue/44505

    - The methods Reader.Reset and - Writer.Reset + The Reader.Reset and + Writer.Reset methods now use the default buffer size when called on objects with a nil buffer.

    @@ -1043,7 +1043,7 @@ For more details, see go.dev/issue/44505
    os/user

    - User.GroupIds. + User.GroupIds now uses a Go native implementation when cgo is not available.

    @@ -1056,7 +1056,7 @@ For more details, see go.dev/issue/44505Value.SetIterKey and Value.SetIterValue methods set a Value using a map iterator as the source. They are equivalent to - Value.Set(iter.Key()) and Value.Set(iter.Value()) but + Value.Set(iter.Key()) and Value.Set(iter.Value()), but do fewer allocations.

    @@ -1219,7 +1219,7 @@ For more details, see go.dev/issue/44505
    syscall/js

    - Wrapper interface has been removed. + The Wrapper interface has been removed.

    @@ -1291,7 +1291,7 @@ For more details, see go.dev/issue/44505
    unicode/utf8

    - The AppendRune function appends the UTF-8 new + The new AppendRune function appends the UTF-8 encoding of a rune to a []byte.

    From d17b65ff54a1824288eb68fe3fbc8c7beed14bb6 Mon Sep 17 00:00:00 2001 From: Russ Cox Date: Tue, 22 Feb 2022 09:05:21 -0500 Subject: [PATCH 12/44] =?UTF-8?q?crypto/x509,=20runtime:=20fix=20occasiona?= =?UTF-8?q?l=20spurious=20=E2=80=9Ccertificate=20is=20expired=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit As documented in #51209, we have been seeing a low-rate failure on macOS builders caused by spurious x509 “certificate is expired” errors. The root cause is that CFDateCreate takes a float64, but it is being passed a uintptr instead. That is, we're not even putting CFDateCreate's argument in the right register during the call. Luckily, having just computed the argument by calling time.Duration.Seconds, which returns a float64, most of the time the argument we want is still in the right floating point register, somewhat accidentally. The only time the lucky accident doesn't happen is when the goroutine is rescheduled between calling time.Duration.Seconds and calling into CFDateCreate *and* the rescheduling smashes the floating point register, which can happen during various block memory moves, since the floating point registers are also the SIMD registers. Passing the float64 through explicitly eliminates the problem. It is difficult to write a test for this that is suitable for inclusion in the standard library. We will have to rely on the builders to start flaking again if somehow this problem is reintroduced. For future reference, there is a standalone test that used to fail every few seconds at https://go.dev/play/p/OWfDpxgnW9g. Fixes #51209. Change-Id: I8b334a51e41f406b13f37270e9175c64fe6f55ea Reviewed-on: https://go-review.googlesource.com/c/go/+/387255 Trust: Russ Cox Run-TryBot: Russ Cox Reviewed-by: David Chase Reviewed-by: Cherry Mui TryBot-Result: Gopher Robot --- src/crypto/x509/internal/macos/corefoundation.go | 8 ++++---- src/runtime/sys_darwin.go | 6 +++--- src/runtime/sys_darwin_amd64.s | 9 +++++---- src/runtime/sys_darwin_arm64.s | 9 +++++---- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/src/crypto/x509/internal/macos/corefoundation.go b/src/crypto/x509/internal/macos/corefoundation.go index cda1d95d81..75c212910b 100644 --- a/src/crypto/x509/internal/macos/corefoundation.go +++ b/src/crypto/x509/internal/macos/corefoundation.go @@ -48,7 +48,7 @@ func CFStringToString(ref CFRef) string { // TimeToCFDateRef converts a time.Time into an apple CFDateRef func TimeToCFDateRef(t time.Time) CFRef { secs := t.Sub(time.Date(2001, 1, 1, 0, 0, 0, 0, time.UTC)).Seconds() - ref := CFDateCreate(int(secs)) + ref := CFDateCreate(secs) return ref } @@ -170,8 +170,8 @@ func x509_CFArrayAppendValue_trampoline() //go:cgo_import_dynamic x509_CFDateCreate CFDateCreate "/System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation" -func CFDateCreate(seconds int) CFRef { - ret := syscall(abi.FuncPCABI0(x509_CFDateCreate_trampoline), kCFAllocatorDefault, uintptr(seconds), 0, 0, 0, 0) +func CFDateCreate(seconds float64) CFRef { + ret := syscall(abi.FuncPCABI0(x509_CFDateCreate_trampoline), kCFAllocatorDefault, 0, 0, 0, 0, seconds) return CFRef(ret) } func x509_CFDateCreate_trampoline() @@ -193,7 +193,7 @@ func CFStringCreateExternalRepresentation(strRef CFRef) CFRef { func x509_CFStringCreateExternalRepresentation_trampoline() // syscall is implemented in the runtime package (runtime/sys_darwin.go) -func syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) uintptr +func syscall(fn, a1, a2, a3, a4, a5 uintptr, f1 float64) uintptr // ReleaseCFArray iterates through an array, releasing its contents, and then // releases the array itself. This is necessary because we cannot, easily, set the diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index 80dd1a0378..7573d0f9b3 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -91,13 +91,13 @@ func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintpt //go:linkname crypto_x509_syscall crypto/x509/internal/macos.syscall //go:nosplit //go:cgo_unsafe_args -func crypto_x509_syscall(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1 uintptr) { +func crypto_x509_syscall(fn, a1, a2, a3, a4, a5 uintptr, f1 float64) (r1 uintptr) { entersyscall() - libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallNoErr)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall_x509)), unsafe.Pointer(&fn)) exitsyscall() return } -func syscallNoErr() +func syscall_x509() // The *_trampoline functions convert from the Go calling convention to the C calling convention // and then call the underlying libc function. They are defined in sys_darwin_$ARCH.s. diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s index 5d89cda8e6..db4715d2b7 100644 --- a/src/runtime/sys_darwin_amd64.s +++ b/src/runtime/sys_darwin_amd64.s @@ -831,9 +831,10 @@ ok: POPQ BP RET -// syscallNoErr is like syscall6 but does not check for errors, and -// only returns one value, for use with standard C ABI library functions. -TEXT runtime·syscallNoErr(SB),NOSPLIT,$0 +// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors, +// takes 5 uintptrs and 1 float64, and only returns one value, +// for use with standard C ABI functions. +TEXT runtime·syscall_x509(SB),NOSPLIT,$0 PUSHQ BP MOVQ SP, BP SUBQ $16, SP @@ -842,7 +843,7 @@ TEXT runtime·syscallNoErr(SB),NOSPLIT,$0 MOVQ (3*8)(DI), DX // a3 MOVQ (4*8)(DI), CX // a4 MOVQ (5*8)(DI), R8 // a5 - MOVQ (6*8)(DI), R9 // a6 + MOVQ (6*8)(DI), X0 // f1 MOVQ DI, (SP) MOVQ (1*8)(DI), DI // a1 XORL AX, AX // vararg: say "no float args" diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s index 96d2ed1076..e57ac53e10 100644 --- a/src/runtime/sys_darwin_arm64.s +++ b/src/runtime/sys_darwin_arm64.s @@ -736,9 +736,10 @@ TEXT runtime·syscall6X(SB),NOSPLIT,$0 ok: RET -// syscallNoErr is like syscall6 but does not check for errors, and -// only returns one value, for use with standard C ABI library functions. -TEXT runtime·syscallNoErr(SB),NOSPLIT,$0 +// syscall_x509 is for crypto/x509. It is like syscall6 but does not check for errors, +// takes 5 uintptrs and 1 float64, and only returns one value, +// for use with standard C ABI functions. +TEXT runtime·syscall_x509(SB),NOSPLIT,$0 SUB $16, RSP // push structure pointer MOVD R0, (RSP) @@ -747,7 +748,7 @@ TEXT runtime·syscallNoErr(SB),NOSPLIT,$0 MOVD 24(R0), R2 // a3 MOVD 32(R0), R3 // a4 MOVD 40(R0), R4 // a5 - MOVD 48(R0), R5 // a6 + FMOVD 48(R0), F0 // f1 MOVD 8(R0), R0 // a1 BL (R12) From 3140625606f83328a5c7754fd952ed8d52a76404 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Tue, 22 Feb 2022 12:54:57 -0500 Subject: [PATCH 13/44] doc/go1.18: correct "go build -asan" HTML tag The tag was "go-mod-vendor", which doesn't match the content. Also move that section later, so "go mod" sections stay together. For #47694. Change-Id: Id4fa7ee0768682a9aadfeb1b2f1d723e7521896b Reviewed-on: https://go-review.googlesource.com/c/go/+/387354 Trust: Cherry Mui Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 8617dd8fe1..25d85dd92a 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -333,15 +333,6 @@ Do not send CLs removing the interior tags from such phrases. third-party tools that need to collect package source code.)

    -

    go build -asan

    - -

    - The go build command and related commands - now support an -asan flag that enables interoperation - with C (or C++) code compiled with the address sanitizer (C compiler - option -fsanitize=address). -

    -

    go mod tidy

    @@ -369,6 +360,15 @@ Do not send CLs removing the interior tags from such phrases. documentation.

    +

    go build -asan

    + +

    + The go build command and related commands + now support an -asan flag that enables interoperation + with C (or C++) code compiled with the address sanitizer (C compiler + option -fsanitize=address). +

    +

    go test

    From 35170365c83085024e4855c14032599f5513d563 Mon Sep 17 00:00:00 2001 From: Martin Sucha Date: Tue, 22 Feb 2022 21:51:04 +0100 Subject: [PATCH 14/44] net: document methods of Buffers There is code in the wild that copies the Buffers slice, but not the contents. Let's document explicitly that it is not safe to do so. Updates #45163 Change-Id: Id45e27b93037d4e9f2bfde2558e7869983b60bcf Reviewed-on: https://go-review.googlesource.com/c/go/+/387434 Reviewed-by: Ian Lance Taylor Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Damien Neil --- src/net/net.go | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/net/net.go b/src/net/net.go index 77e54a9125..d91e743a01 100644 --- a/src/net/net.go +++ b/src/net/net.go @@ -703,6 +703,12 @@ var ( _ io.Reader = (*Buffers)(nil) ) +// WriteTo writes contents of the buffers to w. +// +// WriteTo implements io.WriterTo for Buffers. +// +// WriteTo modifies the slice v as well as v[i] for 0 <= i < len(v), +// but does not modify v[i][j] for any i, j. func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) { if wv, ok := w.(buffersWriter); ok { return wv.writeBuffers(v) @@ -719,6 +725,12 @@ func (v *Buffers) WriteTo(w io.Writer) (n int64, err error) { return n, nil } +// Read from the buffers. +// +// Read implements io.Reader for Buffers. +// +// Read modifies the slice v as well as v[i] for 0 <= i < len(v), +// but does not modify v[i][j] for any i, j. func (v *Buffers) Read(p []byte) (n int, err error) { for len(p) > 0 && len(*v) > 0 { n0 := copy(p, (*v)[0]) From d0c3b0116217a898f2e5d2d00cc5f0356ea5ad1e Mon Sep 17 00:00:00 2001 From: Michael Pratt Date: Wed, 23 Feb 2022 12:23:41 -0500 Subject: [PATCH 15/44] doc/go1.18: drop misplaced period Change-Id: Id29f352c8d2e61672f55294120058b1f585f7aeb Reviewed-on: https://go-review.googlesource.com/c/go/+/387655 Trust: Michael Pratt Run-TryBot: Michael Pratt Reviewed-by: Jeremy Faller TryBot-Result: Gopher Robot --- doc/go1.18.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 25d85dd92a..8c786b94fc 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -1210,7 +1210,7 @@ For more details, see go.dev/issue/44505

    - SysProcAttr.Pdeathsig. + SysProcAttr.Pdeathsig is now supported in FreeBSD.

    From e534907f65f5a3eda47a069ea0aab33306c1d616 Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 18 Feb 2022 09:19:47 -0500 Subject: [PATCH 16/44] go/types: delete unnecessary slice construction CL 374294 made our check for incorrect type parameters constraints eager, but failed to remove the construction of the bounds slice, which was no longer used. Change-Id: Ib8778fba947ef8a8414803e95d72c49b8f75c204 Reviewed-on: https://go-review.googlesource.com/c/go/+/386717 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Gopher Robot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/decl.go | 2 -- src/go/types/decl.go | 2 -- 2 files changed, 4 deletions(-) diff --git a/src/cmd/compile/internal/types2/decl.go b/src/cmd/compile/internal/types2/decl.go index 0e8f5085ba..579fa55e59 100644 --- a/src/cmd/compile/internal/types2/decl.go +++ b/src/cmd/compile/internal/types2/decl.go @@ -569,7 +569,6 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel // Keep track of bounds for later validation. var bound Type - var bounds []Type for i, f := range list { // Optimization: Re-use the previous type bound if it hasn't changed. // This also preserves the grouped output of type parameter lists @@ -584,7 +583,6 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list []*syntax.Fiel check.error(f.Type, "cannot use a type parameter as constraint") bound = Typ[Invalid] } - bounds = append(bounds, bound) } tparams[i].bound = bound } diff --git a/src/go/types/decl.go b/src/go/types/decl.go index cd6f709a56..93a37d76ce 100644 --- a/src/go/types/decl.go +++ b/src/go/types/decl.go @@ -624,7 +624,6 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList }() index := 0 - var bounds []Type for _, f := range list.List { var bound Type // NOTE: we may be able to assert that f.Type != nil here, but this is not @@ -642,7 +641,6 @@ func (check *Checker) collectTypeParams(dst **TypeParamList, list *ast.FieldList } else { bound = Typ[Invalid] } - bounds = append(bounds, bound) for i := range f.Names { tparams[index+i].bound = bound } From 163da6feb525a98dab5c1f01d81b2c705ead51ea Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 20 Feb 2022 12:58:21 -0800 Subject: [PATCH 17/44] go/types, types2: add "dynamic" flag to comparable predicate A type implements a comparable interface only if the type is statically known to be comparable. Specifically, a type cannot contain (component) interfaces that are not statically known to be comparable. This CL adds a flag "dynamic" to the comparable predicate to control whether interfaces are always (dynamically) comparable. Set the flag to true when testing for (traditional) Go comparability; set the flag to false when testing whether a type implements the comparable interface. Fixes #51257. Change-Id: If22bc047ee59337deb2e7844b8f488d67e5c5530 Reviewed-on: https://go-review.googlesource.com/c/go/+/387055 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Gopher Robot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/expr.go | 2 +- .../compile/internal/types2/instantiate.go | 2 +- src/cmd/compile/internal/types2/predicates.go | 11 +++-- .../types2/testdata/fixedbugs/issue51257.go2 | 46 +++++++++++++++++++ src/cmd/compile/internal/types2/typeset.go | 2 +- src/go/types/expr.go | 2 +- src/go/types/instantiate.go | 2 +- src/go/types/predicates.go | 11 +++-- .../types/testdata/fixedbugs/issue51257.go2 | 46 +++++++++++++++++++ src/go/types/typeset.go | 2 +- 10 files changed, 110 insertions(+), 16 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue51257.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue51257.go2 diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index 02ece21e67..ac5630dbbb 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -899,7 +899,7 @@ func (check *Checker) incomparableCause(typ Type) string { } // see if we can extract a more specific error var cause string - comparable(typ, nil, func(format string, args ...interface{}) { + comparable(typ, true, nil, func(format string, args ...interface{}) { cause = check.sprintf(format, args...) }) return cause diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index f54938b6e1..c2653a3834 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -204,7 +204,7 @@ func (check *Checker) implements(V, T Type) error { // If T is comparable, V must be comparable. // Remember as a pending error and report only if we don't have a more specific error. var pending error - if Ti.IsComparable() && ((Vi != nil && !Vi.IsComparable()) || (Vi == nil && !Comparable(V))) { + if Ti.IsComparable() && !comparable(V, false, nil, nil) { pending = errorf("%s does not implement comparable", V) } diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 0e46333af7..ba259341f6 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -102,11 +102,12 @@ func isGeneric(t Type) bool { // Comparable reports whether values of type T are comparable. func Comparable(T Type) bool { - return comparable(T, nil, nil) + return comparable(T, true, nil, nil) } +// If dynamic is set, non-type parameter interfaces are always comparable. // If reportf != nil, it may be used to report why T is not comparable. -func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{})) bool { +func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, ...interface{})) bool { if seen[T] { return true } @@ -124,7 +125,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{}) return true case *Struct: for _, f := range t.fields { - if !comparable(f.typ, seen, nil) { + if !comparable(f.typ, dynamic, seen, nil) { if reportf != nil { reportf("struct containing %s cannot be compared", f.typ) } @@ -133,7 +134,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{}) } return true case *Array: - if !comparable(t.elem, seen, nil) { + if !comparable(t.elem, dynamic, seen, nil) { if reportf != nil { reportf("%s cannot be compared", t) } @@ -141,7 +142,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{}) } return true case *Interface: - return !isTypeParam(T) || t.typeSet().IsComparable(seen) + return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) } return false } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51257.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51257.go2 new file mode 100644 index 0000000000..bc4208e6ee --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51257.go2 @@ -0,0 +1,46 @@ +// 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 f[_ comparable]() {} + +type S1 struct{ x int } +type S2 struct{ x any } +type S3 struct{ x [10]interface{ m() } } + +func _[P1 comparable, P2 S2]() { + _ = f[S1] + _ = f[S2 /* ERROR S2 does not implement comparable */ ] + _ = f[S3 /* ERROR S3 does not implement comparable */ ] + + type L1 struct { x P1 } + type L2 struct { x P2 } + _ = f[L1] + _ = f[L2 /* ERROR L2 does not implement comparable */ ] +} + + +// example from issue + +type Set[T comparable] map[T]struct{} + +func NewSetFromSlice[T comparable](items []T) *Set[T] { + s := Set[T]{} + + for _, item := range items { + s[item] = struct{}{} + } + + return &s +} + +type T struct{ x any } + +func main() { + NewSetFromSlice( /* ERROR T does not implement comparable */ []T{ + {"foo"}, + {5}, + }) +} diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index fff348bcf4..2c3e826a3f 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -39,7 +39,7 @@ func (s *_TypeSet) IsComparable(seen map[Type]bool) bool { return s.comparable } return s.is(func(t *term) bool { - return t != nil && comparable(t.typ, seen, nil) + return t != nil && comparable(t.typ, false, seen, nil) }) } diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 8747838c4b..e8038dd178 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -859,7 +859,7 @@ func (check *Checker) incomparableCause(typ Type) string { } // see if we can extract a more specific error var cause string - comparable(typ, nil, func(format string, args ...interface{}) { + comparable(typ, true, nil, func(format string, args ...interface{}) { cause = check.sprintf(format, args...) }) return cause diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go index 4aeaeb7f11..4b8e3d4661 100644 --- a/src/go/types/instantiate.go +++ b/src/go/types/instantiate.go @@ -204,7 +204,7 @@ func (check *Checker) implements(V, T Type) error { // If T is comparable, V must be comparable. // Remember as a pending error and report only if we don't have a more specific error. var pending error - if Ti.IsComparable() && ((Vi != nil && !Vi.IsComparable()) || (Vi == nil && !Comparable(V))) { + if Ti.IsComparable() && !comparable(V, false, nil, nil) { pending = errorf("%s does not implement comparable", V) } diff --git a/src/go/types/predicates.go b/src/go/types/predicates.go index 14e99bf426..0360f27ee6 100644 --- a/src/go/types/predicates.go +++ b/src/go/types/predicates.go @@ -104,11 +104,12 @@ func isGeneric(t Type) bool { // Comparable reports whether values of type T are comparable. func Comparable(T Type) bool { - return comparable(T, nil, nil) + return comparable(T, true, nil, nil) } +// If dynamic is set, non-type parameter interfaces are always comparable. // If reportf != nil, it may be used to report why T is not comparable. -func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{})) bool { +func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, ...interface{})) bool { if seen[T] { return true } @@ -126,7 +127,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{}) return true case *Struct: for _, f := range t.fields { - if !comparable(f.typ, seen, nil) { + if !comparable(f.typ, dynamic, seen, nil) { if reportf != nil { reportf("struct containing %s cannot be compared", f.typ) } @@ -135,7 +136,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{}) } return true case *Array: - if !comparable(t.elem, seen, nil) { + if !comparable(t.elem, dynamic, seen, nil) { if reportf != nil { reportf("%s cannot be compared", t) } @@ -143,7 +144,7 @@ func comparable(T Type, seen map[Type]bool, reportf func(string, ...interface{}) } return true case *Interface: - return !isTypeParam(T) || t.typeSet().IsComparable(seen) + return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) } return false } diff --git a/src/go/types/testdata/fixedbugs/issue51257.go2 b/src/go/types/testdata/fixedbugs/issue51257.go2 new file mode 100644 index 0000000000..8a3eb3278d --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue51257.go2 @@ -0,0 +1,46 @@ +// 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 f[_ comparable]() {} + +type S1 struct{ x int } +type S2 struct{ x any } +type S3 struct{ x [10]interface{ m() } } + +func _[P1 comparable, P2 S2]() { + _ = f[S1] + _ = f[S2 /* ERROR S2 does not implement comparable */ ] + _ = f[S3 /* ERROR S3 does not implement comparable */ ] + + type L1 struct { x P1 } + type L2 struct { x P2 } + _ = f[L1] + _ = f[L2 /* ERROR L2 does not implement comparable */ ] +} + + +// example from issue + +type Set[T comparable] map[T]struct{} + +func NewSetFromSlice[T comparable](items []T) *Set[T] { + s := Set[T]{} + + for _, item := range items { + s[item] = struct{}{} + } + + return &s +} + +type T struct{ x any } + +func main() { + NewSetFromSlice /* ERROR T does not implement comparable */ ([]T{ + {"foo"}, + {5}, + }) +} diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index e1f73015b9..3bc9474660 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -37,7 +37,7 @@ func (s *_TypeSet) IsComparable(seen map[Type]bool) bool { return s.comparable } return s.is(func(t *term) bool { - return t != nil && comparable(t.typ, seen, nil) + return t != nil && comparable(t.typ, false, seen, nil) }) } From e94f7df957b6cfbdfbed7092fd05628452c5e018 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 22 Feb 2022 13:06:52 -0800 Subject: [PATCH 18/44] go/types, types2: generalize cleanup phase after type checking Use a cleanup method and simple registration mechanism for types that need some final processing before the end of type checking. Use cleanup mechanism instead of expandDefTypes mechanism for *Named types. There is no change in functionality here. Use cleanup mechanism also for TypeParam and Interface types to ensure that their check fields are nilled out at the end. Introduce a simple constructor method for Interface types to ensure that the cleanup method is always registered. In go/types, add tracing code to Checker.checkFiles to match types2. Minor comment adjustments. Fixes #51316. Fixes #51326. Change-Id: I7b2bd79cc419717982f3c918645af623c0e80d5e Reviewed-on: https://go-review.googlesource.com/c/go/+/387417 Trust: Robert Griesemer Run-TryBot: Robert Griesemer Reviewed-by: Robert Findley TryBot-Result: Gopher Robot --- src/cmd/compile/internal/types2/check.go | 45 +++++++-------- src/cmd/compile/internal/types2/interface.go | 28 ++++++---- src/cmd/compile/internal/types2/named.go | 32 +++++++++-- src/cmd/compile/internal/types2/subst.go | 5 +- src/cmd/compile/internal/types2/typeparam.go | 12 ++-- src/cmd/compile/internal/types2/typexpr.go | 2 +- src/go/types/check.go | 58 ++++++++++++-------- src/go/types/interface.go | 28 ++++++---- src/go/types/named.go | 32 +++++++++-- src/go/types/subst.go | 5 +- src/go/types/typeparam.go | 12 ++-- src/go/types/typexpr.go | 2 +- 12 files changed, 168 insertions(+), 93 deletions(-) diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go index 535de0256c..4ec6a7b4fd 100644 --- a/src/cmd/compile/internal/types2/check.go +++ b/src/cmd/compile/internal/types2/check.go @@ -126,7 +126,7 @@ type Checker struct { untyped map[syntax.Expr]exprInfo // map of expressions without final type delayed []action // stack of delayed action segments; segments are processed in FIFO order objPath []Object // path of object dependencies during type inference (for cycle reporting) - defTypes []*Named // defined types created during type checking, for final validation. + cleaners []cleaner // list of types that may need a final cleanup at the end of type-checking // environment within which the current object is type-checked (valid only // for the duration of type-checking a specific object) @@ -205,6 +205,16 @@ func (check *Checker) pop() Object { return obj } +type cleaner interface { + cleanup() +} + +// needsCleanup records objects/types that implement the cleanup method +// which will be called at the end of type-checking. +func (check *Checker) needsCleanup(c cleaner) { + check.cleaners = append(check.cleaners, c) +} + // NewChecker returns a new Checker instance for a given package. // Package files may be added incrementally via checker.Files. func NewChecker(conf *Config, pkg *Package, info *Info) *Checker { @@ -247,6 +257,8 @@ func (check *Checker) initFiles(files []*syntax.File) { check.methods = nil check.untyped = nil check.delayed = nil + check.objPath = nil + check.cleaners = nil // determine package name and collect valid files pkg := check.pkg @@ -315,8 +327,8 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { print("== processDelayed ==") check.processDelayed(0) // incl. all functions - print("== expandDefTypes ==") - check.expandDefTypes() + print("== cleanup ==") + check.cleanup() print("== initOrder ==") check.initOrder() @@ -344,7 +356,6 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) { check.recvTParamMap = nil check.brokenAliases = nil check.unionTypeSets = nil - check.defTypes = nil check.ctxt = nil // TODO(gri) There's more memory we should release at this point. @@ -372,27 +383,13 @@ func (check *Checker) processDelayed(top int) { check.delayed = check.delayed[:top] } -func (check *Checker) expandDefTypes() { - // Ensure that every defined type created in the course of type-checking has - // either non-*Named underlying, or is unresolved. - // - // This guarantees that we don't leak any types whose underlying is *Named, - // because any unresolved instances will lazily compute their underlying by - // substituting in the underlying of their origin. The origin must have - // either been imported or type-checked and expanded here, and in either case - // its underlying will be fully expanded. - for i := 0; i < len(check.defTypes); i++ { - n := check.defTypes[i] - switch n.underlying.(type) { - case nil: - if n.resolver == nil { - panic("nil underlying") - } - case *Named: - n.under() // n.under may add entries to check.defTypes - } - n.check = nil +// cleanup runs cleanup for all collected cleaners. +func (check *Checker) cleanup() { + // Don't use a range clause since Named.cleanup may add more cleaners. + for i := 0; i < len(check.cleaners); i++ { + check.cleaners[i].cleanup() } + check.cleaners = nil } func (check *Checker) record(x *operand) { diff --git a/src/cmd/compile/internal/types2/interface.go b/src/cmd/compile/internal/types2/interface.go index ca5140d092..75597abaf9 100644 --- a/src/cmd/compile/internal/types2/interface.go +++ b/src/cmd/compile/internal/types2/interface.go @@ -37,7 +37,7 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { } // set method receivers if necessary - typ := new(Interface) + typ := (*Checker)(nil).newInterface() for _, m := range methods { if sig := m.typ.(*Signature); sig.recv == nil { sig.recv = NewVar(m.pos, m.pkg, "", typ) @@ -54,6 +54,15 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { return typ } +// check may be nil +func (check *Checker) newInterface() *Interface { + typ := &Interface{check: check} + if check != nil { + check.needsCleanup(typ) + } + return typ +} + // MarkImplicit marks the interface t as implicit, meaning this interface // corresponds to a constraint literal such as ~T or A|B without explicit // interface embedding. MarkImplicit should be called before any concurrent use @@ -100,6 +109,11 @@ func (t *Interface) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- // Implementation +func (t *Interface) cleanup() { + t.check = nil + t.embedPos = nil +} + func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType, def *Named) { addEmbedded := func(pos syntax.Pos, typ Type) { ityp.embeddeds = append(ityp.embeddeds, typ) @@ -162,16 +176,10 @@ func (check *Checker) interfaceType(ityp *Interface, iface *syntax.InterfaceType // (don't sort embeddeds: they must correspond to *embedPos entries) sortMethods(ityp.methods) - // Compute type set with a non-nil *Checker as soon as possible - // to report any errors. Subsequent uses of type sets will use - // this computed type set and won't need to pass in a *Checker. - // - // Pin the checker to the interface type in the interim, in case the type set - // must be used before delayed funcs are processed (see issue #48234). - // TODO(rfindley): clean up use of *Checker with computeInterfaceTypeSet - ityp.check = check + // Compute type set as soon as possible to report any errors. + // Subsequent uses of type sets will use this computed type + // set and won't need to pass in a *Checker. check.later(func() { computeInterfaceTypeSet(check, iface.Pos(), ityp) - ityp.check = nil }).describef(iface, "compute type set for %s", ityp) } diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go index bb522e8fe3..5c6a1cf5d8 100644 --- a/src/cmd/compile/internal/types2/named.go +++ b/src/cmd/compile/internal/types2/named.go @@ -72,11 +72,31 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar } // Ensure that typ is always expanded and sanity-checked. if check != nil { - check.defTypes = append(check.defTypes, typ) + check.needsCleanup(typ) } return typ } +func (t *Named) cleanup() { + // Ensure that every defined type created in the course of type-checking has + // either non-*Named underlying, or is unresolved. + // + // This guarantees that we don't leak any types whose underlying is *Named, + // because any unresolved instances will lazily compute their underlying by + // substituting in the underlying of their origin. The origin must have + // either been imported or type-checked and expanded here, and in either case + // its underlying will be fully expanded. + switch t.underlying.(type) { + case nil: + if t.resolver == nil { + panic("nil underlying") + } + case *Named: + t.under() // t.under may add entries to check.cleaners + } + t.check = nil +} + // Obj returns the type name for the declaration defining the named type t. For // instantiated types, this is the type name of the base type. func (t *Named) Obj() *TypeName { return t.orig.obj } // for non-instances this is the same as t.obj @@ -360,11 +380,11 @@ func expandNamed(ctxt *Context, n *Named, instPos syntax.Pos) (tparams *TypePara // that it wasn't substituted. In this case we need to create a new // *Interface before modifying receivers. if iface == n.orig.underlying { - iface = &Interface{ - embeddeds: iface.embeddeds, - complete: iface.complete, - implicit: iface.implicit, // should be false but be conservative - } + old := iface + iface = check.newInterface() + iface.embeddeds = old.embeddeds + iface.complete = old.complete + iface.implicit = old.implicit // should be false but be conservative underlying = iface } iface.methods = methods diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 44a59f55fd..037f04797b 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -160,7 +160,10 @@ func (subst *subster) typ(typ Type) Type { methods, mcopied := subst.funcList(t.methods) embeddeds, ecopied := subst.typeList(t.embeddeds) if mcopied || ecopied { - iface := &Interface{embeddeds: embeddeds, implicit: t.implicit, complete: t.complete} + iface := subst.check.newInterface() + iface.embeddeds = embeddeds + iface.implicit = t.implicit + iface.complete = t.complete // If we've changed the interface type, we may need to replace its // receiver if the receiver type is the original interface. Receivers of // *Named type are replaced during named type expansion. diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 971fdaec73..57613706f7 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -36,6 +36,7 @@ func NewTypeParam(obj *TypeName, constraint Type) *TypeParam { return (*Checker)(nil).newTypeParam(obj, constraint) } +// check may be nil func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam { // Always increment lastID, even if it is not used. id := nextID() @@ -50,9 +51,7 @@ func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam { // iface may mutate typ.bound, so we must ensure that iface() is called // at least once before the resulting TypeParam escapes. if check != nil { - check.later(func() { - typ.iface() - }) + check.needsCleanup(typ) } else if constraint != nil { typ.iface() } @@ -93,9 +92,12 @@ func (t *TypeParam) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- // Implementation +func (t *TypeParam) cleanup() { + t.iface() + t.check = nil +} + // iface returns the constraint interface of t. -// TODO(gri) If we make tparamIsIface the default, this should be renamed to under -// (similar to Named.under). func (t *TypeParam) iface() *Interface { bound := t.bound diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go index 149bd5b0b3..2847aa76c0 100644 --- a/src/cmd/compile/internal/types2/typexpr.go +++ b/src/cmd/compile/internal/types2/typexpr.go @@ -342,7 +342,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) { return typ case *syntax.InterfaceType: - typ := new(Interface) + typ := check.newInterface() def.setUnderlying(typ) if def != nil { typ.obj = def.obj diff --git a/src/go/types/check.go b/src/go/types/check.go index 6e1da04b9f..23136377c8 100644 --- a/src/go/types/check.go +++ b/src/go/types/check.go @@ -133,7 +133,7 @@ type Checker struct { untyped map[ast.Expr]exprInfo // map of expressions without final type delayed []action // stack of delayed action segments; segments are processed in FIFO order objPath []Object // path of object dependencies during type inference (for cycle reporting) - defTypes []*Named // defined types created during type checking, for final validation. + cleaners []cleaner // list of types that may need a final cleanup at the end of type-checking // environment within which the current object is type-checked (valid only // for the duration of type-checking a specific object) @@ -212,6 +212,16 @@ func (check *Checker) pop() Object { return obj } +type cleaner interface { + cleanup() +} + +// needsCleanup records objects/types that implement the cleanup method +// which will be called at the end of type-checking. +func (check *Checker) needsCleanup(c cleaner) { + check.cleaners = append(check.cleaners, c) +} + // NewChecker returns a new Checker instance for a given package. // Package files may be added incrementally via checker.Files. func NewChecker(conf *Config, fset *token.FileSet, pkg *Package, info *Info) *Checker { @@ -255,6 +265,8 @@ func (check *Checker) initFiles(files []*ast.File) { check.methods = nil check.untyped = nil check.delayed = nil + check.objPath = nil + check.cleaners = nil // determine package name and collect valid files pkg := check.pkg @@ -304,22 +316,37 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { defer check.handleBailout(&err) + print := func(msg string) { + if trace { + fmt.Println() + fmt.Println(msg) + } + } + + print("== initFiles ==") check.initFiles(files) + print("== collectObjects ==") check.collectObjects() + print("== packageObjects ==") check.packageObjects() + print("== processDelayed ==") check.processDelayed(0) // incl. all functions - check.expandDefTypes() + print("== cleanup ==") + check.cleanup() + print("== initOrder ==") check.initOrder() if !check.conf.DisableUnusedImportCheck { + print("== unusedImports ==") check.unusedImports() } + print("== recordUntyped ==") check.recordUntyped() if check.firstErr == nil { @@ -337,7 +364,6 @@ func (check *Checker) checkFiles(files []*ast.File) (err error) { check.recvTParamMap = nil check.brokenAliases = nil check.unionTypeSets = nil - check.defTypes = nil check.ctxt = nil // TODO(rFindley) There's more memory we should release at this point. @@ -365,27 +391,13 @@ func (check *Checker) processDelayed(top int) { check.delayed = check.delayed[:top] } -func (check *Checker) expandDefTypes() { - // Ensure that every defined type created in the course of type-checking has - // either non-*Named underlying, or is unresolved. - // - // This guarantees that we don't leak any types whose underlying is *Named, - // because any unresolved instances will lazily compute their underlying by - // substituting in the underlying of their origin. The origin must have - // either been imported or type-checked and expanded here, and in either case - // its underlying will be fully expanded. - for i := 0; i < len(check.defTypes); i++ { - n := check.defTypes[i] - switch n.underlying.(type) { - case nil: - if n.resolver == nil { - panic("nil underlying") - } - case *Named: - n.under() // n.under may add entries to check.defTypes - } - n.check = nil +// cleanup runs cleanup for all collected cleaners. +func (check *Checker) cleanup() { + // Don't use a range clause since Named.cleanup may add more cleaners. + for i := 0; i < len(check.cleaners); i++ { + check.cleaners[i].cleanup() } + check.cleaners = nil } func (check *Checker) record(x *operand) { diff --git a/src/go/types/interface.go b/src/go/types/interface.go index b9d4660eb4..3db3580a91 100644 --- a/src/go/types/interface.go +++ b/src/go/types/interface.go @@ -56,7 +56,7 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { } // set method receivers if necessary - typ := new(Interface) + typ := (*Checker)(nil).newInterface() for _, m := range methods { if sig := m.typ.(*Signature); sig.recv == nil { sig.recv = NewVar(m.pos, m.pkg, "", typ) @@ -73,6 +73,15 @@ func NewInterfaceType(methods []*Func, embeddeds []Type) *Interface { return typ } +// check may be nil +func (check *Checker) newInterface() *Interface { + typ := &Interface{check: check} + if check != nil { + check.needsCleanup(typ) + } + return typ +} + // MarkImplicit marks the interface t as implicit, meaning this interface // corresponds to a constraint literal such as ~T or A|B without explicit // interface embedding. MarkImplicit should be called before any concurrent use @@ -141,6 +150,11 @@ func (t *Interface) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- // Implementation +func (t *Interface) cleanup() { + t.check = nil + t.embedPos = nil +} + func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, def *Named) { addEmbedded := func(pos token.Pos, typ Type) { ityp.embeddeds = append(ityp.embeddeds, typ) @@ -210,16 +224,10 @@ func (check *Checker) interfaceType(ityp *Interface, iface *ast.InterfaceType, d sortMethods(ityp.methods) // (don't sort embeddeds: they must correspond to *embedPos entries) - // Compute type set with a non-nil *Checker as soon as possible - // to report any errors. Subsequent uses of type sets will use - // this computed type set and won't need to pass in a *Checker. - // - // Pin the checker to the interface type in the interim, in case the type set - // must be used before delayed funcs are processed (see issue #48234). - // TODO(rfindley): clean up use of *Checker with computeInterfaceTypeSet - ityp.check = check + // Compute type set as soon as possible to report any errors. + // Subsequent uses of type sets will use this computed type + // set and won't need to pass in a *Checker. check.later(func() { computeInterfaceTypeSet(check, iface.Pos(), ityp) - ityp.check = nil }).describef(iface, "compute type set for %s", ityp) } diff --git a/src/go/types/named.go b/src/go/types/named.go index 5e84c39776..5b84e0653b 100644 --- a/src/go/types/named.go +++ b/src/go/types/named.go @@ -72,11 +72,31 @@ func (check *Checker) newNamed(obj *TypeName, orig *Named, underlying Type, tpar } // Ensure that typ is always expanded and sanity-checked. if check != nil { - check.defTypes = append(check.defTypes, typ) + check.needsCleanup(typ) } return typ } +func (t *Named) cleanup() { + // Ensure that every defined type created in the course of type-checking has + // either non-*Named underlying, or is unresolved. + // + // This guarantees that we don't leak any types whose underlying is *Named, + // because any unresolved instances will lazily compute their underlying by + // substituting in the underlying of their origin. The origin must have + // either been imported or type-checked and expanded here, and in either case + // its underlying will be fully expanded. + switch t.underlying.(type) { + case nil: + if t.resolver == nil { + panic("nil underlying") + } + case *Named: + t.under() // t.under may add entries to check.cleaners + } + t.check = nil +} + // Obj returns the type name for the declaration defining the named type t. For // instantiated types, this is the type name of the base type. func (t *Named) Obj() *TypeName { @@ -362,11 +382,11 @@ func expandNamed(ctxt *Context, n *Named, instPos token.Pos) (tparams *TypeParam // that it wasn't substituted. In this case we need to create a new // *Interface before modifying receivers. if iface == n.orig.underlying { - iface = &Interface{ - embeddeds: iface.embeddeds, - complete: iface.complete, - implicit: iface.implicit, // should be false but be conservative - } + old := iface + iface = check.newInterface() + iface.embeddeds = old.embeddeds + iface.complete = old.complete + iface.implicit = old.implicit // should be false but be conservative underlying = iface } iface.methods = methods diff --git a/src/go/types/subst.go b/src/go/types/subst.go index 53247a3585..4b4a0f4ad6 100644 --- a/src/go/types/subst.go +++ b/src/go/types/subst.go @@ -160,7 +160,10 @@ func (subst *subster) typ(typ Type) Type { methods, mcopied := subst.funcList(t.methods) embeddeds, ecopied := subst.typeList(t.embeddeds) if mcopied || ecopied { - iface := &Interface{embeddeds: embeddeds, implicit: t.implicit, complete: t.complete} + iface := subst.check.newInterface() + iface.embeddeds = embeddeds + iface.implicit = t.implicit + iface.complete = t.complete // If we've changed the interface type, we may need to replace its // receiver if the receiver type is the original interface. Receivers of // *Named type are replaced during named type expansion. diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 71e6861b87..5505372cff 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -35,6 +35,7 @@ func NewTypeParam(obj *TypeName, constraint Type) *TypeParam { return (*Checker)(nil).newTypeParam(obj, constraint) } +// check may be nil func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam { // Always increment lastID, even if it is not used. id := nextID() @@ -49,9 +50,7 @@ func (check *Checker) newTypeParam(obj *TypeName, constraint Type) *TypeParam { // iface may mutate typ.bound, so we must ensure that iface() is called // at least once before the resulting TypeParam escapes. if check != nil { - check.later(func() { - typ.iface() - }) + check.needsCleanup(typ) } else if constraint != nil { typ.iface() } @@ -95,9 +94,12 @@ func (t *TypeParam) String() string { return TypeString(t, nil) } // ---------------------------------------------------------------------------- // Implementation +func (t *TypeParam) cleanup() { + t.iface() + t.check = nil +} + // iface returns the constraint interface of t. -// TODO(gri) If we make tparamIsIface the default, this should be renamed to under -// (similar to Named.under). func (t *TypeParam) iface() *Interface { bound := t.bound diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go index db6a904aaa..724c40963f 100644 --- a/src/go/types/typexpr.go +++ b/src/go/types/typexpr.go @@ -323,7 +323,7 @@ func (check *Checker) typInternal(e0 ast.Expr, def *Named) (T Type) { return typ case *ast.InterfaceType: - typ := new(Interface) + typ := check.newInterface() def.setUnderlying(typ) if def != nil { typ.obj = def.obj From 78e99761fc4bf1f5370f912b8a4594789c2f09f8 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 23 Feb 2022 14:26:07 -0800 Subject: [PATCH 19/44] go/types, types2: don't crash if comp. literal element type has no core type Instead, report a suitable error. Fixes #51335. Change-Id: Ifce90cb7487b1e99c6b4221c0d43bacc0c39dca8 Reviewed-on: https://go-review.googlesource.com/c/go/+/387676 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Gopher Robot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/expr.go | 4 ++++ .../types2/testdata/fixedbugs/issue51335.go2 | 16 ++++++++++++++++ src/go/types/expr.go | 4 ++++ src/go/types/testdata/fixedbugs/issue51335.go2 | 16 ++++++++++++++++ 4 files changed, 40 insertions(+) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue51335.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue51335.go2 diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go index ac5630dbbb..c587c40f80 100644 --- a/src/cmd/compile/internal/types2/expr.go +++ b/src/cmd/compile/internal/types2/expr.go @@ -1360,6 +1360,10 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin // no composite literal type present - use hint (element type of enclosing type) typ = hint base, _ = deref(coreType(typ)) // *T implies &T{} + if base == nil { + check.errorf(e, "invalid composite literal element type %s: no core type", typ) + goto Error + } default: // TODO(gri) provide better error messages depending on context diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51335.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51335.go2 new file mode 100644 index 0000000000..0b5a1af082 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51335.go2 @@ -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 + +type S1 struct{} +type S2 struct{} + +func _[P *S1|*S2]() { + _= []P{{ /* ERROR invalid composite literal element type P: no core type */ }} +} + +func _[P *S1|S1]() { + _= []P{{ /* ERROR invalid composite literal element type P: no core type */ }} +} diff --git a/src/go/types/expr.go b/src/go/types/expr.go index e8038dd178..9241c243f2 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -1339,6 +1339,10 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind { // no composite literal type present - use hint (element type of enclosing type) typ = hint base, _ = deref(coreType(typ)) // *T implies &T{} + if base == nil { + check.errorf(e, _InvalidLit, "invalid composite literal element type %s: no core type", typ) + goto Error + } default: // TODO(gri) provide better error messages depending on context diff --git a/src/go/types/testdata/fixedbugs/issue51335.go2 b/src/go/types/testdata/fixedbugs/issue51335.go2 new file mode 100644 index 0000000000..0b5a1af082 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue51335.go2 @@ -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 + +type S1 struct{} +type S2 struct{} + +func _[P *S1|*S2]() { + _= []P{{ /* ERROR invalid composite literal element type P: no core type */ }} +} + +func _[P *S1|S1]() { + _= []P{{ /* ERROR invalid composite literal element type P: no core type */ }} +} From b2dfec100afa7739dc1845f1009dad2d7163116c Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 24 Feb 2022 10:02:52 +0100 Subject: [PATCH 20/44] doc/go1.18: fix typo in AMD64 port section Change-Id: I234ae7988fd3c7a41c08e72664f8db811eb23bb1 Reviewed-on: https://go-review.googlesource.com/c/go/+/387854 Trust: Tobias Klauser Reviewed-by: Matt Layher Reviewed-by: Keith Randall --- doc/go1.18.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 8c786b94fc..2af5e04f98 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -182,7 +182,7 @@ Do not send CLs removing the interior tags from such phrases.

    Go 1.18 introduces the new GOAMD64 environment variable, which selects at compile time - a mininum target version of the AMD64 architecture. Allowed values are v1, + a minimum target version of the AMD64 architecture. Allowed values are v1, v2, v3, or v4. Each higher level requires, and takes advantage of, additional processor features. A detailed description can be found From 8c5904f149a4863183925c71ce4118413e7e0167 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Felix=20Geisend=C3=B6rfer?= Date: Wed, 23 Feb 2022 10:55:18 +0100 Subject: [PATCH 21/44] doc/go1.18: mention runtime/pprof improvements For #47694. Change-Id: Ib49145a58b8388d35267cf4b0caa730d7e436d06 Reviewed-on: https://go-review.googlesource.com/c/go/+/387574 Reviewed-by: Michael Pratt Trust: Michael Pratt Run-TryBot: Michael Pratt TryBot-Result: Gopher Robot Reviewed-by: Rhys Hiltner Reviewed-by: Bryan Mills Trust: Bryan Mills --- doc/go1.18.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 2af5e04f98..bc29ed4afe 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -1141,6 +1141,16 @@ For more details, see go.dev/issue/44505 +

    runtime/pprof
    +
    +

    + The CPU profiler now uses per-thread timers on Linux. This increases the + maximum CPU usage that a profile can observe, and reduces some forms of + bias. +

    +
    +
    +
    strconv

    From 4edefe95689c31846a73e36b3e0723c924def45d Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Sun, 31 Oct 2021 19:45:21 -0700 Subject: [PATCH 22/44] cmd/compile: delay all call transforms if in a generic function We changed to delaying all transforms of generic functions, since there are so many complicated situations where type params can be used. We missed changing so that all Call expressions(not just some) are delayed if in a generic function. This changes to delaying all transforms on calls in generic functions. Had to convert Call() to g.callExpr() (so we can access g.delayTransform()). By always delaying transforms on calls in generic functions, we actually simplify the code a bit both in g.CallExpr() and stencil.go. Fixes #51236 Change-Id: I0342c7995254082c4baf709b0b92a06ec14425e9 Reviewed-on: https://go-review.googlesource.com/c/go/+/386220 Reviewed-by: Keith Randall Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Gopher Robot --- src/cmd/compile/internal/noder/expr.go | 49 ++++++++++++- src/cmd/compile/internal/noder/helpers.go | 89 ----------------------- src/cmd/compile/internal/noder/stencil.go | 11 +-- test/typeparam/issue51236.go | 22 ++++++ 4 files changed, 71 insertions(+), 100 deletions(-) create mode 100644 test/typeparam/issue51236.go diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index a4e144554c..4b5ae706c1 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -114,7 +114,7 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { case *syntax.CallExpr: fun := g.expr(expr.Fun) - return Call(pos, g.typ(typ), fun, g.exprs(expr.ArgList), expr.HasDots) + return g.callExpr(pos, g.typ(typ), fun, g.exprs(expr.ArgList), expr.HasDots) case *syntax.IndexExpr: args := unpackListExpr(expr.Index) @@ -206,6 +206,53 @@ func (g *irgen) substType(typ *types.Type, tparams *types.Type, targs []ir.Node) return newt } +// callExpr creates a call expression (which might be a type conversion, built-in +// call, or a regular call) and does standard transforms, unless we are in a generic +// function. +func (g *irgen) callExpr(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) ir.Node { + n := ir.NewCallExpr(pos, ir.OCALL, fun, args) + n.IsDDD = dots + typed(typ, n) + + if fun.Op() == ir.OTYPE { + // Actually a type conversion, not a function call. + if !g.delayTransform() { + return transformConvCall(n) + } + return n + } + + if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 { + if !g.delayTransform() { + return transformBuiltin(n) + } + return n + } + + // Add information, now that we know that fun is actually being called. + switch fun := fun.(type) { + case *ir.SelectorExpr: + if fun.Op() == ir.OMETHVALUE { + op := ir.ODOTMETH + if fun.X.Type().IsInterface() { + op = ir.ODOTINTER + } + fun.SetOp(op) + // Set the type to include the receiver, since that's what + // later parts of the compiler expect + fun.SetType(fun.Selection.Type) + } + } + + // A function instantiation (even if fully concrete) shouldn't be + // transformed yet, because we need to add the dictionary during the + // transformation. + if fun.Op() != ir.OFUNCINST && !g.delayTransform() { + transformCall(n) + } + return n +} + // selectorExpr resolves the choice of ODOT, ODOTPTR, OMETHVALUE (eventually // ODOTMETH & ODOTINTER), and OMETHEXPR and deals with embedded fields here rather // than in typecheck.go. diff --git a/src/cmd/compile/internal/noder/helpers.go b/src/cmd/compile/internal/noder/helpers.go index 5524673e66..33acd6051a 100644 --- a/src/cmd/compile/internal/noder/helpers.go +++ b/src/cmd/compile/internal/noder/helpers.go @@ -98,95 +98,6 @@ func Binary(pos src.XPos, op ir.Op, typ *types.Type, x, y ir.Node) *ir.BinaryExp } } -func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool) ir.Node { - n := ir.NewCallExpr(pos, ir.OCALL, fun, args) - n.IsDDD = dots - - if fun.Op() == ir.OTYPE { - // Actually a type conversion, not a function call. - if !fun.Type().IsInterface() && - (fun.Type().HasTParam() || args[0].Type().HasTParam()) { - // For type params, we can transform if fun.Type() is known - // to be an interface (in which case a CONVIFACE node will be - // inserted). Otherwise, don't typecheck until we actually - // know the type. - return typed(typ, n) - } - typed(typ, n) - return transformConvCall(n) - } - - if fun, ok := fun.(*ir.Name); ok && fun.BuiltinOp != 0 { - // For most Builtin ops, we delay doing transformBuiltin if any of the - // args have type params, for a variety of reasons: - // - // OMAKE: transformMake can't choose specific ops OMAKESLICE, etc. - // until arg type is known - // OREAL/OIMAG: transformRealImag can't determine type float32/float64 - // until arg type known - // OAPPEND: transformAppend requires that the arg is a slice - // ODELETE: transformDelete requires that the arg is a map - // OALIGNOF, OSIZEOF: can be eval'ed to a constant until types known. - switch fun.BuiltinOp { - case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.ODELETE, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: - hasTParam := false - for _, arg := range args { - if fun.BuiltinOp == ir.OOFFSETOF { - // It's the type of left operand of the - // selection that matters, not the type of - // the field itself (which is irrelevant for - // offsetof). - arg = arg.(*ir.SelectorExpr).X - } - if arg.Type().HasTParam() { - hasTParam = true - break - } - } - if hasTParam { - return typed(typ, n) - } - } - - typed(typ, n) - return transformBuiltin(n) - } - - // Add information, now that we know that fun is actually being called. - switch fun := fun.(type) { - case *ir.SelectorExpr: - if fun.Op() == ir.OMETHVALUE { - op := ir.ODOTMETH - if fun.X.Type().IsInterface() { - op = ir.ODOTINTER - } - fun.SetOp(op) - // Set the type to include the receiver, since that's what - // later parts of the compiler expect - fun.SetType(fun.Selection.Type) - } - } - - if fun.Type().HasTParam() || fun.Op() == ir.OXDOT || fun.Op() == ir.OFUNCINST { - // If the fun arg is or has a type param, we can't do all the - // transformations, since we may not have needed properties yet - // (e.g. number of return values, etc). The same applies if a fun - // which is an XDOT could not be transformed yet because of a generic - // type in the X of the selector expression. - // - // A function instantiation (even if fully concrete) shouldn't be - // transformed yet, because we need to add the dictionary during the - // transformation. - return typed(typ, n) - } - - // If no type params, do the normal call transformations. This - // will convert OCALL to OCALLFUNC. - typed(typ, n) - transformCall(n) - return n -} - func Compare(pos src.XPos, typ *types.Type, op ir.Op, x, y ir.Node) *ir.BinaryExpr { n := ir.NewBinaryExpr(pos, op, x, y) typed(typ, n) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 50b6c0efcd..03937094e1 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -1055,8 +1055,6 @@ func (subst *subster) node(n ir.Node) ir.Node { // Transform the conversion, now that we know the // type argument. m = transformConvCall(call) - // CONVIFACE transformation was already done in noder2 - assert(m.Op() != ir.OCONVIFACE) case ir.OMETHVALUE, ir.OMETHEXPR: // Redo the transformation of OXDOT, now that we @@ -1076,14 +1074,7 @@ func (subst *subster) node(n ir.Node) ir.Node { case ir.ONAME: name := call.X.Name() if name.BuiltinOp != ir.OXXX { - switch name.BuiltinOp { - case ir.OMAKE, ir.OREAL, ir.OIMAG, ir.OAPPEND, ir.ODELETE, ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF: - // Transform these builtins now that we - // know the type of the args. - m = transformBuiltin(call) - default: - base.FatalfAt(call.Pos(), "Unexpected builtin op") - } + m = transformBuiltin(call) } else { // This is the case of a function value that was a // type parameter (implied to be a function via a diff --git a/test/typeparam/issue51236.go b/test/typeparam/issue51236.go new file mode 100644 index 0000000000..779c74ee6c --- /dev/null +++ b/test/typeparam/issue51236.go @@ -0,0 +1,22 @@ +// run -gcflags=-G=3 + +// 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 I interface { + []byte +} + +func F[T I]() { + var t T + explodes(t) +} + +func explodes(b []byte) {} + +func main() { + +} From 5a9fc946b42cc987db41eabcfcbaffd2fb310d94 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Wed, 23 Feb 2022 11:55:08 -0500 Subject: [PATCH 23/44] cmd/go: avoid +incompatible major versions if a go.mod file exists in a subdirectory for that version MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previous versions of the 'go' command would reject a pseudo-version passed to 'go get' if that pseudo-version had a mismatched major version and lacked a "+incompatible" suffix. However, they would erroneously accept a version *with* a "+incompatible" suffix even if the repo contained a vN/go.mod file for the same major version, and would generate a "+incompatible" pseudo-version or version if the user requested a tag, branch, or commit hash. This change uniformly rejects "vN.…" without "+incompatible", and also avoids resolving to "vN.…+incompatible", when vN/go.mod exists. To maintain compatibility with existing go.mod files, it still accepts "vN.…+incompatible" if the version is requested explicitly as such and the repo root lacks a go.mod file. Fixes #51324 Updates #36438 Change-Id: I2b16150c73fc2abe4d0a1cd34cb1600635db7139 Reviewed-on: https://go-review.googlesource.com/c/go/+/387675 Trust: Bryan Mills Reviewed-by: Michael Matloob --- src/cmd/go/internal/modfetch/coderepo.go | 53 ++++++++++++++----- src/cmd/go/internal/modfetch/coderepo_test.go | 48 +++++++++++++++++ 2 files changed, 89 insertions(+), 12 deletions(-) diff --git a/src/cmd/go/internal/modfetch/coderepo.go b/src/cmd/go/internal/modfetch/coderepo.go index 2206c7c840..dfaf16def6 100644 --- a/src/cmd/go/internal/modfetch/coderepo.go +++ b/src/cmd/go/internal/modfetch/coderepo.go @@ -305,17 +305,46 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e // // (If the version is +incompatible, then the go.mod file must not exist: // +incompatible is not an ongoing opt-out from semantic import versioning.) - var canUseIncompatible func() bool - canUseIncompatible = func() bool { - var ok bool - if r.codeDir == "" && r.pathMajor == "" { + incompatibleOk := map[string]bool{} + canUseIncompatible := func(v string) bool { + if r.codeDir != "" || r.pathMajor != "" { + // A non-empty codeDir indicates a module within a subdirectory, + // which necessarily has a go.mod file indicating the module boundary. + // A non-empty pathMajor indicates a module path with a major-version + // suffix, which must match. + return false + } + + ok, seen := incompatibleOk[""] + if !seen { _, errGoMod := r.code.ReadFile(info.Name, "go.mod", codehost.MaxGoMod) - if errGoMod != nil { - ok = true + ok = (errGoMod != nil) + incompatibleOk[""] = ok + } + if !ok { + // A go.mod file exists at the repo root. + return false + } + + // Per https://go.dev/issue/51324, previous versions of the 'go' command + // didn't always check for go.mod files in subdirectories, so if the user + // requests a +incompatible version explicitly, we should continue to allow + // it. Otherwise, if vN/go.mod exists, expect that release tags for that + // major version are intended for the vN module. + if v != "" && !strings.HasSuffix(statVers, "+incompatible") { + major := semver.Major(v) + ok, seen = incompatibleOk[major] + if !seen { + _, errGoModSub := r.code.ReadFile(info.Name, path.Join(major, "go.mod"), codehost.MaxGoMod) + ok = (errGoModSub != nil) + incompatibleOk[major] = ok + } + if !ok { + return false } } - canUseIncompatible = func() bool { return ok } - return ok + + return true } // checkCanonical verifies that the canonical version v is compatible with the @@ -367,7 +396,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e base := strings.TrimSuffix(v, "+incompatible") var errIncompatible error if !module.MatchPathMajor(base, r.pathMajor) { - if canUseIncompatible() { + if canUseIncompatible(base) { v = base + "+incompatible" } else { if r.pathMajor != "" { @@ -495,7 +524,7 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e // Save the highest non-retracted canonical tag for the revision. // If we don't find a better match, we'll use it as the canonical version. if tagIsCanonical && semver.Compare(highestCanonical, v) < 0 && !isRetracted(v) { - if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible() { + if module.MatchPathMajor(v, r.pathMajor) || canUseIncompatible(v) { highestCanonical = v } } @@ -513,12 +542,12 @@ func (r *codeRepo) convert(info *codehost.RevInfo, statVers string) (*RevInfo, e // retracted versions. allowedMajor := func(major string) func(v string) bool { return func(v string) bool { - return (major == "" || semver.Major(v) == major) && !isRetracted(v) + return ((major == "" && canUseIncompatible(v)) || semver.Major(v) == major) && !isRetracted(v) } } if pseudoBase == "" { var tag string - if r.pseudoMajor != "" || canUseIncompatible() { + if r.pseudoMajor != "" || canUseIncompatible("") { tag, _ = r.code.RecentTag(info.Name, tagPrefix, allowedMajor(r.pseudoMajor)) } else { // Allow either v1 or v0, but not incompatible higher versions. diff --git a/src/cmd/go/internal/modfetch/coderepo_test.go b/src/cmd/go/internal/modfetch/coderepo_test.go index d98ea87da2..bb9268adb8 100644 --- a/src/cmd/go/internal/modfetch/coderepo_test.go +++ b/src/cmd/go/internal/modfetch/coderepo_test.go @@ -458,6 +458,54 @@ var codeRepoTests = []codeRepoTest{ rev: "v3.0.0-devel", err: `resolves to version v0.1.1-0.20220203155313-d59622f6e4d7 (v3.0.0-devel is not a tag)`, }, + + // If v2/go.mod exists, then we should prefer to match the "v2" + // pseudo-versions to the nested module, and resolve the module in the parent + // directory to only compatible versions. + // + // However (https://go.dev/issue/51324), previous versions of the 'go' command + // didn't always do so, so if the user explicitly requests a +incompatible + // version (as would be present in an existing go.mod file), we should + // continue to allow it. + { + vcs: "git", + path: "vcs-test.golang.org/git/v2sub.git", + rev: "80beb17a1603", + version: "v0.0.0-20220222205507-80beb17a1603", + name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5", + short: "80beb17a1603", + time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC), + }, + { + vcs: "git", + path: "vcs-test.golang.org/git/v2sub.git", + rev: "v2.0.0", + err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`, + }, + { + vcs: "git", + path: "vcs-test.golang.org/git/v2sub.git", + rev: "v2.0.1-0.20220222205507-80beb17a1603", + err: `module contains a go.mod file, so module path must match major version ("vcs-test.golang.org/git/v2sub.git/v2")`, + }, + { + vcs: "git", + path: "vcs-test.golang.org/git/v2sub.git", + rev: "v2.0.0+incompatible", + version: "v2.0.0+incompatible", + name: "5fcd3eaeeb391d399f562fd45a50dac9fc34ae8b", + short: "5fcd3eaeeb39", + time: time.Date(2022, 2, 22, 20, 53, 33, 0, time.UTC), + }, + { + vcs: "git", + path: "vcs-test.golang.org/git/v2sub.git", + rev: "v2.0.1-0.20220222205507-80beb17a1603+incompatible", + version: "v2.0.1-0.20220222205507-80beb17a1603+incompatible", + name: "80beb17a16036f17a5aedd1bb5bd6d407b3c6dc5", + short: "80beb17a1603", + time: time.Date(2022, 2, 22, 20, 55, 7, 0, time.UTC), + }, } func TestCodeRepo(t *testing.T) { From c15527f0b05fe893e2630420747b128fe17566a6 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 22 Feb 2022 16:53:17 -0800 Subject: [PATCH 24/44] go/types, types2: implement adjCoreType using TypeParam.is TypeParam.is also provides ~ (tilde) information which is needed to fix #51229. Delete all code related to singleType as it's not used anymore. Also, remove TypeParam.hasTerms as it was not used. For #51229. Change-Id: Ie49b19d157230beecb17a444d1f17cf24aa4f6ba Reviewed-on: https://go-review.googlesource.com/c/go/+/387774 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/infer.go | 23 ++++++++++----- src/cmd/compile/internal/types2/termlist.go | 9 ------ .../compile/internal/types2/termlist_test.go | 29 ------------------- src/cmd/compile/internal/types2/typeparam.go | 10 ------- src/cmd/compile/internal/types2/typeset.go | 3 -- src/go/types/infer.go | 23 ++++++++++----- src/go/types/termlist.go | 9 ------ src/go/types/termlist_test.go | 29 ------------------- src/go/types/typeparam.go | 10 ------- src/go/types/typeset.go | 3 -- 10 files changed, 32 insertions(+), 116 deletions(-) diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go index 2d6f26c0c9..617f3edad7 100644 --- a/src/cmd/compile/internal/types2/infer.go +++ b/src/cmd/compile/internal/types2/infer.go @@ -591,15 +591,24 @@ func (check *Checker) inferB(pos syntax.Pos, tparams []*TypeParam, targs []Type) return } +// adjCoreType returns the core type of tpar unless the +// type parameter embeds a single, possibly named type, +// in which case it returns that single type instead. +// (The core type is always the underlying type of that +// single type.) func adjCoreType(tpar *TypeParam) Type { - // If the type parameter embeds a single, possibly named - // type, use that one instead of the core type (which is - // always the underlying type of that single type). - if single := tpar.singleType(); single != nil { - if debug { - assert(under(single) == coreType(tpar)) + var single *term + if tpar.is(func(t *term) bool { + if single == nil && t != nil { + single = t + return true } - return single + return false // zero or more than one terms + }) { + if debug { + assert(under(single.typ) == coreType(tpar)) + } + return single.typ } return coreType(tpar) } diff --git a/src/cmd/compile/internal/types2/termlist.go b/src/cmd/compile/internal/types2/termlist.go index 844e39e3bf..a0108c4638 100644 --- a/src/cmd/compile/internal/types2/termlist.go +++ b/src/cmd/compile/internal/types2/termlist.go @@ -92,15 +92,6 @@ func (xl termlist) norm() termlist { return rl } -// If the type set represented by xl is specified by a single (non-𝓤) term, -// singleType returns that type. Otherwise it returns nil. -func (xl termlist) singleType() Type { - if nl := xl.norm(); len(nl) == 1 { - return nl[0].typ // if nl.isAll() then typ is nil, which is ok - } - return nil -} - // union returns the union xl ∪ yl. func (xl termlist) union(yl termlist) termlist { return append(xl, yl...).norm() diff --git a/src/cmd/compile/internal/types2/termlist_test.go b/src/cmd/compile/internal/types2/termlist_test.go index 1bdf9e1386..d1e3bdf88e 100644 --- a/src/cmd/compile/internal/types2/termlist_test.go +++ b/src/cmd/compile/internal/types2/termlist_test.go @@ -106,35 +106,6 @@ func TestTermlistNorm(t *testing.T) { } } -func TestTermlistSingleType(t *testing.T) { - // helper to deal with nil types - tstring := func(typ Type) string { - if typ == nil { - return "nil" - } - return typ.String() - } - - for test, want := range map[string]string{ - "∅": "nil", - "𝓤": "nil", - "int": "int", - "myInt": "myInt", - "~int": "int", - "~int ∪ string": "nil", - "~int ∪ myInt": "int", - "∅ ∪ int": "int", - "∅ ∪ ~int": "int", - "∅ ∪ ~int ∪ string": "nil", - } { - xl := maketl(test) - got := tstring(xl.singleType()) - if got != want { - t.Errorf("(%v).singleType() == %v; want %v", test, got, want) - } - } -} - func TestTermlistUnion(t *testing.T) { for _, test := range []struct { xl, yl, want string diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go index 57613706f7..9ed3369ff4 100644 --- a/src/cmd/compile/internal/types2/typeparam.go +++ b/src/cmd/compile/internal/types2/typeparam.go @@ -138,16 +138,6 @@ func (t *TypeParam) iface() *Interface { return ityp } -// singleType returns the single type of the type parameter constraint; or nil. -func (t *TypeParam) singleType() Type { - return t.iface().typeSet().singleType() -} - -// hasTerms reports whether the type parameter constraint has specific type terms. -func (t *TypeParam) hasTerms() bool { - return t.iface().typeSet().hasTerms() -} - // is calls f with the specific type terms of t's constraint and reports whether // all calls to f returned true. If there are no specific terms, is // returns the result of f(nil). diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go index 2c3e826a3f..65ae04819e 100644 --- a/src/cmd/compile/internal/types2/typeset.go +++ b/src/cmd/compile/internal/types2/typeset.go @@ -103,9 +103,6 @@ func (s *_TypeSet) String() string { // hasTerms reports whether the type set has specific type terms. func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } -// singleType returns the single type in s if there is exactly one; otherwise the result is nil. -func (s *_TypeSet) singleType() Type { return s.terms.singleType() } - // subsetOf reports whether s1 ⊆ s2. func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) } diff --git a/src/go/types/infer.go b/src/go/types/infer.go index 8f22144c83..d481aaa877 100644 --- a/src/go/types/infer.go +++ b/src/go/types/infer.go @@ -590,15 +590,24 @@ func (check *Checker) inferB(posn positioner, tparams []*TypeParam, targs []Type return } +// adjCoreType returns the core type of tpar unless the +// type parameter embeds a single, possibly named type, +// in which case it returns that single type instead. +// (The core type is always the underlying type of that +// single type.) func adjCoreType(tpar *TypeParam) Type { - // If the type parameter embeds a single, possibly named - // type, use that one instead of the core type (which is - // always the underlying type of that single type). - if single := tpar.singleType(); single != nil { - if debug { - assert(under(single) == coreType(tpar)) + var single *term + if tpar.is(func(t *term) bool { + if single == nil && t != nil { + single = t + return true } - return single + return false // zero or more than one terms + }) { + if debug { + assert(under(single.typ) == coreType(tpar)) + } + return single.typ } return coreType(tpar) } diff --git a/src/go/types/termlist.go b/src/go/types/termlist.go index c4ab0e037e..94e49caee0 100644 --- a/src/go/types/termlist.go +++ b/src/go/types/termlist.go @@ -92,15 +92,6 @@ func (xl termlist) norm() termlist { return rl } -// If the type set represented by xl is specified by a single (non-𝓤) term, -// singleType returns that type. Otherwise it returns nil. -func (xl termlist) singleType() Type { - if nl := xl.norm(); len(nl) == 1 { - return nl[0].typ // if nl.isAll() then typ is nil, which is ok - } - return nil -} - // union returns the union xl ∪ yl. func (xl termlist) union(yl termlist) termlist { return append(xl, yl...).norm() diff --git a/src/go/types/termlist_test.go b/src/go/types/termlist_test.go index dddca7a682..f0d58ac1bc 100644 --- a/src/go/types/termlist_test.go +++ b/src/go/types/termlist_test.go @@ -106,35 +106,6 @@ func TestTermlistNorm(t *testing.T) { } } -func TestTermlistSingleType(t *testing.T) { - // helper to deal with nil types - tstring := func(typ Type) string { - if typ == nil { - return "nil" - } - return typ.String() - } - - for test, want := range map[string]string{ - "∅": "nil", - "𝓤": "nil", - "int": "int", - "myInt": "myInt", - "~int": "int", - "~int ∪ string": "nil", - "~int ∪ myInt": "int", - "∅ ∪ int": "int", - "∅ ∪ ~int": "int", - "∅ ∪ ~int ∪ string": "nil", - } { - xl := maketl(test) - got := tstring(xl.singleType()) - if got != want { - t.Errorf("(%v).singleType() == %v; want %v", test, got, want) - } - } -} - func TestTermlistUnion(t *testing.T) { for _, test := range []struct { xl, yl, want string diff --git a/src/go/types/typeparam.go b/src/go/types/typeparam.go index 5505372cff..778c687d43 100644 --- a/src/go/types/typeparam.go +++ b/src/go/types/typeparam.go @@ -140,16 +140,6 @@ func (t *TypeParam) iface() *Interface { return ityp } -// singleType returns the single type of the type parameter constraint; or nil. -func (t *TypeParam) singleType() Type { - return t.iface().typeSet().singleType() -} - -// hasTerms reports whether the type parameter constraint has specific type terms. -func (t *TypeParam) hasTerms() bool { - return t.iface().typeSet().hasTerms() -} - // is calls f with the specific type terms of t's constraint and reports whether // all calls to f returned true. If there are no specific terms, is // returns the result of f(nil). diff --git a/src/go/types/typeset.go b/src/go/types/typeset.go index 3bc9474660..4c3f018cfe 100644 --- a/src/go/types/typeset.go +++ b/src/go/types/typeset.go @@ -101,9 +101,6 @@ func (s *_TypeSet) String() string { // hasTerms reports whether the type set has specific type terms. func (s *_TypeSet) hasTerms() bool { return !s.terms.isEmpty() && !s.terms.isAll() } -// singleType returns the single type in s if there is exactly one; otherwise the result is nil. -func (s *_TypeSet) singleType() Type { return s.terms.singleType() } - // subsetOf reports whether s1 ⊆ s2. func (s1 *_TypeSet) subsetOf(s2 *_TypeSet) bool { return s1.terms.subsetOf(s2.terms) } From c0840a7c720061f1293063bad5d5648267a02ba8 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Wed, 23 Feb 2022 21:43:06 -0800 Subject: [PATCH 25/44] go/types, types2: method recv type parameter count must match base type parameter count Check receiver type parameter count when type checking the method signature and report a suitable error (don't rely on delayed instantiation and possibly constraint type inference). While at it, simplify blank name recoding and type bound rewriting. Stop-gap measure to avoid crashes in the compiler. Fixes #51339. For #51343. Change-Id: Idbe2d32d69b66573ca973339f8924b349d2bc9cc Reviewed-on: https://go-review.googlesource.com/c/go/+/387836 Trust: Robert Griesemer Reviewed-by: David Chase Reviewed-by: Robert Findley --- .../compile/internal/types2/assignments.go | 13 +++---- src/cmd/compile/internal/types2/signature.go | 34 ++++++++--------- .../types2/testdata/fixedbugs/issue51339.go2 | 16 ++++++++ src/go/types/assignments.go | 13 +++---- src/go/types/signature.go | 37 ++++++++++--------- .../types/testdata/fixedbugs/issue51339.go2 | 16 ++++++++ 6 files changed, 80 insertions(+), 49 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue51339.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue51339.go2 diff --git a/src/cmd/compile/internal/types2/assignments.go b/src/cmd/compile/internal/types2/assignments.go index 936930f0b1..d88b03748f 100644 --- a/src/cmd/compile/internal/types2/assignments.go +++ b/src/cmd/compile/internal/types2/assignments.go @@ -294,15 +294,14 @@ func (check *Checker) typesSummary(list []Type, variadic bool) string { return "(" + strings.Join(res, ", ") + ")" } -func (check *Checker) assignError(rhs []syntax.Expr, nvars, nvals int) { - measure := func(x int, unit string) string { - s := fmt.Sprintf("%d %s", x, unit) - if x != 1 { - s += "s" - } - return s +func measure(x int, unit string) string { + if x != 1 { + unit += "s" } + return fmt.Sprintf("%d %s", x, unit) +} +func (check *Checker) assignError(rhs []syntax.Expr, nvars, nvals int) { vars := measure(nvars, "variable") vals := measure(nvals, "value") rhs0 := rhs[0] diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index c87fab749c..76e588254d 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -116,11 +116,10 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] // lookup in the scope. for i, p := range rparams { if p.Value == "_" { - tpar := sig.rparams.At(i) if check.recvTParamMap == nil { check.recvTParamMap = make(map[*syntax.Name]*TypeParam) } - check.recvTParamMap[p] = tpar + check.recvTParamMap[p] = tparams[i] } } // determine receiver type to get its type parameters @@ -136,22 +135,23 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] } } // provide type parameter bounds - // - only do this if we have the right number (otherwise an error is reported elsewhere) - if sig.RecvTypeParams().Len() == len(recvTParams) { - // We have a list of *TypeNames but we need a list of Types. - list := make([]Type, sig.RecvTypeParams().Len()) - for i, t := range sig.RecvTypeParams().list() { - list[i] = t - check.mono.recordCanon(t, recvTParams[i]) - } - smap := makeSubstMap(recvTParams, list) - for i, tpar := range sig.RecvTypeParams().list() { - bound := recvTParams[i].bound - // bound is (possibly) parameterized in the context of the - // receiver type declaration. Substitute parameters for the - // current context. - tpar.bound = check.subst(tpar.obj.pos, bound, smap, nil) + if len(tparams) == len(recvTParams) { + smap := makeRenameMap(recvTParams, tparams) + for i, tpar := range tparams { + recvTPar := recvTParams[i] + check.mono.recordCanon(tpar, recvTPar) + // recvTPar.bound is (possibly) parameterized in the context of the + // receiver type declaration. Substitute parameters for the current + // context. + tpar.bound = check.subst(tpar.obj.pos, recvTPar.bound, smap, nil) } + } else if len(tparams) < len(recvTParams) { + // Reporting an error here is a stop-gap measure to avoid crashes in the + // compiler when a type parameter/argument cannot be inferred later. It + // may lead to follow-on errors (see issues #51339, #51343). + // TODO(gri) find a better solution + got := measure(len(tparams), "type parameter") + check.errorf(recvPar, "got %s, but receiver base type declares %d", got, len(recvTParams)) } } } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51339.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51339.go2 new file mode 100644 index 0000000000..40706ec493 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51339.go2 @@ -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. + +// This file is tested when running "go test -run Manual" +// without source arguments. Use for one-off debugging. + +package p + +type T[P any, B *P] struct{} + +func (T /* ERROR cannot use generic type */ ) m0() {} +func (T /* ERROR got 1 type parameter, but receiver base type declares 2 */ [_]) m1() {} +func (T[_, _]) m2() {} +// TODO(gri) this error is unfortunate (issue #51343) +func (T /* ERROR got 3 arguments but 2 type parameters */ [_, _, _]) m3() {} diff --git a/src/go/types/assignments.go b/src/go/types/assignments.go index f75b8b6f6b..f5e22c2f67 100644 --- a/src/go/types/assignments.go +++ b/src/go/types/assignments.go @@ -290,15 +290,14 @@ func (check *Checker) typesSummary(list []Type, variadic bool) string { return "(" + strings.Join(res, ", ") + ")" } -func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) { - measure := func(x int, unit string) string { - s := fmt.Sprintf("%d %s", x, unit) - if x != 1 { - s += "s" - } - return s +func measure(x int, unit string) string { + if x != 1 { + unit += "s" } + return fmt.Sprintf("%d %s", x, unit) +} +func (check *Checker) assignError(rhs []ast.Expr, nvars, nvals int) { vars := measure(nvars, "variable") vals := measure(nvals, "value") rhs0 := rhs[0] diff --git a/src/go/types/signature.go b/src/go/types/signature.go index 8f89e931fb..f174516268 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -112,7 +112,8 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // - the receiver specification acts as local declaration for its type parameters, which may be blank _, rname, rparams := check.unpackRecv(recvPar.List[0].Type, true) if len(rparams) > 0 { - sig.rparams = bindTParams(check.declareTypeParams(nil, rparams)) + tparams := check.declareTypeParams(nil, rparams) + sig.rparams = bindTParams(tparams) // Blank identifiers don't get declared, so naive type-checking of the // receiver type expression would fail in Checker.collectParams below, // when Checker.ident cannot resolve the _ to a type. @@ -122,11 +123,10 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast // lookup in the scope. for i, p := range rparams { if p.Name == "_" { - tpar := sig.rparams.At(i) if check.recvTParamMap == nil { check.recvTParamMap = make(map[*ast.Ident]*TypeParam) } - check.recvTParamMap[p] = tpar + check.recvTParamMap[p] = tparams[i] } } // determine receiver type to get its type parameters @@ -142,22 +142,23 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast } } // provide type parameter bounds - // - only do this if we have the right number (otherwise an error is reported elsewhere) - if sig.RecvTypeParams().Len() == len(recvTParams) { - // We have a list of *TypeNames but we need a list of Types. - list := make([]Type, sig.RecvTypeParams().Len()) - for i, t := range sig.RecvTypeParams().list() { - list[i] = t - check.mono.recordCanon(t, recvTParams[i]) - } - smap := makeSubstMap(recvTParams, list) - for i, tpar := range sig.RecvTypeParams().list() { - bound := recvTParams[i].bound - // bound is (possibly) parameterized in the context of the - // receiver type declaration. Substitute parameters for the - // current context. - tpar.bound = check.subst(tpar.obj.pos, bound, smap, nil) + if len(tparams) == len(recvTParams) { + smap := makeRenameMap(recvTParams, tparams) + for i, tpar := range tparams { + recvTPar := recvTParams[i] + check.mono.recordCanon(tpar, recvTPar) + // recvTPar.bound is (possibly) parameterized in the context of the + // receiver type declaration. Substitute parameters for the current + // context. + tpar.bound = check.subst(tpar.obj.pos, recvTPar.bound, smap, nil) } + } else if len(tparams) < len(recvTParams) { + // Reporting an error here is a stop-gap measure to avoid crashes in the + // compiler when a type parameter/argument cannot be inferred later. It + // may lead to follow-on errors (see issues #51339, #51343). + // TODO(gri) find a better solution + got := measure(len(tparams), "type parameter") + check.errorf(recvPar, _BadRecv, "got %s, but receiver base type declares %d", got, len(recvTParams)) } } } diff --git a/src/go/types/testdata/fixedbugs/issue51339.go2 b/src/go/types/testdata/fixedbugs/issue51339.go2 new file mode 100644 index 0000000000..6803c44d76 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue51339.go2 @@ -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. + +// This file is tested when running "go test -run Manual" +// without source arguments. Use for one-off debugging. + +package p + +type T[P any, B *P] struct{} + +func (T /* ERROR cannot use generic type */ ) m0() {} +func (/* ERROR got 1 type parameter, but receiver base type declares 2 */ T[_]) m1() {} +func (T[_, _]) m2() {} +// TODO(gri) this error is unfortunate (issue #51343) +func (T /* ERROR got 3 arguments but 2 type parameters */ [_, _, _]) m3() {} From b8b3196375e6b5275ae05eba8ca04662f10ab047 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 24 Feb 2022 15:45:11 -0800 Subject: [PATCH 26/44] doc/go1.18: document method set limitation for method selectors For #51183. For #47694. Change-Id: If47ae074c3cd9f73b2e7f6408749d9a7d56bd8d2 Reviewed-on: https://go-review.googlesource.com/c/go/+/387924 Trust: Robert Griesemer Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index bc29ed4afe..53e9d9b258 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -135,6 +135,16 @@ Do not send CLs removing the interior tags from such phrases. the predeclared functions real, imag, and complex. We hope to remove this restriction in Go 1.19. +

  • + The Go compiler currently only supports calling a method m on a value + x of type parameter type P if m is explictly + declared by P's constraint interface. + Similarly, method values x.m and method expressions + P.m also are only supported if m is explicitly + declared by P, even though m might be in the method set + of P by virtue of the fact that all types in P implement + m. We hope to remove this restriction in Go 1.19. +
  • Embedding a type parameter, or a pointer to a type parameter, as an unnamed field in a struct type is not permitted. Similarly, From 6d810241ebd2a02bc63b7706ad68ae8d0edbfd8e Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Thu, 24 Feb 2022 10:19:54 +0100 Subject: [PATCH 27/44] doc/go1.18: document minimum Linux kernel version For #45964 Change-Id: Ic66502c50ca328e944c91e710dca6c8dbc168e4f Reviewed-on: https://go-review.googlesource.com/c/go/+/387855 Trust: Tobias Klauser Reviewed-by: Matt Layher Reviewed-by: Ian Lance Taylor --- doc/go1.18.html | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 53e9d9b258..5289f82665 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -209,6 +209,12 @@ Do not send CLs removing the interior tags from such phrases. now supports the c-archive and c-shared build modes.

    +

    Linux

    + +

    + Go 1.18 requires Linux kernel version 2.6.32 or later. +

    +

    Windows

    From 55e5b03cb359c591a2ca6ad8b6e9274d094b1632 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Thu, 24 Feb 2022 17:01:14 -0500 Subject: [PATCH 28/44] doc/go1.18: note changes to automatic go.mod and go.sum updates Fixes #51242 Updates #45551 Change-Id: Iba6e6acd9a94d24e26fcdd125f1022430723ada7 Reviewed-on: https://go-review.googlesource.com/c/go/+/387920 Trust: Dmitri Shuralyov Reviewed-by: Ian Lance Taylor Trust: Bryan Mills --- doc/go1.18.html | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/doc/go1.18.html b/doc/go1.18.html index 5289f82665..21089ef4b3 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -287,6 +287,20 @@ Do not send CLs removing the interior tags from such phrases. and installs packages, as before.

    +

    Automatic go.mod and go.sum updates

    + +

    + The go mod graph, + go mod vendor, + go mod verify, and + go mod why subcommands + no longer automatically update the go.mod and + go.sum files. + (Those files can be updated explicitly using go get, + go mod tidy, or + go mod download.) +

    +

    go version

    From 7c694fbad1ed6f2f825fd09cf7a86da3be549cea Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Thu, 24 Feb 2022 13:35:16 -0800 Subject: [PATCH 29/44] go/types, types2: delay receiver type validation Delay validation of receiver type as it may cause premature expansion of types the receiver type is dependent on. This was actually a TODO. While the diff looks large-ish, the actual change is small: all the receiver validation code has been moved inside the delayed function body, and a couple of comments have been adjusted. Fixes #51232. Fixes #51233. Change-Id: I44edf0ba615996266791724b832d81b9ccb8b435 Reviewed-on: https://go-review.googlesource.com/c/go/+/387918 Trust: Robert Griesemer Run-TryBot: Robert Griesemer TryBot-Result: Gopher Robot Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/signature.go | 105 ++++++++--------- .../types2/testdata/fixedbugs/issue51232.go2 | 29 +++++ .../types2/testdata/fixedbugs/issue51233.go2 | 25 ++++ src/go/types/signature.go | 107 ++++++++++-------- .../types/testdata/fixedbugs/issue51232.go2 | 29 +++++ .../types/testdata/fixedbugs/issue51233.go2 | 25 ++++ test/typeparam/issue51232.go | 31 +++++ test/typeparam/issue51233.go | 22 ++++ 8 files changed, 274 insertions(+), 99 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue51232.go2 create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue51233.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue51232.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue51233.go2 create mode 100644 test/typeparam/issue51232.go create mode 100644 test/typeparam/issue51233.go diff --git a/src/cmd/compile/internal/types2/signature.go b/src/cmd/compile/internal/types2/signature.go index 76e588254d..c98024f924 100644 --- a/src/cmd/compile/internal/types2/signature.go +++ b/src/cmd/compile/internal/types2/signature.go @@ -194,66 +194,69 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams [] case 1: recv = recvList[0] } + sig.recv = recv - // TODO(gri) We should delay rtyp expansion to when we actually need the - // receiver; thus all checks here should be delayed to later. - rtyp, _ := deref(recv.typ) + // Delay validation of receiver type as it may cause premature expansion + // of types the receiver type is dependent on (see issues #51232, #51233). + check.later(func() { + rtyp, _ := deref(recv.typ) - // spec: "The receiver type must be of the form T or *T where T is a type name." - // (ignore invalid types - error was reported before) - if rtyp != Typ[Invalid] { - var err string - switch T := rtyp.(type) { - case *Named: - T.resolve(check.bestContext(nil)) - // The receiver type may be an instantiated type referred to - // by an alias (which cannot have receiver parameters for now). - if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { - check.errorf(recv.pos, "cannot define methods on instantiated type %s", recv.typ) - break - } - // spec: "The type denoted by T is called the receiver base type; it must not - // be a pointer or interface type and it must be declared in the same package - // as the method." - if T.obj.pkg != check.pkg { - err = "type not defined in this package" + // spec: "The receiver type must be of the form T or *T where T is a type name." + // (ignore invalid types - error was reported before) + if rtyp != Typ[Invalid] { + var err string + switch T := rtyp.(type) { + case *Named: + T.resolve(check.bestContext(nil)) + // The receiver type may be an instantiated type referred to + // by an alias (which cannot have receiver parameters for now). + if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { + check.errorf(recv.pos, "cannot define methods on instantiated type %s", recv.typ) + break + } + // spec: "The type denoted by T is called the receiver base type; it must not + // be a pointer or interface type and it must be declared in the same package + // as the method." + if T.obj.pkg != check.pkg { + err = "type not defined in this package" + if check.conf.CompilerErrorMessages { + check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ) + err = "" + } + } else { + // The underlying type of a receiver base type can be a type parameter; + // e.g. for methods with a generic receiver T[P] with type T[P any] P. + // TODO(gri) Such declarations are currently disallowed. + // Revisit the need for underIs. + underIs(T, func(u Type) bool { + switch u := u.(type) { + case *Basic: + // unsafe.Pointer is treated like a regular pointer + if u.kind == UnsafePointer { + err = "unsafe.Pointer" + return false + } + case *Pointer, *Interface: + err = "pointer or interface type" + return false + } + return true + }) + } + case *Basic: + err = "basic or unnamed type" if check.conf.CompilerErrorMessages { check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ) err = "" } - } else { - // The underlying type of a receiver base type can be a type parameter; - // e.g. for methods with a generic receiver T[P] with type T[P any] P. - underIs(T, func(u Type) bool { - switch u := u.(type) { - case *Basic: - // unsafe.Pointer is treated like a regular pointer - if u.kind == UnsafePointer { - err = "unsafe.Pointer" - return false - } - case *Pointer, *Interface: - err = "pointer or interface type" - return false - } - return true - }) + default: + check.errorf(recv.pos, "invalid receiver type %s", recv.typ) } - case *Basic: - err = "basic or unnamed type" - if check.conf.CompilerErrorMessages { - check.errorf(recv.pos, "cannot define new methods on non-local type %s", recv.typ) - err = "" + if err != "" { + check.errorf(recv.pos, "invalid receiver type %s (%s)", recv.typ, err) } - default: - check.errorf(recv.pos, "invalid receiver type %s", recv.typ) } - if err != "" { - check.errorf(recv.pos, "invalid receiver type %s (%s)", recv.typ, err) - // ok to continue - } - } - sig.recv = recv + }).describef(recv, "validate receiver %s", recv) } sig.params = NewTuple(params...) diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51232.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51232.go2 new file mode 100644 index 0000000000..6e575a376d --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51232.go2 @@ -0,0 +1,29 @@ +// 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 + +type RC[RG any] interface { + ~[]RG +} + +type Fn[RCT RC[RG], RG any] func(RCT) + +type F[RCT RC[RG], RG any] interface { + Fn() Fn[RCT] +} + +type concreteF[RCT RC[RG], RG any] struct { + makeFn func() Fn[RCT] +} + +func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { + return c.makeFn() +} + +func NewConcrete[RCT RC[RG], RG any](Rc RCT) F[RCT] { + return &concreteF[RCT]{ + makeFn: nil, + } +} diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51233.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51233.go2 new file mode 100644 index 0000000000..5c8393d039 --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51233.go2 @@ -0,0 +1,25 @@ +// 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 + +type RC[RG any] interface { + ~[]RG +} + +type Fn[RCT RC[RG], RG any] func(RCT) + +type FFn[RCT RC[RG], RG any] func() Fn[RCT] + +type F[RCT RC[RG], RG any] interface { + Fn() Fn[RCT] +} + +type concreteF[RCT RC[RG], RG any] struct { + makeFn FFn[RCT] +} + +func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { + return c.makeFn() +} diff --git a/src/go/types/signature.go b/src/go/types/signature.go index f174516268..a340ac701e 100644 --- a/src/go/types/signature.go +++ b/src/go/types/signature.go @@ -193,66 +193,77 @@ func (check *Checker) funcType(sig *Signature, recvPar *ast.FieldList, ftyp *ast switch len(recvList) { case 0: // error reported by resolver - recv = NewParam(0, nil, "", Typ[Invalid]) // ignore recv below + recv = NewParam(token.NoPos, nil, "", Typ[Invalid]) // ignore recv below default: // more than one receiver - check.error(recvList[len(recvList)-1], _BadRecv, "method must have exactly one receiver") + check.error(recvList[len(recvList)-1], _InvalidRecv, "method must have exactly one receiver") fallthrough // continue with first receiver case 1: recv = recvList[0] } + sig.recv = recv - // TODO(gri) We should delay rtyp expansion to when we actually need the - // receiver; thus all checks here should be delayed to later. - rtyp, _ := deref(recv.typ) + // Delay validation of receiver type as it may cause premature expansion + // of types the receiver type is dependent on (see issues #51232, #51233). + check.later(func() { + rtyp, _ := deref(recv.typ) - // spec: "The receiver type must be of the form T or *T where T is a type name." - // (ignore invalid types - error was reported before) - if rtyp != Typ[Invalid] { - var err string - switch T := rtyp.(type) { - case *Named: - T.resolve(check.bestContext(nil)) - // The receiver type may be an instantiated type referred to - // by an alias (which cannot have receiver parameters for now). - if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { - check.errorf(atPos(recv.pos), _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ) - break - } - // spec: "The type denoted by T is called the receiver base type; it must not - // be a pointer or interface type and it must be declared in the same package - // as the method." - if T.obj.pkg != check.pkg { - err = "type not defined in this package" - } else { - // The underlying type of a receiver base type can be a type parameter; - // e.g. for methods with a generic receiver T[P] with type T[P any] P. - underIs(T, func(u Type) bool { - switch u := u.(type) { - case *Basic: - // unsafe.Pointer is treated like a regular pointer - if u.kind == UnsafePointer { - err = "unsafe.Pointer" + // spec: "The receiver type must be of the form T or *T where T is a type name." + // (ignore invalid types - error was reported before) + if rtyp != Typ[Invalid] { + var err string + switch T := rtyp.(type) { + case *Named: + T.resolve(check.bestContext(nil)) + // The receiver type may be an instantiated type referred to + // by an alias (which cannot have receiver parameters for now). + if T.TypeArgs() != nil && sig.RecvTypeParams() == nil { + check.errorf(recv, _InvalidRecv, "cannot define methods on instantiated type %s", recv.typ) + break + } + // spec: "The type denoted by T is called the receiver base type; it must not + // be a pointer or interface type and it must be declared in the same package + // as the method." + if T.obj.pkg != check.pkg { + err = "type not defined in this package" + if compilerErrorMessages { + check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ) + err = "" + } + } else { + // The underlying type of a receiver base type can be a type parameter; + // e.g. for methods with a generic receiver T[P] with type T[P any] P. + // TODO(gri) Such declarations are currently disallowed. + // Revisit the need for underIs. + underIs(T, func(u Type) bool { + switch u := u.(type) { + case *Basic: + // unsafe.Pointer is treated like a regular pointer + if u.kind == UnsafePointer { + err = "unsafe.Pointer" + return false + } + case *Pointer, *Interface: + err = "pointer or interface type" return false } - case *Pointer, *Interface: - err = "pointer or interface type" - return false - } - return true - }) + return true + }) + } + case *Basic: + err = "basic or unnamed type" + if compilerErrorMessages { + check.errorf(recv, _InvalidRecv, "cannot define new methods on non-local type %s", recv.typ) + err = "" + } + default: + check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ) + } + if err != "" { + check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err) } - case *Basic: - err = "basic or unnamed type" - default: - check.errorf(recv, _InvalidRecv, "invalid receiver type %s", recv.typ) } - if err != "" { - check.errorf(recv, _InvalidRecv, "invalid receiver type %s (%s)", recv.typ, err) - // ok to continue - } - } - sig.recv = recv + }).describef(recv, "validate receiver %s", recv) } sig.params = NewTuple(params...) diff --git a/src/go/types/testdata/fixedbugs/issue51232.go2 b/src/go/types/testdata/fixedbugs/issue51232.go2 new file mode 100644 index 0000000000..6e575a376d --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue51232.go2 @@ -0,0 +1,29 @@ +// 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 + +type RC[RG any] interface { + ~[]RG +} + +type Fn[RCT RC[RG], RG any] func(RCT) + +type F[RCT RC[RG], RG any] interface { + Fn() Fn[RCT] +} + +type concreteF[RCT RC[RG], RG any] struct { + makeFn func() Fn[RCT] +} + +func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { + return c.makeFn() +} + +func NewConcrete[RCT RC[RG], RG any](Rc RCT) F[RCT] { + return &concreteF[RCT]{ + makeFn: nil, + } +} diff --git a/src/go/types/testdata/fixedbugs/issue51233.go2 b/src/go/types/testdata/fixedbugs/issue51233.go2 new file mode 100644 index 0000000000..5c8393d039 --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue51233.go2 @@ -0,0 +1,25 @@ +// 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 + +type RC[RG any] interface { + ~[]RG +} + +type Fn[RCT RC[RG], RG any] func(RCT) + +type FFn[RCT RC[RG], RG any] func() Fn[RCT] + +type F[RCT RC[RG], RG any] interface { + Fn() Fn[RCT] +} + +type concreteF[RCT RC[RG], RG any] struct { + makeFn FFn[RCT] +} + +func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { + return c.makeFn() +} diff --git a/test/typeparam/issue51232.go b/test/typeparam/issue51232.go new file mode 100644 index 0000000000..2272dcdfcd --- /dev/null +++ b/test/typeparam/issue51232.go @@ -0,0 +1,31 @@ +// compile -G=3 + +// 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 + +type RC[RG any] interface { + ~[]RG +} + +type Fn[RCT RC[RG], RG any] func(RCT) + +type F[RCT RC[RG], RG any] interface { + Fn() Fn[RCT] +} + +type concreteF[RCT RC[RG], RG any] struct { + makeFn func() Fn[RCT] +} + +func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { + return c.makeFn() +} + +func NewConcrete[RCT RC[RG], RG any](Rc RCT) F[RCT] { + return &concreteF[RCT]{ + makeFn: nil, + } +} diff --git a/test/typeparam/issue51233.go b/test/typeparam/issue51233.go new file mode 100644 index 0000000000..523f0b34d6 --- /dev/null +++ b/test/typeparam/issue51233.go @@ -0,0 +1,22 @@ +// compile -G=3 + +// 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 + +type RC[RG any] interface { + ~[]RG +} +type Fn[RCT RC[RG], RG any] func(RCT) +type FFn[RCT RC[RG], RG any] func() Fn[RCT] +type F[RCT RC[RG], RG any] interface { + Fn() Fn[RCT] +} +type concreteF[RCT RC[RG], RG any] struct { + makeFn FFn[RCT] +} + +func (c *concreteF[RCT, RG]) Fn() Fn[RCT] { + return c.makeFn() +} From 26999cfd84dfa11f8e87153dc91a9f67070f6916 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Thu, 24 Feb 2022 23:31:53 -0500 Subject: [PATCH 30/44] runtime/internal/atomic: set SP delta correctly for 64-bit atomic functions on ARM 64-bit atomic functions on ARM have the following structure: - check if the address is 64-bit aligned, if not, prepare a frame and call panicUnaligned - tail call armXXX or goXXX depending on GOARM The alignment check calls panicUnaligned after preparing a frame, so the stack can be unwound. The call never returns, so the SP is not set back. However, the assembler assigns SP delta following the instruction stream order, not the control flow. So it leaves a nonzero SP delta after the check, to the tail call instructions, which is wrong because when they are executed the SP is not decremented. This CL fixes this by adding the SP back (the instruction never executes, just tells the assembler to set the SP delta back). Should fix #51353. Change-Id: I976cb1cfb0e9008b13538765cbc7eea0c19c7130 Reviewed-on: https://go-review.googlesource.com/c/go/+/388014 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Gopher Robot Reviewed-by: Michael Pratt --- src/runtime/internal/atomic/atomic_arm.s | 42 +++++++++--------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/src/runtime/internal/atomic/atomic_arm.s b/src/runtime/internal/atomic/atomic_arm.s index be3fd3a395..92cbe8a34f 100644 --- a/src/runtime/internal/atomic/atomic_arm.s +++ b/src/runtime/internal/atomic/atomic_arm.s @@ -229,16 +229,22 @@ store64loop: // functions tail-call into the appropriate implementation, which // means they must not open a frame. Hence, when they go down the // panic path, at that point they push the LR to create a real frame -// (they don't need to pop it because panic won't return). +// (they don't need to pop it because panic won't return; however, we +// do need to set the SP delta back). + +// Check if R1 is 8-byte aligned, panic if not. +// Clobbers R2. +#define CHECK_ALIGN \ + AND.S $7, R1, R2 \ + BEQ 4(PC) \ + MOVW.W R14, -4(R13) /* prepare a real frame */ \ + BL ·panicUnaligned(SB) \ + ADD $4, R13 /* compensate SP delta */ TEXT ·Cas64(SB),NOSPLIT,$-4-21 NO_LOCAL_POINTERS MOVW addr+0(FP), R1 - // make unaligned atomic access panic - AND.S $7, R1, R2 - BEQ 3(PC) - MOVW.W R14, -4(R13) // prepare a real frame - BL ·panicUnaligned(SB) + CHECK_ALIGN MOVB runtime·goarm(SB), R11 CMP $7, R11 @@ -249,11 +255,7 @@ TEXT ·Cas64(SB),NOSPLIT,$-4-21 TEXT ·Xadd64(SB),NOSPLIT,$-4-20 NO_LOCAL_POINTERS MOVW addr+0(FP), R1 - // make unaligned atomic access panic - AND.S $7, R1, R2 - BEQ 3(PC) - MOVW.W R14, -4(R13) // prepare a real frame - BL ·panicUnaligned(SB) + CHECK_ALIGN MOVB runtime·goarm(SB), R11 CMP $7, R11 @@ -264,11 +266,7 @@ TEXT ·Xadd64(SB),NOSPLIT,$-4-20 TEXT ·Xchg64(SB),NOSPLIT,$-4-20 NO_LOCAL_POINTERS MOVW addr+0(FP), R1 - // make unaligned atomic access panic - AND.S $7, R1, R2 - BEQ 3(PC) - MOVW.W R14, -4(R13) // prepare a real frame - BL ·panicUnaligned(SB) + CHECK_ALIGN MOVB runtime·goarm(SB), R11 CMP $7, R11 @@ -279,11 +277,7 @@ TEXT ·Xchg64(SB),NOSPLIT,$-4-20 TEXT ·Load64(SB),NOSPLIT,$-4-12 NO_LOCAL_POINTERS MOVW addr+0(FP), R1 - // make unaligned atomic access panic - AND.S $7, R1, R2 - BEQ 3(PC) - MOVW.W R14, -4(R13) // prepare a real frame - BL ·panicUnaligned(SB) + CHECK_ALIGN MOVB runtime·goarm(SB), R11 CMP $7, R11 @@ -294,11 +288,7 @@ TEXT ·Load64(SB),NOSPLIT,$-4-12 TEXT ·Store64(SB),NOSPLIT,$-4-12 NO_LOCAL_POINTERS MOVW addr+0(FP), R1 - // make unaligned atomic access panic - AND.S $7, R1, R2 - BEQ 3(PC) - MOVW.W R14, -4(R13) // prepare a real frame - BL ·panicUnaligned(SB) + CHECK_ALIGN MOVB runtime·goarm(SB), R11 CMP $7, R11 From 01e522a97384d2c81c90490654c2749bfe05045e Mon Sep 17 00:00:00 2001 From: Robert Findley Date: Fri, 25 Feb 2022 18:20:12 -0500 Subject: [PATCH 31/44] go/types,types2: revert documentation for Type.Underlying In the dev.typeparams branch, the documentation for Type.Underlying was updated with commentary about forwarding chains. This aspect of Underlying should not be exposed to the user. Revert to the documentation of Go 1.16. Fixes #51036 Change-Id: I4b73d3908a88606314aab56540cca91c014dc426 Reviewed-on: https://go-review.googlesource.com/c/go/+/388036 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Gopher Robot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/type.go | 4 +--- src/go/types/type.go | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/types2/type.go b/src/cmd/compile/internal/types2/type.go index ca8f155791..0fe39dbca4 100644 --- a/src/cmd/compile/internal/types2/type.go +++ b/src/cmd/compile/internal/types2/type.go @@ -7,9 +7,7 @@ package types2 // A Type represents a type of Go. // All types implement the Type interface. type Type interface { - // Underlying returns the underlying type of a type - // w/o following forwarding chains. Only used by - // client packages. + // Underlying returns the underlying type of a type. Underlying() Type // String returns a string representation of a type. diff --git a/src/go/types/type.go b/src/go/types/type.go index 323365aefe..130637530b 100644 --- a/src/go/types/type.go +++ b/src/go/types/type.go @@ -7,9 +7,7 @@ package types // A Type represents a type of Go. // All types implement the Type interface. type Type interface { - // Underlying returns the underlying type of a type - // w/o following forwarding chains. Only used by - // client packages. + // Underlying returns the underlying type of a type. Underlying() Type // String returns a string representation of a type. From 286e3e61aa9310bb8fd333adac6d06cfb2fcc95b Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Fri, 25 Feb 2022 11:10:44 -0800 Subject: [PATCH 32/44] go/types, types2: report an error for x.sel where x is a built-in In case of a selector expression x.sel where x is a built-in we didn't report an error because the type of built-ins is invalid and we surpress errors on operands of invalid types, assuming that an error has been reported before. Add a corresponding check for this case. Review all places where we call Checker.exprOrType to ensure (invalid) built-ins are reported. Adjusted position for index error in types2. Fixes #51360. Change-Id: I24693819c729994ab79d31de8fa7bd370b3e8469 Reviewed-on: https://go-review.googlesource.com/c/go/+/388054 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/call.go | 6 +++++- src/cmd/compile/internal/types2/index.go | 2 +- .../types2/testdata/fixedbugs/issue51360.go | 13 +++++++++++++ src/go/types/call.go | 7 ++++++- src/go/types/index.go | 1 + src/go/types/testdata/fixedbugs/issue51360.go | 13 +++++++++++++ 6 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue51360.go create mode 100644 src/go/types/testdata/fixedbugs/issue51360.go diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go index 22f65ed626..d12ee49adb 100644 --- a/src/cmd/compile/internal/types2/call.go +++ b/src/cmd/compile/internal/types2/call.go @@ -525,7 +525,11 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) { } check.exprOrType(x, e.X, false) - if x.mode == invalid { + switch x.mode { + case builtin: + check.errorf(e.Pos(), "cannot select on %s", x) + goto Error + case invalid: goto Error } diff --git a/src/cmd/compile/internal/types2/index.go b/src/cmd/compile/internal/types2/index.go index 1eaddded9a..61009c121e 100644 --- a/src/cmd/compile/internal/types2/index.go +++ b/src/cmd/compile/internal/types2/index.go @@ -182,7 +182,7 @@ func (check *Checker) indexExpr(x *operand, e *syntax.IndexExpr) (isFuncInst boo } if !valid { - check.errorf(x, invalidOp+"cannot index %s", x) + check.errorf(e.Pos(), invalidOp+"cannot index %s", x) x.mode = invalid return false } diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51360.go b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51360.go new file mode 100644 index 0000000000..447ce036ae --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51360.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. + +package p + +func _() { + len. /* ERROR cannot select on len */ Println + len. /* ERROR cannot select on len */ Println() + _ = len. /* ERROR cannot select on len */ Println + _ = len[ /* ERROR cannot index len */ 0] + _ = *len /* ERROR cannot indirect len */ +} diff --git a/src/go/types/call.go b/src/go/types/call.go index 3dab284459..854528ddfa 100644 --- a/src/go/types/call.go +++ b/src/go/types/call.go @@ -527,7 +527,12 @@ func (check *Checker) selector(x *operand, e *ast.SelectorExpr) { } check.exprOrType(x, e.X, false) - if x.mode == invalid { + switch x.mode { + case builtin: + // types2 uses the position of '.' for the error + check.errorf(e.Sel, _UncalledBuiltin, "cannot select on %s", x) + goto Error + case invalid: goto Error } diff --git a/src/go/types/index.go b/src/go/types/index.go index eac6017ba2..33075edaf1 100644 --- a/src/go/types/index.go +++ b/src/go/types/index.go @@ -183,6 +183,7 @@ func (check *Checker) indexExpr(x *operand, e *typeparams.IndexExpr) (isFuncInst } if !valid { + // types2 uses the position of '[' for the error check.invalidOp(x, _NonIndexableOperand, "cannot index %s", x) x.mode = invalid return false diff --git a/src/go/types/testdata/fixedbugs/issue51360.go b/src/go/types/testdata/fixedbugs/issue51360.go new file mode 100644 index 0000000000..fe3de04dbf --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue51360.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. + +package p + +func _() { + len.Println /* ERROR cannot select on len */ + len.Println /* ERROR cannot select on len */ () + _ = len.Println /* ERROR cannot select on len */ + _ = len /* ERROR cannot index len */ [0] + _ = *len /* ERROR cannot indirect len */ +} From a064a4f29a97a4fc7398d1ac9d7c53c5ba0bc646 Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 25 Feb 2022 15:10:24 -0800 Subject: [PATCH 33/44] cmd/compile: ensure dictionary assignment statements are defining statements The problem in 51355 is that escape analysis decided that the dictionary variable was captured by reference instead of by value. We want dictionaries to always be captured by value. Escape analysis was confused because it saw what it thought was a reassignment of the dictionary variable. In fact, it was the only assignment, it just wasn't marked as the defining assignment. Fix that. Add an assert to make sure this stays true. Fixes #51355 Change-Id: Ifd9342455fa107b113f5ff521a94cdbf1b8a7733 Reviewed-on: https://go-review.googlesource.com/c/go/+/388115 Trust: Keith Randall Run-TryBot: Keith Randall Trust: Cuong Manh Le Trust: Dan Scales Reviewed-by: Cuong Manh Le Reviewed-by: Dan Scales TryBot-Result: Gopher Robot --- src/cmd/compile/internal/escape/escape.go | 4 +++ src/cmd/compile/internal/noder/stencil.go | 4 ++- test/typeparam/issue51355.go | 31 +++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) create mode 100644 test/typeparam/issue51355.go diff --git a/src/cmd/compile/internal/escape/escape.go b/src/cmd/compile/internal/escape/escape.go index c2145bdf91..bc6f7c93bb 100644 --- a/src/cmd/compile/internal/escape/escape.go +++ b/src/cmd/compile/internal/escape/escape.go @@ -10,6 +10,7 @@ import ( "cmd/compile/internal/base" "cmd/compile/internal/ir" "cmd/compile/internal/logopt" + "cmd/compile/internal/typecheck" "cmd/compile/internal/types" ) @@ -243,6 +244,9 @@ func (b *batch) flowClosure(k hole, clo *ir.ClosureExpr) { n.SetByval(!loc.addrtaken && !loc.reassigned && n.Type().Size() <= 128) if !n.Byval() { n.SetAddrtaken(true) + if n.Sym().Name == typecheck.LocalDictName { + base.FatalfAt(n.Pos(), "dictionary variable not captured by value") + } } if base.Flag.LowerM > 1 { diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 03937094e1..807794dc30 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -410,7 +410,8 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node { fn, formalParams, formalResults := startClosure(pos, outer, typ) // This is the dictionary we want to use. - // It may be a constant, or it may be a dictionary acquired from the outer function's dictionary. + // It may be a constant, it may be the outer functions's dictionary, or it may be + // a subdictionary acquired from the outer function's dictionary. // For the latter, dictVar is a variable in the outer function's scope, set to the subdictionary // read from the outer function's dictionary. var dictVar *ir.Name @@ -1145,6 +1146,7 @@ func (subst *subster) node(n ir.Node) ir.Node { newfn.Dcl = append(newfn.Dcl, ldict) as := ir.NewAssignStmt(x.Pos(), ldict, cdict) as.SetTypecheck(1) + ldict.Defn = as newfn.Body.Append(as) // Create inst info for the instantiated closure. The dict diff --git a/test/typeparam/issue51355.go b/test/typeparam/issue51355.go new file mode 100644 index 0000000000..15ffa4ba21 --- /dev/null +++ b/test/typeparam/issue51355.go @@ -0,0 +1,31 @@ +// compile -G=3 + +// 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 Cache[E comparable] struct { + adder func(...E) +} + +func New[E comparable]() *Cache[E] { + c := &Cache[E]{} + + c.adder = func(elements ...E) { + for _, value := range elements { + value := value + go func() { + println(value) + }() + } + } + + return c +} + +func main() { + c := New[string]() + c.adder("test") +} From 57dda9795da20fc12c7cfb03438959302200dbc7 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Wed, 23 Feb 2022 17:57:09 -0800 Subject: [PATCH 34/44] test: add new test case for 51219 that triggers the types2 issue The existing test for 51219 didn't actually trigger the types2 issue - I hadn't been able to minimize the test case yet properly. This new test case issue51219b.go now does trigger the types2 issue (it's only slightly different). Updates #51219 Change-Id: Iaba8144b4702ff4fefec86c899b8acef127b10dc Reviewed-on: https://go-review.googlesource.com/c/go/+/387814 Trust: Dan Scales Reviewed-by: Robert Findley --- test/typeparam/issue51219.dir/a.go | 39 ------------------- test/typeparam/issue51219.dir/main.go | 4 +- test/typeparam/issue51219.out | 2 +- test/typeparam/issue51219b.dir/a.go | 37 ++++++++++++++++++ .../{issue51219.dir => issue51219b.dir}/b.go | 5 ++- test/typeparam/issue51219b.dir/p.go | 14 +++++++ test/typeparam/issue51219b.go | 7 ++++ 7 files changed, 64 insertions(+), 44 deletions(-) create mode 100644 test/typeparam/issue51219b.dir/a.go rename test/typeparam/{issue51219.dir => issue51219b.dir}/b.go (77%) create mode 100644 test/typeparam/issue51219b.dir/p.go create mode 100644 test/typeparam/issue51219b.go diff --git a/test/typeparam/issue51219.dir/a.go b/test/typeparam/issue51219.dir/a.go index 3ed4322dbf..29670df0d3 100644 --- a/test/typeparam/issue51219.dir/a.go +++ b/test/typeparam/issue51219.dir/a.go @@ -18,42 +18,3 @@ type IConstraint interface { type I[T IConstraint] struct { } - -// The following types form an even more complex recursion (through two type -// constraints), and model the actual types in the issue (#51219) more closely. -// However, they don't reveal any new issue. But it seems useful to leave this -// complex set of types in a test in case it might be broken by future changes. - -type Message struct { - Interaction *Interaction[JsonRaw] `json:"interaction,omitempty"` -} - -type ResolvedDataConstraint interface { - User | Message -} - -type Snowflake uint64 - -type ResolvedData[T ResolvedDataConstraint] map[Snowflake]T - -type User struct { -} - -type Resolved struct { - Users ResolvedData[User] `json:"users,omitempty"` -} - -type resolvedInteractionWithOptions struct { - Resolved Resolved `json:"resolved,omitempty"` -} - -type UserCommandInteractionData struct { - resolvedInteractionWithOptions -} - -type InteractionDataConstraint interface { - JsonRaw | UserCommandInteractionData -} - -type Interaction[DataT InteractionDataConstraint] struct { -} diff --git a/test/typeparam/issue51219.dir/main.go b/test/typeparam/issue51219.dir/main.go index c5cffd111c..999b4a96a1 100644 --- a/test/typeparam/issue51219.dir/main.go +++ b/test/typeparam/issue51219.dir/main.go @@ -6,13 +6,11 @@ package main import ( "a" - "b" "fmt" ) func main() { var x a.I[a.JsonRaw] - var y b.InteractionRequest[a.JsonRaw] - fmt.Printf("%v %v\n", x, y) + fmt.Printf("%v\n", x) } diff --git a/test/typeparam/issue51219.out b/test/typeparam/issue51219.out index 99c5b9aa9b..0967ef424b 100644 --- a/test/typeparam/issue51219.out +++ b/test/typeparam/issue51219.out @@ -1 +1 @@ -{} {{}} +{} diff --git a/test/typeparam/issue51219b.dir/a.go b/test/typeparam/issue51219b.dir/a.go new file mode 100644 index 0000000000..19049406a6 --- /dev/null +++ b/test/typeparam/issue51219b.dir/a.go @@ -0,0 +1,37 @@ +// 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 Interaction[DataT InteractionDataConstraint] struct { +} + +type InteractionDataConstraint interface { + []byte | + UserCommandInteractionData +} + +type UserCommandInteractionData struct { + resolvedInteractionWithOptions +} + +type resolvedInteractionWithOptions struct { + Resolved Resolved `json:"resolved,omitempty"` +} + +type Resolved struct { + Users ResolvedData[User] `json:"users,omitempty"` +} + +type ResolvedData[T ResolvedDataConstraint] map[uint64]T + +type ResolvedDataConstraint interface { + User | Message +} + +type User struct{} + +type Message struct { + Interaction *Interaction[[]byte] `json:"interaction,omitempty"` +} diff --git a/test/typeparam/issue51219.dir/b.go b/test/typeparam/issue51219b.dir/b.go similarity index 77% rename from test/typeparam/issue51219.dir/b.go rename to test/typeparam/issue51219b.dir/b.go index c1590725b0..8413d666b7 100644 --- a/test/typeparam/issue51219.dir/b.go +++ b/test/typeparam/issue51219b.dir/b.go @@ -4,8 +4,11 @@ package b -import "a" +import ( + "./a" +) +// InteractionRequest is an incoming request Interaction type InteractionRequest[T a.InteractionDataConstraint] struct { a.Interaction[T] } diff --git a/test/typeparam/issue51219b.dir/p.go b/test/typeparam/issue51219b.dir/p.go new file mode 100644 index 0000000000..9f8b840d48 --- /dev/null +++ b/test/typeparam/issue51219b.dir/p.go @@ -0,0 +1,14 @@ +// 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 ( + "./b" +) + +// ResponseWriterMock mocks corde's ResponseWriter interface +type ResponseWriterMock struct { + x b.InteractionRequest[[]byte] +} diff --git a/test/typeparam/issue51219b.go b/test/typeparam/issue51219b.go new file mode 100644 index 0000000000..060a1214cc --- /dev/null +++ b/test/typeparam/issue51219b.go @@ -0,0 +1,7 @@ +// compiledir -G=3 + +// 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 9c4a8620c802fbb03545e401c41f11d622b84b42 Mon Sep 17 00:00:00 2001 From: Dmitri Shuralyov Date: Mon, 28 Feb 2022 09:28:47 -0500 Subject: [PATCH 35/44] CONTRIBUTORS: update for the Go 1.18 release This update was created using the updatecontrib command: go install golang.org/x/build/cmd/updatecontrib@latest cd gotip updatecontrib With manual changes based on publicly available information to canonicalize letter case and formatting for a few names. For #12042. Change-Id: If08b7e798cff6ec4248011bdadcc524b510aaff7 Reviewed-on: https://go-review.googlesource.com/c/go/+/388394 Trust: Dmitri Shuralyov Run-TryBot: Dmitri Shuralyov Auto-Submit: Dmitri Shuralyov TryBot-Result: Gopher Robot Reviewed-by: Carlos Amedee Trust: Carlos Amedee --- CONTRIBUTORS | 97 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTORS b/CONTRIBUTORS index e2e102f610..48567eed15 100644 --- a/CONTRIBUTORS +++ b/CONTRIBUTORS @@ -120,6 +120,7 @@ Alex Kohler Alex Myasoedov Alex Opie Alex Plugaru +Alex Schade <39062967+aschade92@users.noreply.github.com> Alex Schroeder Alex Sergeyev Alex Tokarev @@ -135,6 +136,7 @@ Alexander Klauer Alexander Kucherenko Alexander Larsson Alexander Lourier +Alexander Melentyev Alexander Menzhinsky Alexander Morozov Alexander Neumann @@ -145,6 +147,7 @@ Alexander Polcyn Alexander Rakoczy Alexander Reece Alexander Surma +Alexander Yastrebov Alexander Zhavnerchik Alexander Zillion Alexander Zolotov @@ -179,6 +182,7 @@ Alok Menghrajani Alwin Doss Aman Gupta Amarjeet Anand +Amelia Downs Amir Mohammad Saied Amit Kumar Amr Mohammed @@ -191,6 +195,7 @@ Anatol Pomozov Anders Pearson Anderson Queiroz André Carvalho +Andre Marianiello André Martins Andre Nathan Andrea Nodari @@ -221,6 +226,7 @@ Andrew Gerrand Andrew Harding Andrew Jackura Andrew Kemm +Andrew LeFevre Andrew Louis Andrew Lutomirski Andrew Medvedev @@ -234,6 +240,7 @@ Andrew Stormont Andrew Stribblehill Andrew Szeto Andrew Todd +Andrew Wansink Andrew Werner Andrew Wilkins Andrew Williams @@ -283,6 +290,7 @@ Antonio Bibiano Antonio Garcia Antonio Huete Jimenez Antonio Murdaca +Antonio Ojea Antonio Troina Anze Kolar Aofei Sheng @@ -290,6 +298,7 @@ Apisak Darakananda Aram Hăvărneanu Araragi Hokuto Arash Bina +Archana Ravindar Arda Güçlü Areski Belaid Ariel Mashraki @@ -299,6 +308,7 @@ Arnaud Ysmal Arne Hormann Arnout Engelen Aron Nopanen +Arran Walker Artem Alekseev Artem Khvastunov Artem Kolin @@ -337,6 +347,7 @@ Balaram Makam Balazs Lecz Baokun Lee Barnaby Keene +Bartłomiej Klimczak Bartosz Grzybowski Bartosz Oler Bassam Ojeil @@ -368,6 +379,7 @@ Benny Siegert Benoit Sigoure Berengar Lehr Berkant Ipek <41230766+0xbkt@users.noreply.github.com> +Beth Brown Bharath Kumar Uppala Bharath Thiruveedula Bhavin Gandhi @@ -430,6 +442,7 @@ Brian Ketelsen Brian Slesinsky Brian Smith Brian Starke +Bruce Huang Bryan Alexander Bryan Boreham Bryan C. Mills @@ -482,17 +495,21 @@ Charles Kenney Charles L. Dorian Charles Lee Charles Weill +Charlie Getzen Charlie Moog Charlotte Brandhorst-Satzkorn Chauncy Cullitan Chen Zhidong Chen Zhihan +Cheng Wang Cherry Mui Chew Choon Keat +Chia-Chi Hsu Chiawen Chen Chirag Sukhala Cholerae Hu Chotepud Teo +Chressie Himpel Chris Ball Chris Biscardi Chris Broadfoot @@ -570,6 +587,7 @@ Cuong Manh Le Curtis La Graff Cyrill Schumacher Dai Jie +Dai Wentao Daisuke Fujita Daisuke Suzuki Daker Fernandes Pinheiro @@ -603,6 +621,7 @@ Daniel Langner Daniel Lidén Daniel Lublin Daniel Mangum +Daniel Marshall Daniel Martí Daniel McCarney Daniel Morsing @@ -727,6 +746,7 @@ Dmitry Mottl Dmitry Neverov Dmitry Savintsev Dmitry Yakunin +Dmytro Shynkevych Doga Fincan Domas Tamašauskas Domen Ipavec @@ -751,6 +771,7 @@ Dustin Herbison Dustin Long Dustin Sallings Dustin Shields-Cloues +Dustin Spicuzza Dvir Volk Dylan Waits Ed Schouten @@ -810,9 +831,11 @@ Erin Masatsugu Ernest Chiang Erwin Oegema Esko Luontola +Ethan Anderson Ethan Burns Ethan Hur Ethan Miller +Ethan Reesor Euan Kemp Eugene Formanenko Eugene Kalinin @@ -831,8 +854,10 @@ Evgeniy Polyakov Ewan Chou Ewan Valentine Eyal Posener +F. Talha Altınel Fabian Wickborn Fabian Zaremba +Fabio Falzoi Fabrizio Milo Faiyaz Ahmed Fan Hongjian @@ -861,21 +886,25 @@ Firmansyah Adiputra Florian Forster Florian Uekermann Florian Weimer +Florin Papa Florin Patan Folke Behrens Ford Hurley +Forest Johnson Francesc Campoy Francesco Guardiani Francesco Renzi Francisco Claude Francisco Rojas Francisco Souza +Frank Chiarulli Jr Frank Schroeder Frank Somers Frederic Guillot Frederick Kelly Mayle III Frederik Ring Frederik Zipp +Frediano Ziglio Fredrik Enestad Fredrik Forsmo Fredrik Wallgren @@ -914,6 +943,7 @@ Geon Kim Georg Reinke George Gkirtsou George Hartzell +George Looshch George Shammas George Tsilias Gerasimos (Makis) Maropoulos @@ -954,19 +984,27 @@ GitHub User @fatedier (7346661) GitHub User @frennkie (6499251) GitHub User @geedchin (11672310) GitHub User @GrigoriyMikhalkin (3637857) +GitHub User @Gusted (25481501) GitHub User @hengwu0 (41297446) <41297446+hengwu0@users.noreply.github.com> GitHub User @hitzhangjie (3725760) +GitHub User @hkhere (33268704) <33268704+hkhere@users.noreply.github.com> +GitHub User @hopehook (7326168) GitHub User @hqpko (13887251) +GitHub User @Illirgway (5428603) GitHub User @itchyny (375258) GitHub User @jinmiaoluo (39730824) GitHub User @jopbrown (6345470) GitHub User @kazyshr (30496953) GitHub User @kc1212 (1093806) GitHub User @komisan19 (18901496) +GitHub User @korzhao (64203902) GitHub User @Kropekk (13366453) +GitHub User @lgbgbl (65756378) GitHub User @lhl2617 (33488131) GitHub User @linguohua (3434367) +GitHub User @lloydchang (1329685) GitHub User @LotusFenn (13775899) +GitHub User @luochuanhang (96416201) GitHub User @ly303550688 (11519839) GitHub User @madiganz (18340029) GitHub User @maltalex (10195391) @@ -976,6 +1014,7 @@ GitHub User @micnncim (21333876) GitHub User @mkishere (224617) <224617+mkishere@users.noreply.github.com> GitHub User @nu50218 (40682920) GitHub User @OlgaVlPetrova (44112727) +GitHub User @pierwill (19642016) GitHub User @pityonline (438222) GitHub User @po3rin (29445112) GitHub User @pokutuna (57545) @@ -983,13 +1022,18 @@ GitHub User @povsister (11040951) GitHub User @pytimer (17105586) GitHub User @qcrao (7698088) GitHub User @ramenjuniti (32011829) +GitHub User @renthraysk (30576707) +GitHub User @roudkerk (52280478) GitHub User @saitarunreddy (21041941) GitHub User @SataQiu (9354727) +GitHub User @seifchen (23326132) GitHub User @shogo-ma (9860598) GitHub User @sivchari (55221074) GitHub User @skanehira (7888591) GitHub User @soolaugust (10558124) GitHub User @surechen (7249331) +GitHub User @syumai (6882878) +GitHub User @tangxi666 (48145175) GitHub User @tatsumack (4510569) GitHub User @tell-k (26263) GitHub User @tennashi (10219626) @@ -999,6 +1043,7 @@ GitHub User @unbyte (5772358) GitHub User @uropek (39370426) GitHub User @utkarsh-extc (53217283) GitHub User @witchard (4994659) +GitHub User @wmdngngng (22067700) GitHub User @wolf1996 (5901874) GitHub User @yah01 (12216890) GitHub User @yuanhh (1298735) @@ -1029,12 +1074,14 @@ Guilherme Garnier Guilherme Goncalves Guilherme Rezende Guilherme Souza <32180229+gqgs@users.noreply.github.com> +Guillaume Blaquiere Guillaume J. Charmes Guillaume Sottas Günther Noack Guobiao Mei Guodong Li Guoliang Wang +Guoqi Chen Gustav Paul Gustav Westling Gustavo Franco @@ -1050,6 +1097,8 @@ Hang Qian Hanjun Kim Hanlin He Hanlin Shi +Hans Nielsen +Hao Mou Haoran Luo Haosdent Huang Harald Nordgren @@ -1126,6 +1175,7 @@ Igor Zhilianin Ikko Ashimine Illya Yalovyy Ilya Chukov <56119080+Elias506@users.noreply.github.com> +Ilya Mateyko Ilya Sinelnikov Ilya Tocar INADA Naoki @@ -1157,6 +1207,7 @@ Jaana Burcu Dogan Jaap Aarts Jack Britton Jack Lindamood +Jack You Jacob Baskin Jacob Blain Christen Jacob H. Haven @@ -1165,6 +1216,7 @@ Jacob Walker Jaden Teng Jae Kwon Jake B +Jake Ciolek Jakob Borg Jakob Weisblat Jakub Čajka @@ -1183,6 +1235,7 @@ James Eady James Fennell James Fysh James Gray +James Harris James Hartig James Kasten James Lawrence @@ -1246,6 +1299,7 @@ Jean de Klerk Jean-André Santoni Jean-François Bustarret Jean-Francois Cantin +Jean-Hadrien Chabran Jean-Marc Eurin Jean-Nicolas Moal Jed Denlea @@ -1260,6 +1314,7 @@ Jeff Johnson Jeff R. Allen Jeff Sickel Jeff Wendling +Jeff Wentworth Jeff Widman Jeffrey H Jelte Fennema @@ -1282,6 +1337,7 @@ Jesús Espino Jia Zhan Jiacai Liu Jiahao Lu +Jiahua Wang Jianing Yu Jianqiao Li Jiayu Yi @@ -1298,10 +1354,12 @@ Jingcheng Zhang Jingguo Yao Jingnan Si Jinkun Zhang +Jinwen Wo Jiong Du Jirka Daněk Jiulong Wang Joakim Sernbrant +Jochen Weber Joe Bowbeer Joe Cortopassi Joe Farrell @@ -1324,6 +1382,7 @@ Johan Euphrosine Johan Jansson Johan Knutzen Johan Sageryd +Johannes Altmanninger Johannes Huning John Asmuth John Bampton @@ -1338,10 +1397,12 @@ John Howard Palevich John Jago John Jeffery John Jenkins +John Kelly John Leidegren John McCabe John Moore John Newlin +John Olheiser John Papandriopoulos John Potocny John R. Lenton @@ -1382,6 +1443,7 @@ Jordan Rupprecht Jordi Martin Jorge Araya Jorge L. Fatta +Jorge Troncoso Jos Visser Josa Gesell Jose Luis Vázquez González @@ -1508,6 +1570,7 @@ Keyuan Li Kezhu Wang Khosrow Moossavi Kieran Colford +Kieran Gorman Kim Shrier Kim Yongbin Kir Kolyshkin @@ -1577,6 +1640,7 @@ Leonel Quinteros Lev Shamardin Lewin Bormann Lewis Waddicor +Li-Yu Yu Liam Haworth Lily Chung Lingchao Xin @@ -1657,7 +1721,9 @@ Mark Adams Mark Bucciarelli Mark Dain Mark Glines +Mark Hansen Mark Harrison +Mark Jeffery Mark Percival Mark Pulford Mark Rushakoff @@ -1686,7 +1752,7 @@ Martin Hoefling Martin Kreichgauer Martin Kunc Martin Lindhe -Martin Möhrmann +Martin Möhrmann Martin Neubauer Martin Olsen Martin Olsson @@ -1741,6 +1807,7 @@ Matthew Denton Matthew Holt Matthew Horsnell Matthew Waters +Matthias Dötsch Matthias Frei Matthieu Hauglustaine Matthieu Olivier @@ -1814,6 +1881,7 @@ Michal Bohuslávek Michal Cierniak Michał Derkacz Michal Franc +Michal Hruby Michał Łowicki Michal Pristas Michal Rostecki @@ -1844,6 +1912,7 @@ Mike Solomon Mike Strosaker Mike Tsao Mike Wiacek +Mikhail Faraponov <11322032+moredure@users.noreply.github.com> Mikhail Fesenko Mikhail Gusarov Mikhail Panchenko @@ -1870,6 +1939,7 @@ Moritz Fain Moriyoshi Koizumi Morten Siebuhr Môshe van der Sterre +Mostafa Solati Mostyn Bramley-Moore Mrunal Patel Muhammad Falak R Wani @@ -1927,6 +1997,7 @@ Nick Miyake Nick Patavalis Nick Petroni Nick Robinson +Nick Sherron Nick Smolin Nicolas BRULEZ Nicolas Kaiser @@ -1956,6 +2027,7 @@ Noah Santschi-Cooney Noble Johnson Nodir Turakulov Noel Georgi +Nooras Saba Norberto Lopes Norman B. Lancaster Nuno Cruces @@ -1973,6 +2045,7 @@ Oliver Tan Oliver Tonnhofer Olivier Antoine Olivier Duperray +Olivier Mengué Olivier Poitrey Olivier Saingre Olivier Wulveryck @@ -1982,6 +2055,7 @@ Ori Bernstein Ori Rawlings Oryan Moshe Osamu TONOMORI +Oscar Söderlund Özgür Kesim Pablo Caderno Pablo Lalloni @@ -2014,6 +2088,7 @@ Patrick Pelletier Patrick Riley Patrick Smith Patrik Lundin +Patrik Nyblom Paul A Querna Paul Borman Paul Boyd @@ -2042,6 +2117,7 @@ Paul Wankadia Paulo Casaretto Paulo Flabiano Smorigo Paulo Gomes +Pavel Kositsyn Pavel Paulau Pavel Watson Pavel Zinovkin @@ -2049,6 +2125,7 @@ Pavlo Sumkin Pawel Knap Pawel Szczur Paweł Szulik +Pedro Lopez Mareque Pei Xian Chee Pei-Ming Wu Pen Tree @@ -2164,6 +2241,7 @@ Rhys Hiltner Ricardo Padilha Ricardo Pchevuzinske Katz Ricardo Seriani +Rich Hong Richard Barnes Richard Crowley Richard Dingwall @@ -2179,6 +2257,7 @@ Rick Hudson Rick Sayre Rijnard van Tonder Riku Voipio +Riley Avron Risto Jaakko Saarelma Rob Earhart Rob Findley @@ -2186,8 +2265,10 @@ Rob Norman Rob Phoenix Rob Pike Robert Ayrapetyan +Robert Burke Robert Daniel Kortschak Robert Dinu +Robert Engels Robert Figueiredo Robert Griesemer Robert Hencke @@ -2212,6 +2293,7 @@ Roger Peppe Rohan Challa Rohan Verma Rohith Ravi +Roi Martin Roland Illig Roland Shoemaker Romain Baugue @@ -2242,6 +2324,7 @@ Ryan Canty Ryan Dahl Ryan Hitchman Ryan Kohler +Ryan Leung Ryan Lower Ryan Roden-Corrent Ryan Seys @@ -2275,6 +2358,7 @@ Sami Pönkänen Samuel Kelemen Samuel Tan Samuele Pedroni +San Ye Sander van Harmelen Sanjay Menakuru Santhosh Kumar Tekuri @@ -2339,6 +2423,7 @@ Shaba Abhiram Shahar Kohanim Shailesh Suryawanshi Shamil Garatuev +Shamim Akhtar Shane Hansen Shang Jian Ding Shaozhen Ding @@ -2375,6 +2460,7 @@ Simon Drake Simon Ferquel Simon Frei Simon Jefford +Simon Law Simon Rawet Simon Rozman Simon Ser @@ -2440,6 +2526,7 @@ Suharsh Sivakumar Sukrit Handa Sunny Suriyaa Sundararuban +Suvaditya Sur Suyash Suzy Mueller Sven Almgren @@ -2502,6 +2589,7 @@ Thomas Symborski Thomas Wanielista Thorben Krueger Thordur Bjornsson +Tiago Peczenyj Tiago Queiroz Tianji Wu Tianon Gravi @@ -2636,6 +2724,7 @@ Vladimir Varankin Vojtech Bocek Volker Dobler Volodymyr Paprotski +Vyacheslav Pachkov W. Trevor King Wade Simmons Wagner Riffel @@ -2653,6 +2742,7 @@ Wei Guangjing Wei Xiao Wei Xikai Weichao Tang +Weilu Jia Weixie Cui <523516579@qq.com> Wembley G. Leach, Jr Wenlei (Frank) He @@ -2722,9 +2812,11 @@ Yuichi Nishiwaki Yuji Yaginuma Yuki Ito Yuki OKUSHI +Yuki Osaki Yuki Yugui Sonoda Yukihiro Nishinaka <6elpinal@gmail.com> YunQiang Su +Yuntao Wang Yury Smolsky Yusuke Kagiwada Yuusei Kuwana @@ -2736,7 +2828,9 @@ Zach Gershman Zach Hoffman Zach Jones Zachary Amsden +Zachary Burkett Zachary Gershman +Zaiyang Li Zak Zakatell Kanda Zellyn Hunter @@ -2745,6 +2839,7 @@ Zhang Boyang Zheng Dayu Zheng Xu Zhengyu He +Zhi Zheng Zhongpeng Lin Zhongtao Chen Zhongwei Yao From 0907d57abf34e1d11debef2ea7bb4d7b2c11f51e Mon Sep 17 00:00:00 2001 From: Keith Randall Date: Fri, 25 Feb 2022 16:06:53 -0800 Subject: [PATCH 36/44] cmd/compile: emit types of constants which are instantiated generic types Normally types of constants are emitted when the type is defined (an ODCLTYPE). However, the types of constants where the type is an instantiated generic type made inside the constant declaration, do not normally get emitted. But the DWARF processor in the linker wants to see those types. So we emit them during stenciling. Fixes #51245 Change-Id: I59f20f1d7b91501c9ac760cf839a354356331fc6 Reviewed-on: https://go-review.googlesource.com/c/go/+/388117 Trust: Keith Randall Run-TryBot: Keith Randall TryBot-Result: Gopher Robot Reviewed-by: Cherry Mui --- src/cmd/compile/internal/gc/obj.go | 4 ++++ test/typeparam/issue51245.go | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 test/typeparam/issue51245.go diff --git a/src/cmd/compile/internal/gc/obj.go b/src/cmd/compile/internal/gc/obj.go index 5353435ed1..74e4c0a890 100644 --- a/src/cmd/compile/internal/gc/obj.go +++ b/src/cmd/compile/internal/gc/obj.go @@ -217,6 +217,10 @@ func dumpGlobalConst(n ir.Node) { if ir.ConstOverflow(v, t) { return } + } else { + // If the type of the constant is an instantiated generic, we need to emit + // that type so the linker knows about it. See issue 51245. + _ = reflectdata.TypeLinksym(t) } base.Ctxt.DwarfIntConst(base.Ctxt.Pkgpath, n.Sym().Name, types.TypeSymName(t), ir.IntVal(t, v)) } diff --git a/test/typeparam/issue51245.go b/test/typeparam/issue51245.go new file mode 100644 index 0000000000..bd4f7c5dc9 --- /dev/null +++ b/test/typeparam/issue51245.go @@ -0,0 +1,16 @@ +// build -gcflags=-G=3 + +// 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 T[P any] int +const C T[int] = 3 + +type T2 int +const C2 T2 = 9 + +func main() { +} From 06a43e4ab62bc5f8353e1c6ed5267d51ce2b483c Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Fri, 25 Feb 2022 14:56:04 -0800 Subject: [PATCH 37/44] cmd/compile: fix case for structural types where we should be looking at typeparams In getInstantiation, we were not computing tparams correctly for the case where the receiver of a method was a fully-instantiated type. This wasn't affecting later parts of the function, since method instantiations of fully-instantiated types were already being calculated in an earlier path. But it did give us a non-typeparam when trying to see if a shape was associated with a type param with a structural type. The fix is just to get the typeparams associated with the base generic type. Then we can eliminate a conditional check later in the code. The tparam parameter of Shapify should always be non-nil Fixes #51367 Change-Id: I6f95fe603886148b2dad0c581416c51373c85009 Reviewed-on: https://go-review.googlesource.com/c/go/+/388116 Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Gopher Robot Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/stencil.go | 13 ++++++++----- src/cmd/compile/internal/typecheck/subr.go | 6 +++--- test/typeparam/issue51367.dir/a.go | 14 ++++++++++++++ test/typeparam/issue51367.dir/main.go | 13 +++++++++++++ test/typeparam/issue51367.go | 7 +++++++ 5 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 test/typeparam/issue51367.dir/a.go create mode 100644 test/typeparam/issue51367.dir/main.go create mode 100644 test/typeparam/issue51367.go diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 807794dc30..9d17d5ffd1 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -641,6 +641,11 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe // over any pointer) recvType := nameNode.Type().Recv().Type recvType = deref(recvType) + if recvType.IsFullyInstantiated() { + // Get the type of the base generic type, so we get + // its original typeparams. + recvType = recvType.OrigSym().Def.(*ir.Name).Type() + } tparams = recvType.RParams() } else { fields := nameNode.Type().TParams().Fields().Slice() @@ -657,11 +662,9 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe s1 := make([]*types.Type, len(shapes)) for i, t := range shapes { var tparam *types.Type - if tparams[i].Kind() == types.TTYPEPARAM { - // Shapes are grouped differently for structural types, so we - // pass the type param to Shapify(), so we can distinguish. - tparam = tparams[i] - } + // Shapes are grouped differently for structural types, so we + // pass the type param to Shapify(), so we can distinguish. + tparam = tparams[i] if !t.IsShape() { s1[i] = typecheck.Shapify(t, i, tparam) } else { diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 9892471142..181066ba96 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1432,9 +1432,9 @@ func genericTypeName(sym *types.Sym) string { // For now, we only consider two types to have the same shape, if they have exactly // the same underlying type or they are both pointer types. // -// tparam is the associated typeparam. If there is a structural type for -// the associated type param (not common), then a pointer type t is mapped to its -// underlying type, rather than being merged with other pointers. +// tparam is the associated typeparam - it must be TTYPEPARAM type. If there is a +// structural type for the associated type param (not common), then a pointer type t +// is mapped to its underlying type, rather than being merged with other pointers. // // Shape types are also distinguished by the index of the type in a type param/arg // list. We need to do this so we can distinguish and substitute properly for two diff --git a/test/typeparam/issue51367.dir/a.go b/test/typeparam/issue51367.dir/a.go new file mode 100644 index 0000000000..be0c3b0688 --- /dev/null +++ b/test/typeparam/issue51367.dir/a.go @@ -0,0 +1,14 @@ +// 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 A[T any] struct{} + +func (_ A[T]) Method() {} + +func DoSomething[P any]() { + a := A[*byte]{} + a.Method() +} diff --git a/test/typeparam/issue51367.dir/main.go b/test/typeparam/issue51367.dir/main.go new file mode 100644 index 0000000000..64273d313b --- /dev/null +++ b/test/typeparam/issue51367.dir/main.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. + +package main + +import ( + "a" +) + +func main() { + a.DoSomething[byte]() +} diff --git a/test/typeparam/issue51367.go b/test/typeparam/issue51367.go new file mode 100644 index 0000000000..642f4bf49f --- /dev/null +++ b/test/typeparam/issue51367.go @@ -0,0 +1,7 @@ +// rundir -G=3 + +// 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 57e3809884dd695d484acaefba8ded720c5a02c1 Mon Sep 17 00:00:00 2001 From: Cherry Mui Date: Fri, 18 Feb 2022 13:09:54 -0500 Subject: [PATCH 38/44] runtime: avoid cgo_unsafe_args for syscall.syscall functions on darwin/arm64 Currently, syscall.syscall-like functions are defined as cgo_unsafe_args, which makes them ABI0, as it takes the address of the argument area based on ABI0 layout. Those functions are linkname'd to the syscall package. When compiling the syscall package, the compiler doesn't know they are ABI0 therefore generate an ABIInternal call, which will use the wrapper. As some of the functions (e.g. syscall6) has many arguments, the wrapper would take a good amount of stack space. And those functions must be nosplit. This causes nosplit overflow when building with -N -l and -race. Avoid that by rewriting the functions to not use cgo_unsafe_args. Instead, make a struct locally and pass the address of that struct. This way the functions are ABIInternal and the call will not use the wrapper. Fixes #51247. Change-Id: I76c1ab86b9d28664fa7d5b9c7928fbb2fd8d1417 Reviewed-on: https://go-review.googlesource.com/c/go/+/386719 Trust: Cherry Mui Run-TryBot: Cherry Mui TryBot-Result: Gopher Robot Reviewed-by: Michael Knyszek --- src/runtime/sys_darwin.go | 52 +++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go index 7573d0f9b3..58b3a9171c 100644 --- a/src/runtime/sys_darwin.go +++ b/src/runtime/sys_darwin.go @@ -17,85 +17,89 @@ import ( //go:linkname syscall_syscall syscall.syscall //go:nosplit -//go:cgo_unsafe_args func syscall_syscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { + args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err} entersyscall() - libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args)) exitsyscall() - return + return args.r1, args.r2, args.err } func syscall() //go:linkname syscall_syscallX syscall.syscallX //go:nosplit -//go:cgo_unsafe_args func syscall_syscallX(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { + args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err} entersyscall() - libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallX)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallX)), unsafe.Pointer(&args)) exitsyscall() - return + return args.r1, args.r2, args.err } func syscallX() //go:linkname syscall_syscall6 syscall.syscall6 //go:nosplit -//go:cgo_unsafe_args func syscall_syscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { + args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err} entersyscall() - libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args)) exitsyscall() - return + return args.r1, args.r2, args.err } func syscall6() //go:linkname syscall_syscall6X syscall.syscall6X //go:nosplit -//go:cgo_unsafe_args func syscall_syscall6X(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { + args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err} entersyscall() - libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6X)), unsafe.Pointer(&args)) exitsyscall() - return + return args.r1, args.r2, args.err } func syscall6X() //go:linkname syscall_syscallPtr syscall.syscallPtr //go:nosplit -//go:cgo_unsafe_args func syscall_syscallPtr(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { + args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err} entersyscall() - libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallPtr)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscallPtr)), unsafe.Pointer(&args)) exitsyscall() - return + return args.r1, args.r2, args.err } func syscallPtr() //go:linkname syscall_rawSyscall syscall.rawSyscall //go:nosplit -//go:cgo_unsafe_args func syscall_rawSyscall(fn, a1, a2, a3 uintptr) (r1, r2, err uintptr) { - libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&fn)) - return + args := struct{ fn, a1, a2, a3, r1, r2, err uintptr }{fn, a1, a2, a3, r1, r2, err} + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall)), unsafe.Pointer(&args)) + return args.r1, args.r2, args.err } //go:linkname syscall_rawSyscall6 syscall.rawSyscall6 //go:nosplit -//go:cgo_unsafe_args func syscall_rawSyscall6(fn, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2, err uintptr) { - libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&fn)) - return + args := struct{ fn, a1, a2, a3, a4, a5, a6, r1, r2, err uintptr }{fn, a1, a2, a3, a4, a5, a6, r1, r2, err} + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall6)), unsafe.Pointer(&args)) + return args.r1, args.r2, args.err } // syscallNoErr is used in crypto/x509 to call into Security.framework and CF. //go:linkname crypto_x509_syscall crypto/x509/internal/macos.syscall //go:nosplit -//go:cgo_unsafe_args func crypto_x509_syscall(fn, a1, a2, a3, a4, a5 uintptr, f1 float64) (r1 uintptr) { + args := struct { + fn, a1, a2, a3, a4, a5 uintptr + f1 float64 + r1 uintptr + }{fn, a1, a2, a3, a4, a5, f1, r1} entersyscall() - libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall_x509)), unsafe.Pointer(&fn)) + libcCall(unsafe.Pointer(abi.FuncPCABI0(syscall_x509)), unsafe.Pointer(&args)) exitsyscall() - return + return args.r1 } func syscall_x509() From b33592dcfd2c8cf1e574531ecb49af7755864e82 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Sat, 26 Feb 2022 21:08:52 -0800 Subject: [PATCH 39/44] spec: the -'s possessive suffix is English, not code Change-Id: I2debcf926ef116c632c7366646d37de8686b7c9e Reviewed-on: https://go-review.googlesource.com/c/go/+/388174 Reviewed-by: Robert Griesemer Trust: Matthew Dempsky --- doc/go_spec.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/doc/go_spec.html b/doc/go_spec.html index bf8b5ed5bf..6c6f982854 100644 --- a/doc/go_spec.html +++ b/doc/go_spec.html @@ -1,6 +1,6 @@ @@ -2008,7 +2008,7 @@ by a value of type T.

    -Additionally, if x's type V or T are type parameters +Additionally, if x's type V or T are type parameters with specific types, x is assignable to a variable of type T if one of the following conditions applies:

    @@ -7414,7 +7414,7 @@ an explicit call to panic or a run-time terminates the execution of F. Any functions deferred by F are then executed as usual. -Next, any deferred functions run by F's caller are run, +Next, any deferred functions run by F's caller are run, and so on up to any deferred by the top-level function in the executing goroutine. At that point, the program is terminated and the error condition is reported, including the value of the argument to panic. From eb8198d2f67477517e7a735faa49dfd7c0fb3622 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Tue, 22 Feb 2022 21:41:43 -0800 Subject: [PATCH 40/44] cmd/compile: deal with constructed types that have shapes in them We convert type args to shape types inside instantiations. If an instantiation constructs a compound type based on that shape type and uses that as a type arg to another generic function being called, then we have a type arg with a shape type embedded inside of it. In that case, we need to substitute out those embedded shape types with their underlying type. If we don't do this, we may create extra unneeded shape types that have these other shape types embedded in them. This may lead to generating extra shape instantiations, and a mismatch between the instantiations that we used in generating dictionaries and the instantations that are actually called. Updates #51303 Change-Id: Ieef894a5fac176cfd1415f95926086277ad09759 Reviewed-on: https://go-review.googlesource.com/c/go/+/387674 Reviewed-by: Keith Randall Trust: Dan Scales Run-TryBot: Dan Scales TryBot-Result: Gopher Robot --- src/cmd/compile/internal/typecheck/subr.go | 86 ++++++++++++++++++++++ test/typeparam/issue51303.go | 65 ++++++++++++++++ test/typeparam/issue51303.out | 4 + 3 files changed, 155 insertions(+) create mode 100644 test/typeparam/issue51303.go create mode 100644 test/typeparam/issue51303.out diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 181066ba96..5147ebbd2c 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1424,6 +1424,68 @@ func genericTypeName(sym *types.Sym) string { return sym.Name[0:strings.Index(sym.Name, "[")] } +// getShapes appends the list of the shape types that are used within type t to +// listp. The type traversal is simplified for two reasons: (1) we can always stop a +// type traversal when t.HasShape() is false; and (2) shape types can't appear inside +// a named type, except for the type args of a generic type. So, the traversal will +// always stop before we have to deal with recursive types. +func getShapes(t *types.Type, listp *[]*types.Type) { + if !t.HasShape() { + return + } + if t.IsShape() { + *listp = append(*listp, t) + return + } + + if t.Sym() != nil { + // A named type can't have shapes in it, except for type args of a + // generic type. We will have to deal with this differently once we + // alloc local types in generic functions (#47631). + for _, rparam := range t.RParams() { + getShapes(rparam, listp) + } + return + } + + switch t.Kind() { + case types.TARRAY, types.TPTR, types.TSLICE, types.TCHAN: + getShapes(t.Elem(), listp) + + case types.TSTRUCT: + for _, f := range t.FieldSlice() { + getShapes(f.Type, listp) + } + + case types.TFUNC: + for _, f := range t.Recvs().FieldSlice() { + getShapes(f.Type, listp) + } + for _, f := range t.Params().FieldSlice() { + getShapes(f.Type, listp) + } + for _, f := range t.Results().FieldSlice() { + getShapes(f.Type, listp) + } + for _, f := range t.TParams().FieldSlice() { + getShapes(f.Type, listp) + } + + case types.TINTER: + for _, f := range t.Methods().Slice() { + getShapes(f.Type, listp) + } + + case types.TMAP: + getShapes(t.Key(), listp) + getShapes(t.Elem(), listp) + + default: + panic(fmt.Sprintf("Bad type in getShapes: %v", t.Kind())) + } + +} + // Shapify takes a concrete type and a type param index, and returns a GCshape type that can // be used in place of the input type and still generate identical code. // No methods are added - all methods calls directly on a shape should @@ -1442,6 +1504,30 @@ func genericTypeName(sym *types.Sym) string { // instantiation. func Shapify(t *types.Type, index int, tparam *types.Type) *types.Type { assert(!t.IsShape()) + if t.HasShape() { + // We are sometimes dealing with types from a shape instantiation + // that were constructed from existing shape types, so t may + // sometimes have shape types inside it. In that case, we find all + // those shape types with getShapes() and replace them with their + // underlying type. + // + // If we don't do this, we may create extra unneeded shape types that + // have these other shape types embedded in them. This may lead to + // generating extra shape instantiations, and a mismatch between the + // instantiations that we used in generating dictionaries and the + // instantations that are actually called. (#51303). + list := []*types.Type{} + getShapes(t, &list) + list2 := make([]*types.Type, len(list)) + for i, shape := range list { + list2[i] = shape.Underlying() + } + ts := Tsubster{ + Tparams: list, + Targs: list2, + } + t = ts.Typ(t) + } // Map all types with the same underlying type to the same shape. u := t.Underlying() diff --git a/test/typeparam/issue51303.go b/test/typeparam/issue51303.go new file mode 100644 index 0000000000..5f4bdc0634 --- /dev/null +++ b/test/typeparam/issue51303.go @@ -0,0 +1,65 @@ +// run -gcflags=-G=3 + +// 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 + +import ( + "fmt" +) + +func main() { + x := [][]int{{1}} + y := [][]int{{2, 3}} + IntersectSS(x, y) +} + +type list[E any] interface { + ~[]E + Equal(x, y E) bool +} + +// ss is a set of sets +type ss[E comparable, T []E] []T + +func (ss[E, T]) Equal(a, b T) bool { + return SetEq(a, b) +} + +func IntersectSS[E comparable](x, y [][]E) [][]E { + return IntersectT[[]E, ss[E, []E]](ss[E, []E](x), ss[E, []E](y)) +} + +func IntersectT[E any, L list[E]](x, y L) L { + var z L +outer: + for _, xe := range x { + fmt.Println("xe", xe) + for _, ye := range y { + fmt.Println("ye", ye) + fmt.Println("x", x) + if x.Equal(xe, ye) { + fmt.Println("appending") + z = append(z, xe) + continue outer + } + } + } + return z +} + +func SetEq[S []E, E comparable](x, y S) bool { + fmt.Println("SetEq", x, y) +outer: + for _, xe := range x { + for _, ye := range y { + if xe == ye { + continue outer + } + } + return false // xs wasn't found in y + } + return true +} diff --git a/test/typeparam/issue51303.out b/test/typeparam/issue51303.out new file mode 100644 index 0000000000..34b3be32dd --- /dev/null +++ b/test/typeparam/issue51303.out @@ -0,0 +1,4 @@ +xe [1] +ye [2 3] +x [[1]] +SetEq [1] [2 3] From f9285818b6890b896f43a38449e35744d97c817a Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Sun, 27 Feb 2022 18:13:23 -0800 Subject: [PATCH 41/44] go/types, types2: fix string to type parameter conversions Converting an untyped constant to a type parameter results in a non-constant value; but the constant must still be representable by all specific types of the type parameter. Adjust the special handling for constant-to-type parameter conversions to also include string-to-[]byte and []rune conversions, which are handled separately for conversions to types that are not type parameters because those are not constant conversions in non-generic code. Fixes #51386. Change-Id: I15e5a0fd281efd15af387280cd3dee320a1ac5e1 Reviewed-on: https://go-review.googlesource.com/c/go/+/388254 Trust: Robert Griesemer Reviewed-by: Robert Findley --- src/cmd/compile/internal/types2/conversions.go | 5 ++++- .../types2/testdata/fixedbugs/issue51386.go2 | 17 +++++++++++++++++ src/go/types/conversions.go | 5 ++++- src/go/types/testdata/fixedbugs/issue51386.go2 | 17 +++++++++++++++++ 4 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2 create mode 100644 src/go/types/testdata/fixedbugs/issue51386.go2 diff --git a/src/cmd/compile/internal/types2/conversions.go b/src/cmd/compile/internal/types2/conversions.go index 7fe1d5056b..08b3cbff29 100644 --- a/src/cmd/compile/internal/types2/conversions.go +++ b/src/cmd/compile/internal/types2/conversions.go @@ -49,11 +49,14 @@ func (check *Checker) conversion(x *operand, T Type) { // have specific types, constant x cannot be // converted. ok = T.(*TypeParam).underIs(func(u Type) bool { - // t is nil if there are no specific type terms + // u is nil if there are no specific type terms if u == nil { cause = check.sprintf("%s does not contain specific types", T) return false } + if isString(x.typ) && isBytesOrRunes(u) { + return true + } if !constConvertibleTo(u, nil) { cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T) return false diff --git a/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2 b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2 new file mode 100644 index 0000000000..ef6223927a --- /dev/null +++ b/src/cmd/compile/internal/types2/testdata/fixedbugs/issue51386.go2 @@ -0,0 +1,17 @@ +// 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 + +type myString string + +func _[P ~string | ~[]byte | ~[]rune]() { + _ = P("") + const s myString = "" + _ = P(s) +} + +func _[P myString]() { + _ = P("") +} diff --git a/src/go/types/conversions.go b/src/go/types/conversions.go index 84741359c0..c5a69cddf4 100644 --- a/src/go/types/conversions.go +++ b/src/go/types/conversions.go @@ -48,11 +48,14 @@ func (check *Checker) conversion(x *operand, T Type) { // have specific types, constant x cannot be // converted. ok = T.(*TypeParam).underIs(func(u Type) bool { - // t is nil if there are no specific type terms + // u is nil if there are no specific type terms if u == nil { cause = check.sprintf("%s does not contain specific types", T) return false } + if isString(x.typ) && isBytesOrRunes(u) { + return true + } if !constConvertibleTo(u, nil) { cause = check.sprintf("cannot convert %s to %s (in %s)", x, u, T) return false diff --git a/src/go/types/testdata/fixedbugs/issue51386.go2 b/src/go/types/testdata/fixedbugs/issue51386.go2 new file mode 100644 index 0000000000..ef6223927a --- /dev/null +++ b/src/go/types/testdata/fixedbugs/issue51386.go2 @@ -0,0 +1,17 @@ +// 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 + +type myString string + +func _[P ~string | ~[]byte | ~[]rune]() { + _ = P("") + const s myString = "" + _ = P(s) +} + +func _[P myString]() { + _ = P("") +} From 9fe3676bc7de9f648c2e3ce6d4f1aa395b92cefd Mon Sep 17 00:00:00 2001 From: cuishuang Date: Mon, 28 Feb 2022 12:17:25 +0000 Subject: [PATCH 42/44] all: fix typos Change-Id: I93ff3d33a5db130dd57a9545456f2961fc3f668b GitHub-Last-Rev: f95fafc04937a99f82cb992aabb7bac602033d8e GitHub-Pull-Request: golang/go#51394 Reviewed-on: https://go-review.googlesource.com/c/go/+/388314 Run-TryBot: Ian Lance Taylor TryBot-Result: Gopher Robot Reviewed-by: Ian Lance Taylor Reviewed-by: Robert Griesemer --- doc/go1.18.html | 2 +- misc/cgo/testsanitizers/asan_test.go | 2 +- src/cmd/compile/internal/types/fmt.go | 2 +- src/cmd/compile/internal/types2/validtype.go | 2 +- src/go/types/validtype.go | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/go1.18.html b/doc/go1.18.html index 21089ef4b3..b320579c37 100644 --- a/doc/go1.18.html +++ b/doc/go1.18.html @@ -137,7 +137,7 @@ Do not send CLs removing the interior tags from such phrases.
  • The Go compiler currently only supports calling a method m on a value - x of type parameter type P if m is explictly + x of type parameter type P if m is explicitly declared by P's constraint interface. Similarly, method values x.m and method expressions P.m also are only supported if m is explicitly diff --git a/misc/cgo/testsanitizers/asan_test.go b/misc/cgo/testsanitizers/asan_test.go index 1b70bce3d1..22dcf23c3b 100644 --- a/misc/cgo/testsanitizers/asan_test.go +++ b/misc/cgo/testsanitizers/asan_test.go @@ -63,7 +63,7 @@ func TestASAN(t *testing.T) { // sanitizer library needs a // symbolizer program and can't find it. const noSymbolizer = "external symbolizer" - // Check if -asan option can correctly print where the error occured. + // Check if -asan option can correctly print where the error occurred. if tc.errorLocation != "" && !strings.Contains(out, tc.errorLocation) && !strings.Contains(out, noSymbolizer) && diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index e1b395559a..09814ac46d 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -657,7 +657,7 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty // Compute tsym, the symbol that would normally be used as // the field name when embedding f.Type. - // TODO(mdempsky): Check for other occurences of this logic + // TODO(mdempsky): Check for other occurrences of this logic // and deduplicate. typ := f.Type if typ.IsPtr() { diff --git a/src/cmd/compile/internal/types2/validtype.go b/src/cmd/compile/internal/types2/validtype.go index c508eadc7c..f365ad1e27 100644 --- a/src/cmd/compile/internal/types2/validtype.go +++ b/src/cmd/compile/internal/types2/validtype.go @@ -79,7 +79,7 @@ func (check *Checker) validType0(typ Type, env *tparamEnv, path []Object) typeIn // would have reported a type cycle and couldn't have been // imported in the first place. assert(t.obj.pkg == check.pkg) - t.underlying = Typ[Invalid] // t is in the current package (no race possibilty) + t.underlying = Typ[Invalid] // t is in the current package (no race possibility) // Find the starting point of the cycle and report it. for i, tn := range path { if tn == t.obj { diff --git a/src/go/types/validtype.go b/src/go/types/validtype.go index c4ec2f2e0a..7d7029bce2 100644 --- a/src/go/types/validtype.go +++ b/src/go/types/validtype.go @@ -79,7 +79,7 @@ func (check *Checker) validType0(typ Type, env *tparamEnv, path []Object) typeIn // would have reported a type cycle and couldn't have been // imported in the first place. assert(t.obj.pkg == check.pkg) - t.underlying = Typ[Invalid] // t is in the current package (no race possibilty) + t.underlying = Typ[Invalid] // t is in the current package (no race possibility) // Find the starting point of the cycle and report it. for i, tn := range path { if tn == t.obj { From f04d5c118c2ccd058a3fb81586f92c8b29b373ae Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Mon, 28 Feb 2022 14:34:11 +0100 Subject: [PATCH 43/44] cmd/internal/obj/riscv/testdata/testbranch: add //go:build lines Change-Id: I95ea33c0aad7d427da99c0ea7d0869f10ed5dd71 Reviewed-on: https://go-review.googlesource.com/c/go/+/388334 Trust: Tobias Klauser Run-TryBot: Tobias Klauser TryBot-Result: Gopher Robot Reviewed-by: Matt Layher Reviewed-by: Ian Lance Taylor --- src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go | 1 + src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s | 1 + 2 files changed, 2 insertions(+) diff --git a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go index 68d9589bf2..843398d3b0 100644 --- a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go +++ b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.go @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build riscv64 // +build riscv64 package testbranch diff --git a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s index cce296feb5..d7141e38c1 100644 --- a/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s +++ b/src/cmd/internal/obj/riscv/testdata/testbranch/branch_test.s @@ -2,6 +2,7 @@ // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. +//go:build riscv64 // +build riscv64 #include "textflag.h" From acc5f55bac6884f8b27c5b73c4a15d777a7169a0 Mon Sep 17 00:00:00 2001 From: Michael Matloob Date: Mon, 28 Feb 2022 16:39:28 -0500 Subject: [PATCH 44/44] cmd/go: make work and work_edit script tests version-independent The work and work_edit script tests ran go work init, which put the current Go version into the go.work files. Before this change, the tests used cmp to compare the outputs with a file that contained a literal "go 1.18" line. Instead, use cmpenv so we can compare with "go $goversion". (Some of the test cases still compare against files that contain "go 1.18" lines, but these tests explicitly set the version to go 1.18 either in the original go.work files or using go work edit.) Change-Id: Iea2caa7697b5fe5939070558b1664f70130095ce Reviewed-on: https://go-review.googlesource.com/c/go/+/388514 Trust: Michael Matloob Run-TryBot: Michael Matloob Reviewed-by: Bryan Mills TryBot-Result: Gopher Robot Reviewed-by: Carlos Amedee --- src/cmd/go/testdata/script/work.txt | 4 ++-- src/cmd/go/testdata/script/work_edit.txt | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/cmd/go/testdata/script/work.txt b/src/cmd/go/testdata/script/work.txt index a10bf5a1c3..fa1558f9e6 100644 --- a/src/cmd/go/testdata/script/work.txt +++ b/src/cmd/go/testdata/script/work.txt @@ -4,7 +4,7 @@ go env GOWORK ! stdout . go work init ./a ./b -cmp go.work go.work.want +cmpenv go.work go.work.want go env GOWORK stdout '^'$WORK'(\\|/)gopath(\\|/)src(\\|/)go.work$' @@ -69,7 +69,7 @@ use ( ../src/a ) -- go.work.want -- -go 1.18 +go $goversion use ( ./a diff --git a/src/cmd/go/testdata/script/work_edit.txt b/src/cmd/go/testdata/script/work_edit.txt index 71959ca0dd..278afb7f61 100644 --- a/src/cmd/go/testdata/script/work_edit.txt +++ b/src/cmd/go/testdata/script/work_edit.txt @@ -1,10 +1,10 @@ # Test editing go.work files. go work init m -cmp go.work go.work.want_initial +cmpenv go.work go.work.want_initial go work edit -use n -cmp go.work go.work.want_use_n +cmpenv go.work go.work.want_use_n go work edit -go 1.18 cmp go.work go.work.want_go_118 @@ -39,11 +39,11 @@ module m go 1.18 -- go.work.want_initial -- -go 1.18 +go $goversion use ./m -- go.work.want_use_n -- -go 1.18 +go $goversion use ( ./m