Compare commits

...

125 Commits

Author SHA1 Message Date
Gopher Robot
be59153dd8 [release-branch.go1.18] go1.18.5
Change-Id: I4ca2e873fa21fb4676bc1d0e382bd8fd407a2986
Reviewed-on: https://go-review.googlesource.com/c/go/+/420555
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Gopher Robot <gobot@golang.org>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-08-01 15:12:43 +00:00
Roland Shoemaker
9240558e4f [release-branch.go1.18] math/big: check buffer lengths in GobDecode
In Float.GobDecode and Rat.GobDecode, check buffer sizes before
indexing slices.

Updates #53871
Fixes #54095

Change-Id: I1b652c32c2bc7a0e8aa7620f7be9b2740c568b0a
Reviewed-on: https://go-review.googlesource.com/c/go/+/417774
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Tatiana Bradley <tatiana@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
(cherry picked from commit 055113ef36)
Reviewed-on: https://go-review.googlesource.com/c/go/+/419815
Reviewed-by: Julie Qiu <julieqiu@google.com>
2022-07-29 14:06:25 +00:00
Bryan C. Mills
be7c681478 [release-branch.go1.18] cmd/go: avoid re-enqueuing workspace dependencies with errors
Fixes #53875.
Updates #53874.

Change-Id: I41ab15cb9b86b807a9d9ad21fe21fb7aa5fbb46f
Reviewed-on: https://go-review.googlesource.com/c/go/+/417594
Run-TryBot: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Hyang-Ah Hana Kim <hyangah@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit a906d3dd09)
Reviewed-on: https://go-review.googlesource.com/c/go/+/417656
2022-07-27 17:20:18 +00:00
Matthew Dempsky
6ff8801d3e [release-branch.go1.18] cmd/compile: revert "fix missing dict pass for type assertions"
This reverts CL 411934 (commit 460a93b54a).

Fixes #53852.
Updates #53357.

Change-Id: I93d7015d8962d22ffd73128b038e4e7e7ca41c2f
Reviewed-on: https://go-review.googlesource.com/c/go/+/417615
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-27 16:55:10 +00:00
Matthew Dempsky
76ba1a5e55 [release-branch.go1.18] cmd/compile: revert "backport fix for #51840"
This reverts CL 405436 (commit e1b14f53c1).

Fixes #53883.
Updates #51840.

Change-Id: Ide5a9568a7ae5b449ef154c29b69699a7e4b3f6b
Reviewed-on: https://go-review.googlesource.com/c/go/+/417616
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Jenny Rakoczy <jenny@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-27 16:54:19 +00:00
Cherry Mui
ed50277fd9 [release-branch.go1.18] cmd/compile: do not use special literal assignment if LHS is address-taken
A composite literal assignment

x = T{field: v}

may be compiled to

x = T{}
x.field = v

We already do not use this form is RHS uses LHS. If LHS is
address-taken, RHS may uses LHS implicitly, e.g.

v = &x.field
x = T{field: *v}

The lowering above would change the value of RHS (*v).

Updates #52953.
Fixes #52961.

Change-Id: I3f798e00598aaa550b8c17182c7472fef440d483
Reviewed-on: https://go-review.googlesource.com/c/go/+/407014
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.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 1c77137d4f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/419450
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
2022-07-26 14:15:46 +00:00
Bryan C. Mills
d06c911fe1 [release-branch.go1.18] testing: include ERROR_SHARING_VIOLATION in Windows cleanup retries
Fixes #52986
Updates #51442
Updates #50051

Change-Id: I1bfbc08c907077467fd50febbec6299a9b73af41
Reviewed-on: https://go-review.googlesource.com/c/go/+/388916
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit eeb9f095dc)
Reviewed-on: https://go-review.googlesource.com/c/go/+/407877
Reviewed-by: Nooras Saba‎ <saba@golang.org>
Auto-Submit: Bryan Mills <bcmills@google.com>
2022-07-25 23:29:29 +00:00
Bryan C. Mills
d252fdd630 [release-branch.go1.18] cmd/go: omit build metadata that may contain system paths when -trimpath is set
CGO flag variables often include system paths for header files and
compiled libraries. The point of -trimpath is to avoid dependending on
system paths, so stamping these variables is counterproductive.

Moreover, the point of stamping build information is to improve
reproducibility. Since we don't also stamp the versions of C
compilers, headers, and libraries used in a cgo build, only the most
trivial cgo programs can be faithfully reproduced from the stamped
information.

Likewise, the -ldflags flag may include system-specific paths,
particularly if external linking is in use. For now, we omit -ldflags
entirely; however, in the future we may instead want to parse and
redact the individual flags.

Updates #52372.
Fixes #53119.

Change-Id: I73318a01cce4371d66955b3261fc7ee58d4b33dd
Reviewed-on: https://go-review.googlesource.com/c/go/+/409174
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>
(cherry picked from commit a6e5be0d30)
Reviewed-on: https://go-review.googlesource.com/c/go/+/414794
Reviewed-by: Nooras Saba‎ <saba@golang.org>
2022-07-25 23:27:36 +00:00
Michael Pratt
4782f4275c [release-branch.go1.18] runtime: clear timerModifiedEarliest when last timer is deleted
timerModifiedEarliest contains the lowest possible expiration for a
modified earlier timer, which may be earlier than timer0When because we
haven't yet updated the heap. Note "may", as the modified earlier timer
that set timerModifiedEarliest may have since been modified later or
deleted.

We can clear timerModifiedEarliest when the last timer is deleted
because by definition there must not be any modified earlier timers.

Why does this matter? checkTimersNoP claims that there is work to do if
timerModifiedEarliest has passed, causing findRunnable to loop back
around to checkTimers. But the code to clean up timerModifiedEarliest in
checkTimers (i.e., the call to adjusttimers) is conditional behind a
check that len(pp.timers) > 0.

Without clearing timerModifiedEarliest, a spinning M that would
otherwise go to sleep will busy loop in findRunnable until some other
work is available.

Note that changing the condition on the call to adjusttimers would also
be a valid fix. I took this approach because it feels a bit cleaner to
clean up timerModifiedEarliest as soon as it is known to be irrelevant.

For #51654.
Fixes #53847.

Change-Id: I3f3787c67781cac7ce87939c5706cef8db927dd5
Reviewed-on: https://go-review.googlesource.com/c/go/+/417434
Auto-Submit: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Michael Pratt <mpratt@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
(cherry picked from commit c006b7ac27)
Reviewed-on: https://go-review.googlesource.com/c/go/+/417475
2022-07-25 23:11:17 +00:00
Cherry Mui
12e00f6c6b [release-branch.go1.18] runtime: use saved LR when unwinding through morestack
On LR machine, consider F calling G calling H, which grows stack.
The stack looks like
...
G's frame:
	... locals ...
	saved LR = return PC in F  <- SP points here at morestack
H's frame (to be created)

At morestack, we save
	gp.sched.pc = H's morestack call
	gp.sched.sp = H's entry SP (the arrow above)
	gp.sched.lr = return PC in G

Currently, when unwinding through morestack (if _TraceJumpStack
is set), we switch PC and SP but not LR. We then have
	frame.pc = H's morestack call
	frame.sp = H's entry SP (the arrow above)
As LR is not set, we load it from stack at *sp, so
	frame.lr = return PC in F
As the SP hasn't decremented at the morestack call,
	frame.fp = frame.sp = H's entry SP

Unwinding a frame, we have
	frame.pc = old frame.lr = return PC in F
	frame.sp = old frame.fp = H's entry SP a.k.a. G's SP
The PC and SP don't match. The unwinding will go off if F and G
have different frame sizes.

Fix this by preserving the LR when switching stack.

Also add code to detect infinite loop in unwinding.

TODO: add some test. I can reproduce the infinite loop (or throw
with added check) but the frequency is low.

Fixes #53112.
Updates #52116.

Change-Id: I6e1294f1c6e55f664c962767a1cf6c466a0c0eff
Reviewed-on: https://go-review.googlesource.com/c/go/+/400575
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Eric Fang <eric.fang@arm.com>
Reviewed-by: Benny Siegert <bsiegert@gmail.com>
(cherry picked from commit 74f0009422)
Reviewed-on: https://go-review.googlesource.com/c/go/+/408821
Reviewed-by: Austin Clements <austin@google.com>
2022-07-22 17:25:27 +00:00
Gopher Robot
88a06f40df [release-branch.go1.18] go1.18.4
Change-Id: I9f64c24e60775e23095bf144fecad32e13fbd9d7
Reviewed-on: https://go-review.googlesource.com/c/go/+/417177
Run-TryBot: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2022-07-12 19:56:08 +00:00
Roland Shoemaker
fb979a5082 [release-branch.go1.18] encoding/gob: add a depth limit for ignored fields
Enforce a nesting limit of 10,000 for ignored fields during decoding
of messages. This prevents the possibility of triggering stack
exhaustion.

Fixes #53710
Updates #53615
Fixes CVE-2022-30635

Change-Id: I05103d06dd5ca3945fcba3c1f5d3b5a645e8fb0f
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1484771
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Tatiana Bradley <tatianabradley@google.com>
(cherry picked from commit 55e8f938d22bfec29cc9dc9671044c5a41d1ea9c)
Reviewed-on: https://go-review.googlesource.com/c/go/+/417060
Reviewed-by: Tatiana Bradley <tatiana@golang.org>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-07-12 15:06:49 +00:00
Julie Qiu
5ebd862b17 [release-branch.go1.18] path/filepath: fix stack exhaustion in Glob
A limit is added to the number of path separators allowed by an input to
Glob, to prevent stack exhaustion issues.

Thanks to Juho Nurminen of Mattermost who reported the issue.

Fixes #53714
Updates #53416
Fixes CVE-2022-30632

Change-Id: I1b9fd4faa85411a05dbc91dceae1c0c8eb021f07
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1498176
Reviewed-by: Roland Shoemaker <bracewell@google.com>
(cherry picked from commit d182a6d1217fd0d04c9babfa9a7ccd3515435c39)
Reviewed-on: https://go-review.googlesource.com/c/go/+/417059
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
2022-07-12 15:06:43 +00:00
Julie Qiu
315e80d293 [release-branch.go1.18] io/fs: fix stack exhaustion in Glob
A limit is added to the number of path separators allowed by an input to
Glob, to prevent stack exhaustion issues.

Thanks to Juho Nurminen of Mattermost who reported a similar issue in
path/filepath.

Fixes #53720
Updates #53415
Fixes CVE-2022-30630

Change-Id: I5a9d02591fed90cd3d52627f5945f1301e53465d
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1497588
Reviewed-by: Roland Shoemaker <bracewell@google.com>
(cherry picked from commit fdccc5d7bd0f276d0a8de3a818ca844f0bed5d97)
Reviewed-on: https://go-review.googlesource.com/c/go/+/417058
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-07-12 15:06:37 +00:00
Tatiana Bradley
8e27a8ac4c [release-branch.go1.18] compress/gzip: fix stack exhaustion bug in Reader.Read
Replace recursion with iteration in Reader.Read to avoid stack
exhaustion when there are a large number of files.

Fixes CVE-2022-30631
Fixes #53718
Updates #53168

Change-Id: I47d8afe3f2d40b0213ab61431df9b221794dbfe0
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1455673
Reviewed-by: Roland Shoemaker <bracewell@google.com>
Reviewed-by: Julie Qiu <julieqiu@google.com>
(cherry picked from commit cf498969c8a0bae9d7a24b98fc1f66c824a4775d)
Reviewed-on: https://go-review.googlesource.com/c/go/+/417057
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-07-12 15:06:32 +00:00
Roland Shoemaker
0d1615b23f [release-branch.go1.18] go/parser: limit recursion depth
Limit nested parsing to 100,000, which prevents stack exhaustion when
parsing deeply nested statements, types, and expressions. Also limit
the scope depth to 1,000 during object resolution.

Thanks to Juho Nurminen of Mattermost for reporting this issue.

Fixes #53708
Updates #53616
Fixes CVE-2022-1962

Change-Id: I4d7b86c1d75d0bf3c7af1fdea91582aa74272c64
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1491025
Reviewed-by: Russ Cox <rsc@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
(cherry picked from commit 6a856f08d58e4b6705c0c337d461c540c1235c83)
Reviewed-on: https://go-review.googlesource.com/c/go/+/417056
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-07-12 15:06:26 +00:00
Roland Shoemaker
2924ced71d [release-branch.go1.18] encoding/xml: limit depth of nesting in unmarshal
Prevent exhausting the stack limit when unmarshalling extremely deeply
nested structures into nested types.

Fixes #53716
Updates #53611
Fixes CVE-2022-30633

Change-Id: Ic6c5d41674c93cfc9a316135a408db9156d39c59
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1421319
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Julie Qiu <julieqiu@google.com>
(cherry picked from commit ebee00a55e28931b2cad0e76207a73712b000432)
Reviewed-on: https://go-review.googlesource.com/c/go/+/417055
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
2022-07-12 15:06:21 +00:00
Roland Shoemaker
90f040ec51 [release-branch.go1.18] encoding/xml: use iterative Skip, rather than recursive
Prevents exhausting the stack limit in _incredibly_ deeply nested
structures.

Fixes #53712
Updates #53614
Fixes CVE-2022-28131

Change-Id: I47db4595ce10cecc29fbd06afce7b299868599e6
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1419912
Reviewed-by: Julie Qiu <julieqiu@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
(cherry picked from commit 9278cb78443d2b4deb24cbb5b61c9ba5ac688d49)
Reviewed-on: https://go-review.googlesource.com/c/go/+/417054
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
2022-07-12 15:06:15 +00:00
Damien Neil
ebea1e3353 [release-branch.go1.18] net/http: preserve nil values in Header.Clone
ReverseProxy makes a distinction between nil and zero-length header values.
Avoid losing nil-ness when cloning a request.

Thanks to Christian Mehlmauer for discovering this.

For #53423
For CVE-2022-32148
Fixes #53621

Change-Id: Ice369cdb4712e2d62e25bb881b080847aa4801f5
Reviewed-on: https://go-review.googlesource.com/c/go/+/412857
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
(cherry picked from commit b2cc0fecc2)
Reviewed-on: https://go-review.googlesource.com/c/go/+/415222
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
Run-TryBot: Heschi Kreinick <heschi@google.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
2022-07-12 14:51:53 +00:00
Damien Neil
222ee24a00 [release-branch.go1.18] net/http: don't strip whitespace from Transfer-Encoding headers
Do not accept "Transfer-Encoding: \rchunked" as a valid TE header
setting chunked encoding.

Thanks to Zeyu Zhang (https://www.zeyu2001.com/) for identifying
the issue.

For #53188
For CVE-2022-1705
Fixes #53433

Change-Id: I1a16631425159267f2eca68056b057192a7edf6c
Reviewed-on: https://go-review.googlesource.com/c/go/+/409874
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
(cherry picked from commit e5017a93fc)
Reviewed-on: https://go-review.googlesource.com/c/go/+/415218
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
2022-07-12 14:50:47 +00:00
Cuong Manh Le
93aab18139 [release-branch.go1.18] cmd/compile: only check implicit dots for method call enabled by a type bound
Fixes #53723

Change-Id: Ibad64f5c4af2112deeb0a9ecc9c589b17594bd05
Reviewed-on: https://go-review.googlesource.com/c/go/+/414836
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/416155
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-07-07 17:30:11 +00:00
Paul E. Murphy
3a7cec2773 [release-branch.go1.18] cmd/link: use TOC-relative trampolines on PPC64 when needed
When linking a PIE binary with the internal linker, TOC relative
relocations need to be generated. Update trampolines to indirect
call using R12 to more closely match the AIX/ELFv2 regardless of
buildmode, and work with position-indepdent code.

Likewise, update the check for offseting R_CALLPOWER relocs to
make a local call. It should be checking ldr.AttrExternal, not
ldr.IsExternal. This offset should not be adjusted for external
(non-go) object files, it is handled when ELF reloc are translated
into go relocs.

And, update trampoline tests to verify these are generated correctly
and produce a working binary using -buildmode=pie on ppc64le.

Fixes #53107

Change-Id: I8a2dea06c3237bdf0e87888b56a17b6c4c99a7de
Reviewed-on: https://go-review.googlesource.com/c/go/+/400234
Reviewed-by: Than McIntosh <thanm@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Paul Murphy <murp@ibm.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/409075
Run-TryBot: Cherry Mui <cherryyz@google.com>
2022-07-06 20:55:56 +00:00
Cherry Mui
b80ae10221 [release-branch.go1.18] cmd/link: preserve symbol attributes when cloning to external
There are some symbol attributes that are encoded in the object
file. Currently, they are lost when cloning a symbol to external.
Copy them over.

Also delete CopyAttributes as it is no longer called anywhere.

For #53107. Backporting this CL as the fix of #53107 depends on
it.

Change-Id: I1497e3223a641704bf35aa3e904dd0eda2f8ec3e
Reviewed-on: https://go-review.googlesource.com/c/go/+/400574
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 df08c9a821)
Reviewed-on: https://go-review.googlesource.com/c/go/+/408820
2022-07-06 20:32:07 +00:00
Michael Pratt
e5ca37df46 [release-branch.go1.18] runtime: add race annotations to cbs.lock
cbs.lock protects a map. The map implementation is race instrumented
regardless of which package is it called from.

lock/unlock are not automatically race instrumented, so we can trigger
race false positives without manually annotating our lock acquire and
release.

compileCallback is used during initialization before the P is available,
at which point raceacquire will crash during a racecallback to get the
race proc. Thus we skip instrumentation until scheduler initialization
is complete.

Fixes #53613.
For #50249.

Change-Id: Ie49227c9e9210ffbf0aee65f86f2b7b6a2f64638
Reviewed-on: https://go-review.googlesource.com/c/go/+/414518
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Michael Pratt <mpratt@google.com>
(cherry picked from commit 20760cff00)
Reviewed-on: https://go-review.googlesource.com/c/go/+/415198
Run-TryBot: Heschi Kreinick <heschi@google.com>
2022-07-06 20:16:26 +00:00
Keith Randall
5f2dff9b66 [release-branch.go1.18] cmd/compile: fix prove pass when upper condition is <= maxint
When the terminating condition is <= X, we need to make sure that
X+step doesn't overflow.

Fixes #53618

Change-Id: I36e5384d05b4d7168e48db6094200fcae409bfe5
Reviewed-on: https://go-review.googlesource.com/c/go/+/415219
Reviewed-by: Than McIntosh <thanm@google.com>
Run-TryBot: David Chase <drchase@google.com>
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
(cherry picked from commit 31b8c23c57)
Reviewed-on: https://go-review.googlesource.com/c/go/+/415414
Reviewed-by: Keith Randall <khr@google.com>
2022-07-06 19:44:10 +00:00
Michael Pratt
2f43de6da0 [release-branch.go1.18] runtime: add race annotations to metricsSema
metricsSema protects the metrics map. The map implementation is race
instrumented regardless of which package is it called from.

semacquire/semrelease are not automatically race instrumented, so we can
trigger race false positives without manually annotating our lock
acquire and release.

See similar instrumentation on trace.shutdownSema and reflectOffs.lock.

Fixes #53590.
For #53542.

Change-Id: Ia3fd239ac860e037d09c7cb9c4ad267391e70705
Reviewed-on: https://go-review.googlesource.com/c/go/+/414517
Run-TryBot: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Cherry Mui <cherryyz@google.com>
(cherry picked from commit d6481d5b96)
Reviewed-on: https://go-review.googlesource.com/c/go/+/415195
2022-07-06 19:34:57 +00:00
hidu
1872c338a3 [release-branch.go1.18] cmd/go: pass --no-decorate when listing git tags for a commit
This avoids a parse error when the user's global .gitconfig sets
log.decorate to true.

Updates #51312.
Fixes #53588.

Change-Id: Ic47b0f604c0c3a404ec50d6e09f4e138045ac2f2
Reviewed-on: https://go-review.googlesource.com/c/go/+/387835
Run-TryBot: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
(cherry picked from commit a30f434667)
Reviewed-on: https://go-review.googlesource.com/c/go/+/414874
2022-07-06 19:34:16 +00:00
Cuong Manh Le
f86c6b9a32 [release-branch.go1.18] cmd/compile: fix generic inter-inter comparisons from value switch statements
If value is a non-empty interface and has shape, we still need to
convert it to an interface{} first.

Fixes #53587

Change-Id: I516063ba4429a6cc24c483758387ec13815fc63e
Reviewed-on: https://go-review.googlesource.com/c/go/+/414834
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/414835
2022-07-06 19:33:49 +00:00
Keith Randall
eeef5ebd84 [release-branch.go1.18] cmd/compile: allow 128-bit values to be spilled
We sometimes use 16-byte load+store to move values around in memory.
In rare circumstances, the loaded value must be spilled because the
store can't happen yet.

In that case, we need to be able to spill the 16-byte value.

Fixes #53471

Change-Id: I09fd08e11a63c6ba3ef781d3f5ede237e9b0132e
Reviewed-on: https://go-review.googlesource.com/c/go/+/413294
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
(cherry picked from commit c2d373d5d1)
Reviewed-on: https://go-review.googlesource.com/c/go/+/413455
Reviewed-by: Alex Rakoczy <jenny@golang.org>
2022-07-06 19:33:22 +00:00
Cuong Manh Le
460a93b54a [release-branch.go1.18] cmd/compile: fix missing dict pass for type assertions
For type assertions, if either src or dst type has shape, we must
convert them to dynamic type assertions.

Fixes #53357

Change-Id: Ia3362fa67c011febcbdb5b26f856d081b5c366de
Reviewed-on: https://go-review.googlesource.com/c/go/+/411617
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/411934
Reviewed-by: Keith Randall <khr@google.com>
2022-07-06 19:31:41 +00:00
Cuong Manh Le
3da88c0bdc [release-branch.go1.18] cmd/compile: fix wrong unsafe.Offsetof evaluation inside generic function
For instantiated generic functions, all implicit dot operations are
resolved. Thus unsafe.Offsetof may calculating the offset against the
wrong base selector.

To fix it, we must remove any implicit dot operations to find the first
non-implicit one, which is the right base selector for calculating the
offset.

Fixes #53159

Change-Id: I38504067ce0f274615b306edc8f7d7933bdb631a
Reviewed-on: https://go-review.googlesource.com/c/go/+/409355
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Keith Randall <khr@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/409494
2022-07-06 19:31:10 +00:00
Michael Anthony Knyszek
f0eca661ea [release-branch.go1.18] runtime: store consistent total allocation stats as uint64
Currently the consistent total allocation stats are managed as uintptrs,
which means they can easily overflow on 32-bit systems. Fix this by
storing these stats as uint64s. This will cause some minor performance
degradation on 32-bit systems, but there really isn't a way around this,
and it affects the correctness of the metrics we export.

For #52680.
Fixes #52689.

Change-Id: I8b1926116e899ae9f03d58e0320bcb9264945b3e
Reviewed-on: https://go-review.googlesource.com/c/go/+/411495
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Michael Pratt <mpratt@google.com>
2022-07-06 19:27:52 +00:00
Dmitri Shuralyov
4068be56ce [release-branch.go1.18] go1.18.3
Change-Id: I89e0df420c0626add131103015cadd7b3f3dfd98
Reviewed-on: https://go-review.googlesource.com/c/go/+/409735
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Alex Rakoczy <alex@golang.org>
2022-06-01 16:38:24 +00:00
Yasuhiro Matsumoto
5a89bb334d [release-branch.go1.18] path/filepath: do not remove prefix "." when following path contains ":".
For #52476
Fixes #52479
Fixes CVE-2022-29804

Change-Id: I9eb72ac7dbccd6322d060291f31831dc389eb9bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/401595
Auto-Submit: Ian Lance Taylor <iant@google.com>
Reviewed-by: Alex Brainman <alex.brainman@gmail.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Damien Neil <dneil@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/405234
Reviewed-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
2022-05-31 17:30:10 +00:00
Bryan C. Mills
da608a20ed [release-branch.go1.18] misc/cgo/testsanitizers: buffer the signal channel in TestTSAN/tsan11
This fix is analogous to the one in CL 407888.

'go vet' catches the error, but it is not run on this file because the
file is (only) compiled when running testsanitizers/TestTSAN.

Fixes #53115.
Updates #53113.

Change-Id: I74f7b7390a9775ff00a06214c1019ba28846dd11
Reviewed-on: https://go-review.googlesource.com/c/go/+/409094
Auto-Submit: Bryan Mills <bcmills@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Bryan Mills <bcmills@google.com>
(cherry picked from commit 0f57c88bce)
Reviewed-on: https://go-review.googlesource.com/c/go/+/408823
Reviewed-by: Ian Lance Taylor <iant@google.com>
2022-05-30 20:29:29 +00:00
David Taylor
a34f420774 [release-branch.go1.18] crypto/tls: avoid extra allocations in steady-state Handshake calls
The Read and Write methods of *tls.Conn call Handshake
unconditionally, every time they are called, expecting it to only
perform a new handshake if required.

However in go 1.17 handshakeContext was extended to set up a
cancelable Context, and importantly did so prior to checking if a
handshake is required. This thus causes it to allocate on every call,
even in those that are no-ops when called in a Read or Write on an
established connection, sometimes leading to very large numbers of
allocations during reads.

This change adds an early return, prior to setting up the context or
proceeding into the handshakeMutex and checking the handshake error, if
the handshake status atomic indicates handshake is already complete.

name                                     old allocs/op  new allocs/op  delta
Throughput/MaxPacket/1MB/TLSv12-10          1.07k ± 0%     0.62k ± 0%  -42.16%  (p=0.000 n=4+5)
Throughput/MaxPacket/1MB/TLSv13-10          1.70k ± 0%     1.25k ± 0%     ~     (p=0.079 n=4+5)
Throughput/MaxPacket/2MB/TLSv12-10          1.62k ± 0%     0.73k ± 0%  -55.18%  (p=0.008 n=5+5)
Throughput/MaxPacket/2MB/TLSv13-10          2.26k ± 0%     1.36k ± 0%  -39.64%  (p=0.008 n=5+5)
Throughput/MaxPacket/4MB/TLSv12-10          2.74k ± 0%     0.95k ± 0%  -65.35%  (p=0.008 n=5+5)
Throughput/MaxPacket/4MB/TLSv13-10          3.37k ± 0%     1.58k ± 0%  -53.15%  (p=0.008 n=5+5)
Throughput/MaxPacket/8MB/TLSv12-10          4.96k ± 0%     1.39k ± 0%  -72.06%  (p=0.016 n=4+5)
Throughput/MaxPacket/8MB/TLSv13-10          5.60k ± 0%     2.01k ± 0%  -64.05%  (p=0.008 n=5+5)
Throughput/MaxPacket/16MB/TLSv12-10         9.42k ± 0%     2.27k ± 1%  -75.92%  (p=0.016 n=4+5)
Throughput/MaxPacket/16MB/TLSv13-10         10.0k ± 0%      2.9k ± 0%  -71.39%  (p=0.008 n=5+5)
Throughput/MaxPacket/32MB/TLSv12-10         18.3k ± 0%      4.0k ± 0%  -77.97%  (p=0.008 n=5+5)
Throughput/MaxPacket/32MB/TLSv13-10         18.9k ± 0%      4.6k ± 0%  -75.62%  (p=0.008 n=5+5)
Throughput/MaxPacket/64MB/TLSv12-10         36.2k ± 0%      7.5k ± 0%  -79.15%  (p=0.008 n=5+5)
Throughput/MaxPacket/64MB/TLSv13-10         36.7k ± 0%      8.1k ± 0%  -78.06%  (p=0.008 n=5+5)
Throughput/DynamicPacket/1MB/TLSv12-10      1.12k ± 0%     0.63k ± 0%  -44.20%  (p=0.008 n=5+5)
Throughput/DynamicPacket/1MB/TLSv13-10      1.76k ± 0%     1.26k ± 0%  -28.22%  (p=0.016 n=5+4)
Throughput/DynamicPacket/2MB/TLSv12-10      1.68k ± 0%     0.74k ± 0%  -56.11%  (p=0.008 n=5+5)
Throughput/DynamicPacket/2MB/TLSv13-10      2.32k ± 0%     1.37k ± 0%  -40.80%  (p=0.008 n=5+5)
Throughput/DynamicPacket/4MB/TLSv12-10      2.80k ± 0%     0.96k ± 0%  -65.81%  (p=0.008 n=5+5)
Throughput/DynamicPacket/4MB/TLSv13-10      3.43k ± 0%     1.59k ± 0%  -53.57%  (p=0.008 n=5+5)
Throughput/DynamicPacket/8MB/TLSv12-10      5.03k ± 0%     1.39k ± 0%  -72.27%  (p=0.008 n=5+5)
Throughput/DynamicPacket/8MB/TLSv13-10      5.66k ± 0%     2.02k ± 0%  -64.27%  (p=0.008 n=5+5)
Throughput/DynamicPacket/16MB/TLSv12-10     9.48k ± 0%     2.28k ± 1%  -75.98%  (p=0.008 n=5+5)
Throughput/DynamicPacket/16MB/TLSv13-10     10.1k ± 0%      2.9k ± 0%  -71.34%  (p=0.008 n=5+5)
Throughput/DynamicPacket/32MB/TLSv12-10     18.4k ± 0%      4.0k ± 0%  -78.13%  (p=0.008 n=5+5)
Throughput/DynamicPacket/32MB/TLSv13-10     19.0k ± 0%      4.6k ± 0%  -75.54%  (p=0.008 n=5+5)
Throughput/DynamicPacket/64MB/TLSv12-10     36.2k ± 0%      7.6k ± 1%  -79.02%  (p=0.008 n=5+5)
Throughput/DynamicPacket/64MB/TLSv13-10     36.8k ± 0%      8.2k ± 1%  -77.76%  (p=0.008 n=5+5)

Fixes #52791

Change-Id: Iacb1f9bf7802022960d9dbce141b8c0587a614d4
Reviewed-on: https://go-review.googlesource.com/c/go/+/379034
Reviewed-by: David Chase <drchase@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Filippo Valsorda <valsorda@google.com>
Auto-Submit: Filippo Valsorda <filippo@golang.org>
Run-TryBot: Filippo Valsorda <filippo@golang.org>
(cherry picked from commit a4af356075)
Reviewed-on: https://go-review.googlesource.com/c/go/+/405545
Reviewed-by: Roland Shoemaker <roland@golang.org>
Reviewed-by: Alex Rakoczy <alex@golang.org>
2022-05-27 14:59:08 +00:00
Tatiana Bradley
c838098c32 [release-branch.go1.18 crypto/tls: randomly generate ticket_age_add
As required by RFC 8446, section 4.6.1, ticket_age_add now holds a
random 32-bit value. Before this change, this value was always set
to 0.

This change also documents the reasoning for always setting
ticket_nonce to 0. The value ticket_nonce must be unique per
connection, but we only ever send one ticket per connection.

Updates #52814
Fixes #52833
Fixes CVE-2022-30629

Change-Id: I6c2fc6ca0376b7b968abd59d6d3d3854c1ab68bb
Reviewed-on: https://go-review.googlesource.com/c/go/+/405994
Reviewed-by: Tatiana Bradley <tatiana@golang.org>
Reviewed-by: Roland Shoemaker <roland@golang.org>
Run-TryBot: Tatiana Bradley <tatiana@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit fe4de36198)
Reviewed-on: https://go-review.googlesource.com/c/go/+/408575
Run-TryBot: Roland Shoemaker <roland@golang.org>
2022-05-27 14:58:06 +00:00
Russ Cox
6c65a4ab8e [release-branch.go1.18] os/exec: return clear error for missing cmd.Path
Following up on CL 403694, there is a bit of confusion about
when Path is and isn't set, along with now the exported Err field.
Catch the case where Path and Err (and lookPathErr) are all unset
and give a helpful error.

Updates #52574
Followup after #43724.

Fixes #53057
Fixes CVE-2022-30580

Change-Id: I03205172aef3801c3194f5098bdb93290c02b1b6
Reviewed-on: https://go-review.googlesource.com/c/go/+/403759
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: Roland Shoemaker <roland@golang.org>
(cherry picked from commit 960ffa98ce)
Reviewed-on: https://go-review.googlesource.com/c/go/+/408577
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Roland Shoemaker <roland@golang.org>
2022-05-27 14:57:10 +00:00
Rob Pike
a08baaad1a [release-branch.go1.18] text/template/parse: allow space after continue or break
Trivial fix: We must skip space after either of these keywords
before we expect a closing delimiter.

Also delete the stutter-generating extra 'in' in the error message.
(See what I did there?)

For #51670
Fixes #52878

Change-Id: If5415632c36eaac6699bdc0aa6ce18be956c9b53
Reviewed-on: https://go-review.googlesource.com/c/go/+/392615
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Daniel Martí <mvdan@mvdan.cc>
Trust: Daniel Martí <mvdan@mvdan.cc>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 41a82aa9c3)
Reviewed-on: https://go-review.googlesource.com/c/go/+/406074
Reviewed-by: Alex Rakoczy <alex@golang.org>
Auto-Submit: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
2022-05-26 17:27:08 +00:00
Matthew Dempsky
e1b14f53c1 [release-branch.go1.18] cmd/compile: backport fix for #51840
This CL is a manual backport of CLs 403837 and 404914 to Go 1.18.

CL 403837 was intended just as a simplification CL, but evidently it
also fixed #51840. However, for backporting to Go 1.18, the existing
logic needs to be preserved to support -G=0 mode (which still relies
on Ntype).

Fixes #51849.

Change-Id: Ib060b0bc67ecf26de8a65d5b4d2f8a65cd547517
Reviewed-on: https://go-review.googlesource.com/c/go/+/405436
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
2022-05-25 19:31:22 +00:00
Wayne Zuo
e46ac38370 [release-branch.go1.18] cmd/compile: allow exporting .rcvr ident
Noder pass will build a closure to implement generic function
instantiation which may produce `.dict` and `.rcvr` ident.
Since we allow `.dict` during exporting, we should allow `.rcvr` too.

Fixes #52242.

Change-Id: Ifc3912ba5155b5ac1887f20830da64f4fb3fceb6
Reviewed-on: https://go-review.googlesource.com/c/go/+/404314
Run-TryBot: Wayne Zuo <wdvxdr@golangcn.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
(cherry picked from commit ac39dbdf58)
Reviewed-on: https://go-review.googlesource.com/c/go/+/404774
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
2022-05-25 19:31:01 +00:00
Roland Shoemaker
32dedaa69e [release-branch.go1.18] [release-branch.go1.18 crypto/rand: properly handle large Read on windows
Use the batched reader to chunk large Read calls on windows to a max of
1 << 31 - 1 bytes. This prevents an infinite loop when trying to read
more than 1 << 32 -1 bytes, due to how RtlGenRandom works.

This change moves the batched function from rand_unix.go to rand.go,
since it is now needed for both windows and unix implementations.

Updates #52561
Fixes #52933
Fixes CVE-2022-30634

Change-Id: Id98fc4b1427e5cb2132762a445b2aed646a37473
Reviewed-on: https://go-review.googlesource.com/c/go/+/402257
Run-TryBot: Roland Shoemaker <roland@golang.org>
Reviewed-by: Filippo Valsorda <filippo@golang.org>
Reviewed-by: Filippo Valsorda <valsorda@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit bb1f441618)
Reviewed-on: https://go-review.googlesource.com/c/go/+/406634
Reviewed-by: Damien Neil <dneil@google.com>
2022-05-25 19:26:12 +00:00
Cherry Mui
04337a6d10 [release-branch.go1.18] misc/cgo/testsanitizers: use buffered channel in tsan12.go
os/signal.Notify requires that "the caller must ensure that c has
sufficient buffer space to keep up with the expected signal rate"
as it does a nonblocking send when it receives a signal. The test
currently using a unbuffered channel, which means it may miss the
signal if the signal arrives before the channel receive operation.

Fixes #53043.
Updates #52998.

Change-Id: Icdcab9396d735506480ef880fb45a4669fa7cc8f
Reviewed-on: https://go-review.googlesource.com/c/go/+/407888
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Cherry Mui <cherryyz@google.com>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 62e1302267)
Reviewed-on: https://go-review.googlesource.com/c/go/+/408114
2022-05-25 19:25:08 +00:00
David Chase
cf5fa2b4a7 cmd/compile: be sure to export types mentioned in f.i.g. method signature
When a fully instantiated generic method is exported, be sure to also
export the types in its signature.

Updates #52279.
Fixes #52286.

Change-Id: Icc6bca05b01f914cf67faaf1bf184eaa5484f521
Reviewed-on: https://go-review.googlesource.com/c/go/+/405118
Run-TryBot: David Chase <drchase@google.com>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 1284cc2495)
Reviewed-on: https://go-review.googlesource.com/c/go/+/405543
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
2022-05-17 17:29:34 +00:00
Heschi Kreinick
8ed0e51b5e [release-branch.go1.18] go1.18.2
Change-Id: I2f9a3e6819d10190117973262568aaacf47435e0
Reviewed-on: https://go-review.googlesource.com/c/go/+/405477
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Heschi Kreinick <heschi@google.com>
Reviewed-by: David Chase <drchase@google.com>
2022-05-10 16:47:15 +00:00
Robert Findley
020fc47501 [release-branch.go1.18] go/types, types2: use a type lookup by identity in method lookup
Named type identity is no longer canonical. For correctness, named types
need to be compared with types.Identical. Our method set algorithm was
not doing this: it was using a map to de-duplicate named types, relying
on their pointer identity. As a result it was possible to get incorrect
results or even infinite recursion, as encountered in #52715.

To fix this, look up types by identity in NewMethodSet and
LookupFieldOrMethod. This does a linear search among types with equal
origin. Alternatively we could use a *Context to do a hash lookup, but
in practice we will be considering a small number of types, and so
performance is not a concern and a linear lookup is simpler. This also
means we don't have to rely on our type hash being perfect, which we
don't depend on elsewhere.

Also add more tests for NewMethodSet and LookupFieldOrMethod involving
generics.

Fixes #52804

Change-Id: I04dfeff54347bc3544d95a30224c640ef448e9b7
Reviewed-on: https://go-review.googlesource.com/c/go/+/404099
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
(cherry picked from commit f088f4962e)
Reviewed-on: https://go-review.googlesource.com/c/go/+/405117
Reviewed-by: Alan Donovan <adonovan@google.com>
2022-05-10 15:00:03 +00:00
Heschi Kreinick
b2b4b9e015 [release-branch.go1.18] net: skip TestDialCancel on darwin-arm64
We're turning up Macs in a network environment that clashes with this
test. I don't think it's critical to get it working, so skip it.

For #49149.
Fixes #52706.

Change-Id: I925e3ecc5356c4cefd208bdcff3d98021215d0b4
Reviewed-on: https://go-review.googlesource.com/c/go/+/402181
Reviewed-by: Alex Rakoczy <alex@golang.org>
Run-TryBot: Heschi Kreinick <heschi@google.com>
Auto-Submit: Heschi Kreinick <heschi@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 06b0a655a1)
Reviewed-on: https://go-review.googlesource.com/c/go/+/405294
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2022-05-09 21:42:12 +00:00
Maisem Ali
45568433ed [release-branch.go1.18] net/http/httptest: fix race in Server.Close
When run with race detector the test fails without the fix.

For #51799
Fixes #51897

Change-Id: I273adb6d3a2b1e0d606b9c27ab4c6a9aa4aa8064
GitHub-Last-Rev: a5ddd146a2
GitHub-Pull-Request: golang/go#51805
Reviewed-on: https://go-review.googlesource.com/c/go/+/393974
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Trust: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
(cherry picked from commit 1d19cea740)
Reviewed-on: https://go-review.googlesource.com/c/go/+/401317
Reviewed-by: David Chase <drchase@google.com>
2022-05-09 20:28:28 +00:00
Robert Findley
6fabc53cae [release-branch.go1.18] go/types: clarify that contexts do not guarantee deduplication
Documentation around the use of types.Context is unclear about whether
contexts guarantee deduplication of identical instances. Add explicit
disclaimers that this is not the case.

Fixes golang/go#52028

Change-Id: I6651587315d3cbf9e8d70a69d3e2ec5cedd00da5
Reviewed-on: https://go-review.googlesource.com/c/go/+/396536
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 83327b4ae4)
Reviewed-on: https://go-review.googlesource.com/c/go/+/397674
Reviewed-by: Russ Cox <rsc@golang.org>
2022-05-09 20:28:06 +00:00
Keith Randall
2375a6882e [release-branch.go1.18] cmd/compile: always write fun[0] in incomplete itab
runtime.getitab need filled fun[0] to identify whether
implemented the interface.

Fixes #51738
Fixes #52244

Change-Id: I0173b98f4e1b45e3a0183a5b60229d289140d1e6
Reviewed-on: https://go-review.googlesource.com/c/go/+/399058
Reviewed-by: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
Auto-Submit: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/399974
Reviewed-by: Austin Clements <austin@google.com>
2022-05-09 20:25:20 +00:00
Michael Pratt
4f4542479d [release-branch.go1.18] runtime: align m.procid to 8 bytes on 32-bit systems
https://go-review.googlesource.com/c/go/+/383434 started using
atomic Load64 on this field, which breaks 32 bit platforms which
require 64-bit alignment of uint64s that are passed to atomic operations.

Not sure why this doesn't break everywhere, but I saw it break on
my laptop during all.bash.

For #51776.
Fixes #52305.

Change-Id: Ida27b23068b3cc7208fce3c97b69a464ccf68209
Reviewed-on: https://go-review.googlesource.com/c/go/+/399754
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Michael Pratt <mpratt@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
(cherry-picked from commit ea7e3e3c0f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/399954
Run-TryBot: Michael Pratt <mpratt@google.com>
2022-05-09 20:24:44 +00:00
Keith Randall
13bda0ebfb [release-branch.go1.18] cmd/compile: disable rewrite loop detector for deadcode-only changes
We're guaranteed we won't infinite loop on deadcode-only changes,
because each change converts valid -> invalid, and there are only a
finite number of valid values.

The loops this test is looking for are those generated by rule
applications, so it isn't useful to check for loops when rules aren't
involved.

Fixes #52366

Change-Id: Idf1abeab9d47baafddc3a1197d5064faaf07ef78
Reviewed-on: https://go-review.googlesource.com/c/go/+/392760
Trust: Keith Randall <khr@golang.org>
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
Trust: Josh Bleecher Snyder <josharian@gmail.com>
(cherry picked from commit 15728ce950)
Reviewed-on: https://go-review.googlesource.com/c/go/+/400514
Reviewed-by: Cherry Mui <cherryyz@google.com>
Reviewed-by: Austin Clements <austin@google.com>
Reviewed-by: David Chase <drchase@google.com>
2022-05-09 20:24:02 +00:00
Dan Kortschak
0287895996 [release-branch.go1.18] reflect: ensure map keys match key type in MapIndex and SetMapIndex
name                          old time/op    new time/op    delta
Map/StringKeys/MapIndex-8           2.36µs ± 5%    2.55µs ±11%  +7.98%  (p=0.006 n=10+9)
Map/StringKeys/SetMapIndex-8        4.86µs ± 7%    4.77µs ± 1%    ~     (p=0.211 n=10+9)
Map/StringKindKeys/MapIndex-8       2.29µs ± 3%    2.28µs ± 4%    ~     (p=0.631 n=10+10)
Map/StringKindKeys/SetMapIndex-8    4.44µs ± 3%    4.61µs ± 1%  +3.78%  (p=0.000 n=10+10)
Map/Uint64Keys/MapIndex-8           3.42µs ± 9%    3.11µs ± 2%  -9.20%  (p=0.000 n=10+9)
Map/Uint64Keys/SetMapIndex-8        5.17µs ± 3%    5.00µs ± 1%  -3.23%  (p=0.000 n=9+10)

For #52379
Fixes #52386

Change-Id: I545c71ea3145280828ca4186aad036a6c02016ed
Reviewed-on: https://go-review.googlesource.com/c/go/+/400635
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Joseph Tsai <joetsai@digital-static.net>
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Ian Lance Taylor <iant@google.com>
(cherry picked from commit 11a650bb4a)
Reviewed-on: https://go-review.googlesource.com/c/go/+/404000
Reviewed-by: David Chase <drchase@google.com>
2022-05-09 20:23:04 +00:00
Damien Neil
c0599c5b78 [release-branch.go1.18] syscall: check correct group in Faccessat
The Faccessat call checks the user, group, or other permission bits of a
file to see if the calling process can access it. The test to see if the
group permissions should be used was made with the wrong group id, using
the process's group id rather than the file's group id. Fix this to use
the correct group id.

No test since we cannot easily change file permissions when not running
as root and the test is meaningless if running as root.

For #52313
Fixes #52440

Change-Id: I4e2c84754b0af7830b40fd15dedcbc58374d75ee
Reviewed-on: https://go-review.googlesource.com/c/go/+/399539
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit f66925e854)
Reviewed-on: https://go-review.googlesource.com/c/go/+/401079
Auto-Submit: Damien Neil <dneil@google.com>
Reviewed-by: Tatiana Bradley <tatiana@golang.org>
Run-TryBot: Tatiana Bradley <tatiana@golang.org>
Auto-Submit: Tatiana Bradley <tatiana@golang.org>
Run-TryBot: Damien Neil <dneil@google.com>
2022-05-09 20:17:54 +00:00
Bryan C. Mills
2d6881b91a [release-branch.go1.18] cmd/go: write changes to go.mod and go.sum after loading the command-line-arguments package
This entrypoint was missed in CL 349600, and the behavior happened not
to be covered by existing tests.

Updates #52331.
Fixes #52468.

Change-Id: Iccf12e8e633215abe4bfa1c3ca2fe3a8391b5ba5
Reviewed-on: https://go-review.googlesource.com/c/go/+/401536
Run-TryBot: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
(cherry picked from commit cf697253ab)
Reviewed-on: https://go-review.googlesource.com/c/go/+/404094
Reviewed-by: David Chase <drchase@google.com>
2022-05-09 20:16:25 +00:00
Robert Findley
f4f19990c6 [release-branch.go1.18] go/types,types2: delay the check for conflicting struct field names
In #52529, we observed that checking types for duplicate fields and
methods during method collection can result in incorrect early expansion
of the base type. Fix this by delaying the check for duplicate fields.
Notably, we can't delay the check for duplicate methods as we must
preserve the invariant that added method names are unique.

After this change, it may be possible in the presence of errors to have
a type-checked type containing a method name that conflicts with a field
name. With the previous logic conflicting methods would have been
skipped. This is a change in behavior, but only for invalid code.
Preserving the existing behavior would likely require delaying method
collection, which could have more significant consequences.

As a result of this change, the compiler test fixedbugs/issue28268.go
started passing with types2, being previously marked as broken. The fix
was not actually related to the duplicate method error, but rather the
fact that we stopped reporting redundant errors on the calls to x.b()
and x.E(), because they are now (valid!) methods.

Updates #52529
Fixes #52558

Change-Id: I850ce85c6ba76d79544f46bfd3deb8538d8c7d00
Reviewed-on: https://go-review.googlesource.com/c/go/+/403455
Reviewed-by: Robert Griesemer <gri@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit b75e492b35)
Reviewed-on: https://go-review.googlesource.com/c/go/+/403754
2022-05-09 20:14:33 +00:00
Cuong Manh Le
1fb46d2a20 [release-branch.go1.18] cmd/compile: set correct package for vars/params/results from nested instantiation
Fixes #52606

Change-Id: Ib5b2cdbdbce1d516aa10a0df349449b756f2f404
Reviewed-on: https://go-review.googlesource.com/c/go/+/398474
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/403174
2022-05-09 20:13:36 +00:00
Keith Randall
9247bdddba [release-branch.go1.18] sync/atomic: use consistent first-store-in-progress marker
We need to use the same marker everywhere. My CL to rename the
marker (CL 241661) and the CL to add more uses of the marker
under the old name (CL 241678) weren't coordinated with each other.

Fixes #52615

Change-Id: I97023c0769e518491924ef457fe03bf64a2cefa6
Reviewed-on: https://go-review.googlesource.com/c/go/+/403094
Run-TryBot: Keith Randall <khr@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/403198
2022-05-09 20:12:59 +00:00
Keith Randall
500d75a555 [release-branch.go1.18] cmd/compile: use dictionary to convert type to shaped interface type
When we convert a type to a shaped interface type, we are not able
to recognize the itab. So passing the itab by dictionary as the
workaround.

Fixes #52691.

Change-Id: I75c23c7dd215daf9761dc24116a8af2c28c6d948
Reviewed-on: https://go-review.googlesource.com/c/go/+/401034
Run-TryBot: Wayne Zuo <wdvxdr@golangcn.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Auto-Submit: Keith Randall <khr@golang.org>
Reviewed-by: Keith Randall <khr@google.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
Reviewed-on: https://go-review.googlesource.com/c/go/+/403934
Reviewed-by: Than McIntosh <thanm@google.com>
Run-TryBot: Keith Randall <khr@golang.org>
2022-05-09 20:11:53 +00:00
eric fang
66432dadb1 [release-branch.go1.18] runtime: support for debugger function calls on linux/arm64
This CL adds support for debugger function calls on linux arm64
platform. The protocol is basically the same as in CL 109699, except for
the following differences:
1, The abi difference which affect parameter passing and frame layout.
2, Stores communication information in R20.
3, The closure register is R26.
4, Use BRK 0 instruction to generate a breakpoint. The saved PC in
sigcontext is the PC where the signal occurred, not the next PC.

In addition, this CL refactors the existing code (which is dedicated to
amd64) for easier multi-arch scaling.

Fixes #52699

Change-Id: I06b14e345cc89aab175f4a5f2287b765da85a86b
Reviewed-on: https://go-review.googlesource.com/c/go/+/395754
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
Run-TryBot: Eric Fang <eric.fang@arm.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 9717e8f80f)
Reviewed-on: https://go-review.googlesource.com/c/go/+/404215
Reviewed-by: David Chase <drchase@google.com>
2022-05-09 20:11:26 +00:00
Ian Lance Taylor
3e79a84853 [release-branch.go1.18] runtime: don't block preemption signal in new M's or ensureSigM
No test because we already have a test in the syscall package.
The issue reports 1 failure per 100,000 iterations, which is rare enough
that our builders won't catch the problem.

For #52226
Fixes #52375

Change-Id: I17633ff6cf676b6d575356186dce42cdacad0746
Reviewed-on: https://go-review.googlesource.com/c/go/+/400315
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
(cherry picked from commit e3982660a7)
Reviewed-on: https://go-review.googlesource.com/c/go/+/400318
Reviewed-by: Austin Clements <austin@google.com>
2022-05-06 23:12:25 +00:00
Bryan C. Mills
a286c7dd79 [release-branch.go1.18] syscall: relax output check in TestGroupCleanupUserNamespace
“If you have a procedure with ten parameters, you probably missed some.”
― attr. Alan J. Perlis

I argue that the same is true for hard-coded special cases.

In TestGroupCleanupUserNamespace, instead of a curated list of strings
observed in the wild we now check for a prefix, as was done for
TestGroupCleanup in CL 24670.

Updates #52088.
Fixes #52149.

Change-Id: I59c5b0c048113e306996c0f8247e09c714d2423a
Reviewed-on: https://go-review.googlesource.com/c/go/+/397316
Trust: Bryan Mills <bcmills@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
(cherry picked from commit 434b2a5d0d)
Reviewed-on: https://go-review.googlesource.com/c/go/+/398234
Reviewed-by: Russ Cox <rsc@golang.org>
2022-05-04 15:44:30 +00:00
Roland Shoemaker
c6688b58ea [release-branch.go1.18] crypto/x509: properly handle issuerUniqueID and subjectUniqueID
Updates #51754
Fixes #51859

Change-Id: I3bfa15db3497de9fb82d6391d87fca1ae9ba6543
Reviewed-on: https://go-review.googlesource.com/c/go/+/394297
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>
Reviewed-by: Damien Neil <dneil@google.com>
(cherry picked from commit 9a53b472b5)
Reviewed-on: https://go-review.googlesource.com/c/go/+/399500
Reviewed-by: Russ Cox <rsc@golang.org>
2022-05-04 15:38:23 +00:00
Robert Griesemer
94274d0ffd [release-branch.go1.18] cmd/compile/internal/types2: use correct value of iota
Fixes #52441.

Change-Id: I5cbf8c448dba037e9e0c5fe8f209401d6bf7d43f
Reviewed-on: https://go-review.googlesource.com/c/go/+/401134
Reviewed-by: Ian Lance Taylor <iant@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-on: https://go-review.googlesource.com/c/go/+/401174
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
2022-05-02 20:59:21 +00:00
Bryan C. Mills
24fcbb9808 [release-branch.go1.18] cmd/go: allow '-buildvcs=auto' and treat it as the default
When we added VCS stamping in the Go 1.18 release, we defaulted to
-buildvcs=true, on the theory that most folks will actually want VCS
information stamped.

We also made -buildvcs=true error out if a VCS directory is found and
no VCS tool is available, on the theory that a user who builds with
'-buildvcs=true' will be very surprised if the VCS metadata is
silently missing.

However, that causes a problem for CI environments that don't have the
appropriate VCS tool installed. (And we know that's a common situation
because we're in that situation ourselves — see #46693!)

The new '-buildvcs=auto' setting provides a middle ground: it stamps
VCS information by default when the tool is present (and reports
explicit errors if the tool errors out), but omits the metadata
when the tool isn't present at all.

Updates #51748.
Updates #51999.
Fixes #51798.

Change-Id: Iebc955c2af0abca9b7517f62ca48b1d944eb2df4
Reviewed-on: https://go-review.googlesource.com/c/go/+/398855
Run-TryBot: Bryan Mills <bcmills@google.com>
Reviewed-by: Russ Cox <rsc@golang.org>
Reviewed-by: Michael Matloob <matloob@golang.org>
Auto-Submit: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
(cherry picked from commit 4569fe6410)
Reviewed-on: https://go-review.googlesource.com/c/go/+/400454
Run-TryBot: Dmitri Shuralyov <dmitshur@golang.org>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Reviewed-by: Bryan Mills <bcmills@google.com>
2022-04-20 16:33:28 +00:00
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
315 changed files with 7180 additions and 2081 deletions

1
VERSION Normal file
View File

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

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

@@ -45,7 +45,7 @@ static void register_handler(int signo) {
import "C"
func main() {
ch := make(chan os.Signal)
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGUSR2)
C.register_handler(C.int(syscall.SIGUSR1))

View File

@@ -22,7 +22,7 @@ import (
import "C"
func main() {
ch := make(chan os.Signal)
ch := make(chan os.Signal, 1)
signal.Notify(ch, syscall.SIGUSR1)
if err := exec.Command("true").Run(); err != nil {

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

@@ -78,6 +78,8 @@ func storeByType(t *types.Type) obj.As {
return x86.AMOVL
case 8:
return x86.AMOVQ
case 16:
return x86.AMOVUPS
}
}
panic(fmt.Sprintf("bad store type %v", t))

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

@@ -91,6 +91,11 @@ func Info(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.Scope,
continue
}
apdecls = append(apdecls, n)
if n.Type().Kind() == types.TSSA {
// Can happen for TypeInt128 types. This only happens for
// spill locations, so not a huge deal.
continue
}
fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type()))
}
}

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 {
@@ -418,6 +417,7 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
var dictAssign *ir.AssignStmt
if outer != nil {
dictVar = ir.NewNameAt(pos, typecheck.LookupNum(typecheck.LocalDictName, g.dnum))
dictVar.SetSym(outer.Sym().Pkg.Lookup(dictVar.Sym().Name))
g.dnum++
dictVar.Class = ir.PAUTO
typed(types.Types[types.TUINTPTR], dictVar)
@@ -432,6 +432,9 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
var rcvrAssign ir.Node
if rcvrValue != nil {
rcvrVar = ir.NewNameAt(pos, typecheck.LookupNum(".rcvr", g.dnum))
if outer != nil {
rcvrVar.SetSym(outer.Sym().Pkg.Lookup(rcvrVar.Sym().Name))
}
g.dnum++
typed(rcvrValue.Type(), rcvrVar)
rcvrAssign = ir.NewAssignStmt(pos, rcvrVar, rcvrValue)
@@ -543,8 +546,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 +646,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 +900,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 +1181,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().IsEmptyInterface() && 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().IsEmptyInterface() && x.Type().HasShape() {
c.List[i] = assignconvfn(x, types.Types[types.TINTER])
}
}
}
}
return m
}
@@ -1270,8 +1292,9 @@ func (g *genInst) dictPass(info *instInfo) {
mce := m.(*ir.ConvExpr)
// Note: x's argument is still typed as a type parameter.
// m's argument now has an instantiated type.
if mce.X.Type().HasShape() || (mce.X.Type().IsInterface() && m.Type().HasShape()) {
m = convertUsingDictionary(info, info.dictParam, m.Pos(), m.(*ir.ConvExpr).X, m, m.Type(), false)
if mce.X.Type().HasShape() || m.Type().HasShape() {
m = convertUsingDictionary(info, info.dictParam, m.Pos(), mce.X, m, m.Type(), false)
}
case ir.ODOTTYPE, ir.ODOTTYPE2:
if !m.Type().HasShape() {
@@ -1367,7 +1390,7 @@ func findDictType(info *instInfo, t *types.Type) int {
// If nonEscaping is true, the caller guarantees that the backing store needed for the interface data
// word will not escape.
func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type, nonEscaping bool) ir.Node {
assert(v.Type().HasShape() || v.Type().IsInterface() && in.Type().HasShape())
assert(v.Type().HasShape() || in.Type().HasShape())
assert(dst.IsInterface())
if v.Type().IsInterface() {
@@ -1576,12 +1599,14 @@ func (g *genInst) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool
se := call.X.(*ir.SelectorExpr)
if se.X.Type().IsShape() {
// This is a method call enabled by a type bound.
// We need this extra check for method expressions,
// which don't add in the implicit XDOTs.
tmpse := ir.NewSelectorExpr(src.NoXPos, ir.OXDOT, se.X, se.Sel)
tmpse = typecheck.AddImplicitDots(tmpse)
tparam := tmpse.X.Type()
tparam := se.X.Type()
if call.X.Op() == ir.ODOTMETH {
// We need this extra check for method expressions,
// which don't add in the implicit XDOTs.
tmpse := ir.NewSelectorExpr(src.NoXPos, ir.OXDOT, se.X, se.Sel)
tmpse = typecheck.AddImplicitDots(tmpse)
tparam = tmpse.X.Type()
}
if !tparam.IsShape() {
// The method expression is not
// really on a typeparam.
@@ -1608,7 +1633,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 +1712,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))
@@ -1746,6 +1771,7 @@ func (g *genInst) finalizeSyms() {
g.instantiateMethods()
itabLsym := reflectdata.ITabLsym(srctype, dsttype)
d.off = objw.SymPtr(lsym, d.off, itabLsym, 0)
markTypeUsed(srctype, lsym)
infoPrint(" + Itab for (%v,%v)\n", srctype, dsttype)
}
}
@@ -1896,7 +1922,7 @@ func (g *genInst) getInstInfo(st *ir.Func, shapes []*types.Type, instInfo *instI
}
case ir.OCONVIFACE:
if n.Type().IsInterface() && !n.Type().IsEmptyInterface() &&
n.(*ir.ConvExpr).X.Type().HasShape() {
(n.Type().HasShape() || n.(*ir.ConvExpr).X.Type().HasShape()) {
infoPrint(" Itab for interface conv: %v\n", n)
info.itabConvs = append(info.itabConvs, n)
}
@@ -2091,6 +2117,9 @@ func startClosure(pos src.XPos, outer *ir.Func, typ *types.Type) (*ir.Func, []*t
for i := 0; i < typ.NumParams(); i++ {
t := typ.Params().Field(i).Type
arg := ir.NewNameAt(pos, typecheck.LookupNum("a", i))
if outer != nil {
arg.SetSym(outer.Sym().Pkg.Lookup(arg.Sym().Name))
}
arg.Class = ir.PPARAM
typed(t, arg)
arg.Curfn = fn
@@ -2103,6 +2132,9 @@ func startClosure(pos src.XPos, outer *ir.Func, typ *types.Type) (*ir.Func, []*t
for i := 0; i < typ.NumResults(); i++ {
t := typ.Results().Field(i).Type
result := ir.NewNameAt(pos, typecheck.LookupNum("r", i)) // TODO: names not needed?
if outer != nil {
result.SetSym(outer.Sym().Pkg.Lookup(result.Sym().Name))
}
result.Class = ir.PPARAMOUT
typed(t, result)
result.Curfn = fn

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

@@ -1321,21 +1321,21 @@ func writeITab(lsym *obj.LSym, typ, iface *types.Type, allowNonImplement bool) {
// type itab struct {
// inter *interfacetype
// _type *_type
// hash uint32
// hash uint32 // copy of _type.hash. Used for type switches.
// _ [4]byte
// fun [1]uintptr // variable sized
// fun [1]uintptr // variable sized. fun[0]==0 means _type does not implement inter.
// }
o := objw.SymPtr(lsym, 0, writeType(iface), 0)
o = objw.SymPtr(lsym, o, writeType(typ), 0)
o = objw.Uint32(lsym, o, types.TypeHash(typ)) // copy of type hash
o += 4 // skip unused field
if !completeItab {
// If typ doesn't implement iface, make method entries be zero.
o = objw.Uintptr(lsym, o, 0)
entries = entries[:0]
}
for _, fn := range entries {
if !completeItab {
// If typ doesn't implement iface, make method entries be zero.
o = objw.Uintptr(lsym, o, 0)
} else {
o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method
}
o = objw.SymPtrWeak(lsym, o, fn, 0) // method pointer for each method
}
// Nothing writes static itabs, so they are read only.
objw.Global(lsym, int32(o), int16(obj.DUPOK|obj.RODATA))
@@ -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

@@ -159,6 +159,13 @@ func findIndVar(f *Func) []indVar {
step = -step
}
if flags&indVarMaxInc != 0 && max.Op == OpConst64 && max.AuxInt+step < max.AuxInt {
// For a <= comparison, we need to make sure that a value equal to
// max can be incremented without overflowing.
// (For a < comparison, the %step check below ensures no overflow.)
continue
}
// Up to now we extracted the induction variable (ind),
// the increment delta (inc), the temporary sum (nxt),
// the mininum value (min) and the maximum value (max).

View File

@@ -40,6 +40,7 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValu
var states map[string]bool
for {
change := false
deadChange := false
for _, b := range f.Blocks {
var b0 *Block
if debug > 1 {
@@ -73,7 +74,7 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValu
// Not quite a deadcode pass, because it does not handle cycles.
// But it should help Uses==1 rules to fire.
v.reset(OpInvalid)
change = true
deadChange = true
}
// No point rewriting values which aren't used.
continue
@@ -145,15 +146,16 @@ func applyRewrite(f *Func, rb blockRewriter, rv valueRewriter, deadcode deadValu
}
}
}
if !change {
if !change && !deadChange {
break
}
iters++
if iters > 1000 || debug >= 2 {
if (iters > 1000 || debug >= 2) && change {
// We've done a suspiciously large number of rewrites (or we're in debug mode).
// As of Sep 2021, 90% of rewrites complete in 4 iterations or fewer
// and the maximum value encountered during make.bash is 12.
// Start checking for cycles. (This is too expensive to do routinely.)
// Note: we avoid this path for deadChange-only iterations, to fix #51639.
if states == nil {
states = make(map[string]bool)
}

View File

@@ -895,6 +895,18 @@ func evalunsafe(n ir.Node) int64 {
sel.X = Expr(sel.X)
sbase := sel.X
// Implicit dot may already be resolved for instantiating generic function. So we
// need to remove any implicit dot until we reach the first non-implicit one, it's
// the right base selector. See issue #53137.
var clobberBase func(n ir.Node) ir.Node
clobberBase = func(n ir.Node) ir.Node {
if sel, ok := n.(*ir.SelectorExpr); ok && sel.Implicit() {
return clobberBase(sel.X)
}
return n
}
sbase = clobberBase(sbase)
tsel := Expr(sel)
n.X = tsel
if tsel.Type() == nil {

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,12 +229,12 @@ 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])
}
for j := range t.Methods().Slice() {
for j, tmethod := range t.Methods().Slice() {
baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
dictsym := MakeDictSym(baseNname.Sym(), t.RParams(), true)
if dictsym.Def == nil {
@@ -255,6 +255,8 @@ func (p *crawler) checkForFullyInst(t *types.Type) {
ImportedBody(methNode.Func)
methNode.Func.SetExportInline(true)
}
// Make sure that any associated types are also exported. (See #52279)
p.checkForFullyInst(tmethod.Type)
}
}

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
@@ -2281,7 +2284,7 @@ func (w *exportWriter) localIdent(s *types.Sym) {
return
}
if i := strings.LastIndex(name, "."); i >= 0 && !strings.HasPrefix(name, LocalDictName) {
if i := strings.LastIndex(name, "."); i >= 0 && !strings.HasPrefix(name, LocalDictName) && !strings.HasPrefix(name, ".rcvr") {
base.Fatalf("unexpected dot in identifier: %v", name)
}

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

@@ -696,6 +696,12 @@ func PtrDataSize(t *Type) int64 {
}
return 0
case TSSA:
if t != TypeInt128 {
base.Fatalf("PtrDataSize: unexpected ssa type %v", t)
}
return 0
default:
base.Fatalf("PtrDataSize: unexpected type, %v", t)
return 0

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 }
@@ -1721,6 +1721,11 @@ var (
TypeResultMem = newResults([]*Type{TypeMem})
)
func init() {
TypeInt128.width = 16
TypeInt128.align = 8
}
// NewNamed returns a new named type for the given type name. obj should be an
// ir.Name. The new type is incomplete (marked as TFORW kind), and the underlying
// type should be set later via SetUnderlying(). References to the type are

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
@@ -1598,19 +1619,41 @@ func TestLookupFieldOrMethod(t *testing.T) {
{"var x T; type T struct{ f int }", true, []int{0}, false},
{"var x T; type T struct{ a, b, f, c int }", true, []int{2}, false},
// field lookups on a generic type
{"var x T[int]; type T[P any] struct{}", false, nil, false},
{"var x T[int]; type T[P any] struct{ f P }", true, []int{0}, false},
{"var x T[int]; type T[P any] struct{ a, b, f, c P }", true, []int{2}, false},
// method lookups
{"var a T; type T struct{}; func (T) f() {}", true, []int{0}, false},
{"var a *T; type T struct{}; func (T) f() {}", true, []int{0}, true},
{"var a T; type T struct{}; func (*T) f() {}", true, []int{0}, false},
{"var a *T; type T struct{}; func (*T) f() {}", true, []int{0}, true}, // TODO(gri) should this report indirect = false?
// method lookups on a generic type
{"var a T[int]; type T[P any] struct{}; func (T[P]) f() {}", true, []int{0}, false},
{"var a *T[int]; type T[P any] struct{}; func (T[P]) f() {}", true, []int{0}, true},
{"var a T[int]; type T[P any] struct{}; func (*T[P]) f() {}", true, []int{0}, false},
{"var a *T[int]; type T[P any] struct{}; func (*T[P]) f() {}", true, []int{0}, true}, // TODO(gri) should this report indirect = false?
// collisions
{"type ( E1 struct{ f int }; E2 struct{ f int }; x struct{ E1; *E2 })", false, []int{1, 0}, false},
{"type ( E1 struct{ f int }; E2 struct{}; x struct{ E1; *E2 }); func (E2) f() {}", false, []int{1, 0}, false},
// collisions on a generic type
{"type ( E1[P any] struct{ f P }; E2[P any] struct{ f P }; x struct{ E1[int]; *E2[int] })", false, []int{1, 0}, false},
{"type ( E1[P any] struct{ f P }; E2[P any] struct{}; x struct{ E1[int]; *E2[int] }); func (E2[P]) f() {}", false, []int{1, 0}, false},
// outside methodset
// (*T).f method exists, but value of type T is not addressable
{"var x T; type T struct{}; func (*T) f() {}", false, nil, true},
// outside method set of a generic type
{"var x T[int]; type T[P any] struct{}; func (*T[P]) f() {}", false, nil, true},
// recursive generic types; see golang/go#52715
{"var a T[int]; type ( T[P any] struct { *N[P] }; N[P any] struct { *T[P] } ); func (N[P]) f() {}", true, []int{0, 0}, true},
{"var a T[int]; type ( T[P any] struct { *N[P] }; N[P any] struct { *T[P] } ); func (T[P]) f() {}", true, []int{0}, false},
}
for _, test := range tests {
@@ -1645,6 +1688,37 @@ func TestLookupFieldOrMethod(t *testing.T) {
}
}
// Test for golang/go#52715
func TestLookupFieldOrMethod_RecursiveGeneric(t *testing.T) {
const src = `
package pkg
type Tree[T any] struct {
*Node[T]
}
func (*Tree[R]) N(r R) R { return r }
type Node[T any] struct {
*Tree[T]
}
type Instance = *Tree[int]
`
f, err := parseSrc("foo.go", src)
if err != nil {
panic(err)
}
pkg := NewPackage("pkg", f.PkgName.Value)
if err := NewChecker(nil, pkg, nil).Files([]*syntax.File{f}); err != nil {
panic(err)
}
T := pkg.Scope().Lookup("Instance").Type()
_, _, _ = LookupFieldOrMethod(T, false, pkg, "M") // verify that LookupFieldOrMethod terminates
}
func sameSlice(a, b []int) bool {
if len(a) != len(b) {
return false
@@ -1697,7 +1771,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 +2341,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

@@ -12,11 +12,12 @@ import (
"sync"
)
// An Context is an opaque type checking context. It may be used to share
// A Context is an opaque type checking context. It may be used to share
// identical type instances across type-checked packages or calls to
// Instantiate.
// Instantiate. Contexts are safe for concurrent use.
//
// It is safe for concurrent use.
// The use of a shared context does not guarantee that identical instances are
// deduplicated in all cases.
type Context struct {
mu sync.Mutex
typeMap map[string][]ctxtEntry // type hash -> instances entries

View File

@@ -636,14 +636,12 @@ func (check *Checker) collectMethods(obj *TypeName) {
base, _ := obj.typ.(*Named) // shouldn't fail but be conservative
if base != nil {
assert(base.targs.Len() == 0) // collectMethods should not be called on an instantiated type
u := base.under()
if t, _ := u.(*Struct); t != nil {
for _, fld := range t.fields {
if fld.name != "_" {
assert(mset.insert(fld) == nil)
}
}
}
// See issue #52529: we must delay the expansion of underlying here, as
// base may not be fully set-up.
check.later(func() {
check.checkFieldUniqueness(base)
}).describef(obj, "verifying field uniqueness for %v", base)
// Checker.Files may be called multiple times; additional package files
// may add methods to already type-checked types. Add pre-existing methods
@@ -662,17 +660,10 @@ func (check *Checker) collectMethods(obj *TypeName) {
assert(m.name != "_")
if alt := mset.insert(m); alt != nil {
var err error_
switch alt.(type) {
case *Var:
err.errorf(m.pos, "field and method with the same name %s", m.name)
case *Func:
if check.conf.CompilerErrorMessages {
err.errorf(m.pos, "%s.%s redeclared in this block", obj.Name(), m.name)
} else {
err.errorf(m.pos, "method %s already declared for %s", m.name, obj)
}
default:
unreachable()
if check.conf.CompilerErrorMessages {
err.errorf(m.pos, "%s.%s redeclared in this block", obj.Name(), m.name)
} else {
err.errorf(m.pos, "method %s already declared for %s", m.name, obj)
}
err.recordAltDecl(alt)
check.report(&err)
@@ -686,6 +677,36 @@ func (check *Checker) collectMethods(obj *TypeName) {
}
}
func (check *Checker) checkFieldUniqueness(base *Named) {
if t, _ := base.under().(*Struct); t != nil {
var mset objset
for i := 0; i < base.methods.Len(); i++ {
m := base.methods.At(i, nil)
assert(m.name != "_")
assert(mset.insert(m) == nil)
}
// Check that any non-blank field names of base are distinct from its
// method names.
for _, fld := range t.fields {
if fld.name != "_" {
if alt := mset.insert(fld); alt != nil {
// Struct fields should already be unique, so we should only
// encounter an alternate via collision with a method name.
_ = alt.(*Func)
// For historical consistency, we report the primary error on the
// method, and the alt decl on the field.
var err error_
err.errorf(alt, "field and method with the same name %s", fld.name)
err.recordAltDecl(fld)
check.report(&err)
}
}
}
}
}
func (check *Checker) funcDecl(obj *Func, decl *declInfo) {
assert(obj.typ == nil)
@@ -735,7 +756,7 @@ func (check *Checker) declStmt(list []syntax.Decl) {
top := len(check.delayed)
// iota is the index of the current constDecl within the group
if first < 0 || list[index-1].(*syntax.ConstDecl).Group != s.Group {
if first < 0 || s.Group == nil || list[index-1].(*syntax.ConstDecl).Group != s.Group {
first = index
last = nil
}

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,16 +15,17 @@ 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
// *Signature origin types are only considered identical if they are pointer
// equivalent, so that instantiating distinct (but possibly identical)
// signatures will yield different instances.
// signatures will yield different instances. The use of a shared context does
// not guarantee that identical instances are deduplicated in all cases.
//
// If validate is set, Instantiate verifies that the number of type arguments
// and parameters match, and that the type arguments satisfy their

View File

@@ -25,9 +25,9 @@ import (
// The last index entry is the field or method index in the (possibly embedded)
// type where the entry was found, either:
//
// 1) the list of declared methods of a named type; or
// 2) the list of all methods (method set) of an interface type; or
// 3) the list of fields of a struct type.
// 1. the list of declared methods of a named type; or
// 2. the list of all methods (method set) of an interface type; or
// 3. the list of fields of a struct type.
//
// The earlier index entries are the indices of the embedded struct fields
// traversed to get to the found entry, starting at depth 0.
@@ -35,13 +35,12 @@ import (
// If no entry is found, a nil object is returned. In this case, the returned
// index and indirect values have the following meaning:
//
// - If index != nil, the index sequence points to an ambiguous entry
// (the same name appeared more than once at the same embedding level).
//
// - If indirect is set, a method with a pointer receiver type was found
// but there was no pointer on the path from the actual receiver type to
// the method's formal receiver base type, nor was the receiver addressable.
// - If index != nil, the index sequence points to an ambiguous entry
// (the same name appeared more than once at the same embedding level).
//
// - If indirect is set, a method with a pointer receiver type was found
// but there was no pointer on the path from the actual receiver type to
// the method's formal receiver base type, nor was the receiver addressable.
func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (obj Object, index []int, indirect bool) {
if T == nil {
panic("LookupFieldOrMethod on nil type")
@@ -70,7 +69,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 {
@@ -81,11 +81,6 @@ func LookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string) (o
return
}
// TODO(gri) The named type consolidation and seen maps below must be
// indexed by unique keys for a given type. Verify that named
// types always have only one representation (even when imported
// indirectly via different packages.)
// lookupFieldOrMethod should only be called by LookupFieldOrMethod and missingMethod.
// If foldCase is true, the lookup for methods will include looking for any method
// which case-folds to the same as 'name' (used for giving helpful error messages).
@@ -110,14 +105,12 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string, fo
// Start with typ as single entry at shallowest depth.
current := []embeddedType{{typ, nil, isPtr, false}}
// Named types that we have seen already, allocated lazily.
// seen tracks named types that we have seen already, allocated lazily.
// Used to avoid endless searches in case of recursive types.
// Since only Named types can be used for recursive types, we
// only need to track those.
// (If we ever allow type aliases to construct recursive types,
// we must use type identity rather than pointer equality for
// the map key comparison, as we do in consolidateMultiples.)
var seen map[*Named]bool
//
// We must use a lookup on identity rather than a simple map[*Named]bool as
// instantiated types may be identical but not equal.
var seen instanceLookup
// search current depth
for len(current) > 0 {
@@ -130,7 +123,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string, fo
// If we have a named type, we may have associated methods.
// Look for those first.
if named, _ := typ.(*Named); named != nil {
if seen[named] {
if alt := seen.lookup(named); alt != nil {
// We have seen this type before, at a more shallow depth
// (note that multiples of this type at the current depth
// were consolidated before). The type at that depth shadows
@@ -138,10 +131,7 @@ func lookupFieldOrMethod(T Type, addressable bool, pkg *Package, name string, fo
// this one.
continue
}
if seen == nil {
seen = make(map[*Named]bool)
}
seen[named] = true
seen.add(named)
// look for a matching attached method
named.resolve(nil)
@@ -271,6 +261,27 @@ func lookupType(m map[Type]int, typ Type) (int, bool) {
return 0, false
}
type instanceLookup struct {
m map[*Named][]*Named
}
func (l *instanceLookup) lookup(inst *Named) *Named {
for _, t := range l.m[inst.Origin()] {
if Identical(inst, t) {
return t
}
}
return nil
}
func (l *instanceLookup) add(inst *Named) {
if l.m == nil {
l.m = make(map[*Named][]*Named)
}
insts := l.m[inst.Origin()]
l.m[inst.Origin()] = append(insts, inst)
}
// MissingMethod returns (nil, false) if V implements T, otherwise it
// returns a missing method required by T and whether it is missing or
// just has the wrong type.
@@ -280,7 +291,6 @@ func lookupType(m map[Type]int, typ Type) (int, bool) {
// is not set), MissingMethod only checks that methods of T which are also
// present in V have matching types (e.g., for a type assertion x.(T) where
// x is of interface type V).
//
func MissingMethod(V Type, T *Interface, static bool) (method *Func, wrongType bool) {
m, alt := (*Checker)(nil).missingMethod(V, T, static)
// Only report a wrong type if the alternative method has the same name as m.

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

@@ -339,7 +339,7 @@ func (check *Checker) collectObjects() {
case *syntax.ConstDecl:
// iota is the index of the current constDecl within the group
if first < 0 || file.DeclList[index-1].(*syntax.ConstDecl).Group != s.Group {
if first < 0 || s.Group == nil || file.DeclList[index-1].(*syntax.ConstDecl).Group != s.Group {
first = index
last = nil
}
@@ -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

@@ -349,6 +349,25 @@ const _ = unsafe.Sizeof(func() {
assert(iota == 0)
})
// issue #52438
const i1 = iota
const i2 = iota
const i3 = iota
func _() {
assert(i1 == 0)
assert(i2 == 0)
assert(i3 == 0)
const i4 = iota
const i5 = iota
const i6 = iota
assert(i4 == 0)
assert(i5 == 0)
assert(i6 == 0)
}
// untyped constants must not get arbitrarily large
const prec = 512 // internal maximum precision for integers
const maxInt = (1<<(prec/2) - 1) * (1<<(prec/2) + 1) // == 1<<prec - 1

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

@@ -0,0 +1,15 @@
// 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 Foo[P any] struct {
_ *Bar[P]
}
type Bar[Q any] Foo[Q]
func (v *Bar[R]) M() {
_ = (*Foo[R])(v)
}

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

@@ -621,6 +621,12 @@ func oaslit(n *ir.AssignStmt, init *ir.Nodes) bool {
// not a special composite literal assignment
return false
}
if x.Addrtaken() {
// If x is address-taken, the RHS may (implicitly) uses LHS.
// Not safe to do a special composite literal assignment
// (which may expand to multiple assignments).
return false
}
switch n.Y.Op() {
default:
@@ -629,7 +635,7 @@ func oaslit(n *ir.AssignStmt, init *ir.Nodes) bool {
case ir.OSTRUCTLIT, ir.OARRAYLIT, ir.OSLICELIT, ir.OMAPLIT:
if ir.Any(n.Y, func(y ir.Node) bool { return ir.Uses(y, x) }) {
// not a special composite literal assignment
// not safe to do a special composite literal assignment if RHS uses LHS.
return false
}
anylit(n.Y, n.X, init)

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

@@ -138,11 +138,13 @@
// -buildmode mode
// build mode to use. See 'go help buildmode' for more.
// -buildvcs
// Whether to stamp binaries with version control information. By default,
// version control information is stamped into a binary if the main package
// and the main module containing it are in the repository containing the
// current directory (if there is a repository). Use -buildvcs=false to
// omit version control information.
// Whether to stamp binaries with version control information
// ("true", "false", or "auto"). By default ("auto"), version control
// information is stamped into a binary if the main package, the main module
// containing it, and the current directory are all in the same repository.
// Use -buildvcs=false to always omit version control information, or
// -buildvcs=true to error out if version control information is available but
// cannot be included due to a missing tool or ambiguous directory structure.
// -compiler name
// name of compiler to use, as in runtime.Compiler (gccgo or gc).
// -gccgoflags '[pattern=]arg list'
@@ -1356,7 +1358,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 +1366,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 +1493,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 +1514,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 +1540,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 +1562,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

@@ -24,9 +24,9 @@ import (
// These are general "build flags" used by build and other commands.
var (
BuildA bool // -a flag
BuildBuildmode string // -buildmode flag
BuildBuildvcs bool // -buildvcs flag
BuildA bool // -a flag
BuildBuildmode string // -buildmode flag
BuildBuildvcs = "auto" // -buildvcs flag: "true", "false", or "auto"
BuildContext = defaultContext()
BuildMod string // -mod flag
BuildModExplicit bool // whether -mod was set explicitly

View File

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

View File

@@ -17,6 +17,7 @@ import (
"internal/goroot"
"io/fs"
"os"
"os/exec"
"path"
pathpkg "path"
"path/filepath"
@@ -193,6 +194,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 +1939,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 +2233,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.
@@ -2312,7 +2329,17 @@ func (p *Package) setBuildInfo() {
appendSetting("-gcflags", BuildGcflags.String())
}
if BuildLdflags.present {
appendSetting("-ldflags", BuildLdflags.String())
// https://go.dev/issue/52372: only include ldflags if -trimpath is not set,
// since it can include system paths through various linker flags (notably
// -extar, -extld, and -extldflags).
//
// TODO: since we control cmd/link, in theory we can parse ldflags to
// determine whether they may refer to system paths. If we do that, we can
// redact only those paths from the recorded -ldflags setting and still
// record the system-independent parts of the flags.
if !cfg.BuildTrimpath {
appendSetting("-ldflags", BuildLdflags.String())
}
}
if cfg.BuildMSan {
appendSetting("-msan", "true")
@@ -2328,7 +2355,14 @@ func (p *Package) setBuildInfo() {
cgo = "1"
}
appendSetting("CGO_ENABLED", cgo)
if cfg.BuildContext.CgoEnabled {
// https://go.dev/issue/52372: only include CGO flags if -trimpath is not set.
// (If -trimpath is set, it is possible that these flags include system paths.)
// If cgo is involved, reproducibility is already pretty well ruined anyway,
// given that we aren't stamping header or library versions.
//
// TODO(bcmills): perhaps we could at least parse the flags and stamp the
// subset of flags that are known not to be paths?
if cfg.BuildContext.CgoEnabled && !cfg.BuildTrimpath {
for _, name := range []string{"CGO_CFLAGS", "CGO_CPPFLAGS", "CGO_CXXFLAGS", "CGO_LDFLAGS"} {
appendSetting(name, cfg.Getenv(name))
}
@@ -2346,8 +2380,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 +2393,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 && cfg.BuildBuildvcs != "false" && 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)
@@ -2371,7 +2405,14 @@ func (p *Package) setBuildInfo() {
// repository containing the working directory. Don't include VCS info.
// If the repo contains the module or vice versa, but they are not
// the same directory, it's likely an error (see below).
repoDir, vcsCmd = "", nil
goto omitVCS
}
if cfg.BuildBuildvcs == "auto" && vcsCmd != nil && vcsCmd.Cmd != "" {
if _, err := exec.LookPath(vcsCmd.Cmd); err != nil {
// We fould a repository, but the required VCS tool is not present.
// "-buildvcs=auto" means that we should silently drop the VCS metadata.
goto omitVCS
}
}
}
if repoDir != "" && vcsCmd.Status != nil {
@@ -2385,8 +2426,11 @@ func (p *Package) setBuildInfo() {
return
}
if pkgRepoDir != repoDir {
setVCSError(fmt.Errorf("main package is in repository %q but current directory is in repository %q", pkgRepoDir, repoDir))
return
if cfg.BuildBuildvcs != "auto" {
setVCSError(fmt.Errorf("main package is in repository %q but current directory is in repository %q", pkgRepoDir, repoDir))
return
}
goto omitVCS
}
modRepoDir, _, err := vcs.FromDir(p.Module.Dir, "", allowNesting)
if err != nil {
@@ -2394,8 +2438,11 @@ func (p *Package) setBuildInfo() {
return
}
if modRepoDir != repoDir {
setVCSError(fmt.Errorf("main module is in repository %q but current directory is in repository %q", modRepoDir, repoDir))
return
if cfg.BuildBuildvcs != "auto" {
setVCSError(fmt.Errorf("main module is in repository %q but current directory is in repository %q", modRepoDir, repoDir))
return
}
goto omitVCS
}
type vcsStatusError struct {
@@ -2422,6 +2469,7 @@ func (p *Package) setBuildInfo() {
}
appendSetting("vcs.modified", strconv.FormatBool(st.Uncommitted))
}
omitVCS:
p.Internal.BuildInfo = info.String()
}
@@ -2648,6 +2696,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

@@ -447,7 +447,7 @@ func (r *gitRepo) fetchRefsLocked() error {
// statLocal returns a RevInfo describing rev in the local git repository.
// It uses version as info.Version.
func (r *gitRepo) statLocal(version, rev string) (*RevInfo, error) {
out, err := Run(r.dir, "git", "-c", "log.showsignature=false", "log", "-n1", "--format=format:%H %ct %D", rev, "--")
out, err := Run(r.dir, "git", "-c", "log.showsignature=false", "log", "--no-decorate", "-n1", "--format=format:%H %ct %D", rev, "--")
if err != nil {
return nil, &UnknownRevisionError{Rev: rev}
}

View File

@@ -397,7 +397,6 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio
seen := map[module.Version]bool{}
for _, m := range roots {
hasDepsInAll[m.Path] = true
seen[m] = true
}
// This loop will terminate because it will call enqueue on each version of
// each dependency of the modules in hasDepsInAll at most once (and only
@@ -406,11 +405,11 @@ func readModGraph(ctx context.Context, pruning modPruning, roots []module.Versio
needsEnqueueing := map[module.Version]bool{}
for p := range hasDepsInAll {
m := module.Version{Path: p, Version: mg.g.Selected(p)}
reqs, ok := mg.g.RequiredBy(m)
if !ok {
if !seen[m] {
needsEnqueueing[m] = true
continue
}
reqs, _ := mg.g.RequiredBy(m)
for _, r := range reqs {
s := module.Version{Path: r.Path, Version: mg.g.Selected(r.Path)}
if cmpVersion(s.Version, r.Version) > 0 && !seen[s] {

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

@@ -715,6 +715,12 @@ func ImportFromFiles(ctx context.Context, gofiles []string) {
},
})
requirements = loaded.requirements
if !ExplicitWriteGoMod {
if err := commitRequirements(ctx); err != nil {
base.Fatalf("go: %v", err)
}
}
}
// DirImportPath returns the effective import path for dir,

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

@@ -13,6 +13,7 @@ import (
"os"
"path/filepath"
"runtime"
"strconv"
"strings"
"cmd/go/internal/base"
@@ -91,11 +92,13 @@ and test commands:
-buildmode mode
build mode to use. See 'go help buildmode' for more.
-buildvcs
Whether to stamp binaries with version control information. By default,
version control information is stamped into a binary if the main package
and the main module containing it are in the repository containing the
current directory (if there is a repository). Use -buildvcs=false to
omit version control information.
Whether to stamp binaries with version control information
("true", "false", or "auto"). By default ("auto"), version control
information is stamped into a binary if the main package, the main module
containing it, and the current directory are all in the same repository.
Use -buildvcs=false to always omit version control information, or
-buildvcs=true to error out if version control information is available but
cannot be included due to a missing tool or ambiguous directory structure.
-compiler name
name of compiler to use, as in runtime.Compiler (gccgo or gc).
-gccgoflags '[pattern=]arg list'
@@ -302,7 +305,7 @@ func AddBuildFlags(cmd *base.Command, mask BuildFlagMask) {
cmd.Flag.Var((*base.StringsFlag)(&cfg.BuildToolexec), "toolexec", "")
cmd.Flag.BoolVar(&cfg.BuildTrimpath, "trimpath", false, "")
cmd.Flag.BoolVar(&cfg.BuildWork, "work", false, "")
cmd.Flag.BoolVar(&cfg.BuildBuildvcs, "buildvcs", true, "")
cmd.Flag.Var((*buildvcsFlag)(&cfg.BuildBuildvcs), "buildvcs", "")
// Undocumented, unstable debugging flags.
cmd.Flag.StringVar(&cfg.DebugActiongraph, "debug-actiongraph", "", "")
@@ -332,6 +335,29 @@ func (v *tagsFlag) String() string {
return "<TagsFlag>"
}
// buildvcsFlag is the implementation of the -buildvcs flag.
type buildvcsFlag string
func (f *buildvcsFlag) IsBoolFlag() bool { return true } // allow -buildvcs (without arguments)
func (f *buildvcsFlag) Set(s string) error {
// https://go.dev/issue/51748: allow "-buildvcs=auto",
// in addition to the usual "true" and "false".
if s == "" || s == "auto" {
*f = "auto"
return nil
}
b, err := strconv.ParseBool(s)
if err != nil {
return errors.New("value is neither 'auto' nor a valid bool")
}
*f = (buildvcsFlag)(strconv.FormatBool(b)) // convert to canonical "true" or "false"
return nil
}
func (f *buildvcsFlag) String() string { return string(*f) }
// fileExtSplit expects a filename and returns the name
// and ext (without the dot). If the file has no
// extension, ext will be empty.
@@ -379,7 +405,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: true}, args)
load.CheckPackageErrors(pkgs)
explicitO := len(cfg.BuildO) > 0
@@ -603,7 +629,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: true}, 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,87 @@
# Regression test for https://go.dev/issue/51748: by default, 'go build' should
# not attempt to stamp VCS information when the VCS tool is not present.
[short] skip
[!exec:git] skip
cd sub
exec git init .
exec git add sub.go
exec git commit -m 'initial state'
cd ..
exec git init
exec git submodule add ./sub
exec git add go.mod example.go
exec git commit -m 'initial state'
# Control case: with a git binary in $PATH,
# 'go build' on a package in the same git repo
# succeeds and stamps VCS metadata by default.
go build -o example.exe .
go version -m example.exe
stdout '^\tbuild\tvcs=git$'
stdout '^\tbuild\tvcs.modified=false$'
# Building a binary from a different (nested) VCS repo should not stamp VCS
# info. It should be an error if VCS stamps are requested explicitly with
# '-buildvcs' (since we know the VCS metadata exists), but not an error
# with '-buildvcs=auto'.
go build -o sub.exe ./sub
go version -m sub.exe
! stdout '^\tbuild\tvcs'
! go build -buildvcs -o sub.exe ./sub
stderr '\Aerror obtaining VCS status: main package is in repository ".*" but current directory is in repository ".*"\n\tUse -buildvcs=false to disable VCS stamping.\n\z'
cd ./sub
go build -o sub.exe .
go version -m sub.exe
! stdout '^\tbuild\tvcs'
! go build -buildvcs -o sub.exe .
stderr '\Aerror obtaining VCS status: main module is in repository ".*" but current directory is in repository ".*"\n\tUse -buildvcs=false to disable VCS stamping.\n\z'
cd ..
# After removing 'git' from $PATH, 'go build -buildvcs' should fail...
env PATH=
env path=
! go build -buildvcs -o example.exe .
stderr 'go: missing Git command\. See https://golang\.org/s/gogetcmd$'
# ...but by default we should omit VCS metadata when the tool is missing.
go build -o example.exe .
go version -m example.exe
! stdout '^\tbuild\tvcs'
# The default behavior can be explicitly set with '-buildvcs=auto'.
go build -buildvcs=auto -o example.exe .
go version -m example.exe
! stdout '^\tbuild\tvcs'
# Other flag values should be rejected with a useful error message.
! go build -buildvcs=hg -o example.exe .
stderr '\Ainvalid boolean value "hg" for -buildvcs: value is neither ''auto'' nor a valid bool\nusage: go build .*\nRun ''go help build'' for details.\n\z'
-- go.mod --
module example
go 1.18
-- example.go --
package main
func main() {}
-- sub/sub.go --
package main
func main() {}

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