Compare commits

...

60 Commits

Author SHA1 Message Date
Dmitri Shuralyov
0b0d2fe66d [release-branch.go1.18] go1.18.1
Change-Id: If2b91acf7fb4a55cded985d6f2a2ab058c1b7bd3
Reviewed-on: https://go-review.googlesource.com/c/go/+/399818
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2022-04-12 15:40:19 +00:00
Julie Qiu
84264fceca [release-branch.go1.18] encoding/pem: fix stack overflow in Decode
Previously, Decode called decodeError, a recursive function that was
prone to stack overflows when given a large PEM file containing errors.

Credit to Juho Nurminen of Mattermost who reported the error.

Fixes CVE-2022-24675
Updates #51853
Fixes #52037

Change-Id: Iffe768be53c8ddc0036fea0671d290f8f797692c
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1391157
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Filippo Valsorda <valsorda@google.com>
(cherry picked from commit 794ea5e828010e8b68493b2fc6d2963263195a02)
Reviewed-on: https://go-review.googlesource.com/c/go/+/399817
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-04-12 14:45:32 +00:00
Robert Findley
9535031e32 [release-branch.go1.18] go/types: don't report errors for untyped int shifts on Go < 1.13
CL 337529 introduced upfront type-checking of constant shift operands,
to avoid converting their type to uint (per the spec). However, it
had an oversight in that the checks intended for non-constant operands
still ran after the explicit checking of constant operands. As a
result, there are at least two bugs:
 - When GoVersion is < 1.13, we report spurious errors for untyped
   constant shift operands.
 - When the operand is an untyped float constant, we still convert to
   uint (this was a known bug reported in #47410).

Looking at this now, it seems clear that we can avoid both of these bugs
by simply not running the additional checks in the case of a constant
operand. However, this should be considered with some care, as shifts
are notoriously tricky.

While cherry-picking, the new test file is updated to use the go1_12
package name, following our convention for specifying language version
in the release branch.

Fixes #52032

Change-Id: Ia489cc5470b92a8187d3de0423d05b309daf47bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/396775
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 8a816d5efc)
Reviewed-on: https://go-review.googlesource.com/c/go/+/397680
2022-04-06 17:10:45 +00:00
Robert Griesemer
2097b2d51b [release-branch.go1.18] go/types, types2: fix overlap test for union termlist
Per the spec, "the type sets of all non-interface terms must be
pairwise disjoint (the pairwise intersection of the type sets must
be empty)" in a union.

For the overlap test, the existing implementation casually mixed
syntactic union terms (which may have interface type) with type set
terms (which are normalized/expanded and must not have interface
type). As a consequence, in some cases the overlap test failed.

This change skips terms with interface types in the overlap test.

For this cherry-pick, also rename the files ending in issue51607.go
to issue51607.go2 because the 1.18 branch requires tests containing
generic features to end in .go2.

Fixes #52119.

Change-Id: I8ae9953db31f0a0428389c6a45a6696aa2450219
Reviewed-on: https://go-review.googlesource.com/c/go/+/397695
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/398154
2022-04-06 16:37:43 +00:00
Filippo Valsorda
c9b9a010eb [release-branch.go1.18] crypto/elliptic: tolerate zero-padded scalars in generic P-256
Updates #52075
Fixes #52077
Fixes CVE-2022-28327

Change-Id: I595a7514c9a0aa1b9c76aedfc2307e1124271f27
Reviewed-on: https://go-review.googlesource.com/c/go/+/397137
Trust: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Julie Qiu <julie@golang.org>
2022-04-06 16:36:36 +00:00
Filippo Rossi
f92bfa440f [release-branch.go1.18] cmd/go: prevent panic in go work use
Check if paths passed as arguments are existing directories.

Fixes #52140
Updates #51841

Change-Id: Icfd148627e6f2c4651d6f923a37d413e68c67f6c
GitHub-Last-Rev: 77fffa7635
GitHub-Pull-Request: golang/go#51845
Reviewed-on: https://go-review.googlesource.com/c/go/+/394154
Trust: Bryan Mills <bcmills@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
Run-TryBot: Emmanuel Odeke <emmanuel@orijtech.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/397995
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
2022-04-05 15:18:32 +00:00
Roland Shoemaker
abb3f05524 [release-branch.go1.18] crypto/x509: only disable SHA-1 verification for certificates
Disable SHA-1 signature verification in Certificate.CheckSignatureFrom,
but not in Certificate.CheckSignature. This allows verification of OCSP
responses and CRLs, which still use SHA-1 signatures, but not on
certificates.

Updates #41682
Fixes #51852

Change-Id: Ia705eb5052e6fc2724fed59248b1c4ef8af6c3fe
Reviewed-on: https://go-review.googlesource.com/c/go/+/394294
Trust: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
Auto-Submit: Roland Shoemaker <roland@golang.org>
Reviewed-by: Jordan Liggitt <liggitt@google.com>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 35998c0109)
Reviewed-on: https://go-review.googlesource.com/c/go/+/398074
Reviewed-by: Cherry Mui <cherryyz@google.com>
2022-04-05 15:01:00 +00:00
John Anthony
c6ba470316 [release-branch.go1.18] cmd/go: prevent go work use panic when given a file
The current implementation fails to identify that an argument to go work
use is a file when expecting a directory, and panics when attempting to
access it as a directory. This change checks arguments are directories
and generates an error otherwise.

Fixes #51764
Updates #51749

Change-Id: If8f69d233409e93fcf391a8774bace74c031c986
Reviewed-on: https://go-review.googlesource.com/c/go/+/393615
Reviewed-by: Bryan Mills <bcmills@google.com>
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Trust: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit a84ef50021)
Reviewed-on: https://go-review.googlesource.com/c/go/+/397994
Reviewed-by: Cherry Mui <cherryyz@google.com>
2022-04-05 14:17:24 +00:00
Brad Fitzpatrick
30d9077a34 [release-branch.go1.18] crypto/x509: fix Certificate.Verify crash
(Primarily from Josh)

Updates #51759
Fixes #51763
Fixes CVE-2022-27536

Co-authored-by: Josh Bleecher Snyder <josharian@gmail.com>
Change-Id: I0a6f2623b57750abd13d5e194b5c6ffa3be6bf72
Reviewed-on: https://go-review.googlesource.com/c/go/+/393655
Trust: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 0fca8a8f25)
Reviewed-on: https://go-review.googlesource.com/c/go/+/394655
Trust: Roland Shoemaker <roland@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
2022-04-04 21:16:23 +00:00
Robert Findley
6412231192 [release-branch.go1.18] go/types, types2: preserve parent scope when substituting receivers
For #51920
Fixes #52007

Change-Id: I29e44a52dabee5c09e1761f9ec8fb2e8795f8901
Reviewed-on: https://go-review.googlesource.com/c/go/+/395538
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 9b90838712)
Reviewed-on: https://go-review.googlesource.com/c/go/+/395680
2022-04-04 20:28:11 +00:00
Paul E. Murphy
0bf8319883 [release-branch.go1.18] runtime: make static/dynamic startup detection work with musl on ppc64le
The glibc loader explicitly sets the first doubleword on the stack (R1)
to $0 to indicate it was dynamically loaded.

An ELFv2 ABI compliant loader will set R3/R4 to argc/argv when starting
the process, and R13 to TLS. musl is not compliant. Instead it passes
argc/argv like the kernel, but R3/R4 are in an undefined state and R13
is valid.

With the knowledge above, the startup code can be modified to
dynamically handle all three cases when linked internally.

Fixes #51874

Change-Id: I5de33862c161900d9161817388bbc13a65fdc69c
Reviewed-on: https://go-review.googlesource.com/c/go/+/394654
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Paul Murphy <murp@ibm.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Trust: Paul Murphy <murp@ibm.com>
Trust: Lynn Boger <laboger@linux.vnet.ibm.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/394794
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
2022-04-04 20:27:32 +00:00
Matthew Dempsky
78b8b4a176 [release-branch.go1.18] cmd/compile: replace Type.OrigSym with Type.OrigType
First law of cmd/compile frontend development: thou shalt not rely on
types.Sym.

This CL replaces Type.OrigSym with Type.OrigType, which semantically
matches what all of the uses within the frontend actually care about,
and avoids using types.Sym, which invariably leads to mistakes because
symbol scoping in the frontend doesn't work how anyone intuitively
expects it to.

Fixes #51855.

Change-Id: I4affe6ee0718103ce5006ab68aa7e1bb0cac6881
Reviewed-on: https://go-review.googlesource.com/c/go/+/394274
Trust: Matthew Dempsky <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
(cherry picked from commit adae6ec542)
Reviewed-on: https://go-review.googlesource.com/c/go/+/394296
2022-04-04 20:26:50 +00:00
Robert Findley
6ebf676289 [release-branch.go1.18] all update vendored golang.org/x/tools
Update x/tools from internal-branch.go1.18-vendor to pick up the
cherry-picked fix for #51727.

The following commands were used, from the cmd module:
  go get -d golang.org/x/tools@internal-branch.go1.18-vendor
  go mod tidy
  go mod vendor

Fixes #51727

Change-Id: I380a66fee585c8c12f9646de87ffb5e398b4ba80
Reviewed-on: https://go-review.googlesource.com/c/go/+/397476
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-04-04 20:04:16 +00:00
Robert Findley
69bc821a01 [release-branch.go1.18] cmd/compile/internal/importer: key tparams by Package instead of pkgname
The importer type param index used package name as type parameter key,
causing type parameters to be reused/overwritten if two packages in the
import graph had the same combination of (package name, declaration
name, type parameter name).

Fix this by instead using the *Package in the key.

Note: -G=3 was added to typeparam/issue51836.go, as it is necessary for
1.18 but not for tip.

For #51836
Fixes #51847

Change-Id: I881ceaf3cf7c1ab4e0835962350feb552e79b233
Reviewed-on: https://go-review.googlesource.com/c/go/+/394219
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
(cherry picked from commit fd1b5904ae)
Reviewed-on: https://go-review.googlesource.com/c/go/+/394854
2022-04-04 19:57:18 +00:00
Cuong Manh Le
c258e9d07d [release-branch.go1.18] cmd/compile: fix panic with nested dead hidden closures
CL 342350 fixed deadcode panic with dead hidden closures. However, a
closure may contains nested dead hidden closures, so we need to mark
them dead as well.

Fixes #51846

Change-Id: Ib54581adfc1bdea60e74d733cd30fd8e783da983
Reviewed-on: https://go-review.googlesource.com/c/go/+/394079
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/394080
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2022-04-04 19:55:44 +00:00
Bryan C. Mills
d17c5731ba [release-branch.go1.18] cmd/go: avoid stamping VCS metadata in test binaries
Invoking a VCS tool requires that the VCS tool be installed, and also
adds latency to build commands. Unfortunately, we had been mistakenly
loading VCS metadata for tests of "main" packages.

Users almost never care about versioning for test binaries, because
'go test' runs the test in the source tree and test binaries are only
rarely used outside of 'go test'. So the user already knows exactly
which version the test is built against, because the source code is
right there — it's not worth the overhead to stamp.

Fixes #51767.
Updates #51723.

Change-Id: I96f191c5a765f5183e5e10b6dfb75a0381c99814
Reviewed-on: https://go-review.googlesource.com/c/go/+/393894
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
Trust: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 67f6b8c987)
Reviewed-on: https://go-review.googlesource.com/c/go/+/393878
Reviewed-by: Cherry Mui <cherryyz@google.com>
2022-04-04 19:04:21 +00:00
Keith Randall
f4d55662d6 [release-branch.go1.18] cmd/compile: pointers to notinheap types need their own shape
They should not share a shape with regular pointers. We could coalesce
multiple pointer-to-not-in-heap types, but doesn't seem worth it - just
make them fully stenciled.

Fixes #51741

Change-Id: Ie8158177226fbc46a798e71c51897a82f15153df
Reviewed-on: https://go-review.googlesource.com/c/go/+/393895
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
(cherry picked from commit fcf6afb82d)
Reviewed-on: https://go-review.googlesource.com/c/go/+/393935
2022-04-04 19:03:49 +00:00
Cherry Mui
290883a559 [release-branch.go1.18] cmd/link: mark unexported methods for plugins
When plugin is used, we already mark all exported methods
reachable. However, when the plugin and the host program share
a common package, an unexported method could also be reachable
from both the plugin and the host via interfaces. We need to mark
them as well.

Fixes #51737.
Updates #51621.

Change-Id: I1a70d3f96b66b803f2d0ab14d00ed0df276ea500
Reviewed-on: https://go-review.googlesource.com/c/go/+/393365
Trust: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Than McIntosh <thanm@google.com>
(cherry picked from commit 91631bc7e0)
Reviewed-on: https://go-review.googlesource.com/c/go/+/397483
2022-04-04 19:03:11 +00:00
Cuong Manh Le
39a8c8cf2e [release-branch.go1.18] cmd/compile: fix wrong dict param when getting dict type
CL 338129 added getDictionaryType to get the dictionary type from the
specified dict param, but still using the one in info.dictParam, which
is wrong.

Fixes #51669

Change-Id: Ie13460c1e5751c4c5fc44479a44f6eed8b3b06e4
Reviewed-on: https://go-review.googlesource.com/c/go/+/391994
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Trust: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/392614
2022-04-04 18:05:18 +00:00
Robert Griesemer
9d738480d2 [release-branch.go1.18] go/types, types2: use correct underlying type in union set computation
Fixes #51665.

Change-Id: Ibf415d7e12849b8f50b58d74713613d4e65bc347
Reviewed-on: https://go-review.googlesource.com/c/go/+/392575
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/392577
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-04-04 18:04:18 +00:00
Bryan C. Mills
32ff9b5de6 [release-branch.go1.18] crypto/x509: skip WSATRY_AGAIN errors when dialing badssl.com subdomains
(Temporarily, until the root cause of the test failure can be
diagnosed and fixed properly.)

For #52094

Change-Id: Iec69e162159f3f0a93135f742aac97cf82c1d96c
Reviewed-on: https://go-review.googlesource.com/c/go/+/397478
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit df89f2ba53)
Reviewed-on: https://go-review.googlesource.com/c/go/+/397594
Reviewed-by: Cherry Mui <cherryyz@google.com>
2022-04-01 17:39:53 +00:00
Ian Lance Taylor
8b0583a054 [release-branch.go1.18] bytes: restore old Trim/TrimLeft behavior for nil
Keep returning nil for the cases where we historically returned nil,
even though this is slightly different for TrimLeft and TrimRight.

For #51793
Fixes #51796

Change-Id: Ifbdfc6b09d52b8e063cfe6341019f9b2eb8b70e9
Reviewed-on: https://go-review.googlesource.com/c/go/+/393876
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
(cherry picked from commit 32fdad19a2)
Reviewed-on: https://go-review.googlesource.com/c/go/+/396294
Reviewed-by: Austin Clements <austin@google.com>
2022-03-30 16:42:29 +00:00
Ian Lance Taylor
677c6fe94c [release-branch.go1.18] runtime: call testenv.MustHaveCGO in a couple of tests
For #51695
Fixes #51697

Change-Id: Icfe9d26ecc28a7db9040d50d4661cf9e8245471e
Reviewed-on: https://go-review.googlesource.com/c/go/+/392916
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
(cherry picked from commit 2d32594396)
Reviewed-on: https://go-review.googlesource.com/c/go/+/393699
Reviewed-by: Emmanuel Odeke <emmanuel@orijtech.com>
2022-03-28 16:54:53 +00:00
Heschi Kreinick
4aa1efed48 [release-branch.go1.18] go1.18
Change-Id: I81d8267b73c3dbd0d2f76e8c80fa2ae8b6f386df
Reviewed-on: https://go-review.googlesource.com/c/go/+/392894
Trust: Heschi Kreinick <heschi@google.com>
Run-TryBot: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-15 14:06:18 +00:00
Dmitri Shuralyov
428533fab4 [release-branch.go1.18] doc: update go_spec.html with latest changes
Generated at 2022-03-14 14:50 (EDT) with:

	git fetch
	git checkout origin/master -- doc/go_spec.html

This includes spec changes up to CL 391754.

Fixes #51532.

Change-Id: I2c23d764ffa33f24647cd2a4060268c1500f6f99
Reviewed-on: https://go-review.googlesource.com/c/go/+/392674
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-03-14 20:36:15 +00:00
Cuong Manh Le
4b9b25a21d [release-branch.go1.18] cmd/compile: fix re-export closure
For hidden closure built during stenciling to implement a function
instantiation, the function may come from other package, not local
package, which causes the ICE for code that re-export the hidden closure
after inlining.

To fix it, use the closure package for export writer when writing out
the closure itself.

Fixes #51423

Change-Id: I23b067ba14e2d602a0fc3b2e99bd9317afbe53ff
Reviewed-on: https://go-review.googlesource.com/c/go/+/391574
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 9743e9b6d8)
Reviewed-on: https://go-review.googlesource.com/c/go/+/391774
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2022-03-14 17:19:04 +00:00
Steven Johnstone
d69d093c77 [release-branch.go1.18] internal/fuzz: minimization should not reduce coverage
Minimization should result in a fuzz input which
includes the same coverage bits as the original
input.

Updates #48326

Change-Id: I6c5f30058b57ccd1a096ad0e9452a4dfbb7d9aab
Reviewed-on: https://go-review.googlesource.com/c/go/+/391454
Trust: Bryan Mills <bcmills@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
Auto-Submit: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 5003ed884a)
Reviewed-on: https://go-review.googlesource.com/c/go/+/391798
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
2022-03-14 16:31:27 +00:00
Roland Shoemaker
c79ccd88ab [release-branch.go1.18] internal/fuzz: don't use dirty coverage maps during minimization
When minimizing a value, if the value cannot be minimized (i.e. it is
the final value is the same value as was sent for minimization) return
the initial coverage map, rather than the coverageSnapshot, which is
actually the coverage map for the final minimization step and may not
accurately reflect whether the input actually expands the coverage set
or not.

Updates #48326

Change-Id: I01f0eebe5841e808b6799647d2e5fe3aa45cd2e0
Reviewed-on: https://go-review.googlesource.com/c/go/+/391614
Reviewed-by: Bryan Mills <bcmills@google.com>
Trust: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
Auto-Submit: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit bd71dee2b4)
Reviewed-on: https://go-review.googlesource.com/c/go/+/391797
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-14 16:29:23 +00:00
Robert Griesemer
8706c09622 [release-branch.go1.18] go/types, types2: remove incorrect assertion (don't crash)
The removed assertion was never incorrect, as signatures may
be from methods in interfaces, and (some) interfaces set the
receivers of their methods (so we have a position for error
reporting).

This CL changes the issue below from a release blocker to an
issue for Go 1.19.

For #51593.

Change-Id: I0c5f2913b397b9ab557ed74a80cc7a715e840412
Reviewed-on: https://go-review.googlesource.com/c/go/+/391615
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 914195c132)
Reviewed-on: https://go-review.googlesource.com/c/go/+/391796
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2022-03-14 16:24:26 +00:00
Keith Randall
2c6a889234 [release-branch.go1.18] cmd/compile: fix expression switches using type parameters
Both the thing we're switching on, as well as the cases we're switching for.
Convert anything containing a type parameter to interface{} before the
comparison happens.

Fixes #51522

Change-Id: I97ba9429ed332cb7d4240cb60f46d42226dcfa5f
Reviewed-on: https://go-review.googlesource.com/c/go/+/391594
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
(cherry picked from commit 2e46a0a997)
Reviewed-on: https://go-review.googlesource.com/c/go/+/391795
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2022-03-14 16:21:37 +00:00
Keith Randall
1edc1ccf15 [release-branch.go1.18] cmd/compile: fix transform of OEQ/ONE when one arg is a type param
At this point in stenciling, we have shape types, not raw type parameters.
The code was correct in the other part of this function.

Update #51522

Change-Id: Ife495160a2be5f6af5400363c3efb68dda518b5f
Reviewed-on: https://go-review.googlesource.com/c/go/+/391475
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit 8cf11694ab)
Reviewed-on: https://go-review.googlesource.com/c/go/+/391794
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2022-03-14 16:20:02 +00:00
Robert Griesemer
a0c7e2620a [release-branch.go1.18] go/types, types2: pointer base types cannot be type constraints
Pointer types may appear in expressions *P and we don't know if
we have an indirection (P is a pointer value) or a pointer type
(P is a type) until we type-check P. Don't forget to check that
a type P must be an ordinary (not a constraint) type in this
special case.

Fixes #51578.

Change-Id: If782cc6dd2a602a498574c78c99e40c3b72274a5
Reviewed-on: https://go-review.googlesource.com/c/go/+/391275
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 3a5e3d8173)
Reviewed-on: https://go-review.googlesource.com/c/go/+/391357
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2022-03-11 00:01:01 +00:00
Robert Findley
c6b5b7e6e5 [release-branch.go1.18] go/types, types2: clarify documentation with respect to generic types
Address several areas where documentation was inaccurate or unclear
regarding generic types. Also prefer the use of the word 'generic' over
'parameterized', and add additional documentation for the use of
SetConstraint.

For #49593

Change-Id: Iccac60d1b3e2c45a57a3d03b3c10984293af57dd
Reviewed-on: https://go-review.googlesource.com/c/go/+/391154
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit e189b5e06d)
Reviewed-on: https://go-review.googlesource.com/c/go/+/391356
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-11 00:00:29 +00:00
Robert Griesemer
36d32da19f [release-branch.go1.18] go/types, types2: disable field accesses through type parameters
This is a feature that is not understood well enough and may have
subtle repercussions impacting future changes. Disable for Go 1.18.

The actual change is trivial: disable a branch through a flag.
The remaining changes are adjustments to tests.

Fixes #51576.

Change-Id: Ib77b038b846711a808315a8889b3904e72367bce
Reviewed-on: https://go-review.googlesource.com/c/go/+/391135
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit b8248fab89)
Reviewed-on: https://go-review.googlesource.com/c/go/+/391355
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2022-03-10 23:59:19 +00:00
Mark Pulford
1e4dc06f1a [release-branch.go1.18] cmd/go: fix buildvcs when using older git versions
Git versions before v2.10.0 do not support --no-show-signature.
Using "-c" allows Git to ignore the configuration option if it does not
exist.

Fixes #51253

Change-Id: I2b1adaca0eb18ae31f2e1119e354ce515b00cfc2
Reviewed-on: https://go-review.googlesource.com/c/go/+/388194
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
(cherry picked from commit 7026eeb8cf)
Reviewed-on: https://go-review.googlesource.com/c/go/+/391354
2022-03-10 23:58:18 +00:00
Robert Findley
d10b8192c0 [release-branch.go1.18] go/printer: don't print unnecesary commas for func type param lists
Type parameter lists are not ambiguous for function declarations in the
way that they are ambiguous for type declarations. Avoid printing an
extra comma to disambiguate.

Fixes #51548

Change-Id: I8ca2b21e271982013653b9e220f92ee74f577ba2
Reviewed-on: https://go-review.googlesource.com/c/go/+/390914
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 0add0647d8)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390957
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2022-03-09 16:46:32 +00:00
Bryan C. Mills
bf366ef711 [release-branch.go1.18] internal/fuzz: fix encoding for out-of-range ints and runes
Also switch float64 NaN encoding to use hexadecimal, and accept
hexadecimal encoding for all other integer types too. (That gives us
the flexibility to change the encodings in either direction in the
future without breaking earlier Go versions.)

Out-of-range runes encoded using "%q" were previously replaced with
the Unicode replacement charecter, losing their values.

Out-of-range ints and uints on 32-bit platforms were previously
rejected. Now they are wrapped instead: an “interesting” case with a
large int or uint found on a 64-bit platform likely remains
interesting on a 32-bit platform, even if the specific values differ.

To verify the above changes, I have made TestMarshalUnmarshal accept
(and check for) arbitrary differences between input and output, and
added tests cases that include values in valid but non-canonical
encodings.

I have also added round-trip fuzz tests in the opposite direction for
most of the types affected by this change, verifying that a marshaled
value unmarshals to the same bitwise value.

Updates #51258
Updates #51526
Fixes #51528

Change-Id: I7727a9d0582d81be0d954529545678a4374e88ed
Reviewed-on: https://go-review.googlesource.com/c/go/+/390424
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 7419bb3ebb)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390816
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
2022-03-09 16:46:19 +00:00
thepudds
92644ff54a [release-branch.go1.18] cmd/compile/internal/types2: more consistently print "check go.mod" if language version < 1.18
If you attempt to instantiate a generic type or func and run 'go build'
with a language version < 1.18 in the 'go' directive inside the go.mod
file, cmd/compile emits a friendly message that includes the suggestion
to 'check go.mod':

    type instantiation requires go1.18 or later (-lang was set to go1.17; check go.mod)

However, if the code instead only declares a generic type or func
without instantiating, cmd/compile currently emits a less friendly
message:

    type parameters require go1.18 or later

With this CL, the error in that situation becomes:

    type parameter requires go1.18 or later (-lang was set to go1.17; check go.mod)

Within cmd/compile/internal/types2, it already calls check.versionErrorf
in a dozen or so places, including three existing calls to
check.versionErrorf within typeset.go (e.g., for embedding a constraint
interface).

This CL adds two more calls to check.versionErrorf, replacing calls to
check.softErrorf. Both check.versionErrorf and check.softErrorf call
check.err(at, <string>, true) after massaging the string message.

Fixes #51531

Change-Id: If54e179f5952b97701d1dfde4abb08101de07811
GitHub-Last-Rev: b0b7c1346f
GitHub-Pull-Request: golang/go#51536
Reviewed-on: https://go-review.googlesource.com/c/go/+/390578
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Robert Findley <rfindley@google.com>
(cherry picked from commit d3070a767b)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390959
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-03-09 16:46:07 +00:00
Robert Findley
673d52b33a [release-branch.go1.18] go/types, types2: disable inference for type instances
Inference for type instances has dependencies on type-checking order
that can lead to subtle bugs. As explained in #51527, disable it for
1.18.

Fixes #51527

Change-Id: I42795bad30ce53abecfc5a4914599ae5a2041a9e
Reviewed-on: https://go-review.googlesource.com/c/go/+/387934
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 28fab5ef21)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390576
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2022-03-08 00:42:40 +00:00
Robert Findley
e3f9a4f2ae [release-branch.go1.18] go/types: document that predicates are undefined on generic types
Fixes #50887

Change-Id: I451d66b067badcfb7cf2e2756ea2b062366ac9d4
Reviewed-on: https://go-review.googlesource.com/c/go/+/390039
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 20dd9a42fb)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390575
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2022-03-08 00:42:35 +00:00
Robert Findley
c827ddf9e5 [release-branch.go1.18] go/types, types2: record all type instances, even duplicates
Due to instance de-duplication, we were failing to record some type
instances in types.Info.Instances. Fix this by moving the instance
recording out of the resolver.

Fixes #51494

Change-Id: Iddd8989307d95886eedb321efa4ab98cd2b3573a
Reviewed-on: https://go-review.googlesource.com/c/go/+/390041
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 43b09c096a)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390574
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2022-03-08 00:42:28 +00:00
Robert Griesemer
aeced24498 [release-branch.go1.18] go/types, types2: don't crash in selectors referring to the type being declared
In Checker.typInternal, the SelectorExpr case was the only case that
didn't either set or pass along the incoming def *Named type.

Handle this by passing it along to Checker.selector and report a
cycle if one is detected.

Fixes #51509.

Change-Id: I6c2d46835f225aeb4cb25fe0ae55f6180cef038b
Reviewed-on: https://go-review.googlesource.com/c/go/+/390314
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
(cherry picked from commit 114d5deac2)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390423
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-03-08 00:42:20 +00:00
Robert Griesemer
f913f9dd1a [release-branch.go1.18] go/types, types2: correctly include comparable in type set intersection
The comparable bit was handled incorrectly. This CL establishes
a clear invariant for a type set's terms and its comparable bit
and correctly uses the bit when computing term intersections.

Relevant changes:

- Introduce a new function intersectTermLists that does the
  correct intersection computation.

Minor:

- Moved the comparable bit after terms in _TypeSet to make it
  clearer that they belong together.

- Simplify and clarify _TypeSet.IsAll predicate.

- Remove the IsTypeSet predicate which was only used for error
  reporting in union.go, and use the existing predicates instead.

- Rename/introduce local variables in computeInterfaceTypeSet
  for consistency and to avoid confusion.

- Update some tests whose output has changed because the comparable
  bit is now only set if we have have the set of all types.
  For instance, for interface{comparable; int} the type set doesn't
  set the comparable bit because the intersection of comparable and
  int is just int; etc.

- Add many more comments to make the code clearer.

Fixes #51472.

Change-Id: I8a5661eb1693a41a17ce5f70d7e10774301f38ab
Reviewed-on: https://go-review.googlesource.com/c/go/+/390025
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 7dc6c5ec34)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390419
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-08 00:42:10 +00:00
Roland Shoemaker
a54f962c29 [release-branch.go1.18] internal/fuzz: fix TestUnmarshalMarshal on MIPS
Previous value used in the float32 roundtrip used float32(math.NaN())-1
which caused the quiet/signal bit to flip, which seemed to break the
test on MIPS platforms. Instead switch to using float32(math.NaN())+1,
which preserves the bit and makes the test happy.

Possibly related to #37455
Fixes #51258

Change-Id: Ia85c649e89a5d02027c0ec197f0ff318aa819c19
Reviewed-on: https://go-review.googlesource.com/c/go/+/390214
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Trust: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 63bd6f68e6)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390418
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-08 00:41:50 +00:00
Roland Shoemaker
7f9a85f2d9 [release-branch.go1.18] internal/fuzz: handle Inf/NaN float values
Fixes #51258

Change-Id: I3c8b785ac912d66e1a6e2179625e6903032b8330
Reviewed-on: https://go-review.googlesource.com/c/go/+/388354
Reviewed-by: Bryan Mills <bcmills@google.com>
Trust: Roland Shoemaker <roland@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
Auto-Submit: Roland Shoemaker <roland@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 2b8aa2b734)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390095
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-08 00:41:39 +00:00
Ian Lance Taylor
520f0d0401 [release-branch.go1.18] syscall: remove TestRlimit
It's more trouble than it's worth. New code should be using x/sys/unix
anyhow.

Fixes #40564
Fixes #51479

Change-Id: I1c0e13f494380c1565e98359f088af9f52790b79
Reviewed-on: https://go-review.googlesource.com/c/go/+/390020
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 1e122e3894)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390022
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2022-03-07 20:20:41 +00:00
Michael Matloob
0b38b0277e [release-branch.go1.18] cmd/go: add links to workspaces reference and tutorial to go help work
For #45713

Change-Id: Ia2901cbfc5deb52503e74fcf9dff26a56ec582c3
Reviewed-on: https://go-review.googlesource.com/c/go/+/389297
Trust: Michael Matloob <matloob@golang.org>
Run-TryBot: Michael Matloob <matloob@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 1eb1f621da)
Reviewed-on: https://go-review.googlesource.com/c/go/+/389914
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-07 19:39:47 +00:00
Bryan C. Mills
40f6480db6 [release-branch.go1.18] cmd/go: error out of 'go work use' if no directories are given
Otherwise, the behavior of 'go work use -r' (without arguments)
may be surprising.

For #51448.

Change-Id: I50cf1339591720ec5bd333146b89c9944ce420d5
Reviewed-on: https://go-review.googlesource.com/c/go/+/389855
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Michael Matloob <matloob@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 4f8094386c)
Reviewed-on: https://go-review.googlesource.com/c/go/+/389299
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-07 16:35:02 +00:00
Bryan C. Mills
839c0f3b3e [release-branch.go1.18] cmd/go: make paths consistent between 'go work init' and 'go work use'
Fixes #51448

Change-Id: I86719b55037c377eb82154e169d8a9bbae20b77c
Reviewed-on: https://go-review.googlesource.com/c/go/+/389854
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
(cherry picked from commit 87a345ca38)
Reviewed-on: https://go-review.googlesource.com/c/go/+/389298
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-07 16:34:36 +00:00
Cherry Mui
ce427cf961 [release-branch.go1.18] runtime: count spill slot for frame size at finalizer call
The finalizer is called using reflectcall. When register ABI is
used, the finalizer's argument is passed in register(s). But the
frame size calculation does not include the spill slot. When the
argument actually spills, it may clobber the caller's stack frame.
This CL fixes it.

Fixes #51457.

Change-Id: Ibcc7507c518ba65c1c5a7759e5cab0ae3fc7efce
Reviewed-on: https://go-review.googlesource.com/c/go/+/389574
Trust: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
(cherry picked from commit 58804ea67a)
Reviewed-on: https://go-review.googlesource.com/c/go/+/388995
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-07 16:31:22 +00:00
Robert Griesemer
79cf7c839b [release-branch.go1.18] go/types, types2: fix scoping for iteration variables declared by range clause
Also correct scope position for such variables.
Adjusted some comments.

Fixes #51437.

Change-Id: Ic49a1459469c8b2c7bc24fe546795f7d56c67cb4
Reviewed-on: https://go-review.googlesource.com/c/go/+/389594
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Robert Findley <rfindley@google.com>
(cherry picked from commit d3fe4e193e)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390018
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2022-03-07 16:27:17 +00:00
Bryan C. Mills
9f40b4f7a4 [release-branch.go1.18] cmd/go: ignore the workspace when running a package at a specified version
Fixes #51390

Change-Id: I805e66809b2aafb48f7040dee72910dd7d6c1396
Reviewed-on: https://go-review.googlesource.com/c/go/+/388917
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
(cherry picked from commit 86b5f6a7be)
Reviewed-on: https://go-review.googlesource.com/c/go/+/389575
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-07 16:16:08 +00:00
Keith Randall
9f5e2849e1 [release-branch.go1.18] cmd/compile: don't include instantiating types in type hash
This CL is a bit overkill, but it is pretty safe for 1.18. We'll
want to revisit for 1.19 so we can avoid the hash collisions between
types, e.g. G[int] and G[float64], that will cause some slowdowns
(but not incorrect behavior). Thanks Cherry for the simple idea.

Fixes #51250

Change-Id: I68130e09ba68e7cc35687bc623f63547bc552867
Reviewed-on: https://go-review.googlesource.com/c/go/+/389474
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit d3672054fb)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390017
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
2022-03-04 20:56:13 +00:00
Robert Griesemer
77a142486e [release-branch.go1.18] go/types, types2: clarify a comment and add an extra test
Confirm that the current implementation of core type unification
looks correct and update the respective comment. Add an extra test.

Fixes #51376.

Change-Id: I6a603a4baeee2ede5bb4a1d60766204a808936d7
Reviewed-on: https://go-review.googlesource.com/c/go/+/388294
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 6da16b6ad5)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390016
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2022-03-04 20:43:47 +00:00
Robert Griesemer
fd5b9b7c07 [release-branch.go1.18] go/types, types2: correctly consider ~ (tilde) in constraint type inference
When doing constraint type inference, we must consider whether the
constraint's core type is precise (no tilde) or imprecise (tilde,
or not a single specific type). In the latter case, we cannot infer
an unknown type argument from the (imprecise) core type because there
are infinitely many possible types. For instance, given

        [E ~byte]

if we don't know E, we cannot infer that E must be byte (it could be
myByte, etc.). On the other hand, if we do know the type argument,
say for S in this example:

        [S ~[]E, E any]

we must consider the underlying type of S when matching against ~[]E
because we have a tilde.

Because constraint type inference may infer type arguments that were
not eligible initially (because they were unknown and the core type
is imprecise), we must iterate the process until nothing changes any-
more. For instance, given

        [S ~[]E, M ~map[string]S, E any]

where we initially only know the type argument for M, we must ignore
S (and E) at first. After one iteration of constraint type inference,
S is known at which point we can infer E as well.

The change is large-ish but the actual functional changes are small:

- There's a new method "unknowns" to determine the number of as of yet
  unknown type arguments.

- The adjCoreType function has been adjusted to also return tilde
  and single-type information. This is now conveniently returned
  as (*term, bool), and the function has been renamed to coreTerm.

- The original constraint type inference loop has been adjusted to
  consider tilde information.

- This adjusted original constraint type inference loop has been
  nested in another loop for iteration, together with some minimal
  logic to control termination.

The remaining changes are modifications to tests:

- There's a substantial new test for this issue.

- Several existing test cases were adjusted to accomodate the
  fact that they inferred incorrect types: tildes have been
  removed throughout. Most of these tests are for pathological
  cases.

- A couple of tests were adjusted where there was a difference
  between the go/types and types2 version.

Fixes #51229.

Change-Id: If0bf5fb70ec22913b5a2da89adbf8a27fbc921d9
Reviewed-on: https://go-review.googlesource.com/c/go/+/387977
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 0807986fe6)
Reviewed-on: https://go-review.googlesource.com/c/go/+/390015
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2022-03-04 20:43:23 +00:00
Cherry Mui
6206d65235 [release-branch.go1.18] cmd/compile: use AutogeneratedPos for method value wrapper
We use AutogeneratedPos for most compiler-generated functions. But
for method value wrappers we currently don't. Instead, we use the
Pos for their (direct) declaration if there is one, otherwise
not set it in methodValueWrapper, which will probably cause it to
inherit from the caller, i.e. the Pos of that method value
expression. If that Pos has inline information, it will cause the
method wrapper to have bogus inline information, which could lead
to infinite loop when printing a stack trace.

Change it to use AutogeneratedPos instead.

Fixes #51401.

Change-Id: I398dfe85f9f875e1fd82dc2f489dab63ada6570d
Reviewed-on: https://go-review.googlesource.com/c/go/+/388794
Trust: Cherry Mui <cherryyz@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
(cherry picked from commit b0db2f00a0)
Reviewed-on: https://go-review.googlesource.com/c/go/+/388918
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
2022-03-04 20:35:59 +00:00
Dmitri Shuralyov
9f2f0ee6ce [release-branch.go1.18] all: merge master (acc5f55) into release-branch.go1.18
Merge List:

+ 2022-02-28 acc5f55bac cmd/go: make work and work_edit script tests version-independent
+ 2022-02-28 f04d5c118c cmd/internal/obj/riscv/testdata/testbranch: add //go:build lines
+ 2022-02-28 9fe3676bc7 all: fix typos
+ 2022-02-28 f9285818b6 go/types, types2: fix string to type parameter conversions
+ 2022-02-28 eb8198d2f6 cmd/compile: deal with constructed types that have shapes in them
+ 2022-02-28 b33592dcfd spec: the -'s possessive suffix is English, not code
+ 2022-02-28 57e3809884 runtime: avoid cgo_unsafe_args for syscall.syscall functions on darwin/arm64
+ 2022-02-28 06a43e4ab6 cmd/compile: fix case for structural types where we should be looking at typeparams
+ 2022-02-28 0907d57abf cmd/compile: emit types of constants which are instantiated generic types
+ 2022-02-28 9c4a8620c8 CONTRIBUTORS: update for the Go 1.18 release
+ 2022-02-28 57dda9795d test: add new test case for 51219 that triggers the types2 issue
+ 2022-02-26 a064a4f29a cmd/compile: ensure dictionary assignment statements are defining statements
+ 2022-02-26 286e3e61aa go/types, types2: report an error for x.sel where x is a built-in
+ 2022-02-25 01e522a973 go/types,types2: revert documentation for Type.Underlying
+ 2022-02-25 26999cfd84 runtime/internal/atomic: set SP delta correctly for 64-bit atomic functions on ARM
+ 2022-02-25 7c694fbad1 go/types, types2: delay receiver type validation
+ 2022-02-25 55e5b03cb3 doc/go1.18: note changes to automatic go.mod and go.sum updates
+ 2022-02-25 6d810241eb doc/go1.18: document minimum Linux kernel version
+ 2022-02-25 b8b3196375 doc/go1.18: document method set limitation for method selectors
+ 2022-02-24 c0840a7c72 go/types, types2: method recv type parameter count must match base type parameter count
+ 2022-02-24 c15527f0b0 go/types, types2: implement adjCoreType using TypeParam.is
+ 2022-02-24 5a9fc946b4 cmd/go: avoid +incompatible major versions if a go.mod file exists in a subdirectory for that version
+ 2022-02-24 4edefe9568 cmd/compile: delay all call transforms if in a generic function
+ 2022-02-24 8c5904f149 doc/go1.18: mention runtime/pprof improvements
+ 2022-02-24 b2dfec100a doc/go1.18: fix typo in AMD64 port section
+ 2022-02-24 78e99761fc go/types, types2: don't crash if comp. literal element type has no core type
+ 2022-02-23 e94f7df957 go/types, types2: generalize cleanup phase after type checking
+ 2022-02-23 163da6feb5 go/types, types2: add "dynamic" flag to comparable predicate
+ 2022-02-23 e534907f65 go/types: delete unnecessary slice construction
+ 2022-02-23 d0c3b01162 doc/go1.18: drop misplaced period
+ 2022-02-22 35170365c8 net: document methods of Buffers
+ 2022-02-22 3140625606 doc/go1.18: correct "go build -asan" HTML tag
+ 2022-02-22 d17b65ff54 crypto/x509, runtime: fix occasional spurious “certificate is expired”
+ 2022-02-21 c9fe126c8b doc/go1.18: fix a few small typos, add a few commas
+ 2022-02-20 851ecea4cc encoding/xml: embedded reference to substruct causes XML marshaller to panic on encoding
+ 2022-02-19 0261fa616a testdata: fix typo in comment
+ 2022-02-19 903e7cc699 doc/go1.18: fix grammar error
+ 2022-02-19 e002cf4df7 strings: fix typo in comment
+ 2022-02-18 61b5c866a9 doc/go1.18: document Go 1.17 bootstrap and //go:build fix
+ 2022-02-18 d27248c52f runtime: save some stack space for racecall on ARM64
+ 2022-02-18 d93cc8cb96 runtime: define racefuncenter and racefuncexit as ABIInternal
+ 2022-02-18 20b177268f reflect: call ABIInternal moveMakeFuncArgPtrs on ARM64
+ 2022-02-18 d35ed09486 cmd/compile: fix importers to deal with recursion through type constraints
+ 2022-02-16 eaf040502b os: eliminate arbitrary sleep in Kill tests

Change-Id: I74352b70d97c6fd4a45aee4e222160ea2a7854ae
2022-03-02 18:48:48 -05:00
Dmitri Shuralyov
cb5a598d7f [release-branch.go1.18] go1.18rc1
Change-Id: I8097771a219c55ceed3e926a238551e59df0816f
Reviewed-on: https://go-review.googlesource.com/c/go/+/386197
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-02-16 22:23:24 +00:00
Bryan C. Mills
e70ee95914 [release-branch.go1.18] 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.

Updates #44131.

Change-Id: I9753571438380dc14fc3531efdaea84578a47fae
Reviewed-on: https://go-review.googlesource.com/c/go/+/386174
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit eaf040502b)
Reviewed-on: https://go-review.googlesource.com/c/go/+/386196
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-02-16 21:38:42 +00:00
Dmitri Shuralyov
39d2f50919 [release-branch.go1.18] update codereview.cfg for release-branch.go1.18
Change-Id: I2f15c3704c3921c1b648c51566f4984e12a85cfa
Reviewed-on: https://go-review.googlesource.com/c/go/+/386354
Trust: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-02-16 21:18:03 +00:00
193 changed files with 4358 additions and 1468 deletions

1
VERSION Normal file
View File

@@ -0,0 +1 @@
go1.18.1

View File

@@ -1 +1,2 @@
branch: master
branch: release-branch.go1.18
parent-branch: master

View File

@@ -1,26 +1,16 @@
<!--{
"Title": "The Go Programming Language Specification - Go 1.18 Draft",
"Subtitle": "Version of Feb 28, 2022",
"Title": "The Go Programming Language Specification",
"Subtitle": "Version of March 10, 2022",
"Path": "/ref/spec"
}-->
<h2>Earlier version</h2>
<p>
For the pre-Go1.18 specification without generics support see
<a href="/doc/go1.17_spec.html">The Go Programming Language Specification</a>.
</p>
<!-- TODO(gri) remove this before the final release -->
<p><b>
[For reviewers: Sections where we know of missing prose are marked like this. The markers will be removed before the release.]
</b></p>
<h2 id="Introduction">Introduction</h2>
<p>
This is a reference manual for the Go programming language. For
more information and other documents, see <a href="/">golang.org</a>.
This is the reference manual for the Go programming language.
The pre-Go1.18 version, without generics, can be found
<a href="/doc/go1.17_spec.html">here</a>.
For more information and other documents, see <a href="/">golang.org</a>.
</p>
<p>
@@ -766,7 +756,7 @@ type given in its declaration, the type provided in the
<code>new</code> call or composite literal, or the type of
an element of a structured variable.
Variables of interface type also have a distinct <i>dynamic type</i>,
which is the concrete type of the value assigned to the variable at run time
which is the (non-interface) type of the value assigned to the variable at run time
(unless the value is the predeclared identifier <code>nil</code>,
which has no type).
The dynamic type may vary during execution but values stored in interface
@@ -812,7 +802,7 @@ TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType
<p>
The language <a href="#Predeclared_identifiers">predeclares</a> certain type names.
Others are introduced with <a href="#Type_declarations">type declarations</a>
or <a href="#Type_parameter_lists">type parameter lists</a>.
or <a href="#Type_parameter_declarations">type parameter lists</a>.
<i>Composite types</i>&mdash;array, struct, pointer, function,
interface, slice, map, and channel types&mdash;may be constructed using
type literals.
@@ -987,7 +977,7 @@ built-in function <a href="#Length_and_capacity"><code>cap(a)</code></a>.
</p>
<p>
A new, initialized slice value for a given element type <code>T</code> is
A new, initialized slice value for a given element type <code>T</code> may be
made using the built-in function
<a href="#Making_slices_maps_and_channels"><code>make</code></a>,
which takes a slice type
@@ -1422,7 +1412,7 @@ interface {
~int
}
// An interface representing all types with underlying type int which implement the String method.
// An interface representing all types with underlying type int that implement the String method.
interface {
~int
String() string
@@ -1455,32 +1445,32 @@ Union elements denote unions of type sets:
</p>
<pre>
// The Floats interface represents all floating-point types
// The Float interface represents all floating-point types
// (including any named types whose underlying types are
// either float32 or float64).
type Floats interface {
type Float interface {
~float32 | ~float64
}
</pre>
<p>
In a union, a term cannot be a type parameter, and the type sets of all
In a union, a term cannot be a <a href="#Type_parameter_declarations">type parameter</a>, and the type sets of all
non-interface terms must be pairwise disjoint (the pairwise intersection of the type sets must be empty).
Given a type parameter <code>P</code>:
</p>
<pre>
interface {
P // illegal: the term P is a type parameter
int | P // illegal: the term P is a type parameter
~int | MyInt // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
float32 | Floats // overlapping type sets but Floats is an interface
P // illegal: P is a type parameter
int | P // illegal: P is a type parameter
~int | MyInt // illegal: the type sets for ~int and MyInt are not disjoint (~int includes MyInt)
float32 | Float // overlapping type sets but Float is an interface
}
</pre>
<p>
Implementation restriction:
A union with more than one term cannot contain the
A union (with more than one term) cannot contain the
<a href="#Predeclared_identifiers">predeclared identifier</a> <code>comparable</code>
or interfaces that specify methods, or embed <code>comparable</code> or interfaces
that specify methods.
@@ -1494,12 +1484,12 @@ non-interface types.
</p>
<pre>
var x Floats // illegal: Floats is not a basic interface
var x Float // illegal: Float is not a basic interface
var x interface{} = Floats(nil) // illegal
var x interface{} = Float(nil) // illegal
type Floatish struct {
f Floats // illegal
f Float // illegal
}
</pre>
@@ -1545,7 +1535,7 @@ A type <code>T</code> implements an interface <code>I</code> if
</ul>
<p>
A value <code>x</code> of type <code>T</code> implements an interface if <code>T</code>
A value of type <code>T</code> implements an interface if <code>T</code>
implements the interface.
</p>
@@ -1701,10 +1691,9 @@ Each type <code>T</code> has an <i>underlying type</i>: If <code>T</code>
is one of the predeclared boolean, numeric, or string types, or a type literal,
the corresponding underlying type is <code>T</code> itself.
Otherwise, <code>T</code>'s underlying type is the underlying type of the
type to which <code>T</code> refers in its <a href="#Type_declarations">type
declaration</a>. The underlying type of a type parameter is the
underlying type of its <a href="#Type_constraints">type constraint</a>, which
is always an interface.
type to which <code>T</code> refers in its declaration.
For a type parameter that is the underlying type of its
<a href="#Type_constraints">type constraint</a>, which is always an interface.
</p>
<pre>
@@ -1755,7 +1744,7 @@ direction.
</ol>
<p>
All other interfaces don't have a core type.
No other interfaces have a core type.
</p>
<p>
@@ -1775,7 +1764,7 @@ depending on the direction of the directional channels present.
<p>
By definition, a core type is never a <a href="#Type_definitions">defined type</a>,
<a href="#Type_parameter_lists">type parameter</a>, or
<a href="#Type_parameter_declarations">type parameter</a>, or
<a href="#Interface_types">interface type</a>.
</p>
@@ -1795,7 +1784,7 @@ interface{ ~[]*data; String() string } // []*data
</pre>
<p>
Examples of interfaces whithout core types:
Examples of interfaces without core types:
</p>
<pre>
@@ -1805,70 +1794,6 @@ interface{ chan int | chan&lt;- string } // channels have different element
interface{ &lt;-chan int | chan&lt;- int } // directional channels have different directions
</pre>
<h3 id="Specific_types">Specific types</h3>
<p><b>
[The definition of specific types is not quite correct yet.]
</b></p>
<p>
An interface specification that contains <a href="#Interface_types">type elements</a>
defines a (possibly empty) set of <i>specific types</i>.
Loosely speaking, these are the types <code>T</code> that appear in the
interface definition in terms of the form <code>T</code>, <code>~T</code>,
or in unions of such terms.
</p>
<p>
More precisely, for a given interface, the set of specific types corresponds to
the set 𝑅 of representative types of the interface, if 𝑅 is non-empty and finite.
Otherwise, if 𝑅 is empty or infinite, the interface has <i>no specific types</i>.
</p>
<p>
For a given interface, type element or type term, the set 𝑅 of representative types is defined as follows:
</p>
<ul>
<li>For an interface with no type elements, 𝑅 is the (infinite) set of all types.
</li>
<li>For an interface with type elements,
𝑅 is the intersection of the representative types of its type elements.
</li>
<li>For a non-interface type term <code>T</code> or a term of the form <code>~T</code>,
𝑅 is the set consisting of the type <code>T</code>.
</li>
<li>For a <i>union</i> of terms
<code>t<sub>1</sub>|t<sub>2</sub>|…|t<sub>n</sub></code>,
𝑅 is the union of the representative types of the terms.
</li>
</ul>
<p>
An interface may have specific types even if its <a href="#Interface_types">type set</a>
is empty.
</p>
<p>
Examples of interfaces with their specific types:
</p>
<pre>
interface{} // no specific types
interface{ int } // int
interface{ ~string } // string
interface{ int|~string } // int, string
interface{ Celsius|Kelvin } // Celsius, Kelvin
interface{ float64|any } // no specific types (union is all types)
interface{ int; m() } // int (but type set is empty because int has no method m)
interface{ ~int; m() } // int (but type set is infinite because many integer types have a method m)
interface{ int; any } // int
interface{ int; string } // no specific types (intersection is empty)
</pre>
<h3 id="Type_identity">Type identity</h3>
<p>
@@ -1973,21 +1898,21 @@ defined type while the latter is a type literal
<h3 id="Assignability">Assignability</h3>
<p>
A value <code>x</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
A value <code>x</code> of type <code>V</code> is <i>assignable</i> to a <a href="#Variables">variable</a> of type <code>T</code>
("<code>x</code> is assignable to <code>T</code>") if one of the following conditions applies:
</p>
<ul>
<li>
<code>x</code>'s type is identical to <code>T</code>.
<code>V</code> and <code>T</code> are identical.
</li>
<li>
<code>x</code>'s type <code>V</code> and <code>T</code> have identical
<code>V</code> and <code>T</code> have identical
<a href="#Underlying_types">underlying types</a> and at least one of <code>V</code>
or <code>T</code> is not a <a href="#Types">named type</a>.
</li>
<li>
<code>x</code>'s type <code>V</code> and <code>T</code> are channel types with
<code>V</code> and <code>T</code> are channel types with
identical element types, <code>V</code> is a bidirectional channel,
and at least one of <code>V</code> or <code>T</code> is not a <a href="#Types">named type</a>.
</li>
@@ -2008,25 +1933,24 @@ by a value of type <code>T</code>.
</ul>
<p>
Additionally, if <code>x</code>'s type <code>V</code> or <code>T</code> are type parameters
with <a href="#Specific_types">specific types</a>, <code>x</code>
Additionally, if <code>x</code>'s type <code>V</code> or <code>T</code> are type parameters, <code>x</code>
is assignable to a variable of type <code>T</code> if one of the following conditions applies:
</p>
<ul>
<li>
<code>x</code> is the predeclared identifier <code>nil</code>, <code>T</code> is
a type parameter, and <code>x</code> is assignable to each specific type of
<code>T</code>.
a type parameter, and <code>x</code> is assignable to each type in
<code>T</code>'s type set.
</li>
<li>
<code>V</code> is not a <a href="#Types">named type</a>, <code>T</code> is
a type parameter, and <code>x</code> is assignable to each specific type of
<code>T</code>.
a type parameter, and <code>x</code> is assignable to each type in
<code>T</code>'s type set.
</li>
<li>
<code>V</code> is a type parameter and <code>T</code> is not a named type,
and values of each specific type of <code>V</code> are assignable
and values of each type in <code>V</code>'s type set are assignable
to <code>T</code>.
</li>
</ul>
@@ -2036,7 +1960,7 @@ to <code>T</code>.
<p>
A <a href="#Constants">constant</a> <code>x</code> is <i>representable</i>
by a value of type <code>T</code>,
where <code>T</code> is not a <a href="#Type_parameter_lists">type parameter</a>,
where <code>T</code> is not a <a href="#Type_parameter_declarations">type parameter</a>,
if one of the following conditions applies:
</p>
@@ -2061,9 +1985,9 @@ are representable by values of <code>T</code>'s component type (<code>float32</c
</ul>
<p>
If <code>T</code> is a type parameter with <a href="#Specific_types">specific types</a>,
If <code>T</code> is a type parameter,
<code>x</code> is representable by a value of type <code>T</code> if <code>x</code> is representable
by a value of each specific type of <code>T</code>.
by a value of each type in <code>T</code>'s type set.
</p>
<pre>
@@ -2176,6 +2100,7 @@ Blocks nest and influence <a href="#Declarations_and_scope">scoping</a>.
A <i>declaration</i> binds a non-<a href="#Blank_identifier">blank</a> identifier to a
<a href="#Constant_declarations">constant</a>,
<a href="#Type_declarations">type</a>,
<a href="#Type_parameter_declarations">type parameter</a>,
<a href="#Variable_declarations">variable</a>,
<a href="#Function_declarations">function</a>,
<a href="#Labeled_statements">label</a>, or
@@ -2220,13 +2145,13 @@ Go is lexically scoped using <a href="#Blocks">blocks</a>:
<li>The scope of an identifier denoting a method receiver, function parameter,
or result variable is the function body.</li>
<li>The scope of an identifier denoting a type parameter of a generic function
<li>The scope of an identifier denoting a type parameter of a function
or declared by a method receiver is the function body and all parameter lists of the
function.
</li>
<li>The scope of an identifier denoting a type parameter of a generic type
begins after the name of the generic type and ends at the end
<li>The scope of an identifier denoting a type parameter of a type
begins after the name of the type and ends at the end
of the TypeSpec.</li>
<li>The scope of a constant or variable identifier declared
@@ -2512,7 +2437,7 @@ type (
type TreeNode struct {
left, right *TreeNode
value *Comparable
value any
}
type Block interface {
@@ -2573,7 +2498,7 @@ func (tz TimeZone) String() string {
</pre>
<p>
If the type definition specifies <a href="#Type_parameter_lists">type parameters</a>,
If the type definition specifies <a href="#Type_parameter_declarations">type parameters</a>,
the type name denotes a <i>generic type</i>.
Generic types must be <a href="#Instantiations">instantiated</a> when they
are used.
@@ -2584,15 +2509,10 @@ type List[T any] struct {
next *List[T]
value T
}
type Tree[T constraints.Ordered] struct {
left, right *Tree[T]
value T
}
</pre>
<p>
The given type cannot be a type parameter in a type definition.
In a type definition the given type cannot be a type parameter.
</p>
<pre>
@@ -2604,8 +2524,8 @@ func f[T any]() {
</pre>
<p>
A generic type may also have methods associated with it. In this case,
the method receivers must declare the same number of type parameters as
A generic type may also have <a href="#Method_declarations">methods</a> associated with it.
In this case, the method receivers must declare the same number of type parameters as
present in the generic type definition.
</p>
@@ -2614,7 +2534,7 @@ present in the generic type definition.
func (l *List[T]) Len() int { … }
</pre>
<h3 id="Type_parameter_lists">Type parameter lists</h3>
<h3 id="Type_parameter_declarations">Type parameter declarations</h3>
<p>
A type parameter list declares the <i>type parameters</i> of a generic function or type declaration.
@@ -2653,22 +2573,22 @@ has a corresponding (meta-)type which is called its
<p>
A parsing ambiguity arises when the type parameter list for a generic type
declares a single type parameter with a type constraint of the form <code>*C</code>
or <code>(C)</code> where <code>C</code> is not a (possibly parenthesized)
<a href="#Types">type literal</a>:
declares a single type parameter <code>P</code> with a constraint <code>C</code>
such that the text <code>P C</code> forms a valid expression:
</p>
<pre>
type T[P *C] …
type T[P (C)] …
type T[P *C|Q] …
</pre>
<p>
In these rare cases, the type parameter declaration is indistinguishable from
the expressions <code>P*C</code> or <code>P(C)</code> and the type declaration
is parsed as an array type declaration.
To resolve the ambiguity, embed the constraint in an interface or use a trailing
comma:
In these rare cases, the type parameter list is indistinguishable from an
expression and the type declaration is parsed as an array type declaration.
To resolve the ambiguity, embed the constraint in an
<a href="#Interface_types">interface</a> or use a trailing comma:
</p>
<pre>
@@ -2682,6 +2602,11 @@ of a <a href="#Method_declarations">method declaration</a> associated
with a generic type.
</p>
<!--
This section needs to explain if and what kind of cycles are permitted
using type parameters in a type parameter list.
-->
<h4 id="Type_constraints">Type constraints</h4>
<p>
@@ -2701,10 +2626,10 @@ the enclosing <code>interface{ … }</code> may be omitted for convenience:
</p>
<pre>
[T *P] // = [T interface{*P}]
[T ~int] // = [T interface{~int}]
[T int|string] // = [T interface{int|string}]
type Constraint ~int // illegal: ~int is not inside a type parameter list
[T []P] // = [T interface{[]P}]
[T ~int] // = [T interface{~int}]
[T int|string] // = [T interface{int|string}]
type Constraint ~int // illegal: ~int is not inside a type parameter list
</pre>
<!--
@@ -2716,7 +2641,7 @@ other interfaces based on their type sets. But this should get us going for now.
<p>
The <a href="#Predeclared_identifiers">predeclared</a>
<a href="#Interface_types">interface type</a> <code>comparable</code>
denotes the set of all concrete (non-interface) types that are
denotes the set of all non-interface types that are
<a href="#Comparison_operators">comparable</a>. Specifically,
a type <code>T</code> implements <code>comparable</code> if:
</p>
@@ -2897,14 +2822,14 @@ func IndexRune(s string, r rune) int {
</pre>
<p>
If the function declaration specifies <a href="#Type_parameter_lists">type parameters</a>,
If the function declaration specifies <a href="#Type_parameter_declarations">type parameters</a>,
the function name denotes a <i>generic function</i>.
Generic functions must be <a href="#Instantiations">instantiated</a> when they
are used.
A generic function must be <a href="#Instantiations">instantiated</a> before it can be
called or used as a value.
</p>
<pre>
func min[T constraints.Ordered](x, y T) T {
func min[T ~int|~float64](x, y T) T {
if x &lt; y {
return x
}
@@ -2963,7 +2888,7 @@ the non-blank method and field names must be distinct.
</p>
<p>
Given defined type <code>Point</code>, the declarations
Given defined type <code>Point</code> the declarations
</p>
<pre>
@@ -2987,13 +2912,10 @@ to the base type <code>Point</code>.
If the receiver base type is a <a href="#Type_declarations">generic type</a>, the
receiver specification must declare corresponding type parameters for the method
to use. This makes the receiver type parameters available to the method.
</p>
<p>
Syntactically, this type parameter declaration looks like an
<a href="#Instantiations">instantiation</a> of the receiver base type, except that
the type arguments are the type parameters being declared, one for each type parameter
of the receiver base type.
<a href="#Instantiations">instantiation</a> of the receiver base type: the type
arguments must be identifiers denoting the type parameters being declared, one
for each type parameter of the receiver base type.
The type parameter names do not need to match their corresponding parameter names in the
receiver base type definition, and all non-blank parameter names must be unique in the
receiver parameter section and the method signature.
@@ -3007,8 +2929,8 @@ type Pair[A, B any] struct {
b B
}
func (p Pair[A, B]) Swap() Pair[B, A] { return Pair[B, A]{p.b, p.a} }
func (p Pair[First, _]) First() First { return p.a }
func (p Pair[A, B]) Swap() Pair[B, A] { … } // receiver declares A, B
func (p Pair[First, _]) First() First { … } // receiver declares First, corresponds to A in Pair
</pre>
<h2 id="Expressions">Expressions</h2>
@@ -3048,6 +2970,14 @@ The <a href="#Blank_identifier">blank identifier</a> may appear as an
operand only on the left-hand side of an <a href="#Assignments">assignment</a>.
</p>
<p>
Implementation restriction: A compiler need not report an error if an operand's
type is a <a href="#Type_parameter_declarations">type parameter</a> with an empty
<a href="#Interface_types">type set</a>. Functions with such type parameters
cannot be <a href="#Instantiations">instantiated</a>; any attempt will lead
to an error at the instantiation site.
</p>
<h3 id="Qualified_identifiers">Qualified identifiers</h3>
<p>
@@ -3354,10 +3284,6 @@ f.p[i].x()
<h3 id="Selectors">Selectors</h3>
<p><b>
[This section is missing rules for x.f where x's type is a type parameter and f is a field.]
</b></p>
<p>
For a <a href="#Primary_expressions">primary expression</a> <code>x</code>
that is not a <a href="#Package_clause">package name</a>, the
@@ -3758,7 +3684,7 @@ The following rules apply:
</p>
<p>
If <code>a</code> is not a map:
If <code>a</code> is neither a map nor a type parameter:
</p>
<ul>
<li>the index <code>x</code> must be an untyped constant or its
@@ -3827,23 +3753,22 @@ For <code>a</code> of <a href="#Map_types">map type</a> <code>M</code>:
</ul>
<p>
For <code>a</code> of <a href="#Type_parameter_lists">type parameter type</a> <code>P</code>:
For <code>a</code> of <a href="#Type_parameter_declarations">type parameter type</a> <code>P</code>:
</p>
<ul>
<li><code>P</code> must have <a href="#Specific_types">specific types</a>.</li>
<li>The index expression <code>a[x]</code> must be valid for values
of all specific types of <code>P</code>.</li>
<li>The element types of all specific types of <code>P</code> must be identical.
of all types in <code>P</code>'s type set.</li>
<li>The element types of all types in <code>P</code>'s type set must be identical.
In this context, the element type of a string type is <code>byte</code>.</li>
<li>If there is a map type among the specific types of <code>P</code>,
all specific types must be map types, and the respective key types
<li>If there is a map type in the type set of <code>P</code>,
all types in that type set must be map types, and the respective key types
must be all identical.</li>
<li><code>a[x]</code> is the array, slice, or string element at index <code>x</code>,
or the map element with key <code>x</code> of the type argument
that <code>P</code> is instantiated with, and the type of <code>a[x]</code> is
the type of the (identical) element types.</li>
<li><code>a[x]</code> may not be assigned to if the specific types of <code>P</code>
include string types.
<li><code>a[x]</code> may not be assigned to if <code>P</code>'s type set
includes string types.
</ul>
<p>
@@ -4021,7 +3946,7 @@ If the indices are out of range at run time, a <a href="#Run_time_panics">run-ti
<p>
For an expression <code>x</code> of <a href="#Interface_types">interface type</a>,
but not a <a href="#Type_parameter_lists">type parameter</a>, and a type <code>T</code>,
but not a <a href="#Type_parameter_declarations">type parameter</a>, and a type <code>T</code>,
the primary expression
</p>
@@ -4236,7 +4161,7 @@ with the same underlying array.
<p>
A generic function or type is <i>instantiated</i> by substituting <i>type arguments</i>
for the type parameters.
Instantiation proceeds in two phases:
Instantiation proceeds in two steps:
</p>
<ol>
@@ -4249,7 +4174,7 @@ including the type parameter list itself and any types in that list.
<li>
After substitution, each type argument must <a href="#Interface_types">implement</a>
the <a href="#Type_parameter_lists">constraint</a> (instantiated, if necessary)
the <a href="#Type_parameter_declarations">constraint</a> (instantiated, if necessary)
of the corresponding type parameter. Otherwise instantiation fails.
</li>
</ol>
@@ -4262,55 +4187,57 @@ instantiating a function produces a new non-generic function.
<pre>
type parameter list type arguments after substitution
[P any] int [int any]
[S ~[]E, E any] []int, int [[]int ~[]int, int any]
[P io.Writer] string [string io.Writer] // illegal: string doesn't implement io.Writer
[P any] int int implements any
[S ~[]E, E any] []int, int []int implements ~[]int, int implements any
[P io.Writer] string illegal: string doesn't implement io.Writer
</pre>
<p>
Type arguments may be provided explicitly, or they may be partially or completely
<a href="#Type_inference">inferred</a>.
A partially provided type argument list cannot be empty; there must be at least the
first argument.
</p>
<pre>
type T[P1 ~int, P2 ~[]P1] struct{ … }
T[] // illegal: at least the first type argument must be present, even if it could be inferred
T[int] // argument for P1 explicitly provided, argument for P2 inferred
T[int, []int] // both arguments explicitly provided
</pre>
<p>
A partial type argument list specifies a prefix of the full list of type arguments, leaving
the remaining arguments to be inferred. Loosely speaking, type arguments may be omitted from
"right to left".
</p>
<p>
Generic types, and generic functions that are not <a href="#Calls">called</a>,
require a type argument list for instantiation; if the list is partial, all
For a generic function, type arguments may be provided explicitly, or they
may be partially or completely <a href="#Type_inference">inferred</a>.
A generic function that is is <i>not</i> <a href="#Calls">called</a> requires a
type argument list for instantiation; if the list is partial, all
remaining type arguments must be inferrable.
Calls to generic functions may provide a (possibly partial) type
A generic function that is called may provide a (possibly partial) type
argument list, or may omit it entirely if the omitted type arguments are
inferrable from the ordinary (non-type) function arguments.
</p>
<pre>
func min[T constraints.Ordered](x, y T) T { … }
func min[T ~int|~float64](x, y T) T { … }
f := min // illegal: min must be instantiated when used without being called
f := min // illegal: min must be instantiated with type arguments when used without being called
minInt := min[int] // minInt has type func(x, y int) int
a := minInt(2, 3) // a has value 2 of type int
b := min[float64](2.0, 3) // b has value 2.0 of type float64
c := min(b, -1) // c has value -1.0 of type float64
</pre>
<p>
A partial type argument list cannot be empty; at least the first argument must be present.
The list is a prefix of the full list of type arguments, leaving the remaining arguments
to be inferred. Loosely speaking, type arguments may be omitted from "right to left".
</p>
<pre>
func apply[S ~[]E, E any](s S, f(E) E) S { … }
f0 := apply[] // illegal: type argument list cannot be empty
f1 := apply[[]int] // type argument for S explicitly provided, type argument for E inferred
f2 := apply[[]string, string] // both type arguments explicitly provided
var bytes []byte
r := apply(bytes, func(byte) byte { … }) // both type arguments inferred from the function arguments
</pre>
<p>
For a generic type, all type arguments must always be provided explicitly.
</p>
<h3 id="Type_inference">Type inference</h3>
<p>
Missing type arguments may be <i>inferred</i> by a series of steps, described below.
Missing function type arguments may be <i>inferred</i> by a series of steps, described below.
Each step attempts to use known information to infer additional type arguments.
Type inference stops as soon as all type arguments are known.
After type inference is complete, it is still necessary to substitute all type arguments
@@ -4326,7 +4253,7 @@ Type inference is based on
<ul>
<li>
a <a href="#Type_parameter_lists">type parameter list</a>
a <a href="#Type_parameter_declarations">type parameter list</a>
</li>
<li>
a substitution map <i>M</i> initialized with the known type arguments, if any
@@ -4491,9 +4418,8 @@ unresolved type parameters left.
</p>
<p>
Function argument type inference can be used when the function has ordinary parameters
whose types are defined using the function's type parameters. Inference happens in two
separate phases; each phase operates on a specific list of (parameter, argument) pairs:
Inference happens in two separate phases; each phase operates on a specific list of
(parameter, argument) pairs:
</p>
<ol>
@@ -4550,7 +4476,7 @@ Example:
</p>
<pre>
func min[T constraints.Ordered](x, y T) T
func min[T ~int|~float64](x, y T) T
var x int
min(x, 2.0) // T is int, inferred from typed argument x; 2.0 is assignable to int
@@ -4841,9 +4767,8 @@ The bitwise logical and shift operators apply to integers only.
</pre>
<p>
Excluding shifts, if the operand type is a <a href="#Type_parameter_lists">type parameter</a>,
it must have <a href="#Specific_types">specific types</a>, and the operator must
apply to each specific type.
If the operand type is a <a href="#Type_parameter_declarations">type parameter</a>,
the operator must apply to each type in that type set.
The operands are represented as values of the type argument that the type parameter
is <a href="#Instantiations">instantiated</a> with, and the operation is computed
with the precision of that type argument. For example, given the function:
@@ -4866,11 +4791,6 @@ are computed with <code>float32</code> or <code>float64</code> precision,
respectively, depending on the type argument for <code>F</code>.
</p>
<p>
For shifts, the <a href="#Core_types">core type</a> of both operands must be
an integer.
</p>
<h4 id="Integer_operators">Integer operators</h4>
<p>
@@ -5296,7 +5216,7 @@ as for non-constant <code>x</code>.
</p>
<p>
Converting a constant to a type that is not a <a href="#Type_parameter_lists">type parameter</a>
Converting a constant to a type that is not a <a href="#Type_parameter_declarations">type parameter</a>
yields a typed constant.
</p>
@@ -5351,7 +5271,7 @@ in any of these cases:
<li>
ignoring struct tags (see below),
<code>x</code>'s type and <code>T</code> are not
<a href="#Type_parameter_lists">type parameters</a> but have
<a href="#Type_parameter_declarations">type parameters</a> but have
<a href="#Type_identity">identical</a> <a href="#Types">underlying types</a>.
</li>
<li>
@@ -5383,23 +5303,23 @@ in any of these cases:
<p>
Additionally, if <code>T</code> or <code>x</code>'s type <code>V</code> are type
parameters with <a href="#Specific_types">specific types</a>, <code>x</code>
parameters, <code>x</code>
can also be converted to type <code>T</code> if one of the following conditions applies:
</p>
<ul>
<li>
Both <code>V</code> and <code>T</code> are type parameters and a value of each
specific type of <code>V</code> can be converted to each specific type
of <code>T</code>.
type in <code>V</code>'s type set can be converted to each type in <code>T</code>'s
type set.
</li>
<li>
Only <code>V</code> is a type parameter and a value of each
specific type of <code>V</code> can be converted to <code>T</code>.
type in <code>V</code>'s type set can be converted to <code>T</code>.
</li>
<li>
Only <code>T</code> is a type parameter and <code>x</code> can be converted to each
specific type of <code>T</code>.
type in <code>T</code>'s type set.
</li>
</ul>
@@ -6270,7 +6190,7 @@ switch x.(type) {
Cases then match actual types <code>T</code> against the dynamic type of the
expression <code>x</code>. As with type assertions, <code>x</code> must be of
<a href="#Interface_types">interface type</a>, but not a
<a href="#Type_parameter_lists">type parameter</a>, and each non-interface type
<a href="#Type_parameter_declarations">type parameter</a>, and each non-interface type
<code>T</code> listed in a case must implement the type of <code>x</code>.
The types listed in the cases of a type switch must all be
<a href="#Type_identity">different</a>.
@@ -6352,7 +6272,7 @@ if v == nil {
</pre>
<p>
A <a href="#Type_parameter_lists">type parameter</a> or a <a href="#Type_declarations">generic type</a>
A <a href="#Type_parameter_declarations">type parameter</a> or a <a href="#Type_declarations">generic type</a>
may be used as a type in a case. If upon <a href="#Instantiations">instantiation</a> that type turns
out to duplicate another entry in the switch, the first matching case is chosen.
</p>
@@ -7093,10 +7013,9 @@ cap(s) [n]T, *[n]T array length (== n)
</pre>
<p>
If the argument type is a <a href="#Type_parameter_lists">type parameter</a> <code>P</code>,
<code>P</code> must have <a href="#Specific_types">specific types</a>, and
If the argument type is a <a href="#Type_parameter_declarations">type parameter</a> <code>P</code>,
the call <code>len(e)</code> (or <code>cap(e)</code> respectively) must be valid for
each specific type of <code>P</code>.
each type in <code>P</code>'s type set.
The result is the length (or capacity, respectively) of the argument whose type
corresponds to the type argument with which <code>P</code> was
<a href="#Instantiations">instantiated</a>.
@@ -7197,8 +7116,9 @@ make(T, n) channel buffered channel of type T, buffer size n
<p>
Each of the size arguments <code>n</code> and <code>m</code> must be of <a href="#Numeric_types">integer type</a>
or an untyped <a href="#Constants">constant</a>.
Each of the size arguments <code>n</code> and <code>m</code> must be of <a href="#Numeric_types">integer type</a>,
have a <a href="#Interface_types">type set</a> containing only integer types,
or be an untyped <a href="#Constants">constant</a>.
A constant size argument must be non-negative and <a href="#Representability">representable</a>
by a value of type <code>int</code>; if it is an untyped constant it is given type <code>int</code>.
If both <code>n</code> and <code>m</code> are provided and are constant, then
@@ -7235,9 +7155,9 @@ by the arguments overlaps.
<p>
The <a href="#Function_types">variadic</a> function <code>append</code>
appends zero or more values <code>x</code> to a slice <code>s</code>
and returns the resulting slice.
and returns the resulting slice of the same type as <code>s</code>.
The <a href="#Core_types">core type</a> of <code>s</code> must be a slice
of the form <code>[]E</code>.
of type <code>[]E</code>.
The values <code>x</code> are passed to a parameter of type <code>...E</code>
and the respective <a href="#Passing_arguments_to_..._parameters">parameter
passing rules</a> apply.
@@ -7247,7 +7167,7 @@ followed by <code>...</code>. This form appends the bytes of the string.
</p>
<pre class="grammar">
append(s S, x ...E) S // E is the element type of the core type of S
append(s S, x ...E) S // core type of S is []E
</pre>
<p>
@@ -7317,9 +7237,8 @@ delete(m, k) // remove element m[k] from map m
</pre>
<p>
If the type of <code>m</code> is a <a href="#Type_parameter_lists">type parameter</a>,
it must have <a href="#Specific_types">specific types</a>, all specific types
must be maps, and they must all have identical key types.
If the type of <code>m</code> is a <a href="#Type_parameter_declarations">type parameter</a>,
all types in that type set must be maps, and they must all have identical key types.
</p>
<p>
@@ -7330,10 +7249,6 @@ does not exist, <code>delete</code> is a no-op.
<h3 id="Complex_numbers">Manipulating complex numbers</h3>
<p><b>
[We don't support generic arguments for these built-ins for Go 1.18.]
</b></p>
<p>
Three functions assemble and disassemble complex numbers.
The built-in function <code>complex</code> constructs a complex
@@ -7396,6 +7311,10 @@ const c = imag(b) // untyped constant -1.4
_ = imag(3 &lt;&lt; s) // illegal: 3 assumes complex type, cannot shift
</pre>
<p>
Arguments of type parameter type are not permitted.
</p>
<h3 id="Handling_panics">Handling panics</h3>
<p> Two built-in functions, <code>panic</code> and <code>recover</code>,
@@ -8004,11 +7923,17 @@ func Add(ptr Pointer, len IntegerType) Pointer
func Slice(ptr *ArbitraryType, len IntegerType) []ArbitraryType
</pre>
<!--
These conversions also apply to type parameters with suitable core types.
Determine if we can simply use core type insted of underlying type here,
of if the general conversion rules take care of this.
-->
<p>
A <code>Pointer</code> is a <a href="#Pointer_types">pointer type</a> but a <code>Pointer</code>
value may not be <a href="#Address_operators">dereferenced</a>.
Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be converted to
a type of underlying type <code>Pointer</code> and vice versa.
Any pointer or value of <a href="#Types">underlying type</a> <code>uintptr</code> can be
<a href="#Conversions">converted</a> to a type of underlying type <code>Pointer</code> and vice versa.
The effect of converting between <code>Pointer</code> and <code>uintptr</code> is implementation-defined.
</p>
@@ -8055,7 +7980,8 @@ uintptr(unsafe.Pointer(&amp;x)) % unsafe.Alignof(x) == 0
<p>
A (variable of) type <code>T</code> has <i>variable size</i> if <code>T</code>
is a type parameter, or if it is an array or struct type containing elements
is a <a href="#Type_parameter_declarations">type parameter</a>, or if it is an
array or struct type containing elements
or fields of variable size. Otherwise the size is <i>constant</i>.
Calls to <code>Alignof</code>, <code>Offsetof</code>, and <code>Sizeof</code>
are compile-time <a href="#Constant_expressions">constant expressions</a> of

View File

@@ -283,6 +283,12 @@ func TestMethod2(t *testing.T) {
run(t, "./method2.exe")
}
func TestMethod3(t *testing.T) {
goCmd(t, "build", "-buildmode=plugin", "-o", "method3.so", "./method3/plugin.go")
goCmd(t, "build", "-o", "method3.exe", "./method3/main.go")
run(t, "./method3.exe")
}
func TestIssue44956(t *testing.T) {
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p1.so", "./issue44956/plugin1.go")
goCmd(t, "build", "-buildmode=plugin", "-o", "issue44956p2.so", "./issue44956/plugin2.go")

View File

@@ -0,0 +1,32 @@
// 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.
// An unexported method can be reachable from the plugin via interface
// when a package is shared. So it need to be live.
package main
import (
"plugin"
"testplugin/method3/p"
)
var i p.I
func main() {
pl, err := plugin.Open("method3.so")
if err != nil {
panic(err)
}
f, err := pl.Lookup("F")
if err != nil {
panic(err)
}
f.(func())()
i = p.T(123)
}

View File

@@ -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 T int
func (T) m() { println("m") }
type I interface { m() }
func F() {
i.m()
}
var i I = T(123)

View File

@@ -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 main
import "testplugin/method3/p"
func main() {}
func F() { p.F() }

View File

@@ -909,7 +909,11 @@ func containsRune(s string, r rune) bool {
// Trim returns a subslice of s by slicing off all leading and
// trailing UTF-8-encoded code points contained in cutset.
func Trim(s []byte, cutset string) []byte {
if len(s) == 0 || cutset == "" {
if len(s) == 0 {
// This is what we've historically done.
return nil
}
if cutset == "" {
return s
}
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
@@ -924,7 +928,11 @@ func Trim(s []byte, cutset string) []byte {
// TrimLeft returns a subslice of s by slicing off all leading
// UTF-8-encoded code points contained in cutset.
func TrimLeft(s []byte, cutset string) []byte {
if len(s) == 0 || cutset == "" {
if len(s) == 0 {
// This is what we've historically done.
return nil
}
if cutset == "" {
return s
}
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
@@ -940,6 +948,10 @@ func trimLeftByte(s []byte, c byte) []byte {
for len(s) > 0 && s[0] == c {
s = s[1:]
}
if len(s) == 0 {
// This is what we've historically done.
return nil
}
return s
}
@@ -950,6 +962,10 @@ func trimLeftASCII(s []byte, as *asciiSet) []byte {
}
s = s[1:]
}
if len(s) == 0 {
// This is what we've historically done.
return nil
}
return s
}
@@ -964,6 +980,10 @@ func trimLeftUnicode(s []byte, cutset string) []byte {
}
s = s[n:]
}
if len(s) == 0 {
// This is what we've historically done.
return nil
}
return s
}

View File

@@ -1278,24 +1278,69 @@ var trimTests = []TrimTest{
{"TrimSuffix", "aabb", "b", "aab"},
}
type TrimNilTest struct {
f string
in []byte
arg string
out []byte
}
var trimNilTests = []TrimNilTest{
{"Trim", nil, "", nil},
{"Trim", []byte{}, "", nil},
{"Trim", []byte{'a'}, "a", nil},
{"Trim", []byte{'a', 'a'}, "a", nil},
{"Trim", []byte{'a'}, "ab", nil},
{"Trim", []byte{'a', 'b'}, "ab", nil},
{"Trim", []byte("☺"), "☺", nil},
{"TrimLeft", nil, "", nil},
{"TrimLeft", []byte{}, "", nil},
{"TrimLeft", []byte{'a'}, "a", nil},
{"TrimLeft", []byte{'a', 'a'}, "a", nil},
{"TrimLeft", []byte{'a'}, "ab", nil},
{"TrimLeft", []byte{'a', 'b'}, "ab", nil},
{"TrimLeft", []byte("☺"), "☺", nil},
{"TrimRight", nil, "", nil},
{"TrimRight", []byte{}, "", []byte{}},
{"TrimRight", []byte{'a'}, "a", []byte{}},
{"TrimRight", []byte{'a', 'a'}, "a", []byte{}},
{"TrimRight", []byte{'a'}, "ab", []byte{}},
{"TrimRight", []byte{'a', 'b'}, "ab", []byte{}},
{"TrimRight", []byte("☺"), "☺", []byte{}},
{"TrimPrefix", nil, "", nil},
{"TrimPrefix", []byte{}, "", []byte{}},
{"TrimPrefix", []byte{'a'}, "a", []byte{}},
{"TrimPrefix", []byte("☺"), "☺", []byte{}},
{"TrimSuffix", nil, "", nil},
{"TrimSuffix", []byte{}, "", []byte{}},
{"TrimSuffix", []byte{'a'}, "a", []byte{}},
{"TrimSuffix", []byte("☺"), "☺", []byte{}},
}
func TestTrim(t *testing.T) {
for _, tc := range trimTests {
name := tc.f
var f func([]byte, string) []byte
var fb func([]byte, []byte) []byte
toFn := func(name string) (func([]byte, string) []byte, func([]byte, []byte) []byte) {
switch name {
case "Trim":
f = Trim
return Trim, nil
case "TrimLeft":
f = TrimLeft
return TrimLeft, nil
case "TrimRight":
f = TrimRight
return TrimRight, nil
case "TrimPrefix":
fb = TrimPrefix
return nil, TrimPrefix
case "TrimSuffix":
fb = TrimSuffix
return nil, TrimSuffix
default:
t.Errorf("Undefined trim function %s", name)
return nil, nil
}
}
for _, tc := range trimTests {
name := tc.f
f, fb := toFn(name)
if f == nil && fb == nil {
continue
}
var actual string
if f != nil {
@@ -1307,6 +1352,36 @@ func TestTrim(t *testing.T) {
t.Errorf("%s(%q, %q) = %q; want %q", name, tc.in, tc.arg, actual, tc.out)
}
}
for _, tc := range trimNilTests {
name := tc.f
f, fb := toFn(name)
if f == nil && fb == nil {
continue
}
var actual []byte
if f != nil {
actual = f(tc.in, tc.arg)
} else {
actual = fb(tc.in, []byte(tc.arg))
}
report := func(s []byte) string {
if s == nil {
return "nil"
} else {
return fmt.Sprintf("%q", s)
}
}
if len(actual) != 0 {
t.Errorf("%s(%s, %q) returned non-empty value", name, report(tc.in), tc.arg)
} else {
actualNil := actual == nil
outNil := tc.out == nil
if actualNil != outNil {
t.Errorf("%s(%s, %q) got nil %t; want nil %t", name, report(tc.in), tc.arg, actualNil, outNil)
}
}
}
}
type predicate struct {

View File

@@ -163,4 +163,5 @@ func markHiddenClosureDead(n ir.Node) {
if clo.Func.IsHiddenClosure() {
clo.Func.SetIsDeadcodeClosure(true)
}
ir.VisitList(clo.Func.Body, markHiddenClosureDead)
}

View File

@@ -53,7 +53,7 @@ const (
)
type ident struct {
pkg string
pkg *types2.Package
name string
}
@@ -402,7 +402,7 @@ func (r *importReader) obj(name string) {
t := types2.NewTypeParam(tn, nil)
// To handle recursive references to the typeparam within its
// bound, save the partial type in tparamIndex before reading the bounds.
id := ident{r.currPkg.Name(), name}
id := ident{r.currPkg, name}
r.p.tparamIndex[id] = t
var implicit bool
@@ -687,7 +687,7 @@ func (r *importReader) doType(base *types2.Named) types2.Type {
errorf("unexpected type param type")
}
pkg, name := r.qualifiedIdent()
id := ident{pkg.Name(), name}
id := ident{pkg, name}
if t, ok := r.p.tparamIndex[id]; ok {
// We're already in the process of importing this typeparam.
return t

View File

@@ -362,7 +362,7 @@ func NewSendStmt(pos src.XPos, ch, value Node) *SendStmt {
return n
}
// A SwitchStmt is a switch statement: switch Init; Expr { Cases }.
// A SwitchStmt is a switch statement: switch Init; Tag { Cases }.
type SwitchStmt struct {
miniStmt
Tag Node

View File

@@ -114,11 +114,11 @@ func (g *irgen) funcDecl(out *ir.Nodes, decl *syntax.FuncDecl) {
// the Fields to represent the receiver's method set.
if recv := fn.Type().Recv(); recv != nil {
typ := types.ReceiverBaseType(recv.Type)
if typ.OrigSym() != nil {
if orig := typ.OrigType(); orig != nil {
// For a generic method, we mark the methods on the
// base generic type, since those are the methods
// that will be stenciled.
typ = typ.OrigSym().Def.Type()
typ = orig
}
meth := typecheck.Lookdot1(fn, typecheck.Lookup(decl.Name.Value), typ, typ.Methods(), 0)
meth.SetNointerface(true)

View File

@@ -193,8 +193,7 @@ func (g *genInst) scanForGenCalls(decl ir.Node) {
targs := deref(meth.Type().Recv().Type).RParams()
t := meth.X.Type()
baseSym := deref(t).OrigSym()
baseType := baseSym.Def.(*ir.Name).Type()
baseType := deref(t).OrigType()
var gf *ir.Name
for _, m := range baseType.Methods().Slice() {
if meth.Sel == m.Sym {
@@ -348,7 +347,7 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
// actually generic, so no need to build a closure.
return x
}
baseType := recv.OrigSym().Def.Type()
baseType := recv.OrigType()
var gf *ir.Name
for _, m := range baseType.Methods().Slice() {
if se.Sel == m.Sym {
@@ -543,8 +542,7 @@ func (g *genInst) instantiateMethods() {
typecheck.NeedRuntimeType(typ)
// Lookup the method on the base generic type, since methods may
// not be set on imported instantiated types.
baseSym := typ.OrigSym()
baseType := baseSym.Def.(*ir.Name).Type()
baseType := typ.OrigType()
for j, _ := range typ.Methods().Slice() {
if baseType.Methods().Slice()[j].Nointerface() {
typ.Methods().Slice()[j].SetNointerface(true)
@@ -644,7 +642,7 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe
if recvType.IsFullyInstantiated() {
// Get the type of the base generic type, so we get
// its original typeparams.
recvType = recvType.OrigSym().Def.(*ir.Name).Type()
recvType = recvType.OrigType()
}
tparams = recvType.RParams()
} else {
@@ -898,7 +896,7 @@ func getDictionaryType(info *instInfo, dictParam *ir.Name, pos src.XPos, i int)
base.Fatalf(fmt.Sprintf("bad dict index %d", i))
}
r := getDictionaryEntry(pos, info.dictParam, i, info.dictInfo.startSubDict)
r := getDictionaryEntry(pos, dictParam, i, info.dictInfo.startSubDict)
// change type of retrieved dictionary entry to *byte, which is the
// standard typing of a *runtime._type in the compiler
typed(types.Types[types.TUINT8].PtrTo(), r)
@@ -1179,6 +1177,26 @@ func (subst *subster) node(n ir.Node) ir.Node {
subst.g.newInsts = append(subst.g.newInsts, m.(*ir.ClosureExpr).Func)
m.(*ir.ClosureExpr).SetInit(subst.list(x.Init()))
case ir.OSWITCH:
m := m.(*ir.SwitchStmt)
if m.Tag != nil && m.Tag.Op() == ir.OTYPESW {
break // Nothing to do here for type switches.
}
if m.Tag != nil && !m.Tag.Type().IsInterface() && m.Tag.Type().HasShape() {
// To implement a switch on a value that is or has a type parameter, we first convert
// that thing we're switching on to an interface{}.
m.Tag = assignconvfn(m.Tag, types.Types[types.TINTER])
}
for _, c := range m.Cases {
for i, x := range c.List {
// If we have a case that is or has a type parameter, convert that case
// to an interface{}.
if !x.Type().IsInterface() && x.Type().HasShape() {
c.List[i] = assignconvfn(x, types.Types[types.TINTER])
}
}
}
}
return m
}
@@ -1608,7 +1626,7 @@ func (g *genInst) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool
// instantiated type, so we need a
// sub-dictionary.
targs := recvType.RParams()
genRecvType := recvType.OrigSym().Def.Type()
genRecvType := recvType.OrigType()
nameNode = typecheck.Lookdot1(call.X, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
sym = g.getDictionarySym(nameNode, targs, true)
} else {
@@ -1687,7 +1705,7 @@ func (g *genInst) getSymForMethodCall(se *ir.SelectorExpr, subst *typecheck.Tsub
// also give the receiver type. For method expressions with embedded types, we
// need to look at the type of the selection to get the final receiver type.
recvType := deref(se.Selection.Type.Recv().Type)
genRecvType := recvType.OrigSym().Def.Type()
genRecvType := recvType.OrigType()
nameNode := typecheck.Lookdot1(se, se.Sel, genRecvType, genRecvType.Methods(), 1).Nname.(*ir.Name)
subtargs := recvType.RParams()
s2targs := make([]*types.Type, len(subtargs))

View File

@@ -242,7 +242,7 @@ func transformCompare(n *ir.BinaryExpr) {
aop, _ := typecheck.Assignop(rt, lt)
if aop != ir.OXXX {
types.CalcSize(rt)
if rt.HasTParam() || rt.IsInterface() == lt.IsInterface() || rt.Size() >= 1<<16 {
if rt.HasShape() || rt.IsInterface() == lt.IsInterface() || rt.Size() >= 1<<16 {
r = ir.NewConvExpr(base.Pos, aop, lt, r)
r.SetTypecheck(1)
}

View File

@@ -166,7 +166,7 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
//fmt.Printf("Saw new type %v %v\n", instName, ntyp.HasTParam())
// Save the symbol for the base generic type.
ntyp.SetOrigSym(g.pkg(typ.Obj().Pkg()).Lookup(typ.Obj().Name()))
ntyp.SetOrigType(base.Type())
ntyp.SetUnderlying(g.typ1(typ.Underlying()))
if typ.NumMethods() != 0 {
// Save a delayed call to g.fillinMethods() (once

View File

@@ -1430,7 +1430,7 @@ func WriteBasicTypes() {
type typeAndStr struct {
t *types.Type
short string // "short" here means NameString
short string // "short" here means TypeSymName
regular string
}
@@ -1921,7 +1921,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
// Target method uses shaped names.
targs2 := make([]*types.Type, len(targs))
origRParams := deref(orig).OrigSym().Def.(*ir.Name).Type().RParams()
origRParams := deref(orig).OrigType().RParams()
for i, t := range targs {
targs2[i] = typecheck.Shapify(t, i, origRParams[i])
}

View File

@@ -66,9 +66,9 @@ func (p *crawler) markObject(n *ir.Name) {
// inline bodies may be needed. For instantiated generic types, it visits the base
// generic type, which has the relevant methods.
func (p *crawler) markType(t *types.Type) {
if t.OrigSym() != nil {
if orig := t.OrigType(); orig != nil {
// Convert to the base generic type.
t = t.OrigSym().Def.Type()
t = orig
}
if p.marked[t] {
return
@@ -154,9 +154,9 @@ func (p *crawler) markEmbed(t *types.Type) {
t = t.Elem()
}
if t.OrigSym() != nil {
if orig := t.OrigType(); orig != nil {
// Convert to the base generic type.
t = t.OrigSym().Def.Type()
t = orig
}
if p.embedded[t] {
@@ -194,9 +194,9 @@ func (p *crawler) markGeneric(t *types.Type) {
if t.IsPtr() {
t = t.Elem()
}
if t.OrigSym() != nil {
if orig := t.OrigType(); orig != nil {
// Convert to the base generic type.
t = t.OrigSym().Def.Type()
t = orig
}
if p.generic[t] {
return
@@ -229,7 +229,7 @@ func (p *crawler) checkForFullyInst(t *types.Type) {
// them available for import, and so will not need
// another round of method and dictionary
// instantiation after inlining.
baseType := t.OrigSym().Def.(*ir.Name).Type()
baseType := t.OrigType()
shapes := make([]*types.Type, len(t.RParams()))
for i, t1 := range t.RParams() {
shapes[i] = Shapify(t1, i, baseType.RParams()[i])

View File

@@ -953,7 +953,7 @@ func (w *exportWriter) startType(k itag) {
func (w *exportWriter) doTyp(t *types.Type) {
s := t.Sym()
if s != nil && t.OrigSym() != nil {
if s != nil && t.OrigType() != nil {
assert(base.Flag.G > 0)
// This is an instantiated type - could be a re-instantiation like
// Value[T2] or a full instantiation like Value[int].
@@ -970,7 +970,7 @@ func (w *exportWriter) doTyp(t *types.Type) {
// types or existing typeparams from the function/method header.
w.typeList(t.RParams())
// Export a reference to the base type.
baseType := t.OrigSym().Def.(*ir.Name).Type()
baseType := t.OrigType()
w.typ(baseType)
return
}
@@ -1851,7 +1851,10 @@ func (w *exportWriter) expr(n ir.Node) {
n := n.(*ir.ClosureExpr)
w.op(ir.OCLOSURE)
w.pos(n.Pos())
old := w.currPkg
w.setPkg(n.Type().Pkg(), true)
w.signature(n.Type())
w.setPkg(old, true)
// Write out id for the Outer of each conditional variable. The
// conditional variable itself for this closure will be re-created

View File

@@ -761,7 +761,7 @@ func (p *iimporter) typAt(off uint64) *types.Type {
// No need to calc sizes for re-instantiated generic types, and
// they are not necessarily resolved until the top-level type is
// defined (because of recursive types).
if t.OrigSym() == nil || !t.HasTParam() {
if t.OrigType() == nil || !t.HasTParam() {
types.CheckSize(t)
}
p.typCache[off] = t
@@ -1374,7 +1374,9 @@ func (r *importReader) node() ir.Node {
case ir.OCLOSURE:
//println("Importing CLOSURE")
pos := r.pos()
r.setPkg()
typ := r.signature(nil, nil)
r.setPkg()
// All the remaining code below is similar to (*noder).funcLit(), but
// with Dcls and ClosureVars lists already set up
@@ -1480,7 +1482,7 @@ func (r *importReader) node() ir.Node {
} else {
genType := types.ReceiverBaseType(n1.X.Type())
if genType.IsInstantiatedGeneric() {
genType = genType.OrigSym().Def.Type()
genType = genType.OrigType()
}
m = Lookdot1(n1, sel, genType, genType.Methods(), 1)
}
@@ -1911,7 +1913,7 @@ func Instantiate(pos src.XPos, baseType *types.Type, targs []*types.Type) *types
t := NewIncompleteNamedType(baseType.Pos(), instSym)
t.SetRParams(targs)
t.SetOrigSym(baseSym)
t.SetOrigType(baseType)
// baseType may still be TFORW or its methods may not be fully filled in
// (since we are in the middle of importing it). So, delay call to
@@ -1936,7 +1938,7 @@ func resumeDoInst() {
for len(deferredInstStack) > 0 {
t := deferredInstStack[0]
deferredInstStack = deferredInstStack[1:]
substInstType(t, t.OrigSym().Def.(*ir.Name).Type(), t.RParams())
substInstType(t, t.OrigType(), t.RParams())
}
}
deferInst--
@@ -1948,7 +1950,7 @@ func resumeDoInst() {
// instantiations of mutually recursive types.
func doInst(t *types.Type) *types.Type {
assert(t.Kind() == types.TFORW)
return Instantiate(t.Pos(), t.OrigSym().Def.(*ir.Name).Type(), t.RParams())
return Instantiate(t.Pos(), t.OrigType(), t.RParams())
}
// substInstType completes the instantiation of a generic type by doing a

View File

@@ -1120,10 +1120,10 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type {
forw = NewIncompleteNamedType(t.Pos(), newsym)
//println("Creating new type by sub", newsym.Name, forw.HasTParam())
forw.SetRParams(neededTargs)
// Copy the OrigSym from the re-instantiated type (which is the sym of
// Copy the OrigType from the re-instantiated type (which is the sym of
// the base generic type).
assert(t.OrigSym() != nil)
forw.SetOrigSym(t.OrigSym())
assert(t.OrigType() != nil)
forw.SetOrigType(t.OrigType())
}
var newt *types.Type
@@ -1536,7 +1536,7 @@ func Shapify(t *types.Type, index int, tparam *types.Type) *types.Type {
// Note: pointers to arrays are special because of slice-to-array-pointer
// conversions. See issue 49295.
if u.Kind() == types.TPTR && u.Elem().Kind() != types.TARRAY &&
tparam.Bound().StructuralType() == nil {
tparam.Bound().StructuralType() == nil && !u.Elem().NotInHeap() {
u = types.Types[types.TUINT8].PtrTo()
}

View File

@@ -72,6 +72,7 @@ const (
fmtDebug
fmtTypeID
fmtTypeIDName
fmtTypeIDHash
)
// Sym
@@ -144,10 +145,21 @@ func symfmt(b *bytes.Buffer, s *Sym, verb rune, mode fmtMode) {
if q := pkgqual(s.Pkg, verb, mode); q != "" {
b.WriteString(q)
b.WriteByte('.')
if mode == fmtTypeIDName {
switch mode {
case fmtTypeIDName:
// If name is a generic instantiation, it might have local package placeholders
// in it. Replace those placeholders with the package name. See issue 49547.
name = strings.Replace(name, LocalPkg.Prefix, q, -1)
case fmtTypeIDHash:
// If name is a generic instantiation, don't hash the instantiating types.
// This isn't great, but it is safe. If we hash the instantiating types, then
// we need to make sure they have just the package name. At this point, they
// either have "", or the whole package path, and it is hard to reconcile
// the two without depending on -p (which we might do someday).
// See issue 51250.
if i := strings.Index(name, "["); i >= 0 {
name = name[:i]
}
}
}
b.WriteString(name)
@@ -173,7 +185,7 @@ func pkgqual(pkg *Pkg, verb rune, mode fmtMode) string {
case fmtDebug:
return pkg.Name
case fmtTypeIDName:
case fmtTypeIDName, fmtTypeIDHash:
// dcommontype, typehash
return pkg.Name
@@ -331,7 +343,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
if t == AnyType || t == ByteType || t == RuneType {
// in %-T mode collapse predeclared aliases with their originals.
switch mode {
case fmtTypeIDName, fmtTypeID:
case fmtTypeIDName, fmtTypeIDHash, fmtTypeID:
t = Types[t.Kind()]
default:
sconv2(b, t.Sym(), 'S', mode)
@@ -422,7 +434,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
case TPTR:
b.WriteByte('*')
switch mode {
case fmtTypeID, fmtTypeIDName:
case fmtTypeID, fmtTypeIDName, fmtTypeIDHash:
if verb == 'S' {
tconv2(b, t.Elem(), 'S', mode, visited)
return
@@ -484,7 +496,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
case IsExported(f.Sym.Name):
sconv2(b, f.Sym, 'S', mode)
default:
if mode != fmtTypeIDName {
if mode != fmtTypeIDName && mode != fmtTypeIDHash {
mode = fmtTypeID
}
sconv2(b, f.Sym, 'v', mode)
@@ -554,7 +566,7 @@ func tconv2(b *bytes.Buffer, t *Type, verb rune, mode fmtMode, visited map[*Type
b.WriteByte(byte(open))
fieldVerb := 'v'
switch mode {
case fmtTypeID, fmtTypeIDName, fmtGo:
case fmtTypeID, fmtTypeIDName, fmtTypeIDHash, fmtGo:
// no argument names on function signature, and no "noescape"/"nosplit" tags
fieldVerb = 'S'
}
@@ -688,7 +700,7 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty
if name == ".F" {
name = "F" // Hack for toolstash -cmp.
}
if !IsExported(name) && mode != fmtTypeIDName {
if !IsExported(name) && mode != fmtTypeIDName && mode != fmtTypeIDHash {
name = sconv(s, 0, mode) // qualify non-exported names (used on structs, not on funarg)
}
} else {
@@ -756,7 +768,7 @@ func FmtConst(v constant.Value, sharp bool) string {
// TypeHash computes a hash value for type t to use in type switch statements.
func TypeHash(t *Type) uint32 {
p := t.NameString()
p := tconv(t, 0, fmtTypeIDHash)
// Using MD5 is overkill, but reduces accidental collisions.
h := md5.Sum([]byte(p))

View File

@@ -202,10 +202,10 @@ type Type struct {
// TODO(danscales): choose a better name.
rparams *[]*Type
// For an instantiated generic type, the symbol for the base generic type.
// For an instantiated generic type, the base generic type.
// This backpointer is useful, because the base type is the type that has
// the method bodies.
origSym *Sym
origType *Type
}
func (*Type) CanBeAnSSAAux() {}
@@ -250,10 +250,10 @@ func (t *Type) Kind() Kind { return t.kind }
func (t *Type) Sym() *Sym { return t.sym }
func (t *Type) SetSym(sym *Sym) { t.sym = sym }
// OrigSym returns the name of the original generic type that t is an
// OrigType returns the original generic type that t is an
// instantiation of, if any.
func (t *Type) OrigSym() *Sym { return t.origSym }
func (t *Type) SetOrigSym(sym *Sym) { t.origSym = sym }
func (t *Type) OrigType() *Type { return t.origType }
func (t *Type) SetOrigType(orig *Type) { t.origType = orig }
// Underlying returns the underlying type of type t.
func (t *Type) Underlying() *Type { return t.underlying }

View File

@@ -204,12 +204,12 @@ type Info struct {
// qualified identifiers are collected in the Uses map.
Types map[syntax.Expr]TypeAndValue
// Instances maps identifiers denoting parameterized types or functions to
// their type arguments and instantiated type.
// Instances maps identifiers denoting generic types or functions to their
// type arguments and instantiated type.
//
// For example, Instances will map the identifier for 'T' in the type
// instantiation T[int, string] to the type arguments [int, string] and
// resulting instantiated *Named type. Given a parameterized function
// resulting instantiated *Named type. Given a generic function
// func F[A any](A), Instances will map the identifier for 'F' in the call
// expression F(int(1)) to the inferred type arguments [int], and resulting
// instantiated *Signature.
@@ -421,8 +421,11 @@ func (conf *Config) Check(path string, files []*syntax.File, info *Info) (*Packa
}
// AssertableTo reports whether a value of type V can be asserted to have type T.
// The behavior of AssertableTo is undefined if V is a generalized interface; i.e.,
// an interface that may only be used as a type constraint in Go code.
//
// The behavior of AssertableTo is undefined in two cases:
// - if V is a generalized interface; i.e., an interface that may only be used
// as a type constraint in Go code
// - if T is an uninstantiated generic type
func AssertableTo(V *Interface, T Type) bool {
// Checker.newAssertableTo suppresses errors for invalid types, so we need special
// handling here.
@@ -432,20 +435,31 @@ func AssertableTo(V *Interface, T Type) bool {
return (*Checker)(nil).newAssertableTo(V, T) == nil
}
// AssignableTo reports whether a value of type V is assignable to a variable of type T.
// AssignableTo reports whether a value of type V is assignable to a variable
// of type T.
//
// The behavior of AssignableTo is undefined if V or T is an uninstantiated
// generic type.
func AssignableTo(V, T Type) bool {
x := operand{mode: value, typ: V}
ok, _ := x.assignableTo(nil, T, nil) // check not needed for non-constant x
return ok
}
// ConvertibleTo reports whether a value of type V is convertible to a value of type T.
// ConvertibleTo reports whether a value of type V is convertible to a value of
// type T.
//
// The behavior of ConvertibleTo is undefined if V or T is an uninstantiated
// generic type.
func ConvertibleTo(V, T Type) bool {
x := operand{mode: value, typ: V}
return x.convertibleTo(nil, T, nil) // check not needed for non-constant x
}
// Implements reports whether type V implements interface T.
//
// The behavior of Implements is undefined if V is an uninstantiated generic
// type.
func Implements(V Type, T *Interface) bool {
if T.Empty() {
// All types (even Typ[Invalid]) implement the empty interface.

View File

@@ -12,6 +12,7 @@ import (
"internal/testenv"
"reflect"
"regexp"
"sort"
"strings"
"testing"
@@ -403,69 +404,61 @@ func TestTypesInfo(t *testing.T) {
}
func TestInstanceInfo(t *testing.T) {
var tests = []struct {
src string
const lib = `package lib
func F[P any](P) {}
type T[P any] []P
`
type testInst struct {
name string
targs []string
typ string
}
var tests = []struct {
src string
instances []testInst // recorded instances in source order
}{
{`package p0; func f[T any](T) {}; func _() { f(42) }`,
`f`,
[]string{`int`},
`func(int)`,
[]testInst{{`f`, []string{`int`}, `func(int)`}},
},
{`package p1; func f[T any](T) T { panic(0) }; func _() { f('@') }`,
`f`,
[]string{`rune`},
`func(rune) rune`,
[]testInst{{`f`, []string{`rune`}, `func(rune) rune`}},
},
{`package p2; func f[T any](...T) T { panic(0) }; func _() { f(0i) }`,
`f`,
[]string{`complex128`},
`func(...complex128) complex128`,
[]testInst{{`f`, []string{`complex128`}, `func(...complex128) complex128`}},
},
{`package p3; func f[A, B, C any](A, *B, []C) {}; func _() { f(1.2, new(string), []byte{}) }`,
`f`,
[]string{`float64`, `string`, `byte`},
`func(float64, *string, []byte)`,
[]testInst{{`f`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`}},
},
{`package p4; func f[A, B any](A, *B, ...[]B) {}; func _() { f(1.2, new(byte)) }`,
`f`,
[]string{`float64`, `byte`},
`func(float64, *byte, ...[]byte)`,
[]testInst{{`f`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`}},
},
// we don't know how to translate these but we can type-check them
{`package q0; type T struct{}; func (T) m[P any](P) {}; func _(x T) { x.m(42) }`,
`m`,
[]string{`int`},
`func(int)`,
[]testInst{{`m`, []string{`int`}, `func(int)`}},
},
{`package q1; type T struct{}; func (T) m[P any](P) P { panic(0) }; func _(x T) { x.m(42) }`,
`m`,
[]string{`int`},
`func(int) int`,
[]testInst{{`m`, []string{`int`}, `func(int) int`}},
},
{`package q2; type T struct{}; func (T) m[P any](...P) P { panic(0) }; func _(x T) { x.m(42) }`,
`m`,
[]string{`int`},
`func(...int) int`,
[]testInst{{`m`, []string{`int`}, `func(...int) int`}},
},
{`package q3; type T struct{}; func (T) m[A, B, C any](A, *B, []C) {}; func _(x T) { x.m(1.2, new(string), []byte{}) }`,
`m`,
[]string{`float64`, `string`, `byte`},
`func(float64, *string, []byte)`,
[]testInst{{`m`, []string{`float64`, `string`, `byte`}, `func(float64, *string, []byte)`}},
},
{`package q4; type T struct{}; func (T) m[A, B any](A, *B, ...[]B) {}; func _(x T) { x.m(1.2, new(byte)) }`,
`m`,
[]string{`float64`, `byte`},
`func(float64, *byte, ...[]byte)`,
[]testInst{{`m`, []string{`float64`, `byte`}, `func(float64, *byte, ...[]byte)`}},
},
{`package r0; type T[P any] struct{}; func (_ T[P]) m[Q any](Q) {}; func _[P any](x T[P]) { x.m(42) }`,
`m`,
[]string{`int`},
`func(int)`,
{`package r0; type T[P1 any] struct{}; func (_ T[P2]) m[Q any](Q) {}; func _[P3 any](x T[P3]) { x.m(42) }`,
[]testInst{
{`T`, []string{`P2`}, `struct{}`},
{`T`, []string{`P3`}, `struct{}`},
{`m`, []string{`int`}, `func(int)`},
},
},
// TODO(gri) record method type parameters in syntax.FuncType so we can check this
// {`package r1; type T interface{ m[P any](P) }; func _(x T) { x.m(4.2) }`,
@@ -474,97 +467,113 @@ func TestInstanceInfo(t *testing.T) {
// `func(float64)`,
// },
{`package s1; func f[T any, P interface{~*T}](x T) {}; func _(x string) { f(x) }`,
`f`,
[]string{`string`, `*string`},
`func(x string)`,
{`package s1; func f[T any, P interface{*T}](x T) {}; func _(x string) { f(x) }`,
[]testInst{{`f`, []string{`string`, `*string`}, `func(x string)`}},
},
{`package s2; func f[T any, P interface{~*T}](x []T) {}; func _(x []int) { f(x) }`,
`f`,
[]string{`int`, `*int`},
`func(x []int)`,
{`package s2; func f[T any, P interface{*T}](x []T) {}; func _(x []int) { f(x) }`,
[]testInst{{`f`, []string{`int`, `*int`}, `func(x []int)`}},
},
{`package s3; type C[T any] interface{~chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`,
`f`,
[]string{`int`, `chan<- int`},
`func(x []int)`,
{`package s3; type C[T any] interface{chan<- T}; func f[T any, P C[T]](x []T) {}; func _(x []int) { f(x) }`,
[]testInst{
{`C`, []string{`T`}, `interface{chan<- T}`},
{`f`, []string{`int`, `chan<- int`}, `func(x []int)`},
},
},
{`package s4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`,
`f`,
[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
`func(x []int)`,
{`package s4; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]](x []T) {}; func _(x []int) { f(x) }`,
[]testInst{
{`C`, []string{`T`}, `interface{chan<- T}`},
{`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
{`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func(x []int)`},
},
},
{`package t1; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = f[string] }`,
`f`,
[]string{`string`, `*string`},
`func() string`,
{`package t1; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = f[string] }`,
[]testInst{{`f`, []string{`string`, `*string`}, `func() string`}},
},
{`package t2; func f[T any, P interface{~*T}]() T { panic(0) }; func _() { _ = (f[string]) }`,
`f`,
[]string{`string`, `*string`},
`func() string`,
{`package t2; func f[T any, P interface{*T}]() T { panic(0) }; func _() { _ = (f[string]) }`,
[]testInst{{`f`, []string{`string`, `*string`}, `func() string`}},
},
{`package t3; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
`f`,
[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
`func() []int`,
{`package t3; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
[]testInst{
{`C`, []string{`T`}, `interface{chan<- T}`},
{`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
{`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`},
},
},
{`package t4; type C[T any] interface{~chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = f[int] }`,
`f`,
[]string{`int`, `chan<- int`, `chan<- []*chan<- int`},
`func() []int`,
{`package t4; type C[T any] interface{chan<- T}; func f[T any, P C[T], Q C[[]*P]]() []T { return nil }; func _() { _ = (f[int]) }`,
[]testInst{
{`C`, []string{`T`}, `interface{chan<- T}`},
{`C`, []string{`[]*P`}, `interface{chan<- []*P}`},
{`f`, []string{`int`, `chan<- int`, `chan<- []*chan<- int`}, `func() []int`},
},
},
{`package i0; import lib "generic_lib"; func _() { lib.F(42) }`,
`F`,
[]string{`int`},
`func(int)`,
{`package i0; import "lib"; func _() { lib.F(42) }`,
[]testInst{{`F`, []string{`int`}, `func(int)`}},
},
{`package duplfunc0; func f[T any](T) {}; func _() { f(42); f("foo"); f[int](3) }`,
[]testInst{
{`f`, []string{`int`}, `func(int)`},
{`f`, []string{`string`}, `func(string)`},
{`f`, []string{`int`}, `func(int)`},
},
},
{`package duplfunc1; import "lib"; func _() { lib.F(42); lib.F("foo"); lib.F(3) }`,
[]testInst{
{`F`, []string{`int`}, `func(int)`},
{`F`, []string{`string`}, `func(string)`},
{`F`, []string{`int`}, `func(int)`},
},
},
{`package type0; type T[P interface{~int}] struct{ x P }; var _ T[int]`,
`T`,
[]string{`int`},
`struct{x int}`,
[]testInst{{`T`, []string{`int`}, `struct{x int}`}},
},
{`package type1; type T[P interface{~int}] struct{ x P }; var _ (T[int])`,
`T`,
[]string{`int`},
`struct{x int}`,
[]testInst{{`T`, []string{`int`}, `struct{x int}`}},
},
{`package type2; type T[P interface{~int}] struct{ x P }; var _ T[(int)]`,
`T`,
[]string{`int`},
`struct{x int}`,
[]testInst{{`T`, []string{`int`}, `struct{x int}`}},
},
{`package type3; type T[P1 interface{~[]P2}, P2 any] struct{ x P1; y P2 }; var _ T[[]int, int]`,
`T`,
[]string{`[]int`, `int`},
`struct{x []int; y int}`,
[]testInst{{`T`, []string{`[]int`, `int`}, `struct{x []int; y int}`}},
},
{`package type4; import lib "generic_lib"; var _ lib.T[int]`,
`T`,
[]string{`int`},
`[]int`,
{`package type4; import "lib"; var _ lib.T[int]`,
[]testInst{{`T`, []string{`int`}, `[]int`}},
},
{`package dupltype0; type T[P interface{~int}] struct{ x P }; var x T[int]; var y T[int]`,
[]testInst{
{`T`, []string{`int`}, `struct{x int}`},
{`T`, []string{`int`}, `struct{x int}`},
},
},
{`package dupltype1; type T[P ~int] struct{ x P }; func (r *T[Q]) add(z T[Q]) { r.x += z.x }`,
[]testInst{
{`T`, []string{`Q`}, `struct{x Q}`},
{`T`, []string{`Q`}, `struct{x Q}`},
},
},
{`package dupltype1; import "lib"; var x lib.T[int]; var y lib.T[int]; var z lib.T[string]`,
[]testInst{
{`T`, []string{`int`}, `[]int`},
{`T`, []string{`int`}, `[]int`},
{`T`, []string{`string`}, `[]string`},
},
},
}
for _, test := range tests {
const lib = `package generic_lib
func F[P any](P) {}
type T[P any] []P
`
imports := make(testImporter)
conf := Config{Importer: imports}
instances := make(map[*syntax.Name]Instance)
uses := make(map[*syntax.Name]Object)
instMap := make(map[*syntax.Name]Instance)
useMap := make(map[*syntax.Name]Object)
makePkg := func(src string) *Package {
f, err := parseSrc("p.go", src)
if err != nil {
t.Fatal(err)
}
pkg, err := conf.Check("", []*syntax.File{f}, &Info{Instances: instances, Uses: uses})
pkg, err := conf.Check("", []*syntax.File{f}, &Info{Instances: instMap, Uses: useMap})
if err != nil {
t.Fatal(err)
}
@@ -574,60 +583,72 @@ type T[P any] []P
makePkg(lib)
pkg := makePkg(test.src)
// look for instance information
var targs []Type
var typ Type
for ident, inst := range instances {
if syntax.String(ident) == test.name {
for i := 0; i < inst.TypeArgs.Len(); i++ {
targs = append(targs, inst.TypeArgs.At(i))
}
typ = inst.Type
t.Run(pkg.Name(), func(t *testing.T) {
// Sort instances in source order for stability.
instances := sortedInstances(instMap)
if got, want := len(instances), len(test.instances); got != want {
t.Fatalf("got %d instances, want %d", got, want)
}
// Check that we can find the corresponding parameterized type.
ptype := uses[ident].Type()
// Pairwise compare with the expected instances.
for ii, inst := range instances {
var targs []Type
for i := 0; i < inst.Inst.TypeArgs.Len(); i++ {
targs = append(targs, inst.Inst.TypeArgs.At(i))
}
typ := inst.Inst.Type
testInst := test.instances[ii]
if got := inst.Name.Value; got != testInst.name {
t.Fatalf("got name %s, want %s", got, testInst.name)
}
if len(targs) != len(testInst.targs) {
t.Fatalf("got %d type arguments; want %d", len(targs), len(testInst.targs))
}
for i, targ := range targs {
if got := targ.String(); got != testInst.targs[i] {
t.Errorf("type argument %d: got %s; want %s", i, got, testInst.targs[i])
}
}
if got := typ.Underlying().String(); got != testInst.typ {
t.Errorf("package %s: got %s; want %s", pkg.Name(), got, testInst.typ)
}
// Verify the invariant that re-instantiating the corresponding generic
// type with TypeArgs results in an identical instance.
ptype := useMap[inst.Name].Type()
lister, _ := ptype.(interface{ TypeParams() *TypeParamList })
if lister == nil || lister.TypeParams().Len() == 0 {
t.Errorf("package %s: info.Types[%v] = %v, want parameterized type", pkg.Name(), ident, ptype)
continue
t.Fatalf("info.Types[%v] = %v, want parameterized type", inst.Name, ptype)
}
// Verify the invariant that re-instantiating the generic type with
// TypeArgs results in an equivalent type.
inst2, err := Instantiate(nil, ptype, targs, true)
if err != nil {
t.Errorf("Instantiate(%v, %v) failed: %v", ptype, targs, err)
}
if !Identical(inst.Type, inst2) {
t.Errorf("%v and %v are not identical", inst.Type, inst2)
if !Identical(inst.Inst.Type, inst2) {
t.Errorf("%v and %v are not identical", inst.Inst.Type, inst2)
}
break
}
}
if targs == nil {
t.Errorf("package %s: no instance information found for %s", pkg.Name(), test.name)
continue
}
// check that type arguments are correct
if len(targs) != len(test.targs) {
t.Errorf("package %s: got %d type arguments; want %d", pkg.Name(), len(targs), len(test.targs))
continue
}
for i, targ := range targs {
if got := targ.String(); got != test.targs[i] {
t.Errorf("package %s, %d. type argument: got %s; want %s", pkg.Name(), i, got, test.targs[i])
continue
}
}
// check that the types match
if got := typ.Underlying().String(); got != test.typ {
t.Errorf("package %s: got %s; want %s", pkg.Name(), got, test.typ)
}
})
}
}
type recordedInstance struct {
Name *syntax.Name
Inst Instance
}
func sortedInstances(m map[*syntax.Name]Instance) (instances []recordedInstance) {
for id, inst := range m {
instances = append(instances, recordedInstance{id, inst})
}
sort.Slice(instances, func(i, j int) bool {
return instances[i].Name.Pos().Cmp(instances[j].Name.Pos()) < 0
})
return instances
}
func TestDefsInfo(t *testing.T) {
var tests = []struct {
src string
@@ -1697,7 +1718,7 @@ func F(){
var F = /*F=func:12*/ F /*F=var:17*/ ; _ = F
var a []int
for i, x := range /*i=undef*/ /*x=var:16*/ a /*i=var:20*/ /*x=var:20*/ { _ = i; _ = x }
for i, x := range a /*i=undef*/ /*x=var:16*/ { _ = i; _ = x }
var i interface{}
switch y := i.(type) { /*y=undef*/
@@ -2267,6 +2288,103 @@ func TestInstanceIdentity(t *testing.T) {
}
}
// TestInstantiatedObjects verifies properties of instantiated objects.
func TestInstantiatedObjects(t *testing.T) {
const src = `
package p
type T[P any] struct {
field P
}
func (recv *T[Q]) concreteMethod() {}
type FT[P any] func(ftp P) (ftrp P)
func F[P any](fp P) (frp P){ return }
type I[P any] interface {
interfaceMethod(P)
}
var (
t T[int]
ft FT[int]
f = F[int]
i I[int]
)
`
info := &Info{
Defs: make(map[*syntax.Name]Object),
}
f, err := parseSrc("p.go", src)
if err != nil {
t.Fatal(err)
}
conf := Config{}
pkg, err := conf.Check(f.PkgName.Value, []*syntax.File{f}, info)
if err != nil {
t.Fatal(err)
}
lookup := func(name string) Type { return pkg.Scope().Lookup(name).Type() }
tests := []struct {
ident string
obj Object
}{
{"field", lookup("t").Underlying().(*Struct).Field(0)},
{"concreteMethod", lookup("t").(*Named).Method(0)},
{"recv", lookup("t").(*Named).Method(0).Type().(*Signature).Recv()},
{"ftp", lookup("ft").Underlying().(*Signature).Params().At(0)},
{"ftrp", lookup("ft").Underlying().(*Signature).Results().At(0)},
{"fp", lookup("f").(*Signature).Params().At(0)},
{"frp", lookup("f").(*Signature).Results().At(0)},
{"interfaceMethod", lookup("i").Underlying().(*Interface).Method(0)},
}
// Collect all identifiers by name.
idents := make(map[string][]*syntax.Name)
syntax.Inspect(f, func(n syntax.Node) bool {
if id, ok := n.(*syntax.Name); ok {
idents[id.Value] = append(idents[id.Value], id)
}
return true
})
for _, test := range tests {
test := test
t.Run(test.ident, func(t *testing.T) {
if got := len(idents[test.ident]); got != 1 {
t.Fatalf("found %d identifiers named %s, want 1", got, test.ident)
}
ident := idents[test.ident][0]
def := info.Defs[ident]
if def == test.obj {
t.Fatalf("info.Defs[%s] contains the test object", test.ident)
}
if def.Pkg() != test.obj.Pkg() {
t.Errorf("Pkg() = %v, want %v", def.Pkg(), test.obj.Pkg())
}
if def.Name() != test.obj.Name() {
t.Errorf("Name() = %v, want %v", def.Name(), test.obj.Name())
}
if def.Pos() != test.obj.Pos() {
t.Errorf("Pos() = %v, want %v", def.Pos(), test.obj.Pos())
}
if def.Parent() != test.obj.Parent() {
t.Fatalf("Parent() = %v, want %v", def.Parent(), test.obj.Parent())
}
if def.Exported() != test.obj.Exported() {
t.Fatalf("Exported() = %v, want %v", def.Exported(), test.obj.Exported())
}
if def.Id() != test.obj.Id() {
t.Fatalf("Id() = %v, want %v", def.Id(), test.obj.Id())
}
// String and Type are expected to differ.
})
}
}
func TestImplements(t *testing.T) {
const src = `
package p

View File

@@ -423,7 +423,7 @@ var cgoPrefixes = [...]string{
"_Cmacro_", // function to evaluate the expanded expression
}
func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *Named) {
// these must be declared before the "goto Error" statements
var (
obj Object
@@ -526,6 +526,12 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr) {
check.exprOrType(x, e.X, false)
switch x.mode {
case typexpr:
// don't crash for "type T T.x" (was issue #51509)
if def != nil && x.typ == def {
check.cycleError([]Object{def.obj})
goto Error
}
case builtin:
check.errorf(e.Pos(), "cannot select on %s", x)
goto Error

View File

@@ -1556,7 +1556,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
return kind
case *syntax.SelectorExpr:
check.selector(x, e)
check.selector(x, e, nil)
case *syntax.IndexExpr:
if check.indexExpr(x, e) {
@@ -1642,6 +1642,7 @@ func (check *Checker) exprInternal(x *operand, e syntax.Expr, hint Type) exprKin
case invalid:
goto Error
case typexpr:
check.validVarType(e.X, x.typ)
x.typ = &Pointer{base: x.typ}
default:
var base Type

View File

@@ -488,21 +488,88 @@ func (check *Checker) inferB(pos syntax.Pos, tparams []*TypeParam, targs []Type)
}
}
// If a constraint has a core type, unify the corresponding type parameter with it.
for _, tpar := range tparams {
if ctype := adjCoreType(tpar); ctype != nil {
if !u.unify(tpar, ctype) {
// TODO(gri) improve error message by providing the type arguments
// which we know already
check.errorf(pos, "%s does not match %s", tpar, ctype)
return nil, 0
// Repeatedly apply constraint type inference as long as
// there are still unknown type arguments and progress is
// being made.
//
// This is an O(n^2) algorithm where n is the number of
// type parameters: if there is progress (and iteration
// continues), at least one type argument is inferred
// per iteration and we have a doubly nested loop.
// In practice this is not a problem because the number
// of type parameters tends to be very small (< 5 or so).
// (It should be possible for unification to efficiently
// signal newly inferred type arguments; then the loops
// here could handle the respective type parameters only,
// but that will come at a cost of extra complexity which
// may not be worth it.)
for n := u.x.unknowns(); n > 0; {
nn := n
for i, tpar := range tparams {
// If there is a core term (i.e., a core type with tilde information)
// unify the type parameter with the core type.
if core, single := coreTerm(tpar); core != nil {
// A type parameter can be unified with its core type in two cases.
tx := u.x.at(i)
switch {
case tx != nil:
// The corresponding type argument tx is known.
// In this case, if the core type has a tilde, the type argument's underlying
// type must match the core type, otherwise the type argument and the core type
// must match.
// If tx is an external type parameter, don't consider its underlying type
// (which is an interface). Core type unification will attempt to unify against
// core.typ.
// Note also that even with inexact unification we cannot leave away the under
// call here because it's possible that both tx and core.typ are named types,
// with under(tx) being a (named) basic type matching core.typ. Such cases do
// not match with inexact unification.
if core.tilde && !isTypeParam(tx) {
tx = under(tx)
}
if !u.unify(tx, core.typ) {
// TODO(gri) improve error message by providing the type arguments
// which we know already
// Don't use term.String() as it always qualifies types, even if they
// are in the current package.
tilde := ""
if core.tilde {
tilde = "~"
}
check.errorf(pos, "%s does not match %s%s", tpar, tilde, core.typ)
return nil, 0
}
case single && !core.tilde:
// The corresponding type argument tx is unknown and there's a single
// specific type and no tilde.
// In this case the type argument must be that single type; set it.
u.x.set(i, core.typ)
default:
// Unification is not possible and no progress was made.
continue
}
// The number of known type arguments may have changed.
nn = u.x.unknowns()
if nn == 0 {
break // all type arguments are known
}
}
}
assert(nn <= n)
if nn == n {
break // no progress
}
n = nn
}
// u.x.types() now contains the incoming type arguments plus any additional type
// arguments which were inferred from core types. The newly inferred non-
// nil entries may still contain references to other type parameters.
// arguments which were inferred from core terms. The newly inferred non-nil
// entries may still contain references to other type parameters.
// For instance, for [A any, B interface{ []C }, C interface{ *A }], if A == int
// was given, unification produced the type list [int, []C, *A]. We eliminate the
// remaining type parameters by substituting the type parameters in this type list
@@ -591,26 +658,40 @@ 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 {
var single *term
if tpar.is(func(t *term) bool {
if single == nil && t != nil {
single = t
return true
// If the type parameter has a single specific type S, coreTerm returns (S, true).
// Otherwise, if tpar has a core type T, it returns a term corresponding to that
// core type and false. In that case, if any term of tpar has a tilde, the core
// term has a tilde. In all other cases coreTerm returns (nil, false).
func coreTerm(tpar *TypeParam) (*term, bool) {
n := 0
var single *term // valid if n == 1
var tilde bool
tpar.is(func(t *term) bool {
if t == nil {
assert(n == 0)
return false // no terms
}
return false // zero or more than one terms
}) {
n++
single = t
if t.tilde {
tilde = true
}
return true
})
if n == 1 {
if debug {
assert(under(single.typ) == coreType(tpar))
assert(debug && under(single.typ) == coreType(tpar))
}
return single.typ
return single, true
}
return coreType(tpar)
if typ := coreType(tpar); typ != nil {
// A core type is always an underlying type.
// If any term of tpar has a tilde, we don't
// have a precise core type and we must return
// a tilde as well.
return &term{tilde, typ}, false
}
return nil, false
}
type cycleFinder struct {
@@ -658,8 +739,6 @@ func (w *cycleFinder) typ(typ Type) {
// in signatures where they are handled explicitly.
case *Signature:
// There are no "method types" so we should never see a recv.
assert(t.recv == nil)
if t.params != nil {
w.varList(t.params.vars)
}

View File

@@ -15,10 +15,10 @@ import (
// Instantiate instantiates the type orig with the given type arguments targs.
// orig must be a *Named or a *Signature type. If there is no error, the
// resulting Type is a new, instantiated (not parameterized) type of the same
// kind (either a *Named or a *Signature). Methods attached to a *Named type
// are also instantiated, and associated with a new *Func that has the same
// position as the original method, but nil function scope.
// resulting Type is an instantiated type of the same kind (either a *Named or
// a *Signature). Methods attached to a *Named type are also instantiated, and
// associated with a new *Func that has the same position as the original
// method, but nil function scope.
//
// If ctxt is non-nil, it may be used to de-duplicate the instance against
// previous instances with the same identity. As a special case, generic

View File

@@ -70,7 +70,8 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
// see if there is a matching field (but not a method, those need to be declared
// explicitly in the constraint). If the constraint is a named pointer type (see
// above), we are ok here because only fields are accepted as results.
if obj == nil && isTypeParam(T) {
const enableTParamFieldLookup = false // see issue #51576
if enableTParamFieldLookup && obj == nil && isTypeParam(T) {
if t := coreType(T); t != nil {
obj, index, indirect = lookupFieldOrMethod(t, addressable, pkg, name, false)
if _, ok := obj.(*Var); !ok {

View File

@@ -98,10 +98,10 @@ func (t *Named) cleanup() {
}
// 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.
// instantiated types, this is same as the type name of the origin type.
func (t *Named) Obj() *TypeName { return t.orig.obj } // for non-instances this is the same as t.obj
// Origin returns the parameterized type from which the named type t is
// Origin returns the generic type from which the named type t is
// instantiated. If t is not an instantiated type, the result is t.
func (t *Named) Origin() *Named { return t.orig }
@@ -109,7 +109,7 @@ func (t *Named) Origin() *Named { return t.orig }
// between parameterized instantiated and non-instantiated types.
// TypeParams returns the type parameters of the named type t, or nil.
// The result is non-nil for an (originally) parameterized type even if it is instantiated.
// The result is non-nil for an (originally) generic type even if it is instantiated.
func (t *Named) TypeParams() *TypeParamList { return t.resolve(nil).tparams }
// SetTypeParams sets the type parameters of the named type t.
@@ -122,7 +122,11 @@ func (t *Named) SetTypeParams(tparams []*TypeParam) {
// TypeArgs returns the type arguments used to instantiate the named type t.
func (t *Named) TypeArgs() *TypeList { return t.targs }
// NumMethods returns the number of explicit methods whose receiver is named type t.
// NumMethods returns the number of explicit methods defined for t.
//
// For an ordinary or instantiated type t, the receiver base type of these
// methods will be the named type t. For an uninstantiated generic type t, each
// method receiver will be instantiated with its receiver type parameters.
func (t *Named) NumMethods() int { return t.resolve(nil).methods.Len() }
// Method returns the i'th method of named type t for 0 <= i < t.NumMethods().
@@ -186,7 +190,7 @@ func (t *Named) instantiateMethod(i int) *Func {
rtyp = t
}
sig.recv = NewParam(origSig.recv.pos, origSig.recv.pkg, origSig.recv.name, rtyp)
sig.recv = substVar(origSig.recv, rtyp)
return NewFunc(origm.pos, origm.pkg, origm.name, sig)
}

View File

@@ -413,7 +413,7 @@ func (check *Checker) collectObjects() {
case *syntax.TypeDecl:
if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) {
check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later")
check.versionErrorf(s.TParamList[0], "go1.18", "type parameter")
}
obj := NewTypeName(s.Name.Pos(), pkg, s.Name.Value, nil)
check.declarePkgObj(s.Name, obj, &declInfo{file: fileScope, tdecl: s})
@@ -458,7 +458,7 @@ func (check *Checker) collectObjects() {
check.recordDef(s.Name, obj)
}
if len(s.TParamList) != 0 && !check.allowVersion(pkg, 1, 18) && !hasTParamError {
check.softErrorf(s.TParamList[0], "type parameters require go1.18 or later")
check.versionErrorf(s.TParamList[0], "go1.18", "type parameter")
}
info := &declInfo{file: fileScope, fdecl: s}
// Methods are not package-level objects but we still track them in the

View File

@@ -626,14 +626,15 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
case *syntax.ForStmt:
inner |= breakOk | continueOk
check.openScope(s, "for")
defer check.closeScope()
if rclause, _ := s.Init.(*syntax.RangeClause); rclause != nil {
check.rangeStmt(inner, s, rclause)
break
}
check.openScope(s, "for")
defer check.closeScope()
check.simpleStmt(s.Init)
if s.Cond != nil {
var x operand
@@ -809,8 +810,6 @@ func (check *Checker) typeSwitchStmt(inner stmtContext, s *syntax.SwitchStmt, gu
}
func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *syntax.RangeClause) {
// scope already opened
// determine lhs, if any
sKey := rclause.Lhs // possibly nil
var sValue, sExtra syntax.Expr
@@ -866,6 +865,11 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
}
}
// Open the for-statement block scope now, after the range clause.
// Iteration variables declared with := need to go in this scope (was issue #51437).
check.openScope(s, "range")
defer check.closeScope()
// check assignment to/declaration of iteration variables
// (irregular assignment, cannot easily map to existing assignment checks)
@@ -874,9 +878,7 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
rhs := [2]Type{key, val} // key, val may be nil
if rclause.Def {
// short variable declaration; variable scope starts after the range clause
// (the for loop opens a new scope, so variables on the lhs never redeclare
// previously declared variables)
// short variable declaration
var vars []*Var
for i, lhs := range lhs {
if lhs == nil {
@@ -913,12 +915,8 @@ func (check *Checker) rangeStmt(inner stmtContext, s *syntax.ForStmt, rclause *s
// declare variables
if len(vars) > 0 {
scopePos := syntax.EndPos(rclause.X) // TODO(gri) should this just be s.Body.Pos (spec clarification)?
scopePos := s.Body.Pos()
for _, obj := range vars {
// spec: "The scope of a constant or variable identifier declared inside
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
// for short variable declarations) and ends at the end of the innermost
// containing block."
check.declare(check.scope, nil /* recordDef already called */, obj, scopePos)
}
} else {

View File

@@ -290,14 +290,18 @@ func (subst *subster) typOrNil(typ Type) Type {
func (subst *subster) var_(v *Var) *Var {
if v != nil {
if typ := subst.typ(v.typ); typ != v.typ {
copy := *v
copy.typ = typ
return &copy
return substVar(v, typ)
}
}
return v
}
func substVar(v *Var, typ Type) *Var {
copy := *v
copy.typ = typ
return &copy
}
func (subst *subster) tuple(t *Tuple) *Tuple {
if t != nil {
if vars, copied := subst.varList(t.vars); copied {
@@ -410,9 +414,8 @@ func replaceRecvType(in []*Func, old, new Type) (out []*Func, copied bool) {
copied = true
}
newsig := *sig
sig = &newsig
sig.recv = NewVar(sig.recv.pos, sig.recv.pkg, "", new)
out[i] = NewFunc(method.pos, method.pkg, method.name, sig)
newsig.recv = substVar(sig.recv, new)
out[i] = NewFunc(method.pos, method.pkg, method.name, &newsig)
}
}
return

View File

@@ -8,21 +8,21 @@ import "strconv"
type any interface{}
func f0[A any, B interface{~*C}, C interface{~*D}, D interface{~*A}](A, B, C, D) {}
func f0[A any, B interface{*C}, C interface{*D}, D interface{*A}](A, B, C, D) {}
func _() {
f := f0[string]
f("a", nil, nil, nil)
f0("a", nil, nil, nil)
}
func f1[A any, B interface{~*A}](A, B) {}
func f1[A any, B interface{*A}](A, B) {}
func _() {
f := f1[int]
f(int(0), new(int))
f1(int(0), new(int))
}
func f2[A any, B interface{~[]A}](A, B) {}
func f2[A any, B interface{[]A}](A, B) {}
func _() {
f := f2[byte]
f(byte(0), []byte{})
@@ -38,7 +38,7 @@ func _() {
// f3(x, &x, &x)
// }
func f4[A any, B interface{~[]C}, C interface{~*A}](A, B, C) {}
func f4[A any, B interface{[]C}, C interface{*A}](A, B, C) {}
func _() {
f := f4[int]
var x int
@@ -46,7 +46,7 @@ func _() {
f4(x, []*int{}, &x)
}
func f5[A interface{~struct{b B; c C}}, B any, C interface{~*B}](x B) A { panic(0) }
func f5[A interface{struct{b B; c C}}, B any, C interface{*B}](x B) A { panic(0) }
func _() {
x := f5(1.2)
var _ float64 = x.b
@@ -79,14 +79,14 @@ var _ = Double(MySlice{1})
type Setter[B any] interface {
Set(string)
~*B
*B
}
func FromStrings[T interface{}, PT Setter[T]](s []string) []T {
result := make([]T, len(s))
for i, v := range s {
// The type of &result[i] is *T which is in the type list
// of Setter2, so we can convert it to PT.
// of Setter, so we can convert it to PT.
p := PT(&result[i])
// PT has a Set method.
p.Set(v)

View File

@@ -4,44 +4,46 @@
package typeInference
// As of issue #51527, type-type inference has been disabled.
// basic inference
type Tb[P ~*Q, Q any] int
func _() {
var x Tb[*int]
var x Tb /* ERROR got 1 arguments */ [*int]
var y Tb[*int, int]
x = y
x = y /* ERROR cannot use y .* in assignment */
_ = x
}
// recursive inference
type Tr[A any, B ~*C, C ~*D, D ~*A] int
type Tr[A any, B *C, C *D, D *A] int
func _() {
var x Tr[string]
var x Tr /* ERROR got 1 arguments */ [string]
var y Tr[string, ***string, **string, *string]
var z Tr[int, ***int, **int, *int]
x = y
x = y /* ERROR cannot use y .* in assignment */
x = z // ERROR cannot use z .* as Tr
_ = x
}
// other patterns of inference
type To0[A any, B ~[]A] int
type To1[A any, B ~struct{a A}] int
type To2[A any, B ~[][]A] int
type To3[A any, B ~[3]*A] int
type To4[A any, B any, C ~struct{a A; b B}] int
type To0[A any, B []A] int
type To1[A any, B struct{a A}] int
type To2[A any, B [][]A] int
type To3[A any, B [3]*A] int
type To4[A any, B any, C struct{a A; b B}] int
func _() {
var _ To0[int]
var _ To1[int]
var _ To2[int]
var _ To3[int]
var _ To4[int, string]
var _ To0 /* ERROR got 1 arguments */ [int]
var _ To1 /* ERROR got 1 arguments */ [int]
var _ To2 /* ERROR got 1 arguments */ [int]
var _ To3 /* ERROR got 1 arguments */ [int]
var _ To4 /* ERROR got 2 arguments */ [int, string]
}
// failed inference
type Tf0[A, B any] int
type Tf1[A any, B ~struct{a A; c C}, C any] int
func _() {
var _ Tf0 /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [int]
var _ Tf1 /* ERROR cannot infer B */ /* ERROR got 1 arguments but 3 type parameters */ [int]
var _ Tf0 /* ERROR got 1 arguments but 2 type parameters */ [int]
var _ Tf1 /* ERROR got 1 arguments but 3 type parameters */ [int]
}

View File

@@ -24,7 +24,8 @@ type (
_ interface{int|any}
_ interface{int|~string|union}
_ interface{int|~string|interface{int}}
_ interface{union|union /* ERROR overlapping terms p.union and p.union */ }
_ interface{union|int} // interfaces (here: union) are ignored when checking for overlap
_ interface{union|union} // ditto
// For now we do not permit interfaces with methods in unions.
_ interface{~ /* ERROR invalid use of ~ */ any}

View File

@@ -78,7 +78,7 @@ func _() {
related1(si, "foo" /* ERROR cannot use "foo" */ )
}
func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) {}
func related2[Elem any, Slice interface{[]Elem}](e Elem, s Slice) {}
func _() {
// related2 can be called with explicit instantiation.
@@ -109,16 +109,8 @@ func _() {
related3[int, []int]()
related3[byte, List[byte]]()
// Alternatively, the 2nd type argument can be inferred
// from the first one through constraint type inference.
related3[int]()
// The inferred type is the core type of the Slice
// type parameter.
var _ []int = related3[int]()
// It is not the defined parameterized type List.
type anotherList []float32
var _ anotherList = related3[float32]() // valid
var _ anotherList = related3 /* ERROR cannot use .* \(value of type List\[float32\]\) as anotherList */ [float32, List[float32]]()
// The 2nd type argument cannot be inferred from the first
// one because there's two possible choices: []Elem and
// List[Elem].
related3[int]( /* ERROR cannot infer Slice */ )
}

View File

@@ -35,7 +35,7 @@ func _() int {
return deref(p)
}
func addrOfCopy[V any, P ~*V](v V) P {
func addrOfCopy[V any, P *V](v V) P {
return &v
}

View File

@@ -47,7 +47,7 @@ type _ struct{
}
type _ struct{
I3 // ERROR interface is .* comparable
I3 // ERROR interface contains type constraints
}
// General composite types.
@@ -59,19 +59,19 @@ type (
_ []I1 // ERROR interface is .* comparable
_ []I2 // ERROR interface contains type constraints
_ *I3 // ERROR interface is .* comparable
_ *I3 // ERROR interface contains type constraints
_ map[I1 /* ERROR interface is .* comparable */ ]I2 // ERROR interface contains type constraints
_ chan I3 // ERROR interface is .* comparable
_ chan I3 // ERROR interface contains type constraints
_ func(I1 /* ERROR interface is .* comparable */ )
_ func() I2 // ERROR interface contains type constraints
)
// Other cases.
var _ = [...]I3 /* ERROR interface is .* comparable */ {}
var _ = [...]I3 /* ERROR interface contains type constraints */ {}
func _(x interface{}) {
_ = x.(I3 /* ERROR interface is .* comparable */ )
_ = x.(I3 /* ERROR interface contains type constraints */ )
}
type T1[_ any] struct{}

View File

@@ -4,7 +4,7 @@
package p
func f[F interface{~*Q}, G interface{~*R}, Q, R any](q Q, r R) {}
func f[F interface{*Q}, G interface{*R}, Q, R any](q Q, r R) {}
func _() {
f[*float64, *int](1, 2)

View File

@@ -8,13 +8,13 @@
package go1_17
type T[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{}
type T[P /* ERROR type parameter requires go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ] struct{}
// for init (and main, but we're not in package main) we should only get one error
func init[P /* ERROR func init must have no type parameters */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
func main[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
func main[P /* ERROR type parameter requires go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ]() {}
func f[P /* ERROR type parameters require go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ](x P) {
func f[P /* ERROR type parameter requires go1\.18 or later */ any /* ERROR undeclared name: any \(requires version go1\.18 or later\) */ ](x P) {
var _ T[ /* ERROR type instantiation requires go1\.18 or later */ int]
var _ (T[ /* ERROR type instantiation requires go1\.18 or later */ int])
_ = T[ /* ERROR type instantiation requires go1\.18 or later */ int]{}

View File

@@ -10,9 +10,10 @@ type S[A, B any] struct {
func (S[A, B]) m() {}
// TODO(gri) We should only report one error below. See issue #50588.
// TODO(gri): with type-type inference enabled we should only report one error
// below. See issue #50588.
func _[A any](s S /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [A]) {
func _[A any](s S /* ERROR got 1 arguments but 2 type parameters */ [A]) {
// we should see no follow-on errors below
s.f = 1
s.m()
@@ -21,7 +22,7 @@ func _[A any](s S /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type
// another test case from the issue
func _() {
X(Interface[*F /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [string]](Impl{}))
X(Interface[*F /* ERROR got 1 arguments but 2 type parameters */ [string]](Impl{}))
}
func X[Q Qer](fs Interface[Q]) {

View File

@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Field accesses through type parameters are disabled
// until we have a more thorough understanding of the
// implications on the spec. See issue #51576.
package p
type Sf struct {
@@ -9,13 +13,13 @@ type Sf struct {
}
func f0[P Sf](p P) {
_ = p.f
p.f = 0
_ = p.f // ERROR p\.f undefined
p.f /* ERROR p\.f undefined */ = 0
}
func f0t[P ~struct{f int}](p P) {
_ = p.f
p.f = 0
_ = p.f // ERROR p\.f undefined
p.f /* ERROR p\.f undefined */ = 0
}
var _ = f0[Sf]
@@ -25,8 +29,8 @@ var _ = f0[Sm /* ERROR does not implement */ ]
var _ = f0t[Sm /* ERROR does not implement */ ]
func f1[P interface{ Sf; m() }](p P) {
_ = p.f
p.f = 0
_ = p.f // ERROR p\.f undefined
p.f /* ERROR p\.f undefined */ = 0
p.m()
}
@@ -44,8 +48,8 @@ type Sfm struct {
func (Sfm) m() {}
func f2[P interface{ Sfm; m() }](p P) {
_ = p.f
p.f = 0
_ = p.f // ERROR p\.f undefined
p.f /* ERROR p\.f undefined */ = 0
p.m()
}
@@ -56,8 +60,8 @@ var _ = f2[Sfm]
type PSfm *Sfm
func f3[P interface{ PSfm }](p P) {
_ = p.f
p.f = 0
_ = p.f // ERROR p\.f undefined
p.f /* ERROR p\.f undefined */ = 0
p.m /* ERROR type P has no field or method m */ ()
}

View File

@@ -2,6 +2,10 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Field accesses through type parameters are disabled
// until we have a more thorough understanding of the
// implications on the spec. See issue #51576.
package p
// The first example from the issue.
@@ -18,9 +22,12 @@ type numericAbs[T Numeric] interface {
// AbsDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
func absDifference[T numericAbs[T /* ERROR T does not implement Numeric */]](a, b T) T {
// TODO: the error below should probably be positioned on the '-'.
d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
return d.Abs()
// Field accesses are not permitted for now. Keep an error so
// we can find and fix this code once the situation changes.
return a.Value // ERROR a\.Value undefined
// TODO: The error below should probably be positioned on the '-'.
// d := a /* ERROR "invalid operation: operator - not defined" */ .Value - b.Value
// return d.Abs()
}
// The second example from the issue.

View File

@@ -16,7 +16,7 @@ func G[A, B any](F[A, B]) {
func _() {
// TODO(gri) only report one error below (issue #50932)
var x F /* ERROR cannot infer B */ /* ERROR got 1 arguments but 2 type parameters */ [int]
var x F /* ERROR got 1 arguments but 2 type parameters */ [int]
G(x /* ERROR does not match */)
}
@@ -46,9 +46,9 @@ func NSG[G any](c RSC[G]) {
fmt.Println(c)
}
func MMD[Rc RC /* ERROR cannot infer RG */ /* ERROR got 1 arguments */ [RG], RG any, G any]() M /* ERROR got 2 arguments */ /* ERROR Rc does not match */ [Rc, RG] {
func MMD[Rc RC /* ERROR got 1 arguments */ [RG], RG any, G any]() M /* ERROR got 2 arguments */ [Rc, RG] {
var nFn NFn /* ERROR got 2 arguments */ /* ERROR Rc does not match */ [Rc, RG]
var nFn NFn /* ERROR got 2 arguments */ [Rc, RG]
var empty Rc
switch any(empty).(type) {

View File

@@ -0,0 +1,164 @@
// 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
// Constraint type inference should be independent of the
// ordering of the type parameter declarations. Try all
// permutations in the test case below.
// Permutations produced by https://go.dev/play/p/PHcZNGJTEBZ.
func f00[S1 ~[]E1, S2 ~[]E2, E1 ~byte, E2 ~byte](S1, S2) {}
func f01[S2 ~[]E2, S1 ~[]E1, E1 ~byte, E2 ~byte](S1, S2) {}
func f02[E1 ~byte, S1 ~[]E1, S2 ~[]E2, E2 ~byte](S1, S2) {}
func f03[S1 ~[]E1, E1 ~byte, S2 ~[]E2, E2 ~byte](S1, S2) {}
func f04[S2 ~[]E2, E1 ~byte, S1 ~[]E1, E2 ~byte](S1, S2) {}
func f05[E1 ~byte, S2 ~[]E2, S1 ~[]E1, E2 ~byte](S1, S2) {}
func f06[E2 ~byte, S2 ~[]E2, S1 ~[]E1, E1 ~byte](S1, S2) {}
func f07[S2 ~[]E2, E2 ~byte, S1 ~[]E1, E1 ~byte](S1, S2) {}
func f08[S1 ~[]E1, E2 ~byte, S2 ~[]E2, E1 ~byte](S1, S2) {}
func f09[E2 ~byte, S1 ~[]E1, S2 ~[]E2, E1 ~byte](S1, S2) {}
func f10[S2 ~[]E2, S1 ~[]E1, E2 ~byte, E1 ~byte](S1, S2) {}
func f11[S1 ~[]E1, S2 ~[]E2, E2 ~byte, E1 ~byte](S1, S2) {}
func f12[S1 ~[]E1, E1 ~byte, E2 ~byte, S2 ~[]E2](S1, S2) {}
func f13[E1 ~byte, S1 ~[]E1, E2 ~byte, S2 ~[]E2](S1, S2) {}
func f14[E2 ~byte, S1 ~[]E1, E1 ~byte, S2 ~[]E2](S1, S2) {}
func f15[S1 ~[]E1, E2 ~byte, E1 ~byte, S2 ~[]E2](S1, S2) {}
func f16[E1 ~byte, E2 ~byte, S1 ~[]E1, S2 ~[]E2](S1, S2) {}
func f17[E2 ~byte, E1 ~byte, S1 ~[]E1, S2 ~[]E2](S1, S2) {}
func f18[E2 ~byte, E1 ~byte, S2 ~[]E2, S1 ~[]E1](S1, S2) {}
func f19[E1 ~byte, E2 ~byte, S2 ~[]E2, S1 ~[]E1](S1, S2) {}
func f20[S2 ~[]E2, E2 ~byte, E1 ~byte, S1 ~[]E1](S1, S2) {}
func f21[E2 ~byte, S2 ~[]E2, E1 ~byte, S1 ~[]E1](S1, S2) {}
func f22[E1 ~byte, S2 ~[]E2, E2 ~byte, S1 ~[]E1](S1, S2) {}
func f23[S2 ~[]E2, E1 ~byte, E2 ~byte, S1 ~[]E1](S1, S2) {}
type myByte byte
func _(a []byte, b []myByte) {
f00(a, b)
f01(a, b)
f02(a, b)
f03(a, b)
f04(a, b)
f05(a, b)
f06(a, b)
f07(a, b)
f08(a, b)
f09(a, b)
f10(a, b)
f11(a, b)
f12(a, b)
f13(a, b)
f14(a, b)
f15(a, b)
f16(a, b)
f17(a, b)
f18(a, b)
f19(a, b)
f20(a, b)
f21(a, b)
f22(a, b)
f23(a, b)
}
// Constraint type inference may have to iterate.
// Again, the order of the type parameters shouldn't matter.
func g0[S ~[]E, M ~map[string]S, E any](m M) {}
func g1[M ~map[string]S, S ~[]E, E any](m M) {}
func g2[E any, S ~[]E, M ~map[string]S](m M) {}
func g3[S ~[]E, E any, M ~map[string]S](m M) {}
func g4[M ~map[string]S, E any, S ~[]E](m M) {}
func g5[E any, M ~map[string]S, S ~[]E](m M) {}
func _(m map[string][]byte) {
g0(m)
g1(m)
g2(m)
g3(m)
g4(m)
g5(m)
}
// Worst-case scenario.
// There are 10 unknown type parameters. In each iteration of
// constraint type inference we infer one more, from right to left.
// Each iteration looks repeatedly at all 11 type parameters,
// requiring a total of 10*11 = 110 iterations with the current
// implementation. Pathological case.
func h[K any, J ~*K, I ~*J, H ~*I, G ~*H, F ~*G, E ~*F, D ~*E, C ~*D, B ~*C, A ~*B](x A) {}
func _(x **********int) {
h(x)
}
// Examples with channel constraints and tilde.
func ch1[P chan<- int]() (_ P) { return } // core(P) == chan<- int (single type, no tilde)
func ch2[P ~chan int]() { return } // core(P) == ~chan<- int (tilde)
func ch3[P chan E, E any](E) { return } // core(P) == chan<- E (single type, no tilde)
func ch4[P chan E | ~chan<- E, E any](E) { return } // core(P) == ~chan<- E (tilde)
func ch5[P chan int | chan<- int]() { return } // core(P) == chan<- int (not a single type)
func _() {
// P can be inferred as there's a single specific type and no tilde.
var _ chan int = ch1 /* ERROR cannot use ch1.*value of type chan<- int */ ()
var _ chan<- int = ch1()
// P cannot be inferred as there's a tilde.
ch2( /* ERROR cannot infer P */ )
type myChan chan int
ch2[myChan]()
// P can be inferred as there's a single specific type and no tilde.
var e int
ch3(e)
// P cannot be inferred as there's more than one specific type and a tilde.
ch4( /* ERROR cannot infer P */ e)
_ = ch4[chan int]
// P cannot be inferred as there's more than one specific type.
ch5( /* ERROR cannot infer P */ )
ch5[chan<- int]()
}
// test case from issue
func equal[M1 ~map[K1]V1, M2 ~map[K2]V2, K1, K2 ~uint32, V1, V2 ~string](m1 M1, m2 M2) bool {
if len(m1) != len(m2) {
return false
}
for k, v1 := range m1 {
if v2, ok := m2[K2(k)]; !ok || V2(v1) != v2 {
return false
}
}
return true
}
func equalFixed[K1, K2 ~uint32, V1, V2 ~string](m1 map[K1]V1, m2 map[K2]V2) bool {
if len(m1) != len(m2) {
return false
}
for k, v1 := range m1 {
if v2, ok := m2[K2(k)]; !ok || v1 != V1(v2) {
return false
}
}
return true
}
type (
someNumericID uint32
someStringID string
)
func _() {
foo := map[uint32]string{10: "bar"}
bar := map[someNumericID]someStringID{10: "bar"}
equal(foo, bar)
}

View File

@@ -11,19 +11,20 @@ type RC[RG any] interface {
type Fn[RCT RC[RG], RG any] func(RCT)
type F[RCT RC[RG], RG any] interface {
Fn() Fn[RCT]
Fn() Fn /* ERROR got 1 arguments */ [RCT]
}
type concreteF[RCT RC[RG], RG any] struct {
makeFn func() Fn[RCT]
makeFn func() Fn /* ERROR got 1 arguments */ [RCT]
}
func (c *concreteF[RCT, RG]) Fn() Fn[RCT] {
func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR got 1 arguments */ [RCT] {
return c.makeFn()
}
func NewConcrete[RCT RC[RG], RG any](Rc RCT) F[RCT] {
return &concreteF[RCT]{
func NewConcrete[RCT RC[RG], RG any](Rc RCT) F /* ERROR got 1 arguments */ [RCT] {
// TODO(rfindley): eliminate the duplicate error below.
return & /* ERROR cannot use .* as F\[RCT\] */ concreteF /* ERROR got 1 arguments */ [RCT]{
makeFn: nil,
}
}

View File

@@ -4,22 +4,24 @@
package p
// As of issue #51527, type-type inference has been disabled.
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 FFn[RCT RC[RG], RG any] func() Fn /* ERROR got 1 arguments */ [RCT]
type F[RCT RC[RG], RG any] interface {
Fn() Fn[RCT]
Fn() Fn /* ERROR got 1 arguments */ [RCT]
}
type concreteF[RCT RC[RG], RG any] struct {
makeFn FFn[RCT]
makeFn FFn /* ERROR got 1 arguments */ [RCT]
}
func (c *concreteF[RCT, RG]) Fn() Fn[RCT] {
func (c *concreteF[RCT, RG]) Fn() Fn /* ERROR got 1 arguments */ [RCT] {
return c.makeFn()
}

View File

@@ -10,7 +10,9 @@ 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() {}
// TODO(rfindley): eliminate the duplicate errors here.
func (T /* ERROR got 1 type parameter, but receiver base type declares 2 */ /* ERROR got 1 arguments but 2 type parameters */ [_]) m1() {}
func (T[_, _]) m2() {}
// TODO(gri) this error is unfortunate (issue #51343)
func (T /* ERROR got 3 arguments but 2 type parameters */ [_, _, _]) m3() {}

View File

@@ -0,0 +1,24 @@
// 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 Map map[string]int
func f[M ~map[K]V, K comparable, V any](M) {}
func g[M map[K]V, K comparable, V any](M) {}
func _[M1 ~map[K]V, M2 map[K]V, K comparable, V any]() {
var m1 M1
f(m1)
g( /* ERROR M1 does not implement map\[K\]V */ m1) // M1 has tilde
var m2 M2
f(m2)
g(m2) // M1 does not have tilde
var m3 Map
f(m3)
g( /* ERROR Map does not implement map\[string\]int */ m3) // M in g does not have tilde
}

View File

@@ -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 T struct{}
func (T) m() []int { return nil }
func f(x T) {
for _, x := range func() []int {
return x.m() // x declared in parameter list of f
}() {
_ = x // x declared by range clause
}
}

View File

@@ -0,0 +1,54 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
func _[T comparable](x T) {
_ = x == x
}
func _[T interface{interface{comparable}}](x T) {
_ = x == x
}
func _[T interface{comparable; interface{comparable}}](x T) {
_ = x == x
}
func _[T interface{comparable; ~int}](x T) {
_ = x == x
}
func _[T interface{comparable; ~[]byte}](x T) {
_ = x /* ERROR cannot compare */ == x
}
// TODO(gri) The error message here should be better. See issue #51525.
func _[T interface{comparable; ~int; ~string}](x T) {
_ = x /* ERROR cannot compare */ == x
}
// TODO(gri) The error message here should be better. See issue #51525.
func _[T interface{~int; ~string}](x T) {
_ = x /* ERROR cannot compare */ == x
}
func _[T interface{comparable; interface{~int}; interface{int|float64}}](x T) {
_ = x == x
}
func _[T interface{interface{comparable; ~int}; interface{~float64; comparable; m()}}](x T) {
_ = x /* ERROR cannot compare */ == x
}
// test case from issue
func f[T interface{comparable; []byte|string}](x T) {
_ = x == x
}
func _(s []byte) {
f( /* ERROR \[\]byte does not implement interface{comparable; \[\]byte\|string} */ s)
_ = f[[ /* ERROR does not implement */ ]byte]
}

View File

@@ -0,0 +1,7 @@
// 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 T /* ERROR illegal cycle */ T.x

View File

@@ -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
var _ = (*interface /* ERROR interface contains type constraints */ {int})(nil)
// abbreviated test case from issue
type TypeSet interface{ int | string }
func _() {
f((*TypeSet /* ERROR interface contains type constraints */)(nil))
}
func f(any) {}

View File

@@ -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 f[P interface{ m(R) }, R any]() {}
type T = interface { m(int) }
func _() {
_ = f[ /* ERROR cannot infer R */ T] // don't crash in type inference
}

View File

@@ -0,0 +1,65 @@
// 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
// Interface types must be ignored during overlap test.
type (
T1 interface{int}
T2 interface{~int}
T3 interface{T1 | bool | string}
T4 interface{T2 | ~bool | ~string}
)
type (
// overlap errors for non-interface terms
// (like the interface terms, but explicitly inlined)
_ interface{int | int /* ERROR overlapping terms int and int */ }
_ interface{int | ~ /* ERROR overlapping terms ~int and int */ int}
_ interface{~int | int /* ERROR overlapping terms int and ~int */ }
_ interface{~int | ~ /* ERROR overlapping terms ~int and ~int */ int}
_ interface{T1 | bool | string | T1 | bool /* ERROR overlapping terms bool and bool */ | string /* ERROR overlapping terms string and string */ }
_ interface{T1 | bool | string | T2 | ~ /* ERROR overlapping terms ~bool and bool */ bool | ~ /* ERROR overlapping terms ~string and string */ string}
// no errors for interface terms
_ interface{T1 | T1}
_ interface{T1 | T2}
_ interface{T2 | T1}
_ interface{T2 | T2}
_ interface{T3 | T3 | int}
_ interface{T3 | T4 | bool }
_ interface{T4 | T3 | string }
_ interface{T4 | T4 | float64 }
)
func _[_ T1 | bool | string | T1 | bool /* ERROR overlapping terms */ ]() {}
func _[_ T1 | bool | string | T2 | ~ /* ERROR overlapping terms */ bool ]() {}
func _[_ T2 | ~bool | ~string | T1 | bool /* ERROR overlapping terms */ ]() {}
func _[_ T2 | ~bool | ~string | T2 | ~ /* ERROR overlapping terms */ bool ]() {}
func _[_ T3 | T3 | int]() {}
func _[_ T3 | T4 | bool]() {}
func _[_ T4 | T3 | string]() {}
func _[_ T4 | T4 | float64]() {}
// test cases from issue
type _ interface {
interface {bool | int} | interface {bool | string}
}
type _ interface {
interface {bool | int} ; interface {bool | string}
}
type _ interface {
interface {bool; int} ; interface {bool; string}
}
type _ interface {
interface {bool; int} | interface {bool; string}
}

View File

@@ -0,0 +1,39 @@
// 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 F { // ERROR syntax error
float64
} // ERROR syntax error
func _[T F | int](x T) {
_ = x == 0 // don't crash when recording type of 0
}
// test case from issue
type FloatType { // ERROR syntax error
float32 | float64
} // ERROR syntax error
type IntegerType interface {
int8 | int16 | int32 | int64 | int |
uint8 | uint16 | uint32 | uint64 | uint
}
type ComplexType interface {
complex64 | complex128
}
type Number interface {
FloatType | IntegerType | ComplexType
}
func GetDefaultNumber[T Number](value, defaultValue T) T {
if value == 0 {
return defaultValue
}
return value
}

View File

@@ -31,7 +31,8 @@ func (t *TypeParam) Obj() *TypeName { return t.obj }
// or Signature type by calling SetTypeParams. Setting a type parameter on more
// than one type will result in a panic.
//
// The constraint argument can be nil, and set later via SetConstraint.
// The constraint argument can be nil, and set later via SetConstraint. If the
// constraint is non-nil, it must be fully defined.
func NewTypeParam(obj *TypeName, constraint Type) *TypeParam {
return (*Checker)(nil).newTypeParam(obj, constraint)
}
@@ -71,8 +72,10 @@ func (t *TypeParam) Constraint() Type {
// SetConstraint sets the type constraint for t.
//
// SetConstraint should not be called concurrently, but once SetConstraint
// returns the receiver t is safe for concurrent use.
// It must be called by users of NewTypeParam after the bound's underlying is
// fully defined, and before using the type parameter in any way other than to
// form other types. Once SetConstraint returns the receiver, t is safe for
// concurrent use.
func (t *TypeParam) SetConstraint(bound Type) {
if bound == nil {
panic("nil constraint")

View File

@@ -15,20 +15,25 @@ import (
// API
// A _TypeSet represents the type set of an interface.
// Because of existing language restrictions, methods can be "factored out"
// from the terms. The actual type set is the intersection of the type set
// implied by the methods and the type set described by the terms and the
// comparable bit. To test whether a type is included in a type set
// ("implements" relation), the type must implement all methods _and_ be
// an element of the type set described by the terms and the comparable bit.
// If the term list describes the set of all types and comparable is true,
// only comparable types are meant; in all other cases comparable is false.
type _TypeSet struct {
comparable bool // if set, the interface is or embeds comparable
// TODO(gri) consider using a set for the methods for faster lookup
methods []*Func // all methods of the interface; sorted by unique ID
terms termlist // type terms of the type set
methods []*Func // all methods of the interface; sorted by unique ID
terms termlist // type terms of the type set
comparable bool // invariant: !comparable || terms.isAll()
}
// IsEmpty reports whether type set s is the empty set.
func (s *_TypeSet) IsEmpty() bool { return s.terms.isEmpty() }
// IsAll reports whether type set s is the set of all types (corresponding to the empty interface).
func (s *_TypeSet) IsAll() bool {
return !s.comparable && len(s.methods) == 0 && s.terms.isAll()
}
func (s *_TypeSet) IsAll() bool { return s.IsMethodSet() && len(s.methods) == 0 }
// IsMethodSet reports whether the interface t is fully described by its method set.
func (s *_TypeSet) IsMethodSet() bool { return !s.comparable && s.terms.isAll() }
@@ -43,13 +48,6 @@ func (s *_TypeSet) IsComparable(seen map[Type]bool) bool {
})
}
// TODO(gri) IsTypeSet is not a great name for this predicate. Find a better one.
// IsTypeSet reports whether the type set s is represented by a finite set of underlying types.
func (s *_TypeSet) IsTypeSet() bool {
return !s.comparable && len(s.methods) == 0
}
// NumMethods returns the number of methods available.
func (s *_TypeSet) NumMethods() int { return len(s.methods) }
@@ -215,12 +213,12 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
var todo []*Func
var seen objset
var methods []*Func
var allMethods []*Func
mpos := make(map[*Func]syntax.Pos) // method specification or method embedding position, for good error messages
addMethod := func(pos syntax.Pos, m *Func, explicit bool) {
switch other := seen.insert(m); {
case other == nil:
methods = append(methods, m)
allMethods = append(allMethods, m)
mpos[m] = pos
case explicit:
if check == nil {
@@ -259,7 +257,8 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
}
// collect embedded elements
var allTerms = allTermlist
allTerms := allTermlist
allComparable := false
for i, typ := range ityp.embeddeds {
// The embedding position is nil for imported interfaces
// and also for interface copies after substitution (but
@@ -268,6 +267,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
if ityp.embedPos != nil {
pos = (*ityp.embedPos)[i]
}
var comparable bool
var terms termlist
switch u := under(typ).(type) {
case *Interface:
@@ -279,9 +279,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
check.versionErrorf(pos, "go1.18", "embedding constraint interface %s", typ)
continue
}
if tset.comparable {
ityp.tset.comparable = true
}
comparable = tset.comparable
for _, m := range tset.methods {
addMethod(pos, m, false) // use embedding position pos rather than m.pos
}
@@ -295,6 +293,8 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
if tset == &invalidTypeSet {
continue // ignore invalid unions
}
assert(!tset.comparable)
assert(len(tset.methods) == 0)
terms = tset.terms
default:
if u == Typ[Invalid] {
@@ -306,11 +306,11 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
}
terms = termlist{{false, typ}}
}
// The type set of an interface is the intersection
// of the type sets of all its elements.
// Intersection cannot produce longer termlists and
// thus cannot overflow.
allTerms = allTerms.intersect(terms)
// The type set of an interface is the intersection of the type sets of all its elements.
// Due to language restrictions, only embedded interfaces can add methods, they are handled
// separately. Here we only need to intersect the term lists and comparable bits.
allTerms, allComparable = intersectTermLists(allTerms, allComparable, terms, comparable)
}
ityp.embedPos = nil // not needed anymore (errors have been reported)
@@ -323,15 +323,46 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
}
}
if methods != nil {
sortMethods(methods)
ityp.tset.methods = methods
ityp.tset.comparable = allComparable
if len(allMethods) != 0 {
sortMethods(allMethods)
ityp.tset.methods = allMethods
}
ityp.tset.terms = allTerms
return ityp.tset
}
// TODO(gri) The intersectTermLists function belongs to the termlist implementation.
// The comparable type set may also be best represented as a term (using
// a special type).
// intersectTermLists computes the intersection of two term lists and respective comparable bits.
// xcomp, ycomp are valid only if xterms.isAll() and yterms.isAll() respectively.
func intersectTermLists(xterms termlist, xcomp bool, yterms termlist, ycomp bool) (termlist, bool) {
terms := xterms.intersect(yterms)
// If one of xterms or yterms is marked as comparable,
// the result must only include comparable types.
comp := xcomp || ycomp
if comp && !terms.isAll() {
// only keep comparable terms
i := 0
for _, t := range terms {
assert(t.typ != nil)
if Comparable(t.typ) {
terms[i] = t
i++
}
}
terms = terms[:i]
if !terms.isAll() {
comp = false
}
}
assert(!comp || terms.isAll()) // comparable invariant
return terms, comp
}
func sortMethods(list []*Func) {
sort.Sort(byUniqueMethodName(list))
}
@@ -375,7 +406,7 @@ func computeUnionTypeSet(check *Checker, unionSets map[*Union]*_TypeSet, pos syn
// For now we don't permit type parameters as constraints.
assert(!isTypeParam(t.typ))
terms = computeInterfaceTypeSet(check, pos, ui).terms
} else if t.typ == Typ[Invalid] {
} else if u == Typ[Invalid] {
continue
} else {
if t.tilde && !Identical(t.typ, u) {

View File

@@ -25,9 +25,9 @@ func TestTypeSetString(t *testing.T) {
"{int; string}": "∅",
"{comparable}": "{comparable}",
"{comparable; int}": "{comparable; int}",
"{~int; comparable}": "{comparable; ~int}",
"{int|string; comparable}": "{comparable; int string}",
"{comparable; int}": "{int}",
"{~int; comparable}": "{~int}",
"{int|string; comparable}": "{int string}",
"{comparable; int; string}": "∅",
"{m()}": "{func (p.T).m()}",
@@ -37,8 +37,8 @@ func TestTypeSetString(t *testing.T) {
"{m1(); comparable; m2() int }": "{comparable; func (p.T).m1(); func (p.T).m2() int}",
"{comparable; error}": "{comparable; func (error).Error() string}",
"{m(); comparable; int|float32|string}": "{comparable; func (p.T).m(); int float32 string}",
"{m1(); int; m2(); comparable }": "{comparable; func (p.T).m1(); func (p.T).m2(); int}",
"{m(); comparable; int|float32|string}": "{func (p.T).m(); int float32 string}",
"{m1(); int; m2(); comparable }": "{func (p.T).m1(); func (p.T).m2(); int}",
"{E}; type E interface{}": "𝓤",
"{E}; type E interface{int;string}": "∅",

View File

@@ -147,10 +147,16 @@ func (check *Checker) typ(e syntax.Expr) Type {
// constraint interface.
func (check *Checker) varType(e syntax.Expr) Type {
typ := check.definedType(e, nil)
check.validVarType(e, typ)
return typ
}
// validVarType reports an error if typ is a constraint interface.
// The expression e is used for error reporting, if any.
func (check *Checker) validVarType(e syntax.Expr, typ Type) {
// If we have a type parameter there's nothing to do.
if isTypeParam(typ) {
return typ
return
}
// We don't want to call under() or complete interfaces while we are in
@@ -169,8 +175,6 @@ func (check *Checker) varType(e syntax.Expr) Type {
}
}
})
return typ
}
// definedType is like typ but also accepts a type name def.
@@ -256,7 +260,7 @@ func (check *Checker) typInternal(e0 syntax.Expr, def *Named) (T Type) {
case *syntax.SelectorExpr:
var x operand
check.selector(&x, e)
check.selector(&x, e, def)
switch x.mode {
case typexpr:
@@ -430,10 +434,14 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *
// evaluate arguments
targs := check.typeList(xlist)
if targs == nil {
def.setUnderlying(Typ[Invalid]) // avoid later errors due to lazy instantiation
def.setUnderlying(Typ[Invalid]) // avoid errors later due to lazy instantiation
return Typ[Invalid]
}
// enableTypeTypeInference controls whether to infer missing type arguments
// using constraint type inference. See issue #51527.
const enableTypeTypeInference = false
// create the instance
ctxt := check.bestContext(nil)
h := ctxt.instanceHash(orig, targs)
@@ -453,19 +461,18 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *
def.setUnderlying(inst)
inst.resolver = func(ctxt *Context, n *Named) (*TypeParamList, Type, *methodList) {
tparams := orig.TypeParams().list()
tparams := n.orig.TypeParams().list()
inferred := targs
if len(targs) < len(tparams) {
targs := n.targs.list()
if enableTypeTypeInference && len(targs) < len(tparams) {
// If inference fails, len(inferred) will be 0, and inst.underlying will
// be set to Typ[Invalid] in expandNamed.
inferred = check.infer(x.Pos(), tparams, targs, nil, nil)
inferred := check.infer(x.Pos(), tparams, targs, nil, nil)
if len(inferred) > len(targs) {
inst.targs = newTypeList(inferred)
n.targs = newTypeList(inferred)
}
}
check.recordInstance(x, inferred, inst)
return expandNamed(ctxt, n, x.Pos())
}
@@ -478,6 +485,7 @@ func (check *Checker) instantiatedType(x syntax.Expr, xlist []syntax.Expr, def *
// Since check is non-nil, we can still mutate inst. Unpinning the resolver
// frees some memory.
inst.resolver = nil
check.recordInstance(x, inst.TypeArgs().list(), inst)
if check.validateTArgLen(x.Pos(), inst.tparams.Len(), inst.targs.Len()) {
if i, err := check.verify(x.Pos(), inst.tparams.list(), inst.targs.list()); err != nil {

View File

@@ -247,6 +247,17 @@ func (d *tparamsList) set(i int, typ Type) {
}
}
// unknowns returns the number of type parameters for which no type has been set yet.
func (d *tparamsList) unknowns() int {
n := 0
for _, ti := range d.indices {
if ti <= 0 {
n++
}
}
return n
}
// types returns the list of inferred types (via unification) for the type parameters
// described by d, and an index. If all types were inferred, the returned index is < 0.
// Otherwise, it is the index of the first type parameter which couldn't be inferred;
@@ -349,12 +360,16 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
if enableCoreTypeUnification && !u.exact {
if isTypeParam(x) && !hasName(y) {
// When considering the type parameter for unification
// we look at the adjusted core type (adjCoreType).
// we look at the adjusted core term (adjusted core type
// with tilde information).
// If the adjusted core type is a named type N; the
// corresponding core type is under(N). Since !u.exact
// and y doesn't have a name, unification will end up
// comparing under(N) to y, so we can just use the core
// type instead. Optimization.
// type instead. And we can ignore the tilde because we
// already look at the underlying types on both sides
// and we have known types on both sides.
// Optimization.
if cx := coreType(x); cx != nil {
if traceInference {
u.tracef("core %s ≡ %s", x, y)

View File

@@ -100,25 +100,25 @@ func parseUnion(check *Checker, uexpr syntax.Expr) Type {
if !Identical(u, t.typ) {
check.errorf(tlist[i], "invalid use of ~ (underlying type of %s is %s)", t.typ, u)
continue // don't report another error for t
continue
}
}
// Stand-alone embedded interfaces are ok and are handled by the single-type case
// in the beginning. Embedded interfaces with tilde are excluded above. If we reach
// here, we must have at least two terms in the union.
if f != nil && !f.typeSet().IsTypeSet() {
// here, we must have at least two terms in the syntactic term list (but not necessarily
// in the term list of the union's type set).
if f != nil {
tset := f.typeSet()
switch {
case f.typeSet().NumMethods() != 0:
case tset.NumMethods() != 0:
check.errorf(tlist[i], "cannot use %s in union (%s contains methods)", t, t)
case t.typ == universeComparable.Type():
check.error(tlist[i], "cannot use comparable in union")
case f.typeSet().comparable:
case tset.comparable:
check.errorf(tlist[i], "cannot use %s in union (%s embeds comparable)", t, t)
default:
panic("not a type set but no methods and not comparable")
}
continue // don't report another error for t
continue // terms with interface types are not subject to the no-overlap rule
}
// Report overlapping (non-disjoint) terms such as
@@ -158,10 +158,16 @@ func parseTilde(check *Checker, tx syntax.Expr) *Term {
// overlappingTerm reports the index of the term x in terms which is
// overlapping (not disjoint) from y. The result is < 0 if there is no
// such term.
// such term. The type of term y must not be an interface, and terms
// with an interface type are ignored in the terms list.
func overlappingTerm(terms []*Term, y *Term) int {
assert(!IsInterface(y.typ))
for i, x := range terms {
// disjoint requires non-nil, non-top arguments
if IsInterface(x.typ) {
continue
}
// disjoint requires non-nil, non-top arguments,
// and non-interface types as term types.
if debug {
if x == nil || x.typ == nil || y == nil || y.typ == nil {
panic("empty or top union term")

View File

@@ -111,7 +111,7 @@ func defPredeclaredTypes() {
typ := NewNamed(obj, nil, nil)
// interface{} // marked as comparable
ityp := &Interface{obj: obj, complete: true, tset: &_TypeSet{true, nil, allTermlist}}
ityp := &Interface{obj: obj, complete: true, tset: &_TypeSet{nil, allTermlist, true}}
typ.SetUnderlying(ityp)
def(obj)

View File

@@ -235,15 +235,7 @@ func methodValueWrapper(dot *ir.SelectorExpr) *ir.Name {
saveLineNo := base.Pos
ir.CurFunc = nil
// Set line number equal to the line number where the method is declared.
if pos := dot.Selection.Pos; pos.IsKnown() {
base.Pos = pos
}
// Note: !dot.Selection.Pos.IsKnown() happens for method expressions where
// the method is implicitly declared. The Error method of the
// built-in error type is one such method. We leave the line
// number at the use of the method expression in this
// case. See issue 29389.
base.Pos = base.AutogeneratedPos
tfn := ir.NewFuncType(base.Pos, nil,
typecheck.NewFuncParams(t0.Params(), true),

View File

@@ -8,7 +8,7 @@ require (
golang.org/x/mod v0.6.0-dev.0.20211102181907-3a5865c02020
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
golang.org/x/tools v0.1.9-0.20220124164225-97de9ec46646
golang.org/x/tools v0.1.9-0.20220329150752-294080fd2f5a
)
require (

View File

@@ -18,7 +18,7 @@ golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7q
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/tools v0.1.9-0.20220124164225-97de9ec46646 h1:f8aekWvlQQ8ZhD8SL7lOu18dtWslZYl029PN2F0VnS4=
golang.org/x/tools v0.1.9-0.20220124164225-97de9ec46646/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/tools v0.1.9-0.20220329150752-294080fd2f5a h1:IlVBSvpiWIkpqADzaiismkf1xcqsZjBDIXzO+7kZEpY=
golang.org/x/tools v0.1.9-0.20220329150752-294080fd2f5a/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@@ -1356,7 +1356,7 @@
//
// Workspace maintenance
//
// Go workspace provides access to operations on workspaces.
// Work provides access to operations on workspaces.
//
// Note that support for workspaces is built into many other commands, not
// just 'go work'.
@@ -1364,6 +1364,12 @@
// See 'go help modules' for information about Go's module system of which
// workspaces are a part.
//
// See https://go.dev/ref/mod#workspaces for an in-depth reference on
// workspaces.
//
// See https://go.dev/doc/tutorial/workspaces for an introductory
// tutorial on workspaces.
//
// A workspace is specified by a go.work file that specifies a set of
// module directories with the "use" directive. These modules are used as
// root modules by the go command for builds and related operations. A
@@ -1485,9 +1491,8 @@
// Version string
// }
//
// See the workspaces design proposal at
// https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for
// more information.
// See the workspaces reference at https://go.dev/ref/mod#workspaces
// for more information.
//
//
// Initialize workspace file
@@ -1507,6 +1512,9 @@
// Each argument path is added to a use directive in the go.work file. The
// current go version will also be listed in the go.work file.
//
// See the workspaces reference at https://go.dev/ref/mod#workspaces
// for more information.
//
//
// Sync workspace build list to modules
//
@@ -1530,12 +1538,15 @@
// build list's version of each module is always the same or higher than
// that in each workspace module.
//
// See the workspaces reference at https://go.dev/ref/mod#workspaces
// for more information.
//
//
// Add modules to workspace file
//
// Usage:
//
// go work use [-r] [moddirs]
// go work use [-r] moddirs
//
// Use provides a command-line interface for adding
// directories, optionally recursively, to a go.work file.
@@ -1549,6 +1560,9 @@
// were specified as arguments: namely, use directives will be added for
// directories that exist, and removed for directories that do not exist.
//
// See the workspaces reference at https://go.dev/ref/mod#workspaces
// for more information.
//
//
// Compile and run Go program
//

View File

@@ -503,6 +503,7 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
pkgOpts := load.PackageOpts{
IgnoreImports: *listFind,
ModResolveTests: *listTest,
LoadVCS: cfg.BuildBuildvcs,
}
pkgs := load.PackagesAndErrors(ctx, pkgOpts, args)
if !*listE {

View File

@@ -193,6 +193,18 @@ func (p *Package) Desc() string {
return p.ImportPath
}
// IsTestOnly reports whether p is a test-only package.
//
// A “test-only” package is one that:
// - is a test-only variant of an ordinary package, or
// - is a synthesized "main" package for a test binary, or
// - contains only _test.go files.
func (p *Package) IsTestOnly() bool {
return p.ForTest != "" ||
p.Internal.TestmainGo != nil ||
len(p.TestGoFiles)+len(p.XTestGoFiles) > 0 && len(p.GoFiles)+len(p.CgoFiles) == 0
}
type PackageInternal struct {
// Unexported fields are not part of the public API.
Build *build.Package
@@ -1926,8 +1938,12 @@ func (p *Package) load(ctx context.Context, opts PackageOpts, path string, stk *
}
p.Internal.Imports = imports
p.collectDeps()
if p.Error == nil && p.Name == "main" && len(p.DepsErrors) == 0 {
p.setBuildInfo()
if p.Error == nil && p.Name == "main" && !p.Internal.ForceLibrary && len(p.DepsErrors) == 0 {
// TODO(bcmills): loading VCS metadata can be fairly slow.
// Consider starting this as a background goroutine and retrieving the result
// asynchronously when we're actually ready to build the package, or when we
// actually need to evaluate whether the package's metadata is stale.
p.setBuildInfo(opts.LoadVCS)
}
// unsafe is a fake package.
@@ -2216,7 +2232,7 @@ var vcsStatusCache par.Cache
//
// Note that the GoVersion field is not set here to avoid encoding it twice.
// It is stored separately in the binary, mostly for historical reasons.
func (p *Package) setBuildInfo() {
func (p *Package) setBuildInfo(includeVCS bool) {
// TODO: build and vcs information is not embedded for executables in GOROOT.
// cmd/dist uses -gcflags=all= -ldflags=all= by default, which means these
// executables always appear stale unless the user sets the same flags.
@@ -2346,8 +2362,8 @@ func (p *Package) setBuildInfo() {
// Add VCS status if all conditions are true:
//
// - -buildvcs is enabled.
// - p is contained within a main module (there may be multiple main modules
// in a workspace, but local replacements don't count).
// - p is a non-test contained within a main module (there may be multiple
// main modules in a workspace, but local replacements don't count).
// - Both the current directory and p's module's root directory are contained
// in the same local repository.
// - We know the VCS commands needed to get the status.
@@ -2359,7 +2375,7 @@ func (p *Package) setBuildInfo() {
var vcsCmd *vcs.Cmd
var err error
const allowNesting = true
if cfg.BuildBuildvcs && p.Module != nil && p.Module.Version == "" && !p.Standard {
if includeVCS && p.Module != nil && p.Module.Version == "" && !p.Standard && !p.IsTestOnly() {
repoDir, vcsCmd, err = vcs.FromDir(base.Cwd(), "", allowNesting)
if err != nil && !errors.Is(err, os.ErrNotExist) {
setVCSError(err)
@@ -2648,6 +2664,9 @@ type PackageOpts struct {
// are not be matched, and their dependencies may not be loaded. A warning
// may be printed for non-literal arguments that match no main packages.
MainOnly bool
// LoadVCS controls whether we also load version-control metadata for main packages.
LoadVCS bool
}
// PackagesAndErrors returns the packages named by the command line arguments

View File

@@ -368,9 +368,9 @@ func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, co
if err != nil && pmain.Error == nil {
pmain.Error = &PackageError{Err: err}
}
if data != nil {
pmain.Internal.TestmainGo = &data
}
// Set TestmainGo even if it is empty: the presence of a TestmainGo
// indicates that this package is, in fact, a test main.
pmain.Internal.TestmainGo = &data
return pmain, ptest, pxtest
}

View File

@@ -288,6 +288,11 @@ func BinDir() string {
// operate in workspace mode. It should not be called by other commands,
// for example 'go mod tidy', that don't operate in workspace mode.
func InitWorkfile() {
if RootMode == NoRoot {
workFilePath = ""
return
}
switch gowork := cfg.Getenv("GOWORK"); gowork {
case "off":
workFilePath = ""

View File

@@ -802,7 +802,7 @@ var latestVersionIgnoringRetractionsCache par.Cache // path → queryLatestVersi
// an absolute path or a relative path starting with a '.' or '..'
// path component.
func ToDirectoryPath(path string) string {
if modfile.IsDirectoryPath(path) {
if path == "." || modfile.IsDirectoryPath(path) {
return path
}
// The path is not a relative path or an absolute path, so make it relative

View File

@@ -73,8 +73,6 @@ func printStderr(args ...any) (int, error) {
}
func runRun(ctx context.Context, cmd *base.Command, args []string) {
modload.InitWorkfile()
if shouldUseOutsideModuleMode(args) {
// Set global module flags for 'go run cmd@version'.
// This must be done before modload.Init, but we need to call work.BuildInit
@@ -84,7 +82,10 @@ func runRun(ctx context.Context, cmd *base.Command, args []string) {
modload.RootMode = modload.NoRoot
modload.AllowMissingModuleImports()
modload.Init()
} else {
modload.InitWorkfile()
}
work.BuildInit()
var b work.Builder
b.Init()

View File

@@ -312,7 +312,7 @@ func gitStatus(vcsGit *Cmd, rootDir string) (Status, error) {
// uncommitted files and skip tagging revision / committime.
var rev string
var commitTime time.Time
out, err = vcsGit.runOutputVerboseOnly(rootDir, "show -s --no-show-signature --format=%H:%ct")
out, err = vcsGit.runOutputVerboseOnly(rootDir, "-c log.showsignature=false show -s --format=%H:%ct")
if err != nil && !uncommitted {
return Status{}, err
} else if err == nil {

View File

@@ -379,7 +379,7 @@ func runBuild(ctx context.Context, cmd *base.Command, args []string) {
var b Builder
b.Init()
pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args)
pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{LoadVCS: cfg.BuildBuildvcs}, args)
load.CheckPackageErrors(pkgs)
explicitO := len(cfg.BuildO) > 0
@@ -603,7 +603,7 @@ func runInstall(ctx context.Context, cmd *base.Command, args []string) {
modload.InitWorkfile()
BuildInit()
pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{}, args)
pkgs := load.PackagesAndErrors(ctx, load.PackageOpts{LoadVCS: cfg.BuildBuildvcs}, args)
if cfg.ModulesEnabled && !modload.HasModRoot() {
haveErrors := false
allMissingErrors := true

View File

@@ -84,9 +84,8 @@ writing it back to go.mod. The JSON output corresponds to these Go types:
Version string
}
See the workspaces design proposal at
https://go.googlesource.com/proposal/+/master/design/45713-workspace.md for
more information.
See the workspaces reference at https://go.dev/ref/mod#workspaces
for more information.
`,
}

View File

@@ -27,6 +27,8 @@ modules will be created.
Each argument path is added to a use directive in the go.work file. The
current go version will also be listed in the go.work file.
See the workspaces reference at https://go.dev/ref/mod#workspaces
for more information.
`,
Run: runInit,
}

View File

@@ -33,6 +33,9 @@ if the dependency module's version is not already the same as the build
list's version. Note that Minimal Version Selection guarantees that the
build list's version of each module is always the same or higher than
that in each workspace module.
See the workspaces reference at https://go.dev/ref/mod#workspaces
for more information.
`,
Run: runSync,
}

View File

@@ -12,7 +12,6 @@ import (
"cmd/go/internal/modload"
"cmd/go/internal/str"
"context"
"errors"
"fmt"
"io/fs"
"os"
@@ -20,7 +19,7 @@ import (
)
var cmdUse = &base.Command{
UsageLine: "go work use [-r] [moddirs]",
UsageLine: "go work use [-r] moddirs",
Short: "add modules to workspace file",
Long: `Use provides a command-line interface for adding
directories, optionally recursively, to a go.work file.
@@ -33,6 +32,9 @@ The -r flag searches recursively for modules in the argument
directories, and the use command operates as if each of the directories
were specified as arguments: namely, use directives will be added for
directories that exist, and removed for directories that do not exist.
See the workspaces reference at https://go.dev/ref/mod#workspaces
for more information.
`,
}
@@ -82,13 +84,14 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) {
lookDir := func(dir string) {
absDir, dir := pathRel(workDir, dir)
fi, err := os.Stat(filepath.Join(absDir, "go.mod"))
fi, err := fsys.Stat(filepath.Join(absDir, "go.mod"))
if err != nil {
if os.IsNotExist(err) {
keepDirs[absDir] = ""
return
} else {
base.Errorf("go: %v", err)
}
base.Errorf("go: %v", err)
return
}
if !fi.Mode().IsRegular() {
@@ -101,14 +104,37 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) {
keepDirs[absDir] = dir
}
if len(args) == 0 {
base.Fatalf("go: 'go work use' requires one or more directory arguments")
}
for _, useDir := range args {
absArg, _ := pathRel(workDir, useDir)
info, err := fsys.Stat(absArg)
if err != nil {
// Errors raised from os.Stat are formatted to be more user-friendly.
if os.IsNotExist(err) {
base.Errorf("go: directory %v does not exist", absArg)
} else {
base.Errorf("go: %v", err)
}
continue
} else if !info.IsDir() {
base.Errorf("go: %s is not a directory", absArg)
continue
}
if !*useR {
lookDir(useDir)
continue
}
// Add or remove entries for any subdirectories that still exist.
err := fsys.Walk(useDir, func(path string, info fs.FileInfo, err error) error {
fsys.Walk(useDir, func(path string, info fs.FileInfo, err error) error {
if err != nil {
return err
}
if !info.IsDir() {
if info.Mode()&fs.ModeSymlink != 0 {
if target, err := fsys.Stat(path); err == nil && target.IsDir() {
@@ -120,13 +146,9 @@ func runUse(ctx context.Context, cmd *base.Command, args []string) {
lookDir(path)
return nil
})
if err != nil && !errors.Is(err, os.ErrNotExist) {
base.Errorf("go: %v", err)
}
// Remove entries for subdirectories that no longer exist.
// Because they don't exist, they will be skipped by Walk.
absArg, _ := pathRel(workDir, useDir)
for absDir, _ := range haveDirs {
if str.HasFilePathPrefix(absDir, absArg) {
if _, ok := keepDirs[absDir]; !ok {
@@ -186,5 +208,5 @@ func pathRel(workDir, dir string) (abs, canonical string) {
// Normalize relative paths to use slashes, so that checked-in go.work
// files with relative paths within the repo are platform-independent.
return abs, filepath.ToSlash(rel)
return abs, modload.ToDirectoryPath(rel)
}

View File

@@ -12,7 +12,7 @@ import (
var CmdWork = &base.Command{
UsageLine: "go work",
Short: "workspace maintenance",
Long: `Go workspace provides access to operations on workspaces.
Long: `Work provides access to operations on workspaces.
Note that support for workspaces is built into many other commands, not
just 'go work'.
@@ -20,6 +20,12 @@ just 'go work'.
See 'go help modules' for information about Go's module system of which
workspaces are a part.
See https://go.dev/ref/mod#workspaces for an in-depth reference on
workspaces.
See https://go.dev/doc/tutorial/workspaces for an introductory
tutorial on workspaces.
A workspace is specified by a go.work file that specifies a set of
module directories with the "use" directive. These modules are used as
root modules by the go command for builds and related operations. A

View File

@@ -0,0 +1,16 @@
[short] skip
go run example.com/printversion@v0.1.0
stdout '^main is example.com/printversion v0.1.0$'
-- go.work --
go 1.18
use (
.
)
-- go.mod --
module example
go 1.18
require example.com/printversion v1.0.0

View File

@@ -0,0 +1,92 @@
# https://go.dev/issue/51723: 'go test' should not stamp VCS metadata
# in the build settings. (It isn't worth the latency hit, given that
# test binaries are almost never distributed to users.)
[short] skip
[!exec:git] skip
exec git init
# The test binaries should not have VCS settings stamped.
# (The test itself verifies that.)
go test . ./testonly
# Remove 'git' from $PATH. The test should still build.
# This ensures that we aren't loading VCS metadata that
# we subsequently throw away.
env PATH=''
env path=''
# Compiling the test should not require the VCS tool.
go test -c -o $devnull .
# When listing a main package, in general we need its VCS metadata to determine
# the .Stale and .StaleReason fields.
! go list .
stderr '^go: missing Git command\. See https://golang\.org/s/gogetcmd\nerror obtaining VCS status: .*\n\tUse -buildvcs=false to disable VCS stamping.'
# Adding the -test flag should be strictly additive — it should not suppress the error.
! go list -test .
stderr '^go: missing Git command\. See https://golang\.org/s/gogetcmd\nerror obtaining VCS status: .*\n\tUse -buildvcs=false to disable VCS stamping.'
# Adding the suggested flag should suppress the error.
go list -test -buildvcs=false .
! stderr .
# Since the ./testonly package can't produce an actual binary, we shouldn't
# invoke a VCS tool to compute a build stamp when listing it.
go list ./testonly
! stderr .
go list -test ./testonly
! stderr .
-- go.mod --
module example
go 1.18
-- example.go --
package main
-- example_test.go --
package main
import (
"runtime/debug"
"strings"
"testing"
)
func TestDetail(t *testing.T) {
bi, ok := debug.ReadBuildInfo()
if !ok {
t.Fatal("BuildInfo not present")
}
for _, s := range bi.Settings {
if strings.HasPrefix(s.Key, "vcs.") {
t.Fatalf("unexpected VCS setting: %s=%s", s.Key, s.Value)
}
}
}
-- testonly/main_test.go --
package main
import (
"runtime/debug"
"strings"
"testing"
)
func TestDetail(t *testing.T) {
bi, ok := debug.ReadBuildInfo()
if !ok {
t.Fatal("BuildInfo not present")
}
for _, s := range bi.Settings {
if strings.HasPrefix(s.Key, "vcs.") {
t.Fatalf("unexpected VCS setting: %s=%s", s.Key, s.Value)
}
}
}

View File

@@ -0,0 +1,84 @@
# Test that minimization doesn't use dirty coverage snapshots when it
# is unable to actually minimize the input. We do this by checking that
# a expected value appears in the cache. If a dirty coverage map is used
# (i.e. the coverage map generated during the last minimization step,
# rather than the map provided with the initial input) then this value
# is unlikely to appear in the cache, since the map generated during
# the last minimization step should not increase the coverage.
[short] skip
[!fuzz-instrumented] skip
env GOCACHE=$WORK/gocache
go test -fuzz=FuzzCovMin -fuzztime=25s -test.fuzzcachedir=$GOCACHE/fuzz
go run check_file/main.go $GOCACHE/fuzz/FuzzCovMin abcd
-- go.mod --
module test
-- covmin_test.go --
package covmin
import "testing"
func FuzzCovMin(f *testing.F) {
f.Fuzz(func(t *testing.T, data []byte) {
if len(data) >= 4 && data[0] == 'a' && data[1] == 'b' && data[2] == 'c' && data[3] == 'd' {
return
}
})
}
-- check_file/main.go --
package main
import (
"bytes"
"fmt"
"os"
"path/filepath"
"regexp"
"strconv"
)
func checkFile(name, expected string) (bool, error) {
data, err := os.ReadFile(name)
if err != nil {
return false, err
}
for _, line := range bytes.Split(data, []byte("\n")) {
m := valRe.FindSubmatch(line)
if m == nil {
continue
}
fmt.Println(strconv.Unquote(string(m[1])))
if s, err := strconv.Unquote(string(m[1])); err != nil {
return false, err
} else if s == expected {
return true, nil
}
}
return false, nil
}
var valRe = regexp.MustCompile(`^\[\]byte\(([^)]+)\)$`)
func main() {
dir, expected := os.Args[1], os.Args[2]
ents, err := os.ReadDir(dir)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
for _, ent := range ents {
name := filepath.Join(dir, ent.Name())
if good, err := checkFile(name, expected); err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
} else if good {
os.Exit(0)
}
}
fmt.Fprintln(os.Stderr, "input over minimized")
os.Exit(1)
}

View File

@@ -127,19 +127,8 @@ func FuzzMinCache(f *testing.F) {
if bytes.Equal(buf, seed) {
return
}
if n := sum(buf); n < 0 {
t.Error("sum cannot be negative")
}
})
}
func sum(buf []byte) int {
n := 0
for _, b := range buf {
n += int(b)
}
return n
}
-- check_testdata/check_testdata.go --
//go:build ignore
// +build ignore

View File

@@ -111,7 +111,7 @@ rm $GOBIN/d$GOEXE
go list -x ./...
stdout -count=3 '^example.com'
stderr -count=1 '^git status'
stderr -count=1 '^git show'
stderr -count=1 '^git -c log.showsignature=false show'
-- $WORK/fakebin/git --
#!/bin/sh

View File

@@ -0,0 +1,17 @@
# Regression test for https://go.dev/issue/51448.
# 'go work init . foo/bar' should produce a go.work file
# with the same paths as 'go work init; go work use -r .'.
go work init . foo/bar
mv go.work go.work.init
go work init
go work use -r .
cmp go.work go.work.init
-- go.mod --
module example
go 1.18
-- foo/bar/go.mod --
module example
go 1.18

View File

@@ -14,16 +14,16 @@ use (
go 1.18
use (
foo
foo/bar/baz
./foo
./foo/bar/baz
)
-- go.want_work_other --
go 1.18
use (
foo
foo/bar/baz
other
./foo
./foo/bar/baz
./other
)
-- foo/go.mod --
module foo

View File

@@ -6,13 +6,13 @@ go 1.18
use (
.
sub
sub/dir/deleted
./sub
./sub/dir/deleted
)
-- go.work.want --
go 1.18
use sub/dir
use ./sub/dir
-- sub/README.txt --
A go.mod file has been deleted from this directory.
In addition, the entire subdirectory sub/dir/deleted

View File

@@ -31,7 +31,7 @@ grep '^use ["]?'$PWD'["]?$' ../../go.work
# resulting workspace would contain a duplicate module.
cp ../../go.work.orig ../../go.work
! go work use $PWD .
stderr '^go: already added "bar/baz" as "'$PWD'"$'
stderr '^go: already added "\./bar/baz" as "'$PWD'"$'
cmp ../../go.work ../../go.work.orig
@@ -43,7 +43,7 @@ go 1.18
-- go.work.rel --
go 1.18
use bar/baz
use ./bar/baz
-- bar/baz/go.mod --
module example/bar/baz
go 1.18

View File

@@ -0,0 +1,11 @@
# For now, 'go work use' requires arguments.
# (Eventually, we may may it implicitly behave like 'go work use .'.
! go work use
stderr '^go: ''go work use'' requires one or more directory arguments'
! go work use -r
stderr '^go: ''go work use'' requires one or more directory arguments'
-- go.work --
go 1.18

View File

@@ -0,0 +1,17 @@
! go work use foo bar baz
stderr '^go: '$WORK'[/\\]gopath[/\\]src[/\\]foo is not a directory'
stderr '^go: directory '$WORK'[/\\]gopath[/\\]src[/\\]baz does not exist'
cmp go.work go.work_want
! go work use -r qux
stderr '^go: '$WORK'[/\\]gopath[/\\]src[/\\]qux is not a directory'
-- go.work --
go 1.18
-- go.work_want --
go 1.18
-- foo --
-- qux --
-- bar/go.mod --
module bar

View File

@@ -355,7 +355,7 @@ func deadcode(ctxt *Link) {
// in the last pass.
rem := d.markableMethods[:0]
for _, m := range d.markableMethods {
if (d.reflectSeen && m.isExported()) || d.ifaceMethod[m.m] || d.genericIfaceMethod[m.m.name] {
if (d.reflectSeen && (m.isExported() || d.dynlink)) || d.ifaceMethod[m.m] || d.genericIfaceMethod[m.m.name] {
d.markMethod(m)
} else {
rem = append(rem, m)

View File

@@ -254,18 +254,18 @@ func For(obj types.Object) (Path, error) {
if tname.IsAlias() {
// type alias
if r := find(obj, T, path); r != nil {
if r := find(obj, T, path, nil); r != nil {
return Path(r), nil
}
} else {
if named, _ := T.(*types.Named); named != nil {
if r := findTypeParam(obj, typeparams.ForNamed(named), path); r != nil {
if r := findTypeParam(obj, typeparams.ForNamed(named), path, nil); r != nil {
// generic named type
return Path(r), nil
}
}
// defined (named) type
if r := find(obj, T.Underlying(), append(path, opUnderlying)); r != nil {
if r := find(obj, T.Underlying(), append(path, opUnderlying), nil); r != nil {
return Path(r), nil
}
}
@@ -279,7 +279,7 @@ func For(obj types.Object) (Path, error) {
if _, ok := o.(*types.TypeName); !ok {
if o.Exported() {
// exported non-type (const, var, func)
if r := find(obj, o.Type(), append(path, opType)); r != nil {
if r := find(obj, o.Type(), append(path, opType), nil); r != nil {
return Path(r), nil
}
}
@@ -299,7 +299,7 @@ func For(obj types.Object) (Path, error) {
if m == obj {
return Path(path2), nil // found declared method
}
if r := find(obj, m.Type(), append(path2, opType)); r != nil {
if r := find(obj, m.Type(), append(path2, opType), nil); r != nil {
return Path(r), nil
}
}
@@ -316,41 +316,44 @@ func appendOpArg(path []byte, op byte, arg int) []byte {
}
// find finds obj within type T, returning the path to it, or nil if not found.
func find(obj types.Object, T types.Type, path []byte) []byte {
//
// The seen map is used to short circuit cycles through type parameters. If
// nil, it will be allocated as necessary.
func find(obj types.Object, T types.Type, path []byte, seen map[*types.TypeName]bool) []byte {
switch T := T.(type) {
case *types.Basic, *types.Named:
// Named types belonging to pkg were handled already,
// so T must belong to another package. No path.
return nil
case *types.Pointer:
return find(obj, T.Elem(), append(path, opElem))
return find(obj, T.Elem(), append(path, opElem), seen)
case *types.Slice:
return find(obj, T.Elem(), append(path, opElem))
return find(obj, T.Elem(), append(path, opElem), seen)
case *types.Array:
return find(obj, T.Elem(), append(path, opElem))
return find(obj, T.Elem(), append(path, opElem), seen)
case *types.Chan:
return find(obj, T.Elem(), append(path, opElem))
return find(obj, T.Elem(), append(path, opElem), seen)
case *types.Map:
if r := find(obj, T.Key(), append(path, opKey)); r != nil {
if r := find(obj, T.Key(), append(path, opKey), seen); r != nil {
return r
}
return find(obj, T.Elem(), append(path, opElem))
return find(obj, T.Elem(), append(path, opElem), seen)
case *types.Signature:
if r := findTypeParam(obj, typeparams.ForSignature(T), path); r != nil {
if r := findTypeParam(obj, typeparams.ForSignature(T), path, seen); r != nil {
return r
}
if r := find(obj, T.Params(), append(path, opParams)); r != nil {
if r := find(obj, T.Params(), append(path, opParams), seen); r != nil {
return r
}
return find(obj, T.Results(), append(path, opResults))
return find(obj, T.Results(), append(path, opResults), seen)
case *types.Struct:
for i := 0; i < T.NumFields(); i++ {
f := T.Field(i)
fld := T.Field(i)
path2 := appendOpArg(path, opField, i)
if f == obj {
if fld == obj {
return path2 // found field var
}
if r := find(obj, f.Type(), append(path2, opType)); r != nil {
if r := find(obj, fld.Type(), append(path2, opType), seen); r != nil {
return r
}
}
@@ -362,7 +365,7 @@ func find(obj types.Object, T types.Type, path []byte) []byte {
if v == obj {
return path2 // found param/result var
}
if r := find(obj, v.Type(), append(path2, opType)); r != nil {
if r := find(obj, v.Type(), append(path2, opType), seen); r != nil {
return r
}
}
@@ -374,7 +377,7 @@ func find(obj types.Object, T types.Type, path []byte) []byte {
if m == obj {
return path2 // found interface method
}
if r := find(obj, m.Type(), append(path2, opType)); r != nil {
if r := find(obj, m.Type(), append(path2, opType), seen); r != nil {
return r
}
}
@@ -384,7 +387,14 @@ func find(obj types.Object, T types.Type, path []byte) []byte {
if name == obj {
return append(path, opObj)
}
if r := find(obj, T.Constraint(), append(path, opConstraint)); r != nil {
if seen[name] {
return nil
}
if seen == nil {
seen = make(map[*types.TypeName]bool)
}
seen[name] = true
if r := find(obj, T.Constraint(), append(path, opConstraint), seen); r != nil {
return r
}
return nil
@@ -392,11 +402,11 @@ func find(obj types.Object, T types.Type, path []byte) []byte {
panic(T)
}
func findTypeParam(obj types.Object, list *typeparams.TypeParamList, path []byte) []byte {
func findTypeParam(obj types.Object, list *typeparams.TypeParamList, path []byte, seen map[*types.TypeName]bool) []byte {
for i := 0; i < list.Len(); i++ {
tparam := list.At(i)
path2 := appendOpArg(path, opTypeParam, i)
if r := find(obj, tparam, path2); r != nil {
if r := find(obj, tparam, path2, seen); r != nil {
return r
}
}

View File

@@ -51,7 +51,7 @@ golang.org/x/sys/windows
# golang.org/x/term v0.0.0-20210927222741-03fcf44c2211
## explicit; go 1.17
golang.org/x/term
# golang.org/x/tools v0.1.9-0.20220124164225-97de9ec46646
# golang.org/x/tools v0.1.9-0.20220329150752-294080fd2f5a
## explicit; go 1.17
golang.org/x/tools/cover
golang.org/x/tools/go/analysis

View File

@@ -51,7 +51,7 @@ func p256GetScalar(out *[32]byte, in []byte) {
n := new(big.Int).SetBytes(in)
var scalarBytes []byte
if n.Cmp(p256Params.N) >= 0 {
if n.Cmp(p256Params.N) >= 0 || len(in) > len(out) {
n.Mod(n, p256Params.N)
scalarBytes = n.Bytes()
} else {

View File

@@ -136,3 +136,17 @@ func TestP256CombinedMult(t *testing.T) {
t.Errorf("1×G + (-1)×G = (%d, %d), should be ∞", x, y)
}
}
func TestIssue52075(t *testing.T) {
Gx, Gy := P256().Params().Gx, P256().Params().Gy
scalar := make([]byte, 33)
scalar[32] = 1
x, y := P256().ScalarBaseMult(scalar)
if x.Cmp(Gx) != 0 || y.Cmp(Gy) != 0 {
t.Errorf("unexpected output (%v,%v)", x, y)
}
x, y = P256().ScalarMult(Gx, Gy, scalar)
if x.Cmp(Gx) != 0 || y.Cmp(Gy) != 0 {
t.Errorf("unexpected output (%v,%v)", x, y)
}
}

View File

@@ -13,6 +13,9 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
certs := macOS.CFArrayCreateMutable()
defer macOS.ReleaseCFArray(certs)
leaf := macOS.SecCertificateCreateWithData(c.Raw)
if leaf == 0 {
return nil, errors.New("invalid leaf certificate")
}
macOS.CFArrayAppendValue(certs, leaf)
if opts.Intermediates != nil {
for _, lc := range opts.Intermediates.lazyCerts {
@@ -21,7 +24,9 @@ func (c *Certificate) systemVerify(opts *VerifyOptions) (chains [][]*Certificate
return nil, err
}
sc := macOS.SecCertificateCreateWithData(c.Raw)
macOS.CFArrayAppendValue(certs, sc)
if sc != 0 {
macOS.CFArrayAppendValue(certs, sc)
}
}
}

View File

@@ -7,7 +7,11 @@ package x509_test
import (
"crypto/tls"
"crypto/x509"
"errors"
"internal/testenv"
"net"
"strings"
"syscall"
"testing"
"time"
)
@@ -17,10 +21,19 @@ func TestPlatformVerifier(t *testing.T) {
t.Skip()
}
getChain := func(host string) []*x509.Certificate {
getChain := func(t *testing.T, host string) []*x509.Certificate {
t.Helper()
c, err := tls.Dial("tcp", host+":443", &tls.Config{InsecureSkipVerify: true})
if err != nil {
// From https://docs.microsoft.com/en-us/windows/win32/winsock/windows-sockets-error-codes-2,
// matching the error string observed in https://go.dev/issue/52094.
const WSATRY_AGAIN syscall.Errno = 11002
var errDNS *net.DNSError
if strings.HasSuffix(host, ".badssl.com") && errors.As(err, &errDNS) && strings.HasSuffix(errDNS.Err, WSATRY_AGAIN.Error()) {
t.Log(err)
testenv.SkipFlaky(t, 52094)
}
t.Fatalf("tls connection failed: %s", err)
}
return c.ConnectionState().PeerCertificates
@@ -74,7 +87,7 @@ func TestPlatformVerifier(t *testing.T) {
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
chain := getChain(tc.host)
chain := getChain(t, tc.host)
var opts x509.VerifyOptions
if len(chain) > 1 {
opts.Intermediates = x509.NewCertPool()

Some files were not shown because too many files have changed in this diff Show More