mirror of https://github.com/golang/go.git
[dev.fuzz] all: merge master (c95464f) into dev.fuzz
The new SetEnv method for *testing.T and *testing.B types was automatically supported by *testing.F since it was added to the *testing.common type. This function is not appropriate for *testing.F since fuzzing is run in parallel by default. Conflicts: - api/next.txt Merge List: + 2021-06-27c95464f0eainternal/buildcfg: refactor GOEXPERIMENT parsing code somewhat + 2021-06-25ed01ceaf48runtime/race: use race build tag on syso_test.go + 2021-06-25d1916e5e84go/types: in TestCheck/issues.src, import regexp/syntax instead of cmd/compile/internal/syntax + 2021-06-255160896c69go/types: in TestStdlib, import from source instead of export data + 2021-06-25d01bc571f7runtime: make ncgocall a global counter + 2021-06-2537f9a8f69dgo/types: fix a bug in package qualification logic + 2021-06-24c309c89db5reflect: document that InterfaceData is a low-entropy RNG + 2021-06-24cce621431acmd/compile: fix wrong type in SSA generation for OSLICE2ARRPTR + 2021-06-24600a2a4ffbcmd/go: don't try to add replaced versions that won't be selected + 2021-06-24a9bb38222anet: remove hard-coded timeout in dialClosedPort test helper + 2021-06-2486d72fa2cbtime: handle invalid UTF-8 byte sequences in quote to prevent panic + 2021-06-2444a12e5f33cmd/go: search breadth-first instead of depth-first for test dependency cycles + 2021-06-2473496e0df0net: use absDomainName in the Windows lookupPTR test helper + 2021-06-24222ed1b38aos: enable TestFifoEOF on openbsd + 2021-06-220ebd5a8de0cmd/go: update ToolTags based on GOARCH value + 2021-06-225bd09e5efcspec: unsafe.Add/Slice are not permitted in statement context + 2021-06-22666315b4d3runtime/internal/atomic: remove incorrect pointer indirection in comment + 2021-06-2263daa774b5go/types: guard against checking instantiation when generics is disabled + 2021-06-22197a5ee2abcmd/gofmt: remove stale documentation for the -G flag + 2021-06-229afd158eb2go/parser: parse an ast.IndexExpr for a[] + 2021-06-211bd5a20e3ccmd/go: add a -go flag to 'go mod graph' + 2021-06-21761edf71f6cmd/internal/moddeps: use a temporary directory for GOMODCACHE if needed + 2021-06-21a0400420adcmd/internal/moddeps: use -mod=readonly instead of -mod=mod + 2021-06-213f9ec83b10cmd/go: document GOPPC64 environment variable + 2021-06-2120bdfba325go/scanner: fall back to next() when encountering 0 bytes in parseIdentifier + 2021-06-2144f9a3566cdatabase/sql: fix deadlock test in prepare statement + 2021-06-2116e82be454runtime: fix crash during VDSO calls on PowerPC + 2021-06-212e542c3c06runtime/pprof: deflake TestMorestack more + 2021-06-21ced0fdbad0doc/go1.17: note deprecation of 'go get' for installing commands + 2021-06-217a5e7047a4doc/go1.17: add Go 1.18 pre-announcements + 2021-06-2185a2e24afddoc/go1.17: add security-related release notes + 2021-06-211de332996cdoc/go1.17: document go/parser.SkipObjectResolution + 2021-06-21117ebe0f52cmd/go: do not require the module cache to exist for 'go mod edit' + 2021-06-20460900a7b5os/signal: test with a significantly longer fatal timeout + 2021-06-19b73cc4b02bdatabase/sql: do not rely on timeout for deadlock test + 2021-06-1886743e7d86image: add RGBA64Image interface + 2021-06-189401172166runtime: clarify Frames.Next documentation + 2021-06-1857aaa19aaeruntime: disable CPU profiling before removing the SIGPROF handler + 2021-06-186f22d2c682doc/go1.17: fix typo + 2021-06-1745f251ad6ccmd/pprof,runtime/pprof: disable test on more broken platforms + 2021-06-17ed834853adcmd/go: replace a TODO with an explanatory comment + 2021-06-174dede02550cmd/pprof: make ObjAddr a no-op + 2021-06-1797cee43c93testing: drop unusual characters from TempDir directory name + 2021-06-17b0355a3e72time: fix receiver for Time.IsDST method + 2021-06-17881b6ea7badoc/go1.17: fix redundant space + 2021-06-160e67ce3d28cmd/go: in lazy modules, add transitive imports for 'go get' arguments + 2021-06-166ea2af0890cmd/go: add a regression test for #45979 + 2021-06-16a294e4e798math/rand: mention half-open intervals explicitly + 2021-06-16a6a853f94ccmd/asm: restore supporting of *1 scaling on ARM64 + 2021-06-16785a8f677fcmd/compile: better error message for invalid untyped operation + 2021-06-16a752bc0746syscall: fix TestGroupCleanupUserNamespace test failure on Fedora + 2021-06-15d77f4c0c5cnet/http: improve some server docs + 2021-06-15219fe9d547cmd/go: ignore UTF8 BOM when reading source code + 2021-06-15723f199eddcmd/link: set correct flags in .dynamic for PIE buildmode + 2021-06-154d2d89ff42cmd/go, go/build: update docs to use //go:build syntax + 2021-06-15033d885315doc/go1.17: document go run pkg@version + 2021-06-15ea8612ef42syscall: disable c-shared test when no cgo, for windows/arm + 2021-06-15abc56fd1a0internal/bytealg: remove duplicate go:build line + 2021-06-154061d3463bsyscall: rewrite handle inheritance test to use C rather than Powershell + 2021-06-15cf4e3e3d3breflect: explain why convertible or comparable types may still panic + 2021-06-147841cb14d9doc/go1.17: assorted fixes + 2021-06-148a5a6f46dcdebug/elf: don't apply DWARF relocations for ET_EXEC binaries + 2021-06-149d13f8d43eruntime: update the variable name in comment + 2021-06-140fd20ed5b6reflect: use same conversion panic in reflect and runtime + 2021-06-146bbb0a9d4acmd/internal/sys: mark windows/arm64 as c-shared-capable + 2021-06-14d4f34f8c63doc/go1.17: reword "results" in stack trace printing + 2021-06-14fdab5be159doc/go1.17: further revise OpenBSD release notes + 2021-06-14326ea438bbcmd/compile: rewrite a, b = f() to use temporaries when type not identical + 2021-06-143249b645c9cmd/compile: factor out rewrite multi-valued f() + 2021-06-1314305bf0b9misc/cgo: generate Windows import libraries for clang + 2021-06-1324cff0f044cmd/go, misc/cgo: skip test if no .edata + 2021-06-1367b1b6a2e3cmd/compile: allow ir.OSLICE2ARRPTR in mayCall + 2021-06-121ed0d129e9runtime: testprogcgo: don't call exported Go functions directly from Go + 2021-06-129d46ee5ac4reflect: handle stack-to-register translation in callMethod + 2021-06-11e552a6d312cmd/go: remove hint when no module is suggested + 2021-06-1116b5d766d8syscall: do not load native libraries on non-native powershell on arm + 2021-06-1177aa209b38runtime: loop on EINTR in macOS sigNoteSleep + 2021-06-11e2dc6dd5c9doc/go1.17: clean up formatting of gofmt section + 2021-06-112f1128461dcmd/go: match Windows paths in TestScript/mod_invalid_version + 2021-06-112721da2608doc/go1.17: fix formatting near httptest + 2021-06-10770f1de8c5net/http: remove test-only private key from production binaries + 2021-06-108d11b1d117cmd/go: report the imports of CompiledGoFiles in ImportMap + 2021-06-10dc00dc6c6bcrypto/tls: let HTTP/1.1 clients connect to servers with NextProtos "h2" + 2021-06-0927f83723e9api: promote next to go1.17 + 2021-06-09182157c81adoc/go1.17: remove lingering TODO + 2021-06-09a5bc060b42doc/go1.17: document strconv changes for Go 1.17 + 2021-06-091402b27d46strconv: document parsing of leading +/- + 2021-06-09df35ade067doc/go1.17: document //go:build lines + 2021-06-09e4e7807d24net/http: add AllowQuerySemicolons + 2021-06-09ec3026d032doc/go1.17: remove TODO for ports section + 2021-06-09e6dda19888net/url: reject query values with semicolons + 2021-06-09139e935d3cmath/big: comment division + 2021-06-09aa5540cd82cmd/compile: make map.zero symbol content-addressable + 2021-06-0907ca28d529cmd/link: fix bug in -strictdups checking of BSS symbols + 2021-06-08bcecae2af6doc/go1.17: mention new possibility of type conversion panicking + 2021-06-0863dcab2e91doc/go1.17: mention new vet checks sigchanyzer and stdmethods. + 2021-06-086551763a60doc/go1.17: mention block profile bias fix + 2021-06-08cb80937bf6Revert "doc/go1.17: mention block profile bias fix" + 2021-06-08d3e3d03666net: reject leading zeros in IP address parsers + 2021-06-08da4a640141doc/go1.17: revise OpenBSD release notes + 2021-06-08689f4c7415doc/go1.17: mention block profile bias fix + 2021-06-089afe071c60doc/go1.17: remove TODO for Tools section + 2021-06-08f753d7223edoc/go1.17: resolve TODO for cmd/cover + 2021-06-089498b0155dcmd/go: in Go 1.17+ modules, add indirect go.mod dependencies separately from direct ones + 2021-06-08949f00cebedoc/go1.17: add release notes for crypto packages + 2021-06-080fb3e2c184doc/go1.17: add a release note for the '-compat' flag to 'go mod tidy' + 2021-06-082169deb352cmd/compile: use t.AllMethods when sorting typesByString + 2021-06-08c20bcb6488runtime: remove out-of-date comments about frame skipping + 2021-06-0739c39ae52fdoc: document Go 1.17 language changes + 2021-06-07dc8b558951cmd/dist: pass -Wno-lto-type-mismatch in swig_callback_lto + 2021-06-07909dd5e010strconv: ParseFloat: always return ErrSyntax for bad syntax + 2021-06-078212707871crypto/elliptic: update P-521 docs to say it's constant-time + 2021-06-077406180012fmt: split package documentation into more sections + 2021-06-07e3176bbc3ecrypto/tls: fix typo in Config.NextProtos docs + 2021-06-05e1fa26026dspec: improve wording consistency by eliminating "specifier" + 2021-06-05f490134126spec: improve wording by choosing an official term "keyword" + 2021-06-05e3cb381704go/internal/gcimporter: don't waste CPU copying bytes in `io.ReadAll` + 2021-06-059d669ed47amisc/cgo/errors: use expected column numbers + 2021-06-0495939e8de7cmd/compile/internal/abi: fix typo in comment + 2021-06-04831f9376d8net/http: fix ResponseWriter.ReadFrom with short reads + 2021-06-043a9d906edcos: avoid finalizer race in windows process object + 2021-06-04105c5b50e0os: terminate windows processes via handle directly + 2021-06-0479cd407f88syscall: regenerate zsyscall_windows.go + 2021-06-04c6b6211229doc/go1.17: document testing changes for Go 1.17 + 2021-06-040214440075syscall: do not pass console handles to PROC_THREAD_ATTRIBUTE_HANDLE_LIST on Windows 7 + 2021-06-04962d5c997acmd/compile,go/types: restrict use of unsafe.{Add,Slice} to go1.17 or newer + 2021-06-04b29b123e07cmd/compile: remove spurious ir.Dump + 2021-06-036d98301114cmd/link: use correct alignment in PE DWARF sections + 2021-06-03e0d029f758runtime: avoid gp.lockedm race in exitsyscall0 Change-Id: I00216c3c36e64814c44c79f25d1f38e4df6c1f24
This commit is contained in:
commit
0cf1e16bac
|
|
@ -0,0 +1,191 @@
|
|||
pkg archive/zip, method (*File) OpenRaw() (io.Reader, error)
|
||||
pkg archive/zip, method (*Writer) Copy(*File) error
|
||||
pkg archive/zip, method (*Writer) CreateRaw(*FileHeader) (io.Writer, error)
|
||||
pkg compress/lzw, method (*Reader) Close() error
|
||||
pkg compress/lzw, method (*Reader) Read([]uint8) (int, error)
|
||||
pkg compress/lzw, method (*Reader) Reset(io.Reader, Order, int)
|
||||
pkg compress/lzw, method (*Writer) Close() error
|
||||
pkg compress/lzw, method (*Writer) Reset(io.Writer, Order, int)
|
||||
pkg compress/lzw, method (*Writer) Write([]uint8) (int, error)
|
||||
pkg compress/lzw, type Reader struct
|
||||
pkg compress/lzw, type Writer struct
|
||||
pkg crypto/tls, method (*CertificateRequestInfo) Context() context.Context
|
||||
pkg crypto/tls, method (*ClientHelloInfo) Context() context.Context
|
||||
pkg crypto/tls, method (*Conn) HandshakeContext(context.Context) error
|
||||
pkg database/sql, method (*NullByte) Scan(interface{}) error
|
||||
pkg database/sql, method (*NullInt16) Scan(interface{}) error
|
||||
pkg database/sql, method (NullByte) Value() (driver.Value, error)
|
||||
pkg database/sql, method (NullInt16) Value() (driver.Value, error)
|
||||
pkg database/sql, type NullByte struct
|
||||
pkg database/sql, type NullByte struct, Byte uint8
|
||||
pkg database/sql, type NullByte struct, Valid bool
|
||||
pkg database/sql, type NullInt16 struct
|
||||
pkg database/sql, type NullInt16 struct, Int16 int16
|
||||
pkg database/sql, type NullInt16 struct, Valid bool
|
||||
pkg debug/elf, const SHT_MIPS_ABIFLAGS = 1879048234
|
||||
pkg debug/elf, const SHT_MIPS_ABIFLAGS SectionType
|
||||
pkg encoding/csv, method (*Reader) FieldPos(int) (int, int)
|
||||
pkg go/build, type Context struct, ToolTags []string
|
||||
pkg go/parser, const SkipObjectResolution = 64
|
||||
pkg go/parser, const SkipObjectResolution Mode
|
||||
pkg image, method (*Alpha) RGBA64At(int, int) color.RGBA64
|
||||
pkg image, method (*Alpha) SetRGBA64(int, int, color.RGBA64)
|
||||
pkg image, method (*Alpha16) RGBA64At(int, int) color.RGBA64
|
||||
pkg image, method (*Alpha16) SetRGBA64(int, int, color.RGBA64)
|
||||
pkg image, method (*CMYK) RGBA64At(int, int) color.RGBA64
|
||||
pkg image, method (*CMYK) SetRGBA64(int, int, color.RGBA64)
|
||||
pkg image, method (*Gray) RGBA64At(int, int) color.RGBA64
|
||||
pkg image, method (*Gray) SetRGBA64(int, int, color.RGBA64)
|
||||
pkg image, method (*Gray16) RGBA64At(int, int) color.RGBA64
|
||||
pkg image, method (*Gray16) SetRGBA64(int, int, color.RGBA64)
|
||||
pkg image, method (*NRGBA) RGBA64At(int, int) color.RGBA64
|
||||
pkg image, method (*NRGBA) SetRGBA64(int, int, color.RGBA64)
|
||||
pkg image, method (*NRGBA64) RGBA64At(int, int) color.RGBA64
|
||||
pkg image, method (*NRGBA64) SetRGBA64(int, int, color.RGBA64)
|
||||
pkg image, method (*NYCbCrA) RGBA64At(int, int) color.RGBA64
|
||||
pkg image, method (*Paletted) RGBA64At(int, int) color.RGBA64
|
||||
pkg image, method (*Paletted) SetRGBA64(int, int, color.RGBA64)
|
||||
pkg image, method (*RGBA) RGBA64At(int, int) color.RGBA64
|
||||
pkg image, method (*RGBA) SetRGBA64(int, int, color.RGBA64)
|
||||
pkg image, method (*YCbCr) RGBA64At(int, int) color.RGBA64
|
||||
pkg image, type RGBA64Image interface { At, Bounds, ColorModel, RGBA64At }
|
||||
pkg image, type RGBA64Image interface, At(int, int) color.Color
|
||||
pkg image, type RGBA64Image interface, Bounds() Rectangle
|
||||
pkg image, type RGBA64Image interface, ColorModel() color.Model
|
||||
pkg image, type RGBA64Image interface, RGBA64At(int, int) color.RGBA64
|
||||
pkg image/draw, type RGBA64Image interface { At, Bounds, ColorModel, RGBA64At, Set, SetRGBA64 }
|
||||
pkg image/draw, type RGBA64Image interface, At(int, int) color.Color
|
||||
pkg image/draw, type RGBA64Image interface, Bounds() image.Rectangle
|
||||
pkg image/draw, type RGBA64Image interface, ColorModel() color.Model
|
||||
pkg image/draw, type RGBA64Image interface, RGBA64At(int, int) color.RGBA64
|
||||
pkg image/draw, type RGBA64Image interface, Set(int, int, color.Color)
|
||||
pkg image/draw, type RGBA64Image interface, SetRGBA64(int, int, color.RGBA64)
|
||||
pkg io/fs, func FileInfoToDirEntry(FileInfo) DirEntry
|
||||
pkg math, const MaxFloat64 = 1.79769e+308 // 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368
|
||||
pkg math, const MaxInt = 9223372036854775807
|
||||
pkg math, const MaxInt ideal-int
|
||||
pkg math, const MaxUint = 18446744073709551615
|
||||
pkg math, const MaxUint ideal-int
|
||||
pkg math, const MinInt = -9223372036854775808
|
||||
pkg math, const MinInt ideal-int
|
||||
pkg math, const SmallestNonzeroFloat32 = 1.4013e-45 // 1/713623846352979940529142984724747568191373312
|
||||
pkg math, const SmallestNonzeroFloat64 = 4.94066e-324 // 1/202402253307310618352495346718917307049556649764142118356901358027430339567995346891960383701437124495187077864316811911389808737385793476867013399940738509921517424276566361364466907742093216341239767678472745068562007483424692698618103355649159556340810056512358769552333414615230502532186327508646006263307707741093494784
|
||||
pkg net, method (*ParseError) Temporary() bool
|
||||
pkg net, method (*ParseError) Timeout() bool
|
||||
pkg net, method (IP) IsPrivate() bool
|
||||
pkg net/http, func AllowQuerySemicolons(Handler) Handler
|
||||
pkg net/url, method (Values) Has(string) bool
|
||||
pkg reflect, func VisibleFields(Type) []StructField
|
||||
pkg reflect, method (Method) IsExported() bool
|
||||
pkg reflect, method (StructField) IsExported() bool
|
||||
pkg runtime/cgo (darwin-amd64-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (darwin-amd64-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (freebsd-386-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (freebsd-386-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (freebsd-386-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (freebsd-386-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (freebsd-amd64-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (freebsd-amd64-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (freebsd-amd64-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (freebsd-amd64-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (freebsd-arm-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (freebsd-arm-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (freebsd-arm-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (freebsd-arm-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (linux-386-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (linux-386-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (linux-386-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (linux-386-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (linux-amd64-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (linux-amd64-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (linux-amd64-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (linux-amd64-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (linux-arm-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (linux-arm-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (linux-arm-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (linux-arm-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (netbsd-386-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (netbsd-386-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (netbsd-386-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (netbsd-386-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (netbsd-amd64-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (netbsd-amd64-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (netbsd-amd64-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (netbsd-amd64-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (netbsd-arm-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (netbsd-arm-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (netbsd-arm-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (netbsd-arm-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (netbsd-arm64-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (netbsd-arm64-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (netbsd-arm64-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (netbsd-arm64-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (openbsd-386-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (openbsd-386-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (openbsd-386-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (openbsd-386-cgo), type Handle uintptr
|
||||
pkg runtime/cgo (openbsd-amd64-cgo), func NewHandle(interface{}) Handle
|
||||
pkg runtime/cgo (openbsd-amd64-cgo), method (Handle) Delete()
|
||||
pkg runtime/cgo (openbsd-amd64-cgo), method (Handle) Value() interface{}
|
||||
pkg runtime/cgo (openbsd-amd64-cgo), type Handle uintptr
|
||||
pkg strconv, func QuotedPrefix(string) (string, error)
|
||||
pkg sync/atomic, method (*Value) CompareAndSwap(interface{}, interface{}) bool
|
||||
pkg sync/atomic, method (*Value) Swap(interface{}) interface{}
|
||||
pkg syscall (netbsd-386), const SYS_WAIT6 = 481
|
||||
pkg syscall (netbsd-386), const SYS_WAIT6 ideal-int
|
||||
pkg syscall (netbsd-386), const WEXITED = 32
|
||||
pkg syscall (netbsd-386), const WEXITED ideal-int
|
||||
pkg syscall (netbsd-386-cgo), const SYS_WAIT6 = 481
|
||||
pkg syscall (netbsd-386-cgo), const SYS_WAIT6 ideal-int
|
||||
pkg syscall (netbsd-386-cgo), const WEXITED = 32
|
||||
pkg syscall (netbsd-386-cgo), const WEXITED ideal-int
|
||||
pkg syscall (netbsd-amd64), const SYS_WAIT6 = 481
|
||||
pkg syscall (netbsd-amd64), const SYS_WAIT6 ideal-int
|
||||
pkg syscall (netbsd-amd64), const WEXITED = 32
|
||||
pkg syscall (netbsd-amd64), const WEXITED ideal-int
|
||||
pkg syscall (netbsd-amd64-cgo), const SYS_WAIT6 = 481
|
||||
pkg syscall (netbsd-amd64-cgo), const SYS_WAIT6 ideal-int
|
||||
pkg syscall (netbsd-amd64-cgo), const WEXITED = 32
|
||||
pkg syscall (netbsd-amd64-cgo), const WEXITED ideal-int
|
||||
pkg syscall (netbsd-arm), const SYS_WAIT6 = 481
|
||||
pkg syscall (netbsd-arm), const SYS_WAIT6 ideal-int
|
||||
pkg syscall (netbsd-arm), const WEXITED = 32
|
||||
pkg syscall (netbsd-arm), const WEXITED ideal-int
|
||||
pkg syscall (netbsd-arm-cgo), const SYS_WAIT6 = 481
|
||||
pkg syscall (netbsd-arm-cgo), const SYS_WAIT6 ideal-int
|
||||
pkg syscall (netbsd-arm-cgo), const WEXITED = 32
|
||||
pkg syscall (netbsd-arm-cgo), const WEXITED ideal-int
|
||||
pkg syscall (netbsd-arm64), const SYS_WAIT6 = 481
|
||||
pkg syscall (netbsd-arm64), const SYS_WAIT6 ideal-int
|
||||
pkg syscall (netbsd-arm64), const WEXITED = 32
|
||||
pkg syscall (netbsd-arm64), const WEXITED ideal-int
|
||||
pkg syscall (netbsd-arm64-cgo), const SYS_WAIT6 = 481
|
||||
pkg syscall (netbsd-arm64-cgo), const SYS_WAIT6 ideal-int
|
||||
pkg syscall (netbsd-arm64-cgo), const WEXITED = 32
|
||||
pkg syscall (netbsd-arm64-cgo), const WEXITED ideal-int
|
||||
pkg syscall (openbsd-386), const MSG_CMSG_CLOEXEC = 2048
|
||||
pkg syscall (openbsd-386), const MSG_CMSG_CLOEXEC ideal-int
|
||||
pkg syscall (openbsd-386-cgo), const MSG_CMSG_CLOEXEC = 2048
|
||||
pkg syscall (openbsd-386-cgo), const MSG_CMSG_CLOEXEC ideal-int
|
||||
pkg syscall (openbsd-amd64), const MSG_CMSG_CLOEXEC = 2048
|
||||
pkg syscall (openbsd-amd64), const MSG_CMSG_CLOEXEC ideal-int
|
||||
pkg syscall (openbsd-amd64-cgo), const MSG_CMSG_CLOEXEC = 2048
|
||||
pkg syscall (openbsd-amd64-cgo), const MSG_CMSG_CLOEXEC ideal-int
|
||||
pkg syscall (windows-386), type SysProcAttr struct, AdditionalInheritedHandles []Handle
|
||||
pkg syscall (windows-386), type SysProcAttr struct, ParentProcess Handle
|
||||
pkg syscall (windows-amd64), type SysProcAttr struct, AdditionalInheritedHandles []Handle
|
||||
pkg syscall (windows-amd64), type SysProcAttr struct, ParentProcess Handle
|
||||
pkg testing, method (*B) Setenv(string, string)
|
||||
pkg testing, method (*T) Setenv(string, string)
|
||||
pkg text/template/parse, const SkipFuncCheck = 2
|
||||
pkg text/template/parse, const SkipFuncCheck Mode
|
||||
pkg time, const Layout = "01/02 03:04:05PM '06 -0700"
|
||||
pkg time, const Layout ideal-string
|
||||
pkg time, func UnixMicro(int64) Time
|
||||
pkg time, func UnixMilli(int64) Time
|
||||
pkg time, method (Time) GoString() string
|
||||
pkg time, method (Time) IsDST() bool
|
||||
pkg time, method (Time) UnixMicro() int64
|
||||
pkg time, method (Time) UnixMilli() int64
|
||||
|
|
@ -88,11 +88,11 @@ pkg syscall (windows-386), type SysProcAttr struct, AdditionalInheritedHandles [
|
|||
pkg syscall (windows-386), type SysProcAttr struct, ParentProcess Handle
|
||||
pkg syscall (windows-amd64), type SysProcAttr struct, AdditionalInheritedHandles []Handle
|
||||
pkg syscall (windows-amd64), type SysProcAttr struct, ParentProcess Handle
|
||||
pkg testing, method (*B) Setenv(string, string)
|
||||
pkg testing, func Fuzz(func(*F)) FuzzResult
|
||||
pkg testing, func MainStart(testDeps, []InternalTest, []InternalBenchmark, []InternalFuzzTarget, []InternalExample) *M
|
||||
pkg testing, func RunFuzzTargets(func(string, string) (bool, error), []InternalFuzzTarget) bool
|
||||
pkg testing, func RunFuzzing(func(string, string) (bool, error), []InternalFuzzTarget) bool
|
||||
pkg testing, method (*B) Setenv(string, string)
|
||||
pkg testing, method (*F) Add(...interface{})
|
||||
pkg testing, method (*F) Cleanup(func())
|
||||
pkg testing, method (*F) Error(...interface{})
|
||||
|
|
@ -107,6 +107,7 @@ pkg testing, method (*F) Helper()
|
|||
pkg testing, method (*F) Log(...interface{})
|
||||
pkg testing, method (*F) Logf(string, ...interface{})
|
||||
pkg testing, method (*F) Name() string
|
||||
pkg testing, method (*F) Setenv(string, string)
|
||||
pkg testing, method (*F) Skip(...interface{})
|
||||
pkg testing, method (*F) SkipNow()
|
||||
pkg testing, method (*F) Skipf(string, ...interface{})
|
||||
|
|
@ -130,4 +131,3 @@ pkg time, func UnixMilli(int64) Time
|
|||
pkg time, method (*Time) IsDST() bool
|
||||
pkg time, method (Time) UnixMicro() int64
|
||||
pkg time, method (Time) UnixMilli() int64
|
||||
>>>>>>> origin/master
|
||||
|
|
|
|||
575
doc/go1.17.html
575
doc/go1.17.html
|
|
@ -25,12 +25,54 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
|
||||
<h2 id="language">Changes to the language</h2>
|
||||
|
||||
<p><!-- CL 216424 -->
|
||||
TODO: <a href="https://golang.org/cl/216424">https://golang.org/cl/216424</a>: allow conversion from slice to array ptr
|
||||
<p>
|
||||
Go 1.17 includes three small enhancements to the language.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 312212 -->
|
||||
TODO: <a href="https://golang.org/cl/312212">https://golang.org/cl/312212</a>: add unsafe.Add and unsafe.Slice
|
||||
<ul>
|
||||
<li><!-- CL 216424; issue 395 -->
|
||||
<a href="/ref/spec#Conversions_from_slice_to_array_pointer">Conversions
|
||||
from slice to array pointer</a>: An expression <code>s</code> of
|
||||
type <code>[]T</code> may now be converted to array pointer type
|
||||
<code>*[N]T</code>. If <code>a</code> is the result of such a
|
||||
conversion, then corresponding indices that are in range refer to
|
||||
the same underlying elements: <code>&a[i] == &s[i]</code>
|
||||
for <code>0 <= i < N</code>. The conversion panics if
|
||||
<code>len(s)</code> is less than <code>N</code>.
|
||||
</li>
|
||||
|
||||
<li><!-- CL 312212; issue 40481 -->
|
||||
<a href="/pkg/unsafe#Add"><code>unsafe.Add</code></a>:
|
||||
<code>unsafe.Add(ptr, len)</code> adds <code>len</code>
|
||||
to <code>ptr</code> and returns the updated pointer
|
||||
<code>unsafe.Pointer(uintptr(ptr) + uintptr(len))</code>.
|
||||
</li>
|
||||
|
||||
<li><!-- CL 312212; issue 19367 -->
|
||||
<a href="/pkg/unsafe#Slice"><code>unsafe.Slice</code></a>:
|
||||
For expression <code>ptr</code> of type <code>*T</code>,
|
||||
<code>unsafe.Slice(ptr, len)</code> returns a slice of
|
||||
type <code>[]T</code> whose underlying array starts
|
||||
at <code>ptr</code> and whose length and capacity
|
||||
are <code>len</code>.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
The package unsafe enhancements were added to simplify writing code that conforms
|
||||
to <code>unsafe.Pointer</code>'s <a href="/pkg/unsafe/#Pointer">safety
|
||||
rules</a>, but the rules remain unchanged. In particular, existing
|
||||
programs that correctly use <code>unsafe.Pointer</code> remain
|
||||
valid, and new programs must still follow the rules when
|
||||
using <code>unsafe.Add</code> or <code>unsafe.Slice</code>.
|
||||
</p>
|
||||
|
||||
|
||||
<p>
|
||||
Note that the new conversion from slice to array pointer is the
|
||||
first case in which a type conversion can panic at run time.
|
||||
Analysis tools that assume type conversions can never panic
|
||||
should be updated to consider this possibility.
|
||||
</p>
|
||||
|
||||
<h2 id="ports">Ports</h2>
|
||||
|
|
@ -61,11 +103,12 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
In Go 1.16, on the 64-bit x86 and 64-bit ARM architectures on
|
||||
OpenBSD (the <code>openbsd/amd64</code> and <code>openbsd/arm64</code>
|
||||
ports) system calls are made through <code>libc</code>, instead
|
||||
of directly using the machine instructions. In Go 1.17, this is
|
||||
also done on the 32-bit x86 and 32-bit ARM architectures on OpenBSD
|
||||
of directly using machine instructions. In Go 1.17, this is also
|
||||
done on the 32-bit x86 and 32-bit ARM architectures on OpenBSD
|
||||
(the <code>openbsd/386</code> and <code>openbsd/arm</code> ports).
|
||||
This ensures forward-compatibility with future versions of
|
||||
OpenBSD.
|
||||
This ensures compatibility with OpenBSD 6.9 onwards, which require
|
||||
system calls to be made through <code>libc</code> for non-static
|
||||
Go binaries.
|
||||
</p>
|
||||
|
||||
<h3 id="arm64">ARM64</h3>
|
||||
|
|
@ -76,16 +119,8 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
stack frame pointers only on Linux, macOS, and iOS.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
TODO: complete the Ports section
|
||||
</p>
|
||||
|
||||
<h2 id="tools">Tools</h2>
|
||||
|
||||
<p>
|
||||
TODO: complete the Tools section
|
||||
</p>
|
||||
|
||||
<h3 id="go-command">Go command</h3>
|
||||
|
||||
<h4 id="lazy-loading">Lazy module loading</h4>
|
||||
|
|
@ -103,8 +138,17 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<!-- TODO(bcmills): replace the design-doc link with proper documentation. -->
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/45094 --> To facilitate the upgrade to lazy loading,
|
||||
the <code>go</code> <code>mod</code> <code>tidy</code> subcommand now supports
|
||||
<p><!-- golang.org/issue/45965 -->
|
||||
Because the number of additional explicit requirements in the go.mod file may
|
||||
be substantial, in a Go 1.17 module the newly-added requirements
|
||||
on <em>indirect</em> dependencies are maintained in a
|
||||
separate <code>require</code> block from the block containing direct
|
||||
dependencies.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/45094 -->
|
||||
To facilitate the upgrade to lazy loading, the
|
||||
<code>go</code> <code>mod</code> <code>tidy</code> subcommand now supports
|
||||
a <code>-go</code> flag to set or change the <code>go</code> version in
|
||||
the <code>go.mod</code> file. To enable lazy loading for an existing module
|
||||
without changing the selected versions of its dependencies, run:
|
||||
|
|
@ -115,8 +159,39 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
</pre>
|
||||
|
||||
<p><!-- golang.org/issue/46141 -->
|
||||
TODO: Describe the <code>-compat</code> flag
|
||||
for <code>go</code> <code>mod</code> <code>tidy</code>.
|
||||
By default, <code>go</code> <code>mod</code> <code>tidy</code> verifies that
|
||||
the selected versions of dependencies relevant to the main module are the same
|
||||
versions that would be used by the prior Go release (Go 1.16 for a module that
|
||||
specifies <code>go</code> <code>1.17</code>), and preserves
|
||||
the <code>go.sum</code> entries needed by that release even for dependencies
|
||||
that are not normally needed by other commands.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <code>-compat</code> flag allows that version to be overridden to support
|
||||
older (or only newer) versions, up to the version specified by
|
||||
the <code>go</code> directive in the <code>go.mod</code> file. To tidy
|
||||
a <code>go</code> <code>1.17</code> module for Go 1.17 only, without saving
|
||||
checksums for (or checking for consistency with) Go 1.16:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
go mod tidy -compat=1.17
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Note that even if the main module is tidied with <code>-compat=1.17</code>,
|
||||
users who <code>require</code> the module from a
|
||||
<code>go</code> <code>1.16</code> or earlier module will still be able to
|
||||
use it, provided that the packages use only compatible language and library
|
||||
features.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/46366 -->
|
||||
The <code>go</code> <code>mod</code> <code>graph</code> subcommand also
|
||||
supports the <code>-go</code> flag, which causes it to report the graph as
|
||||
seen by the indicated Go version, showing dependencies that may otherwise be
|
||||
pruned out by lazy loading.
|
||||
</p>
|
||||
|
||||
<h4 id="module-deprecation-comments">Module deprecation comments</h4>
|
||||
|
|
@ -146,6 +221,16 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<code>environment</code> for details.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/43684 -->
|
||||
<code>go</code> <code>get</code> prints a deprecation warning when installing
|
||||
commands outside the main module (without the <code>-d</code> flag).
|
||||
<code>go</code> <code>install</code> <code>cmd@version</code> should be used
|
||||
instead to install a command at a specific version, using a suffix like
|
||||
<code>@latest</code> or <code>@v1.2.3</code>. In Go 1.18, the <code>-d</code>
|
||||
flag will always be enabled, and <code>go</code> <code>get</code> will only
|
||||
be used to change dependencies in <code>go.mod</code>.
|
||||
</p>
|
||||
|
||||
<h4 id="missing-go-directive"><code>go.mod</code> files missing <code>go</code> directives</h4>
|
||||
|
||||
<p><!-- golang.org/issue/44976 -->
|
||||
|
|
@ -210,18 +295,106 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<code>mod</code> <code>download</code> <code>all</code>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 249759 -->
|
||||
TODO: <a href="https://golang.org/cl/249759">https://golang.org/cl/249759</a>: cmd/cover: replace code using optimized golang.org/x/tools/cover
|
||||
<h4 id="build-lines"><code>//go:build</code> lines</h4>
|
||||
|
||||
<p>
|
||||
The <code>go</code> command now understands <code>//go:build</code> lines
|
||||
and prefers them over <code>// +build</code> lines. The new syntax uses
|
||||
boolean expressions, just like Go, and should be less error-prone.
|
||||
As of this release, the new syntax is fully supported, and all Go files
|
||||
should be updated to have both forms with the same meaning. To aid in
|
||||
migration, <a href="#gofmt"><code>gofmt</code></a> now automatically
|
||||
synchronizes the two forms. For more details on the syntax and migration plan,
|
||||
see
|
||||
<a href="https://golang.org/design/draft-gobuild">https://golang.org/design/draft-gobuild</a>.
|
||||
</p>
|
||||
|
||||
<h4 id="go run"><code>go</code> <code>run</code></h4>
|
||||
|
||||
<p><!-- golang.org/issue/42088 -->
|
||||
<code>go</code> <code>run</code> now accepts arguments with version suffixes
|
||||
(for example, <code>go</code> <code>run</code>
|
||||
<code>example.com/cmd@v1.0.0</code>). This causes <code>go</code>
|
||||
<code>run</code> to build and run packages in module-aware mode, ignoring the
|
||||
<code>go.mod</code> file in the current directory or any parent directory, if
|
||||
there is one. This is useful for running executables without installing them or
|
||||
without changing dependencies of the current module.
|
||||
</p>
|
||||
|
||||
<h3 id="gofmt">Gofmt</h3>
|
||||
|
||||
<p>
|
||||
<code>gofmt</code> (and <code>go</code> <code>fmt</code>) now synchronizes
|
||||
<code>//go:build</code> lines with <code>// +build</code> lines. If a file
|
||||
only has <code>// +build</code> lines, they will be moved to the appropriate
|
||||
location in the file, and matching <code>//go:build</code> lines will be
|
||||
added. Otherwise, <code>// +build</code> lines will be overwritten based on
|
||||
any existing <code>//go:build</code> lines. For more information, see
|
||||
<a href="https://golang.org/design/draft-gobuild">https://golang.org/design/draft-gobuild</a>.
|
||||
</p>
|
||||
|
||||
<h3 id="vet">Vet</h3>
|
||||
|
||||
<p><!-- CL 299532 -->
|
||||
TODO: <a href="https://golang.org/cl/299532">https://golang.org/cl/299532</a>: cmd/vet: bring in sigchanyzer to report unbuffered channels to signal.Notify
|
||||
<h4 id="vet-buildtags">New warning for mismatched <code>//go:build</code> and <code>// +build</code> lines</h4>
|
||||
|
||||
<p><!-- CL 240609 -->
|
||||
The <code>vet</code> tool now verifies that <code>//go:build</code> and
|
||||
<code>// +build</code> lines are in the correct part of the file and
|
||||
synchronized with each other. If they aren't,
|
||||
<a href="#gofmt"><code>gofmt</code></a> can be used to fix them. For more
|
||||
information, see
|
||||
<a href="https://golang.org/design/draft-gobuild">https://golang.org/design/draft-gobuild</a>.
|
||||
</p>
|
||||
|
||||
<h4 id="vet-sigchanyzer">New warning for calling <code>signal.Notify</code> on unbuffered channels</h4>
|
||||
|
||||
<p><!-- CL 299532 -->
|
||||
The vet tool now warns about calls to <a href="/pkg/os/signal/#Notify">signal.Notify</a>
|
||||
with incoming signals being sent to an unbuffered channel. Using an unbuffered channel
|
||||
risks missing signals sent on them as <code>signal.Notify</code> does not block when
|
||||
sending to a channel. For example:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
c := make(chan os.Signal)
|
||||
// signals are sent on c before the channel is read from.
|
||||
// This signal may be dropped as c is unbuffered.
|
||||
signal.Notify(c, os.Interrupt)
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
TODO: complete the Vet section
|
||||
Users of <code>signal.Notify</code> should use channels with sufficient buffer space to keep up with the
|
||||
expected signal rate.
|
||||
</p>
|
||||
|
||||
<h4 id="vet-error-stdmethods">New warnings for Is, As and Unwrap methods</h4>
|
||||
|
||||
<p><!-- CL 321389 -->
|
||||
The vet tool now warns about methods named <code>As</code>, <code>Is</code> or <code>Unwrap</code>
|
||||
on types implementing the <code>error</code> interface that have a different signature than the
|
||||
one expected by the <code>errors</code> package. The <code>errors.{As,Is,Unwrap}</code> functions
|
||||
expect such methods to implement either <code>Is(error)</code> <code>bool</code>,
|
||||
<code>As(interface{})</code> <code>bool</code>, or <code>Unwrap()</code> <code>error</code>
|
||||
respectively. The functions <code>errors.{As,Is,Unwrap}</code> will ignore methods with the same
|
||||
names but a different signature. For example:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
type MyError struct { hint string }
|
||||
func (m MyError) Error() string { ... } // MyError implements error.
|
||||
func (MyError) Is(target interface{}) bool { ... } // target is interface{} instead of error.
|
||||
func Foo() bool {
|
||||
x, y := MyError{"A"}, MyError{"B"}
|
||||
return errors.Is(x, y) // returns false as x != y and MyError does not have an `Is(error) bool` function.
|
||||
}
|
||||
</pre>
|
||||
|
||||
<h3 id="cover">Cover</h3>
|
||||
|
||||
<p><!-- CL 249759 -->
|
||||
The <code>cover</code> tool now uses an optimized parser
|
||||
from <code>golang.org/x/tools/cover</code>, which may be noticeably faster
|
||||
when parsing large coverage profiles.
|
||||
</p>
|
||||
|
||||
<h2 id="compiler">Compiler</h2>
|
||||
|
|
@ -231,7 +404,7 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
registers instead of the stack. This work is enabled for Linux, MacOS, and
|
||||
Windows on the 64-bit x86 architecture (the <code>linux/amd64</code>,
|
||||
<code>darwin/amd64</code>, <code>windows/amd64</code> ports). For a
|
||||
representative set of Go packages and programs, benchmarking has shown
|
||||
representative set of Go packages and programs, benchmarking has shown
|
||||
performance improvements of about 5%, and a typical reduction in binary size
|
||||
of about 2%.
|
||||
</p>
|
||||
|
|
@ -262,7 +435,8 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
by commas. Aggregate-typed (struct, array, string, slice, interface, and complex)
|
||||
arguments are delimited by curly braces. A caveat is that the value of an
|
||||
argument that only lives in a register and is not stored to memory may be
|
||||
inaccurate. Results (which were usually inaccurate) are no longer printed.
|
||||
inaccurate. Function return values (which were usually inaccurate) are no longer
|
||||
printed.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 283112, golang.org/issue/28727 -->
|
||||
|
|
@ -275,34 +449,6 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
|
||||
<h2 id="library">Core library</h2>
|
||||
|
||||
<p>
|
||||
TODO: complete the Core library section
|
||||
</p>
|
||||
|
||||
<h3 id="crypto/tls"><a href="/pkg/crypto/tls">crypto/tls</a></h3>
|
||||
|
||||
<p><!-- CL 295370 -->
|
||||
<a href="/pkg/crypto/tls#Conn.HandshakeContext">(*Conn).HandshakeContext</a> was added to
|
||||
allow the user to control cancellation of an in-progress TLS Handshake.
|
||||
The context provided is propagated into the
|
||||
<a href="/pkg/crypto/tls#ClientHelloInfo">ClientHelloInfo</a>
|
||||
and <a href="/pkg/crypto/tls#CertificateRequestInfo">CertificateRequestInfo</a>
|
||||
structs and accessible through the new
|
||||
<a href="/pkg/crypto/tls#ClientHelloInfo.Context">(*ClientHelloInfo).Context</a>
|
||||
and
|
||||
<a href="/pkg/crypto/tls#CertificateRequestInfo.Context">
|
||||
(*CertificateRequestInfo).Context
|
||||
</a> methods respectively. Canceling the context after the handshake has finished
|
||||
has no effect.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 289209 -->
|
||||
When <a href="/pkg/crypto/tls#Config">Config.NextProtos</a> is set, servers now
|
||||
enforce that there is an overlap between the configured protocols and the protocols
|
||||
advertised by the client, if any. If there is no overlap the connection is closed
|
||||
with the <code>no_application_protocol</code> alert, as required by RFC 7301.
|
||||
</p>
|
||||
|
||||
<h3 id="runtime/cgo"><a href="/pkg/runtime/cgo">Cgo</a></h3>
|
||||
|
||||
<p>
|
||||
|
|
@ -312,6 +458,67 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<a href="/pkg/runtime/cgo#Handle">runtime/cgo.Handle</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="semicolons">URL query parsing</h3>
|
||||
<!-- CL 325697, CL 326309 -->
|
||||
|
||||
<p>
|
||||
The <code>net/url</code> and <code>net/http</code> packages used to accept
|
||||
<code>";"</code> (semicolon) as a setting separator in URL queries, in
|
||||
addition to <code>"&"</code> (ampersand). Now, settings with non-percent-encoded
|
||||
semicolons are rejected and <code>net/http</code> servers will log a warning to
|
||||
<a href="/pkg/net/http#Server.ErrorLog"><code>Server.ErrorLog</code></a>
|
||||
when encountering one in a request URL.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For example, before Go 1.17 the <a href="/pkg/net/url#URL.Query"><code>Query</code></a>
|
||||
method of the URL <code>example?a=1;b=2&c=3</code> would have returned
|
||||
<code>map[a:[1] b:[2] c:[3]]</code>, while now it returns <code>map[c:[3]]</code>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
When encountering such a query string,
|
||||
<a href="/pkg/net/url#URL.Query"><code>URL.Query</code></a>
|
||||
and
|
||||
<a href="/pkg/net/http#Request.FormValue"><code>Request.FormValue</code></a>
|
||||
ignore any settings that contain a semicolon,
|
||||
<a href="/pkg/net/url#ParseQuery"><code>ParseQuery</code></a>
|
||||
returns the remaining settings and an error, and
|
||||
<a href="/pkg/net/http#Request.ParseForm"><code>Request.ParseForm</code></a>
|
||||
and
|
||||
<a href="/pkg/net/http#Request.ParseMultipartForm"><code>Request.ParseMultipartForm</code></a>
|
||||
return an error but still set <code>Request</code> fields based on the
|
||||
remaining settings.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<code>net/http</code> users can restore the original behavior by using the new
|
||||
<a href="/pkg/net/http#AllowQuerySemicolons"><code>AllowQuerySemicolons</code></a>
|
||||
handler wrapper. This will also suppress the <code>ErrorLog</code> warning.
|
||||
Note that accepting semicolons as query separators can lead to security issues
|
||||
if different systems interpret cache keys differently.
|
||||
See <a href="https://golang.org/issue/25192">issue 25192</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="ALPN">TLS strict ALPN</h3>
|
||||
<!-- CL 289209, CL 325432 -->
|
||||
|
||||
<p>
|
||||
When <a href="/pkg/crypto/tls#Config.NextProtos"><code>Config.NextProtos</code></a>
|
||||
is set, servers now enforce that there is an overlap between the configured
|
||||
protocols and the ALPN protocols advertised by the client, if any. If there is
|
||||
no mutually supported protocol, the connection is closed with the
|
||||
<code>no_application_protocol</code> alert, as required by RFC 7301. This
|
||||
helps mitigate <a href="https://alpaca-attack.com/">the ALPACA cross-protocol attack</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
As an exception, when the value <code>"h2"</code> is included in the server's
|
||||
<code>Config.NextProtos</code>, HTTP/1.1 clients will be allowed to connect as
|
||||
if they didn't support ALPN.
|
||||
See <a href="https://golang.org/issue/46310">issue 46310</a> for more information.
|
||||
</p>
|
||||
|
||||
<h3 id="minor_library_changes">Minor changes to the library</h3>
|
||||
|
||||
<p>
|
||||
|
|
@ -365,13 +572,126 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
</dd>
|
||||
</dl><!-- compress/lzw -->
|
||||
|
||||
<dl id="crypto/rsa"><dt><a href="/pkg/crypto/rsa/">crypto/rsa</a></dt>
|
||||
<dl id="crypto/ed25519"><dt><a href="/pkg/crypto/ed25519/">crypto/ed25519</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 302230 -->
|
||||
TODO: <a href="https://golang.org/cl/302230">https://golang.org/cl/302230</a>: fix salt length calculation with PSSSaltLengthAuto
|
||||
<p><!-- CL 276272 -->
|
||||
The <code>crypto/ed25519</code> package has been rewritten, and all
|
||||
operations are now approximately twice as fast on amd64 and arm64.
|
||||
The observable behavior has not otherwise changed.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/rsa -->
|
||||
</dl><!-- crypto/ed25519 -->
|
||||
|
||||
<dl id="crypto/elliptic"><dt><a href="/pkg/crypto/elliptic/">crypto/elliptic</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 233939 -->
|
||||
<a href="/pkg/crypto/elliptic#CurveParams"><code>CurveParams</code></a>
|
||||
methods now automatically invoke faster and safer dedicated
|
||||
implementations for known curves (P-224, P-256, and P-521) when
|
||||
available. Note that this is a best-effort approach and applications
|
||||
should avoid using the generic, not constant-time <code>CurveParams</code>
|
||||
methods and instead use dedicated
|
||||
<a href="/pkg/crypto/elliptic#Curve"><code>Curve</code></a> implementations
|
||||
such as <a href="/pkg/crypto/elliptic#P256"><code>P256</code></a>.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 315271, CL 315274 -->
|
||||
The <a href="/pkg/crypto/elliptic#P521"><code>P521</code></a> curve
|
||||
implementation has been rewritten using code generated by the
|
||||
<a href="https://github.com/mit-plv/fiat-crypto">fiat-crypto project</a>,
|
||||
which is based on a formally-verified model of the arithmetic
|
||||
operations. It is now constant-time and three times faster on amd64 and
|
||||
arm64. The observable behavior has not otherwise changed.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/elliptic -->
|
||||
|
||||
<dl id="crypto/rand"><dt><a href="/pkg/crypto/rand/">crypto/rand</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 302489, CL 299134, CL 269999 -->
|
||||
The <code>crypto/rand</code> package now uses the <code>getentropy</code>
|
||||
syscall on macOS and the <code>getrandom</code> syscall on Solaris,
|
||||
Illumos, and DragonFlyBSD.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/rand -->
|
||||
|
||||
<dl id="crypto/tls"><dt><a href="/pkg/crypto/tls/">crypto/tls</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 295370 -->
|
||||
The new <a href="/pkg/crypto/tls#Conn.HandshakeContext"><code>Conn.HandshakeContext</code></a>
|
||||
method allows the user to control cancellation of an in-progress TLS
|
||||
handshake. The provided context is accessible from various callbacks through the new
|
||||
<a href="/pkg/crypto/tls#ClientHelloInfo.Context"><code>ClientHelloInfo.Context</code></a> and
|
||||
<a href="/pkg/crypto/tls#CertificateRequestInfo.Context"><code>CertificateRequestInfo.Context</code></a>
|
||||
methods. Canceling the context after the handshake has finished has no effect.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 314609 -->
|
||||
Cipher suite ordering is now handled entirely by the
|
||||
<code>crypto/tls</code> package. Currently, cipher suites are sorted based
|
||||
on their security, performance, and hardware support taking into account
|
||||
both the local and peer's hardware. The order of the
|
||||
<a href="/pkg/crypto/tls#Config.CipherSuites"><code>Config.CipherSuites</code></a>
|
||||
field is now ignored, as well as the
|
||||
<a href="/pkg/crypto/tls#Config.PreferServerCipherSuites"><code>Config.PreferServerCipherSuites</code></a>
|
||||
field. Note that <code>Config.CipherSuites</code> still allows
|
||||
applications to choose what TLS 1.0–1.2 cipher suites to enable.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The 3DES cipher suites have been moved to
|
||||
<a href="/pkg/crypto/tls#InsecureCipherSuites"><code>InsecureCipherSuites</code></a>
|
||||
due to <a href="https://sweet32.info/">fundamental block size-related
|
||||
weakness</a>. They are still enabled by default but only as a last resort,
|
||||
thanks to the cipher suite ordering change above.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/45428 -->
|
||||
Beginning in the next release, Go 1.18, the
|
||||
<a href="/pkg/crypto/tls/#Config.MinVersion"><code>Config.MinVersion</code></a>
|
||||
for <code>crypto/tls</code> clients will default to TLS 1.2, disabling TLS 1.0
|
||||
and TLS 1.1 by default. Applications will be able to override the change by
|
||||
explicitly setting <code>Config.MinVersion</code>.
|
||||
This will not affect <code>crypto/tls</code> servers.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/tls -->
|
||||
|
||||
<dl id="crypto/x509"><dt><a href="/pkg/crypto/x509/">crypto/x509</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 224157 -->
|
||||
<a href="/pkg/crypto/x509/#CreateCertificate"><code>CreateCertificate</code></a>
|
||||
now returns an error if the provided private key doesn't match the
|
||||
parent's public key, if any. The resulting certificate would have failed
|
||||
to verify.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 315209 -->
|
||||
The temporary <code>GODEBUG=x509ignoreCN=0</code> flag has been removed.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 274234 -->
|
||||
<a href="/pkg/crypto/x509/#ParseCertificate"><code>ParseCertificate</code></a>
|
||||
has been rewritten, and now consumes ~70% fewer resources. The observable
|
||||
behavior has not otherwise changed, except for error messages.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 321190 -->
|
||||
On BSD systems, <code>/etc/ssl/certs</code> is now searched for trusted
|
||||
roots. This adds support for the new system trusted certificate store in
|
||||
FreeBSD 12.2+.
|
||||
</p>
|
||||
|
||||
<p><!-- golang.org/issue/41682 -->
|
||||
Beginning in the next release, Go 1.18, <code>crypto/x509</code> will
|
||||
reject certificates signed with the SHA-1 hash function. This doesn't
|
||||
apply to self-signed root certificates. Practical attacks against SHA-1
|
||||
<a href="https://shattered.io/">have been demonstrated in 2017</a> and publicly
|
||||
trusted Certificate Authorities have not issued SHA-1 certificates since 2015.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- crypto/x509 -->
|
||||
|
||||
<dl id="database/sql"><dt><a href="/pkg/database/sql/">database/sql</a></dt>
|
||||
<dd>
|
||||
|
|
@ -425,6 +745,22 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
</dd>
|
||||
</dl><!-- encoding/csv -->
|
||||
|
||||
<dl id="encoding/xml"><dt><a href="/pkg/encoding/xml/">encoding/xml</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 277893 -->
|
||||
When a comment appears within a
|
||||
<a href="/pkg/encoding/xml/#Directive"><code>Directive</code></a>, it is now replaced
|
||||
with a single space instead of being completely elided.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Invalid element or attribute names with leading, trailing, or multiple
|
||||
colons are now stored unmodified into the
|
||||
<a href="/pkg/encoding/xml/#Name"><code>Name.Local</code></a> field.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- encoding/xml -->
|
||||
|
||||
<dl id="flag"><dt><a href="/pkg/flag/">flag</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 271788 -->
|
||||
|
|
@ -444,6 +780,45 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
</dd>
|
||||
</dl><!-- go/build -->
|
||||
|
||||
<dl id="go/format"><dt><a href="/pkg/go/format/">go/format</a></dt>
|
||||
<dd>
|
||||
<p>
|
||||
The <a href="/pkg/go/format/#Source"><code>Source</code></a> and
|
||||
<a href="/pkg/go/format/#Node"><code>Node</code></a> functions now
|
||||
synchronize <code>//go:build</code> lines with <code>// +build</code>
|
||||
lines. If a file only has <code>// +build</code> lines, they will be
|
||||
moved to the appropriate location in the file, and matching
|
||||
<code>//go:build</code> lines will be added. Otherwise,
|
||||
<code>// +build</code> lines will be overwritten based on any existing
|
||||
<code>//go:build</code> lines. For more information, see
|
||||
<a href="https://golang.org/design/draft-gobuild">https://golang.org/design/draft-gobuild</a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- go/format -->
|
||||
|
||||
<dl id="go/parser"><dt><a href="/pkg/go/parser/">go/parser</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 306149 -->
|
||||
The new <a href="/pkg/go/parser/#SkipObjectResolution"><code>SkipObjectResolution</code></a>
|
||||
<code>Mode</code> value instructs the parser not to resolve identifiers to
|
||||
their declaration. This may improve parsing speed.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- go/parser -->
|
||||
|
||||
<dl id="image"><dt><a href="/pkg/image/">image</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 311129 -->
|
||||
The concrete image types (<code>RGBA</code>, <code>Gray16</code> and so on)
|
||||
now implement a new <a href="/pkg/image/#RGBA64Image"><code>RGBA64Image</code></a>
|
||||
interface. Those concrete types, other than the chroma-subsampling
|
||||
related <code>YCbCr</code> and <code>NYCbCrA</code>, also now implement
|
||||
<a href="/pkg/image/draw/#RGBA64Image"><code>draw.RGBA64Image</code></a>, a
|
||||
new interface in the <code>image/draw</code> package.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- image -->
|
||||
|
||||
<dl id="io/fs"><dt><a href="/pkg/io/fs/">io/fs</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 293649 -->
|
||||
|
|
@ -472,6 +847,20 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
</dd>
|
||||
</dl><!-- mime -->
|
||||
|
||||
<dl id="mime/multipart"><dt><a href="/pkg/mime/multipart/">mime/multipart</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 313809 -->
|
||||
<a href="/pkg/mime/multipart/#Part.FileName"><code>Part.FileName</code></a>
|
||||
now applies
|
||||
<a href="/pkg/path/filepath/#Base"><code>filepath.Base</code></a> to the
|
||||
return value. This mitigates potential path traversal vulnerabilities in
|
||||
applications that accept multipart messages, such as <code>net/http</code>
|
||||
servers that call
|
||||
<a href="/pkg/net/http/#Request.FormFile"><code>Request.FormFile</code></a>.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- mime/multipart -->
|
||||
|
||||
<dl id="net"><dt><a href="/pkg/net/">net</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 272668 -->
|
||||
|
|
@ -490,6 +879,16 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<a href="/pkg/net/#ParseError"><code>ParseError</code></a> error type now implement
|
||||
the <a href="/pkg/net/#Error"><code>net.Error</code></a> interface.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 325829 -->
|
||||
The <a href="/pkg/net/#ParseIP"><code>ParseIP</code></a> and <a href="/pkg/net/#ParseCIDR"><code>ParseCIDR</code></a>
|
||||
functions now reject IPv4 addresses which contain decimal components with leading zeros.
|
||||
|
||||
These components were always interpreted as decimal, but some operating systems treat them as octal.
|
||||
This mismatch could hypothetically lead to security issues if a Go application was used to validate IP addresses
|
||||
which were then used in their original form with non-Go applications which interpreted components as octal. Generally,
|
||||
it is advisable to always re-encode values after validation, which avoids this class of parser misalignment issues.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- net -->
|
||||
|
||||
|
|
@ -512,15 +911,38 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
The <a href="/pkg/net/http/#ReadRequest"><code>ReadRequest</code></a> function
|
||||
now returns an error when the request has multiple Host headers.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 313950 -->
|
||||
When producing a redirect to the cleaned version of a URL,
|
||||
<a href="/pkg/net/http/#ServeMux"><code>ServeMux</code></a> now always
|
||||
uses relative URLs in the <code>Location</code> header. Previously it
|
||||
would echo the full URL of the request, which could lead to unintended
|
||||
redirects if the client could be made to send an absolute request URL.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 308009, CL 313489 -->
|
||||
When interpreting certain HTTP headers handled by <code>net/http</code>,
|
||||
non-ASCII characters are now ignored or rejected.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 325697 -->
|
||||
If
|
||||
<a href="/pkg/net/http/#Request.ParseForm"><code>Request.ParseForm</code></a>
|
||||
returns an error when called by
|
||||
<a href="/pkg/net/http/#Request.ParseMultipartForm"><code>Request.ParseMultipartForm</code></a>,
|
||||
the latter now continues populating
|
||||
<a href="/pkg/net/http/#Request.MultipartForm"><code>Request.MultipartForm</code></a>
|
||||
before returning it.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- net/http -->
|
||||
|
||||
<dl id="net/http/httptest"><dt><a href="/pkg/net/http/httptest/">net/http/httptest</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 308950 -->
|
||||
<a href="/pkg/net/http/httptest/#ResponseRecorder.WriteHeader"><code>ResponseRecorder.WriteHeader></code></a>
|
||||
<a href="/pkg/net/http/httptest/#ResponseRecorder.WriteHeader"><code>ResponseRecorder.WriteHeader</code></a>
|
||||
now panics when the provided code is not a valid three-digit HTTP status code.
|
||||
This matches the behavior of <a href="/pkg/net/http/#ResponseWriter"><code>ResponseWriter></code></a>
|
||||
This matches the behavior of <a href="/pkg/net/http/#ResponseWriter"><code>ResponseWriter</code></a>
|
||||
implementations in the <a href="/pkg/net/http/"><code>net/http</code></a> package.
|
||||
</p>
|
||||
</dd>
|
||||
|
|
@ -539,7 +961,7 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<dd>
|
||||
<p><!-- CL 268020 -->
|
||||
The <a href="/pkg/os/#File.WriteString"><code>File.WriteString</code></a> method
|
||||
has been optimized to no longer make a copy of the input string.
|
||||
has been optimized to not make a copy of the input string.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- os -->
|
||||
|
|
@ -565,6 +987,14 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
The <a href="/pkg/reflect/#ArrayOf"><code>ArrayOf</code></a> function now panics when
|
||||
called with a negative length.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 301652 -->
|
||||
Checking the <a href="/pkg/reflect/#Type"><code>Type.ConvertibleTo</code></a> method
|
||||
is no longer sufficient to guarantee that a call to
|
||||
<a href="/pkg/reflect/#Value.Convert"><code>Value.Convert</code></a> will not panic.
|
||||
It may panic when converting `[]T` to `*[N]T` if the slice's length is less than N.
|
||||
See the language changes section above.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- reflect -->
|
||||
|
||||
|
|
@ -578,14 +1008,20 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
</dd>
|
||||
</dl><!-- runtime/metrics -->
|
||||
|
||||
<dl id="runtime/pprof"><dt><a href="/pkg/runtime/pprof">runtime/pprof</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 299991 -->
|
||||
Block profiles are no longer biased to favor infrequent long events over
|
||||
frequent short events.
|
||||
</p>
|
||||
</dd>
|
||||
</dl><!-- runtime/pprof -->
|
||||
|
||||
<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 170079 -->
|
||||
TODO: <a href="https://golang.org/cl/170079">https://golang.org/cl/170079</a>: implement Ryū-like algorithm for fixed precision ftoa
|
||||
</p>
|
||||
|
||||
<p><!-- CL 170080 -->
|
||||
TODO: <a href="https://golang.org/cl/170080">https://golang.org/cl/170080</a>: Implement Ryū algorithm for ftoa shortest mode
|
||||
<p><!-- CL 170079, CL 170080 -->
|
||||
The <code>strconv</code> package now uses Ulf Adams's Ryū algorithm for formatting floating-point numbers.
|
||||
This algorithm improves performance on most inputs and is more than 99% faster on worst-case inputs.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 314775 -->
|
||||
|
|
@ -659,9 +1095,8 @@ Do not send CLs removing the interior tags from such phrases.
|
|||
<dl id="testing"><dt><a href="/pkg/testing/">testing</a></dt>
|
||||
<dd>
|
||||
<p><!-- CL 310033 -->
|
||||
TODO: <a href="https://golang.org/cl/310033">https://golang.org/cl/310033</a>: add -shuffle=off|on|N to alter the execution order of tests and benchmarks
|
||||
Added a new <a href="/cmd/go/#hdr-Testing_flags">testing flag</a> <code>-shuffle</code> which controls the execution order of tests and benchmarks.
|
||||
</p>
|
||||
|
||||
<p><!-- CL 260577 -->
|
||||
The new
|
||||
<a href="/pkg/testing/#T.Setenv"><code>T.Setenv</code></a>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<!--{
|
||||
"Title": "The Go Programming Language Specification",
|
||||
"Subtitle": "Version of Apr 28, 2021",
|
||||
"Subtitle": "Version of Jun 22, 2021",
|
||||
"Path": "/ref/spec"
|
||||
}-->
|
||||
|
||||
|
|
@ -4670,7 +4670,7 @@ The following built-in functions are not permitted in statement context:
|
|||
|
||||
<pre>
|
||||
append cap complex imag len make new real
|
||||
unsafe.Alignof unsafe.Offsetof unsafe.Sizeof
|
||||
unsafe.Add unsafe.Alignof unsafe.Offsetof unsafe.Sizeof unsafe.Slice
|
||||
</pre>
|
||||
|
||||
<pre>
|
||||
|
|
@ -4909,7 +4909,7 @@ if x := f(); x < y {
|
|||
|
||||
<p>
|
||||
"Switch" statements provide multi-way execution.
|
||||
An expression or type specifier is compared to the "cases"
|
||||
An expression or type is compared to the "cases"
|
||||
inside the "switch" to determine which branch
|
||||
to execute.
|
||||
</p>
|
||||
|
|
@ -5020,7 +5020,7 @@ floating point, or string constants in case expressions.
|
|||
A type switch compares types rather than values. It is otherwise similar
|
||||
to an expression switch. It is marked by a special switch expression that
|
||||
has the form of a <a href="#Type_assertions">type assertion</a>
|
||||
using the reserved word <code>type</code> rather than an actual type:
|
||||
using the keyword <code>type</code> rather than an actual type:
|
||||
</p>
|
||||
|
||||
<pre>
|
||||
|
|
|
|||
|
|
@ -40,7 +40,8 @@ func check(t *testing.T, file string) {
|
|||
if len(frags) == 1 {
|
||||
continue
|
||||
}
|
||||
re, err := regexp.Compile(string(frags[1]))
|
||||
frag := fmt.Sprintf(":%d:.*%s", i+1, frags[1])
|
||||
re, err := regexp.Compile(frag)
|
||||
if err != nil {
|
||||
t.Errorf("Invalid regexp after `ERROR HERE: `: %#q", frags[1])
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -40,15 +40,15 @@ func main() {
|
|||
C.foop = x // ERROR HERE
|
||||
|
||||
// issue 13129: used to output error about C.unsignedshort with CC=clang
|
||||
var x C.ushort
|
||||
x = int(0) // ERROR HERE: C\.ushort
|
||||
var x1 C.ushort
|
||||
x1 = int(0) // ERROR HERE: C\.ushort
|
||||
|
||||
// issue 13423
|
||||
_ = C.fopen() // ERROR HERE
|
||||
|
||||
// issue 13467
|
||||
var x rune = '✈'
|
||||
var _ rune = C.transform(x) // ERROR HERE: C\.int
|
||||
var x2 rune = '✈'
|
||||
var _ rune = C.transform(x2) // ERROR HERE: C\.int
|
||||
|
||||
// issue 13635: used to output error about C.unsignedchar.
|
||||
// This test tests all such types.
|
||||
|
|
@ -91,10 +91,10 @@ func main() {
|
|||
|
||||
// issue 26745
|
||||
_ = func(i int) int {
|
||||
return C.i + 1 // ERROR HERE: :13
|
||||
return C.i + 1 // ERROR HERE: 14
|
||||
}
|
||||
_ = func(i int) {
|
||||
C.fi(i) // ERROR HERE: :6
|
||||
C.fi(i) // ERROR HERE: 7
|
||||
}
|
||||
|
||||
C.fi = C.fi // ERROR HERE
|
||||
|
|
|
|||
|
|
@ -292,11 +292,60 @@ func createHeaders() error {
|
|||
"-installsuffix", "testcshared",
|
||||
"-o", libgoname,
|
||||
filepath.Join(".", "libgo", "libgo.go")}
|
||||
if GOOS == "windows" && strings.HasSuffix(args[6], ".a") {
|
||||
args[6] = strings.TrimSuffix(args[6], ".a") + ".dll"
|
||||
}
|
||||
cmd = exec.Command(args[0], args[1:]...)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("command failed: %v\n%v\n%s\n", args, err, out)
|
||||
}
|
||||
if GOOS == "windows" {
|
||||
// We can't simply pass -Wl,--out-implib, because this relies on having imports from multiple packages,
|
||||
// which results in the linkers output implib getting overwritten at each step. So instead build the
|
||||
// import library the traditional way, using a def file.
|
||||
err = os.WriteFile("libgo.def",
|
||||
[]byte("LIBRARY libgo.dll\nEXPORTS\n\tDidInitRun\n\tDidMainRun\n\tDivu\n\tFromPkg\n\t_cgo_dummy_export\n"),
|
||||
0644)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to write def file: %v", err)
|
||||
}
|
||||
out, err = exec.Command(cc[0], append(cc[1:], "-print-prog-name=dlltool")...).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to find dlltool path: %v\n%s\n", err, out)
|
||||
}
|
||||
args := []string{strings.TrimSpace(string(out)), "-D", args[6], "-l", libgoname, "-d", "libgo.def"}
|
||||
|
||||
// This is an unfortunate workaround for https://github.com/mstorsjo/llvm-mingw/issues/205 in which
|
||||
// we basically reimplement the contents of the dlltool.sh wrapper: https://git.io/JZFlU
|
||||
dlltoolContents, err := os.ReadFile(args[0])
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read dlltool: %v\n", err)
|
||||
}
|
||||
if bytes.HasPrefix(dlltoolContents, []byte("#!/bin/sh")) && bytes.Contains(dlltoolContents, []byte("llvm-dlltool")) {
|
||||
base, name := filepath.Split(args[0])
|
||||
args[0] = filepath.Join(base, "llvm-dlltool")
|
||||
var machine string
|
||||
switch strings.SplitN(name, "-", 2)[0] {
|
||||
case "i686":
|
||||
machine = "i386"
|
||||
case "x86_64":
|
||||
machine = "i386:x86-64"
|
||||
case "armv7":
|
||||
machine = "arm"
|
||||
case "aarch64":
|
||||
machine = "arm64"
|
||||
}
|
||||
if len(machine) > 0 {
|
||||
args = append(args, "-m", machine)
|
||||
}
|
||||
}
|
||||
|
||||
out, err = exec.Command(args[0], args[1:]...).CombinedOutput()
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to run dlltool to create import library: %v\n%s\n", err, out)
|
||||
}
|
||||
}
|
||||
|
||||
if runtime.GOOS != GOOS && GOOS == "android" {
|
||||
args = append(adbCmd(), "push", libgoname, fmt.Sprintf("%s/%s", androiddir, libgoname))
|
||||
|
|
@ -400,7 +449,7 @@ func main() {
|
|||
defer f.Close()
|
||||
section := f.Section(".edata")
|
||||
if section == nil {
|
||||
t.Fatalf(".edata section is not present")
|
||||
t.Skip(".edata section is not present")
|
||||
}
|
||||
|
||||
// TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
|
||||
|
|
@ -749,7 +798,12 @@ func TestGo2C2Go(t *testing.T) {
|
|||
defer os.RemoveAll(tmpdir)
|
||||
|
||||
lib := filepath.Join(tmpdir, "libtestgo2c2go."+libSuffix)
|
||||
run(t, nil, "go", "build", "-buildmode=c-shared", "-o", lib, "./go2c2go/go")
|
||||
var env []string
|
||||
if GOOS == "windows" && strings.HasSuffix(lib, ".a") {
|
||||
env = append(env, "CGO_LDFLAGS=-Wl,--out-implib,"+lib, "CGO_LDFLAGS_ALLOW=.*")
|
||||
lib = strings.TrimSuffix(lib, ".a") + ".dll"
|
||||
}
|
||||
run(t, env, "go", "build", "-buildmode=c-shared", "-o", lib, "./go2c2go/go")
|
||||
|
||||
cgoCflags := os.Getenv("CGO_CFLAGS")
|
||||
if cgoCflags != "" {
|
||||
|
|
|
|||
|
|
@ -1003,7 +1003,8 @@ func (p *Parser) registerIndirect(a *obj.Addr, prefix rune) {
|
|||
p.errorf("unimplemented two-register form")
|
||||
}
|
||||
a.Index = r1
|
||||
if scale != 0 && p.arch.Family == sys.ARM64 {
|
||||
if scale != 0 && scale != 1 && p.arch.Family == sys.ARM64 {
|
||||
// Support (R1)(R2) (no scaling) and (R1)(R2*1).
|
||||
p.errorf("arm64 doesn't support scaled register format")
|
||||
} else {
|
||||
a.Scale = int16(scale)
|
||||
|
|
|
|||
|
|
@ -547,6 +547,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
// shifted or extended register offset.
|
||||
MOVD (R2)(R6.SXTW), R4 // 44c866f8
|
||||
MOVD (R3)(R6), R5 // 656866f8
|
||||
MOVD (R3)(R6*1), R5 // 656866f8
|
||||
MOVD (R2)(R6), R4 // 446866f8
|
||||
MOVWU (R19)(R20<<2), R20 // 747a74b8
|
||||
MOVD (R2)(R6<<3), R4 // 447866f8
|
||||
|
|
@ -579,6 +580,7 @@ TEXT foo(SB), DUPOK|NOSPLIT, $-8
|
|||
MOVB R4, (R2)(R6.SXTX) // 44e82638
|
||||
MOVB R8, (R3)(R9.UXTW) // 68482938
|
||||
MOVB R10, (R5)(R8) // aa682838
|
||||
MOVB R10, (R5)(R8*1) // aa682838
|
||||
MOVH R11, (R2)(R7.SXTW<<1) // 4bd82778
|
||||
MOVH R5, (R1)(R2<<1) // 25782278
|
||||
MOVH R7, (R2)(R5.SXTX<<1) // 47f82578
|
||||
|
|
|
|||
|
|
@ -449,7 +449,7 @@ func (config *ABIConfig) ABIAnalyze(t *types.Type, setNname bool) *ABIParamResul
|
|||
// parameterUpdateMu protects the Offset field of function/method parameters (a subset of structure Fields)
|
||||
var parameterUpdateMu sync.Mutex
|
||||
|
||||
// FieldOffsetOf returns a concurency-safe version of f.Offset
|
||||
// FieldOffsetOf returns a concurrency-safe version of f.Offset
|
||||
func FieldOffsetOf(f *types.Field) int64 {
|
||||
parameterUpdateMu.Lock()
|
||||
defer parameterUpdateMu.Unlock()
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ func dumpdata() {
|
|||
if reflectdata.ZeroSize > 0 {
|
||||
zero := base.PkgLinksym("go.map", "zero", obj.ABI0)
|
||||
objw.Global(zero, int32(reflectdata.ZeroSize), obj.DUPOK|obj.RODATA)
|
||||
zero.Set(obj.AttrContentAddressable, true)
|
||||
}
|
||||
|
||||
staticdata.WriteFuncSyms()
|
||||
|
|
|
|||
|
|
@ -882,9 +882,6 @@ func (p *noder) typeExpr(typ syntax.Expr) ir.Ntype {
|
|||
if n == nil {
|
||||
return nil
|
||||
}
|
||||
if _, ok := n.(ir.Ntype); !ok {
|
||||
ir.Dump("NOT NTYPE", n)
|
||||
}
|
||||
return n.(ir.Ntype)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1475,8 +1475,8 @@ func (a typesByString) Less(i, j int) bool {
|
|||
// will be equal for the above checks, but different in DWARF output.
|
||||
// Sort by source position to ensure deterministic order.
|
||||
// See issues 27013 and 30202.
|
||||
if a[i].t.Kind() == types.TINTER && a[i].t.Methods().Len() > 0 {
|
||||
return a[i].t.Methods().Index(0).Pos.Before(a[j].t.Methods().Index(0).Pos)
|
||||
if a[i].t.Kind() == types.TINTER && a[i].t.AllMethods().Len() > 0 {
|
||||
return a[i].t.AllMethods().Index(0).Pos.Before(a[j].t.AllMethods().Index(0).Pos)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3174,7 +3174,7 @@ func (s *state) expr(n ir.Node) *ssa.Value {
|
|||
arrlen := s.constInt(types.Types[types.TINT], n.Type().Elem().NumElem())
|
||||
cap := s.newValue1(ssa.OpSliceLen, types.Types[types.TINT], v)
|
||||
s.boundsCheck(arrlen, cap, ssa.BoundsConvert, false)
|
||||
return s.newValue1(ssa.OpSlicePtrUnchecked, types.Types[types.TINT], v)
|
||||
return s.newValue1(ssa.OpSlicePtrUnchecked, n.Type(), v)
|
||||
|
||||
case ir.OCALLFUNC:
|
||||
n := n.(*ir.CallExpr)
|
||||
|
|
|
|||
|
|
@ -633,6 +633,17 @@ func defaultlit2(l ir.Node, r ir.Node, force bool) (ir.Node, ir.Node) {
|
|||
if l.Type() == nil || r.Type() == nil {
|
||||
return l, r
|
||||
}
|
||||
|
||||
if !l.Type().IsInterface() && !r.Type().IsInterface() {
|
||||
// Can't mix bool with non-bool, string with non-string.
|
||||
if l.Type().IsBoolean() != r.Type().IsBoolean() {
|
||||
return l, r
|
||||
}
|
||||
if l.Type().IsString() != r.Type().IsString() {
|
||||
return l, r
|
||||
}
|
||||
}
|
||||
|
||||
if !l.Type().IsUntyped() {
|
||||
r = convlit(r, l.Type())
|
||||
return l, r
|
||||
|
|
@ -647,17 +658,10 @@ func defaultlit2(l ir.Node, r ir.Node, force bool) (ir.Node, ir.Node) {
|
|||
return l, r
|
||||
}
|
||||
|
||||
// Can't mix bool with non-bool, string with non-string, or nil with anything (untyped).
|
||||
if l.Type().IsBoolean() != r.Type().IsBoolean() {
|
||||
return l, r
|
||||
}
|
||||
if l.Type().IsString() != r.Type().IsString() {
|
||||
return l, r
|
||||
}
|
||||
// Can't mix nil with anything untyped.
|
||||
if ir.IsNil(l) || ir.IsNil(r) {
|
||||
return l, r
|
||||
}
|
||||
|
||||
t := defaultType(mixUntyped(l.Type(), r.Type()))
|
||||
l = convlit(l, t)
|
||||
r = convlit(r, t)
|
||||
|
|
|
|||
|
|
@ -981,6 +981,12 @@ func tcRecover(n *ir.CallExpr) ir.Node {
|
|||
|
||||
// tcUnsafeAdd typechecks an OUNSAFEADD node.
|
||||
func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
|
||||
if !types.AllowsGoVersion(curpkg(), 1, 17) {
|
||||
base.ErrorfVers("go1.17", "unsafe.Add")
|
||||
n.SetType(nil)
|
||||
return n
|
||||
}
|
||||
|
||||
n.X = AssignConv(Expr(n.X), types.Types[types.TUNSAFEPTR], "argument to unsafe.Add")
|
||||
n.Y = DefaultLit(Expr(n.Y), types.Types[types.TINT])
|
||||
if n.X.Type() == nil || n.Y.Type() == nil {
|
||||
|
|
@ -997,6 +1003,12 @@ func tcUnsafeAdd(n *ir.BinaryExpr) *ir.BinaryExpr {
|
|||
|
||||
// tcUnsafeSlice typechecks an OUNSAFESLICE node.
|
||||
func tcUnsafeSlice(n *ir.BinaryExpr) *ir.BinaryExpr {
|
||||
if !types.AllowsGoVersion(curpkg(), 1, 17) {
|
||||
base.ErrorfVers("go1.17", "unsafe.Slice")
|
||||
n.SetType(nil)
|
||||
return n
|
||||
}
|
||||
|
||||
n.X = Expr(n.X)
|
||||
n.Y = Expr(n.Y)
|
||||
if n.X.Type() == nil || n.Y.Type() == nil {
|
||||
|
|
|
|||
|
|
@ -204,8 +204,20 @@ assignOK:
|
|||
r.Use = ir.CallUseList
|
||||
rtyp := r.Type()
|
||||
|
||||
mismatched := false
|
||||
failed := false
|
||||
for i := range lhs {
|
||||
assignType(i, rtyp.Field(i).Type)
|
||||
result := rtyp.Field(i).Type
|
||||
assignType(i, result)
|
||||
|
||||
if lhs[i].Type() == nil || result == nil {
|
||||
failed = true
|
||||
} else if lhs[i] != ir.BlankNode && !types.Identical(lhs[i].Type(), result) {
|
||||
mismatched = true
|
||||
}
|
||||
}
|
||||
if mismatched && !failed {
|
||||
rewriteMultiValueCall(stmt, r)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -945,16 +945,18 @@ func typecheckargs(n ir.InitNode) {
|
|||
return
|
||||
}
|
||||
|
||||
// Rewrite f(g()) into t1, t2, ... = g(); f(t1, t2, ...).
|
||||
|
||||
// Save n as n.Orig for fmt.go.
|
||||
if ir.Orig(n) == n {
|
||||
n.(ir.OrigNode).SetOrig(ir.SepCopy(n))
|
||||
}
|
||||
|
||||
as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, nil)
|
||||
as.Rhs.Append(list...)
|
||||
// Rewrite f(g()) into t1, t2, ... = g(); f(t1, t2, ...).
|
||||
rewriteMultiValueCall(n, list[0])
|
||||
}
|
||||
|
||||
// rewriteMultiValueCall rewrites multi-valued f() to use temporaries,
|
||||
// so the backend wouldn't need to worry about tuple-valued expressions.
|
||||
func rewriteMultiValueCall(n ir.InitNode, call ir.Node) {
|
||||
// If we're outside of function context, then this call will
|
||||
// be executed during the generated init function. However,
|
||||
// init.go hasn't yet created it. Instead, associate the
|
||||
|
|
@ -964,25 +966,40 @@ func typecheckargs(n ir.InitNode) {
|
|||
if static {
|
||||
ir.CurFunc = InitTodoFunc
|
||||
}
|
||||
list = nil
|
||||
for _, f := range t.FieldSlice() {
|
||||
t := Temp(f.Type)
|
||||
as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, t))
|
||||
as.Lhs.Append(t)
|
||||
list = append(list, t)
|
||||
|
||||
as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, []ir.Node{call})
|
||||
results := call.Type().FieldSlice()
|
||||
list := make([]ir.Node, len(results))
|
||||
for i, result := range results {
|
||||
tmp := Temp(result.Type)
|
||||
as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, tmp))
|
||||
as.Lhs.Append(tmp)
|
||||
list[i] = tmp
|
||||
}
|
||||
if static {
|
||||
ir.CurFunc = nil
|
||||
}
|
||||
|
||||
n.PtrInit().Append(Stmt(as))
|
||||
|
||||
switch n := n.(type) {
|
||||
default:
|
||||
base.Fatalf("rewriteMultiValueCall %+v", n.Op())
|
||||
case *ir.CallExpr:
|
||||
n.Args = list
|
||||
case *ir.ReturnStmt:
|
||||
n.Results = list
|
||||
case *ir.AssignListStmt:
|
||||
if n.Op() != ir.OAS2FUNC {
|
||||
base.Fatalf("rewriteMultiValueCall: invalid op %v", n.Op())
|
||||
}
|
||||
as.SetOp(ir.OAS2FUNC)
|
||||
n.SetOp(ir.OAS2)
|
||||
n.Rhs = make([]ir.Node, len(list))
|
||||
for i, tmp := range list {
|
||||
n.Rhs[i] = AssignConv(tmp, n.Lhs[i].Type(), "assignment")
|
||||
}
|
||||
}
|
||||
|
||||
n.PtrInit().Append(Stmt(as))
|
||||
}
|
||||
|
||||
func checksliceindex(l ir.Node, r ir.Node, tp *types.Type) bool {
|
||||
|
|
|
|||
|
|
@ -579,6 +579,11 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
|
||||
case _Add:
|
||||
// unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
|
||||
if !check.allowVersion(check.pkg, 1, 17) {
|
||||
check.error(call.Fun, "unsafe.Add requires go1.17 or later")
|
||||
return
|
||||
}
|
||||
|
||||
check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
|
||||
if x.mode == invalid {
|
||||
return
|
||||
|
|
@ -675,6 +680,11 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
|
||||
case _Slice:
|
||||
// unsafe.Slice(ptr *T, len IntegerType) []T
|
||||
if !check.allowVersion(check.pkg, 1, 17) {
|
||||
check.error(call.Fun, "unsafe.Slice requires go1.17 or later")
|
||||
return
|
||||
}
|
||||
|
||||
typ := asPointer(x.typ)
|
||||
if typ == nil {
|
||||
check.errorf(x, invalidArg+"%s is not a pointer", x)
|
||||
|
|
|
|||
|
|
@ -313,7 +313,7 @@ func mayCall(n ir.Node) bool {
|
|||
return true
|
||||
|
||||
case ir.OINDEX, ir.OSLICE, ir.OSLICEARR, ir.OSLICE3, ir.OSLICE3ARR, ir.OSLICESTR,
|
||||
ir.ODEREF, ir.ODOTPTR, ir.ODOTTYPE, ir.ODIV, ir.OMOD:
|
||||
ir.ODEREF, ir.ODOTPTR, ir.ODOTTYPE, ir.ODIV, ir.OMOD, ir.OSLICE2ARRPTR:
|
||||
// These ops might panic, make sure they are done
|
||||
// before we start marshaling args for a call. See issue 16760.
|
||||
return true
|
||||
|
|
|
|||
|
|
@ -737,9 +737,9 @@ func (t *tester) registerTests() {
|
|||
fn: func(dt *distTest) error {
|
||||
cmd := t.addCmd(dt, "misc/swig/callback", t.goTest())
|
||||
cmd.Env = append(os.Environ(),
|
||||
"CGO_CFLAGS=-flto",
|
||||
"CGO_CXXFLAGS=-flto",
|
||||
"CGO_LDFLAGS=-flto",
|
||||
"CGO_CFLAGS=-flto -Wno-lto-type-mismatch",
|
||||
"CGO_CXXFLAGS=-flto -Wno-lto-type-mismatch",
|
||||
"CGO_LDFLAGS=-flto -Wno-lto-type-mismatch",
|
||||
)
|
||||
return nil
|
||||
},
|
||||
|
|
@ -1057,7 +1057,7 @@ func (t *tester) supportedBuildmode(mode string) bool {
|
|||
"darwin-amd64", "darwin-arm64",
|
||||
"freebsd-amd64",
|
||||
"android-arm", "android-arm64", "android-386",
|
||||
"windows-amd64", "windows-386":
|
||||
"windows-amd64", "windows-386", "windows-arm64":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ require (
|
|||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639 // indirect
|
||||
golang.org/x/arch v0.0.0-20210502124803-cbf565b21d1e
|
||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e // indirect
|
||||
golang.org/x/mod v0.4.3-0.20210512182355-6088ed88cecd
|
||||
golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a
|
||||
golang.org/x/sys v0.0.0-20210511113859-b0526f3d8744 // indirect
|
||||
golang.org/x/term v0.0.0-20210503060354-a79de5458b56
|
||||
golang.org/x/tools v0.1.2-0.20210519160823-49064d2332f9
|
||||
|
|
|
|||
|
|
@ -13,8 +13,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
|
|||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e h1:8foAy0aoO5GkqCvAEJ4VC4P3zksTg4X4aJCDpZzmgQI=
|
||||
golang.org/x/crypto v0.0.0-20210503195802-e9a32991a82e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.3-0.20210512182355-6088ed88cecd h1:CuRnpyMrCCBulv0d/y0CswR4K0vGydgE3DZ2wYPIOo8=
|
||||
golang.org/x/mod v0.4.3-0.20210512182355-6088ed88cecd/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a h1:e8qnjKz4EE6OjRki9wTadWSIogINvq10sMcuBRORxMY=
|
||||
golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
|
|
|
|||
|
|
@ -1189,13 +1189,17 @@
|
|||
//
|
||||
// Usage:
|
||||
//
|
||||
// go mod graph
|
||||
// go mod graph [-go=version]
|
||||
//
|
||||
// Graph prints the module requirement graph (with replacements applied)
|
||||
// in text form. Each line in the output has two space-separated fields: a module
|
||||
// and one of its requirements. Each module is identified as a string of the form
|
||||
// path@version, except for the main module, which has no @version suffix.
|
||||
//
|
||||
// The -go flag causes graph to report the module graph as loaded by by the
|
||||
// given Go version, instead of the version indicated by the 'go' directive
|
||||
// in the go.mod file.
|
||||
//
|
||||
// See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'.
|
||||
//
|
||||
//
|
||||
|
|
@ -1573,7 +1577,7 @@
|
|||
//
|
||||
// A build constraint, also known as a build tag, is a line comment that begins
|
||||
//
|
||||
// // +build
|
||||
// //go:build
|
||||
//
|
||||
// that lists the conditions under which a file should be included in the package.
|
||||
// Constraints may appear in any kind of source file (not just Go), but
|
||||
|
|
@ -1581,30 +1585,20 @@
|
|||
// only by blank lines and other line comments. These rules mean that in Go
|
||||
// files a build constraint must appear before the package clause.
|
||||
//
|
||||
// To distinguish build constraints from package documentation, a series of
|
||||
// build constraints must be followed by a blank line.
|
||||
// To distinguish build constraints from package documentation,
|
||||
// a build constraint should be followed by a blank line.
|
||||
//
|
||||
// A build constraint is evaluated as the OR of space-separated options.
|
||||
// Each option evaluates as the AND of its comma-separated terms.
|
||||
// Each term consists of letters, digits, underscores, and dots.
|
||||
// A term may be negated with a preceding !.
|
||||
// For example, the build constraint:
|
||||
// A build constraint is evaluated as an expression containing options
|
||||
// combined by ||, &&, and ! operators and parentheses. Operators have
|
||||
// the same meaning as in Go.
|
||||
//
|
||||
// // +build linux,386 darwin,!cgo
|
||||
// For example, the following build constraint constrains a file to
|
||||
// build when the "linux" and "386" constraints are satisfied, or when
|
||||
// "darwin" is satisfied and "cgo" is not:
|
||||
//
|
||||
// corresponds to the boolean formula:
|
||||
// //go:build (linux && 386) || (darwin && !cgo)
|
||||
//
|
||||
// (linux AND 386) OR (darwin AND (NOT cgo))
|
||||
//
|
||||
// A file may have multiple build constraints. The overall constraint is the AND
|
||||
// of the individual constraints. That is, the build constraints:
|
||||
//
|
||||
// // +build linux darwin
|
||||
// // +build amd64
|
||||
//
|
||||
// corresponds to the boolean formula:
|
||||
//
|
||||
// (linux OR darwin) AND amd64
|
||||
// It is an error for a file to have more than one //go:build line.
|
||||
//
|
||||
// During a particular build, the following words are satisfied:
|
||||
//
|
||||
|
|
@ -1642,24 +1636,28 @@
|
|||
//
|
||||
// To keep a file from being considered for the build:
|
||||
//
|
||||
// // +build ignore
|
||||
// //go:build ignore
|
||||
//
|
||||
// (any other unsatisfied word will work as well, but "ignore" is conventional.)
|
||||
//
|
||||
// To build a file only when using cgo, and only on Linux and OS X:
|
||||
//
|
||||
// // +build linux,cgo darwin,cgo
|
||||
// //go:build cgo && (linux || darwin)
|
||||
//
|
||||
// Such a file is usually paired with another file implementing the
|
||||
// default functionality for other systems, which in this case would
|
||||
// carry the constraint:
|
||||
//
|
||||
// // +build !linux,!darwin !cgo
|
||||
// //go:build !(cgo && (linux || darwin))
|
||||
//
|
||||
// Naming a file dns_windows.go will cause it to be included only when
|
||||
// building the package for Windows; similarly, math_386.s will be included
|
||||
// only when building the package for 32-bit x86.
|
||||
//
|
||||
// Go versions 1.16 and earlier used a different syntax for build constraints,
|
||||
// with a "// +build" prefix. The gofmt command will add an equivalent //go:build
|
||||
// constraint when encountering the older syntax.
|
||||
//
|
||||
//
|
||||
// Build modes
|
||||
//
|
||||
|
|
@ -1898,6 +1896,9 @@
|
|||
// GOMIPS64
|
||||
// For GOARCH=mips64{,le}, whether to use floating point instructions.
|
||||
// Valid values are hardfloat (default), softfloat.
|
||||
// GOPPC64
|
||||
// For GOARCH=ppc64{,le}, the target ISA (Instruction Set Architecture).
|
||||
// Valid values are power8 (default), power9.
|
||||
// GOWASM
|
||||
// For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
|
||||
// Valid values are satconv, signext.
|
||||
|
|
|
|||
|
|
@ -72,7 +72,6 @@ func tooSlow(t *testing.T) {
|
|||
// (temp) directory.
|
||||
var testGOROOT string
|
||||
|
||||
var testCC string
|
||||
var testGOCACHE string
|
||||
|
||||
var testGo string
|
||||
|
|
@ -179,13 +178,6 @@ func TestMain(m *testing.M) {
|
|||
os.Exit(2)
|
||||
}
|
||||
|
||||
out, err = exec.Command(gotool, "env", "CC").CombinedOutput()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "could not find testing CC: %v\n%s", err, out)
|
||||
os.Exit(2)
|
||||
}
|
||||
testCC = strings.TrimSpace(string(out))
|
||||
|
||||
cmd := exec.Command(testGo, "env", "CGO_ENABLED")
|
||||
cmd.Stderr = new(strings.Builder)
|
||||
if out, err := cmd.Output(); err != nil {
|
||||
|
|
@ -2185,7 +2177,7 @@ func testBuildmodePIE(t *testing.T, useCgo, setBuildmodeToPIE bool) {
|
|||
// See https://sourceware.org/bugzilla/show_bug.cgi?id=19011
|
||||
section := f.Section(".edata")
|
||||
if section == nil {
|
||||
t.Fatalf(".edata section is not present")
|
||||
t.Skip(".edata section is not present")
|
||||
}
|
||||
// TODO: deduplicate this struct from cmd/link/internal/ld/pe.go
|
||||
type IMAGE_EXPORT_DIRECTORY struct {
|
||||
|
|
|
|||
|
|
@ -81,6 +81,14 @@ func defaultContext() build.Context {
|
|||
ctxt.GOOS = envOr("GOOS", ctxt.GOOS)
|
||||
ctxt.GOARCH = envOr("GOARCH", ctxt.GOARCH)
|
||||
|
||||
// The experiments flags are based on GOARCH, so they may
|
||||
// need to change. TODO: This should be cleaned up.
|
||||
buildcfg.UpdateExperiments(ctxt.GOOS, ctxt.GOARCH, envOr("GOEXPERIMENT", buildcfg.DefaultGOEXPERIMENT))
|
||||
ctxt.ToolTags = nil
|
||||
for _, exp := range buildcfg.EnabledExperiments() {
|
||||
ctxt.ToolTags = append(ctxt.ToolTags, "goexperiment."+exp)
|
||||
}
|
||||
|
||||
// The go/build rule for whether cgo is enabled is:
|
||||
// 1. If $CGO_ENABLED is set, respect it.
|
||||
// 2. Otherwise, if this is a cross-compile, disable cgo.
|
||||
|
|
|
|||
|
|
@ -598,6 +598,9 @@ Architecture-specific environment variables:
|
|||
GOMIPS64
|
||||
For GOARCH=mips64{,le}, whether to use floating point instructions.
|
||||
Valid values are hardfloat (default), softfloat.
|
||||
GOPPC64
|
||||
For GOARCH=ppc64{,le}, the target ISA (Instruction Set Architecture).
|
||||
Valid values are power8 (default), power9.
|
||||
GOWASM
|
||||
For GOARCH=wasm, comma-separated list of experimental WebAssembly features to use.
|
||||
Valid values are satconv, signext.
|
||||
|
|
@ -784,7 +787,7 @@ var HelpBuildConstraint = &base.Command{
|
|||
Long: `
|
||||
A build constraint, also known as a build tag, is a line comment that begins
|
||||
|
||||
// +build
|
||||
//go:build
|
||||
|
||||
that lists the conditions under which a file should be included in the package.
|
||||
Constraints may appear in any kind of source file (not just Go), but
|
||||
|
|
@ -792,30 +795,20 @@ they must appear near the top of the file, preceded
|
|||
only by blank lines and other line comments. These rules mean that in Go
|
||||
files a build constraint must appear before the package clause.
|
||||
|
||||
To distinguish build constraints from package documentation, a series of
|
||||
build constraints must be followed by a blank line.
|
||||
To distinguish build constraints from package documentation,
|
||||
a build constraint should be followed by a blank line.
|
||||
|
||||
A build constraint is evaluated as the OR of space-separated options.
|
||||
Each option evaluates as the AND of its comma-separated terms.
|
||||
Each term consists of letters, digits, underscores, and dots.
|
||||
A term may be negated with a preceding !.
|
||||
For example, the build constraint:
|
||||
A build constraint is evaluated as an expression containing options
|
||||
combined by ||, &&, and ! operators and parentheses. Operators have
|
||||
the same meaning as in Go.
|
||||
|
||||
// +build linux,386 darwin,!cgo
|
||||
For example, the following build constraint constrains a file to
|
||||
build when the "linux" and "386" constraints are satisfied, or when
|
||||
"darwin" is satisfied and "cgo" is not:
|
||||
|
||||
corresponds to the boolean formula:
|
||||
//go:build (linux && 386) || (darwin && !cgo)
|
||||
|
||||
(linux AND 386) OR (darwin AND (NOT cgo))
|
||||
|
||||
A file may have multiple build constraints. The overall constraint is the AND
|
||||
of the individual constraints. That is, the build constraints:
|
||||
|
||||
// +build linux darwin
|
||||
// +build amd64
|
||||
|
||||
corresponds to the boolean formula:
|
||||
|
||||
(linux OR darwin) AND amd64
|
||||
It is an error for a file to have more than one //go:build line.
|
||||
|
||||
During a particular build, the following words are satisfied:
|
||||
|
||||
|
|
@ -853,22 +846,26 @@ in addition to ios tags and files.
|
|||
|
||||
To keep a file from being considered for the build:
|
||||
|
||||
// +build ignore
|
||||
//go:build ignore
|
||||
|
||||
(any other unsatisfied word will work as well, but "ignore" is conventional.)
|
||||
|
||||
To build a file only when using cgo, and only on Linux and OS X:
|
||||
|
||||
// +build linux,cgo darwin,cgo
|
||||
//go:build cgo && (linux || darwin)
|
||||
|
||||
Such a file is usually paired with another file implementing the
|
||||
default functionality for other systems, which in this case would
|
||||
carry the constraint:
|
||||
|
||||
// +build !linux,!darwin !cgo
|
||||
//go:build !(cgo && (linux || darwin))
|
||||
|
||||
Naming a file dns_windows.go will cause it to be included only when
|
||||
building the package for Windows; similarly, math_386.s will be included
|
||||
only when building the package for 32-bit x86.
|
||||
|
||||
Go versions 1.16 and earlier used a different syntax for build constraints,
|
||||
with a "// +build" prefix. The gofmt command will add an equivalent //go:build
|
||||
constraint when encountering the older syntax.
|
||||
`,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ package imports
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"io"
|
||||
"unicode/utf8"
|
||||
|
|
@ -22,6 +23,19 @@ type importReader struct {
|
|||
nerr int
|
||||
}
|
||||
|
||||
var bom = []byte{0xef, 0xbb, 0xbf}
|
||||
|
||||
func newImportReader(b *bufio.Reader) *importReader {
|
||||
// Remove leading UTF-8 BOM.
|
||||
// Per https://golang.org/ref/spec#Source_code_representation:
|
||||
// a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF)
|
||||
// if it is the first Unicode code point in the source text.
|
||||
if leadingBytes, err := b.Peek(3); err == nil && bytes.Equal(leadingBytes, bom) {
|
||||
b.Discard(3)
|
||||
}
|
||||
return &importReader{b: b}
|
||||
}
|
||||
|
||||
func isIdent(c byte) bool {
|
||||
return 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || '0' <= c && c <= '9' || c == '_' || c >= utf8.RuneSelf
|
||||
}
|
||||
|
|
@ -201,7 +215,7 @@ func (r *importReader) readImport(imports *[]string) {
|
|||
// ReadComments is like io.ReadAll, except that it only reads the leading
|
||||
// block of comments in the file.
|
||||
func ReadComments(f io.Reader) ([]byte, error) {
|
||||
r := &importReader{b: bufio.NewReader(f)}
|
||||
r := newImportReader(bufio.NewReader(f))
|
||||
r.peekByte(true)
|
||||
if r.err == nil && !r.eof {
|
||||
// Didn't reach EOF, so must have found a non-space byte. Remove it.
|
||||
|
|
@ -213,7 +227,7 @@ func ReadComments(f io.Reader) ([]byte, error) {
|
|||
// ReadImports is like io.ReadAll, except that it expects a Go file as input
|
||||
// and stops reading the input once the imports have completed.
|
||||
func ReadImports(f io.Reader, reportSyntaxError bool, imports *[]string) ([]byte, error) {
|
||||
r := &importReader{b: bufio.NewReader(f)}
|
||||
r := newImportReader(bufio.NewReader(f))
|
||||
|
||||
r.readKeyword("package")
|
||||
r.readIdent()
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@ var readImportsTests = []readTest{
|
|||
`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"\ufeff𝔻" + `package p; import "x";ℙvar x = 1`,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
var readCommentsTests = []readTest{
|
||||
|
|
@ -81,6 +85,10 @@ var readCommentsTests = []readTest{
|
|||
`ℙpackage p; import . "x"`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"\ufeff𝔻" + `ℙpackage p; import . "x"`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`// foo
|
||||
|
||||
|
|
@ -90,6 +98,19 @@ var readCommentsTests = []readTest{
|
|||
|
||||
/*/ zot */
|
||||
|
||||
// asdf
|
||||
ℙHello, world`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"\ufeff𝔻" + `// foo
|
||||
|
||||
/* bar */
|
||||
|
||||
/* quux */ // baz
|
||||
|
||||
/*/ zot */
|
||||
|
||||
// asdf
|
||||
ℙHello, world`,
|
||||
"",
|
||||
|
|
@ -107,6 +128,11 @@ func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, erro
|
|||
in = tt.in[:j] + tt.in[j+len("ℙ"):]
|
||||
testOut = tt.in[:j]
|
||||
}
|
||||
d := strings.Index(tt.in, "𝔻")
|
||||
if d >= 0 {
|
||||
in = in[:d] + in[d+len("𝔻"):]
|
||||
testOut = testOut[d+len("𝔻"):]
|
||||
}
|
||||
r := strings.NewReader(in)
|
||||
buf, err := read(r)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -724,8 +724,18 @@ func runList(ctx context.Context, cmd *base.Command, args []string) {
|
|||
|
||||
// Record non-identity import mappings in p.ImportMap.
|
||||
for _, p := range pkgs {
|
||||
for i, srcPath := range p.Internal.RawImports {
|
||||
path := p.Imports[i]
|
||||
nRaw := len(p.Internal.RawImports)
|
||||
for i, path := range p.Imports {
|
||||
var srcPath string
|
||||
if i < nRaw {
|
||||
srcPath = p.Internal.RawImports[i]
|
||||
} else {
|
||||
// This path is not within the raw imports, so it must be an import
|
||||
// found only within CompiledGoFiles. Those paths are found in
|
||||
// CompiledImports.
|
||||
srcPath = p.Internal.CompiledImports[i-nRaw]
|
||||
}
|
||||
|
||||
if path != srcPath {
|
||||
if p.ImportMap == nil {
|
||||
p.ImportMap = make(map[string]string)
|
||||
|
|
|
|||
|
|
@ -194,8 +194,8 @@ type PackageInternal struct {
|
|||
// Unexported fields are not part of the public API.
|
||||
Build *build.Package
|
||||
Imports []*Package // this package's direct imports
|
||||
CompiledImports []string // additional Imports necessary when using CompiledGoFiles (all from standard library)
|
||||
RawImports []string // this package's original imports as they appear in the text of the program
|
||||
CompiledImports []string // additional Imports necessary when using CompiledGoFiles (all from standard library); 1:1 with the end of PackagePublic.Imports
|
||||
RawImports []string // this package's original imports as they appear in the text of the program; 1:1 with the end of PackagePublic.Imports
|
||||
ForceLibrary bool // this package is a library (even if named "main")
|
||||
CmdlineFiles bool // package built from files listed on command line
|
||||
CmdlinePkg bool // package listed on command line
|
||||
|
|
|
|||
|
|
@ -116,7 +116,7 @@ func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, co
|
|||
// Can't change that code, because that code is only for loading the
|
||||
// non-test copy of a package.
|
||||
ptestErr = &PackageError{
|
||||
ImportStack: testImportStack(stk[0], p1, p.ImportPath),
|
||||
ImportStack: importCycleStack(p1, p.ImportPath),
|
||||
Err: errors.New("import cycle not allowed in test"),
|
||||
IsImportCycle: true,
|
||||
}
|
||||
|
|
@ -375,22 +375,44 @@ func TestPackagesAndErrors(ctx context.Context, opts PackageOpts, p *Package, co
|
|||
return pmain, ptest, pxtest
|
||||
}
|
||||
|
||||
func testImportStack(top string, p *Package, target string) []string {
|
||||
stk := []string{top, p.ImportPath}
|
||||
Search:
|
||||
for p.ImportPath != target {
|
||||
for _, p1 := range p.Internal.Imports {
|
||||
if p1.ImportPath == target || str.Contains(p1.Deps, target) {
|
||||
stk = append(stk, p1.ImportPath)
|
||||
p = p1
|
||||
continue Search
|
||||
// importCycleStack returns an import stack from p to the package whose import
|
||||
// path is target.
|
||||
func importCycleStack(p *Package, target string) []string {
|
||||
// importerOf maps each import path to its importer nearest to p.
|
||||
importerOf := map[string]string{p.ImportPath: ""}
|
||||
|
||||
// q is a breadth-first queue of packages to search for target.
|
||||
// Every package added to q has a corresponding entry in pathTo.
|
||||
//
|
||||
// We search breadth-first for two reasons:
|
||||
//
|
||||
// 1. We want to report the shortest cycle.
|
||||
//
|
||||
// 2. If p contains multiple cycles, the first cycle we encounter might not
|
||||
// contain target. To ensure termination, we have to break all cycles
|
||||
// other than the first.
|
||||
q := []*Package{p}
|
||||
|
||||
for len(q) > 0 {
|
||||
p := q[0]
|
||||
q = q[1:]
|
||||
if path := p.ImportPath; path == target {
|
||||
var stk []string
|
||||
for path != "" {
|
||||
stk = append(stk, path)
|
||||
path = importerOf[path]
|
||||
}
|
||||
return stk
|
||||
}
|
||||
for _, dep := range p.Internal.Imports {
|
||||
if _, ok := importerOf[dep.ImportPath]; !ok {
|
||||
importerOf[dep.ImportPath] = p.ImportPath
|
||||
q = append(q, dep)
|
||||
}
|
||||
}
|
||||
// Can't happen, but in case it does...
|
||||
stk = append(stk, "<lost path to cycle>")
|
||||
break
|
||||
}
|
||||
return stk
|
||||
|
||||
panic("lost path to cycle")
|
||||
}
|
||||
|
||||
// recompileForTest copies and replaces certain packages in pmain's dependency
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ import (
|
|||
)
|
||||
|
||||
var cmdGraph = &base.Command{
|
||||
UsageLine: "go mod graph",
|
||||
UsageLine: "go mod graph [-go=version]",
|
||||
Short: "print module requirement graph",
|
||||
Long: `
|
||||
Graph prints the module requirement graph (with replacements applied)
|
||||
|
|
@ -26,12 +26,21 @@ in text form. Each line in the output has two space-separated fields: a module
|
|||
and one of its requirements. Each module is identified as a string of the form
|
||||
path@version, except for the main module, which has no @version suffix.
|
||||
|
||||
The -go flag causes graph to report the module graph as loaded by by the
|
||||
given Go version, instead of the version indicated by the 'go' directive
|
||||
in the go.mod file.
|
||||
|
||||
See https://golang.org/ref/mod#go-mod-graph for more about 'go mod graph'.
|
||||
`,
|
||||
Run: runGraph,
|
||||
}
|
||||
|
||||
var (
|
||||
graphGo goVersionFlag
|
||||
)
|
||||
|
||||
func init() {
|
||||
cmdGraph.Flag.Var(&graphGo, "go", "")
|
||||
base.AddModCommonFlags(&cmdGraph.Flag)
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +50,7 @@ func runGraph(ctx context.Context, cmd *base.Command, args []string) {
|
|||
}
|
||||
modload.ForceUseModules = true
|
||||
modload.RootMode = modload.NeedRoot
|
||||
mg := modload.LoadModGraph(ctx)
|
||||
mg := modload.LoadModGraph(ctx, graphGo.String())
|
||||
|
||||
w := bufio.NewWriter(os.Stdout)
|
||||
defer w.Flush()
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ func runVerify(ctx context.Context, cmd *base.Command, args []string) {
|
|||
sem := make(chan token, runtime.GOMAXPROCS(0))
|
||||
|
||||
// Use a slice of result channels, so that the output is deterministic.
|
||||
mods := modload.LoadModGraph(ctx).BuildList()[1:]
|
||||
const defaultGoVersion = ""
|
||||
mods := modload.LoadModGraph(ctx, defaultGoVersion).BuildList()[1:]
|
||||
errsChans := make([]<-chan []error, len(mods))
|
||||
|
||||
for i, mod := range mods {
|
||||
|
|
|
|||
|
|
@ -152,7 +152,7 @@ func lockVersion(mod module.Version) (unlock func(), err error) {
|
|||
// If err is nil, the caller MUST eventually call the unlock function.
|
||||
func SideLock() (unlock func(), err error) {
|
||||
if err := checkCacheDir(); err != nil {
|
||||
base.Fatalf("go: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
path := filepath.Join(cfg.GOMODCACHE, "cache", "lock")
|
||||
|
|
|
|||
|
|
@ -506,7 +506,8 @@ type versionReason struct {
|
|||
func newResolver(ctx context.Context, queries []*query) *resolver {
|
||||
// LoadModGraph also sets modload.Target, which is needed by various resolver
|
||||
// methods.
|
||||
mg := modload.LoadModGraph(ctx)
|
||||
const defaultGoVersion = ""
|
||||
mg := modload.LoadModGraph(ctx, defaultGoVersion)
|
||||
|
||||
buildList := mg.BuildList()
|
||||
initialVersion := make(map[string]string, len(buildList))
|
||||
|
|
@ -1153,6 +1154,7 @@ func (r *resolver) loadPackages(ctx context.Context, patterns []string, findPack
|
|||
Tags: imports.AnyTags(),
|
||||
VendorModulesInGOROOTSrc: true,
|
||||
LoadTests: *getT,
|
||||
AssumeRootsImported: true, // After 'go get foo', imports of foo should build.
|
||||
SilencePackageErrors: true, // May be fixed by subsequent upgrades or downgrades.
|
||||
}
|
||||
|
||||
|
|
@ -1802,7 +1804,8 @@ func (r *resolver) updateBuildList(ctx context.Context, additions []module.Versi
|
|||
return false
|
||||
}
|
||||
|
||||
r.buildList = modload.LoadModGraph(ctx).BuildList()
|
||||
const defaultGoVersion = ""
|
||||
r.buildList = modload.LoadModGraph(ctx, defaultGoVersion).BuildList()
|
||||
r.buildListVersion = make(map[string]string, len(r.buildList))
|
||||
for _, m := range r.buildList {
|
||||
r.buildListVersion[m.Path] = m.Version
|
||||
|
|
|
|||
|
|
@ -403,11 +403,33 @@ func (mg *ModuleGraph) allRootsSelected() bool {
|
|||
// LoadModGraph loads and returns the graph of module dependencies of the main module,
|
||||
// without loading any packages.
|
||||
//
|
||||
// If the goVersion string is non-empty, the returned graph is the graph
|
||||
// as interpreted by the given Go version (instead of the version indicated
|
||||
// in the go.mod file).
|
||||
//
|
||||
// Modules are loaded automatically (and lazily) in LoadPackages:
|
||||
// LoadModGraph need only be called if LoadPackages is not,
|
||||
// typically in commands that care about modules but no particular package.
|
||||
func LoadModGraph(ctx context.Context) *ModuleGraph {
|
||||
rs, mg, err := expandGraph(ctx, LoadModFile(ctx))
|
||||
func LoadModGraph(ctx context.Context, goVersion string) *ModuleGraph {
|
||||
rs := LoadModFile(ctx)
|
||||
|
||||
if goVersion != "" {
|
||||
depth := modDepthFromGoVersion(goVersion)
|
||||
if depth == eager && rs.depth != eager {
|
||||
// Use newRequirements instead of convertDepth because convertDepth
|
||||
// also updates roots; here, we want to report the unmodified roots
|
||||
// even though they may seem inconsistent.
|
||||
rs = newRequirements(eager, rs.rootModules, rs.direct)
|
||||
}
|
||||
|
||||
mg, err := rs.Graph(ctx)
|
||||
if err != nil {
|
||||
base.Fatalf("go: %v", err)
|
||||
}
|
||||
return mg
|
||||
}
|
||||
|
||||
rs, mg, err := expandGraph(ctx, rs)
|
||||
if err != nil {
|
||||
base.Fatalf("go: %v", err)
|
||||
}
|
||||
|
|
@ -443,7 +465,7 @@ func expandGraph(ctx context.Context, rs *Requirements) (*Requirements, *ModuleG
|
|||
// roots — but in a lazy module it may pull in previously-irrelevant
|
||||
// transitive dependencies.
|
||||
|
||||
newRS, rsErr := updateRoots(ctx, rs.direct, rs, nil, nil)
|
||||
newRS, rsErr := updateRoots(ctx, rs.direct, rs, nil, nil, false)
|
||||
if rsErr != nil {
|
||||
// Failed to update roots, perhaps because of an error in a transitive
|
||||
// dependency needed for the update. Return the original Requirements
|
||||
|
|
@ -517,11 +539,11 @@ func tidyRoots(ctx context.Context, rs *Requirements, pkgs []*loadPkg) (*Require
|
|||
return tidyLazyRoots(ctx, rs.direct, pkgs)
|
||||
}
|
||||
|
||||
func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version) (*Requirements, error) {
|
||||
func updateRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) {
|
||||
if rs.depth == eager {
|
||||
return updateEagerRoots(ctx, direct, rs, add)
|
||||
}
|
||||
return updateLazyRoots(ctx, direct, rs, pkgs, add)
|
||||
return updateLazyRoots(ctx, direct, rs, pkgs, add, rootsImported)
|
||||
}
|
||||
|
||||
// tidyLazyRoots returns a minimal set of root requirements that maintains the
|
||||
|
|
@ -661,7 +683,7 @@ func tidyLazyRoots(ctx context.Context, direct map[string]bool, pkgs []*loadPkg)
|
|||
//
|
||||
// (See https://golang.org/design/36460-lazy-module-loading#invariants for more
|
||||
// detail.)
|
||||
func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version) (*Requirements, error) {
|
||||
func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requirements, pkgs []*loadPkg, add []module.Version, rootsImported bool) (*Requirements, error) {
|
||||
roots := rs.rootModules
|
||||
rootsUpgraded := false
|
||||
|
||||
|
|
@ -688,6 +710,10 @@ func updateLazyRoots(ctx context.Context, direct map[string]bool, rs *Requiremen
|
|||
//
|
||||
// (This is the “import invariant” that makes lazy loading possible.)
|
||||
|
||||
case rootsImported && pkg.flags.has(pkgFromRoot):
|
||||
// pkg is a transitive dependency of some root, and we are treating the
|
||||
// roots as if they are imported by the main module (as in 'go get').
|
||||
|
||||
case pkg.flags.has(pkgIsRoot):
|
||||
// pkg is a root of the package-import graph. (Generally this means that
|
||||
// it matches a command-line argument.) We want future invocations of the
|
||||
|
|
|
|||
|
|
@ -178,11 +178,13 @@ func (e *ImportMissingSumError) Error() string {
|
|||
// Importing package is unknown, or the missing package was named on the
|
||||
// command line. Recommend 'go mod download' for the modules that could
|
||||
// provide the package, since that shouldn't change go.mod.
|
||||
args := make([]string, len(e.mods))
|
||||
for i, mod := range e.mods {
|
||||
args[i] = mod.Path
|
||||
if len(e.mods) > 0 {
|
||||
args := make([]string, len(e.mods))
|
||||
for i, mod := range e.mods {
|
||||
args[i] = mod.Path
|
||||
}
|
||||
hint = fmt.Sprintf("; to add:\n\tgo mod download %s", strings.Join(args, " "))
|
||||
}
|
||||
hint = fmt.Sprintf("; to add:\n\tgo mod download %s", strings.Join(args, " "))
|
||||
} else {
|
||||
// Importing package is known (common case). Recommend 'go get' on the
|
||||
// current version of the importing package.
|
||||
|
|
@ -426,6 +428,15 @@ func queryImport(ctx context.Context, path string, rs *Requirements) (module.Ver
|
|||
mv = module.ZeroPseudoVersion("v0")
|
||||
}
|
||||
}
|
||||
mg, err := rs.Graph(ctx)
|
||||
if err != nil {
|
||||
return module.Version{}, err
|
||||
}
|
||||
if cmpVersion(mg.Selected(mp), mv) >= 0 {
|
||||
// We can't resolve the import by adding mp@mv to the module graph,
|
||||
// because the selected version of mp is already at least mv.
|
||||
continue
|
||||
}
|
||||
mods = append(mods, module.Version{Path: mp, Version: mv})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -661,7 +661,7 @@ func requirementsFromModFile(ctx context.Context) *Requirements {
|
|||
for _, n := range mPathCount {
|
||||
if n > 1 {
|
||||
var err error
|
||||
rs, err = updateRoots(ctx, rs.direct, rs, nil, nil)
|
||||
rs, err = updateRoots(ctx, rs.direct, rs, nil, nil, false)
|
||||
if err != nil {
|
||||
base.Fatalf("go: %v", err)
|
||||
}
|
||||
|
|
@ -999,10 +999,14 @@ func commitRequirements(ctx context.Context, goVersion string, rs *Requirements)
|
|||
Indirect: !rs.direct[m.Path],
|
||||
})
|
||||
}
|
||||
modFile.SetRequire(list)
|
||||
if goVersion != "" {
|
||||
modFile.AddGoStmt(goVersion)
|
||||
}
|
||||
if semver.Compare("v"+modFileGoVersion(), separateIndirectVersionV) < 0 {
|
||||
modFile.SetRequire(list)
|
||||
} else {
|
||||
modFile.SetRequireSeparateIndirect(list)
|
||||
}
|
||||
modFile.Cleanup()
|
||||
|
||||
dirty := index.modFileIsDirty(modFile)
|
||||
|
|
|
|||
|
|
@ -171,6 +171,11 @@ type PackageOpts struct {
|
|||
// if the flag is set to "readonly" (the default) or "vendor".
|
||||
ResolveMissingImports bool
|
||||
|
||||
// AssumeRootsImported indicates that the transitive dependencies of the root
|
||||
// packages should be treated as if those roots will be imported by the main
|
||||
// module.
|
||||
AssumeRootsImported bool
|
||||
|
||||
// AllowPackage, if non-nil, is called after identifying the module providing
|
||||
// each package. If AllowPackage returns a non-nil error, that error is set
|
||||
// for the package, and the imports and test of that package will not be
|
||||
|
|
@ -875,6 +880,11 @@ const (
|
|||
// are also roots (and must be marked pkgIsRoot).
|
||||
pkgIsRoot
|
||||
|
||||
// pkgFromRoot indicates that the package is in the transitive closure of
|
||||
// imports starting at the roots. (Note that every package marked as pkgIsRoot
|
||||
// is also trivially marked pkgFromRoot.)
|
||||
pkgFromRoot
|
||||
|
||||
// pkgImportsLoaded indicates that the imports and testImports fields of a
|
||||
// loadPkg have been populated.
|
||||
pkgImportsLoaded
|
||||
|
|
@ -1068,7 +1078,7 @@ func loadFromRoots(ctx context.Context, params loaderParams) *loader {
|
|||
// iteration so we don't need to also update it here. (That would waste time
|
||||
// computing a "direct" map that we'll have to recompute later anyway.)
|
||||
direct := ld.requirements.direct
|
||||
rs, err := updateRoots(ctx, direct, ld.requirements, noPkgs, toAdd)
|
||||
rs, err := updateRoots(ctx, direct, ld.requirements, noPkgs, toAdd, ld.AssumeRootsImported)
|
||||
if err != nil {
|
||||
// If an error was found in a newly added module, report the package
|
||||
// import stack instead of the module requirement stack. Packages
|
||||
|
|
@ -1274,7 +1284,7 @@ func (ld *loader) updateRequirements(ctx context.Context) (changed bool, err err
|
|||
addRoots = tidy.rootModules
|
||||
}
|
||||
|
||||
rs, err = updateRoots(ctx, direct, rs, ld.pkgs, addRoots)
|
||||
rs, err = updateRoots(ctx, direct, rs, ld.pkgs, addRoots, ld.AssumeRootsImported)
|
||||
if err != nil {
|
||||
// We don't actually know what even the root requirements are supposed to be,
|
||||
// so we can't proceed with loading. Return the error to the caller
|
||||
|
|
@ -1433,6 +1443,9 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg
|
|||
// This package matches a root pattern by virtue of being in "all".
|
||||
flags |= pkgIsRoot
|
||||
}
|
||||
if flags.has(pkgIsRoot) {
|
||||
flags |= pkgFromRoot
|
||||
}
|
||||
|
||||
old := pkg.flags.update(flags)
|
||||
new := old | flags
|
||||
|
|
@ -1487,6 +1500,12 @@ func (ld *loader) applyPkgFlags(ctx context.Context, pkg *loadPkg, flags loadPkg
|
|||
ld.applyPkgFlags(ctx, dep, pkgInAll)
|
||||
}
|
||||
}
|
||||
|
||||
if new.has(pkgFromRoot) && !old.has(pkgFromRoot|pkgImportsLoaded) {
|
||||
for _, dep := range pkg.imports {
|
||||
ld.applyPkgFlags(ctx, dep, pkgFromRoot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// preloadRootModules loads the module requirements needed to identify the
|
||||
|
|
@ -1549,7 +1568,7 @@ func (ld *loader) preloadRootModules(ctx context.Context, rootPkgs []string) (ch
|
|||
}
|
||||
module.Sort(toAdd)
|
||||
|
||||
rs, err := updateRoots(ctx, ld.requirements.direct, ld.requirements, nil, toAdd)
|
||||
rs, err := updateRoots(ctx, ld.requirements.direct, ld.requirements, nil, toAdd, ld.AssumeRootsImported)
|
||||
if err != nil {
|
||||
// We are missing some root dependency, and for some reason we can't load
|
||||
// enough of the module dependency graph to add the missing root. Package
|
||||
|
|
|
|||
|
|
@ -35,6 +35,11 @@ const (
|
|||
// module's go.mod file is expected to list explicit requirements on every
|
||||
// module that provides any package transitively imported by that module.
|
||||
lazyLoadingVersionV = "v1.17"
|
||||
|
||||
// separateIndirectVersionV is the Go version (plus leading "v") at which
|
||||
// "// indirect" dependencies are added in a block separate from the direct
|
||||
// ones. See https://golang.org/issue/45965.
|
||||
separateIndirectVersionV = "v1.17"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
# Per https://golang.org/ref/spec#Source_code_representation:
|
||||
# a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF)
|
||||
# if it is the first Unicode code point in the source text.
|
||||
|
||||
go list -f 'Imports: {{.Imports}} EmbedFiles: {{.EmbedFiles}}' .
|
||||
stdout '^Imports: \[embed m/hello\] EmbedFiles: \[.*file\]$'
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
go 1.16
|
||||
-- m.go --
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
|
||||
"m/hello"
|
||||
)
|
||||
|
||||
//go:embed file
|
||||
var s string
|
||||
|
||||
-- hello/hello.go --
|
||||
package hello
|
||||
|
||||
-- file --
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
# Test that the corect default GOEXPERIMENT is used when cross
|
||||
# building with GOENV (#46815).
|
||||
|
||||
# Unset variables set by the TestScript harness. Users typically won't
|
||||
# explicitly configure these, and #46815 doesn't repro if they are.
|
||||
env GOOS=
|
||||
env GOARCH=
|
||||
env GOEXPERIMENT=
|
||||
|
||||
env GOENV=windows-amd64
|
||||
go build internal/abi
|
||||
|
||||
env GOENV=ios-arm64
|
||||
go build internal/abi
|
||||
|
||||
env GOENV=linux-mips
|
||||
go build internal/abi
|
||||
|
||||
-- windows-amd64 --
|
||||
GOOS=windows
|
||||
GOARCH=amd64
|
||||
|
||||
-- ios-arm64 --
|
||||
GOOS=ios
|
||||
GOARCH=arm64
|
||||
|
||||
-- linux-mips --
|
||||
GOOS=linux
|
||||
GOARCH=mips
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
# Regression test for https://golang.org/issue/46462.
|
||||
#
|
||||
# The "runtime/cgo" import found in synthesized .go files (reported in
|
||||
# the CompiledGoFiles field) should have a corresponding entry in the
|
||||
# ImportMap field when a runtime/cgo variant (such as a test variant)
|
||||
# will be used.
|
||||
|
||||
[short] skip # -compiled can be slow (because it compiles things)
|
||||
[!cgo] skip
|
||||
|
||||
env CGO_ENABLED=1
|
||||
env GOFLAGS=-tags=netcgo # Force net to use cgo even on Windows.
|
||||
|
||||
|
||||
# "runtime/cgo [runtime.test]" appears in the the test dependencies of "runtime",
|
||||
# because "runtime/cgo" itself depends on "runtime"
|
||||
|
||||
go list -deps -test -compiled -f '{{if eq .ImportPath "net [runtime.test]"}}{{printf "%q" .Imports}}{{end}}' runtime
|
||||
|
||||
# Control case: the explicitly-imported package "sync" is a test variant,
|
||||
# because "sync" depends on "runtime".
|
||||
stdout '"sync \[runtime\.test\]"'
|
||||
! stdout '"sync"'
|
||||
|
||||
# Experiment: the implicitly-imported package "runtime/cgo" is also a test variant,
|
||||
# because "runtime/cgo" also depends on "runtime".
|
||||
stdout '"runtime/cgo \[runtime\.test\]"'
|
||||
! stdout '"runtime/cgo"'
|
||||
|
||||
|
||||
# Because the import of "runtime/cgo" in the cgo-generated file actually refers
|
||||
# to "runtime/cgo [runtime.test]", the latter should be listed in the ImportMap.
|
||||
# BUG(#46462): Today, it is not.
|
||||
|
||||
go list -deps -test -compiled -f '{{if eq .ImportPath "net [runtime.test]"}}{{printf "%q" .ImportMap}}{{end}}' runtime
|
||||
|
||||
stdout '"sync":"sync \[runtime\.test\]"' # control
|
||||
stdout '"runtime/cgo":"runtime/cgo \[runtime\.test\]"' # experiment
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# 'go mod edit' opportunistically locks the side-lock file in the module cache,
|
||||
# for compatibility with older versions of the 'go' command.
|
||||
# It does not otherwise depend on the module cache, so it should not
|
||||
# fail if the module cache directory cannot be created.
|
||||
|
||||
[root] skip
|
||||
|
||||
mkdir $WORK/readonly
|
||||
chmod 0555 $WORK/readonly
|
||||
env GOPATH=$WORK/readonly/nonexist
|
||||
|
||||
go mod edit -go=1.17
|
||||
|
||||
-- go.mod --
|
||||
module example.com/m
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
# https://golang.org/issue/45979: after 'go get' on a package,
|
||||
# that package should be importable without error.
|
||||
|
||||
|
||||
# We start out with an unresolved dependency.
|
||||
# 'go list' suggests that we run 'go get' on that dependency.
|
||||
|
||||
! go list -deps .
|
||||
stderr '^m.go:3:8: no required module provides package rsc\.io/quote; to add it:\n\tgo get rsc.io/quote$'
|
||||
|
||||
|
||||
# When we run the suggested 'go get' command, the new dependency can be used
|
||||
# immediately.
|
||||
#
|
||||
# 'go get' marks the new dependency as 'indirect', because it doesn't scan
|
||||
# enough source code to know whether it is direct, and it is easier and less
|
||||
# invasive to remove an incorrect indirect mark (e.g. using 'go get') than to
|
||||
# add one that is missing ('go mod tidy' or 'go mod vendor').
|
||||
|
||||
go get rsc.io/quote
|
||||
grep 'rsc.io/quote v\d+\.\d+\.\d+ // indirect$' go.mod
|
||||
! grep 'rsc.io/quote v\d+\.\d+\.\d+$' go.mod
|
||||
|
||||
go list -deps .
|
||||
! stderr .
|
||||
[!short] go build .
|
||||
[!short] ! stderr .
|
||||
|
||||
|
||||
# 'go get .' (or 'go mod tidy') removes the indirect mark.
|
||||
|
||||
go get .
|
||||
grep 'rsc.io/quote v\d+\.\d+\.\d+$' go.mod
|
||||
! grep 'rsc.io/quote v\d+\.\d+\.\d+ // indirect$' go.mod
|
||||
|
||||
|
||||
-- go.mod --
|
||||
module example.com/m
|
||||
|
||||
go 1.17
|
||||
-- m.go --
|
||||
package m
|
||||
|
||||
import _ "rsc.io/quote"
|
||||
|
|
@ -73,10 +73,9 @@ module example.com/m
|
|||
|
||||
go $goversion
|
||||
|
||||
require (
|
||||
example.com/dep v0.1.0
|
||||
example.com/testdep v0.1.0 // indirect
|
||||
)
|
||||
require example.com/dep v0.1.0
|
||||
|
||||
require example.com/testdep v0.1.0 // indirect
|
||||
|
||||
replace (
|
||||
example.com/dep v0.1.0 => ./dep
|
||||
|
|
|
|||
|
|
@ -0,0 +1,101 @@
|
|||
# For this module, Go 1.17 prunes out a (transitive and otherwise-irrelevant)
|
||||
# requirement on a retracted higher version of a dependency.
|
||||
# However, when Go 1.16 reads the same requirements from the go.mod file,
|
||||
# it does not prune out that requirement, and selects the retracted version.
|
||||
#
|
||||
# The Go 1.16 module graph looks like:
|
||||
#
|
||||
# m ---- lazy v0.1.0 ---- requireincompatible v0.1.0 ---- incompatible v2.0.0+incompatible
|
||||
# | |
|
||||
# + -------+------------- incompatible v1.0.0
|
||||
#
|
||||
# The Go 1.17 module graph is the same except that the dependencies of
|
||||
# requireincompatible are pruned out (because the module that requires
|
||||
# it — lazy v0.1.0 — specifies 'go 1.17', and it is not otherwise relevant to
|
||||
# the main module).
|
||||
|
||||
cp go.mod go.mod.orig
|
||||
|
||||
go mod graph
|
||||
cp stdout graph-1.17.txt
|
||||
stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
|
||||
stdout '^example\.net/lazy@v0\.1\.0 example\.com/retract/incompatible@v1\.0\.0$'
|
||||
! stdout 'example\.com/retract/incompatible@v2\.0\.0\+incompatible'
|
||||
|
||||
go mod graph -go=1.17
|
||||
cmp stdout graph-1.17.txt
|
||||
|
||||
cmp go.mod go.mod.orig
|
||||
|
||||
|
||||
# Setting -go=1.16 should report the graph as viewed by Go 1.16,
|
||||
# but should not edit the go.mod file.
|
||||
|
||||
go mod graph -go=1.16
|
||||
cp stdout graph-1.16.txt
|
||||
stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
|
||||
stdout '^example\.net/lazy@v0\.1\.0 example.com/retract/incompatible@v1\.0\.0$'
|
||||
stdout '^example.net/requireincompatible@v0.1.0 example.com/retract/incompatible@v2\.0\.0\+incompatible$'
|
||||
|
||||
cmp go.mod go.mod.orig
|
||||
|
||||
|
||||
# If we actually update the go.mod file to the requested go version,
|
||||
# we should get the same selected versions, but the roots of the graph
|
||||
# may be updated.
|
||||
#
|
||||
# TODO(#45551): The roots should not be updated.
|
||||
|
||||
go mod edit -go=1.16
|
||||
go mod graph
|
||||
! stdout '^example\.com/m example\.com/retract/incompatible@v1\.0\.0$'
|
||||
stdout '^example\.net/lazy@v0.1.0 example.com/retract/incompatible@v1\.0\.0$'
|
||||
stdout '^example.net/requireincompatible@v0.1.0 example.com/retract/incompatible@v2\.0\.0\+incompatible$'
|
||||
# TODO(#45551): cmp stdout graph-1.16.txt
|
||||
|
||||
|
||||
# Unsupported go versions should be rejected, since we don't know
|
||||
# what versions they would report.
|
||||
! go mod graph -go=1.99999999999
|
||||
stderr '^invalid value "1\.99999999999" for flag -go: maximum supported Go version is '$goversion'\nusage: go mod graph \[-go=version\]\nRun ''go help mod graph'' for details.$'
|
||||
|
||||
|
||||
-- go.mod --
|
||||
// Module m indirectly imports a package from
|
||||
// example.com/retract/incompatible. Its selected version of
|
||||
// that module is lower under Go 1.17 semantics than under Go 1.16.
|
||||
module example.com/m
|
||||
|
||||
go 1.17
|
||||
|
||||
replace (
|
||||
example.net/lazy v0.1.0 => ./lazy
|
||||
example.net/requireincompatible v0.1.0 => ./requireincompatible
|
||||
)
|
||||
|
||||
require (
|
||||
example.com/retract/incompatible v1.0.0 // indirect
|
||||
example.net/lazy v0.1.0
|
||||
)
|
||||
-- lazy/go.mod --
|
||||
// Module lazy requires example.com/retract/incompatible v1.0.0.
|
||||
//
|
||||
// When viewed from the outside it also has a transitive dependency
|
||||
// on v2.0.0+incompatible, but in lazy mode that transitive dependency
|
||||
// is pruned out.
|
||||
module example.net/lazy
|
||||
|
||||
go 1.17
|
||||
|
||||
exclude example.com/retract/incompatible v2.0.0+incompatible
|
||||
|
||||
require (
|
||||
example.com/retract/incompatible v1.0.0
|
||||
example.net/requireincompatible v0.1.0
|
||||
)
|
||||
-- requireincompatible/go.mod --
|
||||
module example.net/requireincompatible
|
||||
|
||||
go 1.15
|
||||
|
||||
require example.com/retract/incompatible v2.0.0+incompatible
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
# Module is replaced but not required. No hint appears as no module is suggested.
|
||||
go mod init m
|
||||
go mod edit -replace=github.com/notrequired@v0.5.0=github.com/doesnotexist@v0.5.0
|
||||
! go install github.com/notrequired
|
||||
! stderr 'to add it:'
|
||||
|
|
@ -19,7 +19,7 @@ cp go.mod.orig go.mod
|
|||
go mod edit -require golang.org/x/text@14c0d48ead0c
|
||||
cd outside
|
||||
! go list -m golang.org/x/text
|
||||
stderr 'go list -m: example.com@v0.0.0 \(replaced by \./\..\): parsing ../go.mod: '$WORK'/gopath/src/go.mod:5: require golang.org/x/text: version "14c0d48ead0c" invalid: must be of the form v1.2.3'
|
||||
stderr 'go list -m: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "14c0d48ead0c" invalid: must be of the form v1.2.3'
|
||||
cd ..
|
||||
go list -m golang.org/x/text
|
||||
stdout 'golang.org/x/text v0.1.1-0.20170915032832-14c0d48ead0c'
|
||||
|
|
@ -47,10 +47,10 @@ cp go.mod.orig go.mod
|
|||
go mod edit -require golang.org/x/text@v2.1.1-0.20170915032832-14c0d48ead0c
|
||||
cd outside
|
||||
! go list -m golang.org/x/text
|
||||
stderr 'go list -m: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ../go.mod: '$WORK'/gopath/src/go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
|
||||
stderr 'go list -m: example.com@v0.0.0 \(replaced by \./\.\.\): parsing ..[/\\]go.mod: '$WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
|
||||
cd ..
|
||||
! go list -m golang.org/x/text
|
||||
stderr $WORK'/gopath/src/go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
|
||||
stderr $WORK'[/\\]gopath[/\\]src[/\\]go.mod:5: require golang.org/x/text: version "v2.1.1-0.20170915032832-14c0d48ead0c" invalid: should be v0 or v1, not v2'
|
||||
|
||||
# A pseudo-version with fewer than 12 digits of SHA-1 prefix is invalid.
|
||||
cp go.mod.orig go.mod
|
||||
|
|
|
|||
|
|
@ -139,9 +139,10 @@ go 1.17
|
|||
require (
|
||||
a v0.1.0
|
||||
b v0.1.0
|
||||
c v0.1.0 // indirect
|
||||
)
|
||||
|
||||
require c v0.1.0 // indirect
|
||||
|
||||
replace (
|
||||
a v0.1.0 => ./a1
|
||||
b v0.1.0 => ./b1
|
||||
|
|
|
|||
|
|
@ -78,10 +78,9 @@ module example.com/lazy
|
|||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
example.com/a v0.1.0
|
||||
example.com/b v0.1.0 // indirect
|
||||
)
|
||||
require example.com/a v0.1.0
|
||||
|
||||
require example.com/b v0.1.0 // indirect
|
||||
|
||||
replace (
|
||||
example.com/a v0.1.0 => ./a
|
||||
|
|
@ -94,8 +93,9 @@ module example.com/lazy
|
|||
|
||||
go 1.17
|
||||
|
||||
require example.com/a v0.1.0
|
||||
|
||||
require (
|
||||
example.com/a v0.1.0
|
||||
example.com/b v0.1.0 // indirect
|
||||
example.com/c v0.1.0 // indirect
|
||||
)
|
||||
|
|
|
|||
|
|
@ -148,10 +148,9 @@ module example.com/lazy
|
|||
|
||||
go 1.17
|
||||
|
||||
require (
|
||||
example.com/a v0.1.0
|
||||
example.com/b v0.1.0 // indirect
|
||||
)
|
||||
require example.com/a v0.1.0
|
||||
|
||||
require example.com/b v0.1.0 // indirect
|
||||
|
||||
replace (
|
||||
example.com/a v0.1.0 => ./a
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
# https://golang.org/issue/45863: a typo in a test package leading to an
|
||||
# import cycle should be diagnosed, instead of causing an infinite loop.
|
||||
# The failure mode of this test prior to the fix was a timeout or OOM crash.
|
||||
|
||||
go list -e -test -deps ./datastore/sql
|
||||
|
||||
-- go.mod --
|
||||
module golang.org/issue45863
|
||||
|
||||
go 1.17
|
||||
-- datastore/datastore_health.go --
|
||||
package datastore
|
||||
|
||||
import (
|
||||
"golang.org/issue45863/datastore"
|
||||
"golang.org/issue45863/datastore/sql"
|
||||
)
|
||||
-- datastore/sql/sql.go --
|
||||
package sql
|
||||
-- datastore/sql/sql_test.go --
|
||||
package sql
|
||||
|
||||
import _ "golang.org/issue45863/datastore"
|
||||
|
|
@ -140,8 +140,9 @@ module m
|
|||
go $goversion
|
||||
|
||||
require (
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
|
||||
rsc.io/quote v1.5.2
|
||||
rsc.io/sampler v1.3.0 // indirect
|
||||
rsc.io/testonly v1.0.0 // indirect
|
||||
)
|
||||
|
||||
require golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c // indirect
|
||||
|
|
|
|||
|
|
@ -10,45 +10,73 @@ go env GOSUMDB
|
|||
stdout '^sum.golang.org$'
|
||||
|
||||
# Download direct from github.
|
||||
|
||||
[!net] skip
|
||||
[!exec:git] skip
|
||||
env GOSUMDB=sum.golang.org
|
||||
env GOPROXY=direct
|
||||
|
||||
go get -d rsc.io/quote@v1.5.2
|
||||
cp go.sum saved.sum
|
||||
|
||||
|
||||
# Download from proxy.golang.org with go.sum entry already.
|
||||
# Use 'go list' instead of 'go get' since the latter may download extra go.mod
|
||||
# files not listed in go.sum.
|
||||
|
||||
go clean -modcache
|
||||
env GOSUMDB=
|
||||
env GOPROXY=
|
||||
go list -x -deps rsc.io/quote
|
||||
|
||||
go list -x -m all # Download go.mod files.
|
||||
! stderr github
|
||||
stderr proxy.golang.org/rsc.io/quote
|
||||
! stderr sum.golang.org/tile
|
||||
! stderr sum.golang.org/lookup/rsc.io/quote
|
||||
|
||||
go list -x -deps rsc.io/quote # Download module source.
|
||||
! stderr github
|
||||
stderr proxy.golang.org/rsc.io/quote
|
||||
! stderr sum.golang.org/tile
|
||||
! stderr sum.golang.org/lookup/rsc.io/quote
|
||||
|
||||
cmp go.sum saved.sum
|
||||
|
||||
|
||||
# Download again.
|
||||
# Should use the checksum database to validate new go.sum lines,
|
||||
# but not need to fetch any new data from the proxy.
|
||||
|
||||
rm go.sum
|
||||
go list -mod=mod -x rsc.io/quote
|
||||
|
||||
go list -mod=mod -x -m all # Add checksums for go.mod files.
|
||||
stderr sum.golang.org/tile
|
||||
! stderr github
|
||||
! stderr proxy.golang.org/rsc.io/quote
|
||||
stderr sum.golang.org/tile
|
||||
stderr sum.golang.org/lookup/rsc.io/quote
|
||||
|
||||
go list -mod=mod -x rsc.io/quote # Add checksums for module source.
|
||||
! stderr . # Adds checksums, but for entities already in the module cache.
|
||||
|
||||
cmp go.sum saved.sum
|
||||
|
||||
|
||||
# test fallback to direct
|
||||
|
||||
env TESTGOPROXY404=1
|
||||
go clean -modcache
|
||||
rm go.sum
|
||||
go list -mod=mod -x rsc.io/quote
|
||||
|
||||
go list -mod=mod -x -m all # Download go.mod files
|
||||
stderr 'proxy.golang.org.*404 testing'
|
||||
stderr github.com/rsc
|
||||
|
||||
go list -mod=mod -x rsc.io/quote # Download module source.
|
||||
stderr 'proxy.golang.org.*404 testing'
|
||||
stderr github.com/rsc
|
||||
|
||||
cmp go.sum saved.sum
|
||||
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
|
|
|||
|
|
@ -90,7 +90,6 @@ cmp go.mod go.mod.postget
|
|||
cp go.mod.orig go.mod
|
||||
go mod edit -go=1.17 go.mod
|
||||
go mod edit -go=1.17 go.mod.tidye
|
||||
go mod edit -go=1.17 go.mod.postget
|
||||
|
||||
go mod tidy -e
|
||||
cmp go.mod go.mod.tidye
|
||||
|
|
@ -99,7 +98,7 @@ stderr '^example\.net/m imports\n\texample\.net/x: package example\.net/x provid
|
|||
|
||||
go get -d example.net/x@v0.1.0 example.net/y@v0.1.0
|
||||
go mod tidy
|
||||
cmp go.mod go.mod.postget
|
||||
cmp go.mod go.mod.postget-117
|
||||
|
||||
|
||||
-- go.mod --
|
||||
|
|
@ -144,6 +143,21 @@ require (
|
|||
example.net/x v0.1.0
|
||||
example.net/y v0.1.0 // indirect
|
||||
)
|
||||
-- go.mod.postget-117 --
|
||||
module example.net/m
|
||||
|
||||
go 1.17
|
||||
|
||||
replace (
|
||||
example.net/x v0.1.0 => ./x1
|
||||
example.net/x v0.2.0-pre => ./x2-pre
|
||||
example.net/y v0.1.0 => ./y1
|
||||
example.net/y v0.2.0 => ./y2
|
||||
)
|
||||
|
||||
require example.net/x v0.1.0
|
||||
|
||||
require example.net/y v0.1.0 // indirect
|
||||
-- m.go --
|
||||
package m
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
# Regression test for https://golang.org/issue/46659.
|
||||
#
|
||||
# If a 'replace' directive specifies an older-than-selected version of a module,
|
||||
# 'go mod tidy' shouldn't try to add that version to the build list to resolve a
|
||||
# missing package: it won't be selected, and would cause the module loader to
|
||||
# loop indefinitely trying to resolve the package.
|
||||
|
||||
cp go.mod go.mod.orig
|
||||
|
||||
! go mod tidy
|
||||
! stderr panic
|
||||
stderr '^golang\.org/issue46659 imports\n\texample\.com/missingpkg/deprecated: package example\.com/missingpkg/deprecated provided by example\.com/missingpkg at latest version v1\.0\.0 but not at required version v1\.0\.1-beta$'
|
||||
|
||||
go mod tidy -e
|
||||
|
||||
cmp go.mod go.mod.orig
|
||||
|
||||
-- go.mod --
|
||||
module golang.org/issue46659
|
||||
|
||||
go 1.17
|
||||
|
||||
replace example.com/missingpkg v1.0.1-alpha => example.com/missingpkg v1.0.0
|
||||
|
||||
require example.com/usemissingpre v1.0.0
|
||||
|
||||
require example.com/missingpkg v1.0.1-beta // indirect
|
||||
-- m.go --
|
||||
package m
|
||||
|
||||
import (
|
||||
_ "example.com/missingpkg/deprecated"
|
||||
_ "example.com/usemissingpre"
|
||||
)
|
||||
|
|
@ -92,8 +92,9 @@ cmpenv go.mod go.mod.latest
|
|||
-- go.mod --
|
||||
module example.com/m
|
||||
|
||||
require example.net/a v0.1.0
|
||||
|
||||
require (
|
||||
example.net/a v0.1.0
|
||||
example.net/c v0.1.0 // indirect
|
||||
example.net/d v0.1.0 // indirect
|
||||
)
|
||||
|
|
@ -118,8 +119,9 @@ module example.com/m
|
|||
|
||||
go 1.15
|
||||
|
||||
require example.net/a v0.1.0
|
||||
|
||||
require (
|
||||
example.net/a v0.1.0
|
||||
example.net/c v0.1.0 // indirect
|
||||
example.net/d v0.1.0 // indirect
|
||||
)
|
||||
|
|
@ -139,8 +141,9 @@ module example.com/m
|
|||
|
||||
go 1.15
|
||||
|
||||
require example.net/a v0.1.0
|
||||
|
||||
require (
|
||||
example.net/a v0.1.0
|
||||
example.net/c v0.1.0 // indirect
|
||||
example.net/d v0.2.0 // indirect
|
||||
)
|
||||
|
|
@ -160,10 +163,9 @@ module example.com/m
|
|||
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
example.net/a v0.1.0
|
||||
example.net/c v0.1.0 // indirect
|
||||
)
|
||||
require example.net/a v0.1.0
|
||||
|
||||
require example.net/c v0.1.0 // indirect
|
||||
|
||||
replace (
|
||||
example.net/a v0.1.0 => ./a
|
||||
|
|
@ -180,8 +182,9 @@ module example.com/m
|
|||
|
||||
go 1.17
|
||||
|
||||
require example.net/a v0.1.0
|
||||
|
||||
require (
|
||||
example.net/a v0.1.0
|
||||
example.net/b v0.1.0 // indirect
|
||||
example.net/c v0.1.0 // indirect
|
||||
)
|
||||
|
|
@ -201,8 +204,9 @@ module example.com/m
|
|||
|
||||
go $goversion
|
||||
|
||||
require example.net/a v0.1.0
|
||||
|
||||
require (
|
||||
example.net/a v0.1.0
|
||||
example.net/b v0.1.0 // indirect
|
||||
example.net/c v0.1.0 // indirect
|
||||
)
|
||||
|
|
|
|||
|
|
@ -26,9 +26,6 @@ The flags are:
|
|||
Do not print reformatted sources to standard output.
|
||||
If a file's formatting is different from gofmt's, print its name
|
||||
to standard output.
|
||||
-G
|
||||
Allow generic code, using type parameters.
|
||||
See golang.org/issues/43651 for more information.
|
||||
-r rule
|
||||
Apply the rewrite rule to the source before reformatting.
|
||||
-s
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
package moddeps_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
|
|
@ -68,7 +69,7 @@ func TestAllDependencies(t *testing.T) {
|
|||
|
||||
// There is no vendor directory, so the module must have no dependencies.
|
||||
// Check that the list of active modules contains only the main module.
|
||||
cmd := exec.Command(goBin, "list", "-mod=mod", "-m", "all")
|
||||
cmd := exec.Command(goBin, "list", "-mod=readonly", "-m", "all")
|
||||
cmd.Env = append(os.Environ(), "GO111MODULE=on")
|
||||
cmd.Dir = m.Dir
|
||||
cmd.Stderr = new(strings.Builder)
|
||||
|
|
@ -123,10 +124,38 @@ func TestAllDependencies(t *testing.T) {
|
|||
t.Skip("skipping because a diff command with support for --recursive and --unified flags is unavailable")
|
||||
}
|
||||
|
||||
// We're going to check the standard modules for tidiness, so we need a usable
|
||||
// GOMODCACHE. If the default directory doesn't exist, use a temporary
|
||||
// directory instead. (That can occur, for example, when running under
|
||||
// run.bash with GO_TEST_SHORT=0: run.bash sets GOPATH=/nonexist-gopath, and
|
||||
// GO_TEST_SHORT=0 causes it to run this portion of the test.)
|
||||
var modcacheEnv []string
|
||||
{
|
||||
out, err := exec.Command(goBin, "env", "GOMODCACHE").Output()
|
||||
if err != nil {
|
||||
t.Fatalf("%s env GOMODCACHE: %v", goBin, err)
|
||||
}
|
||||
modcacheOk := false
|
||||
if gomodcache := string(bytes.TrimSpace(out)); gomodcache != "" {
|
||||
if _, err := os.Stat(gomodcache); err == nil {
|
||||
modcacheOk = true
|
||||
}
|
||||
}
|
||||
if !modcacheOk {
|
||||
modcacheEnv = []string{
|
||||
"GOMODCACHE=" + t.TempDir(),
|
||||
"GOFLAGS=" + os.Getenv("GOFLAGS") + " -modcacherw", // Allow t.TempDir() to clean up subdirectories.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the bundle binary at the golang.org/x/tools
|
||||
// module version specified in GOROOT/src/cmd/go.mod.
|
||||
bundleDir := t.TempDir()
|
||||
r := runner{Dir: filepath.Join(runtime.GOROOT(), "src/cmd")}
|
||||
r := runner{
|
||||
Dir: filepath.Join(runtime.GOROOT(), "src/cmd"),
|
||||
Env: append(os.Environ(), modcacheEnv...),
|
||||
}
|
||||
r.run(t, goBin, "build", "-mod=readonly", "-o", bundleDir, "golang.org/x/tools/cmd/bundle")
|
||||
|
||||
var gorootCopyDir string
|
||||
|
|
@ -160,7 +189,7 @@ func TestAllDependencies(t *testing.T) {
|
|||
}
|
||||
r := runner{
|
||||
Dir: filepath.Join(gorootCopyDir, rel),
|
||||
Env: append(os.Environ(),
|
||||
Env: append(append(os.Environ(), modcacheEnv...),
|
||||
// Set GOROOT.
|
||||
"GOROOT="+gorootCopyDir,
|
||||
// Explicitly override PWD and clear GOROOT_FINAL so that GOROOT=gorootCopyDir is definitely used.
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ func BuildModeSupported(compiler, buildmode, goos, goarch string) bool {
|
|||
"android/amd64", "android/arm", "android/arm64", "android/386",
|
||||
"freebsd/amd64",
|
||||
"darwin/amd64", "darwin/arm64",
|
||||
"windows/amd64", "windows/386":
|
||||
"windows/amd64", "windows/386", "windows/arm64":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
|
|
|||
|
|
@ -950,6 +950,11 @@ func elfdynhash(ctxt *Link) {
|
|||
}
|
||||
|
||||
s = ldr.CreateSymForUpdate(".dynamic", 0)
|
||||
if ctxt.BuildMode == BuildModePIE {
|
||||
// https://github.com/bminor/glibc/blob/895ef79e04a953cac1493863bcae29ad85657ee1/elf/elf.h#L986
|
||||
const DTFLAGS_1_PIE = 0x08000000
|
||||
Elfwritedynent(ctxt.Arch, s, elf.DT_FLAGS_1, uint64(DTFLAGS_1_PIE))
|
||||
}
|
||||
elfverneed = nfile
|
||||
if elfverneed != 0 {
|
||||
elfWriteDynEntSym(ctxt, s, elf.DT_VERNEED, gnuVersionR.Sym())
|
||||
|
|
|
|||
|
|
@ -475,7 +475,7 @@ func (f *peFile) addDWARFSection(name string, size int) *peSection {
|
|||
off := f.stringTable.add(name)
|
||||
h := f.addSection(name, size, size)
|
||||
h.shortName = fmt.Sprintf("/%d", off)
|
||||
h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||
h.characteristics = IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||
return h
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -699,12 +699,18 @@ func (l *Loader) checkdup(name string, r *oReader, li uint32, dup Sym) {
|
|||
p := r.Data(li)
|
||||
rdup, ldup := l.toLocal(dup)
|
||||
pdup := rdup.Data(ldup)
|
||||
if bytes.Equal(p, pdup) {
|
||||
return
|
||||
}
|
||||
reason := "same length but different contents"
|
||||
if len(p) != len(pdup) {
|
||||
reason = fmt.Sprintf("new length %d != old length %d", len(p), len(pdup))
|
||||
} else if bytes.Equal(p, pdup) {
|
||||
// For BSS symbols, we need to check size as well, see issue 46653.
|
||||
szdup := l.SymSize(dup)
|
||||
sz := int64(r.Sym(li).Siz())
|
||||
if szdup == sz {
|
||||
return
|
||||
}
|
||||
reason = fmt.Sprintf("different sizes: new size %d != old size %d",
|
||||
sz, szdup)
|
||||
}
|
||||
fmt.Fprintf(os.Stderr, "cmd/link: while reading object for '%v': duplicate symbol '%s', previous def at '%v', with mismatched payload: %s\n", r.unit.Lib, name, rdup.unit.Lib, reason)
|
||||
|
||||
|
|
|
|||
|
|
@ -470,10 +470,30 @@ TEXT ·f(SB), NOSPLIT|DUPOK, $0-0
|
|||
JMP 0(PC)
|
||||
`
|
||||
|
||||
const testStrictDupAsmSrc3 = `
|
||||
#include "textflag.h"
|
||||
GLOBL ·rcon(SB), RODATA|DUPOK, $64
|
||||
`
|
||||
|
||||
const testStrictDupAsmSrc4 = `
|
||||
#include "textflag.h"
|
||||
GLOBL ·rcon(SB), RODATA|DUPOK, $32
|
||||
`
|
||||
|
||||
func TestStrictDup(t *testing.T) {
|
||||
// Check that -strictdups flag works.
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
||||
asmfiles := []struct {
|
||||
fname string
|
||||
payload string
|
||||
}{
|
||||
{"a", testStrictDupAsmSrc1},
|
||||
{"b", testStrictDupAsmSrc2},
|
||||
{"c", testStrictDupAsmSrc3},
|
||||
{"d", testStrictDupAsmSrc4},
|
||||
}
|
||||
|
||||
t.Parallel()
|
||||
|
||||
tmpdir := t.TempDir()
|
||||
|
|
@ -483,15 +503,12 @@ func TestStrictDup(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
src = filepath.Join(tmpdir, "a.s")
|
||||
err = ioutil.WriteFile(src, []byte(testStrictDupAsmSrc1), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
src = filepath.Join(tmpdir, "b.s")
|
||||
err = ioutil.WriteFile(src, []byte(testStrictDupAsmSrc2), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
for _, af := range asmfiles {
|
||||
src = filepath.Join(tmpdir, af.fname+".s")
|
||||
err = ioutil.WriteFile(src, []byte(af.payload), 0666)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
src = filepath.Join(tmpdir, "go.mod")
|
||||
err = ioutil.WriteFile(src, []byte("module teststrictdup\n"), 0666)
|
||||
|
|
@ -503,7 +520,7 @@ func TestStrictDup(t *testing.T) {
|
|||
cmd.Dir = tmpdir
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Errorf("linking with -strictdups=1 failed: %v", err)
|
||||
t.Errorf("linking with -strictdups=1 failed: %v\n%s", err, string(out))
|
||||
}
|
||||
if !bytes.Contains(out, []byte("mismatched payload")) {
|
||||
t.Errorf("unexpected output:\n%s", out)
|
||||
|
|
@ -515,7 +532,11 @@ func TestStrictDup(t *testing.T) {
|
|||
if err == nil {
|
||||
t.Errorf("linking with -strictdups=2 did not fail")
|
||||
}
|
||||
if !bytes.Contains(out, []byte("mismatched payload")) {
|
||||
// NB: on amd64 we get the 'new length' error, on arm64 the 'different
|
||||
// contents' error.
|
||||
if !(bytes.Contains(out, []byte("mismatched payload: new length")) ||
|
||||
bytes.Contains(out, []byte("mismatched payload: same length but different contents"))) ||
|
||||
!bytes.Contains(out, []byte("mismatched payload: different sizes")) {
|
||||
t.Errorf("unexpected output:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -233,8 +233,8 @@ func (f *file) Name() string {
|
|||
}
|
||||
|
||||
func (f *file) ObjAddr(addr uint64) (uint64, error) {
|
||||
// No support for shared libraries.
|
||||
return 0, nil
|
||||
// No support for shared libraries, so translation is a no-op.
|
||||
return addr, nil
|
||||
}
|
||||
|
||||
func (f *file) BuildID() string {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,127 @@
|
|||
// 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
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/testenv"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var tmp, pprofExe string // populated by buildPprof
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
if !testenv.HasGoBuild() {
|
||||
return
|
||||
}
|
||||
|
||||
var exitcode int
|
||||
if err := buildPprof(); err == nil {
|
||||
exitcode = m.Run()
|
||||
} else {
|
||||
fmt.Println(err)
|
||||
exitcode = 1
|
||||
}
|
||||
os.RemoveAll(tmp)
|
||||
os.Exit(exitcode)
|
||||
}
|
||||
|
||||
func buildPprof() error {
|
||||
var err error
|
||||
tmp, err = os.MkdirTemp("", "TestPprof")
|
||||
if err != nil {
|
||||
return fmt.Errorf("TempDir failed: %v", err)
|
||||
}
|
||||
|
||||
pprofExe = filepath.Join(tmp, "testpprof.exe")
|
||||
gotool, err := testenv.GoTool()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out, err := exec.Command(gotool, "build", "-o", pprofExe, "cmd/pprof").CombinedOutput()
|
||||
if err != nil {
|
||||
os.RemoveAll(tmp)
|
||||
return fmt.Errorf("go build -o %v cmd/pprof: %v\n%s", pprofExe, err, string(out))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// See also runtime/pprof.cpuProfilingBroken.
|
||||
func mustHaveCPUProfiling(t *testing.T) {
|
||||
switch runtime.GOOS {
|
||||
case "plan9":
|
||||
t.Skipf("skipping on %s, unimplemented", runtime.GOOS)
|
||||
case "aix":
|
||||
t.Skipf("skipping on %s, issue 45170", runtime.GOOS)
|
||||
case "ios", "dragonfly", "netbsd", "illumos", "solaris":
|
||||
t.Skipf("skipping on %s, issue 13841", runtime.GOOS)
|
||||
case "openbsd":
|
||||
if runtime.GOARCH == "arm" || runtime.GOARCH == "arm64" {
|
||||
t.Skipf("skipping on %s/%s, issue 13841", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mustHaveDisasm(t *testing.T) {
|
||||
switch runtime.GOARCH {
|
||||
case "mips", "mipsle", "mips64", "mips64le":
|
||||
t.Skipf("skipping on %s, issue 12559", runtime.GOARCH)
|
||||
case "riscv64":
|
||||
t.Skipf("skipping on %s, issue 36738", runtime.GOARCH)
|
||||
case "s390x":
|
||||
t.Skipf("skipping on %s, issue 15255", runtime.GOARCH)
|
||||
}
|
||||
|
||||
// Skip PIE platforms, pprof can't disassemble PIE.
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skipf("skipping on %s, issue 46639", runtime.GOOS)
|
||||
}
|
||||
if runtime.GOOS == "darwin" && runtime.GOARCH == "arm64" {
|
||||
t.Skipf("skipping on %s/%s, issue 46639", runtime.GOOS, runtime.GOARCH)
|
||||
}
|
||||
}
|
||||
|
||||
// TestDisasm verifies that cmd/pprof can successfully disassemble functions.
|
||||
//
|
||||
// This is a regression test for issue 46636.
|
||||
func TestDisasm(t *testing.T) {
|
||||
mustHaveCPUProfiling(t)
|
||||
mustHaveDisasm(t)
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
||||
tmpdir := t.TempDir()
|
||||
cpuExe := filepath.Join(tmpdir, "cpu.exe")
|
||||
cmd := exec.Command(testenv.GoToolPath(t), "build", "-o", cpuExe, "cpu.go")
|
||||
cmd.Dir = "testdata/"
|
||||
out, err := cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("build failed: %v\n%s", err, out)
|
||||
}
|
||||
|
||||
profile := filepath.Join(tmpdir, "cpu.pprof")
|
||||
cmd = exec.Command(cpuExe, "-output", profile)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("cpu failed: %v\n%s", err, out)
|
||||
}
|
||||
|
||||
cmd = exec.Command(pprofExe, "-disasm", "main.main", cpuExe, profile)
|
||||
out, err = cmd.CombinedOutput()
|
||||
if err != nil {
|
||||
t.Fatalf("pprof failed: %v\n%s", err, out)
|
||||
}
|
||||
|
||||
sout := string(out)
|
||||
want := "ROUTINE ======================== main.main"
|
||||
if !strings.Contains(sout, want) {
|
||||
t.Errorf("pprof disasm got %s want contains %q", sout, want)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
// 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
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"os"
|
||||
"runtime/pprof"
|
||||
"time"
|
||||
)
|
||||
|
||||
var output = flag.String("output", "", "pprof profile output file")
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if *output == "" {
|
||||
fmt.Fprintf(os.Stderr, "usage: %s -output file.pprof\n", os.Args[0])
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
f, err := os.Create(*output)
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
if err := pprof.StartCPUProfile(f); err != nil {
|
||||
fmt.Fprintln(os.Stderr, err)
|
||||
os.Exit(2)
|
||||
}
|
||||
defer pprof.StopCPUProfile()
|
||||
|
||||
// Spin for long enough to collect some samples.
|
||||
start := time.Now()
|
||||
for time.Since(start) < time.Second {
|
||||
}
|
||||
}
|
||||
|
|
@ -194,12 +194,15 @@ func (x *FileSyntax) updateLine(line *Line, tokens ...string) {
|
|||
line.Token = tokens
|
||||
}
|
||||
|
||||
func (x *FileSyntax) removeLine(line *Line) {
|
||||
// markRemoved modifies line so that it (and its end-of-line comment, if any)
|
||||
// will be dropped by (*FileSyntax).Cleanup.
|
||||
func (line *Line) markRemoved() {
|
||||
line.Token = nil
|
||||
line.Comments.Suffix = nil
|
||||
}
|
||||
|
||||
// Cleanup cleans up the file syntax x after any edit operations.
|
||||
// To avoid quadratic behavior, removeLine marks the line as dead
|
||||
// To avoid quadratic behavior, (*Line).markRemoved marks the line as dead
|
||||
// by setting line.Token = nil but does not remove it from the slice
|
||||
// in which it appears. After edits have all been indicated,
|
||||
// calling Cleanup cleans out the dead lines.
|
||||
|
|
|
|||
|
|
@ -58,13 +58,6 @@ type Go struct {
|
|||
Syntax *Line
|
||||
}
|
||||
|
||||
// A Require is a single require statement.
|
||||
type Require struct {
|
||||
Mod module.Version
|
||||
Indirect bool // has "// indirect" comment
|
||||
Syntax *Line
|
||||
}
|
||||
|
||||
// An Exclude is a single exclude statement.
|
||||
type Exclude struct {
|
||||
Mod module.Version
|
||||
|
|
@ -93,6 +86,93 @@ type VersionInterval struct {
|
|||
Low, High string
|
||||
}
|
||||
|
||||
// A Require is a single require statement.
|
||||
type Require struct {
|
||||
Mod module.Version
|
||||
Indirect bool // has "// indirect" comment
|
||||
Syntax *Line
|
||||
}
|
||||
|
||||
func (r *Require) markRemoved() {
|
||||
r.Syntax.markRemoved()
|
||||
*r = Require{}
|
||||
}
|
||||
|
||||
func (r *Require) setVersion(v string) {
|
||||
r.Mod.Version = v
|
||||
|
||||
if line := r.Syntax; len(line.Token) > 0 {
|
||||
if line.InBlock {
|
||||
// If the line is preceded by an empty line, remove it; see
|
||||
// https://golang.org/issue/33779.
|
||||
if len(line.Comments.Before) == 1 && len(line.Comments.Before[0].Token) == 0 {
|
||||
line.Comments.Before = line.Comments.Before[:0]
|
||||
}
|
||||
if len(line.Token) >= 2 { // example.com v1.2.3
|
||||
line.Token[1] = v
|
||||
}
|
||||
} else {
|
||||
if len(line.Token) >= 3 { // require example.com v1.2.3
|
||||
line.Token[2] = v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// setIndirect sets line to have (or not have) a "// indirect" comment.
|
||||
func (r *Require) setIndirect(indirect bool) {
|
||||
r.Indirect = indirect
|
||||
line := r.Syntax
|
||||
if isIndirect(line) == indirect {
|
||||
return
|
||||
}
|
||||
if indirect {
|
||||
// Adding comment.
|
||||
if len(line.Suffix) == 0 {
|
||||
// New comment.
|
||||
line.Suffix = []Comment{{Token: "// indirect", Suffix: true}}
|
||||
return
|
||||
}
|
||||
|
||||
com := &line.Suffix[0]
|
||||
text := strings.TrimSpace(strings.TrimPrefix(com.Token, string(slashSlash)))
|
||||
if text == "" {
|
||||
// Empty comment.
|
||||
com.Token = "// indirect"
|
||||
return
|
||||
}
|
||||
|
||||
// Insert at beginning of existing comment.
|
||||
com.Token = "// indirect; " + text
|
||||
return
|
||||
}
|
||||
|
||||
// Removing comment.
|
||||
f := strings.TrimSpace(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash)))
|
||||
if f == "indirect" {
|
||||
// Remove whole comment.
|
||||
line.Suffix = nil
|
||||
return
|
||||
}
|
||||
|
||||
// Remove comment prefix.
|
||||
com := &line.Suffix[0]
|
||||
i := strings.Index(com.Token, "indirect;")
|
||||
com.Token = "//" + com.Token[i+len("indirect;"):]
|
||||
}
|
||||
|
||||
// isIndirect reports whether line has a "// indirect" comment,
|
||||
// meaning it is in go.mod only for its effect on indirect dependencies,
|
||||
// so that it can be dropped entirely once the effective version of the
|
||||
// indirect dependency reaches the given minimum version.
|
||||
func isIndirect(line *Line) bool {
|
||||
if len(line.Suffix) == 0 {
|
||||
return false
|
||||
}
|
||||
f := strings.Fields(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash)))
|
||||
return (len(f) == 1 && f[0] == "indirect" || len(f) > 1 && f[0] == "indirect;")
|
||||
}
|
||||
|
||||
func (f *File) AddModuleStmt(path string) error {
|
||||
if f.Syntax == nil {
|
||||
f.Syntax = new(FileSyntax)
|
||||
|
|
@ -476,58 +556,6 @@ func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) {
|
|||
}
|
||||
}
|
||||
|
||||
// isIndirect reports whether line has a "// indirect" comment,
|
||||
// meaning it is in go.mod only for its effect on indirect dependencies,
|
||||
// so that it can be dropped entirely once the effective version of the
|
||||
// indirect dependency reaches the given minimum version.
|
||||
func isIndirect(line *Line) bool {
|
||||
if len(line.Suffix) == 0 {
|
||||
return false
|
||||
}
|
||||
f := strings.Fields(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash)))
|
||||
return (len(f) == 1 && f[0] == "indirect" || len(f) > 1 && f[0] == "indirect;")
|
||||
}
|
||||
|
||||
// setIndirect sets line to have (or not have) a "// indirect" comment.
|
||||
func setIndirect(line *Line, indirect bool) {
|
||||
if isIndirect(line) == indirect {
|
||||
return
|
||||
}
|
||||
if indirect {
|
||||
// Adding comment.
|
||||
if len(line.Suffix) == 0 {
|
||||
// New comment.
|
||||
line.Suffix = []Comment{{Token: "// indirect", Suffix: true}}
|
||||
return
|
||||
}
|
||||
|
||||
com := &line.Suffix[0]
|
||||
text := strings.TrimSpace(strings.TrimPrefix(com.Token, string(slashSlash)))
|
||||
if text == "" {
|
||||
// Empty comment.
|
||||
com.Token = "// indirect"
|
||||
return
|
||||
}
|
||||
|
||||
// Insert at beginning of existing comment.
|
||||
com.Token = "// indirect; " + text
|
||||
return
|
||||
}
|
||||
|
||||
// Removing comment.
|
||||
f := strings.TrimSpace(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash)))
|
||||
if f == "indirect" {
|
||||
// Remove whole comment.
|
||||
line.Suffix = nil
|
||||
return
|
||||
}
|
||||
|
||||
// Remove comment prefix.
|
||||
com := &line.Suffix[0]
|
||||
i := strings.Index(com.Token, "indirect;")
|
||||
com.Token = "//" + com.Token[i+len("indirect;"):]
|
||||
}
|
||||
|
||||
// IsDirectoryPath reports whether the given path should be interpreted
|
||||
// as a directory path. Just like on the go command line, relative paths
|
||||
// and rooted paths are directory paths; the rest are module paths.
|
||||
|
|
@ -835,6 +863,12 @@ func (f *File) AddGoStmt(version string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// AddRequire sets the first require line for path to version vers,
|
||||
// preserving any existing comments for that line and removing all
|
||||
// other lines for path.
|
||||
//
|
||||
// If no line currently exists for path, AddRequire adds a new line
|
||||
// at the end of the last require block.
|
||||
func (f *File) AddRequire(path, vers string) error {
|
||||
need := true
|
||||
for _, r := range f.Require {
|
||||
|
|
@ -844,7 +878,7 @@ func (f *File) AddRequire(path, vers string) error {
|
|||
f.Syntax.updateLine(r.Syntax, "require", AutoQuote(path), vers)
|
||||
need = false
|
||||
} else {
|
||||
f.Syntax.removeLine(r.Syntax)
|
||||
r.Syntax.markRemoved()
|
||||
*r = Require{}
|
||||
}
|
||||
}
|
||||
|
|
@ -856,69 +890,235 @@ func (f *File) AddRequire(path, vers string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// AddNewRequire adds a new require line for path at version vers at the end of
|
||||
// the last require block, regardless of any existing require lines for path.
|
||||
func (f *File) AddNewRequire(path, vers string, indirect bool) {
|
||||
line := f.Syntax.addLine(nil, "require", AutoQuote(path), vers)
|
||||
setIndirect(line, indirect)
|
||||
f.Require = append(f.Require, &Require{module.Version{Path: path, Version: vers}, indirect, line})
|
||||
r := &Require{
|
||||
Mod: module.Version{Path: path, Version: vers},
|
||||
Syntax: line,
|
||||
}
|
||||
r.setIndirect(indirect)
|
||||
f.Require = append(f.Require, r)
|
||||
}
|
||||
|
||||
// SetRequire updates the requirements of f to contain exactly req, preserving
|
||||
// the existing block structure and line comment contents (except for 'indirect'
|
||||
// markings) for the first requirement on each named module path.
|
||||
//
|
||||
// The Syntax field is ignored for the requirements in req.
|
||||
//
|
||||
// Any requirements not already present in the file are added to the block
|
||||
// containing the last require line.
|
||||
//
|
||||
// The requirements in req must specify at most one distinct version for each
|
||||
// module path.
|
||||
//
|
||||
// If any existing requirements may be removed, the caller should call Cleanup
|
||||
// after all edits are complete.
|
||||
func (f *File) SetRequire(req []*Require) {
|
||||
need := make(map[string]string)
|
||||
indirect := make(map[string]bool)
|
||||
type elem struct {
|
||||
version string
|
||||
indirect bool
|
||||
}
|
||||
need := make(map[string]elem)
|
||||
for _, r := range req {
|
||||
need[r.Mod.Path] = r.Mod.Version
|
||||
indirect[r.Mod.Path] = r.Indirect
|
||||
}
|
||||
|
||||
for _, r := range f.Require {
|
||||
if v, ok := need[r.Mod.Path]; ok {
|
||||
r.Mod.Version = v
|
||||
r.Indirect = indirect[r.Mod.Path]
|
||||
} else {
|
||||
*r = Require{}
|
||||
if prev, dup := need[r.Mod.Path]; dup && prev.version != r.Mod.Version {
|
||||
panic(fmt.Errorf("SetRequire called with conflicting versions for path %s (%s and %s)", r.Mod.Path, prev.version, r.Mod.Version))
|
||||
}
|
||||
need[r.Mod.Path] = elem{r.Mod.Version, r.Indirect}
|
||||
}
|
||||
|
||||
var newStmts []Expr
|
||||
// Update or delete the existing Require entries to preserve
|
||||
// only the first for each module path in req.
|
||||
for _, r := range f.Require {
|
||||
e, ok := need[r.Mod.Path]
|
||||
if ok {
|
||||
r.setVersion(e.version)
|
||||
r.setIndirect(e.indirect)
|
||||
} else {
|
||||
r.markRemoved()
|
||||
}
|
||||
delete(need, r.Mod.Path)
|
||||
}
|
||||
|
||||
// Add new entries in the last block of the file for any paths that weren't
|
||||
// already present.
|
||||
//
|
||||
// This step is nondeterministic, but the final result will be deterministic
|
||||
// because we will sort the block.
|
||||
for path, e := range need {
|
||||
f.AddNewRequire(path, e.version, e.indirect)
|
||||
}
|
||||
|
||||
f.SortBlocks()
|
||||
}
|
||||
|
||||
// SetRequireSeparateIndirect updates the requirements of f to contain the given
|
||||
// requirements. Comment contents (except for 'indirect' markings) are retained
|
||||
// from the first existing requirement for each module path, and block structure
|
||||
// is maintained as long as the indirect markings match.
|
||||
//
|
||||
// Any requirements on paths not already present in the file are added. Direct
|
||||
// requirements are added to the last block containing *any* other direct
|
||||
// requirement. Indirect requirements are added to the last block containing
|
||||
// *only* other indirect requirements. If no suitable block exists, a new one is
|
||||
// added, with the last block containing a direct dependency (if any)
|
||||
// immediately before the first block containing only indirect dependencies.
|
||||
//
|
||||
// The Syntax field is ignored for requirements in the given blocks.
|
||||
func (f *File) SetRequireSeparateIndirect(req []*Require) {
|
||||
type modKey struct {
|
||||
path string
|
||||
indirect bool
|
||||
}
|
||||
need := make(map[modKey]string)
|
||||
for _, r := range req {
|
||||
need[modKey{r.Mod.Path, r.Indirect}] = r.Mod.Version
|
||||
}
|
||||
|
||||
comments := make(map[string]Comments)
|
||||
for _, r := range f.Require {
|
||||
v, ok := need[modKey{r.Mod.Path, r.Indirect}]
|
||||
if !ok {
|
||||
if _, ok := need[modKey{r.Mod.Path, !r.Indirect}]; ok {
|
||||
if _, dup := comments[r.Mod.Path]; !dup {
|
||||
comments[r.Mod.Path] = r.Syntax.Comments
|
||||
}
|
||||
}
|
||||
r.markRemoved()
|
||||
continue
|
||||
}
|
||||
r.setVersion(v)
|
||||
delete(need, modKey{r.Mod.Path, r.Indirect})
|
||||
}
|
||||
|
||||
var (
|
||||
lastDirectOrMixedBlock Expr
|
||||
firstIndirectOnlyBlock Expr
|
||||
lastIndirectOnlyBlock Expr
|
||||
)
|
||||
for _, stmt := range f.Syntax.Stmt {
|
||||
switch stmt := stmt.(type) {
|
||||
case *LineBlock:
|
||||
if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
|
||||
var newLines []*Line
|
||||
for _, line := range stmt.Line {
|
||||
if p, err := parseString(&line.Token[0]); err == nil && need[p] != "" {
|
||||
if len(line.Comments.Before) == 1 && len(line.Comments.Before[0].Token) == 0 {
|
||||
line.Comments.Before = line.Comments.Before[:0]
|
||||
}
|
||||
line.Token[1] = need[p]
|
||||
delete(need, p)
|
||||
setIndirect(line, indirect[p])
|
||||
newLines = append(newLines, line)
|
||||
}
|
||||
}
|
||||
if len(newLines) == 0 {
|
||||
continue // drop stmt
|
||||
}
|
||||
stmt.Line = newLines
|
||||
}
|
||||
|
||||
case *Line:
|
||||
if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
|
||||
if p, err := parseString(&stmt.Token[1]); err == nil && need[p] != "" {
|
||||
stmt.Token[2] = need[p]
|
||||
delete(need, p)
|
||||
setIndirect(stmt, indirect[p])
|
||||
} else {
|
||||
continue // drop stmt
|
||||
if len(stmt.Token) == 0 || stmt.Token[0] != "require" {
|
||||
continue
|
||||
}
|
||||
if isIndirect(stmt) {
|
||||
lastIndirectOnlyBlock = stmt
|
||||
} else {
|
||||
lastDirectOrMixedBlock = stmt
|
||||
}
|
||||
case *LineBlock:
|
||||
if len(stmt.Token) == 0 || stmt.Token[0] != "require" {
|
||||
continue
|
||||
}
|
||||
indirectOnly := true
|
||||
for _, line := range stmt.Line {
|
||||
if len(line.Token) == 0 {
|
||||
continue
|
||||
}
|
||||
if !isIndirect(line) {
|
||||
indirectOnly = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if indirectOnly {
|
||||
lastIndirectOnlyBlock = stmt
|
||||
if firstIndirectOnlyBlock == nil {
|
||||
firstIndirectOnlyBlock = stmt
|
||||
}
|
||||
} else {
|
||||
lastDirectOrMixedBlock = stmt
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
isOrContainsStmt := func(stmt Expr, target Expr) bool {
|
||||
if stmt == target {
|
||||
return true
|
||||
}
|
||||
if stmt, ok := stmt.(*LineBlock); ok {
|
||||
if target, ok := target.(*Line); ok {
|
||||
for _, line := range stmt.Line {
|
||||
if line == target {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
newStmts = append(newStmts, stmt)
|
||||
return false
|
||||
}
|
||||
f.Syntax.Stmt = newStmts
|
||||
|
||||
for path, vers := range need {
|
||||
f.AddNewRequire(path, vers, indirect[path])
|
||||
addRequire := func(path, vers string, indirect bool, comments Comments) {
|
||||
var line *Line
|
||||
if indirect {
|
||||
if lastIndirectOnlyBlock != nil {
|
||||
line = f.Syntax.addLine(lastIndirectOnlyBlock, "require", path, vers)
|
||||
} else {
|
||||
// Add a new require block after the last direct-only or mixed "require"
|
||||
// block (if any).
|
||||
//
|
||||
// (f.Syntax.addLine would add the line to an existing "require" block if
|
||||
// present, but here the existing "require" blocks are all direct-only, so
|
||||
// we know we need to add a new block instead.)
|
||||
line = &Line{Token: []string{"require", path, vers}}
|
||||
lastIndirectOnlyBlock = line
|
||||
firstIndirectOnlyBlock = line // only block implies first block
|
||||
if lastDirectOrMixedBlock == nil {
|
||||
f.Syntax.Stmt = append(f.Syntax.Stmt, line)
|
||||
} else {
|
||||
for i, stmt := range f.Syntax.Stmt {
|
||||
if isOrContainsStmt(stmt, lastDirectOrMixedBlock) {
|
||||
f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size
|
||||
copy(f.Syntax.Stmt[i+2:], f.Syntax.Stmt[i+1:]) // shuffle elements up
|
||||
f.Syntax.Stmt[i+1] = line
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if lastDirectOrMixedBlock != nil {
|
||||
line = f.Syntax.addLine(lastDirectOrMixedBlock, "require", path, vers)
|
||||
} else {
|
||||
// Add a new require block before the first indirect block (if any).
|
||||
//
|
||||
// That way if the file initially contains only indirect lines,
|
||||
// the direct lines still appear before it: we preserve existing
|
||||
// structure, but only to the extent that that structure already
|
||||
// reflects the direct/indirect split.
|
||||
line = &Line{Token: []string{"require", path, vers}}
|
||||
lastDirectOrMixedBlock = line
|
||||
if firstIndirectOnlyBlock == nil {
|
||||
f.Syntax.Stmt = append(f.Syntax.Stmt, line)
|
||||
} else {
|
||||
for i, stmt := range f.Syntax.Stmt {
|
||||
if isOrContainsStmt(stmt, firstIndirectOnlyBlock) {
|
||||
f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size
|
||||
copy(f.Syntax.Stmt[i+1:], f.Syntax.Stmt[i:]) // shuffle elements up
|
||||
f.Syntax.Stmt[i] = line
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
line.Comments.Before = commentsAdd(line.Comments.Before, comments.Before)
|
||||
line.Comments.Suffix = commentsAdd(line.Comments.Suffix, comments.Suffix)
|
||||
|
||||
r := &Require{
|
||||
Mod: module.Version{Path: path, Version: vers},
|
||||
Indirect: indirect,
|
||||
Syntax: line,
|
||||
}
|
||||
r.setIndirect(indirect)
|
||||
f.Require = append(f.Require, r)
|
||||
}
|
||||
|
||||
for k, vers := range need {
|
||||
addRequire(k.path, vers, k.indirect, comments[k.path])
|
||||
}
|
||||
f.SortBlocks()
|
||||
}
|
||||
|
|
@ -926,7 +1126,7 @@ func (f *File) SetRequire(req []*Require) {
|
|||
func (f *File) DropRequire(path string) error {
|
||||
for _, r := range f.Require {
|
||||
if r.Mod.Path == path {
|
||||
f.Syntax.removeLine(r.Syntax)
|
||||
r.Syntax.markRemoved()
|
||||
*r = Require{}
|
||||
}
|
||||
}
|
||||
|
|
@ -957,7 +1157,7 @@ func (f *File) AddExclude(path, vers string) error {
|
|||
func (f *File) DropExclude(path, vers string) error {
|
||||
for _, x := range f.Exclude {
|
||||
if x.Mod.Path == path && x.Mod.Version == vers {
|
||||
f.Syntax.removeLine(x.Syntax)
|
||||
x.Syntax.markRemoved()
|
||||
*x = Exclude{}
|
||||
}
|
||||
}
|
||||
|
|
@ -988,7 +1188,7 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error {
|
|||
continue
|
||||
}
|
||||
// Already added; delete other replacements for same.
|
||||
f.Syntax.removeLine(r.Syntax)
|
||||
r.Syntax.markRemoved()
|
||||
*r = Replace{}
|
||||
}
|
||||
if r.Old.Path == oldPath {
|
||||
|
|
@ -1004,7 +1204,7 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error {
|
|||
func (f *File) DropReplace(oldPath, oldVers string) error {
|
||||
for _, r := range f.Replace {
|
||||
if r.Old.Path == oldPath && r.Old.Version == oldVers {
|
||||
f.Syntax.removeLine(r.Syntax)
|
||||
r.Syntax.markRemoved()
|
||||
*r = Replace{}
|
||||
}
|
||||
}
|
||||
|
|
@ -1045,7 +1245,7 @@ func (f *File) AddRetract(vi VersionInterval, rationale string) error {
|
|||
func (f *File) DropRetract(vi VersionInterval) error {
|
||||
for _, r := range f.Retract {
|
||||
if r.VersionInterval == vi {
|
||||
f.Syntax.removeLine(r.Syntax)
|
||||
r.Syntax.markRemoved()
|
||||
*r = Retract{}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ golang.org/x/arch/x86/x86asm
|
|||
## explicit; go 1.17
|
||||
golang.org/x/crypto/ed25519
|
||||
golang.org/x/crypto/ed25519/internal/edwards25519
|
||||
# golang.org/x/mod v0.4.3-0.20210512182355-6088ed88cecd
|
||||
# golang.org/x/mod v0.4.3-0.20210608190319-0f08993efd8a
|
||||
## explicit; go 1.17
|
||||
golang.org/x/mod/internal/lazyregexp
|
||||
golang.org/x/mod/modfile
|
||||
|
|
|
|||
|
|
@ -455,7 +455,7 @@ func initP384() {
|
|||
// Multiple invocations of this function will return the same value, so it can
|
||||
// be used for equality checks and switch statements.
|
||||
//
|
||||
// The cryptographic operations are implemented using constant-time algorithms.
|
||||
// ScalarMult and ScalarBaseMult are implemented using constant-time algorithms.
|
||||
func P256() Curve {
|
||||
initonce.Do(initAll)
|
||||
return p256
|
||||
|
|
@ -479,7 +479,7 @@ func P384() Curve {
|
|||
// Multiple invocations of this function will return the same value, so it can
|
||||
// be used for equality checks and switch statements.
|
||||
//
|
||||
// The cryptographic operations do not use constant-time algorithms.
|
||||
// The cryptographic operations are implemented using constant-time algorithms.
|
||||
func P521() Curve {
|
||||
initonce.Do(initAll)
|
||||
return p521
|
||||
|
|
|
|||
|
|
@ -619,7 +619,7 @@ type Config struct {
|
|||
// protocol will be one from this list, and the connection will fail
|
||||
// if there is no mutually supported protocol. If NextProtos is empty
|
||||
// or the peer doesn't support ALPN, the connection will succeed and
|
||||
// ConnectionState.NegotiatedProtocol will be empty."
|
||||
// ConnectionState.NegotiatedProtocol will be empty.
|
||||
NextProtos []string
|
||||
|
||||
// ServerName is used to verify the hostname on the returned
|
||||
|
|
|
|||
|
|
@ -711,17 +711,11 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
|
|||
}
|
||||
}
|
||||
|
||||
if hs.serverHello.alpnProtocol != "" {
|
||||
if len(hs.hello.alpnProtocols) == 0 {
|
||||
c.sendAlert(alertUnsupportedExtension)
|
||||
return false, errors.New("tls: server advertised unrequested ALPN extension")
|
||||
}
|
||||
if mutualProtocol([]string{hs.serverHello.alpnProtocol}, hs.hello.alpnProtocols) == "" {
|
||||
c.sendAlert(alertUnsupportedExtension)
|
||||
return false, errors.New("tls: server selected unadvertised ALPN protocol")
|
||||
}
|
||||
c.clientProtocol = hs.serverHello.alpnProtocol
|
||||
if err := checkALPN(hs.hello.alpnProtocols, hs.serverHello.alpnProtocol); err != nil {
|
||||
c.sendAlert(alertUnsupportedExtension)
|
||||
return false, err
|
||||
}
|
||||
c.clientProtocol = hs.serverHello.alpnProtocol
|
||||
|
||||
c.scts = hs.serverHello.scts
|
||||
|
||||
|
|
@ -753,6 +747,23 @@ func (hs *clientHandshakeState) processServerHello() (bool, error) {
|
|||
return true, nil
|
||||
}
|
||||
|
||||
// checkALPN ensure that the server's choice of ALPN protocol is compatible with
|
||||
// the protocols that we advertised in the Client Hello.
|
||||
func checkALPN(clientProtos []string, serverProto string) error {
|
||||
if serverProto == "" {
|
||||
return nil
|
||||
}
|
||||
if len(clientProtos) == 0 {
|
||||
return errors.New("tls: server advertised unrequested ALPN extension")
|
||||
}
|
||||
for _, proto := range clientProtos {
|
||||
if proto == serverProto {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("tls: server selected unadvertised ALPN protocol")
|
||||
}
|
||||
|
||||
func (hs *clientHandshakeState) readFinished(out []byte) error {
|
||||
c := hs.c
|
||||
|
||||
|
|
@ -979,19 +990,6 @@ func clientSessionCacheKey(serverAddr net.Addr, config *Config) string {
|
|||
return serverAddr.String()
|
||||
}
|
||||
|
||||
// mutualProtocol finds the mutual ALPN protocol given list of possible
|
||||
// protocols and a list of the preference order.
|
||||
func mutualProtocol(protos, preferenceProtos []string) string {
|
||||
for _, s := range preferenceProtos {
|
||||
for _, c := range protos {
|
||||
if s == c {
|
||||
return s
|
||||
}
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// hostnameInSNI converts name into an appropriate hostname for SNI.
|
||||
// Literal IP addresses and absolute FQDNs are not permitted as SNI values.
|
||||
// See RFC 6066, Section 3.
|
||||
|
|
|
|||
|
|
@ -396,17 +396,11 @@ func (hs *clientHandshakeStateTLS13) readServerParameters() error {
|
|||
}
|
||||
hs.transcript.Write(encryptedExtensions.marshal())
|
||||
|
||||
if encryptedExtensions.alpnProtocol != "" {
|
||||
if len(hs.hello.alpnProtocols) == 0 {
|
||||
c.sendAlert(alertUnsupportedExtension)
|
||||
return errors.New("tls: server advertised unrequested ALPN extension")
|
||||
}
|
||||
if mutualProtocol([]string{encryptedExtensions.alpnProtocol}, hs.hello.alpnProtocols) == "" {
|
||||
c.sendAlert(alertUnsupportedExtension)
|
||||
return errors.New("tls: server selected unadvertised ALPN protocol")
|
||||
}
|
||||
c.clientProtocol = encryptedExtensions.alpnProtocol
|
||||
if err := checkALPN(hs.hello.alpnProtocols, encryptedExtensions.alpnProtocol); err != nil {
|
||||
c.sendAlert(alertUnsupportedExtension)
|
||||
return err
|
||||
}
|
||||
c.clientProtocol = encryptedExtensions.alpnProtocol
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -217,15 +217,13 @@ func (hs *serverHandshakeState) processClientHello() error {
|
|||
c.serverName = hs.clientHello.serverName
|
||||
}
|
||||
|
||||
if len(c.config.NextProtos) > 0 && len(hs.clientHello.alpnProtocols) > 0 {
|
||||
selectedProto := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos)
|
||||
if selectedProto == "" {
|
||||
c.sendAlert(alertNoApplicationProtocol)
|
||||
return fmt.Errorf("tls: client requested unsupported application protocols (%s)", hs.clientHello.alpnProtocols)
|
||||
}
|
||||
hs.hello.alpnProtocol = selectedProto
|
||||
c.clientProtocol = selectedProto
|
||||
selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols)
|
||||
if err != nil {
|
||||
c.sendAlert(alertNoApplicationProtocol)
|
||||
return err
|
||||
}
|
||||
hs.hello.alpnProtocol = selectedProto
|
||||
c.clientProtocol = selectedProto
|
||||
|
||||
hs.cert, err = c.config.getCertificate(clientHelloInfo(hs.ctx, c, hs.clientHello))
|
||||
if err != nil {
|
||||
|
|
@ -277,6 +275,34 @@ func (hs *serverHandshakeState) processClientHello() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// negotiateALPN picks a shared ALPN protocol that both sides support in server
|
||||
// preference order. If ALPN is not configured or the peer doesn't support it,
|
||||
// it returns "" and no error.
|
||||
func negotiateALPN(serverProtos, clientProtos []string) (string, error) {
|
||||
if len(serverProtos) == 0 || len(clientProtos) == 0 {
|
||||
return "", nil
|
||||
}
|
||||
var http11fallback bool
|
||||
for _, s := range serverProtos {
|
||||
for _, c := range clientProtos {
|
||||
if s == c {
|
||||
return s, nil
|
||||
}
|
||||
if s == "h2" && c == "http/1.1" {
|
||||
http11fallback = true
|
||||
}
|
||||
}
|
||||
}
|
||||
// As a special case, let http/1.1 clients connect to h2 servers as if they
|
||||
// didn't support ALPN. We used not to enforce protocol overlap, so over
|
||||
// time a number of HTTP servers were configured with only "h2", but
|
||||
// expected to accept connections from "http/1.1" clients. See Issue 46310.
|
||||
if http11fallback {
|
||||
return "", nil
|
||||
}
|
||||
return "", fmt.Errorf("tls: client requested unsupported application protocols (%s)", clientProtos)
|
||||
}
|
||||
|
||||
// supportsECDHE returns whether ECDHE key exchanges can be used with this
|
||||
// pre-TLS 1.3 client.
|
||||
func supportsECDHE(c *Config, supportedCurves []CurveID, supportedPoints []uint8) bool {
|
||||
|
|
|
|||
|
|
@ -949,6 +949,27 @@ func TestHandshakeServerALPNNotConfigured(t *testing.T) {
|
|||
runServerTestTLS13(t, test)
|
||||
}
|
||||
|
||||
func TestHandshakeServerALPNFallback(t *testing.T) {
|
||||
config := testConfig.Clone()
|
||||
config.NextProtos = []string{"proto1", "h2", "proto2"}
|
||||
|
||||
test := &serverTest{
|
||||
name: "ALPN-Fallback",
|
||||
// Note that this needs OpenSSL 1.0.2 because that is the first
|
||||
// version that supports the -alpn flag.
|
||||
command: []string{"openssl", "s_client", "-alpn", "proto3,http/1.1,proto4", "-cipher", "ECDHE-RSA-CHACHA20-POLY1305", "-ciphersuites", "TLS_CHACHA20_POLY1305_SHA256"},
|
||||
config: config,
|
||||
validate: func(state ConnectionState) error {
|
||||
if state.NegotiatedProtocol != "" {
|
||||
return fmt.Errorf("Got protocol %q, wanted nothing", state.NegotiatedProtocol)
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
runServerTestTLS12(t, test)
|
||||
runServerTestTLS13(t, test)
|
||||
}
|
||||
|
||||
// TestHandshakeServerSNI involves a client sending an SNI extension of
|
||||
// "snitest.com", which happens to match the CN of testSNICertificate. The test
|
||||
// verifies that the server correctly selects that certificate.
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@ import (
|
|||
"crypto/hmac"
|
||||
"crypto/rsa"
|
||||
"errors"
|
||||
"fmt"
|
||||
"hash"
|
||||
"io"
|
||||
"sync/atomic"
|
||||
|
|
@ -551,15 +550,13 @@ func (hs *serverHandshakeStateTLS13) sendServerParameters() error {
|
|||
|
||||
encryptedExtensions := new(encryptedExtensionsMsg)
|
||||
|
||||
if len(c.config.NextProtos) > 0 && len(hs.clientHello.alpnProtocols) > 0 {
|
||||
selectedProto := mutualProtocol(hs.clientHello.alpnProtocols, c.config.NextProtos)
|
||||
if selectedProto == "" {
|
||||
c.sendAlert(alertNoApplicationProtocol)
|
||||
return fmt.Errorf("tls: client requested unsupported application protocols (%s)", hs.clientHello.alpnProtocols)
|
||||
}
|
||||
encryptedExtensions.alpnProtocol = selectedProto
|
||||
c.clientProtocol = selectedProto
|
||||
selectedProto, err := negotiateALPN(c.config.NextProtos, hs.clientHello.alpnProtocols)
|
||||
if err != nil {
|
||||
c.sendAlert(alertNoApplicationProtocol)
|
||||
return err
|
||||
}
|
||||
encryptedExtensions.alpnProtocol = selectedProto
|
||||
c.clientProtocol = selectedProto
|
||||
|
||||
hs.transcript.Write(encryptedExtensions.marshal())
|
||||
if _, err := c.writeRecord(recordTypeHandshake, encryptedExtensions.marshal()); err != nil {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,91 @@
|
|||
>>> Flow 1 (client to server)
|
||||
00000000 16 03 01 00 a6 01 00 00 a2 03 03 b5 c9 ab 32 7f |..............2.|
|
||||
00000010 e1 af 3f f2 ac 2a 11 dd 33 f9 b5 21 88 0d e4 29 |..?..*..3..!...)|
|
||||
00000020 e2 47 49 dc c7 31 a8 a5 25 81 0c 00 00 04 cc a8 |.GI..1..%.......|
|
||||
00000030 00 ff 01 00 00 75 00 0b 00 04 03 00 01 02 00 0a |.....u..........|
|
||||
00000040 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#|
|
||||
00000050 00 00 00 10 00 19 00 17 06 70 72 6f 74 6f 33 08 |.........proto3.|
|
||||
00000060 68 74 74 70 2f 31 2e 31 06 70 72 6f 74 6f 34 00 |http/1.1.proto4.|
|
||||
00000070 16 00 00 00 17 00 00 00 0d 00 30 00 2e 04 03 05 |..........0.....|
|
||||
00000080 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 |................|
|
||||
00000090 05 08 06 04 01 05 01 06 01 03 03 02 03 03 01 02 |................|
|
||||
000000a0 01 03 02 02 02 04 02 05 02 06 02 |...........|
|
||||
>>> Flow 2 (server to client)
|
||||
00000000 16 03 03 00 3b 02 00 00 37 03 03 00 00 00 00 00 |....;...7.......|
|
||||
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
00000020 00 00 00 44 4f 57 4e 47 52 44 01 00 cc a8 00 00 |...DOWNGRD......|
|
||||
00000030 0f 00 23 00 00 ff 01 00 01 00 00 0b 00 02 01 00 |..#.............|
|
||||
00000040 16 03 03 02 59 0b 00 02 55 00 02 52 00 02 4f 30 |....Y...U..R..O0|
|
||||
00000050 82 02 4b 30 82 01 b4 a0 03 02 01 02 02 09 00 e8 |..K0............|
|
||||
00000060 f0 9d 3f e2 5b ea a6 30 0d 06 09 2a 86 48 86 f7 |..?.[..0...*.H..|
|
||||
00000070 0d 01 01 0b 05 00 30 1f 31 0b 30 09 06 03 55 04 |......0.1.0...U.|
|
||||
00000080 0a 13 02 47 6f 31 10 30 0e 06 03 55 04 03 13 07 |...Go1.0...U....|
|
||||
00000090 47 6f 20 52 6f 6f 74 30 1e 17 0d 31 36 30 31 30 |Go Root0...16010|
|
||||
000000a0 31 30 30 30 30 30 30 5a 17 0d 32 35 30 31 30 31 |1000000Z..250101|
|
||||
000000b0 30 30 30 30 30 30 5a 30 1a 31 0b 30 09 06 03 55 |000000Z0.1.0...U|
|
||||
000000c0 04 0a 13 02 47 6f 31 0b 30 09 06 03 55 04 03 13 |....Go1.0...U...|
|
||||
000000d0 02 47 6f 30 81 9f 30 0d 06 09 2a 86 48 86 f7 0d |.Go0..0...*.H...|
|
||||
000000e0 01 01 01 05 00 03 81 8d 00 30 81 89 02 81 81 00 |.........0......|
|
||||
000000f0 db 46 7d 93 2e 12 27 06 48 bc 06 28 21 ab 7e c4 |.F}...'.H..(!.~.|
|
||||
00000100 b6 a2 5d fe 1e 52 45 88 7a 36 47 a5 08 0d 92 42 |..]..RE.z6G....B|
|
||||
00000110 5b c2 81 c0 be 97 79 98 40 fb 4f 6d 14 fd 2b 13 |[.....y.@.Om..+.|
|
||||
00000120 8b c2 a5 2e 67 d8 d4 09 9e d6 22 38 b7 4a 0b 74 |....g....."8.J.t|
|
||||
00000130 73 2b c2 34 f1 d1 93 e5 96 d9 74 7b f3 58 9f 6c |s+.4......t{.X.l|
|
||||
00000140 61 3c c0 b0 41 d4 d9 2b 2b 24 23 77 5b 1c 3b bd |a<..A..++$#w[.;.|
|
||||
00000150 75 5d ce 20 54 cf a1 63 87 1d 1e 24 c4 f3 1d 1a |u]. T..c...$....|
|
||||
00000160 50 8b aa b6 14 43 ed 97 a7 75 62 f4 14 c8 52 d7 |P....C...ub...R.|
|
||||
00000170 02 03 01 00 01 a3 81 93 30 81 90 30 0e 06 03 55 |........0..0...U|
|
||||
00000180 1d 0f 01 01 ff 04 04 03 02 05 a0 30 1d 06 03 55 |...........0...U|
|
||||
00000190 1d 25 04 16 30 14 06 08 2b 06 01 05 05 07 03 01 |.%..0...+.......|
|
||||
000001a0 06 08 2b 06 01 05 05 07 03 02 30 0c 06 03 55 1d |..+.......0...U.|
|
||||
000001b0 13 01 01 ff 04 02 30 00 30 19 06 03 55 1d 0e 04 |......0.0...U...|
|
||||
000001c0 12 04 10 9f 91 16 1f 43 43 3e 49 a6 de 6d b6 80 |.......CC>I..m..|
|
||||
000001d0 d7 9f 60 30 1b 06 03 55 1d 23 04 14 30 12 80 10 |..`0...U.#..0...|
|
||||
000001e0 48 13 49 4d 13 7e 16 31 bb a3 01 d5 ac ab 6e 7b |H.IM.~.1......n{|
|
||||
000001f0 30 19 06 03 55 1d 11 04 12 30 10 82 0e 65 78 61 |0...U....0...exa|
|
||||
00000200 6d 70 6c 65 2e 67 6f 6c 61 6e 67 30 0d 06 09 2a |mple.golang0...*|
|
||||
00000210 86 48 86 f7 0d 01 01 0b 05 00 03 81 81 00 9d 30 |.H.............0|
|
||||
00000220 cc 40 2b 5b 50 a0 61 cb ba e5 53 58 e1 ed 83 28 |.@+[P.a...SX...(|
|
||||
00000230 a9 58 1a a9 38 a4 95 a1 ac 31 5a 1a 84 66 3d 43 |.X..8....1Z..f=C|
|
||||
00000240 d3 2d d9 0b f2 97 df d3 20 64 38 92 24 3a 00 bc |.-...... d8.$:..|
|
||||
00000250 cf 9c 7d b7 40 20 01 5f aa d3 16 61 09 a2 76 fd |..}.@ ._...a..v.|
|
||||
00000260 13 c3 cc e1 0c 5c ee b1 87 82 f1 6c 04 ed 73 bb |.....\.....l..s.|
|
||||
00000270 b3 43 77 8d 0c 1c f1 0f a1 d8 40 83 61 c9 4c 72 |.Cw.......@.a.Lr|
|
||||
00000280 2b 9d ae db 46 06 06 4d f4 c1 b3 3e c0 d1 bd 42 |+...F..M...>...B|
|
||||
00000290 d4 db fe 3d 13 60 84 5c 21 d3 3b e9 fa e7 16 03 |...=.`.\!.;.....|
|
||||
000002a0 03 00 ac 0c 00 00 a8 03 00 1d 20 2f e5 7d a3 47 |.......... /.}.G|
|
||||
000002b0 cd 62 43 15 28 da ac 5f bb 29 07 30 ff f6 84 af |.bC.(.._.).0....|
|
||||
000002c0 c4 cf c2 ed 90 99 5f 58 cb 3b 74 08 04 00 80 5f |......_X.;t...._|
|
||||
000002d0 37 27 84 58 1e ea 1e 40 1b de a9 8f 04 d4 94 64 |7'.X...@.......d|
|
||||
000002e0 4e 27 c7 f1 b3 30 d0 53 f5 3d 57 50 d2 17 97 c8 |N'...0.S.=WP....|
|
||||
000002f0 3d 61 af a6 21 ab 1c 34 47 70 f8 b1 3b 9c 06 86 |=a..!..4Gp..;...|
|
||||
00000300 87 00 e2 13 50 83 91 ad bc 84 bd b4 7b f3 4b ed |....P.......{.K.|
|
||||
00000310 ca 81 0c 94 37 a8 ec 67 ca 9c f3 00 f6 af c2 92 |....7..g........|
|
||||
00000320 c4 8c 78 07 18 0e 43 24 1b 98 16 50 5c 2b 75 0e |..x...C$...P\+u.|
|
||||
00000330 40 66 dc 40 cd 10 1a 51 25 f3 96 25 1a 3e 70 af |@f.@...Q%..%.>p.|
|
||||
00000340 16 24 d0 1c 0e 33 f9 c1 74 cf b7 e2 28 ac 60 16 |.$...3..t...(.`.|
|
||||
00000350 03 03 00 04 0e 00 00 00 |........|
|
||||
>>> Flow 3 (client to server)
|
||||
00000000 16 03 03 00 25 10 00 00 21 20 30 f2 bb f7 a7 ac |....%...! 0.....|
|
||||
00000010 23 20 22 ee 73 0d 49 9c b3 7b c1 9a db 2c 85 f3 |# ".s.I..{...,..|
|
||||
00000020 c0 82 31 60 bd 8b 14 4e 73 43 14 03 03 00 01 01 |..1`...NsC......|
|
||||
00000030 16 03 03 00 20 09 8d c7 86 ee cc f4 c7 36 a3 49 |.... ........6.I|
|
||||
00000040 d3 f7 a1 4a 68 a2 1e b4 fc cc a2 15 cb 01 92 d8 |...Jh...........|
|
||||
00000050 72 b0 d1 6f eb |r..o.|
|
||||
>>> Flow 4 (server to client)
|
||||
00000000 16 03 03 00 8b 04 00 00 87 00 00 00 00 00 81 50 |...............P|
|
||||
00000010 46 ad c1 db a8 38 86 7b 2b bb fd d0 c3 42 3e 00 |F....8.{+....B>.|
|
||||
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 94 |................|
|
||||
00000030 6f e0 18 83 51 ed 14 ef 68 ca 42 c5 4c a2 ac 05 |o...Q...h.B.L...|
|
||||
00000040 9c 69 69 99 08 9f de a4 d4 e7 37 ab 14 38 4c 47 |.ii.......7..8LG|
|
||||
00000050 70 f0 97 1d db 2d 0a 14 c2 1e f0 16 9f 6d 37 02 |p....-.......m7.|
|
||||
00000060 4b f1 16 be 98 3f df 74 83 7c 19 85 61 49 38 16 |K....?.t.|..aI8.|
|
||||
00000070 ee 35 7a e2 3f 74 fe 8d e3 07 93 a1 5e fa f2 02 |.5z.?t......^...|
|
||||
00000080 e5 c8 60 3f 11 83 8b 0e 32 52 f1 aa 52 b7 0a 89 |..`?....2R..R...|
|
||||
00000090 14 03 03 00 01 01 16 03 03 00 20 9e 65 15 cf 45 |.......... .e..E|
|
||||
000000a0 a5 03 69 c9 b1 d8 9e 92 a3 a2 b0 df 2e 62 b1 3a |..i..........b.:|
|
||||
000000b0 17 78 cd e5 1d f3 51 42 7e 4e 25 17 03 03 00 1d |.x....QB~N%.....|
|
||||
000000c0 d9 ae d0 fa b7 90 a9 2f 28 8d 1d 6f 54 1f c0 1e |......./(..oT...|
|
||||
000000d0 4d ae b6 91 f0 e8 84 cf 86 11 22 25 ea 15 03 03 |M........."%....|
|
||||
000000e0 00 12 0e 71 f2 11 9e 9f 58 ad c0 d8 fc fa 34 bc |...q....X.....4.|
|
||||
000000f0 02 5a 60 00 |.Z`.|
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
>>> Flow 1 (client to server)
|
||||
00000000 16 03 01 00 eb 01 00 00 e7 03 03 1c d3 8e 3b d9 |..............;.|
|
||||
00000010 fe 7d e7 f9 9f fa c6 51 c3 8c 1b dd dc 87 95 f4 |.}.....Q........|
|
||||
00000020 39 23 67 e4 d6 bd 94 93 fc 88 4e 20 c3 c0 e2 c1 |9#g.......N ....|
|
||||
00000030 3d 12 ec 4c 0a 3f 40 51 13 24 61 11 c0 5d 09 f9 |=..L.?@Q.$a..]..|
|
||||
00000040 08 d6 3e cd e7 b3 51 c3 06 8f b4 42 00 04 13 03 |..>...Q....B....|
|
||||
00000050 00 ff 01 00 00 9a 00 0b 00 04 03 00 01 02 00 0a |................|
|
||||
00000060 00 0c 00 0a 00 1d 00 17 00 1e 00 19 00 18 00 23 |...............#|
|
||||
00000070 00 00 00 10 00 19 00 17 06 70 72 6f 74 6f 33 08 |.........proto3.|
|
||||
00000080 68 74 74 70 2f 31 2e 31 06 70 72 6f 74 6f 34 00 |http/1.1.proto4.|
|
||||
00000090 16 00 00 00 17 00 00 00 0d 00 1e 00 1c 04 03 05 |................|
|
||||
000000a0 03 06 03 08 07 08 08 08 09 08 0a 08 0b 08 04 08 |................|
|
||||
000000b0 05 08 06 04 01 05 01 06 01 00 2b 00 03 02 03 04 |..........+.....|
|
||||
000000c0 00 2d 00 02 01 01 00 33 00 26 00 24 00 1d 00 20 |.-.....3.&.$... |
|
||||
000000d0 f4 05 eb 4a 7a 73 20 18 74 aa 14 2a 0c 35 63 29 |...Jzs .t..*.5c)|
|
||||
000000e0 cb f2 ad d1 a2 3d bd 9d 02 b4 62 00 bc eb 10 58 |.....=....b....X|
|
||||
>>> Flow 2 (server to client)
|
||||
00000000 16 03 03 00 7a 02 00 00 76 03 03 00 00 00 00 00 |....z...v.......|
|
||||
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
|
||||
00000020 00 00 00 00 00 00 00 00 00 00 00 20 c3 c0 e2 c1 |........... ....|
|
||||
00000030 3d 12 ec 4c 0a 3f 40 51 13 24 61 11 c0 5d 09 f9 |=..L.?@Q.$a..]..|
|
||||
00000040 08 d6 3e cd e7 b3 51 c3 06 8f b4 42 13 03 00 00 |..>...Q....B....|
|
||||
00000050 2e 00 2b 00 02 03 04 00 33 00 24 00 1d 00 20 2f |..+.....3.$... /|
|
||||
00000060 e5 7d a3 47 cd 62 43 15 28 da ac 5f bb 29 07 30 |.}.G.bC.(.._.).0|
|
||||
00000070 ff f6 84 af c4 cf c2 ed 90 99 5f 58 cb 3b 74 14 |.........._X.;t.|
|
||||
00000080 03 03 00 01 01 17 03 03 00 17 fb 75 d8 5c 50 35 |...........u.\P5|
|
||||
00000090 55 82 ba 65 1e 63 73 b8 c1 e9 d7 f5 28 68 3c c1 |U..e.cs.....(h<.|
|
||||
000000a0 5d 17 03 03 02 6d 56 c9 a9 09 73 6a bc fd 1a 3c |]....mV...sj...<|
|
||||
000000b0 6a f8 3e 32 99 83 e8 f6 01 9e 5e 30 e8 53 7f 72 |j.>2......^0.S.r|
|
||||
000000c0 fd 86 72 a8 9e 47 25 67 c1 f1 9a 03 c0 9d 6f 9d |..r..G%g......o.|
|
||||
000000d0 bd ed 29 30 8f 3c 01 ce 49 bb 5f dd 58 9a ae 80 |..)0.<..I._.X...|
|
||||
000000e0 5c 2d 81 fc ea 7b 03 03 3d 5d bb 92 23 73 67 89 |\-...{..=]..#sg.|
|
||||
000000f0 2e f0 ec 08 20 8a 36 eb 43 a6 a1 68 d0 39 95 37 |.... .6.C..h.9.7|
|
||||
00000100 6b 15 a9 0e 46 20 92 51 9c 04 bf 3b 07 97 84 cb |k...F .Q...;....|
|
||||
00000110 1f 30 38 37 2e ff e7 0f f5 14 93 5a 84 f1 f7 10 |.087.......Z....|
|
||||
00000120 c2 a5 0d bb 97 96 ef 4a e0 13 c0 63 72 2b 60 f3 |.......J...cr+`.|
|
||||
00000130 59 b5 57 aa 5f d1 da a9 0e dd 9c dd c2 cb 61 fe |Y.W._.........a.|
|
||||
00000140 e2 69 8e db 5d 70 6c 3a 33 e0 9e db 9a 31 26 6a |.i..]pl:3....1&j|
|
||||
00000150 2b 9e 19 8e bb 5d 06 48 ea c0 a1 c6 11 24 fb c4 |+....].H.....$..|
|
||||
00000160 ce ae 48 54 64 81 d1 84 38 a6 e0 7a 7b 74 2b bc |..HTd...8..z{t+.|
|
||||
00000170 ce 07 8b b6 04 1f 5b 4c 36 29 68 0c 8c c7 32 15 |......[L6)h...2.|
|
||||
00000180 93 e0 10 52 c2 27 23 96 c5 0c 9c e9 e2 a9 08 7d |...R.'#........}|
|
||||
00000190 25 68 65 f5 4e 44 eb a9 85 78 13 e1 0d 86 5e dc |%he.ND...x....^.|
|
||||
000001a0 fd e5 c6 dd 65 46 8e 2f 32 82 83 0b dd 67 f8 42 |....eF./2....g.B|
|
||||
000001b0 65 87 3b 08 fe b1 f5 12 e9 74 21 04 12 6d 75 35 |e.;......t!..mu5|
|
||||
000001c0 b2 eb 93 95 72 10 fa 56 96 77 c3 0c 17 8c 9e f6 |....r..V.w......|
|
||||
000001d0 77 19 28 37 96 3e 73 98 f4 d2 91 4f 40 db 76 56 |w.(7.>s....O@.vV|
|
||||
000001e0 ce b5 a8 7a b8 86 d0 9a ba b5 8b 40 c2 63 e1 cf |...z.......@.c..|
|
||||
000001f0 49 29 2c 5d 1a 9b 8b 56 cb 93 ca 2c c0 d0 15 b7 |I),]...V...,....|
|
||||
00000200 8a f1 6a d5 0a a8 81 57 b1 6e 10 cd a5 ff b1 4d |..j....W.n.....M|
|
||||
00000210 47 c6 9b 35 f1 5f 83 91 22 f6 88 68 65 b3 b9 c9 |G..5._.."..he...|
|
||||
00000220 02 dc 4b f7 13 39 06 e6 3a ec 94 ef 51 15 05 72 |..K..9..:...Q..r|
|
||||
00000230 1d f4 9d 3b da ca 8d 2c 64 be 9b 45 99 2c 63 cc |...;...,d..E.,c.|
|
||||
00000240 22 b3 8b 93 ad f6 2c f0 d2 d9 11 3f 5b c0 40 fa |".....,....?[.@.|
|
||||
00000250 90 6e a0 76 b2 43 b9 4c 72 c4 24 28 a2 bf 56 d6 |.n.v.C.Lr.$(..V.|
|
||||
00000260 d2 a7 2a d1 8c 5e 1d eb f8 be d0 43 da 7a c7 88 |..*..^.....C.z..|
|
||||
00000270 61 67 a2 69 85 23 43 3e d4 88 f2 33 c3 5b 38 0a |ag.i.#C>...3.[8.|
|
||||
00000280 1e de 28 3b 3b 19 de 95 2f 84 c0 37 88 80 59 2f |..(;;.../..7..Y/|
|
||||
00000290 a6 ee 93 1a 69 08 c3 df 7c cf da c3 9b 96 70 d9 |....i...|.....p.|
|
||||
000002a0 60 c5 e9 0f 42 f6 1a f2 58 5e f2 32 61 6a b2 a3 |`...B...X^.2aj..|
|
||||
000002b0 1f 97 fa 08 6c 3f 4b 83 1f 04 66 80 8a 26 3a 7f |....l?K...f..&:.|
|
||||
000002c0 24 30 ec 10 ae 7d 19 ff 39 91 ca 97 4e ed 0a d7 |$0...}..9...N...|
|
||||
000002d0 64 3b 6b 50 29 33 0d b2 10 bc 83 63 3c fb 9a 82 |d;kP)3.....c<...|
|
||||
000002e0 3b 7f bc 04 40 f1 33 64 4a 80 cd 01 f9 f4 c6 89 |;...@.3dJ.......|
|
||||
000002f0 65 27 25 f9 cf 4f 7e c8 6e d9 0e ec 47 4a 51 29 |e'%..O~.n...GJQ)|
|
||||
00000300 2f be 34 50 bd 9b d2 d8 b7 ea bb 0b a1 e0 20 1b |/.4P.......... .|
|
||||
00000310 02 9c f2 17 03 03 00 99 61 dc 0b 3a 30 de 39 f6 |........a..:0.9.|
|
||||
00000320 f3 db f8 6c 3b fa 4e 1e 7e 62 a5 ae 73 ba e1 41 |...l;.N.~b..s..A|
|
||||
00000330 58 77 2a c1 7a 0c 50 bb 0c 57 b4 c4 25 bf 2f 9f |Xw*.z.P..W..%./.|
|
||||
00000340 38 91 e2 65 22 9d ca ac 18 58 7e 81 2d fd 74 24 |8..e"....X~.-.t$|
|
||||
00000350 28 69 76 11 df 9d 23 b8 be ae 8b e0 93 8e 5d df |(iv...#.......].|
|
||||
00000360 0a 64 d0 b7 02 68 aa 86 01 0d 55 11 3b 76 70 c6 |.d...h....U.;vp.|
|
||||
00000370 83 0c 5e 0a e3 37 a5 8b ad 25 50 b9 e8 5c 6b 04 |..^..7...%P..\k.|
|
||||
00000380 b4 51 ec 9c d3 fa c6 b7 9c f0 46 aa 73 da 3c 0d |.Q........F.s.<.|
|
||||
00000390 d3 bd 32 81 d4 d2 f1 1a b0 92 f3 73 3e 54 2b 05 |..2........s>T+.|
|
||||
000003a0 92 24 34 75 df d6 18 a0 6a 82 95 4c 9b fc 7e b6 |.$4u....j..L..~.|
|
||||
000003b0 8e 17 03 03 00 35 8f 34 0e 3b 91 d8 e7 74 24 71 |.....5.4.;...t$q|
|
||||
000003c0 0e 7b f3 12 bb 76 2f 31 12 17 b8 9e 24 ce f9 2f |.{...v/1....$../|
|
||||
000003d0 3f 5d f2 13 4b 2e 9b 1e c4 78 03 a6 c8 07 11 a3 |?]..K....x......|
|
||||
000003e0 98 79 61 6e 4f 44 6e 18 ee c4 9b 17 03 03 00 93 |.yanODn.........|
|
||||
000003f0 64 dd 52 a9 d9 51 63 6a a0 a3 c2 75 6b 5d 1d 54 |d.R..Qcj...uk].T|
|
||||
00000400 ce d4 53 7e 14 8e d9 26 93 28 78 65 16 1b 95 77 |..S~...&.(xe...w|
|
||||
00000410 68 0a 46 f1 82 36 bb 8a fa 0d df 54 8c 3d 83 e0 |h.F..6.....T.=..|
|
||||
00000420 d7 de 2d 96 e9 c4 d7 22 d3 97 8e ae 90 f8 fc e6 |..-...."........|
|
||||
00000430 a6 4b 78 98 4c c5 28 87 91 46 fa f4 1c 8d 0e ec |.Kx.L.(..F......|
|
||||
00000440 0d 71 40 9a 04 49 b4 e8 5b 62 6f cd 16 c1 d5 fb |.q@..I..[bo.....|
|
||||
00000450 73 2a 96 8f e5 a2 f4 11 1e df 2d 40 45 6b d5 a9 |s*........-@Ek..|
|
||||
00000460 e4 e3 f7 93 fc fa d7 20 af d5 f7 b4 0e 09 ad d5 |....... ........|
|
||||
00000470 26 87 b8 6c e2 20 95 fb c0 70 3e 38 be b7 b1 9f |&..l. ...p>8....|
|
||||
00000480 70 da c1 |p..|
|
||||
>>> Flow 3 (client to server)
|
||||
00000000 14 03 03 00 01 01 17 03 03 00 35 29 d2 b9 bb 9b |..........5)....|
|
||||
00000010 de 6c 5d 22 23 c1 fe 99 4c c5 33 bf fd 70 36 6b |.l]"#...L.3..p6k|
|
||||
00000020 f1 a5 92 e8 bf 7c 3d 6e ef 6a 44 73 bc cb 27 1c |.....|=n.jDs..'.|
|
||||
00000030 09 5d bf 99 4c 19 24 c3 3b 30 91 b5 e3 b6 63 45 |.]..L.$.;0....cE|
|
||||
>>> Flow 4 (server to client)
|
||||
00000000 17 03 03 00 1e 52 55 85 7c b8 87 dd c7 b2 d9 5b |.....RU.|......[|
|
||||
00000010 18 1d bb ac bf b6 ab 76 82 be 64 0e b2 7b 2c 0f |.......v..d..{,.|
|
||||
00000020 aa 17 92 17 03 03 00 13 79 0a 60 b1 46 20 33 74 |........y.`.F 3t|
|
||||
00000030 ed 12 a0 23 de 68 88 fc 6f dd 8e |...#.h..o..|
|
||||
|
|
@ -2838,7 +2838,7 @@ func TestTxStmtDeadlock(t *testing.T) {
|
|||
db := newTestDB(t, "people")
|
||||
defer closeDB(t, db)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Millisecond)
|
||||
ctx, cancel := context.WithCancel(context.Background())
|
||||
defer cancel()
|
||||
tx, err := db.BeginTx(ctx, nil)
|
||||
if err != nil {
|
||||
|
|
@ -2849,6 +2849,7 @@ func TestTxStmtDeadlock(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
cancel()
|
||||
// Run number of stmt queries to reproduce deadlock from context cancel
|
||||
for i := 0; i < 1e3; i++ {
|
||||
// Encounter any close related errors (e.g. ErrTxDone, stmt is closed)
|
||||
|
|
|
|||
|
|
@ -1164,6 +1164,13 @@ func (f *File) DWARF() (*dwarf.Data, error) {
|
|||
b = dbuf
|
||||
}
|
||||
|
||||
if f.Type == ET_EXEC {
|
||||
// Do not apply relocations to DWARF sections for ET_EXEC binaries.
|
||||
// Relocations should already be applied, and .rela sections may
|
||||
// contain incorrect data.
|
||||
return b, nil
|
||||
}
|
||||
|
||||
for _, r := range f.Sections {
|
||||
if r.Type != SHT_RELA && r.Type != SHT_REL {
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -189,7 +189,7 @@
|
|||
When printing a struct, fmt cannot and therefore does not invoke
|
||||
formatting methods such as Error or String on unexported fields.
|
||||
|
||||
Explicit argument indexes:
|
||||
Explicit argument indexes
|
||||
|
||||
In Printf, Sprintf, and Fprintf, the default behavior is for each
|
||||
formatting verb to format successive arguments passed in the call.
|
||||
|
|
@ -211,7 +211,7 @@
|
|||
fmt.Sprintf("%d %d %#[1]x %#x", 16, 17)
|
||||
will yield "16 17 0x10 0x11".
|
||||
|
||||
Format errors:
|
||||
Format errors
|
||||
|
||||
If an invalid argument is given for a verb, such as providing
|
||||
a string to %d, the generated string will contain a
|
||||
|
|
|
|||
|
|
@ -440,7 +440,8 @@ var depsRules = `
|
|||
# HTTP, King of Dependencies.
|
||||
|
||||
FMT
|
||||
< golang.org/x/net/http2/hpack, net/http/internal, net/http/internal/ascii;
|
||||
< golang.org/x/net/http2/hpack
|
||||
< net/http/internal, net/http/internal/ascii, net/http/internal/testcert;
|
||||
|
||||
FMT, NET, container/list, encoding/binary, log
|
||||
< golang.org/x/text/transform
|
||||
|
|
@ -459,6 +460,7 @@ var depsRules = `
|
|||
golang.org/x/net/http2/hpack,
|
||||
net/http/internal,
|
||||
net/http/internal/ascii,
|
||||
net/http/internal/testcert,
|
||||
net/http/httptrace,
|
||||
mime/multipart,
|
||||
log
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@
|
|||
//
|
||||
// A build constraint, also known as a build tag, is a line comment that begins
|
||||
//
|
||||
// // +build
|
||||
// //go:build
|
||||
//
|
||||
// that lists the conditions under which a file should be included in the
|
||||
// package. Build constraints may also be part of a file's name
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ package build
|
|||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
|
|
@ -28,9 +29,19 @@ type importReader struct {
|
|||
pos token.Position
|
||||
}
|
||||
|
||||
var bom = []byte{0xef, 0xbb, 0xbf}
|
||||
|
||||
func newImportReader(name string, r io.Reader) *importReader {
|
||||
b := bufio.NewReader(r)
|
||||
// Remove leading UTF-8 BOM.
|
||||
// Per https://golang.org/ref/spec#Source_code_representation:
|
||||
// a compiler may ignore a UTF-8-encoded byte order mark (U+FEFF)
|
||||
// if it is the first Unicode code point in the source text.
|
||||
if leadingBytes, err := b.Peek(3); err == nil && bytes.Equal(leadingBytes, bom) {
|
||||
b.Discard(3)
|
||||
}
|
||||
return &importReader{
|
||||
b: bufio.NewReader(r),
|
||||
b: b,
|
||||
pos: token.Position{
|
||||
Filename: name,
|
||||
Line: 1,
|
||||
|
|
|
|||
|
|
@ -66,6 +66,10 @@ var readGoInfoTests = []readTest{
|
|||
`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"\ufeff𝔻" + `package p; import "x";ℙvar x = 1`,
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
var readCommentsTests = []readTest{
|
||||
|
|
@ -81,6 +85,10 @@ var readCommentsTests = []readTest{
|
|||
`ℙpackage p; import . "x"`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"\ufeff𝔻" + `ℙpackage p; import . "x"`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
`// foo
|
||||
|
||||
|
|
@ -90,6 +98,19 @@ var readCommentsTests = []readTest{
|
|||
|
||||
/*/ zot */
|
||||
|
||||
// asdf
|
||||
ℙHello, world`,
|
||||
"",
|
||||
},
|
||||
{
|
||||
"\ufeff𝔻" + `// foo
|
||||
|
||||
/* bar */
|
||||
|
||||
/* quux */ // baz
|
||||
|
||||
/*/ zot */
|
||||
|
||||
// asdf
|
||||
ℙHello, world`,
|
||||
"",
|
||||
|
|
@ -107,6 +128,11 @@ func testRead(t *testing.T, tests []readTest, read func(io.Reader) ([]byte, erro
|
|||
in = tt.in[:j] + tt.in[j+len("ℙ"):]
|
||||
testOut = tt.in[:j]
|
||||
}
|
||||
d := strings.Index(tt.in, "𝔻")
|
||||
if d >= 0 {
|
||||
in = in[:d] + in[d+len("𝔻"):]
|
||||
testOut = testOut[d+len("𝔻"):]
|
||||
}
|
||||
r := strings.NewReader(in)
|
||||
buf, err := read(r)
|
||||
if err != nil {
|
||||
|
|
@ -264,6 +290,12 @@ var readEmbedTests = []struct {
|
|||
test:3:14:y
|
||||
test:3:16:z`,
|
||||
},
|
||||
{
|
||||
"\ufeffpackage p\nimport \"embed\"\n//go:embed x y z\nvar files embed.FS",
|
||||
`test:3:12:x
|
||||
test:3:14:y
|
||||
test:3:16:z`,
|
||||
},
|
||||
{
|
||||
"package p\nimport \"embed\"\nvar s = \"/*\"\n//go:embed x\nvar files embed.FS",
|
||||
`test:4:12:x`,
|
||||
|
|
@ -292,6 +324,10 @@ var readEmbedTests = []struct {
|
|||
"package p\n//go:embed x y z\nvar files embed.FS", // no import, no scan
|
||||
"",
|
||||
},
|
||||
{
|
||||
"\ufeffpackage p\n//go:embed x y z\nvar files embed.FS", // no import, no scan
|
||||
"",
|
||||
},
|
||||
}
|
||||
|
||||
func TestReadEmbed(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -145,17 +145,14 @@ func Import(fset *token.FileSet, packages map[string]*types.Package, path, srcDi
|
|||
err = fmt.Errorf("import %q: old textual export format no longer supported (recompile library)", path)
|
||||
|
||||
case "$$B\n":
|
||||
var data []byte
|
||||
data, err = io.ReadAll(buf)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
var exportFormat byte
|
||||
exportFormat, err = buf.ReadByte()
|
||||
|
||||
// The indexed export format starts with an 'i'; the older
|
||||
// binary export format starts with a 'c', 'd', or 'v'
|
||||
// (from "version"). Select appropriate importer.
|
||||
if len(data) > 0 && data[0] == 'i' {
|
||||
_, pkg, err = iImportData(fset, packages, data[1:], id)
|
||||
if err == nil && exportFormat == 'i' {
|
||||
pkg, err = iImportData(fset, packages, buf, id)
|
||||
} else {
|
||||
err = fmt.Errorf("import %q: old binary export format no longer supported (recompile library)", path)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
package gcimporter
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
|
|
@ -20,7 +21,7 @@ import (
|
|||
)
|
||||
|
||||
type intReader struct {
|
||||
*bytes.Reader
|
||||
*bufio.Reader
|
||||
path string
|
||||
}
|
||||
|
||||
|
|
@ -61,7 +62,7 @@ const (
|
|||
// and returns the number of bytes consumed and a reference to the package.
|
||||
// If the export data version is not recognized or the format is otherwise
|
||||
// compromised, an error is returned.
|
||||
func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
|
||||
func iImportData(fset *token.FileSet, imports map[string]*types.Package, dataReader *bufio.Reader, path string) (pkg *types.Package, err error) {
|
||||
const currentVersion = 1
|
||||
version := int64(-1)
|
||||
defer func() {
|
||||
|
|
@ -74,7 +75,7 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
|||
}
|
||||
}()
|
||||
|
||||
r := &intReader{bytes.NewReader(data), path}
|
||||
r := &intReader{dataReader, path}
|
||||
|
||||
version = int64(r.uint64())
|
||||
switch version {
|
||||
|
|
@ -86,10 +87,12 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
|||
sLen := int64(r.uint64())
|
||||
dLen := int64(r.uint64())
|
||||
|
||||
whence, _ := r.Seek(0, io.SeekCurrent)
|
||||
stringData := data[whence : whence+sLen]
|
||||
declData := data[whence+sLen : whence+sLen+dLen]
|
||||
r.Seek(sLen+dLen, io.SeekCurrent)
|
||||
data := make([]byte, sLen+dLen)
|
||||
if _, err := io.ReadFull(r, data); err != nil {
|
||||
errorf("cannot read %d bytes of stringData and declData: %s", len(data), err)
|
||||
}
|
||||
stringData := data[:sLen]
|
||||
declData := data[sLen:]
|
||||
|
||||
p := iimporter{
|
||||
ipath: path,
|
||||
|
|
@ -165,9 +168,7 @@ func iImportData(fset *token.FileSet, imports map[string]*types.Package, data []
|
|||
|
||||
// package was imported completely and without errors
|
||||
localpkg.MarkComplete()
|
||||
|
||||
consumed, _ := r.Seek(0, io.SeekCurrent)
|
||||
return int(consumed), localpkg, nil
|
||||
return localpkg, nil
|
||||
}
|
||||
|
||||
type iimporter struct {
|
||||
|
|
|
|||
|
|
@ -1302,7 +1302,12 @@ func (p *parser) parseIndexOrSliceOrInstance(x ast.Expr) ast.Expr {
|
|||
p.errorExpected(p.pos, "operand")
|
||||
rbrack := p.pos
|
||||
p.next()
|
||||
return &ast.BadExpr{From: x.Pos(), To: rbrack}
|
||||
return &ast.IndexExpr{
|
||||
X: x,
|
||||
Lbrack: lbrack,
|
||||
Index: &ast.BadExpr{From: rbrack, To: rbrack},
|
||||
Rbrack: rbrack,
|
||||
}
|
||||
}
|
||||
p.exprLev++
|
||||
|
||||
|
|
|
|||
|
|
@ -373,7 +373,7 @@ func (s *Scanner) scanIdentifier() string {
|
|||
continue
|
||||
}
|
||||
s.rdOffset += rdOffset
|
||||
if b < utf8.RuneSelf {
|
||||
if 0 < b && b < utf8.RuneSelf {
|
||||
// Optimization: we've encountered an ASCII character that's not a letter
|
||||
// or number. Avoid the call into s.next() and corresponding set up.
|
||||
//
|
||||
|
|
|
|||
|
|
@ -812,6 +812,8 @@ var errors = []struct {
|
|||
{"//\ufeff", token.COMMENT, 2, "//\ufeff", "illegal byte order mark"}, // only first BOM is ignored
|
||||
{"'\ufeff" + `'`, token.CHAR, 1, "'\ufeff" + `'`, "illegal byte order mark"}, // only first BOM is ignored
|
||||
{`"` + "abc\ufeffdef" + `"`, token.STRING, 4, `"` + "abc\ufeffdef" + `"`, "illegal byte order mark"}, // only first BOM is ignored
|
||||
{"abc\x00def", token.IDENT, 3, "abc", "illegal character NUL"},
|
||||
{"abc\x00", token.IDENT, 3, "abc", "illegal character NUL"},
|
||||
}
|
||||
|
||||
func TestScanErrors(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -588,6 +588,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
case _Add:
|
||||
// unsafe.Add(ptr unsafe.Pointer, len IntegerType) unsafe.Pointer
|
||||
if !check.allowVersion(check.pkg, 1, 17) {
|
||||
check.errorf(call.Fun, _InvalidUnsafeAdd, "unsafe.Add requires go1.17 or later")
|
||||
return
|
||||
}
|
||||
|
||||
check.assignment(x, Typ[UnsafePointer], "argument to unsafe.Add")
|
||||
if x.mode == invalid {
|
||||
return
|
||||
|
|
@ -684,6 +689,11 @@ func (check *Checker) builtin(x *operand, call *ast.CallExpr, id builtinId) (_ b
|
|||
|
||||
case _Slice:
|
||||
// unsafe.Slice(ptr *T, len IntegerType) []T
|
||||
if !check.allowVersion(check.pkg, 1, 17) {
|
||||
check.errorf(call.Fun, _InvalidUnsafeSlice, "unsafe.Slice requires go1.17 or later")
|
||||
return
|
||||
}
|
||||
|
||||
typ := asPointer(x.typ)
|
||||
if typ == nil {
|
||||
check.invalidArg(x, _InvalidUnsafeSlice, "%s is not a pointer", x)
|
||||
|
|
|
|||
|
|
@ -202,17 +202,20 @@ func asGoVersion(s string) string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func checkFiles(t *testing.T, sizes Sizes, goVersion string, filenames []string, srcs [][]byte, manual bool) {
|
||||
func checkFiles(t *testing.T, sizes Sizes, goVersion string, filenames []string, srcs [][]byte, manual bool, imp Importer) {
|
||||
if len(filenames) == 0 {
|
||||
t.Fatal("no source files")
|
||||
}
|
||||
|
||||
if strings.HasSuffix(filenames[0], ".go2") && !typeparams.Enabled {
|
||||
t.Skip("type params are not enabled")
|
||||
}
|
||||
if strings.HasSuffix(filenames[0], ".go1") && typeparams.Enabled {
|
||||
t.Skip("type params are enabled")
|
||||
}
|
||||
|
||||
mode := parser.AllErrors
|
||||
if strings.HasSuffix(filenames[0], ".go2") {
|
||||
if !typeparams.Enabled {
|
||||
t.Skip("type params are not enabled")
|
||||
}
|
||||
} else {
|
||||
if !strings.HasSuffix(filenames[0], ".go2") {
|
||||
mode |= typeparams.DisallowParsing
|
||||
}
|
||||
|
||||
|
|
@ -249,7 +252,10 @@ func checkFiles(t *testing.T, sizes Sizes, goVersion string, filenames []string,
|
|||
}
|
||||
}
|
||||
|
||||
conf.Importer = importer.Default()
|
||||
conf.Importer = imp
|
||||
if imp == nil {
|
||||
conf.Importer = importer.Default()
|
||||
}
|
||||
conf.Error = func(err error) {
|
||||
if *haltOnError {
|
||||
defer panic(err)
|
||||
|
|
@ -319,7 +325,7 @@ func TestManual(t *testing.T) {
|
|||
func TestLongConstants(t *testing.T) {
|
||||
format := "package longconst\n\nconst _ = %s\nconst _ = %s // ERROR excessively long constant"
|
||||
src := fmt.Sprintf(format, strings.Repeat("1", 9999), strings.Repeat("1", 10001))
|
||||
checkFiles(t, nil, "", []string{"longconst.go"}, [][]byte{[]byte(src)}, false)
|
||||
checkFiles(t, nil, "", []string{"longconst.go"}, [][]byte{[]byte(src)}, false, nil)
|
||||
}
|
||||
|
||||
// TestIndexRepresentability tests that constant index operands must
|
||||
|
|
@ -327,7 +333,7 @@ func TestLongConstants(t *testing.T) {
|
|||
// represent larger values.
|
||||
func TestIndexRepresentability(t *testing.T) {
|
||||
const src = "package index\n\nvar s []byte\nvar _ = s[int64 /* ERROR \"int64\\(1\\) << 40 \\(.*\\) overflows int\" */ (1) << 40]"
|
||||
checkFiles(t, &StdSizes{4, 4}, "", []string{"index.go"}, [][]byte{[]byte(src)}, false)
|
||||
checkFiles(t, &StdSizes{4, 4}, "", []string{"index.go"}, [][]byte{[]byte(src)}, false, nil)
|
||||
}
|
||||
|
||||
func TestIssue46453(t *testing.T) {
|
||||
|
|
@ -335,7 +341,7 @@ func TestIssue46453(t *testing.T) {
|
|||
t.Skip("type params are enabled")
|
||||
}
|
||||
const src = "package p\ntype _ comparable // ERROR \"undeclared name: comparable\""
|
||||
checkFiles(t, nil, "", []string{"issue46453.go"}, [][]byte{[]byte(src)}, false)
|
||||
checkFiles(t, nil, "", []string{"issue46453.go"}, [][]byte{[]byte(src)}, false, nil)
|
||||
}
|
||||
|
||||
func TestCheck(t *testing.T) { DefPredeclaredTestFuncs(); testDir(t, "check") }
|
||||
|
|
@ -385,5 +391,5 @@ func testPkg(t *testing.T, filenames []string, goVersion string, manual bool) {
|
|||
}
|
||||
srcs[i] = src
|
||||
}
|
||||
checkFiles(t, nil, goVersion, filenames, srcs, manual)
|
||||
checkFiles(t, nil, goVersion, filenames, srcs, manual, nil)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ func (check *Checker) qualifier(pkg *Package) string {
|
|||
if check.pkgPathMap == nil {
|
||||
check.pkgPathMap = make(map[string]map[string]bool)
|
||||
check.seenPkgMap = make(map[*Package]bool)
|
||||
check.markImports(pkg)
|
||||
check.markImports(check.pkg)
|
||||
}
|
||||
// If the same package name was used by multiple packages, display the full path.
|
||||
if len(check.pkgPathMap[pkg.name]) > 1 {
|
||||
|
|
|
|||
|
|
@ -577,42 +577,64 @@ func TestIssue44515(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestIssue43124(t *testing.T) {
|
||||
// TODO(rFindley) enhance the testdata tests to be able to express this type
|
||||
// of setup.
|
||||
// TODO(rFindley) move this to testdata by enhancing support for importing.
|
||||
|
||||
// All involved packages have the same name (template). Error messages should
|
||||
// disambiguate between text/template and html/template by printing the full
|
||||
// path.
|
||||
const (
|
||||
asrc = `package a; import "text/template"; func F(template.Template) {}; func G(int) {}`
|
||||
bsrc = `package b; import ("a"; "html/template"); func _() { a.F(template.Template{}) }`
|
||||
csrc = `package c; import ("a"; "html/template"); func _() { a.G(template.Template{}) }`
|
||||
bsrc = `
|
||||
package b
|
||||
|
||||
import (
|
||||
"a"
|
||||
"html/template"
|
||||
)
|
||||
|
||||
func _() {
|
||||
// Packages should be fully qualified when there is ambiguity within the
|
||||
// error string itself.
|
||||
a.F(template /* ERROR cannot use.*html/template.* as .*text/template */ .Template{})
|
||||
}
|
||||
`
|
||||
csrc = `
|
||||
package c
|
||||
|
||||
import (
|
||||
"a"
|
||||
"fmt"
|
||||
"html/template"
|
||||
)
|
||||
|
||||
// Issue #46905: make sure template is not the first package qualified.
|
||||
var _ fmt.Stringer = 1 // ERROR cannot use 1.*as fmt\.Stringer
|
||||
|
||||
// Packages should be fully qualified when there is ambiguity in reachable
|
||||
// packages. In this case both a (and for that matter html/template) import
|
||||
// text/template.
|
||||
func _() { a.G(template /* ERROR cannot use .*html/template.*Template */ .Template{}) }
|
||||
`
|
||||
|
||||
tsrc = `
|
||||
package template
|
||||
|
||||
import "text/template"
|
||||
|
||||
type T int
|
||||
|
||||
// Verify that the current package name also causes disambiguation.
|
||||
var _ T = template /* ERROR cannot use.*text/template.* as T value */.Template{}
|
||||
`
|
||||
)
|
||||
|
||||
a, err := pkgFor("a", asrc, nil)
|
||||
if err != nil {
|
||||
t.Fatalf("package a failed to typecheck: %v", err)
|
||||
}
|
||||
conf := Config{Importer: importHelper{pkg: a, fallback: importer.Default()}}
|
||||
imp := importHelper{pkg: a, fallback: importer.Default()}
|
||||
|
||||
// Packages should be fully qualified when there is ambiguity within the
|
||||
// error string itself.
|
||||
bast := mustParse(t, bsrc)
|
||||
_, err = conf.Check(bast.Name.Name, fset, []*ast.File{bast}, nil)
|
||||
if err == nil {
|
||||
t.Fatal("package b had no errors")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "text/template") || !strings.Contains(err.Error(), "html/template") {
|
||||
t.Errorf("type checking error for b does not disambiguate package template: %q", err)
|
||||
}
|
||||
|
||||
// ...and also when there is any ambiguity in reachable packages.
|
||||
cast := mustParse(t, csrc)
|
||||
_, err = conf.Check(cast.Name.Name, fset, []*ast.File{cast}, nil)
|
||||
if err == nil {
|
||||
t.Fatal("package c had no errors")
|
||||
}
|
||||
if !strings.Contains(err.Error(), "html/template") {
|
||||
t.Errorf("type checking error for c does not disambiguate package template: %q", err)
|
||||
}
|
||||
checkFiles(t, nil, "", []string{"b.go"}, [][]byte{[]byte(bsrc)}, false, imp)
|
||||
checkFiles(t, nil, "", []string{"c.go"}, [][]byte{[]byte(csrc)}, false, imp)
|
||||
checkFiles(t, nil, "", []string{"t.go"}, [][]byte{[]byte(tsrc)}, false, imp)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,15 @@ import (
|
|||
. "go/types"
|
||||
)
|
||||
|
||||
// The cmd/*/internal packages may have been deleted as part of a binary
|
||||
// release. Import from source instead.
|
||||
//
|
||||
// (See https://golang.org/issue/43232 and
|
||||
// https://github.com/golang/build/blob/df58bbac082bc87c4a3cdfe336d1ffe60bbaa916/cmd/release/release.go#L533-L545.)
|
||||
//
|
||||
// Use the same importer for all std lib tests to
|
||||
// avoid repeated importing of the same packages.
|
||||
var stdLibImporter = importer.Default()
|
||||
var stdLibImporter = importer.ForCompiler(token.NewFileSet(), "source", nil)
|
||||
|
||||
func TestStdlib(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ package issues
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
syn "cmd/compile/internal/syntax"
|
||||
syn "regexp/syntax"
|
||||
t1 "text/template"
|
||||
t2 "html/template"
|
||||
)
|
||||
|
|
@ -329,10 +329,10 @@ func (... /* ERROR can only use ... with final parameter */ TT) f()
|
|||
func issue28281g() (... /* ERROR can only use ... with final parameter */ TT)
|
||||
|
||||
// Issue #26234: Make various field/method lookup errors easier to read by matching cmd/compile's output
|
||||
func issue26234a(f *syn.File) {
|
||||
func issue26234a(f *syn.Prog) {
|
||||
// The error message below should refer to the actual package name (syntax)
|
||||
// not the local package name (syn).
|
||||
f.foo /* ERROR f.foo undefined \(type \*syntax.File has no field or method foo\) */
|
||||
f.foo /* ERROR f\.foo undefined \(type \*syntax\.Prog has no field or method foo\) */
|
||||
}
|
||||
|
||||
type T struct {
|
||||
|
|
@ -357,11 +357,11 @@ func issue35895() {
|
|||
var _ T = 0 // ERROR cannot use 0 \(untyped int constant\) as T
|
||||
|
||||
// There is only one package with name syntax imported, only use the (global) package name in error messages.
|
||||
var _ *syn.File = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.File
|
||||
var _ *syn.Prog = 0 // ERROR cannot use 0 \(untyped int constant\) as \*syntax.Prog
|
||||
|
||||
// Because both t1 and t2 have the same global package name (template),
|
||||
// qualify packages with full path name in this case.
|
||||
var _ t1.Template = t2 /* ERROR cannot use .* \(value of type "html/template".Template\) as "text/template".Template */ .Template{}
|
||||
var _ t1.Template = t2 /* ERROR cannot use .* \(value of type .html/template.\.Template\) as .text/template.\.Template */ .Template{}
|
||||
}
|
||||
|
||||
func issue42989(s uint) {
|
||||
|
|
|
|||
|
|
@ -210,5 +210,5 @@ func _() {
|
|||
func h[] /* ERROR empty type parameter list */ ()
|
||||
|
||||
func _() {
|
||||
h[] /* ERROR operand */ ()
|
||||
h /* ERROR cannot index */ [] /* ERROR operand */ ()
|
||||
}
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue