Compare commits

...

502 Commits

Author SHA1 Message Date
Ian Lance Taylor
55626ee50b [dev.go2go] README: document that this branch is no longer maintained
For golang/go#46346

Change-Id: Iab050557efb96217477072eca42966662485b6b1
Reviewed-on: https://go-review.googlesource.com/c/go/+/322192
Trust: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2021-05-24 20:10:04 +00:00
Ian Lance Taylor
9cd52cf2a9 [dev.go2go] cmd/go2go: don't pass "run run" to cmd/go
Fixes #45502

Change-Id: I510c47e7780a42ffd0c855da5ce1674d487c1633
Reviewed-on: https://go-review.googlesource.com/c/go/+/309570
Trust: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2021-04-13 00:32:27 +00:00
Alan D. Cabrera
a4b4db4cde cmd/go2go: add ability to specify build tags in go2go
You can specify build tags, so that imports properly work during translation,
by using the `-tags` option, e.g. `go tool go2go run -tags=appengine x.go2`.
The `-tags` option is available for all the `go2go` sub-commands.

Change-Id: Ib60e7542b10c6a561b61db23d35592b2bc7f63cd
GitHub-Last-Rev: 954cccfae8
GitHub-Pull-Request: golang/go#45147
Reviewed-on: https://go-review.googlesource.com/c/go/+/303275
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Trust: Emmanuel Odeke <emmanuel@orijtech.com>
2021-03-22 22:48:13 +00:00
Rob Findley
8f19f8a9e1 [dev.go2go] all: merge master (12bb256) into dev.go2go
Included in this merge are CL 293010 switching to a new ast.ListExpr for
type argument lists (instead of overloading CallExpr), and CL 295929
partially hiding the new type parameter API.

As a result of those two CLs, the following changes were made to fix the
go2go tool:
 + Update the go2go rewriter for the new syntax.
 + Update test cases to eliminate some remaining '()' syntax for type
   argument lists.
 + Add new files exposing the now-hidden API.

These changes can be reviewed by comparing the latest patchset to
patchset 1.

Merge List:

+ 2021-03-04 12bb256cb3 go/types: use correct recv for parameterized embedded methods
+ 2021-03-03 6db80d7420 cmd/compile/internal/types2: use correct recv for parameterized embedded methods
+ 2021-03-03 d6f6ef6358 cmd/compile: remove races introduced in abiutils field update
+ 2021-03-03 3e524ee65a cmd/compile: make modified Aux type for OpArgXXXX pass ssa/check
+ 2021-03-03 9f33dc3ca1 cmd/compile: handle aggregate OpArg in registers
+ 2021-03-03 c4e3f6c4c7 cmd/compile: remove 8-byte alignment requirement of stack slot on s390x
+ 2021-03-03 85f62b0941 cmd/compile: remove 8-byte alignment requirement of stack slot on mips
+ 2021-03-03 497feff168 cmd/compile: intrinsify runtime/internal/atomic.{And,Or}{8,} on RISCV64
+ 2021-03-03 00cb841b83 syscall: implement rawVforkSyscall for remaining linux platforms
+ 2021-03-03 f2df1e3c34 cmd/compile: retrieve Args from registers
+ 2021-03-03 06c72f3627 A+C: change email address for Baokun Lee
+ 2021-03-03 84ca4949a7 cmd/compile: remove 8-byte alignment requirement of stack slot on mips64
+ 2021-03-03 77973863c3 cmd/compile: use abiutils for all rcvr/in/out frame offsets.
+ 2021-03-03 aea1259a72 cmd/link: disable flaky Darwin "symbols" test
+ 2021-03-02 312fd9937d cmd/go: remove -insecure flag on go get
+ 2021-03-02 2a2f99eefb cmd/go/internal/modload: do not resolve an arbitrary version for 'go list --versions'
+ 2021-03-02 b65091c11d cmd/go: add a test case that reproduces #44296
+ 2021-03-02 e9eed78dc3 cmd/go: resolve std-vendored dependencies as std packages except in 'go get' and 'go mod'
+ 2021-03-02 09f4ef4fa7 cmd/go/internal/mvs: prune spurious dependencies in Downgrade
+ 2021-03-02 c6374f5162 dist: generate stub go.mod in workdir
+ 2021-03-02 97b32a6724 cmd/compile: better version of check frame offsets against abi
+ 2021-03-02 2b50ab2aee cmd/compile: optimize single-precision floating point square root
+ 2021-03-02 ebb92dfed9 internal/poll, runtime: handle netpollopen error in poll_runtime_pollOpen
+ 2021-03-02 4c1a7ab49c cmd/go: reject relative paths in GOMODCACHE environment
+ 2021-03-02 580636a78a all: fix spelling
+ 2021-03-02 a6eeb4add4 go/parser,go/types: hide API changes related to type parameters
+ 2021-03-02 ff5cf4ced3 cmd/link,debug/elf: mips32, add .gnu.attributes and .MIPS.abiflags sections
+ 2021-03-01 700b73975e runtime: use entersyscall in syscall_syscallX on Darwin
+ 2021-03-01 a69c45213d go/types: review of expr.go
+ 2021-03-01 b98ce3b606 cmd/compile:  import empty closure function correctly
+ 2021-03-01 97bdac03ae cmd: upgrade golang.org/x/mod to relax import path check
+ 2021-03-01 f6a74c6568 cmd/compile/internal/ir: fix up stale comment
+ 2021-03-01 87beecd6df cmd/go: add missing newline to retraction warning message
+ 2021-03-01 a400eb3261 Revert "cmd/compile: check frame offsets against abi"
+ 2021-03-01 5fafc0bbd4 cmd/go/internal/modload: don't query when fixing canonical versions
+ 2021-03-01 2a8df4488e os: mark pipes returned by os.Pipe() as inheritable by default
+ 2021-02-27 5ff7ec98b7 cmd/compile: check frame offsets against abi
+ 2021-02-27 a429926159 cmd/compile: fix escape analysis of heap-allocated results
+ 2021-02-27 998fe70b68 cmd/compile: fixed which-result confusion in presence of 0-width types
+ 2021-02-27 d9fd38e68b time: correct unusual extension string cases
+ 2021-02-26 cda8ee095e reflect: fix register ABI spill space calculation
+ 2021-02-26 d8e33d558e cmd/compile: deal with closures in generic functions and instantiated function values
+ 2021-02-26 19f96e73bf syscall: introduce SysProcAttr.ParentProcess on Windows
+ 2021-02-26 3146166baa syscall: introduce SysProcAttr.AdditionalInheritedHandles on Windows
+ 2021-02-26 2d760816ff syscall: restrict inherited handles on Windows
+ 2021-02-26 ba9168bd07 syscall: add support for proc thread attribute lists
+ 2021-02-26 f41460145e cmd/link: recognize ARM64 PE files and relocations
+ 2021-02-26 a655208c9e cmd/link: handle types as converted to interface when dynlink
+ 2021-02-26 23943a6737 cmd/compile: fix mishandling of unsafe-uintptr arguments with call method in go/defer
+ 2021-02-26 e25040d162 cmd/compile: change StaticCall to return a "Results"
+ 2021-02-26 9a555fc24c cmd/compile:  fix missing descend in Addrtaken for closures.
+ 2021-02-25 a61524d103 cmd/internal/obj: add Prog.SetFrom3{Reg,Const}
+ 2021-02-25 5f15af111c syscall: comment on fields omitted from the win32finddata1 struct
+ 2021-02-25 9a7fe196e4 Revert "cmd/compile: fix mishandling of unsafe-uintptr arguments with call method in go/defer"
+ 2021-02-25 b83d073e9e reflect: add Method.IsExported and StructField.IsExported methods
+ 2021-02-25 7fcf9893f7 cmd/internal/obj: fix typo in docs
+ 2021-02-25 6c3bcda866 cmd/compile: declare inlined result params early for empty returns
+ 2021-02-25 526ee96f49 os: avoid allocation in File.WriteString
+ 2021-02-25 194b636f8f database/sql: close driver.Connector if it implements io.Closer
+ 2021-02-25 4ebb6f5110 cmd/compile: automate resultInArg0 register checks
+ 2021-02-25 1a3e968b1f cmd/compile: fix mishandling of unsafe-uintptr arguments with call method in go/defer
+ 2021-02-25 ee2a45e5fb runtime: use pipe2 for nonblockingPipe on dragonfly
+ 2021-02-25 1f7a01459b runtime: batch moving gFree list between local p and global schedt
+ 2021-02-25 bcac57f89c cmd: upgrade golang.org/x/mod to fix go.mod parser
+ 2021-02-25 3137da82fd cmd/go: add a script test corresponding to the downhiddenartifact MVS test
+ 2021-02-25 2c4c189bba cmd/go/internal/mvs: add test cases for downgrade interaction with hidden versions
+ 2021-02-25 9fe8ebf9b4 test: add test case that failed with gccgo
+ 2021-02-25 ad17b65b34 testing/fstest: treat dash specially when building glob
+ 2021-02-25 37ca84a9cd syscall: return error if GetQueuedCompletionStatus truncates key
+ 2021-02-25 76c0003cd5 syscall, os: use pipe2 syscall on DragonflyBSD instead of pipe
+ 2021-02-25 666ad85df4 cmd/compile: fix typo in rewrite_test.go
+ 2021-02-25 d822ffebc5 test: fix inline.go test for linux-amd64-noopt
+ 2021-02-25 ff614b13d9 runtime: subtract one from ip when determining abort
+ 2021-02-24 dbbc5ec7e8 syscall: restore broken GetQueuedCompletionStatus signature but make it not crash
+ 2021-02-24 d0d21b7c4c cmd/compile: plumb abi info into expandCalls
+ 2021-02-24 8027343b63 cmd/compile: disable inlining functions with closures for now
+ 2021-02-24 6c3f8a2f47 cmd/link: use ctxt.Logf instead of package log
+ 2021-02-24 3ee32439b5 cmd/compile: ARM64 optimize []float64 and []float32 access
+ 2021-02-24 80ddc17ae1 cmd/compile/internal-abi: fix ABI0-equivalence for zero-sized values
+ 2021-02-24 3deb528199 cmd/compile/internal-abi: update internal ABI spec for g register
+ 2021-02-24 478277f812 cmd/compile/internal-abi: use x87 mode, not MMX mode
+ 2021-02-24 bf48163e8f cmd/compile: add rule to coalesce writes
+ 2021-02-24 b7f62daa59 cmd/internal/goobj: add test case for object file reader
+ 2021-02-24 c9d9b40b13 context: avoid importing context package twice
+ 2021-02-24 dc4698f52b syscall: do not overflow key memory in GetQueuedCompletionStatus
+ 2021-02-24 7a2f3273c5 cmd/compile: plumb abi info into ssagen/ssa
+ 2021-02-24 adb467ffd2 cmd/compile: reduce inline cost of OCONVOP
+ 2021-02-24 27684ea195 testing: print late arriving log line in panic
+ 2021-02-24 ae1fa08e41 context: reduce contention in cancelCtx.Done
+ 2021-02-24 691ac806d2 cmd/go: fix version validation in 'go mod edit -exclude'
+ 2021-02-24 b97b1456ae cmd/go, cmd/cgo: pass -mfp32 and -mhard/soft-float to MIPS GCC
+ 2021-02-24 07c658316b io/ioutil: forward TempFile and TempDir to os package
+ 2021-02-24 04edf418d2 encoding/json: reduce allocated space in Unmarshal
+ 2021-02-24 e496120891 database: remove race in TestTxContextWait
+ 2021-02-24 26001d109e go/types: review of call.go
+ 2021-02-24 35b80eac7d hash/maphash: remove duplicate from Hash documentation
+ 2021-02-24 eb863240dc runtime: remove unused const stackSystem on dragonfly
+ 2021-02-24 084b07d6f6 spec: improve sentence structure for passing a slice
+ 2021-02-24 6ba4a300d8 docs: fix spelling
+ 2021-02-24 43652dc46f bufio, bytes, strings: handle negative runes in WriteRune
+ 2021-02-24 3780529255 unicode: correctly handle negative runes
+ 2021-02-24 0694fb3d78 image: resolve the TODO of doc comment style
+ 2021-02-23 6cc8aa7ece go/types: minor updates to comments to align with types2
+ 2021-02-23 42b9e3a8df context: fix XTestInterlockedCancels
+ 2021-02-23 aaed6cbced testing/race: fixing intermittent test failure
+ 2021-02-23 fbed561f8a runtime: reset stack poison flag accidentally set
+ 2021-02-23 0458d8c983 go/types, types2: constraints may be parenthesized and that includes "any"
+ 2021-02-23 74903553bc doc: start draft go1.17 release notes, move go1.16 to x/website
+ 2021-02-23 fa40c0232c cmd/go: reproduce issue #44497 in TestScript/mod_edit
+ 2021-02-23 a4dac8bd22 runtime: use BX instead of R15 in race detector
+ 2021-02-23 c49c7a675a runtime: save R15 before checking AVX state
+ 2021-02-23 d2911d7612 cmd/compile: fold MOV*nop and MOV*const
+ 2021-02-23 d434c2338b runtime: clarify GC fractional mode description
+ 2021-02-23 a671e33c6d all: use more precise build tags
+ 2021-02-23 c584f42dcf cmd/compile: change riscv64 Eq32/Neq32 to zero extend before subtraction
+ 2021-02-23 080119799b runtime: fix usleep on windows/arm
+ 2021-02-23 74cac8d479 cmd/compile: add AMD64 parameter register defs, Arg ops, plumb to ssa.Config
+ 2021-02-23 42cd40ee74 cmd/compile: improve bit test code
+ 2021-02-23 f1562c7610 cmd/go: recognize DLL magic from llvm binaries
+ 2021-02-23 bf5fa2d198 cmd/compile: guard special register usage with GOEXPERIMENT=regabi
+ 2021-02-23 c7f596f919 cmd/go: resolve TODO by replacing InDir() function
+ 2021-02-23 5e94fe9316 go/build/constraint: fix splitPlusBuild func doc comment
+ 2021-02-23 55d7dcc3cd runtime: optimize the memory padding in p struct
+ 2021-02-23 ab331c0254 runtime/cgo: use correct lean and mean macro
+ 2021-02-23 91cfbf39e4 cmd/link: set .ctors COFF section to writable and aligned
+ 2021-02-23 811167e2c9 cmd/link: do not pass -Bsymbolic for PE DLLs
+ 2021-02-23 a51daac840 cmd/link: set SizeOfRawData rather than VirtualSize in COFF files for .bss section
+ 2021-02-23 e5159b2a2f cmd/internal/dwarf: minor cleanups
+ 2021-02-23 b3b65f2176 runtime: enable race detector on openbsd/amd64
+ 2021-02-23 a78b0e6721 internal/poll: fix the verbose condition in splice
+ 2021-02-23 08543f0715 ios/fs: mention f.dir in (*subFS).fixErr godoc
+ 2021-02-23 0398a771d2 cmd/internal/obj/riscv: prevent constant loads that do not target registers
+ 2021-02-23 6525abddce cmd/internal/obj/riscv: clean up branch tests
+ 2021-02-23 c4b771348c runtime: fix windows/arm signal handling assembly
+ 2021-02-23 2a18e37c4e cmd/compile: remove backend's "scratch mem" support
+ 2021-02-23 e52149822b cmd/compile: simplify assert{E,I}2I{,2} calling conventions
+ 2021-02-23 86deb459de cmd/compile: remove selectnbrecv2
+ 2021-02-23 4048491234 cmd/compile,runtime: make selectnbrecv return two values
+ 2021-02-23 5e804ba17d cmd/compile: use transitive relations for slice len/cap in poset
+ 2021-02-23 6a40dd05d8 cmd/compile/internal/types2: review of sanitize.go
+ 2021-02-23 975ba6e2b2 cmd/compile: mark OpSB, OpSP as poor statement Op
+ 2021-02-23 a2e150c7cd go/types, cmd/compile/internal/types2: use regular type printing for unsafe.Pointer
+ 2021-02-23 5a0e4fc4e7 cmd/compile/internal/types2: review of conversions.go
+ 2021-02-23 89eb2b55b9 cmd/compile/internal/types2: review of issues_test.go
+ 2021-02-23 378f73e2d5 cmd/compile/internal/types2: enable TestIssue25627
+ 2021-02-23 1901e2647f test: add test for findTypeLoop with symbols from other packages
+ 2021-02-23 5f3dabbb79 cmd/compile: fix import of functions of multiple nested closure
+ 2021-02-23 7af821a661 all: faster midpoint computation in binary search
+ 2021-02-23 f113e9a14f cmd/dist: match goexperiment.regabi tag when GOEXPERIMENT is on
+ 2021-02-22 1126bbb82a go/parser: return ast.BadExpr for missing index operands
+ 2021-02-22 1678829d95 cmd/compile: correctly use X15 to zero frame
+ 2021-02-22 094048b938 cmd/compile/internal: loop opt
+ 2021-02-22 1391d4142c fix typo in issue16760.go
+ 2021-02-22 04903476fe cmd/compile: reject some rare looping CFGs in shortcircuit
+ 2021-02-22 87e984ab29 test: add test for issue 38698
+ 2021-02-22 b2bdadfe88 cmd/internal: cleanup ppc64 optab structure
+ 2021-02-21 0f66fb7b85 go/internal/gccgoimporter: fix up gccgo installation test
+ 2021-02-21 e78e04ce39 cmd/compile: fix panic in DWARF-gen handling obfuscated code
+ 2021-02-20 03d36d8198 syscall: add explicit ios build tag
+ 2021-02-20 40656f3a75 doc/1.16: fix link to fs.FileInfo
+ 2021-02-20 d4b2638234 all: go fmt std cmd (but revert vendor)
+ 2021-02-20 0625460f79 cmd/vet: update buildtag check for //go:build lines
+ 2021-02-20 9fd6cc105d go/printer: canonicalize //go:build and // +build lines while formatting
+ 2021-02-20 5b76343a10 go/build: prefer //go:build over // +build lines
+ 2021-02-20 a8942d2cff runtime/pprof: disable TestMorestack on darwin/arm64
+ 2021-02-20 078f08f0ee spec: every type has a method set (minor clarification)
+ 2021-02-19 26713b5fef go/types: don't write during sanitizeInfo if nothing has changed
+ 2021-02-19 9a99515c8f all: REVERSE MERGE dev.typeparams (7cdfa49) into master
+ 2021-02-19 7cdfa4969a [dev.typeparams] all: merge master (06b86e9) into dev.typeparams
+ 2021-02-19 6521c7b378 [dev.typeparams] cmd/compile/internal/types2: resolve decl cycle the same way as in go/types
+ 2021-02-19 06b86e9803 cmd/compile:  fix check to avoid creating new closure function when typechecking inline body
+ 2021-02-19 9322eec8a2 codereview.cfg: add codereview.cfg for master branch
+ 2021-02-19 02e5a8fdfc runtime: ignore SPWRITE in syscall functions
+ 2021-02-19 fa18f224c3 runtime/pprof: disable TestMorestack on macOS under race detector
+ 2021-02-19 01eb70e3dd os: fix hex exit code print on 32-bit windows
+ 2021-02-19 49add6ad90 runtime: fix spurious stack overflow detection
+ 2021-02-19 fce2a94d84 cmd/compile: fix buglet in inlined info abstract function dwarf-gen
+ 2021-02-19 dfe0ef961b [dev.typeparams] go/types, types2: revert fancy struct printing (fixes x/tools tests)
+ 2021-02-19 7764ee5614 runtime: fix invalid nil g check for for mips64x
+ 2021-02-19 2f37939a21 go/parser: improve error recovery from invalid selector exprs
+ 2021-02-19 8654db4555 [dev.typeparams] go/types: adjust printing of embedded struct fields (fixes x/tools/cmd/guru tests)
+ 2021-02-19 87f425da14 cmd/go/internal/mvs: split Reqs into narrower per-function interfaces
+ 2021-02-19 4da0188c6c cmd/go/internal/modget: split resolveCandidates into two methods
+ 2021-02-19 5f2e24efb3 cmd/internal/diff: skip over Cygwin warning in diff output
+ 2021-02-19 ee7038f6a5 net: disable Windows netsh tests when netsh won't run
+ 2021-02-19 40765ffa95 os/exec: disable failing LookPathTest on windows/arm64
+ 2021-02-19 b445d6ea34 runtime/pprof: expect tests to pass on macOS
+ 2021-02-19 b110a43628 runtime: delete gosave (dead code)
+ 2021-02-19 474d5f4f4d math: remove most 387 implementations
+ 2021-02-19 c7c6c113be runtime: convert windows/arm64 assembly
+ 2021-02-19 3527caa7d6 runtime: initial windows/arm64 implementation files
+ 2021-02-19 427bd7599d runtime: generate windows/arm64 callback asm
+ 2021-02-19 f6c4b4bf96 syscall: add windows/arm64 support
+ 2021-02-19 ac024a0c7b cmd/vendor: get golang.org/x/sys@beda7e5e158
+ 2021-02-19 a3b97e7628 test: disable nilptr on windows/arm64
+ 2021-02-19 985d087782 cmd/link: add windows/arm64 support
+ 2021-02-19 95a44d2409 cmd/internal/objfile: recognize Windows ARM64 executables
+ 2021-02-19 0ca0551f02 debug/pe: recognize arm64 executables
+ 2021-02-19 47e4b0739e Merge "[dev.typeparams] all: merge master (eb98272) into dev.typeparams" into dev.typeparams
+ 2021-02-19 0c633125f2 cmd/dist: add windows/arm64 support
+ 2021-02-19 bb6efb9609 build: set GOPATH consistently in run.bash, run.bat, run.rc
+ 2021-02-19 a1222b7535 cmd/link: add debug print in deadcode
+ 2021-02-19 1c659f2525 cmd/link: clean up windows PE generation
+ 2021-02-19 b6379f190b syscall: clean up windows a bit
+ 2021-02-19 09e059afb1 runtime: enable framepointer on all arm64
+ 2021-02-19 b19e7b518e runtime: clean up windows a bit
+ 2021-02-19 5421c37a1d runtime: fix windows/arm externalthreadhandler
+ 2021-02-19 91cc484ea9 runtime: fix time on windows/arm under WINE
+ 2021-02-19 38672d3dcf runtime: crash earlier on windows for runtime.abort
+ 2021-02-19 a1e9148e3d runtime: print hex numbers with hex prefixes in traceback debug
+ 2021-02-19 75e273fc2c runtime: fix windows/arm CONTEXT_CONTROL
+ 2021-02-19 76ab626bfc runtime: factor common code out of defs_windows_*.go
+ 2021-02-19 ece954d8b8 runtime: find g in Windows profiler using SP
+ 2021-02-19 a54f7fc0fd runtime: do not treat asmcgocall as a topofstack on g0
+ 2021-02-19 776ee4079a runtime: do not treat morestack as a topofstack
+ 2021-02-19 5ecd9e34df runtime: do not treat mcall as a topofstack
+ 2021-02-19 54da3ab385 runtime: use TOPFRAME to identify top-of-frame functions
+ 2021-02-19 fbe74dbf42 runtime: use FuncInfo SPWRITE flag to identify untraceable profile samples
+ 2021-02-19 4dd77bdc91 cmd/asm, cmd/link, runtime: introduce FuncInfo flag bits
+ 2021-02-19 aa0388f2ed runtime: remove unnecessary writes to gp.sched.g
+ 2021-02-19 6fe8981620 cmd/internal/obj/riscv: fix JMP name<>(SB)
+ 2021-02-19 01f05d8ff1 runtime: unify asmcgocall and systemstack traceback setup
+ 2021-02-19 229695a283 runtime: clean up funcID assignment
+ 2021-02-19 c80da0a33a runtime: handle nil gp in cpuprof
+ 2021-02-19 a78879ac67 runtime: move sys.DefaultGoroot to runtime.defaultGOROOT
+ 2021-02-19 8ac23a1f15 runtime: document, clean up internal/sys
+ 2021-02-19 678568a5cf runtime: delete windows setlasterror (unused)
+ 2021-02-19 0d94f989d1 runtime: clean up system calls during cgo callback init
+ 2021-02-19 e7ee3c1fa8 os: report Windows exit status in hex
+ 2021-02-18 a789be7814 [dev.typeparams] cmd/compile: use new converter functions rather than methods (fix build)
+ 2021-02-18 20050a15fe [dev.typeparams] cmd/compile:  support generic types (with stenciling of method calls)
+ 2021-02-18 e7493a9c74 [dev.typeparams] all: merge master (eb98272) into dev.typeparams
+ 2021-02-18 2ff1e05a4c [dev.typeparams] all: update parent repository
+ 2021-02-18 eb982727e3 cmd/go/internal/mvs: fix Downgrade to match Algorithm 4
+ 2021-02-18 3b7277d365 cmd/go: add a script test for artifacts resulting from 'go get -u'
+ 2021-02-18 8960ce7735 [dev.typeparams] cmd/compile/internal/types2: minor adjustments to match go/types more closely
+ 2021-02-18 6f3878b942 [dev.typeparams] cmd/compile/internal/types: review of typestring_test.go
+ 2021-02-18 d6bdd1aeef [dev.typeparams] cmd/compile/internal/types: review of typestring.go
+ 2021-02-18 c2314babb8 [dev.typeparams] cmd/compile/internal/types: review of type.go
+ 2021-02-18 099374b55e [dev.typeparams] cmd/compile/internal/types2: remove Type.Under method in favor of function
+ 2021-02-18 653386a89a [dev.typeparams] cmd/compile/internal/types2: replace Named, TypeParam methods with functions
+ 2021-02-18 5e4da8670b [dev.typeparams] cmd/compile/internal/types2: use converter functions rather than methods
+ 2021-02-18 5ecb9a7887 [dev.typeparams] go/types: use a new ast.ListExpr for multi-type instances
+ 2021-02-18 f3c2208e2c cmd/go: add script tests for potential upgrades due to downgrades
+ 2021-02-18 a5c8a15f64 cmd/go/internal/mvs: clarify and annotate test cases
+ 2021-02-18 a76efea1fe cmd/go/internal/mvs: don't emit duplicates from Req
+ 2021-02-18 609d82b289 cmd/dist: set GOARM=7 for windows/arm
+ 2021-02-18 7b679617f3 [dev.typeparams] go/types: conversions to type parameters are not constant
+ 2021-02-18 f0be3cc547 runtime: unbreak linux/riscv64 following regabi merge
+ 2021-02-18 07ef313525 runtime/cgo: add cast in C code to avoid C compiler warning
+ 2021-02-17 f5d0c653e6 [dev.typeparams] merge master (2f0da6d) into dev.typeparams
+ 2021-02-17 e196cb8258 [dev.typeparams] cmd/dist:  disable -G=3 on the std go tests for now
+ 2021-02-17 2f0da6d9e2 go/types: revert "no 'declared but not used' errors for invalid var decls"
+ 2021-02-17 70c37ee7d0 cmd/compile/internal/test: gofmt abiutils_test.go
+ 2021-02-16 84825599dc all: merge branch dev.regabi (d3cd4830ad) into master
+ 2021-02-16 d3cd4830ad [dev.regabi] test: run abi/regabipragma test with -c=1
+ 2021-02-16 03cea563d1 [dev.regabi] all: merge master (5faf941) into dev.regabi
+ 2021-02-16 b8fb049c7a [dev.regabi] cmd/go: copy internal/abi in TestNewReleaseRebuildsStalePackagesInGOPATH
+ 2021-02-16 5faf941df0 internal/goversion: update Version to 1.17
+ 2021-02-16 ed55da46ab [dev.regabi] go/types: overlapping embedded interfaces requires go1.14
+ 2021-02-16 7696c94334 [dev.regabi] go/types: type alias decl requires go1.9
+ 2021-02-16 c2358a1ae7 [dev.regabi] runtime: stub out spillArgs and unspillArgs
+ 2021-02-16 8cfbf34dd9 internal/abi: set register count constants to zero for regabi experiment
+ 2021-02-16 6f3da9d2f6 README: pull gopher image from website
+ 2021-02-16 d28aae26b0 [dev.regabi] cmd/link: recognize internal/abi as runtime package
+ 2021-02-16 098504c73f cmd/link: generate trampoline for inter-dependent packages
+ 2021-02-16 1004a7cb31 runtime/metrics: update documentation to current interface
+ 2021-02-16 6530f2617f doc/go1.16: remove draft notice
+ 2021-02-16 353e111455 doc/go1.16: fix mismatched id attribute
+ 2021-02-16 e0215315f5 [dev.regabi] reflect: support for register ABI on amd64 for reflect.(Value).Call
+ 2021-02-16 f0d23c9dbb internal/poll: netpollcheckerr before sendfile
+ 2021-02-16 0cb3415154 doc: remove all docs not tied to distribution
+ 2021-02-16 626ef08127 doc: remove install.html and install-source.html
+ 2021-02-16 30641e36aa internal/poll: if copy_file_range returns 0, assume it failed
+ 2021-02-15 33d72fd412 doc/faq: update generics entry to reflect accepted proposal
+ 2021-02-15 852ce7c212 cmd/go: provide a more helpful suggestion for "go vet -?"
+ 2021-02-13 66c27093d0 cmd/link: fix typo in link_test.go
+ 2021-02-13 b81efb7ec4 [dev.regabi] go/types: add support for language version checking
+ 2021-02-13 a7e9b4b948 [dev.regabi] go/types: untyped shift counts must fit into uint
+ 2021-02-13 060fa49bd2 [dev.regabi] go/types: refuse excessively long constants
+ 2021-02-12 a06bd9fecb [dev.typeparams] cmd/compile/internal/types: review of resolver_test.go
+ 2021-02-12 042f88fe30 [dev.typeparams] cmd/compile/internal/types: review of errors_test.go
+ 2021-02-12 0abd7b768b [dev.typeparams] cmd/compile/internal/types: review of universe.go
+ 2021-02-12 1b6f0bf1b2 [dev.typeparams] cmd/compile/internal/types: review of sizes_test.go
+ 2021-02-12 1758780181 [dev.typeparams] cmd/compile/internal/types: review of sizes.go
+ 2021-02-12 3aee461d5c [dev.typeparams] cmd/compile/internal/types: review of return.go
+ 2021-02-12 7428318af6 [dev.typeparams] cmd/compile/internal/types: review of object_test.go
+ 2021-02-12 b20f9e2da1 [dev.typeparams] cmd/compile/internal/types: review of object.go
+ 2021-02-12 20746b2f37 [dev.typeparams] cmd/compile/internal/types: review of labels.go
+ 2021-02-12 bab3461123 [dev.typeparams] cmd/compile/internal/types: review of infer.go
+ 2021-02-12 9168590977 [dev.typeparams] cmd/compile/internal/types: review of builtin_test.go
+ 2021-02-12 f1777cf84c [dev.typeparams] cmd/compile/internal/types: review of builtin.go
+ 2021-02-12 baa6c75dce [dev.regabi] internal/abi: add new internal/abi package for ABI constants
+ 2021-02-12 d1fd9a8863 [dev.regabi] all: merge master (ff0e93e) into dev.regabi
+ 2021-02-12 ff0e93ea31 doc/go1.16: note that package path elements beginning with '.' are disallowed
+ 2021-02-12 0f43973b4b [dev.typeparams] go/types: make predeclared "any" alias for interface{}
+ 2021-02-12 58758e0a21 [dev.typeparams] go/types: better error message for invalid ... use
+ 2021-02-11 c0aa7bd760 [dev.typeparams] cmd/compile: small fixes for stenciling
+ 2021-02-11 249da7ec02 CONTRIBUTORS: update for the Go 1.16 release
+ 2021-02-11 864d4f1c6b cmd/go: multiple small 'go help' fixes
+ 2021-02-11 26ceae85a8 spec: More precise wording in section on function calls.
+ 2021-02-11 930c2c9a68 cmd/go: reject embedded files that can't be packed into modules
+ 2021-02-11 e5b08e6d5c io/fs: allow backslash in ValidPath, reject in os.DirFS.Open
+ 2021-02-10 df23540dde [dev.typeparams] cmd/gofmt: add the -G flag to allow generic code
+ 2021-02-10 ed8079096f cmd/compile: mark concrete call of reflect.(*rtype).Method as REFLECTMETHOD
+ 2021-02-10 ddec18cf82 [dev.typeparams] cmd/compile/internal/types2: overlapping embedded interfaces requires go1.14
+ 2021-02-10 59703d53e2 [dev.regabi] cmd/link: stop using ABI aliases if wrapper is enabled
+ 2021-02-10 fdf3496fcc [dev.typeparams] cmd/compile:  make type conversions by type parameters work
+ 2021-02-10 12e15d430d [dev.typeparams] cmd/compile: handle calling a method on a type param in stenciling
+ 2021-02-09 e9c9683597 cmd/go: suppress errors from 'go get -d' for packages that only conditionally exist
+ 2021-02-09 168d6a49a5 [dev.regabi] go/types: use 512 bits as max. integer precision
+ 2021-02-09 0a62067708 [dev.regabi] go/types: adjust importer to match compiler importer
+ 2021-02-09 1c58fcf7ed [dev.regabi] go/types: handle untyped constant arithmetic overflow
+ 2021-02-09 493363ccff [dev.regabi] go/types: must not import a package called "init"
+ 2021-02-09 e0ac989cf3 archive/tar: detect out of bounds accesses in PAX records resulting from padded lengths
+ 2021-02-09 c48d1503ba [dev.regabi] go/types: report unused packages in source order
+ 2021-02-09 813958f13c [dev.regabi] go/types: factor out sorting of methods
+ 2021-02-09 11d15c171b [dev.regabi] go/types: convert untyped arguments to delete
+ 2021-02-08 ca18c42054 [dev.typeparams] merge dev.regabi (618e3c1) into dev.typeparams
+ 2021-02-09 c9d6f45fec runtime/metrics: fix a couple of documentation typpos
+ 2021-02-09 cea4e21b52 io/fs: backslash is always a glob meta character
+ 2021-02-08 dc725bfb3c doc/go1.16: mention new vet check for asn1.Unmarshal
+ 2021-02-08 618e3c15bd [dev.regabi] go/types: consistently report nil type as "untyped nil"
+ 2021-02-08 a360eeb528 [dev.typeparams] cmd/compile/internal/types2: conversions to type parameters are not constant
+ 2021-02-08 0fbde54ea6 [dev.typeparams] cmd/compile: allow generic funcs to call other generic funcs for stenciling
+ 2021-02-08 50449de66a [dev.regabi] all: merge master (1901853) into dev.regabi
+ 2021-02-08 7b0dfb177f [dev.regabi] runtime: use g register in some assembly functions on AMD64
+ 2021-02-08 2e60c00f56 [dev.regabi] cmd/internal/obj/x86: use g register in stack bounds check
+ 2021-02-08 22f9e1ccbc [dev.regabi] runtime: initialize special registers before sigpanic
+ 2021-02-08 5d7dc53888 [dev.regabi] cmd/compile, runtime: reserve R14 as g registers on AMD64
+ 2021-02-08 1901853098 runtime/metrics: fix panic in readingAllMetric example
+ 2021-02-08 ed3e4afa12 syscall/plan9: remove spooky fd action at a distance
+ 2021-02-08 a21de9ec73 [dev.regabi] cmd/link: resolve symbol ABI in shared linkage
+ 2021-02-05 724d0720b3 doc/go1.16: add missed heading tag in vet section
+ 2021-02-05 b54cd94d47 embed, io/fs: clarify that leading and trailing slashes are disallowed
+ 2021-02-05 4516afebed testing/fstest: avoid symlink-induced failures in tester
+ 2021-02-05 8fa84772ba [dev.regabi] runtime: delete gosave function
+ 2021-02-05 946351d5a2 [dev.regabi] runtime: zero X15 in racecall
+ 2021-02-05 397a46a10a [dev.regabi] cmd/asm: define g register on AMD64
+ 2021-02-05 e79c2fd428 [dev.regabi] runtime: mark racecallbackthunk as ABIInternal
+ 2021-02-05 7cc6de59f2 [dev.regabi] runtime: don't mark rt0_go ABIInternal
+ 2021-02-05 dcb5e0392e [dev.typeparams] cmd/compile: add stenciling of simple generic functions
+ 2021-02-05 63de211014 [dev.regabi] runtime/cgo: call setg_gcc in crosscall_amd64
+ 2021-02-04 f37b0c6c12 [dev.typeparams] cmd/compile/internal/types2: type alias decl requires go1.9
+ 2021-02-04 721488498a [dev.typeparams] cmd/compile: pass -lang flag value to new type checker
+ 2021-02-04 1ff2fdaaf1 [dev.typeparams] cmd/compile/internal/types2: add support for language version checking
+ 2021-02-04 370e9f5843 [dev.typeparams] cmd/compile/internal/types2: use 512 bits as max. integer precision
+ 2021-02-04 120b819f45 [dev.regabi] go/types: report error for invalid main function signature
+ 2021-02-04 52d5cb2822 [dev.regabi] cmd/internal/obj: access Attribute atomically
+ 2021-02-04 bc451b5770 [dev.regabi] go/types: port check_test.go ergonomics from dev.typeparams
+ 2021-02-04 afd67f3334 [dev.regabi] go/types: no "declared but not used" errors for invalid var decls
+ 2021-02-04 ca2f152893 [dev.typeparams] go/types: add missing test from dev.go2go
+ 2021-02-04 8869086d8f runtime: fix typo in histogram.go
+ 2021-02-03 401d7e5a24 [dev.regabi] cmd/compile: reserve X15 as zero register on AMD64
+ 2021-02-03 bfc7418e6d [dev.regabi] runtime, syscall, etc.: mark Darwin syscall wrappers as ABIInternal
+ 2021-02-03 e491c6eea9 math/big: fix comment in divRecursiveStep

Change-Id: Idc1fbc206629b016f7bb24c2066c2be9046a511a
2021-03-04 11:08:34 -05:00
Robert Griesemer
356c1719ec [dev.go2go] all: update/fix codereview.cfg
Change-Id: Icf1a6abc233298ab22fb0e9c3e3792ebd5ff1759
Reviewed-on: https://go-review.googlesource.com/c/go/+/295229
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
2021-02-22 23:59:03 +00:00
Rob Findley
1941f298de [dev.go2go] all: merge dev.typeparams (dc122c7) into dev.go2go
This merge resolved all conflicts by taking the dev.typeparams copy. The
only additional changes were to delete exprstring.go,
exprstring_test.go, methodset.go, and walk.go, which had been deleted
from dev.typeparams but were not present in the merge base.

go/build/deps_test.go was updated to allow go2go dependencies.

Change-Id: I2d6da3c1e44a4da888ee71165d5cb3702fec5f88
2021-02-04 09:12:51 -05:00
Rob Findley
c83a4376c9 [dev.go2go] go/*: merge parser and types changes from dev.typeparams
Merge just the conflicting changes from dev.typeparams (ast, parser,
types, etc.), excluding io/fs changes.

The rest of the dev.typeparams merge will be done in a later CL, once
the compiler changes have stabilized.

Change-Id: Ic24c5902e4cacc85338ab23b100e5a245a5148bc
Reviewed-on: https://go-review.googlesource.com/c/go/+/286774
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Robert Findley <rfindley@google.com>
2021-01-27 17:23:18 +00:00
Rob Findley
673969c453 [dev.go2go] cmd/go2go: update stale documentation for go2go
Update documentation to reflect that -brackets has been removed.

Change-Id: I02efd33ac646a41587a9aaafd2b31a23fb6849f9
Reviewed-on: https://go-review.googlesource.com/c/go/+/286773
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Robert Findley <rfindley@google.com>
2021-01-27 17:21:07 +00:00
Rob Findley
dd089351e9 [dev.go2go] cmd/go2go: remove -brackets from the go2go command
Remove the -brackets flag from the go2go command, as we will no longer
support multiple syntaxes.

Doing this also required removing a test for pointer designation, which
failed without the old syntax. Support for pointer designation will be
removed in the merge from dev.typeparams anyway.

Change-Id: I66f3e604aaa16ce92acc9d8f00e9fce9cd857ec5
Reviewed-on: https://go-review.googlesource.com/c/go/+/286432
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Robert Griesemer <gri@golang.org>
Trust: Robert Findley <rfindley@google.com>
2021-01-27 17:21:01 +00:00
Rob Findley
79f7966688 [dev.go2go] go/format: parse type parameters
In order to support generic code, cmd/gofmt was updated to parse type
parameters. However, the playground uses go/format, which was not
updated accordingly. Fix this.

A minor change is also made in go/printer to avoid a data race exposed
by this change.

Fixes #43470

Change-Id: I8a3ac5e3cbc8767e0ca1675130dd27634cb5018f
Reviewed-on: https://go-review.googlesource.com/c/go/+/283134
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Robert Findley <rfindley@google.com>
2021-01-12 16:41:23 +00:00
Rob Findley
aee3904d8f [dev.go2go] import errorcodes.go from the dev.typeparams branch
This is an initial commit to ensure that the automated deployment of
the go2go playground works as expected.

Change-Id: I76952843a5325bccaacca5ee4ed07c0dda9f33aa
Reviewed-on: https://go-review.googlesource.com/c/go/+/283133
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2021-01-12 00:15:40 +00:00
Rob Findley
abe4d3dce1 [dev.go2go] go/types: remove the aType helper
As of CL 274852, this helper type is no longer necessary.

Change-Id: I47945d5976817cc52b4f092229592d4422a59a67
Reviewed-on: https://go-review.googlesource.com/c/go/+/276193
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
2020-12-08 17:59:47 +00:00
Rob Findley
a87ed01cf0 [dev.go2go] go/types: revert the Type interface for compatibility
The go2go prototype added converter methods to the Type interface for
convenience, but this change breaks compatibility.

Revert to the previous Type interface, and move the converters to helper
functions. Along the way, enforce some relationships between converters
that simplify the code and avoid switch statements:
 - optype(under(t)) == optype(t)
 - asNamed(expand(t)) == asNamed(t)
 - asTypeParam(under(t)) == asTypeParam(t)
 - as<Other>(optype(t)) == as<Other>(t)

Where possible functions are unexported, with a couple exceptions that
are necessary for the go2go rewriter. These exceptions could probably be
avoided, but it doesn't seem worth the effort.

Eliminating interface methods introduces initialization cycles involving
unaryOpPredicates and binaryOpPredicates, which are avoided using init
functions.

Change-Id: Ia695395431e93b4b5c3484ae07531b561599f437
Reviewed-on: https://go-review.googlesource.com/c/go/+/274852
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
Trust: Robert Griesemer <gri@golang.org>
Trust: Robert Findley <rfindley@google.com>
2020-12-04 14:30:20 +00:00
Robert Griesemer
a9402335f2 [dev.go2go] go/types, cmd/compile/internal/types2: a type parameter is a valid type case in a type switch
Likewise for type assertions.

Updates #42758.

Change-Id: Iea727639f348c6997b4d3aaba420ea242e985002
Reviewed-on: https://go-review.googlesource.com/c/go/+/273127
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-11-25 05:57:40 +00:00
Robert Griesemer
440f144a10 [dev.go2go] go/types, cmd/compile/internal/types2: fix incorrect string(int) conversion (regression)
This is a 1:1 port of the go/types changes in
https://golang.org/cl/272666 (master branch).

Updates #42790.

Change-Id: I633fab83ce9c9895e056592039e1f5e7cb3fe23e
Reviewed-on: https://go-review.googlesource.com/c/go/+/272667
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-11-24 01:29:01 +00:00
Robert Griesemer
9daca74ad2 [dev.go2go] cmd/compile/internal/types2: port of CL 270657 and CL 270937
- Port of https://golang.org/cl/270657 in go/types to types2.
- Port of https://golang.org/cl/270937 in go/types to types2.

Change-Id: I7d6dadf5bb91c89e51975127bded4279c92510cc
Reviewed-on: https://go-review.googlesource.com/c/go/+/270957
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-11-18 00:18:01 +00:00
Robert Griesemer
d5beb04d48 [dev.go2go] go/types: backport of https://golang.org/cl/270658
Change-Id: I8f31adff3e0a44767ebdcde3059336bcd549a4b2
Reviewed-on: https://go-review.googlesource.com/c/go/+/270937
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-11-18 00:17:59 +00:00
Robert Griesemer
bac01b04ab [dev.go2go] go/types: fix indexing of type parameter values constraint by maps
For instance, given a constraint

	interface { type []E, map[K]E }

and a variable x of type parameter type constraint by above constraint,
the index expression x[i] is only permitted if K is an integer type.
Also, &x[i] is not permitted if the type list contains a map type since
map index expressions are not addressable. Finally, if the type list
contains only compatible map types, the index expression x[i] can be
used in a comma-ok assignment.

Fixes #42616.

Change-Id: I6287de47619acee25efbcd73a7b04b835d26a885
Reviewed-on: https://go-review.googlesource.com/c/go/+/270657
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-11-17 06:11:46 +00:00
Robert Griesemer
2298dab082 [dev.go2go] cmd/compile/internal/types2: backport latest changes from dev.typeparams
With this CL, the types2 packages in the dev.go2go and dev.typeparams
branch are the same again.

Change-Id: If2cd9256a73fd75cc28675e9baac27ef6a289935
Reviewed-on: https://go-review.googlesource.com/c/go/+/264030
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-22 00:19:08 +00:00
Robert Griesemer
8d00158448 [dev.go2go] cmd/compile/internal/syntax: backport changes from dev.typeparams branch
Change-Id: Iaf9bbd80258746fbcaf7b35919c22528a504bcc2
Reviewed-on: https://go-review.googlesource.com/c/go/+/263629
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-20 04:52:06 +00:00
Robert Griesemer
5ab6b82982 [dev.go2go] cmd/compile/internal/types2: implement syntax tree walk, enable all ResolveIdents test
Also: When type-checking struct types, type-check types shared among
multiple fields (such as type T in "a, b, c T") only once rather than
for each field.

Change-Id: I84d6bb0a01863963d214f59e9f58706c29ae5a16
Reviewed-on: https://go-review.googlesource.com/c/go/+/262840
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-16 01:06:25 +00:00
Robert Griesemer
dab75f981e [dev.go2go] cmd/compile/internal/syntax2: comprehensive channel printing tests
This matches the code in dev.typeparams now.

Change-Id: I75de25756d9bdc3de587653ff519f5e7bb5d6369
Reviewed-on: https://go-review.googlesource.com/c/go/+/262839
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-16 01:06:16 +00:00
Robert Griesemer
69b4547432 [dev.go2go] cmd/compile/internal/types2: remove dead code, invalid comment (cleanups)
Change-Id: I8babc2f3a2714d3a184380416bb25fae0997eaac
Reviewed-on: https://go-review.googlesource.com/c/go/+/262838
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-16 01:06:15 +00:00
Robert Griesemer
fef4c5f526 [dev.go2go] cmd/compile/internal/syntax: fix printing of channel types
Change-Id: I79fc051dc9e79638e3c0078ecdcf667bfa50891a
Reviewed-on: https://go-review.googlesource.com/c/go/+/262443
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-15 05:18:32 +00:00
Robert Griesemer
b7ce5f8101 [dev.go2go] cmd/compile/internal/types2: ordinary index expressions can have only one index
With type parameters, an index expression a[i, j] is syntactically possible.
Report an error if it is not a function or type instantiation rather than panic.

Change-Id: I562a56d7fa4febf75432dbe920aec2ff0db76449
Reviewed-on: https://go-review.googlesource.com/c/go/+/262441
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-15 03:52:05 +00:00
Robert Griesemer
5496b9d0bc [dev.go2go] cmd/compile/internal/types2: use Checker.funcInst for function instantiations
Also:
- Simplified code for index expressions that are type instantiations.
- Removed code from Checker.call that was needed for function instantiations.
- Removed handling of *syntax.CallExpr for types (we use *syntax.IndexExpr).
- Added a missing Checker.use call to satisfy a test that would now report an error.
- Adjusted some tests that were still using ()'s rather than []'s.

Change-Id: I559dcac641ab32f1c323481066afb0773e7e95dc
Reviewed-on: https://go-review.googlesource.com/c/go/+/262440
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-15 03:52:04 +00:00
Robert Griesemer
4f077672b7 [dev.go2go] cmd/compile/internal/types2: factor out function instantiation from call check
Change-Id: If933d0f9a58f3f5e6ddb0e94b1d9f3b859b40352
Reviewed-on: https://go-review.googlesource.com/c/go/+/262439
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-15 03:52:02 +00:00
Robert Griesemer
cbfbbc3bed [dev.go2go] cmd/compile/internal/syntax,types2: always use IndexExpr node for type instantiation
Per @mdempsky's suggestion: Instead of representing a type instantiation T[P]
by an IndexExpr node, and a type instantiation with multiple type arguments
T[P1, P2] by a CallExpr node with special Brackets flag, always use an IndexExpr.
Use a ListExpr as index in the (less common) case of multiple type arguments.

This removes the need for the CallExpr.Brackets field and cleans up the parser
(and eventually the type checker) code for type instantiations.

Change-Id: I5ff784800c8235d278b15c69a8a03acfca144b37
Reviewed-on: https://go-review.googlesource.com/c/go/+/262020
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-14 22:27:13 +00:00
Robert Griesemer
32b18b7307 [dev.go2go] go/types, .../types2: fix subtle bug (typo) in receiver type rewriting
Also: Simplify ParenExpr case.
Change-Id: I09cb6988222cb19835617cb6bcc089307b675ab2
Reviewed-on: https://go-review.googlesource.com/c/go/+/262021
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-14 04:08:57 +00:00
Robert Griesemer
c4e9233358 [dev.go2go] cmd/compile/internal/syntax: backport of changes made in dev.typeparams
The changes match the CLs:

https://golang.org/cl/261657
https://golang.org/cl/261658
https://golang.org/cl/261219
https://golang.org/cl/261660

Also: Updated types2 test to match parser changes.

Change-Id: I397980c41234b43a4f12d0ab4ecc3fc23fad278b
Reviewed-on: https://go-review.googlesource.com/c/go/+/261757
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-13 05:32:17 +00:00
Robert Griesemer
10bb7589dd [dev.go2go] cmd/compile: enable parsing of generic code with new -G flag
Providing the -G flag instructs the compiler to accept generic code.
For now, the compiler only parses such files and then exits.

Added a new test directory (test/generic) and initial test case for
generic code.

Change-Id: Ic11e33a9d5f012f8def0bdae205043659562ac73
Reviewed-on: https://go-review.googlesource.com/c/go/+/261659
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-12 23:40:05 +00:00
Robert Griesemer
4ba7c9eef6 [dev.go2go] cmd/compile/internal/syntax: add AllowGenerics mode for enabling/disabling type parameters
Change-Id: I1f6273c2253d1d6e7395b665c6700c6c937b8564
Reviewed-on: https://go-review.googlesource.com/c/go/+/261597
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-12 18:02:18 +00:00
Robert Griesemer
5f39ddea15 [dev.go2go] cmd/compile/internal/types2: enable TestTestdata
All /testdata tests pass now with relaxed column position requirement.

Change-Id: Idabde521f97b042e8f6018f66e037e2494903a3c
Reviewed-on: https://go-review.googlesource.com/c/go/+/261298
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-10 23:39:20 +00:00
Robert Griesemer
99e8b46e6d [dev.go2go] cmd/compile/internal/types2: permit inexact column position for error tests
Change-Id: Ief4067bff20a94aea09a3993c96d2ba9d623b147
Reviewed-on: https://go-review.googlesource.com/c/go/+/261297
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-10 23:39:18 +00:00
Robert Griesemer
f2c8981d40 [dev.go2go] cmd/compile/internal/types2: various fixes towards enabling TestTestdata
- Fix Checker.use (code was nonsensical).
- Fix arity check for const and var decls.
- Fix binary op predicates.
- Fix collection of parameters: make sure each type (incl. ...T types) is only checked once.
- Report an invalid AST error for 3-index slice expressions with missing indices.
- Adjust some tests to match error messages about 3-index slice expressions.
- Fix position for "missing return" error.
- Provide a better error message for incorrect x++/x-- statements.
- Don't report an error for for-loop post declaration statement (the parser does already).
- Adjust some tests for const/var init expressions because we don't get duplicate errors anymore.
- Adjust some tests to match error messages about methods with multiple receivers.
- Adjust some tests for imports because we don't get duplicate errors anymore.
- Disable tests that check interface method type parameters (parser doesn't collect them).
- Adjust some tests for incorrect type instantiations (parser reports the errors).
- Adjust some tests for go/defer statements (parser reports one of the errors).

With these changes, TestTestdata passes now if we ignore exact error column position.
The next CL will enable imprecise error position matching (only line numbers need to
match) and then we can enable the test.

Change-Id: I46fbcb300f065729f4e4660b40edcd2d1e6c78b0
Reviewed-on: https://go-review.googlesource.com/c/go/+/261277
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-10 23:39:17 +00:00
Robert Griesemer
3ae3ea1f0e [dev.go2go] cmd/compile/internal/syntax: provide BadExpr where needed, call correct error handler
- For "if" statements without a condition, provide a BadExpr rather than nil
  so that the type checker doesn't report the same error again.

- For 3-index slice expressions, also provide BadExpr where an index is
  required but missing.

- Declare a parser-local error method to hide the embedded error method
  so we don't use it by mistake.

Change-Id: I19f89668025e17bd6c632cc98c57bd1f5ca099a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/261138
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-10 23:39:16 +00:00
Robert Griesemer
0d5173761c [dev.go2go] cmd/compile/internal/types2: remove another dependency on go/scanner
Instead use syntax.CommentsDo.

Change-Id: I5a12349de81a4e3e96846f2c3c63c8f0fd4294a3
Reviewed-on: https://go-review.googlesource.com/c/go/+/261157
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-10 00:28:53 +00:00
Robert Griesemer
f857dab8dc [dev.go2go] cmd/compile/internal/types2: remove unused token.FileSet from self_test.go
Change-Id: I9e55a96675cc08ef97e84bda0dbaa77e9fece0e2
Reviewed-on: https://go-review.googlesource.com/c/go/+/260058
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-07 05:44:55 +00:00
Robert Griesemer
e595b8c245 [dev.go2go] cmd/compile/internal/syntax2: rewrite checkFiles in terms of syntax.ErrorMap
This eliminates another of the remaining dependencies on the go/* libraries.
The rewrite also enables "approximate" matching where the reported and expected
lines match, but the columns don't.

Change-Id: Ia81c565ee4c9d14e2c224c7f3f7f1b37595d5524
Reviewed-on: https://go-review.googlesource.com/c/go/+/260057
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-07 05:44:45 +00:00
Robert Griesemer
4889382453 [dev.go2go] cmd/compile/internal/syntax: implement ErrorMap
Also: Move CommentsDo into testing.go.

Change-Id: I78a05f2c4486378f05de41152d5739241ba334cb
Reviewed-on: https://go-review.googlesource.com/c/go/+/260019
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-10-07 05:25:37 +00:00
Robert Griesemer
b81fb4e758 [dev.go2go] cmd/go2go: fix typo in test case
Fixes #41574.

Change-Id: I885f72bd68798b4ccdc539b062afa0d36debce4e
Reviewed-on: https://go-review.googlesource.com/c/go/+/256718
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
Run-TryBot: Ian Lance Taylor <iant@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
2020-09-24 00:15:54 +00:00
Robert Griesemer
e9e897e0fe [dev.go2go] cmd/compile/internal/types2: rename and move leftPos into pos.go (cleanup)
- renamed leftPos to startPos (matching endPos)
- moved startPos into pos.go
- converted code into (manual) tail-recursive form (matching endPos)

Change-Id: Iaf1f6b9ff15120c383fd12928917d8306401c747
Reviewed-on: https://go-review.googlesource.com/c/go/+/255077
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-15 19:46:15 +00:00
Robert Griesemer
6d0b55d886 [dev.go2go] cmd/compile/internal/types2: enable ScopeLookupParent test
- set missing scope positions for objects
- set various end positions for scopes
- implemented endPos function to determine approx. end positions of nodes

Change-Id: Id908f534725b6becc7d2ccbc4382b1042399c556
Reviewed-on: https://go-review.googlesource.com/c/go/+/254958
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-15 19:34:27 +00:00
Robert Griesemer
e62efddde2 [dev.go2go] cmd/compile/internal/types2: get ScopeLookupParent test to compile again
- Fixed commented out code to compile within syntax-based type checker again.
  Test is still disabled as it doesn't pass yet.

- Added syntax.CommentsDo general file comment/error iterator.

Change-Id: I28425d5c129cab5a085f8f427d8b8476fafa99a3
Reviewed-on: https://go-review.googlesource.com/c/go/+/254957
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-15 04:02:26 +00:00
Robert Griesemer
ff2a0a7ea4 [dev.go2go] cmd/compile/internal/syntax: replace Files.Lines with Files.EOF position
Having the actual end position of a file also provides the number of
lines and is more easily used to determine the (scope) range of a file
as needed by cmd/compile/internal/types2.

Change-Id: Idea736b7caacebbb9e0ebc2094057f4cd54084b2
Reviewed-on: https://go-review.googlesource.com/c/go/+/254897
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-15 00:48:09 +00:00
Robert Griesemer
a47099db29 [dev.go2go] cmd/compile/internal/types2: error handlers now take a poser instead of a Pos
This change makes the recent error handler change type-safe again:
Rather than taking a syntax.Pos (and requiring each caller to call
the Pos method), now an error handler accepts a poser

type poser interface
   Pos() syntax.Pos
}

and then can call Pos directly.

Change-Id: I618db450725b49da873e121e1c1ef603dfc6fe5a
Reviewed-on: https://go-review.googlesource.com/c/go/+/254858
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
2020-09-14 22:14:42 +00:00
Robert Griesemer
aa0705b3a7 [dev.go2go] cmd/compile/internal/types2: fix error positions for nodes
Nodes of the syntax AST record a position identifying the node's syntactic
feature (e.g., the position of the '.' in a selector expression, or the
position of the '[' in an index expression). But the go/ast reports the
left-most (= start) position of a node, which is what the existing go/types
based test cases expect.

Compute the left-most position of nodes for error reporting. To simplify
error handler calls, pass syntax.Nodes, Objects, or *operands in place of
a syntax.Pos and let the error handler functions decide how to determine
the correct position. This removes > 200 method pos/Pos method calls.

Renamed invalidAST/Arg/Op error handler functions to invalidASTf/Argf/Opf
for consistency.

Fixed several type-checker bugs (incorrectly ported from go/types).

Enabled Fixedbugs tests.

Fixed a bug in go/types/builtins.go.

Change-Id: I05bb749a5374fc3cc2818094bc59a58972443744
Reviewed-on: https://go-review.googlesource.com/c/go/+/254437
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-12 01:25:34 +00:00
Robert Griesemer
ec995dab79 [dev.go2go] cmd/compile/internal/types2: enable Example tests
- correctly collect parser errors
- fix a few small parser and type checker bugs
- don't skip Example tests anymore

Change-Id: Ia3f9a63fd97c410bbe9bbc21efe9dccae4551586
Reviewed-on: https://go-review.googlesource.com/c/go/+/254277
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-11 03:57:18 +00:00
Robert Griesemer
2eecf29c10 [dev.go2go] go/types: minor adjustment to two tests
Brings go/types in sync with the respective tests in types2.

Change-Id: I7d97657c9b8dc8171834739f649907e1767a0feb
Reviewed-on: https://go-review.googlesource.com/c/go/+/253998
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-10 22:35:49 +00:00
Robert Griesemer
37ac354972 [dev.go2go] cmd/compile/internal/types2: bring over latest go/types changes
Change-Id: I2379f7d84bfe18c4349711555554cce85c103eb1
Reviewed-on: https://go-review.googlesource.com/c/go/+/254197
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-10 22:28:33 +00:00
Robert Griesemer
e6a1350191 [dev.go2go] cmd/compile/internal/syntax: restore errors for embedded parenthesized fields
When we used ()'s for type parameters, we needed to relax the rules for
embedded struct fields and interface methods: parenthesized embedded
fields and methods were necessary to disambiguate from other constructs.
Now that we use []'s, we can go back to the existing Go rules.

Minor cleanups.

Change-Id: I45399e5b5592c76654a5d504f8bb8b23fff53b85
Reviewed-on: https://go-review.googlesource.com/c/go/+/253997
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-10 18:36:09 +00:00
Robert Griesemer
c3f85a2312 [dev.go2go] cmd/compile/internal/syntax: use unified parameter syntax
- type and ordinary parameter list follow the same syntax
- type parameters are enclosed in [], ordinary parameters use ()
- type parameter lists cannot be empty
- all type parameters must be named

Adjusted parser to follow new syntax. Lots of related cleanups.
Adjusted testdata/go2/x.go2 tests and removed the xB.go2 tests.
Preliminary adjustments to types2 package to make tests pass.

Change-Id: Ic4e6597180b97f06345f60cafa9bfc7c642a26ad
Reviewed-on: https://go-review.googlesource.com/c/go/+/253040
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-10 04:49:13 +00:00
Ian Lance Taylor
e6b857770a [dev.go2go] go/go2go: handle inferred arguments for index expressions
Fixes golang/go#41216

Change-Id: Iff109f0a7f047742c5f90d64db201712c04f3259
Reviewed-on: https://go-review.googlesource.com/c/go/+/253818
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-09-09 21:19:10 +00:00
Robert Griesemer
573d94888f [dev.go2go] go/types: don't crash when a generic function is instantiated with a value
Change-Id: I9fe898c57590e9d80545543bca87676e16c6b728
Reviewed-on: https://go-review.googlesource.com/c/go/+/253379
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-07 21:23:04 +00:00
Robert Griesemer
a2c342556d [dev.go2go] go/types: record constraint type inference when some type params are provided
The existing code didn't record the results of constraint type inference
when it was applied to a partial list of (provided) type parameters.

Changed Info.Inferred map to accept *ast.CallExpr and *ast.IndexExpr
as keys ("call" may be f(x) or f[T]).

Updates #41216.

Change-Id: I5da7467d01643bf74fb78f6c6728209cbd4006c4
Reviewed-on: https://go-review.googlesource.com/c/go/+/253258
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-07 19:09:58 +00:00
Robert Griesemer
9ff2aa4272 [dev.go2go] cmd/gofmt, go/format: set []-mode for type parameters in a few more places
Now that we have mostly settled on the type parameter list syntax we should
probably remove the various modes of parsing and printing. For now just set
the UseBrackets flag explicitly when printing.

Updates #41195.

Change-Id: I56b06b4f930908579a38a140e8221618c8e2fa17
Reviewed-on: https://go-review.googlesource.com/c/go/+/252879
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-09-02 23:45:03 +00:00
Robert Griesemer
8ea0120a21 [dev.go2go] go/types: interfaces with type lists are only allowed as constraints
Check that such constraint interfaces don't appear in:
- composite types
- type and function instantiations
- assertions
- type switches

Streamlined respective error messages. Added lots of tests.

Fixes #41124.

Change-Id: Ie04a95ab056b40561484f04ed6e843ca371e1d41
Reviewed-on: https://go-review.googlesource.com/c/go/+/251718
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-31 05:23:21 +00:00
Robert Griesemer
c4914f19b5 [dev.go2go] go/types: improve error when a type argument doesn't satisfy constraint
If the cause is a method with incorrect signature, report the
expected and presented signature.

Updates #41125.

Change-Id: Ibd0fa23547b77df924ec5421cc8e657d41c5a5a6
Reviewed-on: https://go-review.googlesource.com/c/go/+/251717
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-31 00:10:51 +00:00
Robert Griesemer
ea8318cad7 [dev.go2go] go/parser, go/types: type parameters must always be named
Change-Id: Ia78ec8ebc7bc7432c3ca3c75dbca3ffedc6ab388
Reviewed-on: https://go-review.googlesource.com/c/go/+/251561
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-29 01:02:37 +00:00
Robert Griesemer
4d89d2a7e3 [dev.go2go] go/parser: adjust error message for mixed parameter lists
Error doesn't just apply to ordinary function parameters anymore;
it could be a (type or function) type parameter list.

Change-Id: Ied75d363917079b265140eb1f1a291d98e019229
Reviewed-on: https://go-review.googlesource.com/c/go/+/251558
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-28 22:45:43 +00:00
Robert Griesemer
4461513296 [dev.go2go] go/types: add missing instantiation checks for function type arguments
Fixes #40684.

Change-Id: If642edbf321973729a8d5b36b4bf61e3fae7ee3a
Reviewed-on: https://go-review.googlesource.com/c/go/+/251557
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-28 22:45:41 +00:00
Robert Griesemer
93e810a5f5 [dev.go2go] go/types: gotype cmd to use new unified type parameter syntax
Change-Id: I76b0d0312e9f7e262139e3b7e4fb8c22989fbca9
Reviewed-on: https://go-review.googlesource.com/c/go/+/251443
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-28 22:12:57 +00:00
Ian Lance Taylor
36bab40fc1 [dev.go2go] cmd/gofmt: pass UnifiedParamLists to parser
Fixes #41079

Change-Id: I781c5c681c66712ed2ac0112dd44fa8793845978
Reviewed-on: https://go-review.googlesource.com/c/go/+/251278
Run-TryBot: Ian Lance Taylor <iant@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
2020-08-28 02:28:04 +00:00
Robert Griesemer
5e60d1e8c7 [dev.go2go] go/types: predeclared "any" is only visible as constraint in a type parameter list
Per the restriction in the current design draft.

Change-Id: Ic6ff597849335fa23de22529999d20aacfc205b0
Reviewed-on: https://go-review.googlesource.com/c/go/+/251140
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-27 23:37:57 +00:00
Robert Griesemer
dd1af75a70 [dev.go2go] go/types: disable implicit instantiation of single type parameter constraints
Per the latest update to the design draft.

Change-Id: I026b52082e739f6806cd37a0f3e88a546a6f2e90
Reviewed-on: https://go-review.googlesource.com/c/go/+/251139
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-27 23:37:55 +00:00
Robert Griesemer
af1adc5d8c [dev.go2go] go/parser, go/types: make type parameters a syntax error for type aliases
Accept parameterized aliases for robustness but complain.

Change-Id: I86ad945af253b6c483fca0ac331245730fb22a66
Reviewed-on: https://go-review.googlesource.com/c/go/+/251138
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-27 20:00:05 +00:00
Robert Griesemer
21bc157bc5 [dev.go2go] go/parser: disallow empty type parameter lists and instantiations
When using unified parameter list syntax, an empty type parameter
list in a type declaration is impossible (it means a slice type).
For symmetry, and because it doesn't make sense to support it,
disallow empty type parameter lists in function declarations.
Accept (parse) them but report a syntax error.

Analogously, disallow empty index/slice/instantiation expressions.
Accept (parse) them but report a syntax error.

Adjust go/types and tests as necessary.

Change-Id: Ifc783245a54d276eb22232a7a74be4d47a7d33fe
Reviewed-on: https://go-review.googlesource.com/c/go/+/250718
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-08-27 19:10:21 +00:00
Robert Griesemer
3314879ed2 [dev.go2go] go/printer: don't write "type" keyword in type parameter lists if brackets are used
When the printer mode UseBrackets is set, use the new unified parameter
list syntax: use []'s for type parameters without the "type" keyword.
This will also change gofmt behavior accordingly.

Fixes #41053.

Change-Id: Ibaf490ea9ed178684bea34da5b57afa823a6829f
Reviewed-on: https://go-review.googlesource.com/c/go/+/250998
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-27 05:16:25 +00:00
Robert Griesemer
27c9d6ef7c [dev.go2go] cmd/go2go: switch to unified parameter syntax
Type and ordinary parameter lists use the same syntax except
for the square brackets or parentheses, respectively.

Change-Id: I6fb93e93bbfc649a2c1ef195d130e0dcee212c79
Reviewed-on: https://go-review.googlesource.com/c/go/+/250717
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-08-26 16:50:50 +00:00
Robert Griesemer
1964d56295 [dev.go2go] go/types: adjust all tests to use latest syntax
- use square brackets for type parameters
- otherwise, use same syntax as for ordinary parameters:
  all type parameters must have a constraint, can be "any"
- remove (rename) all *B.go2 tests in favor of adjusted *.go2 tests
- remove tests related to pointer notation for type parameters
  (we are going to use constraint type inference instead)
- adjust type string computation accordingly
- minor related adjustments

This change can be reverted if we don't like it.

Change-Id: Ie1034e0996df8f5ca6fbdf9ecaa3c93fcfd7106d
Reviewed-on: https://go-review.googlesource.com/c/go/+/249741
Reviewed-by: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
2020-08-26 01:59:01 +00:00
Robert Griesemer
7d90fb0025 [dev.go2go] go/parser: add mode for unified type and ordinary parameter list syntax
If UnifiedParamLists is set, type parameter must follow the syntax of ordinary
parameter lists except that they use square brackets rather than parentheses.

Change-Id: Ia17753eab2ab07e9ef62715a7b97d641f7d08cca
Reviewed-on: https://go-review.googlesource.com/c/go/+/249740
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-26 01:57:29 +00:00
Robert Griesemer
12c2128b9e [dev.go2go] go/go2go, go/types: enable constraint type inference
Constraint type inference was not enabled for go/go2go and gotype.

Fixes #40859.

Change-Id: Idcab4d0a2eae6f42f938604fb05aabe4ad94c934
Reviewed-on: https://go-review.googlesource.com/c/go/+/249737
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-08-21 00:12:31 +00:00
Ian Lance Taylor
ec50ad4981 [dev.go2go] cmd/go2go: in testdata, drop type keyword, always provide constraint
This is a rewrite of the tests to drop the type keyword for parameterized
functions and types, and to instead always provide a constraint.

We can revert if we don't like this approach.

Change-Id: I9cd097b8db2aa3c84a40a7aeaa10246ab3b990dc
Reviewed-on: https://go-review.googlesource.com/c/go/+/248897
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-08-17 17:54:56 +00:00
Ian Lance Taylor
bc00f5ba9f [dev.go2go] test: drop type keyword, always provide constraint
This is a rewrite to drop the type keyword for parameterized functions
and types, and to instead always provide a constraint.

We can revert if we don't like this approach.

Change-Id: If4669fb4e2015067e9f955ff8567ed421be639ea
Reviewed-on: https://go-review.googlesource.com/c/go/+/248880
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-08-17 17:54:48 +00:00
Robert Griesemer
af48c2e84b [dev.go2go] go/types: use actual (not underlying) types of type list elements for interface satisfaction
This is a rule change in an attempt to streamline interface satisfaction:
If a (constraint) interface contains a type list, a type argument's type
or underlying type must be included in the type list (and the interface's
methods must be present, of course). Until now, a type argument's under-
lying type had to be one of the underlying types of the types in the type
list.

The effect is subtle: Because an underlying type is never a defined type,
if a type list contains defined types, only those defined types satisfy
the interface. If we want the interface to be more flexible, we can in-
clude non-defined types in its type list. In the common case, type lists
simply contain predeclared types (whose underlying types are themselves),
so this doesn't matter. An observable difference appears only for code
that currently uses defined types in constraint type lists: such code
becomes slightly more restrictive.

The primary benefit of this change is that it opens the door for general
(non-constraint) use of interfaces with type lists: Using the same rules
as for constraint satisfaction, a value may be assigned to a variable of
such an interface if it or its underlying type of the value is included
int the interface's type list. If the type list contains only defined types,
the respective interface acts like a sum type: it can only contain values
of those types (and nil).

This CL only changes the rules for constraints. It does not permit
interfaces with type lists for general (non-constraint) use for now.

Change-Id: I3f25b9d883dd865a74c583efee4be2e22258d493
Reviewed-on: https://go-review.googlesource.com/c/go/+/248265
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-14 23:21:42 +00:00
Robert Griesemer
722af87f62 [dev.go2go] go/types: determine if type declaration is generic based on use of type parameter
This change makes it possible to declare a generic type with exactly
one type parameter and no constraints without any special syntactic
augmentation: Instead, the parser determines whether a declaration
of the form

	type T[P] type_literal

is an array or generic declaration based on how the type parameter
P is used in type_literal. If P appears only in array lengths (if
at all) in type_literal, T is an array type. Otherwise it is a
generic type.

Change-Id: I6c1d62d61d04f322d73ee16840e0f3ffe299f4c7
Reviewed-on: https://go-review.googlesource.com/c/go/+/248438
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-14 05:30:01 +00:00
Robert Griesemer
c3a77cc2d3 [dev.go2go] go/types: predeclare type any interface{} (experiment)
For fine-tuning the type parameter list notation. If we
proceed with square brackets rather than parentheses, we
don't need the "type" keyword in type parameter lists in
many cases. However, generic type declarations with one
type parameter and no constraint must somehow disambiguate
from array type declarations:

	type T[P] E

could be a generic type, or an array type declaration

	type T [P]E

There's a variety of choices for disambiguation, such as:

	type T[type P] E         // what we do now
	type T[P interface{}] E  // currently permitted
	type T[P any] E          // permitted with this CL
	type T[P,] E             // currently permitted

If we abandon the "type" keyword (currently optional), we
need an alternative. Writing the constraint seems nicer than
the comma option (in Go, all parameter lists permit a trailing
comma, but an array length specification doesn't allow it).
If we write the constraint, which is often the empty interface,
being able to write "any" would be more convenient.

In the past we have refused to add "any" to the language. There
may be many more situations where we need to specify an empty
constraint (any) so perhaps adding "any" is now justified. It
would also streamline a lot of existing code such as

	Printf(format string, args... any)

Change-Id: I366342ba8d981d344c96b1ceb60f61d963e9175a
Reviewed-on: https://go-review.googlesource.com/c/go/+/248263
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-14 05:13:41 +00:00
Robert Griesemer
2b748f02a0 [dev.go2go] cmd/compile/internal/types2: fix instantiation crash for generic type parameters
Port of go/types CL https://golang.org/cl/247498.

Updates #40038.

Change-Id: Iab002132627b689e0113c087b3f4d38c6356c3a3
Reviewed-on: https://go-review.googlesource.com/c/go/+/248058
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-12 00:03:11 +00:00
Robert Griesemer
fc29b9010e [dev.go2go] cmd/compile/internal/types2: add special case report for generic map key type
Port of go/types CL https://golang.org/cl/247258. (The typeparamsB.go2
version of typeparams.go2 doesn't exist yet for types2.)

Updates #40551.

Change-Id: If2b329372bd4d160b4def8b66cc87f25ed4823fd
Reviewed-on: https://go-review.googlesource.com/c/go/+/248057
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-12 00:03:09 +00:00
tdakkota
cb2cbbcda2 [dev.go2go] go/types: fix instantiation crash for generic type parame…
…ters

Fixes #40038.

Change-Id: I5b095d01fd1e3703561c179c34ddc3b43d7510f6
GitHub-Last-Rev: 3e5067a780
GitHub-Pull-Request: golang/go#40644
Reviewed-on: https://go-review.googlesource.com/c/go/+/247498
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-11 16:59:21 +00:00
tdakkota
6d33075156 [dev.go2go] go/types: add special case report for generic map key type
Fixes #40551.

Change-Id: Ifc10dbdcdbee6af5bdbfc36ec78e1a4361672acc
GitHub-Last-Rev: 8d373dee63
GitHub-Pull-Request: golang/go#40628
Reviewed-on: https://go-review.googlesource.com/c/go/+/247258
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-11 16:58:03 +00:00
Robert Griesemer
ead7e9b351 [dev.go2go] cmd/compile/internal/syntax: add more parser tests
Updated existing tests to more closely match the go/types
tests; added *B.go2 versions for some tests, using [] for
type parameters.

Change-Id: Ie7cfd9f5515f541d9422a2b2ab8a5d3e02d0499a
Reviewed-on: https://go-review.googlesource.com/c/go/+/246261
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-01 05:14:38 +00:00
Robert Griesemer
d8b0f3b91f [dev.go2go] go/parser: p.T(P) is a valid instantiated parameter type (fix bug)
The existing code didn't accept an instantiated imported (qualified) type
as type for a regular function parameter.

Also: Simplified logic around use of typeContext flag when []'s
      are used for type parameters.

Change-Id: Ic6c60e943344a976f5b8546c8a378ebd32a82d90
Reviewed-on: https://go-review.googlesource.com/c/go/+/246260
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-01 01:12:24 +00:00
Robert Griesemer
417abfbaf1 [dev.go2go] cmd/compile/internal/syntax: accept [] for type parameter lists
Still missing:
- embedded []-instantiated types in interfaces
- *B.go2 tests which exist for go/types

Change-Id: I3dd115fcd67f725144062c90550a91fcded1cbe2
Reviewed-on: https://go-review.googlesource.com/c/go/+/246259
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-01 01:12:23 +00:00
Robert Griesemer
c77c3236b1 [dev.go2go] cmd/compile/internal/types2: remove most token.Token dependencies
The remaining uses of token.Token are needed for the go/constant API.

Change-Id: I5dc8be1fae16217433da1acb5606fd1d7b8eea54
Reviewed-on: https://go-review.googlesource.com/c/go/+/246257
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-08-01 01:12:22 +00:00
Robert Griesemer
569c893c93 [dev.go2go] types2: update to include the latest go/types changes
This brings types2 (the syntax-based type-checker) up-to-date
with the latest version of the prototype go/types version. It
does not yet include the *B.go2 tests (using square brackets)
or the relevant syntax parser changes.

Tests that check error positions continue to be disabled since
the synax parser records slightly different positions than the
go/parser (to be fixed).

Manually verified that selected *.go2 tests which don't report
errors pass. Type-checks the std library without errors.

Change-Id: If859b180bba8362db86c211eeb4dc2d46255df36
Reviewed-on: https://go-review.googlesource.com/c/go/+/246137
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-31 06:05:23 +00:00
Robert Griesemer
deb678cebf [dev.go2go] go/types: add testcase for crash 9 of #39634
This test passes type-checking without problems but the
generated code causes a cmd/compile error (filed #40486).

Updates #39634.

Change-Id: If3dd28605f6d8792c6bd5bb032624e9a6140b2c0
Reviewed-on: https://go-review.googlesource.com/c/go/+/245742
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-30 04:50:09 +00:00
Robert Griesemer
15144bdc72 [dev.go2go] go/types: fix isParameterized predicate
When checking if a type is parameterized, we only care about
type parameters bound to the specific type, not "free" type
parameters. The old code simply looked for "any" type parameter.

Change-Id: I6a3fe5ac7e3150c5796d4b7576682ab3d4b8558f
Reviewed-on: https://go-review.googlesource.com/c/go/+/245741
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-30 04:50:01 +00:00
Robert Griesemer
88496095d2 [dev.go2go] go/types: remove incorrect assert and replace with explanatory comment
Addresses crash 26 of #39634.
Also, added test case for crash 25 which was fixed with
https://golang.org/cl/245739.

Updates #39634.

Change-Id: I19793eb79fce63052ba055cde0b1dafdd9476895
Reviewed-on: https://go-review.googlesource.com/c/go/+/245740
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-30 04:00:56 +00:00
Robert Griesemer
f0e6640956 [dev.go2go] go/types: generic types in selector expressions must be instantiated
Addresses crash 24 of #39634.

Updates #39634.

Change-Id: If44e834834a07719e7f727d12cc24ac4af0997e6
Reviewed-on: https://go-review.googlesource.com/c/go/+/245739
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-30 00:57:09 +00:00
Robert Griesemer
0db4da527f [dev.go2go] go/types: don't crash in assignment due to prior errors
Addresses crash #12 of 39634.

Updates #39634.

Change-Id: Ie67545d21b6a1e80fcdec1b2eb101b69c25e2952
Reviewed-on: https://go-review.googlesource.com/c/go/+/245738
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-30 00:27:38 +00:00
Robert Griesemer
d118bf7ce9 [dev.go2go] go/types: don't crash in lookup of incomplete interface
Also, update some comments.

Updates #39634.

Change-Id: I85c63e4b941e2bc04e8b5a59497fc47e5d578b8b
Reviewed-on: https://go-review.googlesource.com/c/go/+/245737
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-30 00:10:38 +00:00
Robert Griesemer
df58427917 [dev.go2go] go/types: remove need to enumerate test files, clean up test handling
- Reorganize testdata directory to either contain single-file packages
or (one level of) sub-directories containing multi-file packages.

- Add TestTestdata that runs all the tests in testdata.

- Change TestCheck to only test files explicitly provided via -files.

Providing -v when running these tests now enumerates the packages.
For TestCheck it also prints the type-checking trace.

Change-Id: I66536881789234af030a0a2c9fc096822f593782
Reviewed-on: https://go-review.googlesource.com/c/go/+/244629
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-24 22:57:29 +00:00
Robert Griesemer
131fbfb416 [dev.go2go] go/types: remove need to enumerate examples and fixedbugs test files
Just traverse the respective directories.

Change-Id: I21432e23550d8331e61d3392e8488c81183ab6f0
Reviewed-on: https://go-review.googlesource.com/c/go/+/244628
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-24 20:13:27 +00:00
Robert Griesemer
edac449852 [dev.go2go] go/types: clean up test support code and remove global variables
Change-Id: I152d2f4ca95f8217502d796ac49a8c96e5aba60b
Reviewed-on: https://go-review.googlesource.com/c/go/+/244627
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-24 19:40:13 +00:00
Robert Griesemer
d0e6f20899 [dev.go2go] go/parser: make "type" optional in generic type declarations
Experiment: Make "type" keyword optional in generic type declarations when
it is clear that we can't have an array type declaration. This is the case
when we have one the following:

- more than one type parameter
- a type parameter with a constraint
- a trailing comma in the type parameter list

Change-Id: If6c473ba93b993a7c15ff2f7e7302709cc985f9e
Reviewed-on: https://go-review.googlesource.com/c/go/+/244623
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-24 18:10:25 +00:00
Robert Griesemer
fad691cf11 [dev.go2go] go/types: don't crash with unsafe.Alignof/Sizeof on a type parameter value
Report an error instead for now until we have a better idea.
(It's unclear what these operations should do as they are
defined to return a compile-time constant which we can't
know in general.)

Fixes #40301.

Change-Id: I22a991311de117bc00d52b67b4ce862ea09d855a
Reviewed-on: https://go-review.googlesource.com/c/go/+/244622
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-24 00:25:37 +00:00
Ian Lance Taylor
64148d34c7 [dev.go2go] go/go2go: don't import renamed package twice
We keep an import spec if it uses a local alias. Avoid importing it
again, unless it is required by something else.

Fixes #40318

Change-Id: If90de3bf30412645c9144083372e6b07df3c6a0b
Reviewed-on: https://go-review.googlesource.com/c/go/+/244621
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-23 23:17:54 +00:00
Robert Griesemer
0030e13efb [dev.go2go] go/types: add a couple more interesting type inference examples
Change-Id: I28b31e013ae28a71adefb07cce0f47b505b57676
Reviewed-on: https://go-review.googlesource.com/c/go/+/244620
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-23 21:52:06 +00:00
Robert Griesemer
de8501c203 [dev.go2go] go/parser: change value of UseBrackets constant (fix API check)
Passes all.bash again.

Change-Id: Ie558957b380cef937761faea69458980407bc8db
Reviewed-on: https://go-review.googlesource.com/c/go/+/244619
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-23 21:19:31 +00:00
Robert Griesemer
c7314f27b3 [dev.go2go] go/*: remove the need for ast.InstantiatedType
Instead, add the field "Brackets" to ast.CallExpr to identify
the bracket used for the (type) parameters. Adjust dependencies.

Change-Id: I6a73b0517ac518d8055e7fadbfb8662dfff585c1
Reviewed-on: https://go-review.googlesource.com/c/go/+/244618
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-23 21:19:13 +00:00
Robert Griesemer
bed4b05106 [dev.go2go] go/types: implement constraint type inference for functions
1) Implement full bidirectional unification for general use.
2) Implement constraint type inference using bidirectional unification.
3) Add flag Config.InferFromConstraints to enable constraint type
   inference (disabled by default).

If we don't have all type arguments (provided or inferred) for a
function call, constraint type inference attempts to infer them
from type parameter constraints that are "structural", i.e., whose
interfaces contain exactly one (non-interface) type in their type
lists. For instance, given

	[type P interface{}, Q interface{type []P}]

the constraint for Q requires that the (underlying) structure of
the type argument for Q must match the underlying type of the type
argument provided for P. If only a type argument for P is given, say
say int, we can infer a type argument for Q, which would be []int.

Change-Id: I8508412ad96a0969d2033e99510c56db0f78177e
Reviewed-on: https://go-review.googlesource.com/c/go/+/244061
Run-TryBot: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-23 06:04:12 +00:00
Robert Griesemer
1576a3d981 [dev.go2go] go/parser: recognize f[a, b] as a (potential) function expression (parser bug)
Change-Id: I6b631a0d7efedfedd6c67640c8cbbff81f9e3af8
Reviewed-on: https://go-review.googlesource.com/c/go/+/244457
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-22 23:57:39 +00:00
Rebecca Stambler
f41e3f6173 [dev.go2go] go/ast: add *ast.InstantiatedType case to go/ast.Walk
This is necessary for continued support for the prototype in gopls.

Fixes golang/go#40316

Change-Id: Iafab2e78cfdfd7415d2e2419b8ed1abe6e6216c5
Reviewed-on: https://go-review.googlesource.com/c/go/+/243717
Reviewed-by: Robert Griesemer <gri@golang.org>
Run-TryBot: Rebecca Stambler <rstambler@golang.org>
2020-07-20 22:53:49 +00:00
Ian Lance Taylor
893c5ec17b [dev.go2go] cmd/go2go: rewrite tests to use square bracket syntax
We can roll back this CL if we go back to parentheses.

Change-Id: Ide85330f4c362dad6ae964c6cc1fd0fc6c8a6a60
Reviewed-on: https://go-review.googlesource.com/c/go/+/243162
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-16 21:30:46 +00:00
Ian Lance Taylor
486b592393 [dev.go2go] cmd/go2go: add -brackets option
Change-Id: I5c3d36df3d84ad85d2fb70152f5692223cf6cfb6
Reviewed-on: https://go-review.googlesource.com/c/go/+/243161
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-16 21:28:54 +00:00
Ian Lance Taylor
78c55f923e [dev.go2go] go/go2go: permit caller to require square brackets
Change-Id: Idcb18ea31edee61931aa253f5f4d95923f6bcf6c
Reviewed-on: https://go-review.googlesource.com/c/go/+/243160
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-16 21:24:39 +00:00
Ian Lance Taylor
ca218546b8 [dev.go2go] test: rewrite generic tests to square bracket syntax
We can roll back this CL if we go back to parentheses.

Change-Id: Ideb7dbe8e3c4499d76518a5c9b6f7931a7c103a4
Reviewed-on: https://go-review.googlesource.com/c/go/+/243158
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-16 20:18:10 +00:00
Ian Lance Taylor
6f583c9a5a [dev.go2go] go/go2go: support square bracket generics syntax
Change-Id: If683ad350aaddebcb3ebb691e1235c24c5dc2fe9
Reviewed-on: https://go-review.googlesource.com/c/go/+/243157
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-16 20:16:37 +00:00
Robert Griesemer
e8f7e323f3 [dev.go2go] go/parser: UseBrackets mode forces parser to use [] for generics
Not setting the UseBracket mode still permits the parser to switch
to using brackets depending on the first generic type or function
declaration.

Change-Id: I2ee1235cfe58108ce1f5fd4a7fa1ce81f9e0ec0a
Reviewed-on: https://go-review.googlesource.com/c/go/+/242904
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-16 20:02:53 +00:00
Robert Griesemer
a1922594db [dev.go2go] go/parser, go/types: allow both type and func decls to select [] for type params
The first generic type or function declaration encountered in a file chosing
square brackets switches the parser to use square brackets for the remainder of
the file.

Removed the need for extra type declarations in tests solely to switch to [].

Change-Id: Ia8d0c16e69b7e9b0e5397fed7405c5c4afc66451
Reviewed-on: https://go-review.googlesource.com/c/go/+/242899
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-16 00:33:55 +00:00
Robert Griesemer
ee1823718a [dev.go2go] go/parser: optional "type" keyword for generic functions using [] (experiment)
Change-Id: Ib7ebcd97f970e3be09626ee3d58d110e531aecd8
Reviewed-on: https://go-review.googlesource.com/c/go/+/242897
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-15 23:08:25 +00:00
Robert Griesemer
42aea19e55 [dev.go2go] go/printer: initial support for []-enclosed type parameters
Also: Don't strip parentheses around unnamed generic parameter
types when () are used for type instantiations (was bug).

Change-Id: I74edde2be2a01d740d2275e5d8768a5c25fa3302
Reviewed-on: https://go-review.googlesource.com/c/go/+/242717
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-15 05:33:40 +00:00
Robert Griesemer
7e7a795836 [dev.go2go] go/types: adjustments to accept [] or () for type parameters
For each testfile xxx.go2, added a corresponding file xxxB.go2
that is using [] instead of () for type parameters. Removed
extra ()'s that are not needed to disambiguate.

See also https://groups.google.com/g/golang-nuts/c/7t-Q2vt60J8

Change-Id: I3d64035b1ca2a22ae50c740ebf4ab8a8f6cab787
Reviewed-on: https://go-review.googlesource.com/c/go/+/242521
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-15 00:53:18 +00:00
Robert Griesemer
5bf3aa1e25 [dev.go2go] go/parser, go/ast: accept [] or () for type parameters
- The first type declaration using [] for type parameters
  switches the parser to using [] for type parameters and
  type instantiations. Otherwise it uses ().

- Type parameters are now always accepted with any function
  or method declaration. It is up to the consumer of the AST
  to reject them as necessary.

- Type parameters are now never accepted in the receiver
  or result parameter list.

- testdata/xxxB.go2 tests correspond to the testdata/xxx.go2
  tests but use [] instead of ().

- See also https://groups.google.com/g/golang-nuts/c/7t-Q2vt60J8

Change-Id: I21b14f9463f7f49deba83b64450a0723b4b1d171
Reviewed-on: https://go-review.googlesource.com/c/go/+/242520
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-15 00:52:51 +00:00
Robert Griesemer
9fe9a324c4 [dev.go2go] go/*: remove vestiges of contracts - they are not coming back
Change-Id: If929860b51b86206d874b49ac00aaa8df09726e5
Reviewed-on: https://go-review.googlesource.com/c/go/+/241657
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-09 00:23:26 +00:00
Ian Lance Taylor
9d9619adc8 [dev.go2go] go/go2go: pass full path when importing Go 1 package
No test case because there is still no test harness for a complex
package heirarchy.

Fixes #40063

Change-Id: Iebe627dd7b2a3e967d437bee61c9d15c7a159fc6
Reviewed-on: https://go-review.googlesource.com/c/go/+/241217
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-07 03:47:15 +00:00
Robert Griesemer
4545287c1b [dev.go2go] go/types: don't panic if receiver type arguments cannot be inferred
This can happen due to earlier errors. This change avoids the panic
but reports a follow-up error. Not ideal, but good enough for now.

Fixes #40056.

Change-Id: I500d4fc2b058cdc70f28883ff8d004df4b43fe4e
Reviewed-on: https://go-review.googlesource.com/c/go/+/241130
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-07 03:13:21 +00:00
Robert Griesemer
17564d8957 [dev.go2go] go/types: do not permit generic types in type switch type lists
Fixes #40057.

Change-Id: Ia1a99378614fda1d0cb3d6b9cf53bbf790fc2953
Reviewed-on: https://go-review.googlesource.com/c/go/+/241126
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-07 00:22:28 +00:00
Ian Lance Taylor
cfb6cac804 [dev.go2go] go/go2go: handle embedded pointers to instantiated types
Change-Id: I47d23dd4a44c644e9ec2f1abbc3cd8cec4a35d04
Reviewed-on: https://go-review.googlesource.com/c/go/+/241125
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-06 23:38:47 +00:00
Ian Lance Taylor
b97f992a7e [dev.go2go] go/go2go: F(type)() is not a parameterized function
Fixes #40015

Change-Id: I4e70398e693a53268d3400e829a179c76ff70e75
Reviewed-on: https://go-review.googlesource.com/c/go/+/241124
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-06 23:18:11 +00:00
Robert Griesemer
c583a5d512 [dev.go2go] go/types: add test for crash 15 from issue 39634
This test case doesn't crash anymore.

Updates #39634.

Change-Id: I29b13762265ef1c16c0298d141fdb6cf2c01f4ee
Reviewed-on: https://go-review.googlesource.com/c/go/+/241123
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-06 22:08:08 +00:00
Robert Griesemer
a599706090 [dev.go2go] go/types: don't crash instantiating defined types that are not fully set up
Addresses crash #16 of #39634.

Updates #39634.

Change-Id: I33063d6e2176586f097d2d1391f490f1775a2202
Reviewed-on: https://go-review.googlesource.com/c/go/+/241122
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-06 22:00:41 +00:00
Robert Griesemer
005397e36d [dev.go2go] go/types: don't crash instantiating arrays/slices that are not fully set up
Addresses crash #18 of #39634.

Updates #39634.

Change-Id: I4b1a3d81ce9dc2b59ae9af3146d26f79d8c05973
Reviewed-on: https://go-review.googlesource.com/c/go/+/240904
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-06 21:54:48 +00:00
Pavlo Bashynskyi
0e1fc80d04 [dev.go2go] cmd/go2go: correct URL in README
Change-Id: I947c0181512b7d5dd4219cec92262bd1f443b957
GitHub-Last-Rev: 44ec636b89
GitHub-Pull-Request: golang/go#40054
Reviewed-on: https://go-review.googlesource.com/c/go/+/241039
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-05 19:48:30 +00:00
Robert Griesemer
34f76220c3 [dev.go2go] go/types: make sure arrays, slices always have an element type
Addresses crash #19 of #39634.

Updates #39634.

Change-Id: I42208511a3fc27432891243dcf4799e80432c2c1
Reviewed-on: https://go-review.googlesource.com/c/go/+/240903
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-04 04:55:49 +00:00
Robert Griesemer
6e86f51c54 [dev.go2go] go/types: don't rely on completed interfaces in isParameterized predicate
Also, take type lists into account when computing predicate.
Addresses crash #27 of #39634.

Updates #39634.

Change-Id: Id6e1d0d86ac1cb9d79828a3b5fdfbeba0e6aace0
Reviewed-on: https://go-review.googlesource.com/c/go/+/240902
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-03 22:37:04 +00:00
Robert Griesemer
167909e5f5 [dev.go2go] go/types: don't modify Named.underlying when checking validity
Addresses crash #20 of #39634.
Added test, also for some of the other cases that don't crash
anymore.

Updates #39634.

Change-Id: I999e376985a443ac435f64a7c249f891e7b7a6d7
Reviewed-on: https://go-review.googlesource.com/c/go/+/240901
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-03 22:20:59 +00:00
Ian Lance Taylor
4dde96e380 [dev.go2go] go/go2go: resolve pointers in sameType
Fixes #39982

Change-Id: Ieb33381716662b44464104e0073a52ab5c19b7c6
Reviewed-on: https://go-review.googlesource.com/c/go/+/240899
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-07-03 19:26:32 +00:00
Robert Griesemer
85ed317eb2 [dev.go2go] go/types: fix computation of type hash
Fixes #39982.

Change-Id: I4e7b52c34bf8df63f2063dc2504a8125ca7585a0
Reviewed-on: https://go-review.googlesource.com/c/go/+/240737
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-02 00:33:43 +00:00
Robert Griesemer
182889ccf5 [dev.go2go] go/types: better error message when converting to a constraint interface
Fixes #39699.

Change-Id: Ib2a756a275c0f96201800d947a72db49d3319a3e
Reviewed-on: https://go-review.googlesource.com/c/go/+/240720
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-01 22:50:35 +00:00
Robert Griesemer
05f750de93 [dev.go2go] go/types: HasTypeList, IsComparable, IsConstraint predicates for interfaces
HasTypeList existed before but now is also written such that it doesn't
expect an interface to be complete.

Change-Id: I43e8d652c6be755473b201a64bf41d363214881c
Reviewed-on: https://go-review.googlesource.com/c/go/+/240719
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-01 22:50:26 +00:00
Robert Griesemer
d014fca6d4 [dev.go2go] go/types: fix assertion failure, better error message for inference failure
Fixes #39976.

Change-Id: Idc304a615193847337438e7024e43140472e7bae
Reviewed-on: https://go-review.googlesource.com/c/go/+/240718
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-01 20:30:10 +00:00
Robert Griesemer
6cf6bf162c [dev.go2go] go/types: report inferred type when a type argument doesn't match
Fixes #39725.

Change-Id: I48248283ae0eb635d489d8661512f32b98700c1a
Reviewed-on: https://go-review.googlesource.com/c/go/+/240523
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-07-01 00:31:32 +00:00
Ian Lance Taylor
938e96e732 [dev.go2go] go/go2go: instantiate embedded field when needed
If an embedded field is an instantiated type, we need to instantiate
it when instantiating the whole type, in case the type arguments
themselves need instantiation.

Fixes #39953

Change-Id: I80b57456aa4f8e8b2eff82359066c37a9c2a40f5
Reviewed-on: https://go-review.googlesource.com/c/go/+/240522
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-30 23:46:04 +00:00
Robert Griesemer
08b9fd164c [dev.go2go] go/types: better error message when confusing a type parameter with an interface
Fixes #39948.

Change-Id: I868d2264a674a92c39fbe31d89bc002dd74c26fe
Reviewed-on: https://go-review.googlesource.com/c/go/+/240520
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-30 19:00:27 +00:00
Robert Griesemer
1e27b76ebd [dev.go2go] go/types: report "inifinite expansion" cycles across instantiated types
Fixes #39938.

Change-Id: I482b211189cefdc098df5acb4f858f6f1635ce60
Reviewed-on: https://go-review.googlesource.com/c/go/+/240519
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-30 17:48:56 +00:00
Robert Griesemer
236ad5a280 [dev.go2go] go/types: fix broken test case
While at it, simplified test case a bit.

Fixes #39935.
Updates #39754.

Change-Id: Ia3b51f23807d25e62113757c51a660c7e3a9b381
Reviewed-on: https://go-review.googlesource.com/c/go/+/240478
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-30 03:51:21 +00:00
tdakkota
71c7be55eb [dev.go2go] go/types: fix type check skipping for constraints when th…
…ere’s more than one generic constraint.

Check of first constraint was breaking the loop, so other constraints was skipped

Fixes #39754.

Change-Id: I48caa380472371a438c2d2029d1383d03dbf22df
GitHub-Last-Rev: bf418db782
GitHub-Pull-Request: golang/go#39902
Reviewed-on: https://go-review.googlesource.com/c/go/+/240339
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-29 16:07:10 +00:00
Ian Lance Taylor
10ea225e28 [dev.go2go] go/go2go: translate types to AST
We were relying on calling typeString and treating that as an AST ident,
with special handling for instantiated types, but that fails if there is
an instantiated type within a type literal.

Fixes #39881

Change-Id: I793fe359868d8d73e830aa8dc67cf52de99355a8
Reviewed-on: https://go-review.googlesource.com/c/go/+/240197
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-26 22:32:53 +00:00
Ian Lance Taylor
93014c51d1 [dev.go2go] go/go2go: avoid crashing on predeclared error type
It has no package, so we need to check for Pkg() == nil.

Fixes #39878

Change-Id: I14a47c5098f97ce42dfa8cc875819f244a2b0201
Reviewed-on: https://go-review.googlesource.com/c/go/+/240013
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-26 18:43:49 +00:00
Ian Lance Taylor
1b08acee45 [dev.go2go] go/go2go: don't add importable name to test file
No test case because we will don't have a general test harness.

Fixes #39851

Change-Id: If7b1262404f390eba80d53c2c1d40724252a5833
Reviewed-on: https://go-review.googlesource.com/c/go/+/240004
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-25 23:22:18 +00:00
Ian Lance Taylor
4dfbf5ab9c [dev.go2go] go/go2go: add package qualifier when needed
Fixes #39842

Change-Id: I5046f1bdd7dbc6d1e17cf3835826933aaadf1581
Reviewed-on: https://go-review.googlesource.com/c/go/+/239711
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-25 02:57:14 +00:00
Ian Lance Taylor
a9f31a8c68 [dev.go2go] cmd/go2go: doc: instantiations can't refer to unexported names
For #39840

Change-Id: Ifc2a95fbd50cbf785251d05042e554872e1e79cc
Reviewed-on: https://go-review.googlesource.com/c/go/+/239709
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-24 23:56:06 +00:00
Ian Lance Taylor
acd7923802 [dev.go2go] go/go2go: add IDs for test files
No test because the test harness doesn't support test packages.
(But probably we'll need a better test harness.)

Fixes #39839

Change-Id: I4532b1443dbdd081552ffb78477cbe5039183416
Reviewed-on: https://go-review.googlesource.com/c/go/+/239708
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-24 23:41:00 +00:00
Ian Lance Taylor
2dce748bd8 [dev.go2go] go/go2go: if we have an import path, pass it to go/types
No test because it doesn't really fit into the current test harness.

FIxes #39797

Change-Id: I410217a0e6b3af6808a111d0edbafaa3047b12f1
Reviewed-on: https://go-review.googlesource.com/c/go/+/239707
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-24 22:35:01 +00:00
Ian Lance Taylor
f04e0ee126 [dev.go2go] go/go2go: include package in instantation of ident
If an instantiated function from a different package uses a plain
identifier to instantiate a generic type or function, include the
package name in the generated identifier.

Fixes #39834

Change-Id: I4c786bac8972475e180cb41178520439343a36ea
Reviewed-on: https://go-review.googlesource.com/c/go/+/239706
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-24 22:15:29 +00:00
Ian Lance Taylor
5b16464101 [dev.go2go] test: keep translated .go2 files if -k
Change-Id: I8f696c201c00d422b176a65ae72e384cc11e1efb
Reviewed-on: https://go-review.googlesource.com/c/go/+/239704
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-24 21:34:54 +00:00
Ian Lance Taylor
af16dac1b0 [dev.go2go] go/go2go: don't import both "./a" and "a"
For #39797

Change-Id: I4063a0138062ce8dc1f35cc7fef7c6773c939362
Reviewed-on: https://go-review.googlesource.com/c/go/+/239703
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-24 21:33:55 +00:00
Ian Lance Taylor
fa201df81e [dev.go2go] go/go2go: update name of embedded pointer to instantiation
Fixes #39774

Change-Id: Icb2948ae19e06a3766e7edb01ef40de50e7aca7e
Reviewed-on: https://go-review.googlesource.com/c/go/+/239702
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-24 21:01:03 +00:00
DeedleFake
2dc2987ac8 cmd/go2go: standardize help flag with other tools
A very small change because the `--help` flag printing nothing was bugging me.

Change-Id: I221c657ba055e94db7a574c8e8fd044bb135f8b1
GitHub-Last-Rev: 8781a1a29f
GitHub-Pull-Request: golang/go#39788
Reviewed-on: https://go-review.googlesource.com/c/go/+/239537
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-23 23:41:16 +00:00
Ian Lance Taylor
e6e8041d02 [dev.go2go] go/go2go: resolve type alias of parameterized type
Fixes #39792

Change-Id: I9eab19a4f516be5a71e71f04b91c4e46b189fba9
Reviewed-on: https://go-review.googlesource.com/c/go/+/239598
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-23 23:35:25 +00:00
Robert Griesemer
2faeebf4e5 [dev.go2go] go/types: permit alias to generic type
Fixes #39768.

Change-Id: I68c8fbec5adc50e448dabe90b212ef147a384a06
Reviewed-on: https://go-review.googlesource.com/c/go/+/239387
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-23 04:54:48 +00:00
Robert Griesemer
6ca930a00a [dev.go2go] go/types: add internal TODO for future simplification
Change-Id: I8e4e8eebf8c64962ccf5f0e225dd007f691c373a
Reviewed-on: https://go-review.googlesource.com/c/go/+/239384
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-22 23:46:33 +00:00
Ian Lance Taylor
dfb538cec8 [dev.go2go] go/go2go: don't permit underscore as type argument
The go/types package doesn't give us an easy way to get the type,
so just reject it.

Fixes #39743

Change-Id: I5404c10baede0fd2cf67980b06fbebd214a50dff
Reviewed-on: https://go-review.googlesource.com/c/go/+/239382
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-22 23:30:28 +00:00
Ian Lance Taylor
404a12f056 [dev.go2go] go/go2go: use package name, not package path
types.TypeString defaults to using the package path for references to names.
Provide our own types.Qualifier that uses just the package name,
since that is what the translated code has to use.

Fixes #39744

Change-Id: Icde289b2ed0fdd9b0a9aae6aae4557a8951d25a4
Reviewed-on: https://go-review.googlesource.com/c/go/+/239381
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-22 23:05:26 +00:00
Ian Lance Taylor
a367b7d270 [dev.go2go] go/go2go: check for instantiation with locally defined type
Fixes #39738

Change-Id: I1a3536484a982ec713019572ff7b3c0c36af9784
Reviewed-on: https://go-review.googlesource.com/c/go/+/239380
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-22 22:19:20 +00:00
Ian Lance Taylor
9b13ca00f8 [dev.go2go] go/go2go: ignore struct tags
Ignore struct tags when generating an instantiated names, and when
comparing types for identity.

Fixes #39737

Change-Id: I53e67fa1d09214dafc4088a59eb00e1a6f18ef3d
Reviewed-on: https://go-review.googlesource.com/c/go/+/239379
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-22 22:07:26 +00:00
Robert Griesemer
da7932368b [dev.go2go] go/types: implement a few more predicates for type list sums
Also: Don't convert an untyped nil to a type parameter when
checking if an untyped value (nil) can be coverted to a target
type.

Fixes #39755.

Change-Id: Ib2645759dc659b9c80c2d0a457180eb9616c7cb9
Reviewed-on: https://go-review.googlesource.com/c/go/+/239338
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-22 19:06:44 +00:00
Ian Lance Taylor
e643c9792f [dev.go2go] go/go2go: avoid multiple identical instantiations
Move tracking of instantiations from translator to Importer,
so that we can track all instantiations within a package
to avoid duplicates.

Fixes #39749

Change-Id: If6cd5bcdc6e19c2d6481e62a6187ddf7f4fac72a
Reviewed-on: https://go-review.googlesource.com/c/go/+/239337
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-22 18:38:41 +00:00
Ian Lance Taylor
6500ed4790 [dev.go2go] go/go2go: instantiate local type specs
Fixes #39741

Change-Id: I75e3b98afa5184b87d4a7bbf360761e5cc6c6217
Reviewed-on: https://go-review.googlesource.com/c/go/+/239297
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-22 17:38:38 +00:00
Robert Griesemer
0a030888da [dev.go2go] go/types: use the underlying type of type list entries
Type lists can contain defined types, make sure we use their
underlying types when computing operational types.

Change-Id: I8b6b11302f6b28977916e495f1486cc7b352e859
Reviewed-on: https://go-review.googlesource.com/c/go/+/239163
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-20 04:46:40 +00:00
Robert Griesemer
c0c872e8b0 [dev.go2go] go/types: the underlying type of a type parameter is itself
No need to call Under() when we know that we have a type parameter.

While at it: Turn off debug mode.

Change-Id: Ia0b39d88191c8e5ac580e7e84a512061911c40cf
Reviewed-on: https://go-review.googlesource.com/c/go/+/239162
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-20 03:57:21 +00:00
Robert Griesemer
cbdb93d5a7 [dev.go2go] go/types: a type constraint must be an interface
In particular, it cannot be a type parameter
with an operational type that is an interface.

Fixes #39723.

Change-Id: Ia6b65eaecd472dd71b1c9f7631ce1872f06e5a6d
Reviewed-on: https://go-review.googlesource.com/c/go/+/239161
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-20 03:49:15 +00:00
Ian Lance Taylor
815b29d859 [dev.go2go] go/go2go: get package name from package, not import path
No test because the test framework doesn't easily support
package paths containing a dot.

Fixes #39722

Change-Id: If43dc768b28f521d10bd2ef4288aa789aa4bee01
Reviewed-on: https://go-review.googlesource.com/c/go/+/239160
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-20 00:45:10 +00:00
Robert Griesemer
7473c4383e [dev.go2go] go/types: check for duplicate types after interfaces were completed
Fixes #39711.

Change-Id: Id0efb854a42bd88a66be8165fa3444e33d1c8f8d
Reviewed-on: https://go-review.googlesource.com/c/go/+/239158
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-20 00:41:07 +00:00
Ian Lance Taylor
ccaf3f5560 [dev.go2go] go/go2go: don't crash on an unnamed receiver
Fixes #39707

Change-Id: I20e5fe2990ceda5429f1a22edf48494d2c6496a2
Reviewed-on: https://go-review.googlesource.com/c/go/+/239159
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-20 00:36:20 +00:00
Ian Lance Taylor
cab5f803e8 [dev.go2go] go/go2go: don't drop type arguments in instantiateType
It's not correct to do it here, as we aren't instantiating this
particular type.

Also had a loop check to avoid endless instantiating a recursive type.

Fixes #39688

Change-Id: Ief4c57bb5cea3013501e33ab5bc82a29707af5be
Reviewed-on: https://go-review.googlesource.com/c/go/+/239137
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-20 00:01:12 +00:00
Robert Griesemer
6cf535a27b [dev.go2go] go/types: avoid endless recursion when computing operational types
The operational type for a type parameter T constrained by
interface { type T } is the top type, not itself. The latter
can lead to infinite recursions.

Fix suggested by @tdakkota.

Fixes #39680.

Change-Id: I8a6a6c503f09294b9276965f1d9e05c5d22ec912
Reviewed-on: https://go-review.googlesource.com/c/go/+/238863
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-19 04:37:09 +00:00
Robert Griesemer
b302b5f775 [dev.go2go] go/types: don't panic if an embedded type is not an interface
Fixes #39693.

Change-Id: I7f2a4dd95edac3365a9b41b66afcd0015b5b836c
Reviewed-on: https://go-review.googlesource.com/c/go/+/238858
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-19 00:09:12 +00:00
Ian Lance Taylor
657803033f [dev.go2go] go/go2go: handle fields promoted through embedded type parameter
Fixes #39678

Change-Id: Ib74d15795ab85ad0b1e58096302a9a88810242c5
Reviewed-on: https://go-review.googlesource.com/c/go/+/238857
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-18 23:28:46 +00:00
Ian Lance Taylor
20dbf4d49d [dev.go2go] go/go2go: add imports for packages referenced by inferred types
Fixes #39625

Change-Id: Iebae2afbb42092e14c91c52d2046bc287d423844
Reviewed-on: https://go-review.googlesource.com/c/go/+/238817
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-18 22:00:57 +00:00
Ian Lance Taylor
4af4810e15 [dev.go2go] go/go2go: add type arguments to type instantiation
Previously we instantiated the underlying type, so we didn't need this.
We stopped doing that to get the same type in the generated code,
but now we need to get the right type arguments, rather than just
leaving the type parameters there.

Fixes #39692

Change-Id: I56ba8ff017c37219e7cb9bb6e07a4beb8c50e9dc
Reviewed-on: https://go-review.googlesource.com/c/go/+/238797
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-18 21:36:57 +00:00
Ian Lance Taylor
7a16d6c119 [dev.go2go] go/go2go: don't crash on functions/methods with no body
Fixes #39672

Change-Id: Ia9fa4e7d5090200d7c2b4f654ac7ee42d7d79732
Reviewed-on: https://go-review.googlesource.com/c/go/+/238761
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-18 20:51:39 +00:00
Robert Griesemer
5e754162cd [dev.go2go] go/types: fix unification issue when looking up generic methods
If enabled in types.Config, the type checker can handle generic
methods (methods that have their own type parameter list).
This CL fixes an issue with method lookup (missing method test)
that caused some assignments to fail.

Note that this does not affect the go2go tool - we don't have any
plans to support such generic methods. Type-checking them is
fairly straight-forward. Translating them into code is not.

Change-Id: I8b8a6b814417277c728732bd5a9421c99440a47a
Reviewed-on: https://go-review.googlesource.com/c/go/+/238627
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-18 05:58:40 +00:00
Robert Griesemer
2c4c09e4ff [dev.go2go] go/types: don't crash when receiver type doesn't declare type parameters
Fixes #39664.

Change-Id: I0cf585f0c704bdaa163a7ebc9e7c82a734fcd5e9
Reviewed-on: https://go-review.googlesource.com/c/go/+/238625
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-18 00:39:33 +00:00
Ian Lance Taylor
57cec2f259 [dev.go2go] go/go2go: accept slash in an instantiated type name
It shows up when instantiating with types with a package path
containing a slash, as in net/url.Error.

Fixes #39642

Change-Id: Icf40e7bcdf1de7c84f58ebde35ebffadbb071d72
Reviewed-on: https://go-review.googlesource.com/c/go/+/238623
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 23:45:00 +00:00
Ian Lance Taylor
e531e11b9a [dev.go2go] go/go2go: return quickly from typeWithoutArgs if no args
Avoids crashing when we see a universe scope type in an instantiated type.

Change-Id: Iec3ebee291973180a63cd4cddef7e2f131a30053
Reviewed-on: https://go-review.googlesource.com/c/go/+/238622
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 23:34:10 +00:00
Ian Lance Taylor
9840dbbef8 [dev.go2go] go/go2go: instantiate embedded type parameters
Turn an embedded type parameter into a regular field with the type
parameter as the name and the type argument as the type.

Fixes #39671

Change-Id: I0050499b90feb5085cac4452d53fa0dc6f614c48
Reviewed-on: https://go-review.googlesource.com/c/go/+/238621
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 23:21:31 +00:00
Ahmed W
3f40f78cab README.go2go: add a note about GO2PATH
Adds a little note about `GO2PATH` and that it is required for the `go2go` tool.

Updates #39617

Change-Id: I9e3cea16a7d7539555180dc065957d6a56f390b9
GitHub-Last-Rev: 2aa6815df7
GitHub-Pull-Request: golang/go#39657
Reviewed-on: https://go-review.googlesource.com/c/go/+/238498
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 22:48:43 +00:00
Ian Lance Taylor
4287a49936 [dev.go2go] cmd/go2go: document that function-local parameterized types don't work
For #39643

Change-Id: Ic3d3e4a4bd46c62705d3ce3473e3e06e1380d834
Reviewed-on: https://go-review.googlesource.com/c/go/+/238620
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 22:05:55 +00:00
Ian Lance Taylor
143b944192 [dev.go2go] go/go2go: error, not panic, for local parameterized type
Fixes #39643

Change-Id: I45aaaf8818d4d383d1514891b5cc9bc68926ad97
Reviewed-on: https://go-review.googlesource.com/c/go/+/238619
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 22:03:14 +00:00
Ian Lance Taylor
e0d5d9f770 [dev.go2go] go/go2go: make uses of typeInstantiations consistent
Fixes #39653

Change-Id: I98fd1bd4f0deccb5b4c2ed0d67d508c7f0117839
Reviewed-on: https://go-review.googlesource.com/c/go/+/238618
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 21:53:37 +00:00
Ian Lance Taylor
3a25e98917 [dev.go2go] go/go2go: parenthesize type strings
Fixes #39662

Change-Id: Id176ec00474d66a24e95f2db092f3b4245a93cfb
Reviewed-on: https://go-review.googlesource.com/c/go/+/238557
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 19:42:47 +00:00
Ian Lance Taylor
5f01333bf1 [dev.go2go] go/go2go: check for embedded interface with type list
Add an accessor to go/types: HasTypeList for an interface type.

Fixes #39626

Change-Id: I880eabbe6660739cd7febc1df89eaa7f9262c8c8
Reviewed-on: https://go-review.googlesource.com/c/go/+/238360
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 04:20:54 +00:00
Robert Griesemer
0b89d8b52a [dev.go2go] go/types: use correct predicate when checking binary addition
See also https://team-review.git.corp.google.com/c/golang/go2-dev/+/759562
for the analogous problem for another predicate.

Fixes #39623.

Change-Id: I39efcb07c337691eb202de166e2cb8d6b5d5ee18
Reviewed-on: https://go-review.googlesource.com/c/go/+/238359
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-17 03:59:45 +00:00
Ian Lance Taylor
1bcef8724f [dev.go2go] go/go2go: catch more embedded comparable cases
Check for comparable embedded via a different embedded interface.
Check for comparable embedded in a defined interface type.

Change-Id: I8c9c576ad31443dcb77b4be71e29ab2284339cb9
Reviewed-on: https://go-review.googlesource.com/c/go/+/238357
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 03:29:48 +00:00
Robert Griesemer
c2b328710b [dev.go2go] go/types: prevent comparable interface from being used outside constraints
It was already not possible to implement an interface that was or
embedded the predeclared interface "comparable" in ordinary (non-
constraint) use, but trying to do so would lead to confusing errors
(missing method "==").

Simply disallow the use of such interfaces outside constraints,
as we do for interfaces containing type lists.

Change-Id: I15ccf1b77226a50baf16df46192e90144208f9dd
Reviewed-on: https://go-review.googlesource.com/c/go/+/238300
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-17 02:11:25 +00:00
Ian Lance Taylor
4ba19b0188 [dev.go2go] go/go2go: if an interface embeds comparable, treat it as parameterized
Change-Id: If61c88ae115bc14ae306653e78e3241380ab936a
Reviewed-on: https://go-review.googlesource.com/c/go/+/238301
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 00:44:16 +00:00
Ian Lance Taylor
56a37ac5a4 [dev.go2go] go/go2go: make defaultImporter a field of Importer
It turns out that defaultImporter has modifiable fields, so making it a
package scope variable can cause confusion in the use by test/run.go.

Change-Id: I33b060f2ffd17639312e7aa15a632268a3c14ab1
Reviewed-on: https://go-review.googlesource.com/c/go/+/238299
Reviewed-by: Ian Lance Taylor <iant@golang.org>
2020-06-17 00:36:21 +00:00
Robert Griesemer
45038b7bca [dev.go2go] README.go2go.md: fix typo
Change-Id: Iee71ea7af488a717986d2e5994f16fdeaf8f3dda
Reviewed-on: https://go-review.googlesource.com/c/go/+/238297
Reviewed-by: Robert Griesemer <gri@golang.org>
2020-06-16 23:13:12 +00:00
Robert Griesemer
ad307489d4 go/types: always use the underlying type of type list entries for operations
Passes all.bash.

Change-Id: Ie31cba04b7147fb1468f90d26450034223745a57
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/771577
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-16 05:49:35 +00:00
Robert Griesemer
84cbe4f953 go/types: allow any type in a type list
Since we have to recompute the underlying type of each type in a
type list after instantiation (if any), there is no need to restrict
the types in the type list anymore.

Per the adjustment in the design draft.

Change-Id: I51ced90788e06ed4a9dbd34566e3baca7f3afe20
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/771574
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-16 03:41:38 +00:00
Ian Lance Taylor
197db4cd00 go/go2go: use types.RelativeTo rather than doing it by hand
Change-Id: I0891f034ef71311df007bb9aa527132d5b45c672
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/771559
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-15 20:51:13 +00:00
Ian Lance Taylor
feeeea1cda README.go2go: add README for branch
Change-Id: I92d9feb0c382a160afbff2428d92487e2275e09f
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/771427
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-15 20:07:34 +00:00
Robert Griesemer
221a28e338 go/types: always compare against underlying types in type lists
The underlying type of each type list entry must be computed
(again) _after_ the interface was instantiated because its
original typelist may have contained type parameters that were
substituted with defined types.

Passes all.bash.

Change-Id: I65a234fe6b9bc7b36121532410a0ecc29061516e
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/770445
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-14 06:40:04 +00:00
Robert Griesemer
8d612e39fe go/types: fix a couple of trace output problems (when -v is set)
- fix endless recursion when caused by trace output for self-referential generic types
- print pointer designation of type parameters in type parameter lists

Change-Id: I02d985187ee5e42fdaece2e7420824de8c90a906
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/770152
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:54 -07:00
Robert Griesemer
795f776602 go/types: stronger type inference across defined types
If a defined type is passed as an argument for a paramater
of a composite generic but unnamed type (and vice versa),
use the defined type's underlying type for type inference
rather than fail.

Passes all.bash.

Change-Id: I90b33b549c1d0e7569c1520b0f8e45a67152df43
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/770149
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:54 -07:00
Ian Lance Taylor
e7b04c5e2d go/go2go: add check for looping while rewriting
Change-Id: I2dacc606e9aecf8616eff2e9ab9fc09af69b7767
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/769752
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:54 -07:00
Robert Griesemer
bbdb05760f go/types: a type parameter acts like a named type; fix predicate and test
Change-Id: Ibe9f074d516200b9b12c26a270e62defc024eeac
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/769347
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:54 -07:00
Ian Lance Taylor
bc77b007e5 go/go2go: compare arguments of instantiated types
types.Identical will report that two instantiated types are different
even if they are instantiated with the same type arguments.
Change our comparison so that we treat them as the same.

This lets us drop fully resolving all types, which is good because
that wasn't correct anyhow.

Change-Id: Ibcf2dc08896ecacb11ca302627e5d0c6f0722da7
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/769080
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:54 -07:00
Robert Griesemer
cf52fda189 go/types: update README
Change-Id: If0031161b0c651d9196ebb7e565dfb8b8c7e664f
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/768852
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:54 -07:00
Ian Lance Taylor
94ebaa9b4f go/go2go: support instantiating functions with directed channels
Change-Id: I5c7cf605862bc4d34e0eb2b72870c68014d2f58a
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/768851
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:54 -07:00
Ian Lance Taylor
09a02162ee test: add a couple of pointer method test cases
Change-Id: If91c8a61fcda93eeb5affe51ef8f537736a28bce
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/768839
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:54 -07:00
Robert Griesemer
d65e7b7b0f go/types: take pointer designation of type parameters into account
There are still a couple of issues with pointer type parameters
that have constraints containing type lists, but at least as far
as method constraints are concerned the code is now matching the
design.

Passes all.bash.

Change-Id: I7b7ad9e03bc6ed159dca2343d3fa6a04fc188659
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/765805
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:54 -07:00
Ian Lance Taylor
730419578e go/go2go: handle references to embedded instantiated types
Change-Id: I4f54a7820483e6b79169d319301943063a26ac53
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/767868
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:54 -07:00
Ian Lance Taylor
a685620169 test: catch go2go panics in test runner
Change-Id: Ie59118941f732fc9111e77dcf8422d1e1afcd563
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/767865
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:53 -07:00
Ian Lance Taylor
3df5cb5c52 go/go2go: improve handling of self-referential types
Also, resolve types when looking up instantiations.

Change-Id: I8b2e976d9c0d313fe3c1dd9dafce41dcb59b33bf
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/767864
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:53 -07:00
Ian Lance Taylor
73c4e1f380 test: add AbsDifference test case from design draft
Change-Id: I184ca0949200064947a3c974f8aa9c3738d93e33
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/765523
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:53 -07:00
Robert Griesemer
7307dda747 go/types: report error if type list contains duplicate entries
Passes all.bash.

Change-Id: I9a795c931100af662c9c62223d4e4ca0103d2af3
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/765675
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:53 -07:00
Robert Griesemer
61c4506052 go/types: permit at most one type list in an interface (excluding embeddings)
Change-Id: Ib5f658341a746d4ac04852b558864bdb1ae3292f
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/765552
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:53 -07:00
Ian Lance Taylor
44579f1e8e cmd/go2go: lock map in metrics Count methods
Change-Id: I4a5e74a3b13ce5ac29f6fedc6d6a6da1dabcc33b
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/765662
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:53 -07:00
Robert Griesemer
468a8d7345 go/types: remove support for contracts
Also: Some additions/corrections to the NOTES file.

Passes all.bash.

Change-Id: I580c7f6f9769b8108e6d8e5a3473b92362eb246d
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/764658
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:53 -07:00
Robert Griesemer
3ec98e186b go/types: implement intersection for embedded type lists
Implement intersection of (sum) type lists so we can correctly
compute a type bound's type list if a type bound embeds other
type bounds (interfaces).

For type bounds A, B we want to preserve the property

   "A embeds B" implies "A satisfies B"

Because type bounds are interfaces this is already true when
considering method sets only. But type bounds also may contain
type lists, and for this property to be true, type lists must
be intersected.

The intersection of two non-empty type lists with different types
may be the empty list (nil), which means that no type satisfies
the type bound. Because we already use nil to indicate the absence
of a type list (i.e., ignoring methods, any type satisfies the type
bound) we need a separate representation. This CL introduces two
new internal types, bottom and top, which stand for "no type" and
"any type" (they represent the bottom and top of the type lattice).
Since nil is already used for what should be the top type, and we
rely on the fact that the zero value for an Interface type is a
valid empty interface, we keep using nil in type lists to indicate
the top type. Eventually we may want to clean this up.

This CL also refines the understanding of type parameters: The
underlying type of a type parameter must be itself (it cannot be
defined by the associated type bound as assumed in a prior CL).
Consider the declaration

	type T(type P) P

which declares a new defined, generic type. The question is, what
is the underlying type of T, i.e., the type which T represents
with a (new) name? (This type is stored in the underlying field
of a Named type.) The only possible answer is P, because otherwise
instantiation of T with any other type Q wouldn't produce that type
Q.

Thus, when checking if an operation is applicable on a value of type
parameter type, we need to explicitly get the type parameter's
"operational type" which is defined by the type parameter's type
bound; specifically the type bounds's type list (which is represented
as a sum type).

Passes all.bash.

Change-Id: Iad7e99884fd8f40a70f75c6470f1817d74994f48
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/764158
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:53 -07:00
Robert Griesemer
690131b027 go/types: add Config flag to enable method type parameters
The type-checker type-checks method type parameters like
function type parameters without any extra work. But the
current design draft does not permit them and the go2go
translator does not expect them.

Add a flag to enable them for type checker tests, but do
not accept them by default. Instead, type-check but report
an error.

Passes all.bash.

Change-Id: Iec02f4a951a3faccd2409d97d48bc4dd4536a750
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/764012
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:53 -07:00
Robert Griesemer
d3a2e0e245 go/types: disable type assertions on variables of generic type
This matches the latest design draft. It's unclear what the
correct approach is here, and there is an easy work-around:
just assign to an interface variable first.

Passes all.bash.

Change-Id: Ic1d6ed3de6333505e2044a318ea05fb984b408cf
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/764001
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:53 -07:00
Ian Lance Taylor
35eefe6b79 test/gen: add some FromStrings test cases
These are from the latest version of the design draft.

There are still a couple of FromStrings test cases that don't yet work.

Change-Id: I057875820d8250012c06faeabda4637f0585b6f8
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/763941
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:53 -07:00
Ian Lance Taylor
a6b6ca6dc9 cmd/go2go: use consistent spacing in package doc
Change-Id: Ic3b03820ebfb6c4b0881b18663f46b64227ea93d
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/763940
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:53 -07:00
Robert Griesemer
1bc39b26bf go/types: treat type bound type lists as underlying types of type parameters
If a type parameter's type bound contains a type list, we can view that as
the underlying type(s) of the type parameter. If there is no type list the
underlying type of a type parameter is itself.

This approach resolves several open issues and clarifies the relationship
between type bound type lists and the type parameters. It also provides a
sensible definition for the underlying type of a type parameter (it will
take some more experimentation to see if this view is holding up within
the axiomatic framework of generic Go).

To implement this new view, in this CL we introduce the (implementation-
internal) notion of a sum type. A sum type is a set of two or more
distinct types. With this, we can view an interface with a type list as
an interface that provides a _single_ underlying type, which may be a
sum type.

Defining the underlying type of a type parameter this way enables a lot
of so far failing tests to work. In other instances, we have to implement
type-checking for sum types and can ignore the connection with generic code.
This simplifies the implementation and leads to a better separation of
concerns.

As part of this change:

- Several test cases in testdata/todos.go2 now work as expected
  and move to testdata/issues.go2.

- Fix, clarify, and add various comments.

Passes all.bash.

Change-Id: I25a435b2ccd0c9f9fda5369bc998e52fe120ee0b
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/762619
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:53 -07:00
Robert Griesemer
cdabf71580 cmd/compile/internal/types2: disallow interfaces with type constraints as variable types
Port of corresponding go/types change:
https://team-review.git.corp.google.com/c/golang/go2-dev/+/760779

Change-Id: Ibdb9b61bb99f34481e2e466b0d024fb14bf1add0
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/760899
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:53 -07:00
Robert Griesemer
25675854ad go/types: disallow interfaces with type constraints as variable types
Passes all.bash.

Change-Id: I0e080e740f5a70f480859196e34b96d47f914755
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/760779
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:53 -07:00
Robert Griesemer
3650c7d512 cmd/compile/internal/types2: fix numeric conversions between type parameter types
This is a simple port of the corresponding go/types change in
https://team-review.git.corp.google.com/c/golang/go2-dev/+/759562.

Also: Added missing newline at end of go/types/testdata/issues.go2.
Change-Id: I8301488d46fa046c0a1f52b47d889864ee094f87
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/759563
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:53 -07:00
Robert Griesemer
0fa4f81317 go/types: fix numeric conversions between type parameter types
The implementation of conversions T(x) between integers and floating-point
numbers checks that both T and x have either integer or floating-point
type. When the type of T or x is a type parameter, the respective simple
predicate disjunction in the implementation was wrong because if a type list
contains both an integer and a floating-point type, the type parameter is
neither an integer or a floating-point number.

Change-Id: I007aa956007ab1a0228e0ee2fca05804686b404c
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/759562
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Robert Griesemer
716d51681b go/{ast,parser,types}: remove support for "underlying" in type lists again
Match the latest generics design draft.

Passes all.bash.

Change-Id: I81880a40e3532cd4e28b753472379e3dfed2f362
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/759561
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Robert Griesemer
fd86e2cab9 cmd/compile/internal/syntax: accept embedded instantiated types in interfaces
Add some smoke tests.

Passes all.bash.

Change-Id: I29ef9a0a8e8b18a6a3c5af151934d38622067857
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/756090
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Robert Griesemer
cb7d43b2ea cmd/compile/internal/syntax: actually collect type list types (fix bug)
The existing code collected empty fields. Collect the actual
field and added type string test.

(This was not found before because the generic tests are still
disabled in this port because of different position information.)

Change-Id: I959711892aac3c8f7587a4025c4b32f1598f5df3
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/756088
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Robert Griesemer
8355f8a9ee cmd/compile/internal/{syntax, types2}: accept type parameter pointer designation
Accept but (for now) ignore the pointer designation.
This is a port of the relevant changes in go/types:

https://team-review.git.corp.google.com/c/golang/go2-dev/+/750582
https://team-review.git.corp.google.com/c/golang/go2-dev/+/751264

Passes all.bash.

Change-Id: I4767c3addc881691bebf22cb030fa578124b7db0
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/755797
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Robert Griesemer
380193353c cmd/compile/internal/types2: make "make" work for generic types
This is a port of the equivalent changes in go/types
(https://team-review.git.corp.google.com/c/golang/go2-dev/+/755783).

Change-Id: I2533a76ea1c5662c93bfd76125946151aa80f660
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/755796
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Robert Griesemer
188ddaf79c go/types: make "make" work for generic types
Passes all.bash.

Change-Id: I524878e0299e12633c633540cc8f76deab81ce48
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/755783
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Ian Lance Taylor
7116b1df5f cmd/go2go, go/go2go: use PathListSeparator
Don't assume that path lists use colon separators.

Fixes golang/go#39211

Change-Id: Ibce7295dcc290a7826ee6b25a06aa36b8e40f961
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/755784
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:52 -07:00
Robert Griesemer
8df9c7a8fa go/types: make type bound instantiation optional if bound has one type parameter
If a type bound expects one type parameter, permit omitting explicit
instantiation of the type bound in a type parameter list. In that case,
the type bound is instantiated with each respective type parameter
and becomes that type bound for that type parameter.

For example, given:

	type Bound(type T) interface { ... }

the type parameter list:

	(type P, Q Bound)

is syntactic sugar for:

	(type P Bound(P), Q Bound(Q))

This is a generalization of the former change:

https://team-review.git.corp.google.com/c/golang/go2-dev/+/728411

Passes all.bash.

Change-Id: I0191dcf3fbccf6e777f01dfa8ccef5aba0310213
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/751267
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Robert Griesemer
c64ef0ed90 go/types: recognize (but for now ignore) pointer and "underlying" designations
1) Recognize pointer designation in type parameter lists.
2) Recognize "underlying" type designation in interface type lists.

Adjust a few tests.

Passes all.bash.

Change-Id: Ic33195f2802698f957cbbda1770c78dc4d8a5e2a
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/751264
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Robert Griesemer
1be59591cc go/parser: accept "underlying type" lists in interfaces
A type list may now be preceeded with "underlying" "type":

interface {
    // type list
    underlying type int, int32, int64

    // method
    underlying(int) int32
}

Change-Id: I37ea2ce3ca0e56f1fc35542ae04481dc7665b17c
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/750491
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Robert Griesemer
f59b75aff6 go/parser: accept "untyped type" lists in interfaces
A type list may now be preceeded with "untyped" "type":

interface {
	// type list
	untyped type int, int32, int64

	// method
	untyped(int) int32
}

Passes all.bash.

Change-Id: I745c5f05ab5d6013d585da278b27e1eb781c0762
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/750483
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Robert Griesemer
774de94abe go/parser: accept pointer type parameter marking
Accept type parameters marked with a '*' as in:

(type A, *B bound)

indicating that the Bound requires pointer methods for B.
The notation is accepted but not yet recorded in the AST.

While at it, clean up some residue in parameter parsing
and disable acceptance of contract notation.

Passes all.bash.

Change-Id: I8d0c4614322bfed885ab26ef2da65a57208a9552
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/750582
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:52 -07:00
Ian Lance Taylor
4b7067c133 cmd/go2go: rename testdata contracts to constraints
Change-Id: I52eaf2e87abc53b79b2fbcfcb156f093298341ef
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/750508
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:51 -07:00
Ian Lance Taylor
db04e7cb2e go/go2go, cmd/go2go, test: rewrite example code to not use contracts
Don't emit interfaces that are type bounds in the generated .go file.

Change-Id: I9b0fd2f6041e9464147ad6d82d349fe894ea762d
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/735474
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:51 -07:00
Robert Griesemer
e83c4715b0 cmd/compile/internal/types2: apply latest go/types changes
After rebasing on top of master, the go/types version of
this branch includes the latest changes of go/types in
the std library. Apply the same changes to types2.

(Created a CL containing the differences between the starting
point for types2 (commit 89463ec, which was a copy of a
prior go/types) and the current go/types, and then cherry-
picked those differences on top of types2.)

Passes all.bash.

Change-Id: I6137a476dc90f5dbd0b90e9fbe144dc7bc13a9e3
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/748099
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:51 -07:00
Robert Griesemer
75b401bccf cmd/compile/internal/types2: make go vet happy
Also, gofmt a few files.

Change-Id: Ie430556f5c1ae9c8acc24bbc5500a2579275fd39
2020-06-13 12:24:51 -07:00
Robert Griesemer
821d2a635c cmd/compile/internal/types: fix const/var decl handling and enable StdTest
Change-Id: Id06e34bcdfddf6bc0cd990b2eb3d0f1c6ccfdeb3
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/747119
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:51 -07:00
Robert Griesemer
3f276cd882 cmd/compile/internal/types2: make all tests of TestTypesInfo run
Change-Id: I02069af89e86b2bd5bf3c84e8f8119d84be0aad9
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/746891
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:51 -07:00
Robert Griesemer
e37af78043 cmd/compile: fix Formats test
Change-Id: I0c5b7e330fb77b4d2b87e93a3af149f0b35ed9fa
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/746630
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:51 -07:00
Robert Griesemer
5887a08520 cmd/compile/internal/gc: report error when compiling generic code
The compiler can parse but not actually compile generic code.

Change-Id: Icfaa61811bdcc80f59d656a25c26db40b6fd7877
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/746626
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:51 -07:00
Robert Griesemer
176a871ff3 cmd/compile/internal/types2: make tests depending on imports work
Passes most types2 tests, incl. type-checking of std library.
Passes all.bash.

Change-Id: I5d452ecb3decf1bdfee864c594e3f2a01525e548
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/744664
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:51 -07:00
Robert Griesemer
c0558e3405 cmd/compile/internal/importer: make importer work with types2
Passes all its tests.

Change-Id: I0ba20a284f08e10531976b6253e3c340bbd84dcd
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/744663
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:51 -07:00
Robert Griesemer
cdfaff44de cmd/compile/internal/importer: starting point for new importer
Make an exact copy of go/internal/gcimporter in
cmd/compile/internal/importer. Serves as starting
point for a types2-based importer.

Change-Id: Ib676794622bc1cb1614e396df6b391f374757cda
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/744662
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:51 -07:00
Robert Griesemer
56162a1a5f cmd/compile/internal/types2: make type2 work with syntax package
Snapshot of work in progress.

- Entire package converted to use syntax package.
  (We still need to convert syntax.Operators to token.Tokens
  in some cases so we can use the go/constant package.)
- Some code is commented out and/or unimplemented.
- The functionality provided by eval.go, eval_test.go, gotype.go
  is not needed and was removed.
- Compiles cleanly and many tests run at this point.
- Skips tests that require import to work.

Passes all.bash.

Change-Id: I2f215d97c858c22058779a6a5b1a2065b51bd4af
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/741794
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:51 -07:00
Robert Griesemer
73270217c8 cmd/compile/internal/types2: starting point for new type checker
Make an exact copy of go/types in cmd/compile/internal/types2.
Serves as starting point for a cmd/compile/internal/syntax-
based type checker, initially using the go/types logic.

Change-Id: Ide782fdaefd591b7757e54be5c16421bb8e935b2
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/741793
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:51 -07:00
Robert Griesemer
90f286c307 cmd/compile/internal/syntax: record type parameters (don't just parse them)
Also: Distribute type parameter names if necessary.
Change-Id: I59d83c29548b62f21a65b225ee3e743c95287adc
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/744598
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
5f8feb36c0 cmd/compile/internal/syntax: encode interface type lists more accurately
Encode an interface list element as a Field (like methods) but with
the special name "type" (no method can have that name as it is a
keyword). Types belonging to the same type list share the same name
pointer. This preserves full position information and removes the
need for another list in InterfaceType.

Change-Id: Ib7f02f7272078445546e47b394ed9e112dd5821f
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/741894
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
d234c93a9b cmd/compile/internal/syntax: clear pragma at the right place (fix build)
The previous CL changed the parser.list implementation to not consume
the opening token anymore; this was changed so it could be used for
parsing type parameter lists which start with a "(" and a "type".

Consequently, parser.appendGroup was changed to consume the opening
"(" early, before parser.clearPragma was invoked. As a result, a
correctly placed pragma for the next declaration was consumed too
early, leading to an error with test/directive.go. Fixed.

Passes all.bash.

Change-Id: Ief2f71228697e5516ebdecb773fdc30438f1fa9f
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/738661
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
70f1138c60 cmd/compile/internal/syntax: accept Go2 syntax
Specifically, this change accepts now:

1) Type parameters in type and function declarations, such as:

	type B(type T) interface {
		m(T) T
	}

	func f(type T B) (list []T) T

2) Type instantiations:

	type T B(int)

3) Embedded instantiated types, with necessary extra parentheses:

	type T struct {
		(B(int))	// ()'s to distinguish from field B of type (int)
	}

	type T interface {
		(B(int))	// ()'s to distinguish from method B with int argument
	}

The compiler simply ignores the new constructs.

Change-Id: Iecb8354d3846d7a5786cbe7d92870d8a2d578133
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/736539
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
bc3ba78503 go/types: implemented AcceptContracts flag to enable/disable contracts
AcceptContracts is a global flag (api.go) to enable/disable contracts.
All go/types tests pass with the flag in either setting, i.e., all
go/types tests involving contracts have been rewritten or disabled.
To ensure the existing go2go code runs, AcceptContracts is set to true
for now.

If contracts are disabled, "comparable" is a predeclared interface
(without type parameters) rather than a predeclared contract (with
one type parameter).

Change-Id: I2ddade9ae38d61d9edca6020f3334d2215b84f1d
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/734984
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
4efa3ddb87 go/types: make type bound instantiation optional if there's only one type parameter
This simplifies the use of parameterized interfaces as type bounds.
For example, given:

	type Bound(type T) interface { ... }

we can use this interface as a type bound with or without instantiation
in a type parameter list:

	func _(type T Bound(T))	...  // with explicit instantiation
	func _(type T Bound) ...     // instantiation left away

In the latter example, Bound is syntactic sugar for Bound(T).

In general, in a type parameter list, instantiation of an interface
type bound is optional iff the the type bound applies to exactly one
type parameter and the type bound expects exactly one type argument.

Change-Id: I0e820a0e214427cce6397069c1d5268494096812
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/728411
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
7c99cab23e go/types: better error when accessing non-existent methods of type parameters
Track the contract or type name specifying a type bound
in the corresponding interface and use that information
for more specific error messages.

Change-Id: I8aa3458addd1e8446a3a5766a03fd50e338fc8ed
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/727599
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
e871c64307 go/types: updated README and NOTES
Change-Id: Id80b2a63ab7d358b5818730dfcc75f9e8b6e48a5
2020-06-13 12:24:50 -07:00
Robert Griesemer
4843595d7f go/types: implement specific converter methods for *instance types
This is fixing a known issue (see below) and many unknown issues:
An *instance type may legally represent any kind of type after
instantiation.

Given the declaration:

	type T(type P) P

T(int) is now a valid constant type, and T([]int) is a valid
slice type.

Also, fixed the implementation of isTyped/isUntyped which caused
types to expand prematurely.

Change-Id: Ic71c7252e3b066b0f97c2f1892cf20b2c4c2ef98
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/723717
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
37801e2c49 go/types: don't forget *contractType in sanitation code (fix cmd/go2go test)
Change-Id: Ie736a1dba7aa73641d2869bc3a6c36c5400d6c09
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/724470
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
bfe0923cc7 go/types: sanitize Info.Defs/Uses and add tests
Change-Id: I4c7003a88009f142ca674c8ea6b138a444a2bac5
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/722935
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
975f454e6a go/types: report error for infinite generic types
To make this work for embedded fields, delay checking of
embedded field properties to the end of type checking to
avoid expanding possibly incomplete types.

Change-Id: I0ff7f86398deb05dcd4d0d5b5f94309d63db7a67
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/723398
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Ian Lance Taylor
c2d160bafc cmd/go2go: add List example
Change-Id: Id12b3489c2cd17f48d918563b002fe704db6a177
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/723255
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
4ba2f1d5fd go/types: fix type substitution
When instantiating a type, cache a new version with a valid (non-nil)
underlying type so that we don't run into a missing underlying type
if instantiation is self-recursive.

Added more tests, also for issues found while debugging.

Change-Id: I520a4f71e60bd9020977276db078582d41a677f1
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/723252
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:50 -07:00
Robert Griesemer
4b95e48766 api: update except.txt to accomodate for bigger types.Type
Fixing API check to make it pass. Adding the extra methods
to types.Type is not backward-compatible, but this is a
prototype, so we don't care too much for now.

Passes all.bash.

Change-Id: I7d1ab5d4eb2d69d10302e2aed2718b4a03ab36cc
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/722390
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:49 -07:00
Robert Griesemer
67da60ed50 go/types: sanitize types.Info maps
Don't export Instance anymore (renamed to instance).

Added sanitizer that expands any *instance type
into an instantiated *Named type as a last pass
of a type checker run.

Note: For now only the Info.Types and Info.Inferred map
      entries are sanitized to make go2go tests pass.

Passes all.bash except for api check.

Change-Id: I2a937b0e7e94c597dfd58af23c314cd20b3f7776
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/722383
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:49 -07:00
Robert Griesemer
6300d5adf9 go/types: instantiate generic types lazily
Until now, a generic type instantiation T(P1, P2, ...) was evaluated
eagerly, that is the formal type parameters of T were substituted with
the actual type arguments P1, P2, ... upon encountering that expression.
This caused problems when the type being instantiated wasn't fully set
up yet (i.e., it's declaration wasn't completely processed yet).

With this CL, a type expression of the form T(P1, P2, ...) is
represented via the new "syntactic" Instance type. The instantiation
is not checked eagerly, and no substitution takes place. Only when
needed, is an Instance type "expanded"; this is typically necessary
when operations on the instantiated type need to be performed. The
new exported function Expand(Type) Type takes a type and expands it
(i.e., instantiates it) if the argument was an Instance type. The
type string of an Instance type is prefixed with a '#' as in #T(int),
to distinguish it from the type string of the expanded type T(int).

Operations on types usually require the underlying type, and thus a
new method Type.Under returns the fully expanded underlying type of
a type (incl. following of forwarding chains). Type.Underlying remains
unchanged for backward-compatibility and use by clients expecting the
old behavior.

This CL is also a first step towards more lazy evaluation and checking
of properties that are better deferred to the end, when all types are
fully set up. For instance, when collecting embedded interfaces, we
now just collect the types (they may be Instances of generic interfaces)
and only expand and check if they are indeed interfaces when interfaces
are completed.

This new lazy approach should also permit the (future) introduction of
an Alias type to cleanly track alias types.

Passes go/types tests (but not all.bash).

Change-Id: Id5fb0e2fa497f506c2e938ca6a6606835c8a8b20
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/719901
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:49 -07:00
Robert Griesemer
63f4460f70 go/types: implement type conversion methods
Provide easy accessors to a type's underlying type. Instead of

	if t, _ := typ.Underlying().(*XXX); t != nil { ... }

we can now write

	if t := typ.XXX(); t != nil { ... }

where XXX is a type such as Basic, Array, Slice, Pointer, etc.
This removes a type assertion in all cases where typ is not a *Named
type and the code is easier to read.

Also, made Named.Underlying more robust by tracking cycles and nil
underlying types.

The Named.Underlying change is a first step towards making type
checking more lazy which eventually should permit dealing with
cycles that we cannot yet handle properly.

This change briefly breaks some external code (gcimporter, gccgoimporter)
due to the change in semantics of type.Underlying. This will be fixed by
the next change.

Passes go/types tests (but not all.bash).

Change-Id: I493a949e554da6f2a944e7e9b1f1f6f38f597042
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/717606
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:49 -07:00
Ian Lance Taylor
04f9e20db3 go/build: permit go/go2go to depend on internal/goroot
Change-Id: I22ee40f6ea529628bebc4e21ba2ae7789f3f6b60
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/721561
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:49 -07:00
Ian Lance Taylor
39dc66f9c2 go/types: improve contract error messages
If a type or type parameter does not satisfy a contract because the
type or type constraint is not found in the list of type constraints,
change
    T does not satisfy C(T) (T type constraint int not found in interface{type ...})
to
    T does not satisfy C(T) (T type constraint int not found in [type ...])
Also, before this change, if the contract had any required methods,
those were also listed; now we just list the type constraints.

If a defined type does not satisfy a contract because the underlying
type is not found in the list of type constraints, change
    MyUint does not satisfy C(T) (MyUint not found in interface{type ...})
to
    MyUint does not satisfy C(T) (uint not found in [type ...])
That is, when describing the type that is not found, use the underlying type,
not the defined type.

Change-Id: I345836c44921e2e13e7f02041839b5eb4df75c45
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/718718
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:49 -07:00
Ian Lance Taylor
7d185f0ba6 go/types: improve contract error messages
If a type parameter that has no type constraints is trying to satisfy
a contract that does have type constraints, change
    T does not satisfy C(T) (missing type int)
to
    T does not satisfy C(T) (T has no type constraints)

If a type parameter that has type constraints is trying to satisfy a
contract that has type constraints, but the parameter has type
constraints that the contract does not permit, change
    T does not satisfy C(T) (missing type int)
to
    T does not satisfy C(T) (T type constraint int not found in interface{type ...}

Change-Id: I3bd4f59b0544b382399d9b9d891a509ce62f56c3
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/718426
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:49 -07:00
Robert Griesemer
67b6f218e9 go/types: fix type bound check
A type argument with an empty type list bound never satisfies
a type parameter with a non-empty type list bound.

Change-Id: Ic4206f74fd4625b4207baa28bdb0de0fc669b37e
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/717296
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:49 -07:00
Jonathan Amsterdam
7a57f4d76e slices: fix Equal contract
slices.Equal only requires comparable, not Ordered.

Change-Id: I0150f1370e478aaa33bbd8788a1f9c9d33b85e06
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/716483
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:49 -07:00
Robert Griesemer
63d4750592 go/types: avoid crashes when printing/tracing invalid interfaces
Rewrite Interface.Empty to not be dependent on an interface being
complete. Be careful when printing invalid interfaces.

This fixes a couple of crashes when running tests with -v (trace)
mode enabled.

Change-Id: I4be416eac7e3fae83c08608ed74bf3987b2a7457
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/716089
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:49 -07:00
Robert Griesemer
a89350ee85 go/types: interfaces are comparable (bug fix)
Also: Updated NOTES (unrelated).

Change-Id: I12ce0465e408920d4cd430ab529f346281f4ac64
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/716118
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:49 -07:00
Ian Lance Taylor
2b5e8d70c0 go/go2go: parse Go1 packages using go/types
When a Go2 package imports a Go1 package, then if the Go1 package is
in the standard library use the default importer, but otherwise
parse the package ourselves by recursively calling go/types.
This supports a Go2 package importing a Go1 package that imports
a Go2 package.

Change-Id: I8906d8ea5b81e6239652c0e46de79b5c1b59cfcd
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/716063
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:49 -07:00
Ian Lance Taylor
c2d8b59433 go/go2go: record types of instantiated AST types
Otherwise we don't know the type of an instantiated type in an
instantiated function.

Change-Id: If7eb75dd920a3c9fc1b6992addcd3b91b6d425a9
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/715718
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:49 -07:00
Ian Lance Taylor
760a3244a7 go/go2go: only copy .go2 files of import to tmpdir
We are only going to translate the .go2 files of an imported package,
so we don't need to copy anything else to the temporary directory.
This fixes the case of an imported package with a subdirectory,
which previously crashed trying to copy the directory.

Change-Id: I54cfb43ad2a3e23a4e0d7201d9e6e2ade02b7469
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/715029
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:49 -07:00
Ian Lance Taylor
6df3320d36 test: drop a 0 from gen/err000n.go2
Matches the g cases.

Change-Id: If0c2558b9304cdd73e01d8718303e8fb0fccaf34
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/714999
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:49 -07:00
Ian Lance Taylor
5dac261e8b cmd/go2go: pass GO2PATH as GOPATH to regular go tool
Also when looking for packages specified on the command line,
search GO2PATH before trying to invoke "go list".

Change-Id: I9704ef86fa46b877ee195a40843a034d014c2a3d
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/714998
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:49 -07:00
Ian Lance Taylor
dbe1a544f9 go/go2go: run "go install" for Go 1 packages
The default importer looks for installed packages, not sources.

Change-Id: I0c85460fa5792953e78288347fc637e0ee540b15
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/714780
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:49 -07:00
Ian Lance Taylor
39ba9cff56 cmd/go2go: add basic test for go2go build
Change-Id: I44109a4c0fe81d4c88e13200db1d2e6da576d262
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/714759
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:49 -07:00
Robert Griesemer
fd583fcbae go/types: update README
Change-Id: Ifc694498d0661c02907a1f39f2ea9f1535d8dbdf
2020-06-13 12:24:48 -07:00
Ian Lance Taylor
061f93c871 test: add test for package name in error messages
Also add support for errorcheckdir in Go 2 tests.

Change-Id: Id69577050917d02ca98c91d6184318286d75ac2f
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/712204
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:48 -07:00
Ian Lance Taylor
1d379da30b go/go2go: don't expect type arguments after instantiated name
Change-Id: I639adb020890e29b96458db5dffdea31bd1f8ffe
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/712186
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:48 -07:00
Robert Griesemer
faf2cc0cb8 go/types: improve printing of type parameter lists
- leave type bounds away if empty (interface); don't write "any"
- boundle type parameters with the same type type bound
- simpler code for error message cleanup

Change-Id: I8c1b662479de185b2ebae47ed1d16482253dfe03
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/710076
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:48 -07:00
Robert Griesemer
f936401d53 go/types: use local and global type cache consistently (cleanup)
- store a *Named type in both caches
- update local cache also when we have a global cache hit

Change-Id: If4ab24a0c24d21f425a76dc51e4ec2ed495b26e4
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/710128
Reviewed-by: Robert Griesemer <gri@google.com>
2020-06-13 12:24:48 -07:00
Robert Griesemer
81022d54ae go/types: remove instantiated type name hacks
Instead of creating a new instantiated type name "name<T1, T2...>"
keep the regular name for the corresponding type object since
these newly created types are never declared. This eliminates
the need to clean up the names (remove the <>'s) before they can
be used.

When printing a named type, simply decide what to print depending
on whether it is instantiated or not.

When looking up an instantiated type, simply create the instantiated
type name string for use in the (local and global) type caches.

Change-Id: I4b20d09ec64d8deefccdd338ffb2f78fdfd2101e
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/710062
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:48 -07:00
Robert Griesemer
f25fd9bf57 go/types: remove an empty line (test for code review)
Change-Id: I5595aa5ea2ae808c60dde1566d35bad8ad7761c5
Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/709260
Reviewed-by: Ian Lance Taylor <iant@google.com>
2020-06-13 12:24:48 -07:00
Ian Lance Taylor
be37919cd7 go/types: better error message for incomparable type
If a type does not satisfy comparable, don't report "missing method ==".

Change-Id: Idae2477e134f73db9ba5fb94302eec84fefe98ef
2020-06-13 12:24:48 -07:00
Ian Lance Taylor
d3ecc7c57c cmd/go2go: mention some tool restrictions in the doc
Change-Id: I8568fffa6570610d909b0f23fa9bdd3ab6097a78
2020-06-13 12:24:48 -07:00
Robert Griesemer
ab835222b0 go/types: updated README (after rebasing on top of master)
Change-Id: I3d63346aa00b6de8a7ba725081affb155cc828f1
2020-06-13 12:24:48 -07:00
Robert Griesemer
ac135a4bcf go/types: better error messages for type inference
Change-Id: I8a5b07eca76b084901cce6f1bae4f8d107d10701
2020-06-13 12:24:48 -07:00
Robert Griesemer
1ad26bf1a7 go/types: fix some internal comments
Change-Id: I50f9127219321c3f173b28bf42b03e01384d920a
2020-06-13 12:24:48 -07:00
Ian Lance Taylor
0c3eb6800e test: support errorcheck for .go2 files
Change-Id: I90f840c89d4437a8b9fbd4f08582b5cb0d2eec6d
2020-06-13 12:24:48 -07:00
Ian Lance Taylor
fad64b3083 cmd/go2go: add pointer variant to graph package
Change-Id: Ib5cf28be42943ea816c64740f5698a5716d3dec1
2020-06-13 12:24:48 -07:00
Robert Griesemer
07382406ea go/types: fix satisfaction check of argument type against type bound
Per the draft design:

In a generic function body all method calls will be pointer method calls.
If necessary, the function body will insert temporary variables, not seen
by the user, in order to get an addressable variable to use to call the method.

When checking if a concrete type argument satisfies its type bound, assume
that concrete type is the type of an addressable value.

Change-Id: I9d40138755c38330448c010994b95a82f38e60e0
2020-06-13 12:24:48 -07:00
Robert Griesemer
6768c4f513 go/types: first cut at better error messages
- added Error.Full and Error.FullError which provide the full error
  message, possibly containing internal details
- Error.Msg and Error.Error provide a user-friendly error message

Change-Id: Id3044165331af71be31ef423cd2c9b8fe28accbd
2020-06-13 12:24:48 -07:00
Robert Griesemer
62683a7752 go/types: fix lookup of methods of pointers to type parameters
Since the type bound of a type parameter is an interface, no method
is found if the receiver is a pointer to a type parameter (pointers
to interfaces have no methods).

Ignore the indirection in this case.

Change-Id: Ie2af78b4cfb2f70b5d4f1d2afc631716a10ff7d9
2020-06-13 12:24:48 -07:00
Robert Griesemer
f81ad49939 go/types: report an error when seeing pointer designation in contracts
Pointer designations were not recognized nor supported.
Now we recognize them and report an error until type-checking
can handle them.

Change-Id: I0deed536aa03c06c3e9ec60a5c2e186e916b970f
2020-06-13 12:24:48 -07:00
Robert Griesemer
e03920500c go/printer: print pointer designation of type parameters in contracts
Also: Align start or methods and type lists.
Change-Id: Icae3be0ebcbc633d2ed88ff6f620dc078a7c698e
2020-06-13 12:24:48 -07:00
Robert Griesemer
49c8636998 go/parser: accept pointer designation for type parameters in contracts
Change-Id: Ib119b7cd22de7117db82b987a3cd4573cbb6f6c8
2020-06-13 12:24:48 -07:00
Ian Lance Taylor
29365a1738 cmd/go2go: rename graphs_test.go2 to graph_test.go2
Change-Id: I25cfedbf6c115db5545c0c12b96588a581e41a53
2020-06-13 12:24:47 -07:00
Ian Lance Taylor
87059675da go/go2go: support instantiating with an inferred local type
Add a graph example.

Change-Id: Iec533487f2757b9fdc883e4a57715ad993e11254
2020-06-13 12:24:47 -07:00
Ian Lance Taylor
5f4c825cf8 go/go2go: support imports that only defines funcs
That case was breaking when looking for a symbol to import to avoid an
unused package error.

Change-Id: I51ccacf36a95a16eac89071d5fa141608b759014
2020-06-13 12:24:47 -07:00
Robert Griesemer
a31f6ae875 go/*: change representation of type lists in interface types, adjusted dependent code
Until now, types of type lists in interface types were collected in
a single expression list "Types". This made it not possible to gofmt
such interfaces while preserving the original layout of type lists.

This change represents types of type lists as part of an ast.FieldList.
The ast.InterfaceType.Methods field list now represents embedded interfaces,
methods, or type list types through ast.Fields. This preserves all position
information and thus permits accurate gofmt-ing.

The new representation is as follows: For an ast.Field f, if
- len(f.Names) == 0        : f.Type is an embedded interface
- f.Names[0].Name == "type": f.Type is a type of a type list
- otherwise                : f represents a method

Since "type" is a keyword, a Go field name cannot be "type".
Fields of types of type lists that share the same "type" keyword
in the source share the same f.Names[0] identifier (named "type"),
and the position of that identifier is the position of the "type"
keyword in the source.

Related changes:
- Adjusted go/parser to build the new representation.
- Adjusted go/printer and implemented formatting of type lists.
  (This is still not quite correct if there are comments, but
  that is fine-tuning).
- Adjusted go/types to work with the new representation.
- Implemented SplitFieldList and MergeFieldList in go2go
  translator to easily switch between old and new representation.
- Updated documentation.

Change-Id: I016e2ce5949bfe294509d703156c41d42cf7084e
2020-06-13 12:24:47 -07:00
Robert Griesemer
e5e519e893 go/printer: cleanups around contract printing
- added more tests
- documented invariants and status quo

Change-Id: I74d75eee3936e659476fc5b428e8d11d5c5e4098
2020-06-13 12:24:47 -07:00
Ian Lance Taylor
01ab391f82 go/go2go: support instantiating with an instantiated type
Add metrics test case to test GO2PATH.

Change-Id: I48c8a418d743ccd80cdcf36fc043ca0e2dd932f4
2020-06-13 12:24:47 -07:00
Ian Lance Taylor
42884d7524 go/types: support setting the TArgs of a types.Named
Change-Id: I468b77165079ab30844e54b4988717be452cb648
2020-06-13 12:24:47 -07:00
Ian Lance Taylor
10efd1cfc6 go/printer, go/ast: gofmt improvements for generic code
Change-Id: I62f7c0f52ac9d51eacd2392083e1aa7799022559
2020-06-13 12:24:47 -07:00
Robert Griesemer
e39082c80f go/types: remove vestiges of type unification in Checker.identical0
Type unification now happens through the new unifier code.
We can revert the functionality of Checker.identical back
to its original purpose of type comparison. This change
should make identity comparison faster again.

Change-Id: I844515b5f20a890152a0a5436f04c553b3b722e5
2020-06-13 12:24:47 -07:00
Robert Griesemer
5da07bf767 go/types: implemented (bidirectional) unifier and use it for type inference
- Implemented bidirectional unifier as a stand-alone mechanism
  separate from Checker.identical0.
- Use it instead of Checker.identical0 where we need unification.
- Missing: Bidirection functionality not fully implemented because
  we don't use it yet, but the basic outline is present.

Change-Id: I1666c9e4c9094eda749084bb69c700f1b5e879bb
2020-06-13 12:24:47 -07:00
Ian Lance Taylor
42e310c4a6 cmd/go2go: add Append and Copy to slices test
Change-Id: Ie6826d8c66ae33a377dac9e66ff8363439a2be6c
2020-06-13 12:24:47 -07:00
Ian Lance Taylor
4a8a353a22 go/go2go, cmd/go2go: add orderedmap example
Add transitive imports so that imports used by instantiated functions
and types work correctly.

Change-Id: Ie8fe0aaece7ca1bdbf201242870113d741ad3f37
2020-06-13 12:24:47 -07:00
Robert Griesemer
46b40480b6 go/types: updated documentation
Change-Id: Id84fd18dc0e1928c96bb50a1759ced1e56605d51
2020-06-13 12:24:47 -07:00
Robert Griesemer
74bad35110 go/types: updated README
Change-Id: Ib68114593c5c26f05e06e7326c1567d3f253c5a5
2020-06-13 12:24:47 -07:00
Ian Lance Taylor
01b5212797 cmd/go2go: point to testdata/go2path in package docs
Change-Id: I94857bb943503d1107b814e5111ccd6512c4a477
2020-06-13 12:24:47 -07:00
Ian Lance Taylor
0b55a72ba3 cmd/go2go: remove explicit type arguments in chans_test
They are no longer needed as the type checker now ignores channel
direction for type inference.

Change-Id: I06f2ffaf60a140747f1fc5c47135045e9004d551
2020-06-13 12:24:47 -07:00
Robert Griesemer
e490a1bfb5 go/types: ignore channel directions for type inference
Change-Id: Ic7c61dfea7b43bb102bff077bf17d86b26fffba9
2020-06-13 12:24:47 -07:00
Ian Lance Taylor
db2cf1336d go/go2go: instantiate all kinds of types
Change-Id: Iaf17de0e5556171e18d4b0c4ae7e3dd1e9f7c777
2020-06-13 12:24:47 -07:00
Ian Lance Taylor
22a2e4f0c2 cmd/go2go, go/go2go: add chans test case
To make this work, add support for instantiating pointer types.

Change-Id: Ifcecf863ad4194014a242d0a0d01ca3dc0288811
2020-06-13 12:24:46 -07:00
Ian Lance Taylor
8d18d04312 go/go2go: report all type checking errors
Previously we reported just the first one.

Change-Id: Id8fbb50f8c6f8ab56ce76dacda4c388b76ce6c80
2020-06-13 12:24:46 -07:00
Ian Lance Taylor
c165308eb6 go/go2go: fill in missing ast.Expr and Stmt nodes
Change-Id: I151a923c72fb61c8f31dc6d3688bcd338ab472f7
2020-06-13 12:24:46 -07:00
Ian Lance Taylor
c65d33fa3d go/go2go: handle ast.Ellipsis in instantiate and rewrite
Change-Id: I03d316677c2a1cf31fe28d55df1ef21515a0a2ba
2020-06-13 12:24:46 -07:00
Ian Lance Taylor
87d1d10fbe go/go2go: register packages by full import path, not package name
Change-Id: Ie40021111c97c6b30a733912e3106e8a87a0634a
2020-06-13 12:24:46 -07:00
Robert Griesemer
399d59ee46 go/types: make type inference work for self-recursive function calls
Cases such as

	func f(type T)(x T) {
		f(x)
	}

can now be type-checked. For more examples see examples/functions.go2
in the go/types directory.

Change-Id: Id661c84f086cc8ee45ec372ac4af543e68bebe8a
2020-06-13 12:24:46 -07:00
Ian Lance Taylor
67e62d261e cmd/go2go: add sets package to testdata/go2path
Change-Id: Id47ae62192c1c8507689f8a5b1bb347baa5db4ea
2020-06-13 12:24:46 -07:00
Ian Lance Taylor
9482f72042 cmd/go2go: add Map/Reduce/Filter/Max/Min to test cases
Change-Id: I586d4c548d4a982fe15d75128ea4f82be9db2416
2020-06-13 12:24:46 -07:00
Robert Griesemer
54d6b25ee0 go/types: updated README
Change-Id: Ib4a86240ca82722d522f8b1ce67c96695c7c4b13
2020-06-13 12:24:46 -07:00
Ian Lance Taylor
2902418378 cmd/go2go: use embedded comparable in maps test
Change-Id: I9f3a8a377597330daa43d1757ddd8a18560cf5d4
2020-06-13 12:24:46 -07:00
Robert Griesemer
a30aa6c43e go/types: fix contract embedding
Contract embedding is reduced to interface embedding. When embedding
interfaces:
1) use the correct interface to embed; and
2) don't leave type bounds residue on the incoming type arguments
   of the embedded interface/contract as those are also the type
   parameters of the embedding (outer) interface/contract.

Also:
- For now, print "any" instead of "interface{}" (empty interface)
  when printing type parameter lists to reduce clutter. Eventually
  we should not print anything for empty interface bounds, but we
  first must also group type parameters with the same type bounds.
- Print the type parameter subscript in type parameter lists to
  make it clearer which type parameter we are referring to.

Change-Id: Ic83516096387d0f512c4c76a8a8fe849d51e033a
2020-06-13 12:24:46 -07:00
Ian Lance Taylor
2044d8b94b cmd/go2go: use predeclared comparable in maps test
(But embedding comparable doesn't work yet.)

Change-Id: I977ca97597de47c79edb56b385c970392afb87f0
2020-06-13 12:24:46 -07:00
Robert Griesemer
10b59aa539 go/types: implement predeclared contract "comparable"
The comparable contract defines a magic method "==" which
enables comparisons with == and != . Comparable types
automagically implement this method.

TODO: If a type is not comparable but a comparable type is
expected, the error message can be confusing (missing ==
method).

Change-Id: Ie0d89b87c36d83549f7d869c18dd9786151adbae
2020-06-13 12:24:46 -07:00
Ian Lance Taylor
e6f000d2f9 go/go2go: add maps test case
Change-Id: Iad570b218a7a3c2075f846cc86c58ec7e6b0e50c
2020-06-13 12:24:46 -07:00
Robert Griesemer
2bc31ee9f4 go/types: de-parameterize instantiated contracts when embedding them
More precisely, de-parameterize the corresponding interfaces when
embedding them in the corresponding type bounds (interfaces) for
the embedding contract. This prevents the embedded (and already
instantiated) interfaces from being instantiated again when the
outer interface is instantiated and avoids breaking an assertion.

See also the test case in testdata/issues.go2 for more details.

Change-Id: I70c9354849eda0c8a36905d0b80f4d3031542f30
2020-06-13 12:24:46 -07:00
Robert Griesemer
3935b33b31 go/types: avoid follow-on panic after assertion failure in subst
Also: Updated NOTES.

Change-Id: Iabc45e46aa76bacf5c6984dab6f4bcab74392562
2020-06-13 12:24:46 -07:00
Ian Lance Taylor
5a5b14a4b3 go/go2go: support type inference
We can now translate code that use type inference when calling generic
functions. A couple of test cases were adjusted to use it.

Change-Id: I53c2f3dd8f9fcdb44b4a8f592acee1a19ff46f22
2020-06-13 12:24:46 -07:00
Ian Lance Taylor
4172f069ae go/go2go: aggregate types.Info together for all packages
Change-Id: I4c73c417a1e7946422fd2e1035a2ce4406ca1cf3
2020-06-13 12:24:45 -07:00
Robert Griesemer
07a7684507 go/types: record inferred type arguments for parameterized calls
In api.go, introduce a new type `Inferred` which collects type arguments
and signature in one place and which can be extended if need be.

Change-Id: I014dd52641843e85ad408fdaa07eda121cf1c41c
2020-06-13 12:24:45 -07:00
Ian Lance Taylor
2eed31c177 go/go2go, cmd/go2go: build a GOPATH of translated packages
Also start a testsuite for cmd/go2go.

Change-Id: Ib693c79b3a7427ac2f6be3264469274157a39851
2020-06-13 12:24:45 -07:00
Ian Lance Taylor
1bf660ee7c go/go2go: initial support for contracts
Includes a small patch to go/types to correctly check whether type
parameters are comparable.

Change-Id: Icd3443e0cd968eabdbd55f90520b0c6ad485edf8
2020-06-13 12:24:45 -07:00
Robert Griesemer
3370013383 go/types: add support for imported contracts (denoted by qualified identifiers)
Original code by iant@. Slightly streamlined and fixed a bug in the
process (if there is a type error in the contract, we only must "use"
the type arguments if they exist in the first place).

Change-Id: Id404d2cd4fd081b9a8053e194bf643593093e397
2020-06-13 12:24:45 -07:00
Robert Griesemer
73bb221120 go/types: add types.Info.Inferred map recording inferred function signatures
Change-Id: Idc57c1662fe63edbe8f494961cb4dcda6db61e79
2020-06-13 12:24:45 -07:00
Robert Griesemer
1211c65e41 go/types: provide accessor to type arguments for instantiated types
Plus a couple of minor unrelated comment updates.

Change-Id: I38554c9ae9143172ea65da6c270fba10772c194b
2020-06-13 12:24:45 -07:00
Ian Lance Taylor
74ba054b38 go/go2go: start to handle inferred types
Also support for statements and inc/dec statements.

Change-Id: I9af474065d3b433f582422b739fc49ef266d2751
2020-06-13 12:24:45 -07:00
Robert Griesemer
e27cae74ec go/types: assertions/type switches on generic types are strict
Assertions/type switches that are guaranteed to fail on generic
types are not permitted (in contrast to regular type assertions
and type switches).

Change-Id: Iaa5b96f094585cb206fdadaa501445f96f26c166
2020-06-13 12:24:45 -07:00
Robert Griesemer
86b6990e9e go/types: implement type assertions and switches over generic types
Change-Id: I5e8debe3fee832e7829bcf2d451bde9bdc50a600
2020-06-13 12:24:45 -07:00
Ian Lance Taylor
fe586a7418 go/go2go, cmd/go2go: support importing Go2 packages
This support works for the top level test directory, but needs more
testing of "go tool go2go".

Change-Id: I01c4ce4a428535777b0fff1e6f8f39eee9005e04
2020-06-13 12:24:45 -07:00
Robert Griesemer
8578f6bfe6 go/types: address TODO (follow-up on previous commit)
Instead of rewriting the underlying AST for a receiver type in place,
explicitly pass the rewritten AST to Checker.collectParams.
Also, better comments in various places.

Change-Id: If64e80b2c6b4b57477a4a0bf87caaa2f4ea1bf21
2020-06-13 12:24:45 -07:00
Robert Griesemer
f7bc9d382f go/types: support blank identifiers for unused receiver type parameters
Change-Id: I5d7d359d7453f7ed949a7cab7b85419f8f4ee2a9
2020-06-13 12:24:45 -07:00
Robert Griesemer
08e2d11638 go/types: update NOTES
Missed with prior commit.

Change-Id: If111c8c6df6663199a23f8a1d2c147114f34ba6f
2020-06-13 12:24:45 -07:00
Robert Griesemer
86c2daf9e9 go/parser, go/types: permit parentheses around embedded contracts
For symmetry with embedding in structs and interfaces.
Fixed an incorrect error message print in the process.

Change-Id: I295685438a22971edc610e6c51cfefd286eaffba
2020-06-13 12:24:45 -07:00
Ian Lance Taylor
5cc90acd4b go/build: add go/go2go to pkgDeps
Change-Id: I43c131a910c372d849095160e6feb958da906e19
2020-06-13 12:24:45 -07:00
Robert Griesemer
6c083a7972 go/types: use correct package when creating a new instantiated type
Fix provided by iant@.

Change-Id: Iec89f007cfe9b9b50351122a03550e64238f9c44
2020-06-13 12:24:45 -07:00
Robert Griesemer
3d8c442870 go/parser, go/types: accept parameterized embedded struct fields
To be able to distinguish between a named field with a parenthesized
type `foo (T)` and an embedded parameterized type `foo(T)` in structs
we permit the use of parentheses in embedded types. For instance, the
latter example will need to be written as `(foo(T))`.

The parser now accepts any parenthesized embedded type liberally
and assumes that type-checking makes sure only permissible types
are accepted. As a result, parsing of field declarations is now
massively simpler. Also, removed an unused function.

The type-checker now complains about invalid embedded types (as
opposed to an invalid AST); it also now accepts embedded parameterized
types.

Change-Id: Ib8c6cbea9a0b739f66ba266fb5f8b71f91b7b64e
2020-06-13 12:24:45 -07:00
Robert Griesemer
38c2ef660d go/types: implement substMap and use it for substitutions
Instead of passing around a type parameter list and type arguments,
create a substitution map from them and use that map instead.

Change-Id: Ia4a041d95bfaa98888c9c06812d33b3d2a79227d
2020-06-13 12:24:44 -07:00
Robert Griesemer
72d320ec6e go/types: don't compute parameter list twice for regular generic functions (optimization)
Avoid a substitution operation for non-variadic generic functions.

Change-Id: Id40c0078a05be3aa53cd5b8551fa9fe6107bcda8
2020-06-13 12:24:44 -07:00
Robert Griesemer
99c8ae0d28 go/types: cleanup instantiation of function signatures
Make sure that a generic signature is not generic anymore
after instantiation. Update various related comments.

Change-Id: I2ac81037e570dc3a96c138b85529f3d86030776a
2020-06-13 12:24:44 -07:00
Robert Griesemer
3ab56f5ff2 go/types: minor adjustment to an error message and comments
Change-Id: Ie9505d508507c9ed764ec725df1027c92bae0702
2020-06-13 12:24:44 -07:00
Robert Griesemer
e70e49973e go/types: move method collection out of type declaration processing
Simplifies Checker.typeDecl. Also, methods can only be added to
top-level types; no need to try to collect them for local types.

Change-Id: I05b926df7ffa70c32c1dd5faed3c68617be8f270
2020-06-13 12:24:44 -07:00
Ian Lance Taylor
12a7da1eb0 go/go2go: add support for methods of parameterized types
Change-Id: I308eb692612cb8d6e7321c4972e90b102466b4c2
2020-06-13 12:24:44 -07:00
Robert Griesemer
1bcfb0add1 go/types: fix receiver type parameter inference
Make sure receiver type and actual receiver argument
match in "pointer-ness" before attempting to infer
any receiver type parameters.

Change-Id: Ie28004ce42ecef46e348424140b8d0c65e37cdaa
2020-06-13 12:24:44 -07:00
Robert Griesemer
5a2e660efa go/types: improved type strings for instantiated generic types
Better output for now, but the printing code is a hack and needs
a rethink and cleanup.

Change-Id: Ieb1f13a21645b48f9494ceda50f58017b31bbd82
2020-06-13 12:24:44 -07:00
Ian Lance Taylor
b1322d38b6 go/go2go: support parameterized types
Added an accessor function to go/types:

// TParams returns the type parameters of the named type t, or nil.
func (t *Named) TParams() []*TypeName { return t.tparams }

Change-Id: Ife2322c73dd6eaecaed42655a57a37541661d1ed
2020-06-13 12:24:44 -07:00
Ian Lance Taylor
f0d1b476a9 cmd/go2go: support "go2go translate a.go2 b.go2"
For the translate subcommand, support .go2 files as well as package names.
Creates a.go b.go.

Change-Id: Ica09ca447e7312dcec5fabbc68b365bc45d55ad5
2020-06-13 12:24:44 -07:00
Ian Lance Taylor
2687ed5586 go/go2go: simplify error handling in rewrite methods
Just store the error in the translator struct, rather than always
checking for an error and returning it up the stack.

Change-Id: I38ea2a282f61457eea123f852d9daf9337bcf9b8
2020-06-13 12:24:44 -07:00
Ian Lance Taylor
9ceb91ef5f go/go2go: cache type instantiations
Change-Id: Ie239e6ac7cfabf472970cd2aeddf337bcc242043
2020-06-13 12:24:44 -07:00
Ian Lance Taylor
a480c1b795 go/go2go, go/types: support recursive instantiation
Permit a generic function to call a generic function.

Change-Id: Ic41b87eb4effd0d5eb9a6a209c98354b306d5449
2020-06-13 12:24:44 -07:00
Ian Lance Taylor
8238ad0ab5 test, go/go2go: support .go2 files in test directory
Add an initial test.

Change-Id: If1bd6922eebf6881d3ac5d93731078fb9ca7b032
2020-06-13 12:24:44 -07:00
Ian Lance Taylor
a588cbcd8e go/go2go, go/types: preliminary support for rewriting and instantiation
Good enough to run this program:

package main

import "fmt"

func Print(type T)(s []T) {
	for _, v := range s {
		fmt.Println(v)
	}
}

func PrintInts(s []int) {
	Print(int)(s)
}

func main() {
	PrintInts([]int{1, 2})
}

Change-Id: I5ac205138085a63e7075b01ca2779b7eb71f9682
2020-06-13 12:24:44 -07:00
Ian Lance Taylor
10c3db1727 go/go2go: add line comments to rewritten files
Change-Id: I6fe3de668381d89131825ba00cc202f49c7971cf
2020-06-13 12:24:44 -07:00
Ian Lance Taylor
f95754ecff cmd/go2go, go/go2go: new framework for translating generics to Go
Adds a new command go2go, invocable after installation as "go tool go2go".
The go2go command supports build, test, run, and translate subcommands.
These will translate .go2 files to .go files.
No actual translation is done yet; the files are simply rewritten.
So this is a framework that works if the .go2 files are pure Go 1 code.

Change-Id: I8183fd276c4c87577c428794fb87e8dde1fa398d
2020-06-13 12:24:44 -07:00
Robert Griesemer
7ad6dd2e38 go/types: add testdata/todos.go2 for documenting unimplemented features
Also: Updated NOTES file.

Change-Id: I9f760693a486433d5a496d155627cad330630e90
2020-06-13 12:24:43 -07:00
Robert Griesemer
352c86eca2 go/types: better error messages for range clauses over generic values
Change-Id: I7b4ad2734aea5ab508b35ab526f0953b4f99c3f3
2020-06-13 12:02:35 -07:00
Robert Griesemer
2b265905e9 go/types: better comments for range stmt code
Change-Id: Id7ccf3f47b5ba9d8edd023675122d5f975b89905
2020-06-13 12:02:35 -07:00
Robert Griesemer
172f10b1e2 go/types: first cut at supporting range over generic variables
TODO
- some channel errors are not reported for generic variables
- error messages should be better

Change-Id: Ie388d6811b605645ea092481eee3a850c7ceb77b
2020-06-13 12:02:34 -07:00
Robert Griesemer
c8947e760e go/types: update README
Change-Id: I73eec3fa1ce247ae91e6acacfdd238a8314a3969
2020-06-13 12:02:34 -07:00
Robert Griesemer
4150c6a490 go/types: fix various issues with contract instantiation
Contract instantiation (= contracts with explicit type
arguments) should work now but has some implementation
restrictions:

- The type arguments provided to a contract must be
  type parameters from the type parameter list using
  the contract or the type parameter list of the en-
  closing contract (in case of contract embedding).

- Each type argument may be used at most once per
  contract expression.

Change-Id: Ia9f9d81e95d84f11ff3821b9f17b74eadab201f8
2020-06-13 12:02:34 -07:00
Robert Griesemer
203449cf09 go/internal/gccgoimporter: fix test
The typestring for embedded fields in structs was changed
by 8d30bd752d4 (type checking of function type parameters)
but this test was not updated.

Change-Id: I0d9438e3000939de09aa298c33ad1e9604a59fe8
2020-06-13 12:02:34 -07:00
Robert Griesemer
2ebcbd9efd go/printer: add missing test files
Change-Id: If5522bcf0f75a86b7aa36ed853a1349ad4a2a1f4
2020-06-13 12:02:34 -07:00
Robert Griesemer
ee164bc407 go/test: steps toward instantiated contracts (partially working)
See testdata/tmp.go for a test that shouldn't succeed.

Change-Id: Iefa738e0b6df6c3abe74670f8bc1d62a3e8c4e46
2020-06-13 12:02:34 -07:00
Robert Griesemer
5d80216f87 go/types: ensure a TypeParam always has a non-nil type bound
Plus minor cleanups.

Change-Id: I2508a576ad56d55fb188aa78c861afd0d032cf80
2020-06-13 12:02:34 -07:00
Robert Griesemer
3272b2b60b go/types: factor out contract expression handling
Change-Id: I499cce2abd6cf0647ea6c0aa5f93bbd513020518
2020-06-13 12:02:33 -07:00
Robert Griesemer
312a8ea57c go/types: initial code to handle instantiated contract expressions
New code not yet used. Snapshot.

Change-Id: Id3f9172d5ebd198d34b66707eaf429b791374ea1
2020-06-13 12:02:33 -07:00
Robert Griesemer
3c2505cae9 go/types: use Interface.is for generic variable indexing/len/cap (cleanup)
Interface.is already takes care of iterating through all types of
a generic type bound; use it instead of writing custom loops each
time.

Change-Id: Ie0f91b27e5a7b65ea85a8c3847a954db1e9f24fe
2020-06-13 12:02:33 -07:00
Robert Griesemer
1a2a175a8e go/types: implement indexing of generic types
Change-Id: I88a488d9d279b1029dd8086ea1befaa7b5733df6
2020-06-13 12:02:33 -07:00
Robert Griesemer
d2fce6bc64 go/types: implement len/cap for arguments of type paramater type
Change-Id: Ieeaa41573e5ec10df46ab25ec0a3563e3ae5b32b
2020-06-13 12:02:33 -07:00
Robert Griesemer
c49fde5b11 go/types: various comment improvments (cleanup)
Change-Id: I0763f7ef202f9dec11abd4f204ab950b86e0272c
2020-06-13 12:02:33 -07:00
Robert Griesemer
45dd45561e go/parser: better error recovery for (invalid) local contracts
Change-Id: I76b0d2af3767978ca138d899a083a6e399fea0fe
2020-06-13 12:02:33 -07:00
Robert Griesemer
b5ecc31064 go/parser, go/types: minor cleanups around type parameters
Change-Id: Ic2faf89a29193d1d50bb5bdccce0fda2301785ed
2020-06-13 12:02:33 -07:00
Robert Griesemer
2c0e53f518 go/parser, go/types: allow parenthesized embedded interfaces
This enables the distinction between a method M(int) and an
embedded instantiated (parameterized) interface (M(int)).

Change-Id: I150d1b1cd53a2b14ddc0ad6336d84078fcb41ad6
2020-06-13 12:02:33 -07:00
Robert Griesemer
9c75653a79 go/types: generalize/cleanup missingMethod to handle generic methods
This simplifies the use of missingMethod again but moving the lazy
instantiation of methods into missingMethod. Method comparison now
also takes method type paramaters into account.

This change enables the first examples of parameterized methods
to type-check.

Change-Id: I4c629fb7b1f8959184c6ce5196365893d11b197d
2020-06-13 12:02:33 -07:00
Robert Griesemer
3fd481043b go/types: must have at least one type when checking type list properties
Fixes bug with generic min being accepted even though the contract
or interface bound doesn't enumerate any types (or is missing).

Change-Id: Icdfc62fbd2b73ece397d5b5f1ebe27e52ed9b32f
2020-06-13 12:02:33 -07:00
Robert Griesemer
32c4c5a5f8 go/*: move TParams field into ast.FuncType and adjust dependencies
This step further consolidates all parameter types (except for the
receiver) in an ast.FuncType which now matches more closely the
representation of a types.Signature. As a result, fewer parameters
need to passed around because we can just use an *ast.FuncType or
a *types.Signature instead.

As an immediate (and implicit) consequence, parameterized interface
methods now type-check. (But we cannot yet "implement" them with a
matching concrete type.)

Change-Id: I2ea24694ade9838488625ffec48d5e98070d1006
2020-06-13 12:02:32 -07:00
Robert Griesemer
e3a0a7429a go/types: first steps towards parameterized methods
This is a generalization of type parameters to methods.
Being able to type-check them (even if we don't have an
idea how to actually implement such methods) is likely
going to inform the structure the type-checker: If the
code is organized correctly, the generalization should
mostly just work (and consist of the elimination of
extra checks).

So far, this first step only exposed some minor scoping
issues (where does the scope of type parameters start).

Change-Id: I8658ea8d1876a0ce9c62c0e9a7e943301e9cc19d
2020-06-13 12:02:32 -07:00
Robert Griesemer
464fb5c1e7 go/parser: allow method type parameters
Controlled via methodTypeParamsOk (internal flag).

Change-Id: I821a303f897f5a99ac42f667a3f592cbd1e98d0c
2020-06-13 12:02:32 -07:00
Robert Griesemer
a9c105c1d7 go/parser: use named consts rather than bools to control paramater parsing (cleanup)
Change-Id: I5d0638f4a9ad396c0203fc88ea93fcc38945f1b4
2020-06-13 12:02:32 -07:00
Robert Griesemer
bc236133bf go/types: implement interface embedding of interfaces with types
This follows the approach used for methods, but there is no error
reporting yet if a type is (explicitly) declared multiple times in
an interface.

Change-Id: I52428174ae278577a7c538b0817c6fb7af1c369e
2020-06-13 12:02:32 -07:00
Robert Griesemer
d4338964b3 go/types: implement contract embedding
Also:
- updated README
- rebased on master

Change-Id: Ieafcdd94460e02964350abc98651d0348d6521f9
2020-06-13 12:02:32 -07:00
Robert Griesemer
b6a8a0a86f go/types: first steps towards contract embedding
Incomplete but all the major steps are outlined now.

Change-Id: I05c0357072d8b2c9f85154d3dd14984d2134de62
2020-06-13 12:02:32 -07:00
Robert Griesemer
af12458327 go/types: always create a bound for each contract parameter
Also:
- simplify Contract struct
- rename some variables for more consistency

Change-Id: Icd10b47ac97d11870c6d4590c154b7efe158c134
2020-06-13 12:02:32 -07:00
Robert Griesemer
24cbbe5229 go/types: use function body scope for type and ordinary parameters
Change-Id: Iab3cf89125d9e13e1dff86710b313770a520a54a
2020-06-13 12:02:32 -07:00
Robert Griesemer
97251af9c4 go/types: move tparams field out of Func, clean up Signature
Type parameters are now collected as part of signature type
checking, as they are part of the type not the object. This
opens the door to more uniform handling of type parameters,
also for concrete methods and interface methods (future use).

Cleaned up confusion between Signature.mtparams and tparams:
tparams are explicitly declared function type parameters.
mtparams is gone and replaced with rparams which are the
receiver type parameters used in the function.

Various related cleanups.

Change-Id: Id8422b57cc8fbc18ffdca12a69d890aef83c3f80
2020-06-13 12:02:32 -07:00
Robert Griesemer
6e52291881 go/types: factor out type parameter list declaration
Including minor related cleanups.

Change-Id: I9d6f6ce6d2460fed10aa0818baa3f53b6f723b39
2020-06-13 12:02:32 -07:00
Robert Griesemer
2741fd2ea1 go/types: rewrite Checker.collectTypeParams (fix TODO)
Change-Id: Ie504606340d6ce52c1d5241ba13ec02043ba5400
2020-06-13 12:02:32 -07:00
Robert Griesemer
3d4810b5ba go/parser: remove vestiges for [type T] style type parameters
We're not going back to that notation.

Change-Id: Ic3d9b2c931525df60c00ed0ba0e43c20be5f7b43
2020-06-13 12:02:31 -07:00
Robert Griesemer
9090a73d10 go/types: updated NOTES and README files
Change-Id: Iea657febf7bf86f28116d9ac0fdf3c921d436b90
2020-06-13 12:02:31 -07:00
Robert Griesemer
53a8d66b5b go/types: temporary fix for subtle signature instantiation bug
A signature that's instantiated but doesn't have any incoming
or result (value) parameters doesn't get a copy automatically.
This leads to bugs because the instantiated signature doesn't
lose its type parameters when it should.

Make a copy outside for now, this fixes some (but not all cases)
and added test cases.

Also, factored out printing of type parameters in type printing.

Change-Id: I0ec3a4226c7473cddfb16704a2218992dd411593
2020-06-13 12:02:31 -07:00
Robert Griesemer
d45f7ef80d go/types: move tparams field out of TypeName and into Named
Type parameters are a property of the type, not the type name.

Change-Id: I479eafea80f9bfbd638e688ac0747cfa52df5da1
2020-06-13 12:02:31 -07:00
Robert Griesemer
1a93d0a2ca go/types: treat contract decl as declaration, not type
This change completes the prior change by adjusting the go/types
implementation accordingly. As a consequence, contracts may now
not occur in type context anymore and errors are reported if they
do.

With this change, all tests pass again.

Change-Id: Id984b3d24b7cb6ff2fceb74fd3c33fd0af91fdce
2020-06-13 12:02:31 -07:00
Robert Griesemer
3a40a4f856 go/ast, go/parser, go/printer: treat contract decl as declaration, not type (cleanup)
Progress snapshot.

This change makes a contract declaration a proper declaration (as it is
envisioned in the design draft). Specifically, contracts cannot be used
in type position anymore, and a contract declaration is not treated as
a type declaration with the type being a contract.

The change has not been pushed through go/types yet; this change will
temporarily brake go/types.

Change-Id: Ia4034caebab07dac449a02cdd362d6ce5d61c4a3
2020-06-13 12:02:31 -07:00
Robert Griesemer
bf01ee1864 go/types: update README
Change-Id: I9508ad449a82295ec2eb1a31c6932fcf8b42fee3
2020-06-13 12:02:31 -07:00
Robert Griesemer
ac0c4f1846 go/types: fix bug with generic function instantiation
Once a generic function is instantiated, it's not generic anymore.

Also: Added various additional test cases.

Change-Id: Ic2304b6c252cfdf41e526825dda64b8a77023d47
2020-06-13 12:02:31 -07:00
Robert Griesemer
edb963e7e9 go/types: fixed testdata/linalg.go2 example
The new lazy method substitution code seems to work. The bug was
in the test, not in the implementation!

Change-Id: I39794743a01e9725d57f49ccd7c3751376cd01d6
2020-06-13 12:02:31 -07:00
Robert Griesemer
a28b69c5d0 go/types: various attempts at lazy substitution of methods for lookups (snapshot)
When instantiating a type, we should also instantiate its methods (at least their
signatures) so that they have the correct type when being looked up. Unfortunately,
methods may not yet be type-checked; and worse, when we type-check them, typing
their receiver means instantiating that type again which would require updating
(= instantiating) the methods...

Instead, we keep the original list of methods (*Funcs) with each (named) type
and only update the method signatures when looking them up. The problem with this
approach is that we need to know with which values to substitute the method (i.e.,
receiver) type parameters, and this is currently not working.

Change-Id: Ie1835919dc8bfb8161a6a9e3d784c3bbbeb958c4
2020-06-13 12:02:31 -07:00
Robert Griesemer
cef8f5c6a4 go/types: move includeTypes function to a method of Interface (cleanup)
Change-Id: Ic3a4beaa279b6d6349136f5a9ff0447227cabb5a
2020-06-13 12:02:31 -07:00
Robert Griesemer
74d0d556d9 go/types: use named receiver type for contract methods
Change-Id: Ib82a8c41490d75ee80cd96fbf862412fdc5657c2
2020-06-13 12:02:30 -07:00
Robert Griesemer
609756301c go/types: updated NOTES
Change-Id: I65cbbb3aaeb1c364932b7e9ee8bdc7635ac41160
2020-06-13 12:02:30 -07:00
Robert Griesemer
960e15c183 go/types: print implementation type in tracing output of types
Change-Id: I9d48540413addaac4b2a6e2b821e9ef63e97c983
2020-06-13 12:02:30 -07:00
Robert Griesemer
118728b8c2 go/types: steps towards customization of methods in bounds checks (snapshot)
This CL introduces an update mechanism to customize method signatures
with the correct type parameters before comparing them for equality.
The mechanism is not correctly used, yet.

Change-Id: Ib88af88e151578a3fb3a648ed70d3f462a936c9b
2020-06-13 12:02:30 -07:00
Robert Griesemer
e1203396e7 go/types: updated README
This README can now be used as commit message.

Change-Id: I26d1e430d643868bd7e3d71ec585b8518ad47366
2020-06-13 12:02:30 -07:00
Robert Griesemer
29f795f511 go/types: implement conversions to generic types
Change-Id: Ifa878fddea3548a27579b3196921c6816f2d9363
2020-06-13 12:02:30 -07:00
Robert Griesemer
75897ab270 go/types: instantiate contracts when used as type bounds
Change-Id: I1b9ecf6007b485ca53096134fa875a9bf6fcfa73
2020-06-13 12:02:30 -07:00
Robert Griesemer
67b83f1382 go/types: represent type parameter bounds always as interfaces
When type-checking contracts, construct a parameterized named
interface for each of the contract parameters. Use those iterfaces
as type bounds for the type parameters.

This simplifies and cleans up the implementation.

Change-Id: I688e38542fa7fa83dd436439dd9ebe35af2f0458
2020-06-13 12:02:30 -07:00
Robert Griesemer
ed8d54fb3a go/types: added testdata/linalg.go2 to test suite, disabled some code
Context-specific customization of parameterized interface methods of
type parameter bounds is missing; as a result some of linalg.go2 fails.

Change-Id: I3e749ee040d2b3ae8f73ae26680984bc1b4b79ef
2020-06-13 12:02:30 -07:00
Robert Griesemer
2aeeba6836 go/types: set receiver type bounds for methods
Enable a few more tests that now work correctly.

Change-Id: I7efe91660c2896d4d8279b86831aa7de2ae7c0ad
2020-06-13 12:02:30 -07:00
Robert Griesemer
d49c915592 go/types: a type arg type list must be a subset of the type param type list
The original implementation (commit 65377ae6e0) checked the wrong way around.
Added more tests.

Change-Id: I59e1fd6d7e646f2e8e0ff68a0bbcf9ff9def0eff
2020-06-13 12:02:30 -07:00
Robert Griesemer
a30fb05aa2 go/types: substitute type parameters when checking type param. bounds
Change-Id: Ib97d1b3928629bc073b32fde48709369213a4bbb
2020-06-13 12:02:30 -07:00
Robert Griesemer
d941f3db1d go/types: remove satisfyContract - now implemented via instantiate
Change-Id: I1561d57709a996112b39aa8a15826387ea062e29
2020-06-13 12:02:29 -07:00
Robert Griesemer
6e1fbb8a53 go/types: factored writeTypeList, various minor cleanups, added test case
Change-Id: I971633c93099ab69466dc152e23aa9cf3ded50e0
2020-06-13 12:02:29 -07:00
Robert Griesemer
5504084423 go/types: implement type bound checking for type parameter type args
If the type argument is itself a type parameter, we must use that
type parameter's bound to check against the bound of the type
parameter matching the type argument.

Change-Id: If5128115a9fc10af8163c37b1f75645447ead766
2020-06-13 12:02:29 -07:00
Robert Griesemer
0de29c0b76 go/types: more cleanups around type instantiation
- type instantiations checks parameter count
- better positions for error messages
- removed some (now) dead code

Change-Id: Icf70642bbfd4e45a7762b002ea94704dc3d56475
2020-06-13 12:02:29 -07:00
Robert Griesemer
13893bbf9e go/types: type instantiation to verify type bounds
Change-Id: Ia4670a0d6bbabf4a1ac71410c7bfccc99ba61c9d
2020-06-13 12:02:29 -07:00
Robert Griesemer
3458c46de1 go/types: factor out/consolidate instantiate calls
Change-Id: I4973e0ebcd07d543b049f1fcdd8040f2ae214142
2020-06-13 12:02:29 -07:00
Robert Griesemer
be92a40c3f go/types: minor improvements in tracing output, removed some TODOs
Also: added failing test cases to NOTES

Change-Id: Ie7b823b4cc46c64068749676d7a1464082e60264
2020-06-13 12:02:29 -07:00
Robert Griesemer
57c8d7fe0a go/types: do not permit parenthesized uninstantiated generic types
Document the design decision.

Change-Id: Ied5d77bc576653b49edcde4cdb3f6b95623a9045
2020-06-13 12:02:29 -07:00
Robert Griesemer
fefe08cbea go/types: check that generic types are instantiated before use
This (temporarily) disables the use of recursively defined
generic types w/o repeating the type arguments, but such
type definitions need some more (type-checking) love anyway
before all conditions are checked.

Change-Id: I173f5ce2296b1c484ac95a3a887812c0b1f88245
2020-06-13 12:02:29 -07:00
Robert Griesemer
eacaaec439 go/types: add NOTES text file
To be used for better record keeping (design notes, observations,
bugs, TODOs, etc.).

Change-Id: Iaecf091dcd46f53ee55b97236bd0febd7c1d2b3d
2020-06-13 12:02:29 -07:00
Robert Griesemer
edc9611855 go/types: various minor fixes around interface type bounds
- print type bounds when printing function signatures
- store (named) tyep bound rather than underlying type
- first example using parameterized interface type bound working

Change-Id: Ic7110039d1e09838c8f33040e887e6a4f038d75d
2020-06-13 12:02:29 -07:00
Robert Griesemer
704beb3881 go/parser, go/types: parse/type-check interface (literal) type constraints
Accept (parse and type-check) parameterized interfaces with literal
type constraints, as in contracts. For instance, instead of

	contract C(T) {
		T add(T) T
		T int, string
	}

one can write

	type C(type T) interface {
		add(T) T
		type int, string
	}

Their use as type bounds still needs some work, though.

Change-Id: I9d59681dc0ba38054ee5627be141fc6e8a78381b
2020-06-13 12:02:28 -07:00
Robert Griesemer
6db0b6d33a go/parser, go/types: various minor fixes around printing and tracing
- set correct token position for ast.ContractType
- print "best effort" interface position in "complete interface" traces
- don't print trace output for types that are already set up
- print contract "signtature" when printing Contract type

Also: rebased on top of today's master branch

Change-Id: I6a528ce51a4152c25ad5d83ad52e01df8e89d283
2020-06-13 12:02:28 -07:00
Robert Griesemer
234ccd01f3 go/types: print contract type strings
Change-Id: Id698420124d526eb481659856705798bc5648b91
2020-06-13 12:02:28 -07:00
Robert Griesemer
4fa7fd828d go/types: fix type inference and method calls with parameterized receivers
This change expands type inference to parameterized named types
and clarifies handling of type parameters during type inference
(specifically, an inferred type may be a type parameter itself).

The change also implements method selectors with parameterized
receiver types by using type inference to deduce the receiver
type parameters.

Add more tests and enable many disabled tests that now work
correctly.

Change-Id: I8e10f9166fec9a8454f14b8fb089230c70422a1b
2020-06-13 12:02:28 -07:00
Robert Griesemer
1a0bc57392 go/types: removed instantiate call, renamed instantiate2 => instantiate
Also: added a currently failing test case to testdata/tmp.go2

Change-Id: I605bffb457e3b3979b42a642010215630c0544c6
2020-06-13 12:02:28 -07:00
Robert Griesemer
45eb8a74f0 go/types: added another example to examples/types.go2
Also: disabled aggressive rewriting of methods upon type instantiation

(Need to first figure out what we really need to do.)

Change-Id: I6fba78d60963534ebfe130164058ac1fbed7e5a3
2020-06-13 12:02:28 -07:00
Robert Griesemer
47ddbd09af go/types: added example to examples/types.go2
Change-Id: Ib2e5d28c48bc818e1c1a54ae4888bbab916b758a
2020-06-13 12:02:28 -07:00
Robert Griesemer
3e2c9743cb go/types: write TypeParam id's using subscript digits (fun)
Change-Id: I0df6e534774b2616f67c29a1525ddb40dbed9b05
2020-06-13 12:02:28 -07:00
Robert Griesemer
8c7ab48154 go/types: remove Parameterized type and related code
The need for the Parameterized type was eliminated by
the prior commit.

Change-Id: I8a2a2ae19ec5fef9292885fc7d23f8950d917e2f
2020-06-13 12:02:27 -07:00
Robert Griesemer
703974d608 go/types: rewrote instantiation of named types
A parameterized named type is in one of two states: not yet
instantiated, or instantiated. It may be instantiated with
any type, including (outer) type parameters. An instantiated
parameterized type may needs its type parameters substituted
if it is part of an enclosing type (or function) that is
instantiated.

A Named type has an extra field targs which is set to the
type arguments if the type is instantiated.

As a result, we don't need a representation for (partially)
instantiated parameterized types anymore: the Parameterized type
is now unused (but still present in the code).

Added a unique id field to TypeParam types so they can be
printed with a unique name. This permits the creation of a
unique type name for instantiated types which then can be used
for hashing that type name.

Also, made interfaces as type bounds work in more cases.

A handful of places (in testdata/map.go2, map2.go2) are broken
(commented out) and need investigation.

Change-Id: I137d352b419b2520eadde1b07f823375e0273dab
2020-06-13 12:02:27 -07:00
Robert Griesemer
46442bd4a9 go/parser: complain if type parameters are not permitted
Always accept them but complain if they are not permitted.
The analogous parser check was lost in a recent change.

Also: Fix index computation in collectTypeParams.

Change-Id: I7cb89944984df6dadd7f603b56f0c3941d60f7c5
2020-06-13 12:02:27 -07:00
Robert Griesemer
c47bad9a28 go/types: interfaces as type bounds starting to work
With various loose ends.

Change-Id: Idbcb4affc585f5bb14caa2045943a64a78d05d09
2020-06-13 12:02:27 -07:00
Robert Griesemer
51d599efa2 go/parser, go/types: steps towards accepting interfaces as type bounds
Also, rebased branch on top of master.

Change-Id: I758b19ae577a4554687b2206c016277c1ca21a45
2020-06-13 12:02:27 -07:00
Robert Griesemer
34f753b9d1 go/types: add testdata/linalg.go2 (not yet type-checked)
Also, added missing copyright notices in a few places.

Change-Id: Iaa39c10a1821a189cef604d2442e6f7ed7ac68a8
2020-06-13 12:02:27 -07:00
Robert Griesemer
660f7c38d1 go/types: first cut at supporting real/imag/complex with type parameters
Change-Id: Ic0dba1a5e758942a03d114df10cb5536cf432985
2020-06-13 12:02:27 -07:00
Robert Griesemer
e4a39e916f go/types: update README
Change-Id: I81e8304da885f36a2f6a41f6809063e74e87b0ea
2020-06-13 12:02:27 -07:00
Robert Griesemer
1bddb66b7c go/types: more operators supported by contracts
Change-Id: I03493508813d13dd1a16cd675de68170da14b29f
2020-06-13 12:02:27 -07:00
Robert Griesemer
cfbeecaabb go/types: first cut at type-checking type parameters with operators
- implemented for comparisons for now
- can type-check generic min
- also: rebased on top of Go tip

Change-Id: Id35582a59c4cddcb2b4ae9c7d7154ef8e41580ab
2020-06-13 12:02:27 -07:00
Robert Griesemer
dc4f9fb373 go/types: first steps towards collecting/recognizing type constraints
Change-Id: Ic0d70db24ad9fb76a5bb128df654c131f173247e
2020-06-13 12:02:27 -07:00
Robert Griesemer
7b6471a756 go/types: use new Checker.completeInterface when constructing Contracts
Change-Id: I1b54ddb7ac69541fcab1f17e0fe1574288a5b9b9
2020-06-13 12:02:27 -07:00
Robert Griesemer
0ac0b8518c go/types: add testdata/map2.go2, update README
Change-Id: I5a859fe3298998810ba56f3b445fae8e1d177995
2020-06-13 12:02:27 -07:00
Robert Griesemer
5891f8c720 go/types: add cycle detection to IsParameterized
Also: Recognize method expressions with parameterized receivers
and report an error for now (not implemented yet).

Change-Id: I96405b2b739d8e9fff6e9840347d3e78bfe8b6ec
2020-06-13 12:02:27 -07:00
Robert Griesemer
1f06612063 go/types: fix a bug with type instantiation
Change-Id: I977bb5525a40d0e17c27bbc01d7c77426e1bad00
2020-06-13 12:02:26 -07:00
Robert Griesemer
e73de77f33 go/types: some prep work for making import "chans" (testdata/map.go2) work
To make the import work, the import needs to be changed into
`import "./chan"`, the file testdata/chans.go2 needs to be
copies into a new directory testdata/chan and the file must
be renamed to chans.go.

But this exposes some problem with instantiating parameterized
types with other type parameters. Delaying this for now.

Change-Id: I1cd784fb89c2374131f3b1105493492eb0189abc
2020-06-13 12:02:26 -07:00
Robert Griesemer
fbff5cc915 go/types: fix collection of receiver type parameters
... and various related smaller fixes

We can now type-check the slices, chans, and maps
examples from the design doc (with the maps example
prodcing an error because importing chans doesn't
work yet). Progress!

Change-Id: Ifc00359a9a1cdad3bde1659a7de2028ac2544469
2020-06-13 12:02:26 -07:00
Robert Griesemer
3c6943daac go/types: more work on checking contract satisfaction
Change-Id: Ibe54e448603c685d714310ff83d4193150d47ebd
2020-06-13 12:02:26 -07:00
Robert Griesemer
b87cfd9558 go/types: more steps towards contract type checking
- moved type parameter collection out of resolver and into decl phase
- collect (meta-) type information (contracts) for type parameters
- first cut at checking contract satisfaction (methods only for now)

Change-Id: I46707969a172423738171aaea9d5282fb4b25a44
2020-06-13 12:02:26 -07:00
Robert Griesemer
590e4ea3f0 go/types: re-enable initial contract type checking
- collect contract methods in respective interfaces
- basic checking on contract type constraints

Contracts are not yet tested against or used to type check
function bodies.

Change-Id: I13b00c44524e599f92f1ba5b4b5d6734e2bf22e1
2020-06-13 12:02:26 -07:00
Robert Griesemer
628e3a2c6f go/printer: first steps towards printing type parameters and contracts
- type parameters can be printed
- empty contracts can be printed
- contract constraints are missing (only started)

Change-Id: I787898203aeb064b0b2ac49a7b858313cee5f45b
2020-06-13 12:02:26 -07:00
Robert Griesemer
a65d9b58a9 go/types: fix type inference bugs for untyped arguments
Change-Id: Ic98be8b102521090108d288514ee2cf016a7bb46
2020-06-13 12:02:26 -07:00
Robert Griesemer
d03ba9f74c go/types: fix a type instantiation issue, added slices.go2 example
Change-Id: If020572762039adf10973bccd072005084e17e4e
2020-06-13 12:02:26 -07:00
Robert Griesemer
c4a20af9f1 go/types: incorporate last-minute changes added for GopherCon
Change-Id: I8e1ff18f073ca47ef1a5d8ea43c8b6a3bc4d27b8
2020-06-13 12:02:26 -07:00
Robert Griesemer
d4272d0350 go/types: add examples/contracts.go2, extended examples/functions.go2
Change-Id: Icb1c0dfc6e752598a51d8039b5df77cde9a115ca
2020-06-13 12:02:26 -07:00
Robert Griesemer
0f7748af30 go/types: add examples directory
Also: fix substitution for cyclic types

Change-Id: I2d4eca6846c1ac9a2b4d0278246228e1f61aea08
2020-06-13 12:02:25 -07:00
Robert Griesemer
025f8ad924 go/types: add README describing the state of this prototype
Change-Id: I9c994be7600ed969064cf49e8edcbe431f1b7242
2020-06-13 12:02:25 -07:00
Robert Griesemer
e2ccf6356b go/types: initial steps towards customizing method signatures
Needs more work and tests.

Change-Id: Ic54e5798c374254d55b46cb582d7cf87efe125d1
2020-06-13 12:02:25 -07:00
Robert Griesemer
3663c91f3a go/types: unpack parameterized method receivers
Also: Print debug trace when running tests and -v is set.

Change-Id: I741377f82845d4713eebeb26706cb47b55afebd3
2020-06-13 12:02:25 -07:00
Robert Griesemer
be88be6e7a go/types: steps towards type-checking of methods with parameterized receivers
Change-Id: I80b4d4c248cb5e29933366322cca1d76c3ed5e23
2020-06-13 12:02:25 -07:00
Robert Griesemer
0ffe62a473 go/types: more fixes around parameterized types
Change-Id: I81e6e70a2833e7dbb17f5155386ed3c7a75dc2ac
2020-06-13 12:02:25 -07:00
Robert Griesemer
d5d25288d4 go/types: remove typemap again (incomplete and currently not used)
Change-Id: If7483716b2ea7f66ef9fe5311ce000a3b6212524
2020-06-13 12:02:25 -07:00
Robert Griesemer
38fa8c1e9b go/types: fix instantiated type name computation (for now)
This needs more work eventually.

Change-Id: I33fce18c454113620df9bb1db71a60b38b0a1306
2020-06-13 12:02:25 -07:00
Robert Griesemer
de712f2df8 go/types: implemented comparison of parameterized types; minor bug fixes
Also: Added -h flag to test framework; setting -h causes a panic when
an error is reported (for debugging).

Change-Id: Ib45d4ef38769f2ecdd3ce53fa3aed9fd99ef6bc8
2020-06-13 12:02:25 -07:00
Robert Griesemer
06ce58509d go/types: cleaned up parameterized type code a bit; enabled more tests
Change-Id: I579239f30f26e8a483c6f5dc379124d8a9eb4576
2020-06-13 12:02:25 -07:00
Robert Griesemer
2a76603101 go/types: fixed various issues in check.subst
Next known issue:

type List(type E) []E
var _ List(List(List(int))) = [](List(List(int))){}

This won't work because the RHS's composite literal type
is not fully instantiated - it has non-instantiated elements
which are ignored by Checker.instantiatedType. We could just
call Checker.subst w/o any parameters and have it walk the
incoming type and instantiate any element Parameterized types
but that is expensive and also appears to lead to stack over-
flow. Need to investigate.

Change-Id: I80bd09ab5f06e3991f198965424ce3322c7d6402
2020-06-13 12:02:25 -07:00
Robert Griesemer
b8b66e1708 go/types: make tests pass again
Disallow parametrized alias types again. They need a bit more work.

Change-Id: I90fd101a4c61f8693ee850c5dbd6849a60b85bdc
2020-06-13 12:02:24 -07:00
Robert Griesemer
52934f1b1e go/types: significant steps towards complete parametrized type instantiation
testdata/typeinst2.go has some complex examples that pass now.
But code elsewhere seems broken. go test has some issues at the
moment. Committing anyway to not lose the snapshot.

Change-Id: Id8f753a7b098405e2580a45ca1707ef6476c198e
2020-06-13 12:02:24 -07:00
Robert Griesemer
a76283d6e4 go/types: add primitive instantiated type map for canonicalization
Change-Id: I265105d483b6fdcee95f3770b9d6d774c1633638
2020-06-13 12:02:24 -07:00
Robert Griesemer
8142528bfd go/types: correctly substitute types when instantiating parametrized types
- use the right type when instantiating a type
- substitute defined types when underlying types are changing
- improved printing of parametrized types
- improved printing of instantiated types
- more top-level trace output

Change-Id: Ie8a65c9cc51e80925d3f580f54dcc6c0b5abe4c6
2020-06-13 12:02:24 -07:00
Robert Griesemer
fac6c330ac go/types: more steps towards type-checking instantiated types
Change-Id: Iab2dab932faad704fc7141f7afe04eb80597ec57
2020-06-13 12:02:24 -07:00
Robert Griesemer
e6f3c8a0b4 go/types: add missing test file
Change-Id: I36af54691bf757f78612549283e3eea1358dca0e
2020-06-13 12:02:24 -07:00
Robert Griesemer
fa30b485bc go/types: collect function type parameters during resolve phase
- move init and method parameter checks to resolve phase as well
- more consistent error messages
- more tests

Change-Id: I6cb147b35385541ca5d7d7e3f87159df84cced76
2020-06-13 12:02:24 -07:00
Robert Griesemer
db132013f4 go/types: collect type parameters of types and set up corresponding scopes
Change-Id: Ie63ffcdb8e3682b75f9863cea7987561772e6809
2020-06-13 12:02:24 -07:00
Robert Griesemer
aa0fabb90e go/types: prepare resolver for types with type parameters
Change-Id: If4395181b5683750098aefd5292a00921b3a5427
2020-06-13 12:02:24 -07:00
Robert Griesemer
7d54168ae9 go/types: add initial TypeMap implementation
Eventually we need this to avoid repeated instantiation
of generic types.

Change-Id: Idd9625dadfe67398d91121e73ef806576437a2f6
2020-06-13 12:02:24 -07:00
Robert Griesemer
e35f6184bd go/*: accept comma-separated list of types/methods in contracts
Updated go/ast and go/parser. go/types doesn't process the
new data structure yet and is missing a good type representation
of contracts.

Change-Id: I101f7c9e98008840dd1edb55404bb97db5a66ccd
2020-06-13 12:02:23 -07:00
Robert Griesemer
150704f738 go/types: implemented a few TODOs (minor progress) 2020-06-13 12:02:23 -07:00
Robert Griesemer
5ef7be9e7c go/types: more work on type-checking stand-alone contracts
Does not handle contract embedding yet.
2020-06-13 12:02:23 -07:00
Robert Griesemer
48d479685e go/*: added linalg.go2, renamed a couple of Go 2 tests to end in .go2 2020-06-13 12:02:23 -07:00
Robert Griesemer
5541826527 go/types: initial checking of type constraints, factored out contracts code 2020-06-13 12:02:23 -07:00
Robert Griesemer
e21d47f346 go/types: first steps toward type-checking individual contracts 2020-06-13 12:02:23 -07:00
Robert Griesemer
66b509a402 go/*: remove ast.TypeParamList in favor of ast.FieldList 2020-06-13 12:02:23 -07:00
Robert Griesemer
e3b54c8023 go/*: fix parsing of T(P){...} comp. literals and add .go2 tests
Additionally, simplify the syntax for contracts specified in a
type parameter list: It is now not possible to provide explicit
type parameters to a contract in a type parameter list - they
are always implicit. For instance

	func f(type P1, P2 C(P1, P2)) ...

must be written as

	func f(type P1, P2 C) ...

If a different order or different types are desired for C,
a new "intermediate" contract must be declared, as in

	contract C'(A, B) {
		C(B, int)  // here we allow type parameters
	}

	func f(type P1, P2 C')

This simplification will remove confusion if we decide to
allow individual contracts in type parameter lists, such as

	func f(type P C, P1, P2 C') ...

In this case, C accepts one type parameter (and applies to P),
and C' accepts two type parameters and applies to P1 and P2.

The simplification avoids questions such as whether this code
should be permitted:

	func f(type P C(P2), P1, P2 C'(P, P1)) ...

(i.e., can pass P2 to C, or P1 to C', etc.)
2020-06-13 12:02:23 -07:00
Robert Griesemer
6069527287 go/*: switch back to () parentheses, fill in various missing pieces
This change switches parsing back to using () parentheses for
type parameters. The parser now also accepts contracts in
parametrized type declarations, and top-level declared
contracts as defined in the design draft:

contract C(T1, T2) { ... }

(Internally, they are mapped to an ast.ContractType as before.)

Added more tests, incl. map.go2 from the design draft, and removed
some unused parser functions.

Passes parser and types tests.

Known issue: Composite literals with instantiated composite literal
types are not recognized properly: T(P){...} fails to parse.
2020-06-13 12:02:23 -07:00
Robert Griesemer
869c7a4e29 go/*: experiments with () and [] parentheses
This change implements parsing of contracts based on the
most recent design (using a combination of methods and
explicit basic types as well as the short-hand notations
0, 0.0, 0i, ==, and !=). At the moment, a contract is
considered a "type" and declared as such:

type C contract(T1, T2) { ...}

This change also implements parsing of type instantiations
and type parameters for type declarations, using both the
() parentheses and [] brackets (if the flag useBrackets is
set in parser.go).

Not all parsed data structures are set up correctly in the
AST yet. The parser and ast tests pass.

Change-Id: I11ce64ad49e404c5a66ce6623edc8313e803e135
2020-06-13 12:02:23 -07:00
Robert Griesemer
fd16d941dc go/*: type-checking of function type parameters
This change implements parsing and type-checking
of parametrized functions (without contracts).
Type-checking includes checking of generic function
calls using explicit type parameters as well as
implicit type parameters inferred from the actual
arguments.

Change-Id: I03c9c6912aa1e2ac79d9c5125fd5ac72df4e808a
2020-06-13 12:02:22 -07:00
112 changed files with 9560 additions and 18 deletions

46
README.go2go.md Normal file
View File

@@ -0,0 +1,46 @@
# dev.go2go branch
This branch provides an experimental go2go tool for testing the use of
the generics design draft.
This branch was published in 2020 and is no longer being maintained.
The [generics
proposal](https://go.googlesource.com/proposal/+/refs/heads/master/design/43651-type-parameters.md)
has [been accepted](https://golang.org/issue/43651) and development is
now focused on implementing the proposal in the ordinary Go tools.
## Original README
This branch contains a type checker and a translation tool for
experimentation with generics in Go.
This implements the [generics design draft](https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md).
You can build this branch [as
usual](https://golang.org/doc/install/source).
You can then use the new `go2go` tool.
Write your generic code in a file with the extension `.go2` instead of
`.go`.
Run it using `go tool go2go run x.go2`.
There are some sample packages in `cmd/go2go/testdata/go2path/src`.
You can see the full documentation for the tool by running `go doc
cmd/go2go`.
The `go2go` tool will look for `.go2` files using the environment variable `GO2PATH`.
You can find some useful packages that you might want to experiment with by
setting `GO2PATH=$GOROOT/src/cmd/go2go/testdata/go2path`.
If you find bugs in the updated type checker or in the translation
tool, they should be filed in the [standard Go issue
tracker](https://golang.org/issue).
Please start the issue title with `cmd/go2go`.
Note that the issue tracker should only be used for reporting bugs in
the tools, not for discussion of changes to the language.
Unlike typical dev branches, we do not intend any eventual merge of
this code into the master branch.
We will update it for bug fixes and change to the generic design
draft.
If a generics language proposal is accepted, it will be implemented in
the standard compiler, not via a translation tool.
The necessary changes to the go/* packages (go/ast, go/parser, and so
forth) may re-use code from this prototype but will follow the usual
code review process.

View File

@@ -1 +1,2 @@
branch: master
branch: dev.go2go
parent-branch: master

View File

@@ -0,0 +1,183 @@
This file serves as a notebook/implementation log.
----------------------------------------------------------------------------------------------------
TODO (implementation issues)
- report a better error when a type is not in a type list (investigate)
- better error message when we need parentheses around a parameterized function parameter type
- review handling of fields of instantiated generic types (do we need to make them non-parameterized,
similar to what we did for the embedded interfaces created by contract embedding?)
- use []*TypeParam for tparams in subst? (unclear)
- should we use nil instead of &emptyInterface for no type bounds (as an optimization)?
- TBD: in prose, should we use "generic" or "parameterized" (try to be consistent)
----------------------------------------------------------------------------------------------------
KNOWN ISSUES
- type parameter constraints are ignored when checking if a parameterized method implements the
matching method in an interface
- iteration over generic variables doesn't report certain channel errors (see TODOs in code)
- cannot handle mutually recursive parameterized interfaces using themselves as type bounds
example: type B(type P B(P)) interface{ m() } (need to delay all checking after seting up declarations)
- invoking a method of a parameterized embedded type doesn't work (cannot properly determine receiver yet)
- pointer designation is incorrectly handled when checking type list constraint satisfaction
----------------------------------------------------------------------------------------------------
OBSERVATIONS
- 2/20/2020: Because we permit parenthesized types anywhere for consistency, also in parameter lists (mea
culpa), we have parsing ambiguities when using instantiated types in parameter lists w/o argument names.
We could disallow the use of parentheses at the top level of type literals and then we might not have
this problem. This is not a backward-compatible change but perhaps worthwhile investigating. Specifically,
will this always work (look specifically at channel types where we need parentheses for disambiguation
and possibly function types). File a proposal?
- 6/3/2020: Observation: gofmt already removes superflous parentheses around types in parameter lists,
so in gofmt'ed code there won't be any such parentheses. Thus we can perhaps make the suggested language
change above without too many problems.
- 2/21/2020: We do need top-level parentheses around types in certain situations such as conversions
or composite literals. We could disallow parentheses around types in parameter lists only, but that
seems quite a bit less elegant.
- 6/13/2020: When comparing against the type list of an interface (to see if the interface is satisfied),
we must either recompute the underlying types of the type list entries after the interface was instantiated,
or we must compute the underlying type of each entry before comparing. (A type list may contain type
parameters which may be substituted with defined types when the interface is instantiated.) With the
latter approach (which is what's implemented now), we could relax some of the constraints that we have
on type lists entries: We could allow any type and just say that for interface satisfaction we always
look at the underlying types.
----------------------------------------------------------------------------------------------------
OPEN QUESTIONS
- Parsing _ = [](a(int)){} requires parentheses around `(a(int))` - should the parser be smarter in
these cases? Another example: []a(b, c){} This cannot be a conversion. Could fix such cases by re-
associating the AST when we see a {. Need to be careful, and need to take into account additional
complexity of spec.
- For len/cap(x) where x is of type parameter type and the bound contains arrays only, should the
result be a constant? (right now it is not). What are the implications for alternative, non-
monomorphizing implementation methods?
- Confirm that it's ok to use inference in missingMethod to compare parameterized methods.
----------------------------------------------------------------------------------------------------
DESIGN/IMPLEMENTATION
- 11/19/2019: For type parameters with interface bounds to work, the scope of all type parameters in
a type parameter list starts at the "type" keyword. This makes all type parameters visible for all
type parameter bounds (interfaces that may be parameterized with the type parameters).
- 12/4/2019: do not allow parenthesized generic uninstantiated types (unless instantiated implicitly)
In other words: generic types must always be instantiated before they can be used in any form
More generally: Only permit type instantiation T(x) in type context, when the type is a named type.
Do not permit it in general in type context: e.g., disallow []T(x) because we consider that a
conversion, in general. Same for ([]T)(x).
- 12/12/2019: represent type bounds always as (possibly unnamed) interfaces
(contracts are user syntactic sugar)
- 12/19/2019: Type parameters don't act like type aliases. For instance:
func f(type T1, T2)(x T1) T2 { return x }
is not valid, no matter how T1 and T2 are instantiated (but if T1 and T2 were type aliases with
both of them having type int, the return x would be valid). In fact, the type parameters act more
like named types with the methods described by their type bound. But type parameters are never
interfaces. To determine: Given a type parameter P, is P == underlying(P) (like for basic types),
or is the the underlying type of P something else (like for defined types). Is there an observable
difference?
- 12/19/2019: Rewrote contract handling: they are now treated as Objects (rather than Types) throughout.
- 12/20/2019: Decided to start moving type parameters to types (from TypeName to Named), need to do the
same for Func. This make more sense as in general any type (conceptually even literal types) could
have type parameters. It's a property of the type, not the type name. It also simplified the code.
- 12/20/2019: Type parameters may be part of type lists in contracts/interfaces. It just falls out
naturally. Added test cases.
- 12/23/2019: Decision: Type parameters and ordinary (value) parameters are in the same block, notably
the function block. The scope of type parameters starts at the 'type' keyword; the scope of ordinary
parameters starts with the (opening '{' of the) function body. Both scopes end with the closing '}'
of the function body (i.e., the end of the function block).
- 1/2/2020: Implementation decision: contracts can only be declared at the package level.
- 1/6/2020: Experimental: First steps towards permitting type parameters in methods as a generalization.
Type-checking problems ooccurring from this are likely to highlight general problematic areas.
First consequence: Scope of type parameters starts at "func" keyword which means that receiver type
name cannot be a type parameter name declared later (or by the receiver type specification). This
seems reasonable and should help avoid confusion which is possible otherwise.
- 1/7/2020: We distinguish embedded instantiated (parameterized) interfaces from methods by enclosing
the embedded interfaces in parentheses (the design draft recommends this change). Since this opens
the possibility for any parenthesized type (that is an interface), we can also allow (parenthesized)
interface literals as it is simpler to permit those than forbid them.
- 1/7/2020: The current implementation permits empty type parameter lists as in: "func f(type)(x int)"
but we cannot call such a function as "f()(1)"; the empty type argument list causes problems.
Document that we allow empty type parameter list declarations, but not empty actual type parameter
lists. (We could allow them for types, but that doesn't seem consistent and probably is confusing).
- 2/19/2020: We accept parenthesized embedded struct fields so we can distinguish between a named
field with a parenthesized type foo (T) and an embedded parameterized type (foo(T)), similarly
to interace embedding.
- 2/19/2020: Permit parentheses around embedded contracts for symmetry with embedding in structs
and interfaces.
- 2/20/2020: Receiver type parameters must always be provided in the receiver parameter list of
a method, even if they are not used by the method. Since the receiver acts like an implicit
declaration of those type parameters, they may be blank, as with any other declaration.
- 3/20/2020: Local type declarations with an underlying type that is a type parameter lose the
methods declared with the type parameter bound. But they don't lose the properties of the
underlying type, i.e., the properties of the type parameter bound's type list.
This is something to consider if we were contemplating moving to a methods-only approach
(no type lists), even though local type declarations are exceedingly rare if they exist at
all in the wild.
- 3/24/2020: Implemented initial support for bidirection type unification which could make
type inference more powerful if we decided to go that route. Specifically, this would
permit type inference for the type parameters of a generic function argument. Given:
func h(f func(int)); func g(type T)(T); one could allow the call: h(g) and the type argument
T of g would be inferred to be int. While not hard to implement, this would be a special case
of the rule that all generic types/functions must be instantiated before they are used except
for function calls where the type arguments can be inferred from the actual arguments.
Decided that for now we leave things as is, since it's not clear the extra complexity is
worth the (probably small) convenience.
- 3/25/2020: We can probably simplify the contract syntax again and only permit one of three
possible constraint entries: 1) an embedded contract, 2) a type parameter followed by a
method signature, and 3) a type parameter followed by a type list. This is what the type
checker currently supports and the printer can print. (The parser still accepts a list of
method signatures or types, freely mixed.)
- 4/24/2020: Permit omission of explicit type bound instantiation if the type bound is an
interface that applies to exactly one type parameter and the type bound expects exactly
one type argument. This makes parameterized interface type bounds easier to use in a common
case.
- 5/?/2020: Relaxed above syntactic sugar and permit omission of explicit type bound instantiation
in any case where the type bound only accepts a single type parameter.
We may not want to permit this in the first version as this is something we can always add later.
- 6/3/2020: A function type parameter acts like a named type. If its type bound has a type list
that type list determines the underlying type of the type parameter. If the bound doesn't have
a type list, the underlying type of a type parameter is itself. (We may decide that in this
latter case there may no underlying type at all which would perhaps more consistent. But this
is not clear cut.)
- 6/6/2020: The underlying type of a type parameter must _always_ be itself, otherwise a declaration
such as: type T(type P interface{type int}) P would have an underlying type int which is wrong.
- 6/7/2020: Introduced the notion of an operational type which is used when determining what
operations are supported by a value of a given type. The operational type of a type parameter
is determined by its type bound. The operational type of any other type is its underlying
type. This approach appears to complete the picture about the nature of type parameters.
- 6/7/2020: Removed support for contracts to match the latest design draft.
- 6/15/2020: Disabled check that types in type lists must only contain basic types or composite types
composed of basic types. It is not needed since we always must recompute the underlying types
after a (possible) instantiation anyway (see observation from 6/3/2020).

View File

@@ -0,0 +1,68 @@
This version of go/types is part of the prototype that implements the
extended Go language as outlined by the latest generics draft design.
DISCLAIMER
This code is based on the std/library's go/types package but it has
been modified heavily. Please bear in mind that:
- This is a prototype. Expect bugs, incomplete parts, and suboptimal
and (gulp) possibly ugly code.
- While all the major aspects of the generics design draft have been
implemented, parts are missing, especially around the operations permitted
on operands of generic types. In such cases, the result is most often
an error reporting that a certain operation is not permitted even though
it should be according to the draft design.
- As prototyping continues, expect refinement and possibly divergence
from the most recent draft design published.
EXAMPLE CODE
For tests and example code (with detailed comments) look for files
with suffix .go2 in the testdata and examples subdirectories.
(The suffix .go2 is solely to distinguish them from regular Go code and
to prevent gofmt from touching them. We expect a proper implementation to
keep using .go .)
RUNNING THE TYPE-CHECKER
The type-checker is automatically run as part of the go2go tool.
To experiment with generic code, it is recommened to use that tool.
But the type-checker can also be run stand-alone on source code if
so desired. There are two primary ways:
1) By building the gotype tool in this source directory:
go build gotype.go
and then running the resulting binary on some input files
./gotype <package files>
(Make sure to use the correct go tool when building.)
2) By using the type-checker's TestCheck test function which
accepts a list of user provided files:
go test -run Check$ -errlist -files <package files>
For instance:
go test -run Check$ -files examples/types.go2
TestCheck will match any type errors against ERROR comments
in the source files and complain about discrepancies.
To report the errors instead, use:
go test -run Check$ -errlist -files examples/types.go2
To see a trace of the type checker progress, use the -v flag:
go test -v -run Check$ -errlist -files examples/types.go2
(When playing with this code, sometimes go vet gets in the
way, so it can be helpful to also provide -vet off.)

71
src/cmd/go2go/doc.go Normal file
View File

@@ -0,0 +1,71 @@
// Copyright 2020 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.
// go2go is a command for trying out generic Go code.
// It supports a small number of commands similar to cmd/go.
//
// This tool was intended for experimental use during the development
// of the generics proposal, and is no longer maintained.
//
// Usage:
//
// go2go [options] <command> [go2go flags] [arguments]
//
// Commands:
//
// build translate and then run "go build packages"
// run translate and then run a list of files
// test translate and then run "go test packages"
// translate translate .go2 files into .go files for listed packages
//
// A package is expected to contain .go2 files but no .go files.
//
// Non-local imported packages will be first looked up using the GO2PATH
// environment variable, which should point to a GOPATH-like directory.
// For example, import "x" will first look for GO2PATHDIR/src/x,
// for each colon-separated component in GO2PATH. If not found in GO2PATH,
// imports will be looked up in the usual way. If an import includes
// .go2 files, they will be translated into .go files.
//
// The go2go flags are shared by the build, run, test, and translate commands:
//
// -tags tag,list
// a comma-separated list of build tags to consider satisfied during the
// build. For more information about build tags, see the description of
// build constraints in the documentation for the go/build package.
//
// There is a sample GO2PATH in cmd/go2go/testdata/go2path. It provides
// several packages that serve as examples of using generics, and may
// be useful in experimenting with your own generic code.
//
// Translation into standard Go requires generating Go code with mangled names.
// The mangled names will always include Odia (Oriya) digits, such as and ୮.
// Do not use Oriya digits in identifiers in your own code.
//
// Because this tool generates Go files, and because instantiated types
// and functions need to refer to the types with which they are instantiated,
// using function-local types as type arguments is not supported.
// Similarly, function-local parameterized types do not work.
// These are deficiencies of the tool, they will work as expected in
// any complete implementation.
//
// Similarly, generic function and type bodies that refer to unexported,
// non-generic, names can't be instantiated by different packages.
//
// Because this tool generates Go files, and because it generates type
// and function instantiations alongside other code in the package that
// instantiates those functions and types, and because those instantiatations
// may refer to names in packages imported by the original generic code,
// this tool will add imports as necessary to support the instantiations.
// Therefore, packages that use generic code must not use top level
// definitions whose names are the same as the names of packages imported
// by the generic code. For example, don't write, in package scope,
//
// var strings = []string{"a", "b"}
//
// because if the generic code imports "strings", the variable name will
// conflict with the package name, even if your code doesn't import "strings".
// This is a deficiency of the tool, it will not be a deficiency in
// any complete implementation.
package main

386
src/cmd/go2go/go2go_test.go Normal file
View File

@@ -0,0 +1,386 @@
// Copyright 2020 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_test
import (
"fmt"
"internal/testenv"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"reflect"
"runtime"
"sort"
"strings"
"sync"
"testing"
)
func TestMain(m *testing.M) {
os.Exit(testMain(m))
}
func testMain(m *testing.M) int {
dir, err := ioutil.TempDir("", "go2gotest")
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
defer os.RemoveAll(dir)
testTempDir = dir
return m.Run()
}
// testTempDir is a temporary directory the tests can use.
var testTempDir string
// testGo2go is the version of cmd/go2go run by the tests.
var testGo2go string
// testGo2goOnce ensures that testGo2go is built only once.
var testGo2goOnce sync.Once
// testGo2goErr is an error that occurred when building testGo2go.
// In the normal case this is nil.
var testGo2goErr error
// buildGo2go builds an up-to-date version of cmd/go2go.
// This is not run from TestMain because it's simpler if it has a *testing.T.
func buildGo2go(t *testing.T) {
t.Helper()
testenv.MustHaveGoBuild(t)
testGo2goOnce.Do(func() {
testGo2go = filepath.Join(testTempDir, "go2go.exe")
t.Logf("running [go build -o %s]", testGo2go)
out, err := exec.Command(testenv.GoToolPath(t), "build", "-o", testGo2go).CombinedOutput()
if len(out) > 0 {
t.Logf("%s", out)
}
testGo2goErr = err
})
if testGo2goErr != nil {
t.Fatal("failed to build testgo2go program:", testGo2goErr)
}
}
func TestGO2PATH(t *testing.T) {
t.Parallel()
buildGo2go(t)
copyFile := func(path string, info os.FileInfo, err error) error {
if err != nil {
t.Fatal(err)
}
newPath := filepath.Join(testTempDir, path)
if info.IsDir() {
if err := os.MkdirAll(newPath, 0o755); err != nil {
t.Fatal(err)
}
return nil
}
data, err := ioutil.ReadFile(path)
if err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(newPath, data, 0o444); err != nil {
t.Fatal(err)
}
return nil
}
if err := filepath.Walk("testdata/go2path/src", copyFile); err != nil {
t.Fatal(err)
}
d, err := os.Open(filepath.Join(testTempDir, "testdata/go2path/src"))
if err != nil {
t.Fatal(err)
}
defer d.Close()
dirs, err := d.Readdirnames(-1)
if err != nil {
t.Fatal(err)
}
sort.Strings(dirs)
for _, dir := range dirs {
t.Run(dir, func(t *testing.T) {
cmd := exec.Command(testGo2go, "test")
cmd.Dir = filepath.Join(testTempDir, "testdata", "go2path", "src", dir)
cmd.Env = append(os.Environ(), "GO2PATH="+filepath.Join(testTempDir, "testdata", "go2path"))
t.Logf("running [%s test] in %s", testGo2go, cmd.Dir)
out, err := cmd.CombinedOutput()
if len(out) > 0 {
t.Log(dir)
t.Logf("%s", out)
}
if err != nil {
t.Errorf("error testing %s: %v", dir, err)
}
})
}
}
type testFile struct {
name, contents string
}
type testFiles []testFile
func (tfs testFiles) create(t *testing.T, gopath string) {
t.Helper()
for _, tf := range tfs {
fn := filepath.Join(gopath, "src", tf.name)
if err := os.MkdirAll(filepath.Dir(fn), 0o755); err != nil {
t.Fatal(err)
}
if err := ioutil.WriteFile(fn, []byte(tf.contents), 0o444); err != nil {
t.Fatal(err)
}
}
}
func TestGO2PATHEqGOPATH(t *testing.T) {
t.Parallel()
buildGo2go(t)
gopath := t.TempDir()
testFiles{
{
"pkg/p.go",
`package pkg; func F() {}`,
},
{
"cmd/cmd.go2",
`package main; import "pkg"; func main() { pkg.F() }`,
},
}.create(t, gopath)
t.Log("go2go build")
cmdDir := filepath.Join(gopath, "src", "cmd")
cmd := exec.Command(testGo2go, "build")
cmd.Dir = cmdDir
cmd.Env = append(os.Environ(),
"GOPATH="+gopath,
"GO2PATH="+gopath,
"GO111MODULE=off",
)
out, err := cmd.CombinedOutput()
if len(out) > 0 {
t.Logf("%s", out)
}
if err != nil {
t.Fatalf(`error running "go2go build": %v`, err)
}
t.Log("./cmd")
cmdName := "./cmd"
if runtime.GOOS == "windows" {
cmdName += ".exe"
}
cmd = exec.Command(cmdName)
cmd.Dir = cmdDir
out, err = cmd.CombinedOutput()
if err != nil {
t.Fatalf("error running %q: %v", cmdName, err)
}
if len(out) != 0 {
t.Errorf("unexpected output: %q", out)
}
}
const buildSource = `
package main
import "fmt"
func PrintSlice[Elem any](s []Elem) {
for _, v := range s {
fmt.Println(v)
}
}
func main() {
PrintSlice([]string{"hello", "world"})
}
`
func TestBuild(t *testing.T) {
t.Parallel()
buildGo2go(t)
gopath := t.TempDir()
testFiles{
{
"hello/hello.go2",
buildSource,
},
}.create(t, gopath)
t.Log("go2go build")
dir := filepath.Join(gopath, "src", "hello")
cmd := exec.Command(testGo2go, "build")
cmd.Dir = dir
out, err := cmd.CombinedOutput()
if len(out) > 0 {
t.Logf("%s", out)
}
if err != nil {
t.Fatalf(`error running "go2go build": %v`, err)
}
runHello(t, dir)
}
func runHello(t *testing.T, dir string) {
cmdName := "./hello"
if runtime.GOOS == "windows" {
cmdName += ".exe"
}
cmd := exec.Command(cmdName)
cmd.Dir = dir
out, err := cmd.CombinedOutput()
t.Log("./hello")
if len(out) > 0 {
t.Logf("%s", out)
}
if err != nil {
t.Fatalf("error running hello: %v", err)
}
got := strings.Split(strings.TrimSpace(string(out)), "\n")
want := []string{"hello", "world"}
if !reflect.DeepEqual(got, want) {
t.Errorf("hello output %v, want %v", got, want)
}
}
func TestBuildPackage(t *testing.T) {
t.Parallel()
buildGo2go(t)
gopath := t.TempDir()
testFiles{
{
"cmd/hello/hello.go2",
buildSource,
},
}.create(t, gopath)
t.Log("go2go build")
cmd := exec.Command(testGo2go, "build", "cmd/hello")
cmd.Dir = gopath
cmd.Env = append(os.Environ(),
"GO2PATH="+gopath,
)
out, err := cmd.CombinedOutput()
if len(out) > 0 {
t.Logf("%s", out)
}
if err != nil {
t.Fatalf(`error running "go2go build": %v`, err)
}
runHello(t, gopath)
}
func TestTransitiveGo1(t *testing.T) {
t.Parallel()
buildGo2go(t)
gopath := t.TempDir()
testFiles{
{
"a/a.go2",
`package a; func ident[T any](v T) T { return v }; func F1(v int) int { return ident(v) }`,
},
{
"b/b.go",
`package b; import "a"; func F2(v int) int { return a.F1(v) }`,
},
{
"c/c.go2",
`package main; import ("fmt"; "b"); func main() { fmt.Println(b.F2(42)) }`,
},
}.create(t, gopath)
t.Log("go2go build")
cmd := exec.Command(testGo2go, "build", "c")
cmd.Dir = gopath
cmd.Env = append(os.Environ(),
"GO2PATH="+gopath,
)
out, err := cmd.CombinedOutput()
if len(out) > 0 {
t.Logf("%s", out)
}
if err != nil {
t.Fatalf(`error running "go2go build": %v`, err)
}
}
func TestBuildWithTags(t *testing.T) {
t.Parallel()
buildGo2go(t)
gopath := t.TempDir()
testFiles{
{
"a/a.go2",
`package a; func ident[T any](v T) T { return v }; func F1(s string) string { return ident(s) }`,
},
{
"b/b_appengine.go",
`// +build appengine
package b; import "a"; func F2(s string) string { return a.F1(s) + " App Engine!" }`,
},
{
"b/b.go",
`// +build !appengine
package b; import "a"; func F2(s string) string { return a.F1(s) + " World!" }`,
},
{
"c/c.go2",
`package main; import ("fmt"; "b"); func main() { fmt.Println(b.F2("Hello")) }`,
},
}.create(t, gopath)
t.Log("go2go build")
cmd := exec.Command(testGo2go, "build", "-tags=appengine", "c")
cmd.Dir = gopath
cmd.Env = append(os.Environ(),
"GO2PATH="+gopath,
)
out, err := cmd.CombinedOutput()
if len(out) > 0 {
t.Logf("%s", out)
}
if err != nil {
t.Fatalf(`error running "go2go build": %v`, err)
}
cmdName := "./c"
if runtime.GOOS == "windows" {
cmdName += ".exe"
}
cmd = exec.Command(cmdName)
cmd.Dir = gopath
out, err = cmd.CombinedOutput()
t.Log("./c")
if len(out) > 0 {
t.Logf("%s", out)
}
if err != nil {
t.Fatalf("error running c: %v", err)
}
got := strings.Split(strings.TrimSpace(string(out)), "\n")[0]
want := "Hello App Engine!"
if !reflect.DeepEqual(got, want) {
t.Errorf("c output %v, want %v", got, want)
}
}

224
src/cmd/go2go/main.go Normal file
View File

@@ -0,0 +1,224 @@
// Copyright 2020 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 (
"flag"
"fmt"
"go/go2go"
"io/ioutil"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
var gotool = filepath.Join(runtime.GOROOT(), "bin", "go")
var cmds = map[string]bool{
"build": true,
"run": true,
"test": true,
"translate": true,
}
// tagsFlag is the implementation of the -tags flag.
type tagsFlag []string
var buildTags tagsFlag
func (v *tagsFlag) Set(s string) error {
// Split on commas, ignore empty strings.
*v = []string{}
for _, s := range strings.Split(s, ",") {
if s != "" {
*v = append(*v, s)
}
}
return nil
}
func (v *tagsFlag) String() string {
return strings.Join(*v, ",")
}
func main() {
flag.Usage = usage
flag.Parse()
args := flag.Args()
if len(args) < 1 {
usage()
}
if !cmds[args[0]] {
usage()
}
cmd := args[0]
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.Var((*tagsFlag)(&buildTags), "tags", "tag,list")
fs.Parse(args[1:])
args = fs.Args()
importerTmpdir, err := ioutil.TempDir("", "go2go")
if err != nil {
log.Fatal(err)
}
defer os.RemoveAll(importerTmpdir)
importer := go2go.NewImporter(importerTmpdir)
if len(buildTags) > 0 {
importer.SetTags(buildTags)
}
var rundir string
if cmd == "run" {
tmpdir := copyToTmpdir(args)
defer os.RemoveAll(tmpdir)
translate(importer, tmpdir)
var nargs []string
for _, arg := range args {
base := filepath.Base(arg)
f := strings.TrimSuffix(base, ".go2") + ".go"
nargs = append(nargs, f)
}
args = nargs
rundir = tmpdir
} else if cmd == "translate" && isGo2Files(args...) {
for _, arg := range args {
translateFile(importer, arg)
}
} else {
for _, dir := range expandPackages(args) {
translate(importer, dir)
}
}
if cmd != "translate" {
if len(buildTags) > 0 {
args = append([]string{
fmt.Sprintf("-tags=%s", strings.Join(buildTags, ",")),
}, args...)
}
args = append([]string{cmd}, args...)
cmd := exec.Command(gotool, args...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
cmd.Dir = rundir
gopath := importerTmpdir
if go2path := os.Getenv("GO2PATH"); go2path != "" {
gopath += string(os.PathListSeparator) + go2path
}
if oldGopath := os.Getenv("GOPATH"); oldGopath != "" {
gopath += string(os.PathListSeparator) + oldGopath
}
cmd.Env = append(os.Environ(),
"GOPATH="+gopath,
"GO111MODULE=off",
)
if err := cmd.Run(); err != nil {
die(fmt.Sprintf("%s %v failed: %v", gotool, args, err))
}
}
}
// isGo2Files reports whether the arguments are a list of .go2 files.
func isGo2Files(args ...string) bool {
for _, arg := range args {
if filepath.Ext(arg) != ".go2" {
return false
}
}
return true
}
// expandPackages returns a list of directories expanded from packages.
func expandPackages(pkgs []string) []string {
if len(pkgs) == 0 {
return []string{"."}
}
go2path := os.Getenv("GO2PATH")
var dirs []string
pkgloop:
for _, pkg := range pkgs {
if go2path != "" {
for _, pd := range strings.Split(go2path, string(os.PathListSeparator)) {
d := filepath.Join(pd, "src", pkg)
if fi, err := os.Stat(d); err == nil && fi.IsDir() {
dirs = append(dirs, d)
continue pkgloop
}
}
}
cmd := exec.Command(gotool, "list", "-f", "{{.Dir}}", pkg)
cmd.Stderr = os.Stderr
if go2path != "" {
gopath := go2path
if oldGopath := os.Getenv("GOPATH"); oldGopath != "" {
gopath += string(os.PathListSeparator) + oldGopath
}
cmd.Env = append(os.Environ(),
"GOPATH="+gopath,
"GO111MODULE=off",
)
}
out, err := cmd.Output()
if err != nil {
die(fmt.Sprintf("%s list %q failed: %v", gotool, pkg, err))
}
dirs = append(dirs, strings.Split(string(out), "\n")...)
}
return dirs
}
// copyToTmpdir copies files into a temporary directory.
func copyToTmpdir(files []string) string {
if len(files) == 0 {
die("no files to run")
}
tmpdir, err := ioutil.TempDir("", "go2go-run")
if err != nil {
die(err.Error())
}
for _, file := range files {
data, err := ioutil.ReadFile(file)
if err != nil {
die(err.Error())
}
if err := ioutil.WriteFile(filepath.Join(tmpdir, filepath.Base(file)), data, 0444); err != nil {
die(err.Error())
}
}
return tmpdir
}
// usage reports a usage message and exits with failure.
func usage() {
fmt.Fprint(os.Stderr, `Usage: go2go <command> [arguments]
The commands are:
build translate and build packages
run translate and run list of files
test translate and test packages
translate translate .go2 files into .go files
`)
os.Exit(2)
}
// die reports an error and exits.
func die(msg string) {
fmt.Fprintln(os.Stderr, msg)
os.Exit(1)
}

View File

@@ -0,0 +1,24 @@
// Copyright 2020 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 alg provides basic algorithms.
package alg
import "constraints"
// Max returns the maximum of two values of some ordered type.
func Max[T constraints.Ordered](a, b T) T {
if a < b {
return b
}
return a
}
// Min returns the minimum of two values of some ordered type.
func Min[T constraints.Ordered](a, b T) T {
if a < b {
return a
}
return b
}

View File

@@ -0,0 +1,215 @@
// Copyright 2020 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 chans provides utility functions for working with channels.
package chans
import (
"context"
"runtime"
)
// ReadAll reads from c until the channel is closed or the context is
// canceled, returning all the values read.
func ReadAll[Elem any](ctx context.Context, c <-chan Elem) []Elem {
var r []Elem
for {
select {
case <-ctx.Done():
return r
case v, ok := <-c:
if !ok {
return r
}
r = append(r, v)
}
}
}
// Merge merges two channels into a single channel.
// This will leave a goroutine running until either both channels are closed
// or the context is canceled, at which point the returned channel is closed.
func Merge[Elem any](ctx context.Context, c1, c2 <-chan Elem) <-chan Elem {
r := make(chan Elem)
go func(ctx context.Context, c1, c2 <-chan Elem, r chan<- Elem) {
defer close(r)
for c1 != nil || c2 != nil {
select {
case <-ctx.Done():
return
case v1, ok := <-c1:
if ok {
r <- v1
} else {
c1 = nil
}
case v2, ok := <-c2:
if ok {
r <- v2
} else {
c2 = nil
}
}
}
}(ctx, c1, c2, r)
return r
}
// Filter calls f on each value read from c. If f returns true the value
// is sent on the returned channel. This will leave a goroutine running
// until c is closed or the context is canceled, at which point the
// returned channel is closed.
func Filter[Elem any](ctx context.Context, c <-chan Elem, f func(Elem) bool) <-chan Elem {
r := make(chan Elem)
go func(ctx context.Context, c <-chan Elem, f func(Elem) bool, r chan<- Elem) {
defer close(r)
for {
select {
case <-ctx.Done():
return
case v, ok := <-c:
if !ok {
return
}
if f(v) {
r <- v
}
}
}
}(ctx, c, f, r)
return r
}
// Sink returns a channel that discards all values sent to it.
// This will leave a goroutine running until the context is canceled
// or the returned channel is closed.
func Sink[Elem any](ctx context.Context) chan<- Elem {
r := make(chan Elem)
go func(ctx context.Context, r <-chan Elem) {
for {
select {
case <-ctx.Done():
return
case _, ok := <-r:
if !ok {
return
}
}
}
}(ctx, r)
return r
}
// An Exclusive is a value that may only be used by a single goroutine
// at a time. This is implemented using channels rather than a mutex.
type Exclusive[Val any] struct {
c chan Val
}
// MakeExclusive makes an initialized exclusive value.
func MakeExclusive[Val any](initial Val) *Exclusive[Val] {
r := &Exclusive[Val]{
c: make(chan Val, 1),
}
r.c <- initial
return r
}
// Acquire acquires the exclusive value for private use.
// It must be released using the Release method.
func (e *Exclusive[Val]) Acquire() Val {
return <-e.c
}
// TryAcquire attempts to acquire the value. The ok result reports whether
// the value was acquired. If the value is acquired, it must be released
// using the Release method.
func (e *Exclusive[Val]) TryAcquire() (v Val, ok bool) {
select {
case r := <-e.c:
return r, true
default:
return v, false
}
}
// Release updates and releases the value.
// This method panics if the value has not been acquired.
func (e *Exclusive[Val]) Release(v Val) {
select {
case e.c <- v:
default:
panic("Exclusive Release without Acquire")
}
}
// Ranger returns a Sender and a Receiver. The Receiver provides a
// Next method to retrieve values. The Sender provides a Send method
// to send values and a Close method to stop sending values. The Next
// method indicates when the Sender has been closed, and the Send
// method indicates when the Receiver has been freed.
//
// This is a convenient way to exit a goroutine sending values when
// the receiver stops reading them.
func Ranger[Elem any]() (*Sender[Elem], *Receiver[Elem]) {
c := make(chan Elem)
d := make(chan struct{})
s := &Sender[Elem]{
values: c,
done: d,
}
r := &Receiver[Elem] {
values: c,
done: d,
}
runtime.SetFinalizer(r, (*Receiver[Elem]).finalize)
return s, r
}
// A Sender is used to send values to a Receiver.
type Sender[Elem any] struct {
values chan<- Elem
done <-chan struct{}
}
// Send sends a value to the receiver. It reports whether the value was sent.
// The value will not be sent if the context is closed or the receiver
// is freed.
func (s *Sender[Elem]) Send(ctx context.Context, v Elem) bool {
select {
case <-ctx.Done():
return false
case s.values <- v:
return true
case <-s.done:
return false
}
}
// Close tells the receiver that no more values will arrive.
// After Close is called, the Sender may no longer be used.
func (s *Sender[Elem]) Close() {
close(s.values)
}
// A Receiver receives values from a Sender.
type Receiver[Elem any] struct {
values <-chan Elem
done chan<- struct{}
}
// Next returns the next value from the channel. The bool result indicates
// whether the value is valid.
func (r *Receiver[Elem]) Next(ctx context.Context) (v Elem, ok bool) {
select {
case <-ctx.Done():
case v, ok = <-r.values:
}
return v, ok
}
// finalize is a finalizer for the receiver.
func (r *Receiver[Elem]) finalize() {
close(r.done)
}

View File

@@ -0,0 +1,180 @@
// Copyright 2020 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 chans
import (
"context"
"runtime"
"sort"
"sync"
"testing"
"time"
"slices"
)
func TestReadAll(t *testing.T) {
c := make(chan int)
go func() {
c <- 4
c <- 2
c <- 5
close(c)
}()
got := ReadAll(context.Background(), c)
want := []int{4, 2, 5}
if !slices.Equal(got, want) {
t.Errorf("ReadAll returned %v, want %v", got, want)
}
}
func TestMerge(t *testing.T) {
c1 := make(chan int)
c2 := make(chan int)
go func() {
c1 <- 1
c1 <- 3
c1 <- 5
close(c1)
}()
go func() {
c2 <- 2
c2 <- 4
c2 <- 6
close(c2)
}()
ctx := context.Background()
got := ReadAll(ctx, Merge(ctx, c1, c2))
sort.Ints(got)
want := []int{1, 2, 3, 4, 5, 6}
if !slices.Equal(got, want) {
t.Errorf("Merge returned %v, want %v", got, want)
}
}
func TestFilter(t *testing.T) {
c := make(chan int)
go func() {
c <- 1
c <- 2
c <- 3
close(c)
}()
even := func(i int) bool { return i%2 == 0 }
ctx := context.Background()
got := ReadAll(ctx, Filter(ctx, c, even))
want := []int{2}
if !slices.Equal(got, want) {
t.Errorf("Filter returned %v, want %v", got, want)
}
}
func TestSink(t *testing.T) {
c := Sink[int](context.Background())
after := time.NewTimer(time.Minute)
defer after.Stop()
send := func(v int) {
select {
case c <- v:
case <-after.C:
t.Error("timed out sending to Sink")
}
}
send(1)
send(2)
send(3)
close(c)
}
func TestExclusive(t *testing.T) {
val := 0
ex := MakeExclusive(&val)
var wg sync.WaitGroup
f := func() {
defer wg.Done()
for i := 0; i < 10; i++ {
p := ex.Acquire()
(*p)++
ex.Release(p)
}
}
wg.Add(2)
go f()
go f()
wg.Wait()
if val != 20 {
t.Errorf("after Acquire/Release loop got %d, want 20", val)
}
}
func TestExclusiveTry(t *testing.T) {
s := ""
ex := MakeExclusive(&s)
p, ok := ex.TryAcquire()
if !ok {
t.Fatalf("TryAcquire failed")
}
*p = "a"
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
_, ok := ex.TryAcquire()
if ok {
t.Errorf("TryAcquire succeeded unexpectedly")
}
}()
wg.Wait()
ex.Release(p)
p, ok = ex.TryAcquire()
if !ok {
t.Errorf("TryAcquire failed")
}
}
func TestRanger(t *testing.T) {
s, r := Ranger[int]()
ctx := context.Background()
go func() {
// Receive one value then exit.
v, ok := r.Next(ctx)
if !ok {
t.Errorf("did not receive any values")
} else if v != 1 {
t.Errorf("received %d, want 1", v)
}
}()
c1 := make(chan bool)
c2 := make(chan bool)
go func() {
defer close(c2)
if !s.Send(ctx, 1) {
t.Errorf("Send failed unexpectedly")
}
close(c1)
if s.Send(ctx, 2) {
t.Errorf("Send succeeded unexpectedly")
}
}()
<-c1
// Force a garbage collection to try to get the finalizers to run.
runtime.GC()
select {
case <-c2:
case <-time.After(time.Minute):
t.Error("Ranger Send should have failed, but timed out")
}
}

View File

@@ -0,0 +1,31 @@
// Copyright 2020 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 constraints defines some useful type constraints.
package constraints
// Ordered permits any ordered type: any type that supports
// the operations <, <=, >=, >, as well as == and !=.
type Ordered interface {
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64,
string
}
// Integer permits any integer type.
type Integer interface {
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr
}
// Signed permits any signed integer type.
type Signed interface {
type int, int8, int16, int32, int64
}
// Unsigned permits any unsigned integer type.
type Unsigned interface {
type uint, uint8, uint16, uint32, uint64, uintptr
}

View File

@@ -0,0 +1,72 @@
// Copyright 2020 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 graph implements general purpose graph algorithms.
package graph
import "errors"
// A Graph is a collection of nodes. A node may have an arbitrary number
// of edges. An edge connects two nodes. Both nodes and edges must be
// comparable. This is an undirected simple graph.
type Graph[Node NodeC[Edge], Edge EdgeC[Node]] struct {
nodes []Node
}
// NodeC is the contraints on a node in a graph, given the Edge type.
type NodeC[Edge any] interface {
comparable
Edges() []Edge
}
// Edgec is the constraints on an edge in a graph, given the Node type.
type EdgeC[Node any] interface {
comparable
Nodes() (a, b Node)
}
// New creates a new Graph from a collection of Nodes.
func New[Node NodeC[Edge], Edge EdgeC[Node]](nodes []Node) *Graph[Node, Edge] {
return &Graph[Node, Edge]{nodes: nodes}
}
// nodePath holds the path to a node during ShortestPath.
// This should ideally be a type defined inside ShortestPath,
// but the translator tool doesn't support that.
type nodePath[Node NodeC[Edge], Edge EdgeC[Node]] struct {
node Node
path []Edge
}
// ShortestPath returns the shortest path between two nodes,
// as an ordered list of edges. If there are multiple shortest paths,
// which one is returned is unpredictable.
func (g *Graph[Node, Edge]) ShortestPath(from, to Node) ([]Edge, error) {
visited := make(map[Node]bool)
visited[from] = true
workqueue := []nodePath[Node, Edge]{nodePath[Node, Edge]{from, nil}}
for len(workqueue) > 0 {
current := workqueue
workqueue = nil
for _, np := range current {
edges := np.node.Edges()
for _, edge := range edges {
a, b := edge.Nodes()
if a == np.node {
a = b
}
if !visited[a] {
ve := append([]Edge(nil), np.path...)
ve = append(ve, edge)
if a == to {
return ve, nil
}
workqueue = append(workqueue, nodePath[Node, Edge]{a, ve})
visited[a] = true
}
}
}
}
return nil, errors.New("no path")
}

View File

@@ -0,0 +1,143 @@
// Copyright 2020 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 graph
import (
"fmt"
"testing"
"slices"
)
type direction int
const (
north direction = iota
ne
east
se
south
sw
west
nw
up
down
)
func (dir direction) String() string {
strs := map[direction]string{
north: "north",
ne: "ne",
east: "east",
se: "se",
south: "south",
sw: "sw",
west: "west",
nw: "nw",
up: "up",
down: "down",
}
if str, ok := strs[dir]; ok {
return str
}
return fmt.Sprintf("direction %d", dir)
}
type mazeRoom struct {
index int
exits [10]int
}
type mazeEdge struct {
from, to int
dir direction
}
// Edges returns the exits from the room.
func (m mazeRoom) Edges() []mazeEdge {
var r []mazeEdge
for i, exit := range m.exits {
if exit != 0 {
r = append(r, mazeEdge{
from: m.index,
to: exit,
dir: direction(i),
})
}
}
return r
}
// Nodes returns the rooms connected by an edge.
func (e mazeEdge) Nodes() (mazeRoom, mazeRoom) {
m1, ok := zork[e.from]
if !ok {
panic("bad edge")
}
m2, ok := zork[e.to]
if !ok {
panic("bad edge")
}
return m1, m2
}
// The first maze in Zork. Room indexes based on original Fortran data file.
// You are in a maze of twisty little passages, all alike.
var zork = map[int]mazeRoom{
11: {exits: [10]int{north: 11, south: 12, east: 14}}, // west to Troll Room
12: {exits: [10]int{south: 11, north: 14, east: 13}},
13: {exits: [10]int{west: 12, north: 14, up: 16}},
14: {exits: [10]int{west: 13, north: 11, east: 15}},
15: {exits: [10]int{south: 14}}, // Dead End
16: {exits: [10]int{east: 17, north: 13, sw: 18}}, // skeleton, etc.
17: {exits: [10]int{west: 16}}, // Dead End
18: {exits: [10]int{down: 16, east: 19, west: 18, up: 22}},
19: {exits: [10]int{up: 29, west: 18, ne: 15, east: 20, south: 30}},
20: {exits: [10]int{ne: 19, west: 20, se: 21}},
21: {exits: [10]int{north: 20}}, // Dead End
22: {exits: [10]int{north: 18, east: 24, down: 23, south: 28, west: 26, nw: 22}},
23: {exits: [10]int{east: 22, west: 28, up: 24}},
24: {exits: [10]int{ne: 25, down: 23, nw: 28, sw: 26}},
25: {exits: [10]int{sw: 24}}, // Grating room (up to Clearing)
26: {exits: [10]int{west: 16, sw: 24, east: 28, up: 22, north: 27}},
27: {exits: [10]int{south: 26}}, // Dead End
28: {exits: [10]int{east: 22, down: 26, south: 23, west: 24}},
29: {exits: [10]int{west: 30, nw: 29, ne: 19, south: 19}},
30: {exits: [10]int{west: 29, south: 19}}, // ne to Cyclops Room
}
func TestShortestPath(t *testing.T) {
// The Zork maze is not a proper undirected simple graph,
// as there are some one way paths (e.g., 19 -> 15),
// but for this test that doesn't matter.
// Set the index field in the map. Simpler than doing it in the
// composite literal.
for k := range zork {
r := zork[k]
r.index = k
zork[k] = r
}
var nodes []mazeRoom
for idx, room := range zork {
mridx := room
mridx.index = idx
nodes = append(nodes, mridx)
}
g := New[mazeRoom, mazeEdge](nodes)
path, err := g.ShortestPath(zork[11], zork[30])
if err != nil {
t.Fatal(err)
}
var steps []direction
for _, edge := range path {
steps = append(steps, edge.dir)
}
want := []direction{east, west, up, sw, east, south}
if !slices.Equal(steps, want) {
t.Errorf("ShortestPath returned %v, want %v", steps, want)
}
}

View File

@@ -0,0 +1,51 @@
// Copyright 2020 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 gsort provides primitives for sorting slices of any type.
package gsort
import (
"sort"
"constraints"
)
// orderedSlice is a slice of values of some ordered type.
type orderedSlice[Elem constraints.Ordered] []Elem
// orderedSlice implements sort.Interface.
func (s orderedSlice[Elem]) Len() int { return len(s) }
func (s orderedSlice[Elem]) Less(i, j int) bool {
if s[i] < s[j] {
return true
}
isNaN := func(f Elem) bool { return f != f }
if isNaN(s[i]) && !isNaN(s[j]) {
return true
}
return false
}
func (s orderedSlice[Elem]) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// OrderedSlice sorts a slice of any ordered type in ascending order.
func OrderedSlice[Elem constraints.Ordered](s []Elem) {
sort.Sort(orderedSlice[Elem](s))
}
// sliceFn implements sort.Interface for a slice of any type with an
// explicit less-than function.
type sliceFn[Elem any] struct {
s []Elem
less func(Elem, Elem) bool
}
func (s sliceFn[Elem]) Len() int { return len(s.s) }
func (s sliceFn[Elem]) Less(i, j int) bool { return s.less(s.s[i], s.s[j]) }
func (s sliceFn[Elem]) Swap(i, j int) { s.s[i], s.s[j] = s.s[j], s.s[i] }
// SliceFn sorts a slice of any type according to a less-than function.
func SliceFn[Elem any](s []Elem, less func(Elem, Elem) bool) {
sort.Sort(sliceFn[Elem]{s, less})
}

View File

@@ -0,0 +1,92 @@
// Copyright 2020 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 gsort
import (
"math"
"sort"
"testing"
"constraints"
"slices"
)
// Test data copied from the standard library sort package.
var ints = []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
var float64s = []float64{74.3, 59.0, math.Inf(1), 238.2, -784.0, 2.3, math.NaN(), math.NaN(), math.Inf(-1), 9845.768, -959.7485, 905, 7.8, 7.8}
var strs = []string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}
func TestSortOrderedInts(t *testing.T) {
testOrdered(t, ints, sort.Ints)
}
func TestSortOrderedFloat64s(t *testing.T) {
testOrdered(t, float64s, sort.Float64s)
}
func TestSortOrderedStrings(t *testing.T) {
testOrdered(t, strs, sort.Strings)
}
func testOrdered[Elem constraints.Ordered](t *testing.T, s []Elem, sorter func([]Elem)) {
s1 := make([]Elem, len(s))
copy(s1, s)
s2 := make([]Elem, len(s))
copy(s2, s)
OrderedSlice(s1)
sorter(s2)
if !slices.Equal(s1, s2) {
t.Fatalf("got %v, want %v", s1, s2)
}
for i := len(s1) - 1; i > 0; i-- {
if s1[i] < s1[i-1] {
t.Fatalf("element %d (%v) < element %d (%v)", i, s1[i], i - 1, s1[i - 1])
}
}
}
var slicesToSort = [][]int {
[]int{1, 2},
[]int{3, 2, 1},
[]int{1},
[]int{1, 3},
[]int{1, 2, 3},
}
var sortedSlices = [][]int {
[]int{1},
[]int{1, 2},
[]int{1, 3},
[]int{1, 2, 3},
[]int{3, 2, 1},
}
func sorter(s1, s2 []int) bool {
switch {
case len(s1) < len(s2):
return true
case len(s1) > len(s2):
return false
}
for i := range s1 {
switch {
case s1[i] < s2[i]:
return true
case s1[i] > s2[i]:
return false
}
}
return false
}
func TestSortSliceFn(t *testing.T) {
c := make([][]int, len(slicesToSort))
copy(c, slicesToSort)
SliceFn(c, sorter)
if !slices.EqualFn(c, sortedSlices, func(a, b []int) bool { return slices.Equal[int](a, b) }) {
t.Errorf("got %v, want %v", c, sortedSlices)
}
}

View File

@@ -0,0 +1,244 @@
// Copyright 2020 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 list provides a doubly linked list of some element type.
package list
// FIXME: This should probably be in container/list,
// perhaps with different type names.
// Element is an element of a linked list.
type Element[TElem any] struct {
// Next and previous pointers in the doubly-linked list of elements.
// To simplify the implementation, internally a list l is implemented
// as a ring, such that &l.root is both the next element of the last
// list element (l.Back()) and the previous element of the first list
// element (l.Front()).
next, prev *Element[TElem]
// The list to which this element belongs.
list *List[TElem]
// The value stored with this element.
Value TElem
}
// Next returns the next list element or nil.
func (e *Element[TElem]) Next() *Element[TElem] {
if p := e.next; e.list != nil && p != &e.list.root {
return p
}
return nil
}
// Prev returns the previous list element or nil.
func (e *Element[TElem]) Prev() *Element[TElem] {
if p := e.prev; e.list != nil && p != &e.list.root {
return p
}
return nil
}
// List represents a doubly linked list.
// The zero value for List is an empty list ready to use.
type List[TElem any] struct {
root Element[TElem] // sentinel list element, only &root, root.prev, and root.next are used
len int // current list length excluding (this) sentinel element
}
// Init initializes or clears list l.
func (l *List[TElem]) Init() *List[TElem] {
l.root.next = &l.root
l.root.prev = &l.root
l.len = 0
return l
}
// New returns an initialized list.
func New[TElem any]() *List[TElem] { return new(List[TElem]).Init() }
// Len returns the number of elements of list l.
// The complexity is O(1).
func (l *List[TElem]) Len() int { return l.len }
// Front returns the first element of list l or nil if the list is empty.
func (l *List[TElem]) Front() *Element[TElem] {
if l.len == 0 {
return nil
}
return l.root.next
}
// Back returns the last element of list l or nil if the list is empty.
func (l *List[TElem]) Back() *Element[TElem] {
if l.len == 0 {
return nil
}
return l.root.prev
}
// lazyInit lazily initializes a zero List value.
func (l *List[TElem]) lazyInit() {
if l.root.next == nil {
l.Init()
}
}
// insert inserts e after at, increments l.len, and returns e.
func (l *List[TElem]) insert(e, at *Element[TElem]) *Element[TElem] {
e.prev = at
e.next = at.next
e.prev.next = e
e.next.prev = e
e.list = l
l.len++
return e
}
// insertValue is a convenience wrapper for insert(&Element[TElem]{Value: v}, at).
func (l *List[TElem]) insertValue(v TElem, at *Element[TElem]) *Element[TElem] {
return l.insert(&Element[TElem]{Value: v}, at)
}
// remove removes e from its list, decrements l.len, and returns e.
func (l *List[TElem]) remove(e *Element[TElem]) *Element[TElem] {
e.prev.next = e.next
e.next.prev = e.prev
e.next = nil // avoid memory leaks
e.prev = nil // avoid memory leaks
e.list = nil
l.len--
return e
}
// move moves e to next to at and returns e.
func (l *List[TElem]) move(e, at *Element[TElem]) *Element[TElem] {
if e == at {
return e
}
e.prev.next = e.next
e.next.prev = e.prev
e.prev = at
e.next = at.next
e.prev.next = e
e.next.prev = e
return e
}
// Remove removes e from l if e is an element of list l.
// It returns the element value e.Value.
// The element must not be nil.
func (l *List[TElem]) Remove(e *Element[TElem]) TElem {
if e.list == l {
// if e.list == l, l must have been initialized when e was inserted
// in l or l == nil (e is a zero Element) and l.remove will crash
l.remove(e)
}
return e.Value
}
// PushFront inserts a new element e with value v at the front of list l and returns e.
func (l *List[TElem]) PushFront(v TElem) *Element[TElem] {
l.lazyInit()
return l.insertValue(v, &l.root)
}
// PushBack inserts a new element e with value v at the back of list l and returns e.
func (l *List[TElem]) PushBack(v TElem) *Element[TElem] {
l.lazyInit()
return l.insertValue(v, l.root.prev)
}
// InsertBefore inserts a new element e with value v immediately before mark and returns e.
// If mark is not an element of l, the list is not modified.
// The mark must not be nil.
func (l *List[TElem]) InsertBefore(v TElem, mark *Element[TElem]) *Element[TElem] {
if mark.list != l {
return nil
}
// see comment in List.Remove about initialization of l
return l.insertValue(v, mark.prev)
}
// InsertAfter inserts a new element e with value v immediately after mark and returns e.
// If mark is not an element of l, the list is not modified.
// The mark must not be nil.
func (l *List[TElem]) InsertAfter(v TElem, mark *Element[TElem]) *Element[TElem] {
if mark.list != l {
return nil
}
// see comment in List.Remove about initialization of l
return l.insertValue(v, mark)
}
// MoveToFront moves element e to the front of list l.
// If e is not an element of l, the list is not modified.
// The element must not be nil.
func (l *List[TElem]) MoveToFront(e *Element[TElem]) {
if e.list != l || l.root.next == e {
return
}
// see comment in List.Remove about initialization of l
l.move(e, &l.root)
}
// MoveToBack moves element e to the back of list l.
// If e is not an element of l, the list is not modified.
// The element must not be nil.
func (l *List[TElem]) MoveToBack(e *Element[TElem]) {
if e.list != l || l.root.prev == e {
return
}
// see comment in List.Remove about initialization of l
l.move(e, l.root.prev)
}
// MoveBefore moves element e to its new position before mark.
// If e or mark is not an element of l, or e == mark, the list is not modified.
// The element and mark must not be nil.
func (l *List[TElem]) MoveBefore(e, mark *Element[TElem]) {
if e.list != l || e == mark || mark.list != l {
return
}
l.move(e, mark.prev)
}
// MoveAfter moves element e to its new position after mark.
// If e or mark is not an element of l, or e == mark, the list is not modified.
// The element and mark must not be nil.
func (l *List[TElem]) MoveAfter(e, mark *Element[TElem]) {
if e.list != l || e == mark || mark.list != l {
return
}
l.move(e, mark)
}
// PushBackList inserts a copy of an other list at the back of list l.
// The lists l and other may be the same. They must not be nil.
func (l *List[TElem]) PushBackList(other *List[TElem]) {
l.lazyInit()
for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() {
l.insertValue(e.Value, l.root.prev)
}
}
// PushFrontList inserts a copy of an other list at the front of list l.
// The lists l and other may be the same. They must not be nil.
func (l *List[TElem]) PushFrontList(other *List[TElem]) {
l.lazyInit()
for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() {
l.insertValue(e.Value, &l.root)
}
}
// Transform runs a transform function on a list returning a new list.
func Transform[TElem1, TElem2 any](lst *List[TElem1], f func(TElem1) TElem2) *List[TElem2] {
ret := New[TElem2]()
for p := lst.Front(); p != nil; p = p.Next() {
ret.PushBack(f(p.Value))
}
return ret
}

View File

@@ -0,0 +1,354 @@
// Copyright 2020 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 list
import (
"strconv"
"testing"
)
func checkListLen[TElem any](t *testing.T, l *List[TElem], len int) bool {
if n := l.Len(); n != len {
t.Errorf("l.Len() = %d, want %d", n, len)
return false
}
return true
}
func checkListPointers[TElem any](t *testing.T, l *List[TElem], es []*Element[TElem]) {
root := &l.root
if !checkListLen(t, l, len(es)) {
return
}
// zero length lists must be the zero value or properly initialized (sentinel circle)
if len(es) == 0 {
if l.root.next != nil && l.root.next != root || l.root.prev != nil && l.root.prev != root {
t.Errorf("l.root.next = %p, l.root.prev = %p; both should both be nil or %p", l.root.next, l.root.prev, root)
}
return
}
// len(es) > 0
// check internal and external prev/next connections
for i, e := range es {
prev := root
Prev := (*Element[TElem])(nil)
if i > 0 {
prev = es[i-1]
Prev = prev
}
if p := e.prev; p != prev {
t.Errorf("elt[%d](%p).prev = %p, want %p", i, e, p, prev)
}
if p := e.Prev(); p != Prev {
t.Errorf("elt[%d](%p).Prev() = %p, want %p", i, e, p, Prev)
}
next := root
Next := (*Element[TElem])(nil)
if i < len(es)-1 {
next = es[i+1]
Next = next
}
if n := e.next; n != next {
t.Errorf("elt[%d](%p).next = %p, want %p", i, e, n, next)
}
if n := e.Next(); n != Next {
t.Errorf("elt[%d](%p).Next() = %p, want %p", i, e, n, Next)
}
}
}
func TestList(t *testing.T) {
l := New[string]()
checkListPointers(t, l, []*(Element[string]){})
// Single element list
e := l.PushFront("a")
checkListPointers(t, l, []*(Element[string]){e})
l.MoveToFront(e)
checkListPointers(t, l, []*(Element[string]){e})
l.MoveToBack(e)
checkListPointers(t, l, []*(Element[string]){e})
l.Remove(e)
checkListPointers(t, l, []*(Element[string]){})
// Bigger list
l2 := New[int]()
e2 := l2.PushFront(2)
e1 := l2.PushFront(1)
e3 := l2.PushBack(3)
e4 := l2.PushBack(600)
checkListPointers(t, l2, []*(Element[int]){e1, e2, e3, e4})
l2.Remove(e2)
checkListPointers(t, l2, []*(Element[int]){e1, e3, e4})
l2.MoveToFront(e3) // move from middle
checkListPointers(t, l2, []*(Element[int]){e3, e1, e4})
l2.MoveToFront(e1)
l2.MoveToBack(e3) // move from middle
checkListPointers(t, l2, []*(Element[int]){e1, e4, e3})
l2.MoveToFront(e3) // move from back
checkListPointers(t, l2, []*(Element[int]){e3, e1, e4})
l2.MoveToFront(e3) // should be no-op
checkListPointers(t, l2, []*(Element[int]){e3, e1, e4})
l2.MoveToBack(e3) // move from front
checkListPointers(t, l2, []*(Element[int]){e1, e4, e3})
l2.MoveToBack(e3) // should be no-op
checkListPointers(t, l2, []*(Element[int]){e1, e4, e3})
e2 = l2.InsertBefore(2, e1) // insert before front
checkListPointers(t, l2, []*(Element[int]){e2, e1, e4, e3})
l2.Remove(e2)
e2 = l2.InsertBefore(2, e4) // insert before middle
checkListPointers(t, l2, []*(Element[int]){e1, e2, e4, e3})
l2.Remove(e2)
e2 = l2.InsertBefore(2, e3) // insert before back
checkListPointers(t, l2, []*(Element[int]){e1, e4, e2, e3})
l2.Remove(e2)
e2 = l2.InsertAfter(2, e1) // insert after front
checkListPointers(t, l2, []*(Element[int]){e1, e2, e4, e3})
l2.Remove(e2)
e2 = l2.InsertAfter(2, e4) // insert after middle
checkListPointers(t, l2, []*(Element[int]){e1, e4, e2, e3})
l2.Remove(e2)
e2 = l2.InsertAfter(2, e3) // insert after back
checkListPointers(t, l2, []*(Element[int]){e1, e4, e3, e2})
l2.Remove(e2)
// Check standard iteration.
sum := 0
for e := l2.Front(); e != nil; e = e.Next() {
sum += e.Value
}
if sum != 604 {
t.Errorf("sum over l = %d, want 604", sum)
}
// Clear all elements by iterating
var next *Element[int]
for e := l2.Front(); e != nil; e = next {
next = e.Next()
l2.Remove(e)
}
checkListPointers(t, l2, []*(Element[int]){})
}
func checkList[TElem comparable](t *testing.T, l *List[TElem], es []interface{}) {
if !checkListLen(t, l, len(es)) {
return
}
i := 0
for e := l.Front(); e != nil; e = e.Next() {
le := e.Value
if le != es[i] {
t.Errorf("elt[%d].Value = %v, want %v", i, le, es[i])
}
i++
}
}
func TestExtending(t *testing.T) {
l1 := New[int]()
l2 := New[int]()
l1.PushBack(1)
l1.PushBack(2)
l1.PushBack(3)
l2.PushBack(4)
l2.PushBack(5)
l3 := New[int]()
l3.PushBackList(l1)
checkList(t, l3, []interface{}{1, 2, 3})
l3.PushBackList(l2)
checkList(t, l3, []interface{}{1, 2, 3, 4, 5})
l3 = New[int]()
l3.PushFrontList(l2)
checkList(t, l3, []interface{}{4, 5})
l3.PushFrontList(l1)
checkList(t, l3, []interface{}{1, 2, 3, 4, 5})
checkList(t, l1, []interface{}{1, 2, 3})
checkList(t, l2, []interface{}{4, 5})
l3 = New[int]()
l3.PushBackList(l1)
checkList(t, l3, []interface{}{1, 2, 3})
l3.PushBackList(l3)
checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3})
l3 = New[int]()
l3.PushFrontList(l1)
checkList(t, l3, []interface{}{1, 2, 3})
l3.PushFrontList(l3)
checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3})
l3 = New[int]()
l1.PushBackList(l3)
checkList(t, l1, []interface{}{1, 2, 3})
l1.PushFrontList(l3)
checkList(t, l1, []interface{}{1, 2, 3})
}
func TestRemove(t *testing.T) {
l := New[int]()
e1 := l.PushBack(1)
e2 := l.PushBack(2)
checkListPointers(t, l, []*(Element[int]){e1, e2})
e := l.Front()
l.Remove(e)
checkListPointers(t, l, []*(Element[int]){e2})
l.Remove(e)
checkListPointers(t, l, []*(Element[int]){e2})
}
func TestIssue4103(t *testing.T) {
l1 := New[int]()
l1.PushBack(1)
l1.PushBack(2)
l2 := New[int]()
l2.PushBack(3)
l2.PushBack(4)
e := l1.Front()
l2.Remove(e) // l2 should not change because e is not an element of l2
if n := l2.Len(); n != 2 {
t.Errorf("l2.Len() = %d, want 2", n)
}
l1.InsertBefore(8, e)
if n := l1.Len(); n != 3 {
t.Errorf("l1.Len() = %d, want 3", n)
}
}
func TestIssue6349(t *testing.T) {
l := New[int]()
l.PushBack(1)
l.PushBack(2)
e := l.Front()
l.Remove(e)
if e.Value != 1 {
t.Errorf("e.value = %d, want 1", e.Value)
}
if e.Next() != nil {
t.Errorf("e.Next() != nil")
}
if e.Prev() != nil {
t.Errorf("e.Prev() != nil")
}
}
func TestMove(t *testing.T) {
l := New[int]()
e1 := l.PushBack(1)
e2 := l.PushBack(2)
e3 := l.PushBack(3)
e4 := l.PushBack(4)
l.MoveAfter(e3, e3)
checkListPointers(t, l, []*(Element[int]){e1, e2, e3, e4})
l.MoveBefore(e2, e2)
checkListPointers(t, l, []*(Element[int]){e1, e2, e3, e4})
l.MoveAfter(e3, e2)
checkListPointers(t, l, []*(Element[int]){e1, e2, e3, e4})
l.MoveBefore(e2, e3)
checkListPointers(t, l, []*(Element[int]){e1, e2, e3, e4})
l.MoveBefore(e2, e4)
checkListPointers(t, l, []*(Element[int]){e1, e3, e2, e4})
e2, e3 = e3, e2
l.MoveBefore(e4, e1)
checkListPointers(t, l, []*(Element[int]){e4, e1, e2, e3})
e1, e2, e3, e4 = e4, e1, e2, e3
l.MoveAfter(e4, e1)
checkListPointers(t, l, []*(Element[int]){e1, e4, e2, e3})
e2, e3, e4 = e4, e2, e3
l.MoveAfter(e2, e3)
checkListPointers(t, l, []*(Element[int]){e1, e3, e2, e4})
e2, e3 = e3, e2
}
// Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized List
func TestZeroList(t *testing.T) {
var l1 = new(List[int])
l1.PushFront(1)
checkList(t, l1, []interface{}{1})
var l2 = new(List[int])
l2.PushBack(1)
checkList(t, l2, []interface{}{1})
var l3 = new(List[int])
l3.PushFrontList(l1)
checkList(t, l3, []interface{}{1})
var l4 = new(List[int])
l4.PushBackList(l2)
checkList(t, l4, []interface{}{1})
}
// Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l.
func TestInsertBeforeUnknownMark(t *testing.T) {
var l List[int]
l.PushBack(1)
l.PushBack(2)
l.PushBack(3)
l.InsertBefore(1, new(Element[int]))
checkList(t, &l, []interface{}{1, 2, 3})
}
// Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l.
func TestInsertAfterUnknownMark(t *testing.T) {
var l List[int]
l.PushBack(1)
l.PushBack(2)
l.PushBack(3)
l.InsertAfter(1, new(Element[int]))
checkList(t, &l, []interface{}{1, 2, 3})
}
// Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l.
func TestMoveUnknownMark(t *testing.T) {
var l1 List[int]
e1 := l1.PushBack(1)
var l2 List[int]
e2 := l2.PushBack(2)
l1.MoveAfter(e1, e2)
checkList(t, &l1, []interface{}{1})
checkList(t, &l2, []interface{}{2})
l1.MoveBefore(e1, e2)
checkList(t, &l1, []interface{}{1})
checkList(t, &l2, []interface{}{2})
}
// Test the Transform function.
func TestTransform(t *testing.T) {
l1 := New[int]()
l1.PushBack(1)
l1.PushBack(2)
l2 := Transform(l1, strconv.Itoa)
checkList(t, l2, []interface{}{"1", "2"})
}

View File

@@ -0,0 +1,91 @@
// Copyright 2020 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 maps implements simple functions to manipulate maps in various ways.
package maps
// Keys returns the keys of the map m.
// The keys will be an indeterminate order.
func Keys[K comparable, V any](m map[K]V) []K {
r := make([]K, 0, len(m))
for k := range m {
r = append(r, k)
}
return r
}
// Values returns the values of the map m.
// The values will be in an indeterminate order.
func Values[K comparable, V any](m map[K]V) []V {
r := make([]V, 0, len(m))
for _, v := range m {
r = append(r, v)
}
return r
}
// Equal reports whether two maps contain the same key/value pairs.
// Values are compared using ==.
func Equal[K, V comparable](m1, m2 map[K]V) bool {
if len(m1) != len(m2) {
return false
}
for k, v1 := range m1 {
if v2, ok := m2[k]; !ok || v1 != v2 {
return false
}
}
return true
}
// Copy returns a copy of m.
func Copy[K comparable, V any](m map[K]V) map[K]V {
r := make(map[K]V, len(m))
for k, v := range m {
r[k] = v
}
return r
}
// Add adds all key/value pairs in m2 to m1. Keys in m2 that are already
// present in m1 will be overwritten with the value in m2.
func Add[K comparable, V any](m1, m2 map[K]V) {
for k, v := range m2 {
m1[k] = v
}
}
// Sub removes all keys in m2 from m1. Keys in m2 that are not present
// in m1 are ignored. The values in m2 are ignored.
func Sub[K comparable, V any](m1, m2 map[K]V) {
for k := range m2 {
delete(m1, k)
}
}
// Intersect removes all keys from m1 that are not present in m2.
// Keys in m2 that are not in m1 are ignored. The values in m2 are ignored.
func Intersect[K comparable, V any](m1, m2 map[K]V) {
for k := range m1 {
if _, ok := m2[k]; !ok {
delete(m1, k)
}
}
}
// Filter deletes any key/value pairs from m for which f returns false.
func Filter[K comparable, V any](m map[K]V, f func(K, V) bool) {
for k, v := range m {
if !f(k, v) {
delete(m, k)
}
}
}
// TransformValues applies f to each value in m. The keys remain unchanged.
func TransformValues[K comparable, V any](m map[K]V, f func(V) V) {
for k, v := range m {
m[k] = f(v)
}
}

View File

@@ -0,0 +1,145 @@
// Copyright 2020 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 maps
import (
"math"
"sort"
"testing"
"slices"
)
var m1 = map[int]int{1: 2, 2: 4, 4: 8, 8: 16}
var m2 = map[int]string{1: "2", 2: "4", 4: "8", 8: "16"}
func TestKeys(t *testing.T) {
want := []int{1, 2, 4, 8}
got1 := Keys(m1)
sort.Ints(got1)
if !slices.Equal(got1, want) {
t.Errorf("Keys(%v) = %v, want %v", m1, got1, want)
}
got2 := Keys(m2)
sort.Ints(got2)
if !slices.Equal(got2, want) {
t.Errorf("Keys(%v) = %v, want %v", m2, got2, want)
}
}
func TestValues(t *testing.T) {
got1 := Values(m1)
want1 := []int{2, 4, 8, 16}
sort.Ints(got1)
if !slices.Equal(got1, want1) {
t.Errorf("Values(%v) = %v, want %v", m1, got1, want1)
}
got2 := Values(m2)
want2 := []string{"16", "2", "4", "8"}
sort.Strings(got2)
if !slices.Equal(got2, want2) {
t.Errorf("Values(%v) = %v, want %v", m2, got2, want2)
}
}
func TestEqual(t *testing.T) {
if !Equal(m1, m1) {
t.Errorf("Equal(%v, %v) = false, want true", m1, m1)
}
if Equal(m1, nil) {
t.Errorf("Equal(%v, nil) = true, want false", m1)
}
if Equal(nil, m1) {
t.Errorf("Equal(nil, %v) = true, want false", m1)
}
if !Equal[int, int](nil, nil) {
t.Error("Equal(nil, nil) = false, want true")
}
if ms := map[int]int{1: 2}; Equal(m1, ms) {
t.Errorf("Equal(%v, %v) = true, want false", m1, ms)
}
// Comparing NaN for equality is expected to fail.
mf := map[int]float64{1: 0, 2: math.NaN()}
if Equal(mf, mf) {
t.Errorf("Equal(%v, %v) = true, want false", mf, mf)
}
}
func TestCopy(t *testing.T) {
m2 := Copy(m1)
if !Equal(m1, m2) {
t.Errorf("Copy(%v) = %v, want %v", m1, m2, m1)
}
m2[16] = 32
if Equal(m1, m2) {
t.Errorf("Equal(%v, %v) = true, want false", m1, m2)
}
}
func TestAdd(t *testing.T) {
mc := Copy(m1)
Add(mc, mc)
if !Equal(mc, m1) {
t.Errorf("Add(%v, %v) = %v, want %v", m1, m1, mc, m1)
}
Add(mc, map[int]int{16: 32})
want := map[int]int{1: 2, 2: 4, 4: 8, 8: 16, 16: 32}
if !Equal(mc, want) {
t.Errorf("Add result = %v, want %v", mc, want)
}
}
func TestSub(t *testing.T) {
mc := Copy(m1)
Sub(mc, mc)
if len(mc) > 0 {
t.Errorf("Sub(%v, %v) = %v, want empty map", m1, m1, mc)
}
mc = Copy(m1)
Sub(mc, map[int]int{1: 0})
want := map[int]int{2: 4, 4: 8, 8: 16}
if !Equal(mc, want) {
t.Errorf("Sub result = %v, want %v", mc, want)
}
}
func TestIntersect(t *testing.T) {
mc := Copy(m1)
Intersect(mc, mc)
if !Equal(mc, m1) {
t.Errorf("Intersect(%v, %v) = %v, want %v", m1, m1, mc, m1)
}
Intersect(mc, map[int]int{1: 0, 2: 0})
want := map[int]int{1: 2, 2: 4}
if !Equal(mc, want) {
t.Errorf("Intersect result = %v, want %v", mc, want)
}
}
func TestFilter(t *testing.T) {
mc := Copy(m1)
Filter(mc, func(int, int) bool { return true })
if !Equal(mc, m1) {
t.Errorf("Filter(%v, true) = %v, want %v", m1, mc, m1)
}
Filter(mc, func(k, v int) bool { return k < 3 })
want := map[int]int{1: 2, 2: 4}
if !Equal(mc, want) {
t.Errorf("Filter result = %v, want %v", mc, want)
}
}
func TestTransformValues(t *testing.T) {
mc := Copy(m1)
TransformValues(mc, func(i int) int { return i / 2 })
want := map[int]int{1: 1, 2: 2, 4: 4, 8: 8}
if !Equal(mc, want) {
t.Errorf("TransformValues result = %v, want %v", mc, want)
}
}

View File

@@ -0,0 +1,117 @@
// Copyright 2020 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 metrics provides tracking arbitrary metrics composed of
// values of comparable types.
package metrics
import (
"sync"
"maps"
)
// Metric1 tracks metrics of values of some type.
type Metric1[T comparable] struct {
mu sync.Mutex
m map[T]int
}
// Add adds another instance of some value.
func (m *Metric1[T]) Add(v T) {
m.mu.Lock()
defer m.mu.Unlock()
if m.m == nil {
m.m = make(map[T]int)
}
m.m[v]++
}
// Count returns the number of instances we've seen of v.
func (m *Metric1[T]) Count(v T) int {
m.mu.Lock()
defer m.mu.Unlock()
return m.m[v]
}
// Metrics returns all the values we've seen, in an indeterminate order.
func (m *Metric1[T]) Metrics() []T {
return maps.Keys(m.m)
}
type key2[T1, T2 comparable] struct {
f1 T1
f2 T2
}
// Metric2 tracks metrics of pairs of values.
type Metric2[T1, T2 comparable] struct {
mu sync.Mutex
m map[key2[T1, T2]]int
}
// Add adds another instance of some pair of values.
func (m *Metric2[T1, T2]) Add(v1 T1, v2 T2) {
m.mu.Lock()
defer m.mu.Unlock()
if m.m == nil {
m.m = make(map[key2[T1, T2]]int)
}
m.m[key2[T1, T2]{v1, v2}]++
}
// Count returns the number of instances we've seen of v1/v2.
func (m *Metric2[T1, T2]) Count(v1 T1, v2 T2) int {
m.mu.Lock()
defer m.mu.Unlock()
return m.m[key2[T1, T2]{v1, v2}]
}
// Metrics returns all the values we've seen, in an indeterminate order.
func (m *Metric2[T1, T2]) Metrics() (r1 []T1, r2 []T2) {
for _, k := range maps.Keys(m.m) {
r1 = append(r1, k.f1)
r2 = append(r2, k.f2)
}
return r1, r2
}
type key3[T1, T2, T3 comparable] struct {
f1 T1
f2 T2
f3 T3
}
// Metric3 tracks metrics of triplets of values.
type Metric3[T1, T2, T3 comparable] struct {
mu sync.Mutex
m map[key3[T1, T2, T3]]int
}
// Add adds another instance of some triplet of values.
func (m *Metric3[T1, T2, T3]) Add(v1 T1, v2 T2, v3 T3) {
m.mu.Lock()
defer m.mu.Unlock()
if m.m == nil {
m.m = make(map[key3[T1, T2, T3]]int)
}
m.m[key3[T1, T2, T3]{v1, v2, v3}]++
}
// Count returns the number of instances we've seen of v1/v2/v3.
func (m *Metric3[T1, T2, T3]) Count(v1 T1, v2 T2, v3 T3) int {
m.mu.Lock()
defer m.mu.Unlock()
return m.m[key3[T1, T2, T3]{v1, v2, v3}]
}
// Metrics returns all the values we've seen, in an indeterminate order.
func (m *Metric3[T1, T2, T3]) Metrics() (r1 []T1, r2 []T2, r3 []T3) {
for k := range m.m {
r1 = append(r1, k.f1)
r2 = append(r2, k.f2)
r3 = append(r3, k.f3)
}
return r1, r2, r3
}

View File

@@ -0,0 +1,57 @@
// Copyright 2020 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 metrics
import (
"sort"
"testing"
"slices"
)
type S struct{ a, b, c string }
func TestMetrics(t *testing.T) {
m1 := Metric1[string]{}
if got := m1.Count("a"); got != 0 {
t.Errorf("Count(%q) = %d, want 0", "a", got)
}
m1.Add("a")
m1.Add("a")
if got := m1.Count("a"); got != 2 {
t.Errorf("Count(%q) = %d, want 2", "a", got)
}
if got, want := m1.Metrics(), []string{"a"}; !slices.Equal(got, want) {
t.Errorf("Metrics = %v, want %v", got, want)
}
m2 := Metric2[int, float64]{}
m2.Add(1, 1)
m2.Add(2, 2)
m2.Add(3, 3)
m2.Add(3, 3)
k1, k2 := m2.Metrics()
sort.Ints(k1)
w1 := []int{1, 2, 3}
if !slices.Equal(k1, w1) {
t.Errorf("Metric2.Metrics first slice = %v, want %v", k1, w1)
}
sort.Float64s(k2)
w2 := []float64{1, 2, 3}
if !slices.Equal(k2, w2) {
t.Errorf("Metric2.Metrics first slice = %v, want %v", k2, w2)
}
m3 := Metric3[string, S, S]{}
m3.Add("a", S{"d", "e", "f"}, S{"g", "h", "i"})
m3.Add("a", S{"d", "e", "f"}, S{"g", "h", "i"})
m3.Add("a", S{"d", "e", "f"}, S{"g", "h", "i"})
m3.Add("b", S{"d", "e", "f"}, S{"g", "h", "i"})
if got := m3.Count("a", S{"d", "e", "f"}, S{"g", "h", "i"}); got != 3 {
t.Errorf("Count(%v, %v, %v) = %d, want 3", "a", S{"d", "e", "f"}, S{"g", "h", "i"}, got)
}
}

View File

@@ -0,0 +1,136 @@
// Copyright 2020 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 orderedmap provides an ordered map, implemented as a binary tree.
package orderedmap
// FIXME: This should probably be container/orderedmap.
import (
"context"
"chans"
"constraints"
)
// Map is an ordered map.
type Map[K, V any] struct {
root *node[K, V]
compare func(K, K) int
}
// node is the type of a node in the binary tree.
type node[K, V any] struct {
key K
val V
left, right *node[K, V]
}
// New returns a new map. It takes a comparison function that compares two
// keys and returns < 0 if the first is less, == 0 if they are equal,
// > 0 if the first is greater.
func New[K, V any](compare func(K, K) int) *Map[K, V] {
return &Map[K, V]{compare: compare}
}
// NewOrdered returns a new map whose key is an ordered type.
// This is like New, but does not require providing a compare function.
// The map compare function uses the obvious key ordering.
func NewOrdered[K constraints.Ordered, V any]() *Map[K, V] {
return New[K, V](func(k1, k2 K) int {
switch {
case k1 < k2:
return -1
case k1 == k2:
return 0
default:
return 1
}
})
}
// find looks up key in the map, returning either a pointer to the slot of the
// node holding key, or a pointer to the slot where should a node would go.
func (m *Map[K, V]) find(key K) **node[K, V] {
pn := &m.root
for *pn != nil {
switch cmp := m.compare(key, (*pn).key); {
case cmp < 0:
pn = &(*pn).left
case cmp > 0:
pn = &(*pn).right
default:
return pn
}
}
return pn
}
// Insert inserts a new key/value into the map.
// If the key is already present, the value is replaced.
// Reports whether this is a new key.
func (m *Map[K, V]) Insert(key K, val V) bool {
pn := m.find(key)
if *pn != nil {
(*pn).val = val
return false
}
*pn = &node[K, V]{key: key, val: val}
return true
}
// Find returns the value associated with a key, or the zero value
// if not present. The found result reports whether the key was found.
func (m *Map[K, V]) Find(key K) (V, bool) {
pn := m.find(key)
if *pn == nil {
var zero V
return zero, false
}
return (*pn).val, true
}
// keyValue is a pair of key and value used while iterating.
type keyValue[K, V any] struct {
key K
val V
}
// iterate returns an iterator that traverses the map.
func (m *Map[K, V]) Iterate() *Iterator[K, V] {
sender, receiver := chans.Ranger[keyValue[K, V]]()
var f func(*node[K, V]) bool
f = func(n *node[K, V]) bool {
if n == nil {
return true
}
// Stop the traversal if Send fails, which means that
// nothing is listening to the receiver.
return f(n.left) &&
sender.Send(context.Background(), keyValue[K, V]{n.key, n.val}) &&
f(n.right)
}
go func() {
f(m.root)
sender.Close()
}()
return &Iterator[K, V]{receiver}
}
// Iterator is used to iterate over the map.
type Iterator[K, V any] struct {
r *chans.Receiver[keyValue[K, V]]
}
// Next returns the next key and value pair, and a boolean that reports
// whether they are valid. If not valid, we have reached the end of the map.
func (it *Iterator[K, V]) Next() (K, V, bool) {
keyval, ok := it.r.Next(context.Background())
if !ok {
var zerok K
var zerov V
return zerok, zerov, false
}
return keyval.key, keyval.val, true
}

View File

@@ -0,0 +1,63 @@
// Copyright 2020 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 orderedmap
import (
"bytes"
"testing"
"slices"
)
func TestMap(t *testing.T) {
m := New[[]byte, int](bytes.Compare)
if _, found := m.Find([]byte("a")); found {
t.Errorf("unexpectedly found %q in empty map", []byte("a"))
}
if !m.Insert([]byte("a"), 'a') {
t.Errorf("key %q unexpectedly already present", []byte("a"))
}
if !m.Insert([]byte("c"), 'c') {
t.Errorf("key %q unexpectedly already present", []byte("c"))
}
if !m.Insert([]byte("b"), 'b') {
t.Errorf("key %q unexpectedly already present", []byte("b"))
}
if m.Insert([]byte("c"), 'x') {
t.Errorf("key %q unexpectedly not present", []byte("c"))
}
if v, found := m.Find([]byte("a")); !found {
t.Errorf("did not find %q", []byte("a"))
} else if v != 'a' {
t.Errorf("key %q returned wrong value %c, expected %c", []byte("a"), v, 'a')
}
if v, found := m.Find([]byte("c")); !found {
t.Errorf("did not find %q", []byte("c"))
} else if v != 'x' {
t.Errorf("key %q returned wrong value %c, expected %c", []byte("c"), v, 'x')
}
if _, found := m.Find([]byte("d")); found {
t.Errorf("unexpectedly found %q", []byte("d"))
}
gather := func(it *Iterator[[]byte, int]) []int {
var r []int
for {
_, v, ok := it.Next()
if !ok {
return r
}
r = append(r, v)
}
}
got := gather(m.Iterate())
want := []int{'a', 'b', 'x'}
if !slices.Equal(got, want) {
t.Errorf("Iterate returned %v, want %v", got, want)
}
}

View File

@@ -0,0 +1,111 @@
// Copyright 2020 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 sets implements sets of any type.
package sets
// A Set is a set of elements of some type.
type Set[Elem comparable] struct {
m map[Elem]struct{}
}
// Make makes a new set.
func Make[Elem comparable]() Set[Elem] {
return Set[Elem]{m: make(map[Elem]struct{})}
}
// Add adds an element to a set.
func (s Set[Elem]) Add(v Elem) {
s.m[v] = struct{}{}
}
// Delete removes an element from a set. If the element is not present
// in the set, this does nothing.
func (s Set[Elem]) Delete(v Elem) {
delete(s.m, v)
}
// Contains reports whether v is in the set.
func (s Set[Elem]) Contains(v Elem) bool {
_, ok := s.m[v]
return ok
}
// Len returns the number of elements in the set.
func (s Set[Elem]) Len() int {
return len(s.m)
}
// Values returns the values in the set.
// The values will be in an indeterminate order.
func (s Set[Elem]) Values() []Elem {
r := make([]Elem, 0, len(s.m))
for v := range s.m {
r = append(r, v)
}
return r
}
// Equal reports whether two sets contain the same elements.
func Equal[Elem comparable](s1, s2 Set[Elem]) bool {
if len(s1.m) != len(s2.m) {
return false
}
for v1 := range s1.m {
if !s2.Contains(v1) {
return false
}
}
return true
}
// Copy returns a copy of s.
func (s Set[Elem]) Copy() Set[Elem] {
r := Set[Elem]{m: make(map[Elem]struct{}, len(s.m))}
for v := range s.m {
r.m[v] = struct{}{}
}
return r
}
// AddSet adds all the elements of s2 to s.
func (s Set[Elem]) AddSet(s2 Set[Elem]) {
for v := range s2.m {
s.m[v] = struct{}{}
}
}
// SubSet removes all elements in s2 from s.
// Values in s2 that are not in s are ignored.
func (s Set[Elem]) SubSet(s2 Set[Elem]) {
for v := range s2.m {
delete(s.m, v)
}
}
// Intersect removes all elements from s that are not present in s2.
// Values in s2 that are not in s are ignored.
func (s Set[Elem]) Intersect(s2 Set[Elem]) {
for v := range s.m {
if !s2.Contains(v) {
delete(s.m, v)
}
}
}
// Iterate calls f on every element in the set.
func (s Set[Elem]) Iterate(f func(Elem)) {
for v := range s.m {
f(v)
}
}
// Filter deletes any elements from s for which f returns false.
func (s Set[Elem]) Filter(f func(Elem) bool) {
for v := range s.m {
if !f(v) {
delete(s.m, v)
}
}
}

View File

@@ -0,0 +1,146 @@
// Copyright 2020 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 sets
import (
"sort"
"testing"
"slices"
)
func TestSet(t *testing.T) {
s1 := Make[int]()
if got := s1.Len(); got != 0 {
t.Errorf("Len of empty set = %d, want 0", got)
}
s1.Add(1)
s1.Add(1)
s1.Add(1)
if got := s1.Len(); got != 1 {
t.Errorf("(%v).Len() == %d, want 1", s1, got)
}
s1.Add(2)
s1.Add(3)
s1.Add(4)
if got := s1.Len(); got != 4 {
t.Errorf("(%v).Len() == %d, want 4", s1, got)
}
if !s1.Contains(1) {
t.Errorf("(%v).Contains(1) == false, want true", s1)
}
if s1.Contains(5) {
t.Errorf("(%v).Contains(5) == true, want false", s1)
}
vals := s1.Values()
sort.Ints(vals)
w1 := []int{1, 2, 3, 4}
if !slices.Equal(vals, w1) {
t.Errorf("(%v).Values() == %v, want %v", s1, vals, w1)
}
}
func TestEqual(t *testing.T) {
s1 := Make[string]()
s2 := Make[string]()
if !Equal(s1, s2) {
t.Errorf("Equal(%v, %v) = false, want true", s1, s2)
}
s1.Add("hello")
s1.Add("world")
if got := s1.Len(); got != 2 {
t.Errorf("(%v).Len() == %d, want 2", s1, got)
}
if Equal(s1, s2) {
t.Errorf("Equal(%v, %v) = true, want false", s1, s2)
}
}
func TestCopy(t *testing.T) {
s1 := Make[float64]()
s1.Add(0)
s2 := s1.Copy()
if !Equal(s1, s2) {
t.Errorf("Equal(%v, %v) = false, want true", s1, s2)
}
s1.Add(1)
if Equal(s1, s2) {
t.Errorf("Equal(%v, %v) = true, want false", s1, s2)
}
}
func TestAddSet(t *testing.T) {
s1 := Make[int]()
s1.Add(1)
s1.Add(2)
s2 := Make[int]()
s2.Add(2)
s2.Add(3)
s1.AddSet(s2)
if got := s1.Len(); got != 3 {
t.Errorf("(%v).Len() == %d, want 3", s1, got)
}
s2.Add(1)
if !Equal(s1, s2) {
t.Errorf("Equal(%v, %v) = false, want true", s1, s2)
}
}
func TestSubSet(t *testing.T) {
s1 := Make[int]()
s1.Add(1)
s1.Add(2)
s2 := Make[int]()
s2.Add(2)
s2.Add(3)
s1.SubSet(s2)
if got := s1.Len(); got != 1 {
t.Errorf("(%v).Len() == %d, want 1", s1, got)
}
if vals, want := s1.Values(), []int{1}; !slices.Equal(vals, want) {
t.Errorf("after SubSet got %v, want %v", vals, want)
}
}
func TestIntersect(t *testing.T) {
s1 := Make[int]()
s1.Add(1)
s1.Add(2)
s2 := Make[int]()
s2.Add(2)
s2.Add(3)
s1.Intersect(s2)
if got := s1.Len(); got != 1 {
t.Errorf("(%v).Len() == %d, want 1", s1, got)
}
if vals, want := s1.Values(), []int{2}; !slices.Equal(vals, want) {
t.Errorf("after Intersect got %v, want %v", vals, want)
}
}
func TestIterate(t *testing.T) {
s1 := Make[int]()
s1.Add(1)
s1.Add(2)
s1.Add(3)
s1.Add(4)
tot := 0
s1.Iterate(func(i int) { tot += i })
if tot != 10 {
t.Errorf("total of %v == %d, want 10", s1, tot)
}
}
func TestFilter(t *testing.T) {
s1 := Make[int]()
s1.Add(1)
s1.Add(2)
s1.Add(3)
s1.Filter(func(v int) bool { return v%2 == 0 })
if vals, want := s1.Values(), []int{2}; !slices.Equal(vals, want) {
t.Errorf("after Filter got %v, want %v", vals, want)
}
}

View File

@@ -0,0 +1,125 @@
// Copyright 2020 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 slices provides functions for basic operations on
// slices of any element type.
package slices
import (
"alg"
"constraints"
)
// Equal reports whether two slices are equal: the same length and all
// elements equal. All floating point NaNs are considered equal.
func Equal[Elem comparable](s1, s2 []Elem) bool {
if len(s1) != len(s2) {
return false
}
for i, v1 := range s1 {
v2 := s2[i]
if v1 != v2 {
isNaN := func(f Elem) bool { return f != f }
if !isNaN(v1) || !isNaN(v2) {
return false
}
}
}
return true
}
// EqualFn reports whether two slices are equal using a comparision
// function on each element.
func EqualFn[Elem any](s1, s2 []Elem, eq func(Elem, Elem) bool) bool {
if len(s1) != len(s2) {
return false
}
for i, v1 := range s1 {
v2 := s2[i]
if !eq(v1, v2) {
return false
}
}
return true
}
// Map turns a []Elem1 to a []Elem2 using a mapping function.
func Map[Elem1, Elem2 any](s []Elem1, f func(Elem1) Elem2) []Elem2 {
r := make([]Elem2, len(s))
for i, v := range s {
r[i] = f(v)
}
return r
}
// Reduce reduces a []Elem1 to a single value of type Elem2 using
// a reduction function.
func Reduce[Elem1, Elem2 any](s []Elem1, initializer Elem2, f func(Elem2, Elem1) Elem2) Elem2 {
r := initializer
for _, v := range s {
r = f(r, v)
}
return r
}
// Filter filters values from a slice using a filter function.
func Filter[Elem any](s []Elem, f func(Elem) bool) []Elem {
var r []Elem
for _, v := range s {
if f(v) {
r = append(r, v)
}
}
return r
}
// Max returns the maximum element in a slice of some ordered type.
// If the slice is empty it returns the zero value of the element type.
func Max[Elem constraints.Ordered](s []Elem) Elem {
if len(s) == 0 {
var zero Elem
return zero
}
return Reduce(s[1:], s[0], alg.Max[Elem])
}
// Min returns the minimum element in a slice of some ordered type.
// If the slice is empty it returns the zero value of the element type.
func Min[Elem constraints.Ordered](s []Elem) Elem {
if len(s) == 0 {
var zero Elem
return zero
}
return Reduce(s[1:], s[0], alg.Min[Elem])
}
// Append adds values to the end of a slice, returning a new slice.
// This is like the predeclared append function; it's an example
// of how to write it using generics. We used to write code like
// this before append was added to the language, but we had to write
// a separate copy for each type.
func Append[T any](s []T, t ...T) []T {
lens := len(s)
tot := lens + len(t)
if tot <= cap(s) {
s = s[:tot]
} else {
news := make([]T, tot, tot + tot/2)
Copy(news, s)
s = news
}
Copy(s[lens:tot], t)
return s
}
// Copy copies values from t to s, stopping when either slice is full,
// returning the number of values copied. This is like the predeclared
// copy function; it's an example of how to write it using generics.
func Copy[T any](s, t []T) int {
i := 0
for ; i < len(s) && i < len(t); i++ {
s[i] = t[i]
}
return i
}

View File

@@ -0,0 +1,164 @@
// Copyright 2020 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 slices
import (
"math"
"strings"
"testing"
"constraints"
)
func TestEqual(t *testing.T) {
s1 := []int{1, 2, 3}
if !Equal(s1, s1) {
t.Errorf("Equal(%v, %v) = false, want true", s1, s1)
}
s2 := []int{1, 2, 3}
if !Equal(s1, s2) {
t.Errorf("Equal(%v, %v) = false, want true", s1, s2)
}
s2 = append(s2, 4)
if Equal(s1, s2) {
t.Errorf("Equal(%v, %v) = true, want false", s1, s2)
}
s3 := []float64{1, 2, math.NaN()}
if !Equal(s3, s3) {
t.Errorf("Equal(%v, %v) = false, want true", s3, s3)
}
if Equal(s1, nil) {
t.Errorf("Equal(%v, nil) = true, want false", s1)
}
if Equal(nil, s1) {
t.Errorf("Equal(nil, %v) = true, want false", s1)
}
if !Equal(s1[:0], nil) {
t.Errorf("Equal(%v, nil = false, want true", s1[:0])
}
}
func offByOne[Elem constraints.Integer](a, b Elem) bool {
return a == b + 1 || a == b - 1
}
func TestEqualFn(t *testing.T) {
s1 := []int{1, 2, 3}
s2 := []int{2, 3, 4}
if EqualFn(s1, s1, offByOne[int]) {
t.Errorf("EqualFn(%v, %v, offByOne) = true, want false", s1, s1)
}
if !EqualFn(s1, s2, offByOne[int]) {
t.Errorf("EqualFn(%v, %v, offByOne) = false, want true", s1, s2)
}
s3 := []string{"a", "b", "c"}
s4 := []string{"A", "B", "C"}
if !EqualFn(s3, s4, strings.EqualFold) {
t.Errorf("EqualFn(%v, %v, strings.EqualFold) = false, want true", s3, s4)
}
if !EqualFn(s1[:0], nil, offByOne[int]) {
t.Errorf("EqualFn(%v, nil, offByOne) = false, want true", s1[:0])
}
}
func TestMap(t *testing.T) {
s1 := []int{1, 2, 3}
s2 := Map(s1, func(i int) float64 { return float64(i) * 2.5 })
if want := []float64{2.5, 5, 7.5}; !Equal(s2, want) {
t.Errorf("Map(%v, ...) = %v, want %v", s1, s2, want)
}
s3 := []string{"Hello", "World"}
s4 := Map(s3, strings.ToLower)
if want := []string{"hello", "world"}; !Equal(s4, want) {
t.Errorf("Map(%v, strings.ToLower) = %v, want %v", s3, s4, want)
}
s5 := Map(nil, func(i int) int { return i })
if len(s5) != 0 {
t.Errorf("Map(nil, identity) = %v, want empty slice", s5)
}
}
func TestReduce(t *testing.T) {
s1 := []int{1, 2, 3}
r := Reduce(s1, 0, func(f float64, i int) float64 { return float64(i) * 2.5 + f })
if want := 15.0; r != want {
t.Errorf("Reduce(%v, 0, ...) = %v, want %v", s1, r, want)
}
if got := Reduce(nil, 0, func(i, j int) int { return i + j}); got != 0 {
t.Errorf("Reduce(nil, 0, add) = %v, want 0", got)
}
}
func TestFilter(t *testing.T) {
s1 := []int{1, 2, 3}
s2 := Filter(s1, func(i int) bool { return i%2 == 0 })
if want := []int{2}; !Equal(s2, want) {
t.Errorf("Filter(%v, even) = %v, want %v", s1, s2, want)
}
if s3 := Filter(s1[:0], func(i int) bool { return true }); len(s3) > 0 {
t.Errorf("Filter(%v, identity) = %v, want empty slice", s1[:0], s3)
}
}
func TestMax(t *testing.T) {
s1 := []int{1, 2, 3, -5}
if got, want := Max(s1), 3; got != want {
t.Errorf("Max(%v) = %d, want %d", s1, got, want)
}
s2 := []string{"aaa", "a", "aa", "aaaa"}
if got, want := Max(s2), "aaaa"; got != want {
t.Errorf("Max(%v) = %q, want %q", s2, got, want)
}
if got, want := Max(s2[:0]), ""; got != want {
t.Errorf("Max(%v) = %q, want %q", s2[:0], got, want)
}
}
func TestMin(t *testing.T) {
s1 := []int{1, 2, 3, -5}
if got, want := Min(s1), -5; got != want {
t.Errorf("Min(%v) = %d, want %d", s1, got, want)
}
s2 := []string{"aaa", "a", "aa", "aaaa"}
if got, want := Min(s2), "a"; got != want {
t.Errorf("Min(%v) = %q, want %q", s2, got, want)
}
if got, want := Min(s2[:0]), ""; got != want {
t.Errorf("Min(%v) = %q, want %q", s2[:0], got, want)
}
}
func TestAppend(t *testing.T) {
s := []int{1, 2, 3}
s = Append(s, 4, 5, 6)
want := []int{1, 2, 3, 4, 5, 6}
if !Equal(s, want) {
t.Errorf("after Append got %v, want %v", s, want)
}
}
func TestCopy(t *testing.T) {
s1 := []int{1, 2, 3}
s2 := []int{4, 5}
if got := Copy(s1, s2); got != 2 {
t.Errorf("Copy returned %d, want 2", got)
}
want := []int{4, 5, 3}
if !Equal(s1, want) {
t.Errorf("after Copy got %v, want %v", s1, want)
}
}

View File

@@ -0,0 +1,33 @@
// Copyright 2020 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 (
"go/go2go"
"io/ioutil"
"strings"
)
// translate writes .go files for all .go2 files in dir.
func translate(importer *go2go.Importer, dir string) {
if err := go2go.Rewrite(importer, dir); err != nil {
die(err.Error())
}
}
// translateFile translates one .go2 file into a .go file.
func translateFile(importer *go2go.Importer, file string) {
data, err := ioutil.ReadFile(file)
if err != nil {
die(err.Error())
}
out, err := go2go.RewriteBuffer(importer, file, data)
if err != nil {
die(err.Error())
}
if err := ioutil.WriteFile(strings.TrimSuffix(file, ".go2")+".go", out, 0644); err != nil {
die(err.Error())
}
}

View File

@@ -75,6 +75,7 @@ func usage() {
}
func initParserMode() {
// Keep this in sync with go/format/format.go.
parserMode = parser.ParseComments
if *allErrors {
parserMode |= parser.AllErrors

View File

@@ -0,0 +1,10 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
func init() {
// Type parameters are allowed on the go2go branch.
allowTypeParams = true
}

View File

@@ -518,6 +518,9 @@ var depsRules = `
FMT, container/heap, math/rand
< internal/trace;
# go2go: a package that should only exist on the dev.go2go branch
go/build, go/importer, go/printer, go/types, log < go/go2go;
`
// listStdPkgs returns the same list of packages as "go list std".

View File

@@ -38,7 +38,13 @@ const (
var config = printer.Config{Mode: printerMode, Tabwidth: tabWidth}
const parserMode = parser.ParseComments
const (
parserMode = parser.ParseComments | parseTypeParams
// parseTypeParams tells go/parser to parse type parameters. Must be kept in
// sync with go/parser/interface.go.
parseTypeParams parser.Mode = 1 << 30
)
// Node formats node in canonical gofmt style and writes the result to dst.
//

276
src/go/go2go/go2go.go Normal file
View File

@@ -0,0 +1,276 @@
// Copyright 2020 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 go2go rewrites polymorphic code into non-polymorphic code.
package go2go
import (
"bytes"
"fmt"
"go/ast"
"go/parser"
"go/token"
"go/types"
"io"
"os"
"path/filepath"
"sort"
"strings"
)
// parseTypeParams tells go/parser to parse type parameters. Must be kept in
// sync with go/parser/interface.go.
const parseTypeParams parser.Mode = 1 << 30
// rewritePrefix is what we put at the start of each newly generated .go file.
const rewritePrefix = "// Code generated by go2go; DO NOT EDIT.\n\n"
// Rewrite rewrites the contents of a single directory.
// It looks for all files with the extension .go2, and parses
// them as a single package. It writes out a .go file with any
// polymorphic code rewritten into normal code.
func Rewrite(importer *Importer, dir string) error {
_, err := rewriteToPkgs(importer, "", dir)
return err
}
// rewriteToPkgs rewrites the contents of a single directory,
// and returns the types.Packages that it computes.
func rewriteToPkgs(importer *Importer, importPath, dir string) ([]*types.Package, error) {
go2files, gofiles, err := go2Files(dir)
if err != nil {
return nil, err
}
if err := checkAndRemoveGofiles(dir, gofiles); err != nil {
return nil, err
}
return rewriteFilesInPath(importer, importPath, dir, go2files)
}
// namedAST holds a file name and the AST parsed from that file.
type namedAST struct {
name string
ast *ast.File
}
// RewriteFiles rewrites a set of .go2 files in dir.
func RewriteFiles(importer *Importer, dir string, go2files []string) ([]*types.Package, error) {
return rewriteFilesInPath(importer, "", dir, go2files)
}
// rewriteFilesInPath rewrites a set of .go2 files in dir for importPath.
func rewriteFilesInPath(importer *Importer, importPath, dir string, go2files []string) ([]*types.Package, error) {
fset := token.NewFileSet()
pkgs, err := parseFiles(importer, dir, go2files, fset)
if err != nil {
return nil, err
}
var rpkgs []*types.Package
var tpkgs [][]namedAST
for _, pkg := range pkgs {
pkgfiles := make([]namedAST, 0, len(pkg.Files))
for n, f := range pkg.Files {
pkgfiles = append(pkgfiles, namedAST{n, f})
}
sort.Slice(pkgfiles, func(i, j int) bool {
return pkgfiles[i].name < pkgfiles[j].name
})
asts := make([]*ast.File, 0, len(pkgfiles))
for _, a := range pkgfiles {
asts = append(asts, a.ast)
}
var merr multiErr
conf := types.Config{
Importer: importer,
Error: merr.add,
}
path := importPath
if path == "" {
path = pkg.Name
}
tpkg, err := conf.Check(path, fset, asts, importer.info)
if err != nil {
return nil, fmt.Errorf("type checking failed for %s\n%v", pkg.Name, merr)
}
importer.record(pkg.Name, pkgfiles, importPath, tpkg, asts)
rpkgs = append(rpkgs, tpkg)
tpkgs = append(tpkgs, pkgfiles)
}
for i, tpkg := range tpkgs {
addImportable := 0
for j, pkgfile := range tpkg {
if !strings.HasSuffix(pkgfile.name, "_test.go2") {
addImportable = j
break
}
}
for j, pkgfile := range tpkg {
if err := rewriteFile(dir, fset, importer, importPath, rpkgs[i], pkgfile.name, pkgfile.ast, j == addImportable); err != nil {
return nil, err
}
}
}
return rpkgs, nil
}
// RewriteBuffer rewrites the contents of a single file, in a buffer.
// It returns a modified buffer. The filename parameter is only used
// for error messages.
func RewriteBuffer(importer *Importer, filename string, file []byte) ([]byte, error) {
fset := token.NewFileSet()
pf, err := parser.ParseFile(fset, filename, file, parseTypeParams)
if err != nil {
return nil, err
}
var merr multiErr
conf := types.Config{
Importer: importer,
Error: merr.add,
}
tpkg, err := conf.Check(pf.Name.Name, fset, []*ast.File{pf}, importer.info)
if err != nil {
return nil, fmt.Errorf("type checking failed for %s\n%v", pf.Name.Name, merr)
}
importer.addIDs(pf)
if err := rewriteAST(fset, importer, "", tpkg, pf, true); err != nil {
return nil, err
}
var buf bytes.Buffer
fmt.Fprintln(&buf, rewritePrefix)
if err := config.Fprint(&buf, fset, pf); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
// go2Files returns the list of files in dir with a .go2 extension
// and a list of files with a .go extension.
// This returns an error if it finds any .go files that do not start
// with rewritePrefix.
func go2Files(dir string) (go2files []string, gofiles []string, err error) {
f, err := os.Open(dir)
if err != nil {
return nil, nil, err
}
defer f.Close()
files, err := f.Readdirnames(0)
if err != nil {
return nil, nil, fmt.Errorf("reading directory %s: %w", dir, err)
}
go2files = make([]string, 0, len(files))
gofiles = make([]string, 0, len(files))
for _, f := range files {
switch filepath.Ext(f) {
case ".go2":
go2files = append(go2files, f)
case ".go":
gofiles = append(gofiles, f)
}
}
return go2files, gofiles, nil
}
// checkAndRemoveGofiles looks through all the .go files.
// Any .go file that starts with rewritePrefix is removed.
// Any other .go file is reported as an error.
// This is intended to make it harder for go2go to break a
// traditional Go package.
func checkAndRemoveGofiles(dir string, gofiles []string) error {
for _, f := range gofiles {
if err := checkGoFile(dir, f); err != nil {
return err
}
if err := os.Remove(filepath.Join(dir, f)); err != nil {
return err
}
}
return nil
}
// checkGofile reports an error if the file does not start with rewritePrefix.
func checkGoFile(dir, f string) error {
o, err := os.Open(filepath.Join(dir, f))
if err != nil {
return err
}
defer o.Close()
var buf [100]byte
n, err := o.Read(buf[:])
if n > 0 && !strings.HasPrefix(string(buf[:n]), rewritePrefix) {
return fmt.Errorf("Go file %s was not created by go2go", f)
}
if err != nil && err != io.EOF {
return err
}
return nil
}
// parseFiles parses a list of .go2 files.
func parseFiles(importer *Importer, dir string, go2files []string, fset *token.FileSet) ([]*ast.Package, error) {
pkgs := make(map[string]*ast.Package)
for _, go2f := range go2files {
mode := parseTypeParams
filename := filepath.Join(dir, go2f)
pf, err := parser.ParseFile(fset, filename, nil, mode)
if err != nil {
return nil, err
}
name := pf.Name.Name
pkg, ok := pkgs[name]
if !ok {
pkg = &ast.Package{
Name: name,
Files: make(map[string]*ast.File),
}
pkgs[name] = pkg
}
pkg.Files[filename] = pf
}
rpkgs := make([]*ast.Package, 0, len(pkgs))
for _, pkg := range pkgs {
rpkgs = append(rpkgs, pkg)
}
sort.Slice(rpkgs, func(i, j int) bool {
return rpkgs[i].Name < rpkgs[j].Name
})
return rpkgs, nil
}
// multiErr is an error value that accumulates type checking errors.
type multiErr []error
// The add methods adds another error to a multiErr.
func (m *multiErr) add(err error) {
*m = append(*m, err)
}
// The Error method returns the accumulated errors.
func (m multiErr) Error() string {
if len(m) == 0 {
return "internal error: empty multiErr"
}
var sb strings.Builder
for _, e := range m {
fmt.Fprintln(&sb, e)
}
return sb.String()
}

573
src/go/go2go/importer.go Normal file
View File

@@ -0,0 +1,573 @@
// Copyright 2020 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 go2go
import (
"bytes"
"fmt"
"go/ast"
"go/build"
"go/importer"
"go/parser"
"go/token"
"go/types"
"internal/goroot"
"io/ioutil"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"sort"
"strings"
"unicode"
)
// Importer implements the types.ImporterFrom interface.
// It looks for Go2 packages using GO2PATH.
// Imported Go2 packages are rewritten to normal Go packages.
// This type also tracks references across imported packages.
type Importer struct {
// The default importer, for Go1 packages.
defaultImporter types.ImporterFrom
// Temporary directory used to rewrite packages.
tmpdir string
// Aggregated info from go/types.
info *types.Info
// Map from import path to directory holding rewritten files.
translated map[string]string
// Map from import path to package information.
packages map[string]*types.Package
// Map from import path to list of import paths that it imports.
imports map[string][]string
// Map from Object to AST function declaration for
// parameterized functions.
idToFunc map[types.Object]*ast.FuncDecl
// Map from Object to AST type definition for parameterized types.
idToTypeSpec map[types.Object]*ast.TypeSpec
// Map from a Package to the instantiations we've created
// for that package. This doesn't really belong here,
// since it doesn't deal with import information,
// but Importer is a useful common location to store the data.
instantiations map[*types.Package]*instantiations
// build tags
tags map[string]bool
}
var _ types.ImporterFrom = &Importer{}
// NewImporter returns a new Importer.
// The tmpdir will become a GOPATH with translated files.
func NewImporter(tmpdir string) *Importer {
info := &types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
Defs: make(map[*ast.Ident]types.Object),
Uses: make(map[*ast.Ident]types.Object),
}
types.SetInferred(info, make(map[ast.Expr]types.Inferred))
return &Importer{
defaultImporter: importer.Default().(types.ImporterFrom),
tmpdir: tmpdir,
info: info,
translated: make(map[string]string),
packages: make(map[string]*types.Package),
imports: make(map[string][]string),
idToFunc: make(map[types.Object]*ast.FuncDecl),
idToTypeSpec: make(map[types.Object]*ast.TypeSpec),
instantiations: make(map[*types.Package]*instantiations),
tags: make(map[string]bool),
}
}
func (imp *Importer) SetTags(tags []string) {
for _, tag := range tags {
imp.tags[tag] = true
}
}
// Import should never be called. This is the old API; current code
// uses ImportFrom. This method still needs to be defined in order
// to implement the interface.
func (imp *Importer) Import(path string) (*types.Package, error) {
log.Fatal("unexpected call to Import method")
return nil, nil
}
// ImportFrom looks for a Go2 package, and if not found tries the
// default importer.
func (imp *Importer) ImportFrom(importPath, dir string, mode types.ImportMode) (*types.Package, error) {
if build.IsLocalImport(importPath) {
return imp.localImport(importPath, dir)
}
if imp.translated[importPath] != "" {
tpkg, ok := imp.packages[importPath]
if !ok {
return nil, fmt.Errorf("circular import when processing %q", importPath)
}
return tpkg, nil
}
var pdir string
if go2path := os.Getenv("GO2PATH"); go2path != "" {
pdir = imp.findFromPath(go2path, importPath)
}
if pdir == "" {
bpkg, err := build.Import(importPath, dir, build.FindOnly)
if err != nil {
return nil, err
}
pdir = bpkg.Dir
}
// If the directory holds .go2 files, we need to translate them.
fdir, err := os.Open(pdir)
if err != nil {
return nil, err
}
defer fdir.Close()
names, err := fdir.Readdirnames(-1)
if err != nil {
return nil, err
}
var gofiles, go2files []string
for _, name := range names {
switch filepath.Ext(name) {
case ".go":
gofiles = append(gofiles, name)
case ".go2":
go2files = append(go2files, name)
}
}
if len(go2files) == 0 {
return imp.importGo1Package(importPath, dir, mode, pdir, gofiles)
}
if len(gofiles) > 0 {
for _, gofile := range gofiles {
if err := checkGoFile(pdir, gofile); err != nil {
return nil, err
}
}
}
tdir := filepath.Join(imp.tmpdir, "src", importPath)
if err := os.MkdirAll(tdir, 0755); err != nil {
return nil, err
}
for _, name := range go2files {
data, err := ioutil.ReadFile(filepath.Join(pdir, name))
if err != nil {
return nil, err
}
if err := ioutil.WriteFile(filepath.Join(tdir, name), data, 0644); err != nil {
return nil, err
}
}
imp.translated[importPath] = tdir
tpkgs, err := rewriteToPkgs(imp, importPath, tdir)
if err != nil {
return nil, err
}
switch len(tpkgs) {
case 1:
return tpkgs[0], nil
case 2:
if strings.HasSuffix(tpkgs[0].Name(), "_test") {
return tpkgs[1], nil
} else if strings.HasSuffix(tpkgs[1].Name(), "_test") {
return tpkgs[0], nil
}
}
return nil, fmt.Errorf("unexpected number of packages (%d) for %q (directory %q)", len(tpkgs), importPath, pdir)
}
// findFromPath looks for a directory under gopath.
func (imp *Importer) findFromPath(gopath, dir string) string {
if filepath.IsAbs(dir) || build.IsLocalImport(dir) {
return ""
}
for _, pd := range strings.Split(gopath, string(os.PathListSeparator)) {
d := filepath.Join(pd, "src", dir)
if fi, err := os.Stat(d); err == nil && fi.IsDir() {
return d
}
}
return ""
}
// importGo1Package handles importing a package with .go files rather
// than .go2 files. The default importer can do this if the package
// has been installed, but not otherwise. Installing the package using
// "go install" won't work if the Go 1 package depends on a Go 2 package.
// So use the default importer for a package in the standard library,
// and otherwise use go/types.
func (imp *Importer) importGo1Package(importPath, dir string, mode types.ImportMode, pdir string, gofiles []string) (*types.Package, error) {
if goroot.IsStandardPackage(runtime.GOROOT(), "gc", importPath) {
return imp.defaultImporter.ImportFrom(importPath, dir, mode)
}
if len(gofiles) == 0 {
return nil, fmt.Errorf("importing %q: no Go files in %s", importPath, pdir)
}
fset := token.NewFileSet()
filter := func(fi os.FileInfo) bool {
name := fi.Name()
if strings.HasSuffix(name, "_test.go") {
return false
}
return imp.shouldInclude(path.Join(pdir, name))
}
pkgs, err := parser.ParseDir(fset, pdir, filter, 0)
if err != nil {
return nil, err
}
if len(pkgs) > 1 {
return nil, fmt.Errorf("importing %q: multiple Go packages in %s", importPath, pdir)
}
var apkg *ast.Package
for _, apkg = range pkgs {
break
}
var asts []*ast.File
for _, f := range apkg.Files {
asts = append(asts, f)
}
sort.Slice(asts, func(i, j int) bool {
return asts[i].Name.Name < asts[j].Name.Name
})
var merr multiErr
conf := types.Config{
Importer: imp,
Error: merr.add,
}
tpkg, err := conf.Check(importPath, fset, asts, imp.info)
if err != nil {
return nil, merr
}
return tpkg, nil
}
// installGo1Package runs "go install" to install a package.
// This is used for Go 1 packages, because the default
// importer looks at .a files, not sources.
// This is best effort; we don't report an error.
func (imp *Importer) installGo1Package(dir string) {
gotool := filepath.Join(runtime.GOROOT(), "bin", "go")
cmd := exec.Command(gotool, "install")
cmd.Dir = dir
cmd.Run()
}
// Register registers a package under an import path.
// This is for tests that use directives like //compiledir.
func (imp *Importer) Register(importPath string, tpkgs []*types.Package) error {
switch len(tpkgs) {
case 1:
imp.packages[importPath] = tpkgs[0]
return nil
case 2:
if strings.HasSuffix(tpkgs[0].Name(), "_test") {
imp.packages[importPath] = tpkgs[1]
return nil
} else if strings.HasSuffix(tpkgs[1].Name(), "_test") {
imp.packages[importPath] = tpkgs[0]
return nil
}
}
return fmt.Errorf("unexpected number of packages (%d) for %q", len(tpkgs), importPath)
}
// localImport handles a local import such as
// import "./a"
// This is for tests that use directives like //compiledir.
func (imp *Importer) localImport(importPath, dir string) (*types.Package, error) {
tpkg, ok := imp.packages[strings.TrimPrefix(importPath, "./")]
if !ok {
return nil, fmt.Errorf("cannot find local import %q", importPath)
}
return tpkg, nil
}
// record records information for a package, for use when working
// with packages that import this one.
func (imp *Importer) record(pkgName string, pkgfiles []namedAST, importPath string, tpkg *types.Package, asts []*ast.File) {
if !strings.HasSuffix(pkgName, "_test") {
if importPath != "" {
imp.packages[importPath] = tpkg
}
imp.imports[importPath] = imp.collectImports(asts)
}
for _, nast := range pkgfiles {
imp.addIDs(nast.ast)
}
}
// collectImports returns all the imports paths imported by any of the ASTs.
func (imp *Importer) collectImports(asts []*ast.File) []string {
m := make(map[string]bool)
for _, a := range asts {
for _, decl := range a.Decls {
gen, ok := decl.(*ast.GenDecl)
if !ok || gen.Tok != token.IMPORT {
continue
}
for _, spec := range gen.Specs {
imp := spec.(*ast.ImportSpec)
if imp.Name != nil {
// We don't try to handle import aliases.
continue
}
path := strings.TrimPrefix(strings.TrimSuffix(imp.Path.Value, `"`), `"`)
m[path] = true
}
}
}
s := make([]string, 0, len(m))
for p := range m {
s = append(s, p)
}
sort.Strings(s)
return s
}
// addIDs finds IDs for generic functions and types and adds them to a map.
func (imp *Importer) addIDs(f *ast.File) {
for _, decl := range f.Decls {
switch decl := decl.(type) {
case *ast.FuncDecl:
if isParameterizedFuncDecl(decl, imp.info) {
obj, ok := imp.info.Defs[decl.Name]
if !ok {
panic(fmt.Sprintf("no types.Object for %q", decl.Name.Name))
}
imp.idToFunc[obj] = decl
}
case *ast.GenDecl:
if decl.Tok == token.TYPE {
for _, s := range decl.Specs {
ts := s.(*ast.TypeSpec)
obj, ok := imp.info.Defs[ts.Name]
if !ok {
panic(fmt.Sprintf("no types.Object for %q", ts.Name.Name))
}
imp.idToTypeSpec[obj] = ts
}
}
}
}
}
// lookupPackage looks up a package by path.
func (imp *Importer) lookupPackage(path string) (*types.Package, bool) {
pkg, ok := imp.packages[strings.TrimPrefix(path, "./")]
return pkg, ok
}
// lookupFunc looks up a function by Object.
func (imp *Importer) lookupFunc(obj types.Object) (*ast.FuncDecl, bool) {
decl, ok := imp.idToFunc[obj]
return decl, ok
}
// lookupTypeSpec looks up a type by Object.
func (imp *Importer) lookupTypeSpec(obj types.Object) (*ast.TypeSpec, bool) {
ts, ok := imp.idToTypeSpec[obj]
return ts, ok
}
// transitiveImports returns all the transitive imports of an import path.
func (imp *Importer) transitiveImports(path string) []string {
return imp.gatherTransitiveImports(path, make(map[string]bool))
}
// gatherTransitiveImports returns all the transitive imports of an import path,
// using a map to avoid duplicate work.
func (imp *Importer) gatherTransitiveImports(path string, m map[string]bool) []string {
imports := imp.imports[path]
if len(imports) == 0 {
return nil
}
var r []string
for _, im := range imports {
r = append(r, im)
if !m[im] {
m[im] = true
r = append(r, imp.gatherTransitiveImports(im, m)...)
}
}
dup := make(map[string]bool)
for _, p := range r {
dup[p] = true
}
r = make([]string, 0, len(dup))
for p := range dup {
r = append(r, p)
}
sort.Strings(r)
return r
}
var slashslash = []byte("//")
// shouldInclude reports whether it is okay to use this file,
// The rule is that in the file's leading run of // comments
// and blank lines, which must be followed by a blank line
// (to avoid including a Go package clause doc comment),
// lines beginning with '// +build' are taken as build directives.
//
// The file is accepted only if each such line lists something
// matching the file. For example:
//
// // +build windows linux
//
// marks the file as applicable only on Windows and Linux.
//
// If tags["*"] is true, then ShouldBuild will consider every
// build tag except "ignore" to be both true and false for
// the purpose of satisfying build tags, in order to estimate
// (conservatively) whether a file could ever possibly be used
// in any build.
//
// This code was copied from the go command internals.
func (imp *Importer) shouldInclude(path string) bool {
content, err := os.ReadFile(path)
if err != nil {
return false
}
// Pass 1. Identify leading run of // comments and blank lines,
// which must be followed by a blank line.
end := 0
p := content
for len(p) > 0 {
line := p
if i := bytes.IndexByte(line, '\n'); i >= 0 {
line, p = line[:i], p[i+1:]
} else {
p = p[len(p):]
}
line = bytes.TrimSpace(line)
if len(line) == 0 { // Blank line
end = len(content) - len(p)
continue
}
if !bytes.HasPrefix(line, slashslash) { // Not comment line
break
}
}
content = content[:end]
// Pass 2. Process each line in the run.
p = content
allok := true
for len(p) > 0 {
line := p
if i := bytes.IndexByte(line, '\n'); i >= 0 {
line, p = line[:i], p[i+1:]
} else {
p = p[len(p):]
}
line = bytes.TrimSpace(line)
if !bytes.HasPrefix(line, slashslash) {
continue
}
line = bytes.TrimSpace(line[len(slashslash):])
if len(line) > 0 && line[0] == '+' {
// Looks like a comment +line.
f := strings.Fields(string(line))
if f[0] == "+build" {
ok := false
for _, tok := range f[1:] {
if matchTags(tok, imp.tags) {
ok = true
}
}
if !ok {
allok = false
}
}
}
}
return allok
}
// matchTags reports whether the name is one of:
//
// tag (if tags[tag] is true)
// !tag (if tags[tag] is false)
// a comma-separated list of any of these
//
func matchTags(name string, tags map[string]bool) bool {
if name == "" {
return false
}
if i := strings.Index(name, ","); i >= 0 {
// comma-separated list
ok1 := matchTags(name[:i], tags)
ok2 := matchTags(name[i+1:], tags)
return ok1 && ok2
}
if strings.HasPrefix(name, "!!") { // bad syntax, reject always
return false
}
if strings.HasPrefix(name, "!") { // negation
return len(name) > 1 && matchTag(name[1:], tags, false)
}
return matchTag(name, tags, true)
}
// matchTag reports whether the tag name is valid and satisfied by tags[name]==want.
func matchTag(name string, tags map[string]bool, want bool) bool {
// Tags must be letters, digits, underscores or dots.
// Unlike in Go identifiers, all digits are fine (e.g., "386").
for _, c := range name {
if !unicode.IsLetter(c) && !unicode.IsDigit(c) && c != '_' && c != '.' {
return false
}
}
if tags["*"] && name != "" && name != "ignore" {
// Special case for gathering all possible imports:
// if we put * in the tags map then all tags
// except "ignore" are considered both present and not
// (so we return true no matter how 'want' is set).
return true
}
have := tags[name]
if name == "linux" {
have = have || tags["android"]
}
if name == "solaris" {
have = have || tags["illumos"]
}
if name == "darwin" {
have = have || tags["ios"]
}
return have == want
}

985
src/go/go2go/instantiate.go Normal file
View File

@@ -0,0 +1,985 @@
// Copyright 2020 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 go2go
import (
"fmt"
"go/ast"
"go/token"
"go/types"
)
// typeArgs holds type arguments for the function that we are instantiating.
// We can look them up either with a types.Object associated with an ast.Ident,
// or with a types.TypeParam.
type typeArgs struct {
types []types.Type // type arguments in order
toAST map[types.Object]ast.Expr
toTyp map[*types.TypeParam]types.Type
}
// newTypeArgs returns a new typeArgs value.
func newTypeArgs(typeTypes []types.Type) *typeArgs {
return &typeArgs{
types: typeTypes,
toAST: make(map[types.Object]ast.Expr),
toTyp: make(map[*types.TypeParam]types.Type),
}
}
// typeArgsFromFields builds mappings from a list of type parameters
// expressed as ast.Field values.
func typeArgsFromFields(t *translator, astTypes []ast.Expr, typeTypes []types.Type, tparams []*ast.Field) *typeArgs {
ta := newTypeArgs(typeTypes)
i := 0
for _, tf := range tparams {
for _, tn := range tf.Names {
obj, ok := t.importer.info.Defs[tn]
if !ok {
panic(fmt.Sprintf("no object for type parameter %q", tn))
}
objType := obj.Type()
objParam, ok := objType.(*types.TypeParam)
if !ok {
panic(fmt.Sprintf("%v is not a TypeParam", objParam))
}
ta.add(obj, objParam, astTypes[i], typeTypes[i])
i++
}
}
return ta
}
// typeArgsFromExprs builds mappings from a list of type parameters
// expressed as ast.Expr values.
func typeArgsFromExprs(t *translator, astTypes []ast.Expr, typeTypes []types.Type, tparams []ast.Expr) *typeArgs {
ta := newTypeArgs(typeTypes)
for i, ti := range tparams {
obj, ok := t.importer.info.Defs[ti.(*ast.Ident)]
if !ok {
panic(fmt.Sprintf("no object for type parameter %q", ti))
}
objType := obj.Type()
objParam, ok := objType.(*types.TypeParam)
if !ok {
panic(fmt.Sprintf("%v is not a TypeParam", objParam))
}
ta.add(obj, objParam, astTypes[i], typeTypes[i])
}
return ta
}
// add adds mappings for obj to ast and typ.
func (ta *typeArgs) add(obj types.Object, objParam *types.TypeParam, ast ast.Expr, typ types.Type) {
ta.toAST[obj] = ast
ta.toTyp[objParam] = typ
}
// ast returns the AST for obj, and reports whether it exists.
func (ta *typeArgs) ast(obj types.Object) (ast.Expr, bool) {
e, ok := ta.toAST[obj]
return e, ok
}
// typ returns the Type for param, and reports whether it exists.
func (ta *typeArgs) typ(param *types.TypeParam) (types.Type, bool) {
t, ok := ta.toTyp[param]
return t, ok
}
// instantiateFunction creates a new instantiation of a function.
func (t *translator) instantiateFunction(qid qualifiedIdent, astTypes []ast.Expr, typeTypes []types.Type) (*ast.Ident, error) {
name, err := t.instantiatedName(qid, typeTypes)
if err != nil {
return nil, err
}
decl, err := t.findFuncDecl(qid)
if err != nil {
return nil, err
}
ta := typeArgsFromFields(t, astTypes, typeTypes, decl.Type.TParams.List)
instIdent := ast.NewIdent(name)
newDecl := &ast.FuncDecl{
Doc: decl.Doc,
Recv: t.instantiateFieldList(ta, decl.Recv),
Name: instIdent,
Type: t.instantiateExpr(ta, decl.Type).(*ast.FuncType),
Body: t.instantiateBlockStmt(ta, decl.Body),
}
t.newDecls = append(t.newDecls, newDecl)
return instIdent, nil
}
// findFuncDecl looks for the FuncDecl for qid.
func (t *translator) findFuncDecl(qid qualifiedIdent) (*ast.FuncDecl, error) {
obj := t.findTypesObject(qid)
if obj == nil {
return nil, fmt.Errorf("could not find Object for %q", qid)
}
decl, ok := t.importer.lookupFunc(obj)
if !ok {
return nil, fmt.Errorf("could not find function body for %q", qid)
}
return decl, nil
}
// findTypesObject looks up the types.Object for qid.
// It returns nil if the ID is not found.
func (t *translator) findTypesObject(qid qualifiedIdent) types.Object {
if qid.pkg == nil {
if obj := t.importer.info.ObjectOf(qid.ident); obj != nil {
// Ignore an embedded struct field.
// We want the type, not the field.
if _, ok := obj.(*types.Var); !ok {
return obj
}
}
return t.tpkg.Scope().Lookup(qid.ident.Name)
} else {
return qid.pkg.Scope().Lookup(qid.ident.Name)
}
}
// instantiateType creates a new instantiation of a type.
func (t *translator) instantiateTypeDecl(qid qualifiedIdent, typ *types.Named, astTypes []ast.Expr, typeTypes []types.Type, instIdent *ast.Ident) (types.Type, error) {
spec, err := t.findTypeSpec(qid)
if err != nil {
return nil, err
}
ta := typeArgsFromFields(t, astTypes, typeTypes, spec.TParams.List)
newSpec := &ast.TypeSpec{
Doc: spec.Doc,
Name: instIdent,
Assign: spec.Assign,
Type: t.instantiateExpr(ta, spec.Type),
Comment: spec.Comment,
}
newDecl := &ast.GenDecl{
Tok: token.TYPE,
Specs: []ast.Spec{newSpec},
}
t.newDecls = append(t.newDecls, newDecl)
// If typ already has type arguments, then they should be correct.
// If it doesn't, we want to use typeTypes.
typeWithTargs := typ
if len(typ.TArgs()) == 0 {
typeWithTargs = t.updateTArgs(typ, typeTypes)
}
instType := t.instantiateType(ta, typeWithTargs)
t.setType(instIdent, instType)
nm := typ.NumMethods()
for i := 0; i < nm; i++ {
method := typ.Method(i)
mast, ok := t.importer.lookupFunc(method)
if !ok {
panic(fmt.Sprintf("no AST for method %v", method))
}
rtyp := mast.Recv.List[0].Type
newRtype := ast.Expr(ast.NewIdent(instIdent.Name))
if p, ok := rtyp.(*ast.StarExpr); ok {
rtyp = p.X
newRtype = &ast.StarExpr{
X: newRtype,
}
}
var tparams []ast.Expr
switch rtyp := rtyp.(type) {
case *ast.IndexExpr:
tparams = unpackExpr(rtyp.Index)
default:
panic("unexpected AST type")
}
ta := typeArgsFromExprs(t, astTypes, typeTypes, tparams)
var names []*ast.Ident
if mnames := mast.Recv.List[0].Names; len(mnames) > 0 {
names = []*ast.Ident{mnames[0]}
}
newDecl := &ast.FuncDecl{
Doc: mast.Doc,
Recv: &ast.FieldList{
Opening: mast.Recv.Opening,
List: []*ast.Field{
{
Doc: mast.Recv.List[0].Doc,
Names: names,
Type: newRtype,
Comment: mast.Recv.List[0].Comment,
},
},
Closing: mast.Recv.Closing,
},
Name: mast.Name,
Type: t.instantiateExpr(ta, mast.Type).(*ast.FuncType),
Body: t.instantiateBlockStmt(ta, mast.Body),
}
t.newDecls = append(t.newDecls, newDecl)
}
return instType, nil
}
// findTypeSpec looks for the TypeSpec for qid.
func (t *translator) findTypeSpec(qid qualifiedIdent) (*ast.TypeSpec, error) {
obj := t.findTypesObject(qid)
if obj == nil {
return nil, fmt.Errorf("could not find Object for %q", qid)
}
spec, ok := t.importer.lookupTypeSpec(obj)
if !ok {
return nil, fmt.Errorf("could not find type spec for %q", qid)
}
if spec.Assign != token.NoPos {
// This is a type alias that we need to resolve.
typ := t.lookupType(spec.Type)
if typ != nil {
if named, ok := typ.(*types.Named); ok {
if s, ok := t.importer.lookupTypeSpec(named.Obj()); ok {
spec = s
}
}
}
}
if spec.TParams == nil {
return nil, fmt.Errorf("found type spec for %q but it has no type parameters", qid)
}
return spec, nil
}
// instantiateDecl instantiates a declaration.
func (t *translator) instantiateDecl(ta *typeArgs, d ast.Decl) ast.Decl {
switch d := d.(type) {
case nil:
return nil
case *ast.GenDecl:
if len(d.Specs) == 0 {
return d
}
nspecs := make([]ast.Spec, len(d.Specs))
changed := false
for i, s := range d.Specs {
ns := t.instantiateSpec(ta, s)
if ns != s {
changed = true
}
nspecs[i] = ns
}
if !changed {
return d
}
return &ast.GenDecl{
Doc: d.Doc,
TokPos: d.TokPos,
Tok: d.Tok,
Lparen: d.Lparen,
Specs: nspecs,
Rparen: d.Rparen,
}
default:
panic(fmt.Sprintf("unimplemented Decl %T", d))
}
}
// instantiateSpec instantiates a spec node.
func (t *translator) instantiateSpec(ta *typeArgs, s ast.Spec) ast.Spec {
switch s := s.(type) {
case nil:
return nil
case *ast.ValueSpec:
typ := t.instantiateExpr(ta, s.Type)
values, changed := t.instantiateExprList(ta, s.Values)
if typ == s.Type && !changed {
return s
}
return &ast.ValueSpec{
Doc: s.Doc,
Names: s.Names,
Type: typ,
Values: values,
Comment: s.Comment,
}
case *ast.TypeSpec:
if s.TParams != nil {
t.err = fmt.Errorf("%s: go2go tool does not support local parameterized types", t.fset.Position(s.Pos()))
return nil
}
typ := t.instantiateExpr(ta, s.Type)
if typ == s.Type {
return s
}
return &ast.TypeSpec{
Doc: s.Doc,
Name: s.Name,
Assign: s.Assign,
Type: typ,
Comment: s.Comment,
}
default:
panic(fmt.Sprintf("unimplemented Spec %T", s))
}
}
// instantiateStmt instantiates a statement.
func (t *translator) instantiateStmt(ta *typeArgs, s ast.Stmt) ast.Stmt {
switch s := s.(type) {
case nil:
return nil
case *ast.DeclStmt:
decl := t.instantiateDecl(ta, s.Decl)
if decl == s.Decl {
return s
}
return &ast.DeclStmt{
Decl: decl,
}
case *ast.EmptyStmt:
return s
case *ast.LabeledStmt:
stmt := t.instantiateStmt(ta, s.Stmt)
if stmt == s.Stmt {
return s
}
return &ast.LabeledStmt{
Label: s.Label,
Colon: s.Colon,
Stmt: stmt,
}
case *ast.ExprStmt:
x := t.instantiateExpr(ta, s.X)
if x == s.X {
return s
}
return &ast.ExprStmt{
X: x,
}
case *ast.SendStmt:
ch := t.instantiateExpr(ta, s.Chan)
value := t.instantiateExpr(ta, s.Value)
if ch == s.Chan && value == s.Value {
return s
}
return &ast.SendStmt{
Chan: ch,
Arrow: s.Arrow,
Value: value,
}
case *ast.IncDecStmt:
x := t.instantiateExpr(ta, s.X)
if x == s.X {
return s
}
return &ast.IncDecStmt{
X: x,
TokPos: s.TokPos,
Tok: s.Tok,
}
case *ast.AssignStmt:
lhs, lchanged := t.instantiateExprList(ta, s.Lhs)
rhs, rchanged := t.instantiateExprList(ta, s.Rhs)
if !lchanged && !rchanged {
return s
}
return &ast.AssignStmt{
Lhs: lhs,
TokPos: s.TokPos,
Tok: s.Tok,
Rhs: rhs,
}
case *ast.GoStmt:
call := t.instantiateExpr(ta, s.Call).(*ast.CallExpr)
if call == s.Call {
return s
}
return &ast.GoStmt{
Go: s.Go,
Call: call,
}
case *ast.DeferStmt:
call := t.instantiateExpr(ta, s.Call).(*ast.CallExpr)
if call == s.Call {
return s
}
return &ast.DeferStmt{
Defer: s.Defer,
Call: call,
}
case *ast.ReturnStmt:
results, changed := t.instantiateExprList(ta, s.Results)
if !changed {
return s
}
return &ast.ReturnStmt{
Return: s.Return,
Results: results,
}
case *ast.BranchStmt:
return s
case *ast.BlockStmt:
return t.instantiateBlockStmt(ta, s)
case *ast.IfStmt:
init := t.instantiateStmt(ta, s.Init)
cond := t.instantiateExpr(ta, s.Cond)
body := t.instantiateBlockStmt(ta, s.Body)
els := t.instantiateStmt(ta, s.Else)
if init == s.Init && cond == s.Cond && body == s.Body && els == s.Else {
return s
}
return &ast.IfStmt{
If: s.If,
Init: init,
Cond: cond,
Body: body,
Else: els,
}
case *ast.CaseClause:
list, listChanged := t.instantiateExprList(ta, s.List)
body, bodyChanged := t.instantiateStmtList(ta, s.Body)
if !listChanged && !bodyChanged {
return s
}
return &ast.CaseClause{
Case: s.Case,
List: list,
Colon: s.Colon,
Body: body,
}
case *ast.SwitchStmt:
init := t.instantiateStmt(ta, s.Init)
tag := t.instantiateExpr(ta, s.Tag)
body := t.instantiateBlockStmt(ta, s.Body)
if init == s.Init && tag == s.Tag && body == s.Body {
return s
}
return &ast.SwitchStmt{
Switch: s.Switch,
Init: init,
Tag: tag,
Body: body,
}
case *ast.TypeSwitchStmt:
init := t.instantiateStmt(ta, s.Init)
assign := t.instantiateStmt(ta, s.Assign)
body := t.instantiateBlockStmt(ta, s.Body)
if init == s.Init && assign == s.Assign && body == s.Body {
return s
}
return &ast.TypeSwitchStmt{
Switch: s.Switch,
Init: init,
Assign: assign,
Body: body,
}
case *ast.CommClause:
comm := t.instantiateStmt(ta, s.Comm)
body, bodyChanged := t.instantiateStmtList(ta, s.Body)
if comm == s.Comm && !bodyChanged {
return s
}
return &ast.CommClause{
Case: s.Case,
Comm: comm,
Colon: s.Colon,
Body: body,
}
case *ast.SelectStmt:
body := t.instantiateBlockStmt(ta, s.Body)
if body == s.Body {
return s
}
return &ast.SelectStmt{
Select: s.Select,
Body: body,
}
case *ast.ForStmt:
init := t.instantiateStmt(ta, s.Init)
cond := t.instantiateExpr(ta, s.Cond)
post := t.instantiateStmt(ta, s.Post)
body := t.instantiateBlockStmt(ta, s.Body)
if init == s.Init && cond == s.Cond && post == s.Post && body == s.Body {
return s
}
return &ast.ForStmt{
For: s.For,
Init: init,
Cond: cond,
Post: post,
Body: body,
}
case *ast.RangeStmt:
key := t.instantiateExpr(ta, s.Key)
value := t.instantiateExpr(ta, s.Value)
x := t.instantiateExpr(ta, s.X)
body := t.instantiateBlockStmt(ta, s.Body)
if key == s.Key && value == s.Value && x == s.X && body == s.Body {
return s
}
return &ast.RangeStmt{
For: s.For,
Key: key,
Value: value,
TokPos: s.TokPos,
Tok: s.Tok,
X: x,
Body: body,
}
default:
panic(fmt.Sprintf("unimplemented Stmt %T", s))
}
}
// instantiateBlockStmt instantiates a BlockStmt.
func (t *translator) instantiateBlockStmt(ta *typeArgs, pbs *ast.BlockStmt) *ast.BlockStmt {
if pbs == nil {
return nil
}
changed := false
stmts := make([]ast.Stmt, len(pbs.List))
for i, s := range pbs.List {
is := t.instantiateStmt(ta, s)
stmts[i] = is
if is != s {
changed = true
}
}
if !changed {
return pbs
}
return &ast.BlockStmt{
Lbrace: pbs.Lbrace,
List: stmts,
Rbrace: pbs.Rbrace,
}
}
// instantiateStmtList instantiates a statement list.
func (t *translator) instantiateStmtList(ta *typeArgs, sl []ast.Stmt) ([]ast.Stmt, bool) {
nsl := make([]ast.Stmt, len(sl))
changed := false
for i, s := range sl {
ns := t.instantiateStmt(ta, s)
if ns != s {
changed = true
}
nsl[i] = ns
}
if !changed {
return sl, false
}
return nsl, true
}
// instantiateFieldList instantiates a field list.
func (t *translator) instantiateFieldList(ta *typeArgs, fl *ast.FieldList) *ast.FieldList {
if fl == nil {
return nil
}
nfl := make([]*ast.Field, len(fl.List))
changed := false
for i, f := range fl.List {
nf := t.instantiateField(ta, f)
if nf != f {
changed = true
}
nfl[i] = nf
}
if !changed {
return fl
}
return &ast.FieldList{
Opening: fl.Opening,
List: nfl,
Closing: fl.Closing,
}
}
// instantiateField instantiates a field.
func (t *translator) instantiateField(ta *typeArgs, f *ast.Field) *ast.Field {
typ := t.instantiateExpr(ta, f.Type)
if typ == f.Type {
return f
}
return &ast.Field{
Doc: f.Doc,
Names: f.Names,
Type: typ,
Tag: f.Tag,
Comment: f.Comment,
}
}
// instantiateExpr instantiates an expression.
func (t *translator) instantiateExpr(ta *typeArgs, e ast.Expr) ast.Expr {
var r ast.Expr
switch e := e.(type) {
case nil:
return nil
case *ast.Ident:
obj := t.importer.info.ObjectOf(e)
if obj != nil {
if typ, ok := ta.ast(obj); ok {
return typ
}
}
return e
case *ast.Ellipsis:
elt := t.instantiateExpr(ta, e.Elt)
if elt == e.Elt {
return e
}
return &ast.Ellipsis{
Ellipsis: e.Ellipsis,
Elt: elt,
}
case *ast.BasicLit:
return e
case *ast.FuncLit:
typ := t.instantiateExpr(ta, e.Type).(*ast.FuncType)
body := t.instantiateBlockStmt(ta, e.Body)
if typ == e.Type && body == e.Body {
return e
}
return &ast.FuncLit{
Type: typ,
Body: body,
}
case *ast.CompositeLit:
typ := t.instantiateExpr(ta, e.Type)
elts, changed := t.instantiateExprList(ta, e.Elts)
if typ == e.Type && !changed {
return e
}
return &ast.CompositeLit{
Type: typ,
Lbrace: e.Lbrace,
Elts: elts,
Rbrace: e.Rbrace,
Incomplete: e.Incomplete,
}
case *ast.ParenExpr:
x := t.instantiateExpr(ta, e.X)
if x == e.X {
return e
}
return &ast.ParenExpr{
Lparen: e.Lparen,
X: x,
Rparen: e.Rparen,
}
case *ast.SelectorExpr:
x := t.instantiateExpr(ta, e.X)
// If this is a reference to an instantiated embedded field,
// we may need to instantiate it. The actual instantiation
// is at the end of the function, as long as we create a
// a new SelectorExpr when needed.
instantiate := false
obj := t.importer.info.ObjectOf(e.Sel)
if obj != nil {
if f, ok := obj.(*types.Var); ok && f.Embedded() {
if named, ok := f.Type().(*types.Named); ok && len(named.TArgs()) > 0 && obj.Name() == named.Obj().Name() {
instantiate = true
}
}
}
if x == e.X && !instantiate {
return e
}
r = &ast.SelectorExpr{
X: x,
Sel: e.Sel,
}
case *ast.IndexExpr:
x := t.instantiateExpr(ta, e.X)
index := t.instantiateExpr(ta, e.Index)
inferredInfo := types.GetInferred(t.importer.info)
origInferred, haveInferred := inferredInfo[e]
var newInferred types.Inferred
inferredChanged := false
if haveInferred {
for _, typ := range origInferred.Targs {
nt := t.instantiateType(ta, typ)
newInferred.Targs = append(newInferred.Targs, nt)
if nt != typ {
inferredChanged = true
}
}
}
if x == e.X && index == e.Index && !inferredChanged {
return e
}
r = &ast.IndexExpr{
X: x,
Lbrack: e.Lbrack,
Index: index,
Rbrack: e.Rbrack,
}
if haveInferred {
inferredInfo[r] = newInferred
}
case *ast.ListExpr:
list, changed := t.instantiateExprList(ta, e.ElemList)
if changed {
r = &ast.ListExpr{ElemList: list}
}
case *ast.SliceExpr:
x := t.instantiateExpr(ta, e.X)
low := t.instantiateExpr(ta, e.Low)
high := t.instantiateExpr(ta, e.High)
max := t.instantiateExpr(ta, e.Max)
if x == e.X && low == e.Low && high == e.High && max == e.Max {
return e
}
r = &ast.SliceExpr{
X: x,
Lbrack: e.Lbrack,
Low: low,
High: high,
Max: max,
Slice3: e.Slice3,
Rbrack: e.Rbrack,
}
case *ast.TypeAssertExpr:
x := t.instantiateExpr(ta, e.X)
typ := t.instantiateExpr(ta, e.Type)
if x == e.X && typ == e.Type {
return e
}
r = &ast.TypeAssertExpr{
X: x,
Lparen: e.Lparen,
Type: typ,
Rparen: e.Rparen,
}
case *ast.CallExpr:
fun := t.instantiateExpr(ta, e.Fun)
args, argsChanged := t.instantiateExprList(ta, e.Args)
inferredInfo := types.GetInferred(t.importer.info)
origInferred, haveInferred := inferredInfo[e]
var newInferred types.Inferred
inferredChanged := false
if haveInferred {
for _, typ := range origInferred.Targs {
nt := t.instantiateType(ta, typ)
newInferred.Targs = append(newInferred.Targs, nt)
if nt != typ {
inferredChanged = true
}
}
newInferred.Sig = t.instantiateType(ta, origInferred.Sig).(*types.Signature)
if newInferred.Sig != origInferred.Sig {
inferredChanged = true
}
}
if fun == e.Fun && !argsChanged && !inferredChanged {
return e
}
r = &ast.CallExpr{
Fun: fun,
Lparen: e.Lparen,
Args: args,
Ellipsis: e.Ellipsis,
Rparen: e.Rparen,
}
if haveInferred {
inferredInfo[r] = newInferred
}
case *ast.StarExpr:
x := t.instantiateExpr(ta, e.X)
if x == e.X {
return e
}
r = &ast.StarExpr{
Star: e.Star,
X: x,
}
case *ast.UnaryExpr:
x := t.instantiateExpr(ta, e.X)
if x == e.X {
return e
}
r = &ast.UnaryExpr{
OpPos: e.OpPos,
Op: e.Op,
X: x,
}
case *ast.BinaryExpr:
x := t.instantiateExpr(ta, e.X)
y := t.instantiateExpr(ta, e.Y)
if x == e.X && y == e.Y {
return e
}
r = &ast.BinaryExpr{
X: x,
OpPos: e.OpPos,
Op: e.Op,
Y: y,
}
case *ast.KeyValueExpr:
key := t.instantiateExpr(ta, e.Key)
value := t.instantiateExpr(ta, e.Value)
if key == e.Key && value == e.Value {
return e
}
r = &ast.KeyValueExpr{
Key: key,
Colon: e.Colon,
Value: value,
}
case *ast.ArrayType:
ln := t.instantiateExpr(ta, e.Len)
elt := t.instantiateExpr(ta, e.Elt)
if ln == e.Len && elt == e.Elt {
return e
}
r = &ast.ArrayType{
Lbrack: e.Lbrack,
Len: ln,
Elt: elt,
}
case *ast.StructType:
fields := e.Fields.List
newFields := make([]*ast.Field, 0, len(fields))
changed := false
for _, f := range fields {
newFields = append(newFields, f)
if len(f.Names) > 0 {
continue
}
isPtr := false
ftyp := f.Type
if star, ok := ftyp.(*ast.StarExpr); ok {
ftyp = star.X
isPtr = true
}
id, ok := ftyp.(*ast.Ident)
if !ok {
continue
}
typ := t.lookupType(id)
if typ == nil {
continue
}
typeParam, ok := typ.(*types.TypeParam)
if !ok {
continue
}
instType := t.instantiateType(ta, typeParam)
if isPtr {
instType = types.NewPointer(instType)
}
newField := &ast.Field{
Doc: f.Doc,
Names: []*ast.Ident{id},
Type: t.typeToAST(instType),
Tag: f.Tag,
Comment: f.Comment,
}
newFields[len(newFields)-1] = newField
changed = true
}
fl := e.Fields
if changed {
fl = &ast.FieldList{
Opening: fl.Opening,
List: newFields,
Closing: fl.Closing,
}
}
newFl := t.instantiateFieldList(ta, fl)
if !changed && newFl == fl {
return e
}
r = &ast.StructType{
Struct: e.Struct,
Fields: newFl,
Incomplete: e.Incomplete,
}
case *ast.FuncType:
params := t.instantiateFieldList(ta, e.Params)
results := t.instantiateFieldList(ta, e.Results)
if e.TParams == nil && params == e.Params && results == e.Results {
return e
}
r = &ast.FuncType{
Func: e.Func,
TParams: nil,
Params: params,
Results: results,
}
case *ast.InterfaceType:
eMethods, eTypes := splitFieldList(e.Methods)
methods := t.instantiateFieldList(ta, eMethods)
types, typesChanged := t.instantiateExprList(ta, eTypes)
if methods == e.Methods && !typesChanged {
return e
}
r = &ast.InterfaceType{
Interface: e.Interface,
Methods: mergeFieldList(methods, types),
Incomplete: e.Incomplete,
}
case *ast.MapType:
key := t.instantiateExpr(ta, e.Key)
value := t.instantiateExpr(ta, e.Value)
if key == e.Key && value == e.Value {
return e
}
r = &ast.MapType{
Map: e.Map,
Key: key,
Value: value,
}
case *ast.ChanType:
value := t.instantiateExpr(ta, e.Value)
if value == e.Value {
return e
}
r = &ast.ChanType{
Begin: e.Begin,
Arrow: e.Arrow,
Dir: e.Dir,
Value: value,
}
default:
panic(fmt.Sprintf("unimplemented Expr %T", e))
}
if et := t.lookupType(e); et != nil {
t.setType(r, t.instantiateType(ta, et))
}
return r
}
// instantiateExprList instantiates an expression list.
func (t *translator) instantiateExprList(ta *typeArgs, el []ast.Expr) ([]ast.Expr, bool) {
nel := make([]ast.Expr, len(el))
changed := false
for i, e := range el {
ne := t.instantiateExpr(ta, e)
if ne != e {
changed = true
}
nel[i] = ne
}
if !changed {
return el, false
}
return nel, true
}

75
src/go/go2go/names.go Normal file
View File

@@ -0,0 +1,75 @@
// Copyright 2020 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 go2go
import (
"fmt"
"go/types"
"strings"
"unicode"
)
// We use Oriya digit zero as a separator.
// Do not use this character in your own identifiers.
const nameSep = ''
// We use Oriya digit eight to introduce a special character code.
// Do not use this character in your own identifiers.
const nameIntro = '୮'
var nameCodes = map[rune]int{
' ': 0,
'*': 1,
';': 2,
',': 3,
'{': 4,
'}': 5,
'[': 6,
']': 7,
'(': 8,
')': 9,
'.': 10,
'<': 11,
'-': 12,
'/': 13,
nameSep: 14,
nameIntro: 15,
}
// instantiatedName returns the name of a newly instantiated function.
func (t *translator) instantiatedName(qid qualifiedIdent, types []types.Type) (string, error) {
var sb strings.Builder
fmt.Fprintf(&sb, "instantiate%c", nameSep)
if qid.pkg != nil {
fmt.Fprintf(&sb, qid.pkg.Name())
}
fmt.Fprintf(&sb, "%c%s", nameSep, qid.ident.Name)
for _, typ := range types {
sb.WriteRune(nameSep)
s := t.withoutTags(typ).String()
// We have to uniquely translate s into a valid Go identifier.
// This is not possible in general but we assume that
// identifiers will not contain nameSep or nameIntro.
for _, r := range s {
if (unicode.IsLetter(r) || unicode.IsDigit(r) || r == '_') && r != nameSep && r != nameIntro {
sb.WriteRune(r)
} else {
code, ok := nameCodes[r]
if !ok {
panic(fmt.Sprintf("%s: unexpected type string character %q in %q", t.fset.Position(qid.ident.Pos()), r, s))
}
fmt.Fprintf(&sb, "%c%x", nameIntro, code)
}
}
}
return sb.String(), nil
}
// importableName returns a name that we define in each package, so that
// we have something to import to avoid an unused package error.
func (t *translator) importableName() string {
return "Importable" + string(nameSep)
}

1300
src/go/go2go/rewrite.go Normal file

File diff suppressed because it is too large Load Diff

626
src/go/go2go/types.go Normal file
View File

@@ -0,0 +1,626 @@
// Copyright 2020 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 go2go
import (
"fmt"
"go/ast"
"go/token"
"go/types"
"strconv"
"strings"
)
// lookupType returns the types.Type for an AST expression.
// Returns nil if the type is not known.
func (t *translator) lookupType(e ast.Expr) types.Type {
if typ := t.importer.info.TypeOf(e); typ != nil {
return typ
}
if typ, ok := t.types[e]; ok {
return typ
}
return nil
}
// setType records the type for an AST expression. This is only used for
// AST expressions created during function instantiation.
// Uninstantiated AST expressions will be listed in t.importer.info.Types.
func (t *translator) setType(e ast.Expr, nt types.Type) {
if ot, ok := t.importer.info.Types[e]; ok {
if !t.sameType(ot.Type, nt) {
panic("expression type changed")
}
return
}
if ot, ok := t.types[e]; ok {
if !t.sameType(ot, nt) {
panic("expression type changed")
}
return
}
t.types[e] = nt
}
// instantiateType instantiates typ using ta.
func (t *translator) instantiateType(ta *typeArgs, typ types.Type) types.Type {
if t.err != nil {
return nil
}
t.typeDepth++
defer func() { t.typeDepth-- }()
if t.typeDepth > 25 {
t.err = fmt.Errorf("looping while instantiating %v %v", typ, ta.types)
return nil
}
var inProgress *typeInstantiation
for _, inst := range t.typeInstantiations(typ) {
if t.sameTypes(ta.types, inst.types) {
if inst.typ == nil {
inProgress = inst
break
}
return inst.typ
}
}
ityp := t.doInstantiateType(ta, typ)
if inProgress != nil {
if inProgress.typ == nil {
inProgress.typ = ityp
} else {
ityp = inProgress.typ
}
} else {
typinst := &typeInstantiation{
types: ta.types,
typ: ityp,
}
t.addTypeInstantiation(typ, typinst)
}
return ityp
}
// doInstantiateType does the work of instantiating typ using ta.
// This should only be called from instantiateType.
func (t *translator) doInstantiateType(ta *typeArgs, typ types.Type) types.Type {
switch typ := typ.(type) {
case *types.Basic:
return typ
case *types.Array:
elem := typ.Elem()
instElem := t.instantiateType(ta, elem)
if elem == instElem {
return typ
}
return types.NewArray(instElem, typ.Len())
case *types.Slice:
elem := typ.Elem()
instElem := t.instantiateType(ta, elem)
if elem == instElem {
return typ
}
return types.NewSlice(instElem)
case *types.Struct:
n := typ.NumFields()
fields := make([]*types.Var, n)
changed := false
tags := make([]string, n)
hasTag := false
for i := 0; i < n; i++ {
v := typ.Field(i)
instType := t.instantiateType(ta, v.Type())
if v.Type() != instType {
changed = true
}
fields[i] = types.NewVar(v.Pos(), v.Pkg(), v.Name(), instType)
tag := typ.Tag(i)
if tag != "" {
tags[i] = tag
hasTag = true
}
}
if !changed {
return typ
}
if !hasTag {
tags = nil
}
return types.NewStruct(fields, tags)
case *types.Pointer:
elem := typ.Elem()
instElem := t.instantiateType(ta, elem)
if elem == instElem {
return typ
}
return types.NewPointer(instElem)
case *types.Tuple:
return t.instantiateTypeTuple(ta, typ)
case *types.Signature:
params := t.instantiateTypeTuple(ta, typ.Params())
results := t.instantiateTypeTuple(ta, typ.Results())
if params == typ.Params() && results == typ.Results() {
return typ
}
r := types.NewSignature(typ.Recv(), params, results, typ.Variadic())
if tparams := typ.TParams(); tparams != nil {
r.SetTParams(tparams)
}
return r
case *types.Interface:
nm := typ.NumExplicitMethods()
methods := make([]*types.Func, nm)
changed := false
for i := 0; i < nm; i++ {
m := typ.ExplicitMethod(i)
instSig := t.instantiateType(ta, m.Type()).(*types.Signature)
if instSig != m.Type() {
m = types.NewFunc(m.Pos(), m.Pkg(), m.Name(), instSig)
changed = true
}
methods[i] = m
}
ne := typ.NumEmbeddeds()
embeddeds := make([]types.Type, ne)
for i := 0; i < ne; i++ {
e := typ.EmbeddedType(i)
instE := t.instantiateType(ta, e)
if e != instE {
changed = true
}
embeddeds[i] = instE
}
if !changed {
return typ
}
return types.NewInterfaceType(methods, embeddeds)
case *types.Map:
key := t.instantiateType(ta, typ.Key())
elem := t.instantiateType(ta, typ.Elem())
if key == typ.Key() && elem == typ.Elem() {
return typ
}
return types.NewMap(key, elem)
case *types.Chan:
elem := t.instantiateType(ta, typ.Elem())
if elem == typ.Elem() {
return typ
}
return types.NewChan(typ.Dir(), elem)
case *types.Named:
targs := typ.TArgs()
targsChanged := false
if len(targs) > 0 {
newTargs := make([]types.Type, 0, len(targs))
for _, targ := range targs {
newTarg := t.instantiateType(ta, targ)
if newTarg != targ {
targsChanged = true
}
newTargs = append(newTargs, newTarg)
}
targs = newTargs
}
if targsChanged {
return t.updateTArgs(typ, targs)
}
return typ
case *types.TypeParam:
if instType, ok := ta.typ(typ); ok {
return instType
}
return typ
default:
panic(fmt.Sprintf("unimplemented Type %T", typ))
}
}
// setTargs returns a new named type with updated type arguments.
func (t *translator) updateTArgs(typ *types.Named, targs []types.Type) *types.Named {
nm := typ.NumMethods()
methods := make([]*types.Func, 0, nm)
for i := 0; i < nm; i++ {
methods = append(methods, typ.Method(i))
}
obj := typ.Obj()
obj = types.NewTypeName(obj.Pos(), obj.Pkg(), obj.Name(), nil)
nt := types.NewNamed(obj, typ.Underlying(), methods)
nt.SetTArgs(targs)
return nt
}
// instantiateTypeTuple instantiates a types.Tuple.
func (t *translator) instantiateTypeTuple(ta *typeArgs, tuple *types.Tuple) *types.Tuple {
if tuple == nil {
return nil
}
l := tuple.Len()
instTypes := make([]types.Type, l)
changed := false
for i := 0; i < l; i++ {
typ := tuple.At(i).Type()
instType := t.instantiateType(ta, typ)
if typ != instType {
changed = true
}
instTypes[i] = instType
}
if !changed {
return tuple
}
vars := make([]*types.Var, l)
for i := 0; i < l; i++ {
v := tuple.At(i)
vars[i] = types.NewVar(v.Pos(), v.Pkg(), v.Name(), instTypes[i])
}
return types.NewTuple(vars...)
}
// addTypePackages adds all packages mentioned in typ to t.typePackages.
func (t *translator) addTypePackages(typ types.Type) {
switch typ := typ.(type) {
case *types.Basic:
case *types.Array:
t.addTypePackages(typ.Elem())
case *types.Slice:
t.addTypePackages(typ.Elem())
case *types.Struct:
n := typ.NumFields()
for i := 0; i < n; i++ {
t.addTypePackages(typ.Field(i).Type())
}
case *types.Pointer:
t.addTypePackages(typ.Elem())
case *types.Tuple:
n := typ.Len()
for i := 0; i < n; i++ {
t.addTypePackages(typ.At(i).Type())
}
case *types.Signature:
// We'll have seen typ.Recv elsewhere.
t.addTypePackages(typ.Params())
t.addTypePackages(typ.Results())
case *types.Interface:
nm := typ.NumExplicitMethods()
for i := 0; i < nm; i++ {
t.addTypePackages(typ.ExplicitMethod(i).Type())
}
ne := typ.NumEmbeddeds()
for i := 0; i < ne; i++ {
t.addTypePackages(typ.EmbeddedType(i))
}
case *types.Map:
t.addTypePackages(typ.Key())
t.addTypePackages(typ.Elem())
case *types.Chan:
t.addTypePackages(typ.Elem())
case *types.Named:
// This is the point of this whole method.
if typ.Obj().Pkg() != nil {
t.typePackages[typ.Obj().Pkg()] = true
}
case *types.TypeParam:
default:
panic(fmt.Sprintf("unimplemented Type %T", typ))
}
}
// withoutTags returns a type with no struct tags. If typ has no
// struct tags anyhow, this just returns typ.
func (t *translator) withoutTags(typ types.Type) types.Type {
switch typ := typ.(type) {
case *types.Basic:
return typ
case *types.Array:
elem := typ.Elem()
elemNoTags := t.withoutTags(elem)
if elem == elemNoTags {
return typ
}
return types.NewArray(elemNoTags, typ.Len())
case *types.Slice:
elem := typ.Elem()
elemNoTags := t.withoutTags(elem)
if elem == elemNoTags {
return typ
}
return types.NewSlice(elemNoTags)
case *types.Struct:
n := typ.NumFields()
fields := make([]*types.Var, n)
changed := false
hasTag := false
for i := 0; i < n; i++ {
v := typ.Field(i)
typeNoTags := t.withoutTags(v.Type())
if v.Type() != typeNoTags {
changed = true
}
fields[i] = types.NewVar(v.Pos(), v.Pkg(), v.Name(), typeNoTags)
if typ.Tag(i) != "" {
hasTag = true
}
}
if !changed && !hasTag {
return typ
}
return types.NewStruct(fields, nil)
case *types.Pointer:
elem := typ.Elem()
elemNoTags := t.withoutTags(elem)
if elem == elemNoTags {
return typ
}
return types.NewPointer(elemNoTags)
case *types.Tuple:
return t.tupleWithoutTags(typ)
case *types.Signature:
params := t.tupleWithoutTags(typ.Params())
results := t.tupleWithoutTags(typ.Results())
if params == typ.Params() && results == typ.Results() {
return typ
}
r := types.NewSignature(typ.Recv(), params, results, typ.Variadic())
if tparams := typ.TParams(); tparams != nil {
r.SetTParams(tparams)
}
return r
case *types.Interface:
nm := typ.NumExplicitMethods()
methods := make([]*types.Func, nm)
changed := false
for i := 0; i < nm; i++ {
m := typ.ExplicitMethod(i)
sigNoTags := t.withoutTags(m.Type()).(*types.Signature)
if sigNoTags != m.Type() {
m = types.NewFunc(m.Pos(), m.Pkg(), m.Name(), sigNoTags)
changed = true
}
methods[i] = m
}
ne := typ.NumEmbeddeds()
embeddeds := make([]types.Type, ne)
for i := 0; i < ne; i++ {
e := typ.EmbeddedType(i)
eNoTags := t.withoutTags(e)
if e != eNoTags {
changed = true
}
embeddeds[i] = eNoTags
}
if !changed {
return typ
}
return types.NewInterfaceType(methods, embeddeds)
case *types.Map:
key := t.withoutTags(typ.Key())
elem := t.withoutTags(typ.Elem())
if key == typ.Key() && elem == typ.Elem() {
return typ
}
return types.NewMap(key, elem)
case *types.Chan:
elem := t.withoutTags(typ.Elem())
if elem == typ.Elem() {
return typ
}
return types.NewChan(typ.Dir(), elem)
case *types.Named:
targs := typ.TArgs()
targsChanged := false
if len(targs) > 0 {
newTargs := make([]types.Type, 0, len(targs))
for _, targ := range targs {
newTarg := t.withoutTags(targ)
if newTarg != targ {
targsChanged = true
}
newTargs = append(newTargs, newTarg)
}
targs = newTargs
}
if targsChanged {
return t.updateTArgs(typ, targs)
}
return typ
case *types.TypeParam:
return typ
default:
panic(fmt.Sprintf("unimplemented Type %T", typ))
}
}
// tupleWithoutTags returns a tuple with all struct tag removed.
func (t *translator) tupleWithoutTags(tuple *types.Tuple) *types.Tuple {
if tuple == nil {
return nil
}
l := tuple.Len()
typesNoTags := make([]types.Type, l)
changed := false
for i := 0; i < l; i++ {
typ := tuple.At(i).Type()
typNoTags := t.withoutTags(typ)
if typ != typNoTags {
changed = true
}
typesNoTags[i] = typNoTags
}
if !changed {
return tuple
}
vars := make([]*types.Var, l)
for i := 0; i < l; i++ {
v := tuple.At(i)
vars[i] = types.NewVar(v.Pos(), v.Pkg(), v.Name(), typesNoTags[i])
}
return types.NewTuple(vars...)
}
// typeToAST converts a types.Type to an ast.Expr.
func (t *translator) typeToAST(typ types.Type) ast.Expr {
var r ast.Expr
switch typ := typ.(type) {
case *types.Basic:
r = ast.NewIdent(typ.Name())
case *types.Array:
r = &ast.ArrayType{
Len: &ast.BasicLit{
Kind: token.INT,
Value: strconv.FormatInt(typ.Len(), 10),
},
Elt: t.typeToAST(typ.Elem()),
}
case *types.Slice:
r = &ast.ArrayType{
Elt: t.typeToAST(typ.Elem()),
}
case *types.Struct:
var fields []*ast.Field
n := typ.NumFields()
for i := 0; i < n; i++ {
tf := typ.Field(i)
var names []*ast.Ident
if !tf.Embedded() {
names = []*ast.Ident{
ast.NewIdent(tf.Name()),
}
}
var atag *ast.BasicLit
if tag := typ.Tag(i); tag != "" {
atag = &ast.BasicLit{
Kind: token.STRING,
Value: strconv.Quote(tag),
}
}
af := &ast.Field{
Names: names,
Type: t.typeToAST(tf.Type()),
Tag: atag,
}
fields = append(fields, af)
}
r = &ast.StructType{
Fields: &ast.FieldList{
List: fields,
},
}
case *types.Pointer:
r = &ast.StarExpr{
X: t.typeToAST(typ.Elem()),
}
case *types.Tuple:
// We should only see this in a types.Signature,
// where we handle it specially, since there is
// no ast.Expr that can represent this.
panic("unexpected types.Tuple")
case *types.Signature:
if len(typ.TParams()) > 0 {
// We should only see type parameters for
// a package scope function declaration.
panic("unexpected type parameters")
}
r = &ast.FuncType{
Params: t.tupleToFieldList(typ.Params()),
Results: t.tupleToFieldList(typ.Params()),
}
case *types.Interface:
var methods []*ast.Field
nm := typ.NumExplicitMethods()
for i := 0; i < nm; i++ {
m := typ.ExplicitMethod(i)
f := &ast.Field{
Names: []*ast.Ident{
ast.NewIdent(m.Name()),
},
Type: t.typeToAST(m.Type()),
}
methods = append(methods, f)
}
ne := typ.NumEmbeddeds()
for i := 0; i < ne; i++ {
e := typ.EmbeddedType(i)
f := &ast.Field{
Type: t.typeToAST(e),
}
methods = append(methods, f)
}
r = &ast.InterfaceType{
Methods: &ast.FieldList{
List: methods,
},
}
case *types.Map:
r = &ast.MapType{
Key: t.typeToAST(typ.Key()),
Value: t.typeToAST(typ.Elem()),
}
case *types.Chan:
var dir ast.ChanDir
switch typ.Dir() {
case types.SendRecv:
dir = ast.SEND | ast.RECV
case types.SendOnly:
dir = ast.SEND
case types.RecvOnly:
dir = ast.RECV
default:
panic("unsupported channel direction")
}
r = &ast.ChanType{
Dir: dir,
Value: t.typeToAST(typ.Elem()),
}
case *types.Named:
if len(typ.TArgs()) > 0 {
_, id := t.lookupInstantiatedType(typ)
r = id
} else {
var sb strings.Builder
tn := typ.Obj()
if tn.Pkg() != nil && tn.Pkg() != t.tpkg {
sb.WriteString(tn.Pkg().Name())
sb.WriteByte('.')
}
sb.WriteString(tn.Name())
r = ast.NewIdent(sb.String())
}
case *types.TypeParam:
// This should have been instantiated already.
panic("unexpected type parameter")
default:
panic(fmt.Sprintf("unimplemented Type %T", typ))
}
t.setType(r, typ)
return r
}
// tupleToFieldList converts a tupes.Tuple to a ast.FieldList.
func (t *translator) tupleToFieldList(tuple *types.Tuple) *ast.FieldList {
var fields []*ast.Field
n := tuple.Len()
for i := 0; i < n; i++ {
v := tuple.At(i)
var names []*ast.Ident
if v.Name() != "" {
names = []*ast.Ident{
ast.NewIdent(v.Name()),
}
}
f := &ast.Field{
Names: names,
Type: t.typeToAST(v.Type()),
}
fields = append(fields, f)
}
return &ast.FieldList{
List: fields,
}
}

View File

@@ -264,7 +264,8 @@ var importedObjectTests = []struct {
{"io.Reader", "type Reader interface{Read(p []byte) (n int, err error)}"},
{"io.ReadWriter", "type ReadWriter interface{Reader; Writer}"},
{"go/ast.Node", "type Node interface{End() go/token.Pos; Pos() go/token.Pos}"},
{"go/types.Type", "type Type interface{String() string; Underlying() Type}"},
// go/types.Type has grown much larger - excluded for now
// {"go/types.Type", "type Type interface{String() string; Underlying() Type}"},
}
func TestImportedTypes(t *testing.T) {

View File

@@ -0,0 +1,33 @@
// Copyright 2020 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 generics
type T[P any] struct{}
type T[P1, P2, P3 any] struct{}
type T[P C] struct{}
type T[P1, P2, P3, C] struct{}
type T[P C[P]] struct{}
type T[P1, P2, P3 C[P1, P2, P3]] struct{}
func f[P any](x P)
func f[P1, P2, P3 any](x1 P1, x2 P2, x3 P3) struct{}
func f[P interface{}](x P)
func f[P1, P2, P3 interface {
m1(P1)
type P2, P3
}](x1 P1, x2 P2, x3 P3) struct{}
func f[P any](T1[P], T2[P]) T3[P]
func (x T[P]) m()
func (T[P]) m(x T[P]) P
func _() {
type _ []T[P]
var _ []T[P]
_ = []T[P]{}
}

30
src/go/printer/testdata/genericsB.input vendored Normal file
View File

@@ -0,0 +1,30 @@
// Copyright 2020 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 generics
type T[P any] struct{}
type T[P1, P2, P3 any] struct{}
type T[P C] struct{}
type T[P1, P2, P3, C] struct{}
type T[P C[P]] struct{}
type T[P1, P2, P3 C[P1, P2, P3]] struct{}
func f[P any](x P)
func f[P1, P2, P3 any](x1 P1, x2 P2, x3 P3) struct{}
func f[P interface{}](x P)
func f[P1, P2, P3 interface{ m1(P1); type P2, P3 }](x1 P1, x2 P2, x3 P3) struct{}
func f[P any](T1[P], T2[P]) T3[P]
func (x T[P]) m()
func ((T[P])) m(x T[P]) P
func _() {
type _ []T[P]
var _ []T[P]
_ = []T[P]{}
}

182
src/go/types/NOTES Normal file
View File

@@ -0,0 +1,182 @@
This file serves as a notebook/implementation log.
----------------------------------------------------------------------------------------------------
TODO (implementation issues)
- report a better error when a type is not in a type list (investigate)
- better error message when we need parentheses around a parameterized function parameter type
- review handling of fields of instantiated generic types (do we need to make them non-parameterized?)
- use []*TypeParam for tparams in subst? (unclear)
- should we use nil instead of &emptyInterface for no type bounds (as an optimization)?
- TBD: in prose, should we use "generic" or "parameterized" (try to be consistent)
----------------------------------------------------------------------------------------------------
KNOWN ISSUES
- type parameter constraints are ignored when checking if a parameterized method implements the
matching method in an interface
- iteration over generic variables doesn't report certain channel errors (see TODOs in code)
- cannot handle mutually recursive parameterized interfaces using themselves as type bounds
example: type B(type P B(P)) interface{ m() } (need to delay all checking after seting up declarations)
- invoking a method of a parameterized embedded type doesn't work (cannot properly determine receiver yet)
- pointer designation is incorrectly handled when checking type list constraint satisfaction
----------------------------------------------------------------------------------------------------
OBSERVATIONS
- 2/20/2020: Because we permit parenthesized types anywhere for consistency, also in parameter lists (mea
culpa), we have parsing ambiguities when using instantiated types in parameter lists w/o argument names.
We could disallow the use of parentheses at the top level of type literals and then we might not have
this problem. This is not a backward-compatible change but perhaps worthwhile investigating. Specifically,
will this always work (look specifically at channel types where we need parentheses for disambiguation
and possibly function types).
- 6/3/2020: Observation: gofmt already removes superflous parentheses around types in parameter lists,
so in gofmt'ed code there won't be any such parentheses. Thus we can perhaps make the suggested language
change above without too many problems.
- 2/21/2020: We do need top-level parentheses around types in certain situations such as conversions
or composite literals. We could disallow parentheses around types in parameter lists only, but that
seems quite a bit less elegant.
- 6/13/2020: When comparing against the type list of an interface (to see if the interface is satisfied),
we must either recompute the underlying types of the type list entries after the interface was instantiated,
or we must compute the underlying type of each entry before comparing. (A type list may contain type
parameters which may be substituted with defined types when the interface is instantiated.) With the
latter approach (which is what's implemented now), we could relax some of the constraints that we have
on type lists entries: We could allow any type and just say that for interface satisfaction we always
look at the underlying types.
----------------------------------------------------------------------------------------------------
OPEN QUESTIONS
- Parsing _ = [](a(int)){} requires parentheses around `(a(int))` - should the parser be smarter in
these cases? Another example: []a(b, c){} This cannot be a conversion. Could fix such cases by re-
associating the AST when we see a {. Need to be careful, and need to take into account additional
complexity of spec.
- For len/cap(x) where x is of type parameter type and the bound contains arrays only, should the
result be a constant? (right now it is not). What are the implications for alternative, non-
monomorphizing implementation methods?
- Confirm that it's ok to use inference in missingMethod to compare parameterized methods.
----------------------------------------------------------------------------------------------------
DESIGN/IMPLEMENTATION
- 11/19/2019: For type parameters with interface bounds to work, the scope of all type parameters in
a type parameter list starts at the "type" keyword. This makes all type parameters visible for all
type parameter bounds (interfaces that may be parameterized with the type parameters).
- 12/4/2019: do not allow parenthesized generic uninstantiated types (unless instantiated implicitly)
In other words: generic types must always be instantiated before they can be used in any form
More generally: Only permit type instantiation T(x) in type context, when the type is a named type.
Do not permit it in general in type context: e.g., disallow []T(x) because we consider that a
conversion, in general. Same for ([]T)(x).
- 12/12/2019: represent type bounds always as (possibly unnamed) interfaces
(contracts are user syntactic sugar)
- 12/19/2019: Type parameters don't act like type aliases. For instance:
func f(type T1, T2)(x T1) T2 { return x }
is not valid, no matter how T1 and T2 are instantiated (but if T1 and T2 were type aliases with
both of them having type int, the return x would be valid). In fact, the type parameters act more
like named types with the methods described by their type bound. But type parameters are never
interfaces. To determine: Given a type parameter P, is P == underlying(P) (like for basic types),
or is the the underlying type of P something else (like for defined types). Is there an observable
difference?
- 12/19/2019: Rewrote contract handling: they are now treated as Objects (rather than Types) throughout.
- 12/20/2019: Decided to start moving type parameters to types (from TypeName to Named), need to do the
same for Func. This make more sense as in general any type (conceptually even literal types) could
have type parameters. It's a property of the type, not the type name. It also simplified the code.
- 12/20/2019: Type parameters may be part of type lists in contracts/interfaces. It just falls out
naturally. Added test cases.
- 12/23/2019: Decision: Type parameters and ordinary (value) parameters are in the same block, notably
the function block. The scope of type parameters starts at the 'type' keyword; the scope of ordinary
parameters starts with the (opening '{' of the) function body. Both scopes end with the closing '}'
of the function body (i.e., the end of the function block).
- 1/2/2020: Implementation decision: contracts can only be declared at the package level.
- 1/6/2020: Experimental: First steps towards permitting type parameters in methods as a generalization.
Type-checking problems ooccurring from this are likely to highlight general problematic areas.
First consequence: Scope of type parameters starts at "func" keyword which means that receiver type
name cannot be a type parameter name declared later (or by the receiver type specification). This
seems reasonable and should help avoid confusion which is possible otherwise.
- 1/7/2020: We distinguish embedded instantiated (parameterized) interfaces from methods by enclosing
the embedded interfaces in parentheses (the design draft recommends this change). Since this opens
the possibility for any parenthesized type (that is an interface), we can also allow (parenthesized)
interface literals as it is simpler to permit those than forbid them.
- 1/7/2020: The current implementation permits empty type parameter lists as in: "func f(type)(x int)"
but we cannot call such a function as "f()(1)"; the empty type argument list causes problems.
Document that we allow empty type parameter list declarations, but not empty actual type parameter
lists. (We could allow them for types, but that doesn't seem consistent and probably is confusing).
- 2/19/2020: We accept parenthesized embedded struct fields so we can distinguish between a named
field with a parenthesized type foo (T) and an embedded parameterized type (foo(T)), similarly
to interace embedding.
- 2/19/2020: Permit parentheses around embedded contracts for symmetry with embedding in structs
and interfaces.
- 2/20/2020: Receiver type parameters must always be provided in the receiver parameter list of
a method, even if they are not used by the method. Since the receiver acts like an implicit
declaration of those type parameters, they may be blank, as with any other declaration.
- 3/20/2020: Local type declarations with an underlying type that is a type parameter lose the
methods declared with the type parameter bound. But they don't lose the properties of the
underlying type, i.e., the properties of the type parameter bound's type list.
This is something to consider if we were contemplating moving to a methods-only approach
(no type lists), even though local type declarations are exceedingly rare if they exist at
all in the wild.
- 3/24/2020: Implemented initial support for bidirection type unification which could make
type inference more powerful if we decided to go that route. Specifically, this would
permit type inference for the type parameters of a generic function argument. Given:
func h(f func(int)); func g(type T)(T); one could allow the call: h(g) and the type argument
T of g would be inferred to be int. While not hard to implement, this would be a special case
of the rule that all generic types/functions must be instantiated before they are used except
for function calls where the type arguments can be inferred from the actual arguments.
Decided that for now we leave things as is, since it's not clear the extra complexity is
worth the (probably small) convenience.
- 3/25/2020: We can probably simplify the contract syntax again and only permit one of three
possible constraint entries: 1) an embedded contract, 2) a type parameter followed by a
method signature, and 3) a type parameter followed by a type list. This is what the type
checker currently supports and the printer can print. (The parser still accepts a list of
method signatures or types, freely mixed.)
- 4/24/2020: Permit omission of explicit type bound instantiation if the type bound is an
interface that applies to exactly one type parameter and the type bound expects exactly
one type argument. This makes parameterized interface type bounds easier to use in a common
case.
- 5/?/2020: Relaxed above syntactic sugar and permit omission of explicit type bound instantiation
in any case where the type bound only accepts a single type parameter.
We may not want to permit this in the first version as this is something we can always add later.
- 6/3/2020: A function type parameter acts like a named type. If its type bound has a type list
that type list determines the underlying type of the type parameter. If the bound doesn't have
a type list, the underlying type of a type parameter is itself. (We may decide that in this
latter case there may no underlying type at all which would perhaps more consistent. But this
is not clear cut.)
- 6/6/2020: The underlying type of a type parameter must _always_ be itself, otherwise a declaration
such as: type T(type P interface{type int}) P would have an underlying type int which is wrong.
- 6/7/2020: Introduced the notion of an operational type which is used when determining what
operations are supported by a value of a given type. The operational type of a type parameter
is determined by its type bound. The operational type of any other type is its underlying
type. This approach appears to complete the picture about the nature of type parameters.
- 6/7/2020: Removed support for contracts to match the latest design draft.
- 6/15/2020: Disabled check that types in type lists must only contain basic types or composite types
composed of basic types. It is not needed since we always must recompute the underlying types
after a (possible) instantiation anyway (see observation from 6/3/2020).

68
src/go/types/README Normal file
View File

@@ -0,0 +1,68 @@
This version of go/types is part of the prototype that implements the
extended Go language as outlined by the latest generics draft design.
DISCLAIMER
This code is based on the std/library's go/types package but it has
been modified heavily. Please bear in mind that:
- This is a prototype. Expect bugs, incomplete parts, and suboptimal
and (gulp) possibly ugly code.
- While all the major aspects of the generics design draft have been
implemented, parts are missing, especially around the operations permitted
on operands of generic types. In such cases, the result is most often
an error reporting that a certain operation is not permitted even though
it should be according to the draft design.
- As prototyping continues, expect refinement and possibly divergence
from the most recent draft design published.
EXAMPLE CODE
For tests and example code (with detailed comments) look for files
with suffix .go2 in the testdata and examples subdirectories.
(The suffix .go2 is solely to distinguish them from regular Go code and
to prevent gofmt from touching them. We expect a proper implementation to
keep using .go .)
RUNNING THE TYPE-CHECKER
The type-checker is automatically run as part of the go2go tool.
To experiment with generic code, it is recommened to use that tool.
But the type-checker can also be run stand-alone on source code if
so desired. There are two primary ways:
1) By building the gotype tool in this source directory:
go build gotype.go
and then running the resulting binary on some input files
./gotype <package files>
(Make sure to use the correct go tool when building.)
2) By using the type-checker's TestCheck test function which
accepts a list of user provided files:
go test -run Check$ -errlist -files <package files>
For instance:
go test -run Check$ -files examples/types.go2
TestCheck will match any type errors against ERROR comments
in the source files and complain about discrepancies.
To report the errors instead, use:
go test -run Check$ -errlist -files examples/types.go2
To see a trace of the type checker progress, use the -v flag:
go test -v -run Check$ -errlist -files examples/types.go2
(When playing with this code, sometimes go vet gets in the
way, so it can be helpful to also provide -vet off.)

22
src/go/types/api_go2go.go Normal file
View File

@@ -0,0 +1,22 @@
// Copyright 2021 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 types
import (
"go/ast"
)
// This file exposes additional API methods related to type parameters, for use
// in the go2go rewriter.
type Inferred = _Inferred
func GetInferred(info *Info) map[ast.Expr]Inferred {
return info._Inferred
}
func SetInferred(info *Info, inferred map[ast.Expr]Inferred) {
info._Inferred = inferred
}

View File

@@ -0,0 +1,27 @@
// Copyright 2021 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 types
// This file exposes additional API methods related to type parameters, for use
// in the go2go rewriter.
type TypeParam = _TypeParam
func (t *Named) TArgs() []Type { return t._TArgs() }
func (t *Named) SetTArgs(args []Type) { t._SetTArgs(args) }
func (t *Named) TParams() []*TypeName { return t._TParams() }
func (t *Interface) HasTypeList() bool { return t._HasTypeList() }
func (s *Signature) TParams() []*TypeName { return s._TParams() }
func (s *Signature) SetTParams(tparams []*TypeName) { s._SetTParams(tparams) }
func AsPointer(t Type) *Pointer {
return asPointer(t)
}
func AsStruct(t Type) *Struct {
return asStruct(t)
}

64
test/gen/err001.go2 Normal file
View File

@@ -0,0 +1,64 @@
// errorcheck
// Copyright 2020 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 F1[T comparable]() {}
func F2() { F1[[]int]() } // ERROR "\[\]int does not satisfy comparable$"
type C interface {
M()
}
func F3[T C]() {}
func F4() { F3[int]() } // ERROR "int does not satisfy C.*method M"
func F5[T any]() { F3[T]() } // ERROR "T does not satisfy C.*method M"
type signed interface {
type int, int8, int16, int32, int64
}
type integer interface {
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr
}
func F6[T signed](a T) bool { return a < 0 }
func F7[T any](a T) bool { return F6(a) } // ERROR "T does not satisfy signed.*T has no type constraints"
func F8[T integer](a T) bool { return F6(a) } // ERROR "T does not satisfy signed.*T type constraint uint not found in"
func F9(a uint) bool { return F6(a) } // ERROR "uint does not satisfy signed.*uint not found in"
type MyInt int
type MyUint uint
func F10(a MyInt) bool { return F6(a) }
func F11(a MyUint) bool { return F6(a) } // ERROR "MyUint does not satisfy signed.*uint not found in"
type C2 interface {
C
signed
}
func F20[T C2](a T) bool {
a.M()
return a < 0
}
func (MyInt) M() {}
func (MyUint) M() {}
type S struct {}
func (S) M() {}
func F21() bool { return F20(MyInt(0)) }
func F22() bool { return F20(0) } // ERROR "int does not satisfy C2.*(missing method M)"
func F23[T any](a T) bool { return F20(a) } // ERROR "T does not satisfy C2.*(missing method M)"
func F24[T integer](a T) bool { return F20(a) } // ERROR "T does not satisfy C2.*(missing method M)"
func F25(a uint) bool { return F20(a) } // ERROR "uint does not satisfy C2.*(missing method M)"
func F26(a MyUint) bool { return F20(a) } // ERROR "MyUint does not satisfy C2.*uint not found in"
func F27(a S) bool { return F20(a) } // ERROR "S does not satisfy C2.*struct{} not found in"

View File

@@ -0,0 +1,9 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package a
type C interface {
M()
}

10
test/gen/err002.dir/b.go2 Normal file
View File

@@ -0,0 +1,10 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package b
import "./a"
func F1[T a.C]() {}
func F2() { F1(int)() } // ERROR "int does not satisfy a.C.*method M"

7
test/gen/err002.go2 Normal file
View File

@@ -0,0 +1,7 @@
// errorcheckdir
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ignored

29
test/gen/err003.go2 Normal file
View File

@@ -0,0 +1,29 @@
// errorcheck
// Copyright 2020 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 Setter interface {
Set(string)
}
func FromStrings[T Setter](s []string) []T {
result := make([]T, len(s))
for i, v := range s {
result[i].Set(v)
}
return result
}
type Settable int
func (p *Settable) Set(s string) {
*p = 0
}
func F() {
FromStrings[Settable]([]string{"1"}) // ERROR "Settable does not satisfy Setter"
}

11
test/gen/err004.go2 Normal file
View File

@@ -0,0 +1,11 @@
// errorcheck
// Copyright 2020 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() {
type t[T any] T // ERROR "parameterized type"
}

15
test/gen/err005.go2 Normal file
View File

@@ -0,0 +1,15 @@
// errorcheck
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39738.
package p
func F1[T any]() {}
func F2() {
type s struct{}
F1[s]() // ERROR "locally defined type"
}

16
test/gen/err006.go2 Normal file
View File

@@ -0,0 +1,16 @@
// errorcheck
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39743.
package p
type S[T any] struct{}
func (s S[_]) M() {} // ERROR "_"
func F() {
S[int]{}.M()
}

23
test/gen/g001.go2 Normal file
View File

@@ -0,0 +1,23 @@
// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "fmt"
func Print[T any](s []T) {
for _, v := range s {
fmt.Println(v)
}
}
func PrintInts(s []int) {
Print[int](s)
}
func main() {
PrintInts([]int{1, 2})
}

2
test/gen/g001.out Normal file
View File

@@ -0,0 +1,2 @@
1
2

27
test/gen/g002.go2 Normal file
View File

@@ -0,0 +1,27 @@
// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "fmt"
func Print1[T any](s []T) {
for _, v := range s {
fmt.Println(v)
}
}
func Print2[T any](s []T) {
Print1(T)(s)
}
func PrintInts(s []int) {
Print2(int)(s)
}
func main() {
PrintInts([]int{1, 2})
}

2
test/gen/g002.out Normal file
View File

@@ -0,0 +1,2 @@
1
2

32
test/gen/g003.go2 Normal file
View File

@@ -0,0 +1,32 @@
// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"unsafe"
)
type Pair[F1, F2 any] struct {
f1 F1
f2 F2
}
func main() {
p := Pair[int32, int64]{1, 2}
if got, want := unsafe.Sizeof(p.f1), uintptr(4); got != want {
panic(fmt.Sprintf("unexpected f1 size == %d want %d", got, want))
}
if got, want := unsafe.Sizeof(p.f2), uintptr(8); got != want {
panic(fmt.Sprintf("unexpected f2 size == %d want %d", got, want))
}
type MyPair struct { f1 int32; f2 int64 }
mp := MyPair(p)
if mp.f1 != 1 || mp.f2 != 2 {
panic(fmt.Sprintf("mp == %#v want %#v", mp, MyPair{1, 2}))
}
}

39
test/gen/g004.go2 Normal file
View File

@@ -0,0 +1,39 @@
// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "fmt"
type Value[T any] struct {
val T
}
func (v *Value[T]) Get() T {
return v.val
}
func (v *Value[T]) Set(val T) {
v.val = val
}
func main() {
var v1 Value[int]
v1.Set(1)
if got, want := v1.Get(), 1; got != want {
panic(fmt.Sprintf("Get() == %d, want %d", got, want))
}
v1.Set(2)
if got, want := v1.Get(), 2; got != want {
panic(fmt.Sprintf("Get() == %d, want %d", got, want))
}
var v2 Value[string]
v2.Set("a")
if got, want := v2.Get(), "a"; got != want {
panic(fmt.Sprintf("Get() == %q, want %q", got, want))
}
}

30
test/gen/g005.dir/a.go2 Normal file
View File

@@ -0,0 +1,30 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package a
type Stack[E any] []E
func (s *Stack[E]) Push(e E) {
*s = append(*s, e)
}
func (s *Stack[E]) Pop() (E, bool) {
l := len(*s)
if l == 0 {
var zero E
return zero, false
}
r := (*s)[l - 1]
*s = (*s)[:l - 1]
return r, true
}
func (s *Stack[E]) IsEmpty() bool {
return len(*s) == 0
}
func (s *Stack[E]) Len() int {
return len(*s)
}

31
test/gen/g005.dir/b.go2 Normal file
View File

@@ -0,0 +1,31 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "./a"
func main() {
var s a.Stack[string]
s.Push("hi")
s.Push("bye")
if s.IsEmpty() {
panic("unexpected IsEmpty")
}
if s.Len() != 2 {
panic("bad Len")
}
if v, ok := s.Pop(); !ok || v != "bye" {
panic("bad Pop 1")
}
if v, ok := s.Pop(); !ok || v != "hi" {
panic("bad Pop 2")
}
if !s.IsEmpty() {
panic("expected IsEmpty")
}
if s.Len() != 0 {
panic("bad Len 2")
}
}

7
test/gen/g005.go2 Normal file
View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ignored

96
test/gen/g006.go2 Normal file
View File

@@ -0,0 +1,96 @@
// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
"math"
"os"
"sort"
)
type Ordered interface {
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64,
string
}
type orderedSlice[Elem Ordered] []Elem
func (s orderedSlice[Elem]) Len() int { return len(s) }
func (s orderedSlice[Elem]) Less(i, j int) bool {
if s[i] < s[j] {
return true
}
isNaN := func(f Elem) bool { return f != f }
if isNaN(s[i]) && !isNaN(s[j]) {
return true
}
return false
}
func (s orderedSlice[Elem]) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
func OrderedSlice[Elem Ordered](s []Elem) {
sort.Sort(orderedSlice[Elem](s))
}
var ints = []int{74, 59, 238, -784, 9845, 959, 905, 0, 0, 42, 7586, -5467984, 7586}
var float64s = []float64{74.3, 59.0, math.Inf(1), 238.2, -784.0, 2.3, math.NaN(), math.NaN(), math.Inf(-1), 9845.768, -959.7485, 905, 7.8, 7.8}
var strings = []string{"", "Hello", "foo", "bar", "foo", "f00", "%*&^*&^&", "***"}
func TestSortOrderedInts() bool {
return testOrdered("ints", ints, sort.Ints)
}
func TestSortOrderedFloat64s() bool {
return testOrdered("float64s", float64s, sort.Float64s)
}
func TestSortOrderedStrings() bool {
return testOrdered("strings", strings, sort.Strings)
}
func testOrdered[Elem Ordered](name string, s []Elem, sorter func([]Elem)) bool {
s1 := make([]Elem, len(s))
copy(s1, s)
s2 := make([]Elem, len(s))
copy(s2, s)
OrderedSlice(s1)
sorter(s2)
ok := true
if !sliceEq(s1, s2) {
fmt.Printf("%s: got %v, want %v", name, s1, s2)
ok = false
}
for i := len(s1) - 1; i > 0; i-- {
if s1[i] < s1[i-1] {
fmt.Printf("%s: element %d (%v) < element %d (%v)", name, i, s1[i], i - 1, s1[i - 1])
ok = false
}
}
return ok
}
func sliceEq[Elem Ordered](s1, s2 []Elem) bool {
for i, v1 := range s1 {
v2 := s2[i]
if v1 != v2 {
isNaN := func(f Elem) bool { return f != f }
if !isNaN(v1) || !isNaN(v2) {
return false
}
}
}
return true
}
func main() {
if !TestSortOrderedInts() || !TestSortOrderedFloat64s() || !TestSortOrderedStrings() {
os.Exit(1)
}
}

20
test/gen/g007.go2 Normal file
View File

@@ -0,0 +1,20 @@
// compile
// Copyright 2020 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.
// Using a type literal based on a type parameter as a type argument
// in a result.
package p
type S[T any] struct {
f T
}
func SliceS[T any]() S[[]T] {
return S[[]T]{nil}
}
var V = SliceS[int]()

41
test/gen/g008.go2 Normal file
View File

@@ -0,0 +1,41 @@
// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
type Setter interface {
Set(string)
}
func FromStrings[T Setter](s []string) []T {
result := make([]T, len(s))
for i, v := range s {
result[i].Set(v)
}
return result
}
type Settable int
func (p *Settable) Set(s string) {
*p = 0
}
func F() {
defer func() {
if recover() == nil {
panic("did not panic as expected")
}
}()
// This should type check but should panic at run time,
// because it will make a slice of *Settable and then call
// Set on a nil value.
FromStrings(*Settable)([]string{"1"})
}
func main() {
F()
}

43
test/gen/g009.go2 Normal file
View File

@@ -0,0 +1,43 @@
// run
// Copyright 2020 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 (
"log"
"strconv"
)
type Setter2[B any] interface {
Set(string)
type *B
}
func FromStrings2[T any, PT Setter2[T]](s []string) []T {
result := make([]T, len(s))
for i, v := range s {
p := PT(&result[i])
p.Set(v)
}
return result
}
type Settable int
func (p *Settable) Set(s string) {
i, err := strconv.Atoi(s)
if err != nil {
log.Fatal(err)
}
*p = Settable(i)
}
func main() {
s := FromStrings2[Settable, *Settable]([]string{"1"})
if len(s) != 1 || s[0] != 1 {
log.Fatalf("got %v, want %v", s, []int{1})
}
}

38
test/gen/g010.go2 Normal file
View File

@@ -0,0 +1,38 @@
// run
// Copyright 2020 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 (
"log"
"strconv"
)
func FromStrings3[T any](s []string, set func(*T, string)) []T {
results := make([]T, len(s))
for i, v := range s {
set(&results[i], v)
}
return results
}
type Settable int
func (p *Settable) Set(s string) {
i, err := strconv.Atoi(s)
if err != nil {
log.Fatal(err)
}
*p = Settable(i)
}
func main() {
s := FromStrings3[Settable]([]string{"1"},
func(p *Settable, s string) { p.Set(s) })
if len(s) != 1 || s[0] != 1 {
log.Fatalf("got %v, want %v", s, []int{1})
}
}

46
test/gen/g011.go2 Normal file
View File

@@ -0,0 +1,46 @@
// run
// Copyright 2020 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 (
"log"
"strconv"
)
type Setter[B any] interface {
Set(string)
type *B
}
func FromStrings[T any, 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 Setter, so we can convert it to PT.
p := PT(&result[i])
// PT has a Set method.
p.Set(v)
}
return result
}
type Settable int
func (p *Settable) Set(s string) {
i, err := strconv.Atoi(s)
if err != nil {
log.Fatal(err)
}
*p = Settable(i)
}
func main() {
s := FromStrings[Settable, *Settable]([]string{"1"})
if len(s) != 1 || s[0] != 1 {
log.Fatalf("got %v, want %v", s, []int{1})
}
}

90
test/gen/g012.go2 Normal file
View File

@@ -0,0 +1,90 @@
// run
// Copyright 2020 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 "math"
type Numeric interface {
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64,
complex64, complex128
}
// NumericAbs matches numeric types with an Abs method.
type NumericAbs[T any] interface {
Numeric
Abs() T
}
// 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]](a, b T) T {
d := a - b
return d.Abs()
}
// OrderedNumeric matches numeric types that support the < operator.
type OrderedNumeric interface {
type int, int8, int16, int32, int64,
uint, uint8, uint16, uint32, uint64, uintptr,
float32, float64
}
// Complex matches the two complex types, which do not have a < operator.
type Complex interface {
type complex64, complex128
}
// OrderedAbs is a helper type that defines an Abs method for
// ordered numeric types.
type OrderedAbs[T OrderedNumeric] T
func (a OrderedAbs[T]) Abs() OrderedAbs[T] {
if a < 0 {
return -a
}
return a
}
// ComplexAbs is a helper type that defines an Abs method for
// complex types.
type ComplexAbs[T Complex] T
func (a ComplexAbs[T]) Abs() ComplexAbs[T] {
r := float64(real(a))
i := float64(imag(a))
d := math.Sqrt(r * r + i * i)
return ComplexAbs[T](complex(d, 0))
}
// OrderedAbsDifference returns the absolute value of the difference
// between a and b, where a and b are of an ordered type.
func OrderedAbsDifference[T OrderedNumeric](a, b T) T {
return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b)))
}
// ComplexAbsDifference returns the absolute value of the difference
// between a and b, where a and b are of a complex type.
func ComplexAbsDifference[T Complex](a, b T) T {
return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b)))
}
func main() {
if d := OrderedAbsDifference(1.0, -2.0); d != 3 {
panic(d)
}
if d := OrderedAbsDifference(-1.0, 2.0); d != 3 {
panic(d)
}
if d := ComplexAbsDifference(5.0 + 2.0i, 2.0 - 2.0i); d != 5 {
panic(d)
}
if d := ComplexAbsDifference(2.0 - 2.0i, 5.0 + 2.0i); d != 5 {
panic(d)
}
}

48
test/gen/g013.go2 Normal file
View File

@@ -0,0 +1,48 @@
// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
type Gen[A any] func() (A, bool)
func combine[T1, T2, T any](g1 Gen[T1], g2 Gen[T2], join func(T1, T2) T) Gen[T] {
return func() (T, bool) {
var t T
t1, ok := g1()
if !ok {
return t, false
}
t2, ok := g2()
if !ok {
return t, false
}
return join(t1, t2), true
}
}
type Pair[A, B any] struct {
A A
B B
}
func NewPair[A, B any](a A, b B) Pair[A, B] { return Pair[A, B]{a, b} }
func Combine2[A, B any](ga Gen[A], gb Gen[B]) Gen[Pair[A, B]] {
return combine(ga, gb, NewPair(A, B))
}
func main() {
var g1 Gen[int] = func() (int, bool) { return 3, true }
var g2 Gen[string] = func() (string, bool) { return "x", false }
gc := combine(g1, g2, NewPair[int, string])
gc2 := Combine2(g1, g2)
if got, ok := gc(); ok {
panic(got)
}
if got2, ok := gc2(); ok {
panic(got2)
}
}

44
test/gen/g014.go2 Normal file
View File

@@ -0,0 +1,44 @@
// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
type T[A any] struct {
V A
}
type S1 struct {
T[int]
V string
}
type Tint = T[int]
type Tbool = T[bool]
type S2 struct {
Tint
Tbool
V string
}
type S3 struct {
*T[int]
}
func main() {
var s1 S1
if s1.T.V != 0 {
panic(s1)
}
var s2 S2
if s2.Tint.V != 0 || s2.Tbool.V {
panic(s2)
}
var s3 S3
if s3.T != nil {
panic(s3)
}
}

17
test/gen/g015.go2 Normal file
View File

@@ -0,0 +1,17 @@
// compile
// Copyright 2020 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 F1[T any](x T) {}
func F2(c <-chan int) {
F1(c)
}
func F3(c chan <- int) {
F1(c)
}

92
test/gen/g016.go2 Normal file
View File

@@ -0,0 +1,92 @@
// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "fmt"
type Any interface{}
type Function[a, b any] interface {
Apply(x a) b
}
type incr struct{ n int }
func (this incr) Apply(x int) int {
return x + this.n
}
type pos struct{}
func (this pos) Apply(x int) bool {
return x > 0
}
type compose[a, b, c any] struct {
f Function[a, b]
g Function[b, c]
}
func (this compose[a, b, c]) Apply(x a) c {
return this.g.Apply(this.f.Apply(x))
}
type Eq[a any] interface {
Equal(a) bool
}
type Int int
func (this Int) Equal(that int) bool {
return int(this) == that
}
type List[a any] interface {
Match(casenil Function[Nil[a], Any], casecons Function[Cons[a], Any]) Any
}
type Nil[a any] struct{}
func (xs Nil[a]) Match(casenil Function[Nil[a], Any], casecons Function[Cons[a], Any]) Any {
return casenil.Apply(xs)
}
type Cons[a any] struct {
Head a
Tail List[a]
}
func (xs Cons[a]) Match(casenil Function[Nil[a], Any], casecons Function[Cons[a], Any]) Any {
return casecons.Apply(xs)
}
type mapNil[a, b any] struct{}
func (m mapNil[a, b]) Apply(_ Nil[a]) Any {
return Nil[b]{}
}
type mapCons[a, b any] struct {
f Function[a, b]
}
func (m mapCons[a, b]) Apply(xs Cons[a]) Any {
return Cons[b]{m.f.Apply(xs.Head), Map[a, b](m.f, xs.Tail)}
}
func Map[a, b any](f Function[a, b], xs List[a]) List[b] {
return xs.Match(mapNil[a, b]{}, mapCons[a, b]{f}).(List[b])
}
func main() {
var xs List[int] = Cons[int]{3, Cons[int]{6, Nil[int]{}}}
var ys List[int] = Map[int, int](incr{-5}, xs)
var xz List[bool] = Map[int, bool](pos{}, ys)
if fmt.Sprint(xz) != "{false {true {}}}" {
panic(xz)
}
}

24
test/gen/g017.go2 Normal file
View File

@@ -0,0 +1,24 @@
// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
type Recv <-chan int
type sliceOf[E any] interface {
type []E
}
func Append[S sliceOf[T], T any](s S, t ...T) S {
return append(s, t...)
}
func main() {
a := Append([]Recv{nil}, Recv(nil))
if len(a) != 2 || a[0] != nil || a[1] != nil {
panic(a)
}
}

27
test/gen/g018.go2 Normal file
View File

@@ -0,0 +1,27 @@
// compile
// Copyright 2020 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 I1 interface {
comparable
}
type I2 interface {
I1
}
type I3 I2
type I4 interface {
type int
}
type I5 interface {
I4
}
type I6 I5

24
test/gen/g019.go2 Normal file
View File

@@ -0,0 +1,24 @@
// compile
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39662.
package p
type S1 struct{}
func (*S1) M() {}
type S2 struct{}
func (S2) M() {}
func F1[T interface{ M() }](t T) {
_ = T.M
}
func F2() {
F1(&S1{})
F1(S2{})
F1(&S2{})
}

23
test/gen/g020.go2 Normal file
View File

@@ -0,0 +1,23 @@
// compile
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39653.
package p
type E struct{}
type N[T any] struct {
i int
n T
}
func F1[T any](i int, n T) N[T] {
return N[T]{i: i, n: n}
}
func F2() {
F1(1, F1(2, F1(3, E{})))
}

50
test/gen/g021.go2 Normal file
View File

@@ -0,0 +1,50 @@
// run
// Copyright 2020 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 "sync"
// A Lockable is a value that may be safely simultaneously accessed
// from multiple goroutines via the Get and Set methods.
type Lockable[T any] struct {
T
mu sync.Mutex
}
// Get returns the value stored in a Lockable.
func (l *Lockable[T]) Get() T {
l.mu.Lock()
defer l.mu.Unlock()
return l.T
}
// Set sets the value in a Lockable.
func (l *Lockable[T]) Set(v T) {
l.mu.Lock()
defer l.mu.Unlock()
l.T = v
}
func main() {
sl := Lockable[string]{T: "a"}
if got := sl.Get(); got != "a" {
panic(got)
}
sl.Set("b")
if got := sl.Get(); got != "b" {
panic(got)
}
il := Lockable[int]{T: 1}
if got := il.Get(); got != 1 {
panic(got)
}
il.Set(2)
if got := il.Get(); got != 2 {
panic(got)
}
}

11
test/gen/g022.go2 Normal file
View File

@@ -0,0 +1,11 @@
// compile
// Copyright 2020 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[T any] func(T) error
type instF = F[int]

17
test/gen/g023.go2 Normal file
View File

@@ -0,0 +1,17 @@
// compile
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
import "net/url"
type S[T any] struct {
f T
}
func F() S[url.Error] {
return S[url.Error]{}
}

23
test/gen/g024.go2 Normal file
View File

@@ -0,0 +1,23 @@
// compile
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39672
package p
type S[T any] T
func (r S[T]) M()
func F() {
var x S[int]
_ = x
}
func G[T any](v T)
func F2() {
G(0)
}

29
test/gen/g025.go2 Normal file
View File

@@ -0,0 +1,29 @@
// compile
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39692
package p
type S1[T1, T2 any] struct {
f1 T1
f2 T2
}
type S2[T1, T2 any] struct {
f1 T1
f2 T2
}
func F1[T any](v T) T {
return v
}
func F() {
_ = S2[int, S1[S1[int, int], S1[int, int]]]{
f1: 0,
f2: S1[S1[int, int], S1[int, int]]{},
}
}

16
test/gen/g026.go2 Normal file
View File

@@ -0,0 +1,16 @@
// run
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39625.
package main
import "io/ioutil"
func F[T1, T2 any](f func(T1) (T2, error)) {}
func main() {
F(ioutil.ReadAll)
}

34
test/gen/g027.go2 Normal file
View File

@@ -0,0 +1,34 @@
// compile
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39678, 39881.
package p
type B[T any] struct {
T
}
type C struct {
F int
}
type BC B[C]
func F(s BC) {
s.F = 7
}
type Pair[T, U any] struct {
T
U
}
func (p Pair[T, U]) M() {
_, _ = p.T, p.U
}
var V1 Pair[Pair[int, int], int]
var V2 Pair[struct { p Pair[int, int] }, int]

14
test/gen/g028.go2 Normal file
View File

@@ -0,0 +1,14 @@
// compile
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39688.
package p
type S[T any] T
func (*S[T]) M() {}
var V S[int]

16
test/gen/g029.go2 Normal file
View File

@@ -0,0 +1,16 @@
// compile
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39741.
package p
func F[T any]() {
type S struct{}
}
func G() {
F[int]()
}

20
test/gen/g030.dir/a.go2 Normal file
View File

@@ -0,0 +1,20 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
func Len[T any](s []T) int {
return len(s)
}
func F1(s []int) int {
return Len(s)
}
func main() {
got := F1(nil) + F2(nil)
if got != 0 {
panic(got)
}
}

9
test/gen/g030.dir/b.go2 Normal file
View File

@@ -0,0 +1,9 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
func F2(s []int) int {
return Len(s)
}

7
test/gen/g030.go2 Normal file
View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ignored

14
test/gen/g031.go2 Normal file
View File

@@ -0,0 +1,14 @@
// compile
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39737.
package p
func F1[T any]() {}
func F2() {
F1(struct { F string `json:"f"` })()
}

16
test/gen/g032.go2 Normal file
View File

@@ -0,0 +1,16 @@
// compile
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Issue 39744.
package p
import "net/http"
func F1[T any](f func() T) { f() }
func F2() {
F1(func() *http.Request { return nil })
}

9
test/gen/g033.dir/a.go2 Normal file
View File

@@ -0,0 +1,9 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package a
type S[T any] struct {
F T
}

16
test/gen/g033.dir/b.go2 Normal file
View File

@@ -0,0 +1,16 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "./a"
type S = a.S
func main() {
var s S[int]
if s.F != 0 {
panic(s.F)
}
}

7
test/gen/g033.go2 Normal file
View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ignored

20
test/gen/g034.go2 Normal file
View File

@@ -0,0 +1,20 @@
// compile
// Copyright 2020 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 I interface{}
type S[T any] struct {
*T
}
func F() {
v := S[I]{}
if v.T != nil {
panic(v)
}
}

9
test/gen/g035.dir/a.go2 Normal file
View File

@@ -0,0 +1,9 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package a
type S[T any] struct {
f T
}

20
test/gen/g035.dir/b.go2 Normal file
View File

@@ -0,0 +1,20 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "./a"
type S = a.S
func F1[T any](T) {}
func F2() { F1(S[string]{}) }
func F3() { F1[S[string]](S[string]{}) }
func main() {
F2()
F3()
}

7
test/gen/g035.go2 Normal file
View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ignored

13
test/gen/g036.dir/a.go2 Normal file
View File

@@ -0,0 +1,13 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package a
type S[T any] struct {
F T
}
func NewS[T any](v T) S[T] {
return S[T]{F: v}
}

23
test/gen/g036.dir/b.go2 Normal file
View File

@@ -0,0 +1,23 @@
// Copyright 2020 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import "./a"
type S[T any] struct {
F T
}
func NewS[T any](v T) S[T] {
return S[T]{F: v}
}
func main() {
v1 := a.NewS(0)
v2 := NewS(0)
if v1.F != v2.F {
panic(v1)
}
}

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