mirror of
https://github.com/golang/go
synced 2024-10-14 11:53:56 +00:00
Merge branch 'master' into ref-chan.go
This commit is contained in:
commit
f97fe5b5bf
1
api/next/57151.txt
Normal file
1
api/next/57151.txt
Normal file
|
@ -0,0 +1 @@
|
|||
pkg path/filepath, func Localize(string) (string, error) #57151
|
1
api/next/62484.txt
Normal file
1
api/next/62484.txt
Normal file
|
@ -0,0 +1 @@
|
|||
pkg os, func CopyFS(string, fs.FS) error #62484
|
|
@ -2,5 +2,11 @@
|
|||
|
||||
### Go command {#go-command}
|
||||
|
||||
Setting the `GOROOT_FINAL` environment variable no longer has an effect
|
||||
([#62047](https://go.dev/issue/62047)).
|
||||
Distributions that install the `go` command to a location other than
|
||||
`$GOROOT/bin/go` should install a symlink instead of relocating
|
||||
or copying the `go` binary.
|
||||
|
||||
### Cgo {#cgo}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
The new type [`KeepAliveConfig`](/net#KeepAliveConfig) permits fine-tuning
|
||||
the keep-alive options for TCP connections, via a new
|
||||
[`TCPConn.SetKeepAliveConfig`](/net#TCPConn.SetKeepAliveConfig) method and
|
||||
new KeepAliveConfig fields for [`Dialer`](net#Dialer) and [`ListenConfig`](net#ListenConfig).
|
||||
new KeepAliveConfig fields for [`Dialer`](/net#Dialer) and [`ListenConfig`](/net#ListenConfig).
|
||||
|
|
2
doc/next/6-stdlib/99-minor/net/http/64910.md
Normal file
2
doc/next/6-stdlib/99-minor/net/http/64910.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
The patterns used by [`net/http.ServeMux`](//net/http#ServeMux) allow
|
||||
multiple spaces matching regexp '[ \t]+'.
|
3
doc/next/6-stdlib/99-minor/os/33357.md
Normal file
3
doc/next/6-stdlib/99-minor/os/33357.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
The [`os.Stat`](/os#Stat) function now sets the [`os.ModeSocket`](/os#ModeSocket)
|
||||
bit for files that are Unix sockets on Windows. These files are identified by
|
||||
having a reparse tag set to `IO_REPARSE_TAG_AF_UNIX`.
|
2
doc/next/6-stdlib/99-minor/os/62484.md
Normal file
2
doc/next/6-stdlib/99-minor/os/62484.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
The [`CopyFS`](/os#CopyFS) function copies an [`io/fs.FS`](/io/fs#FS)
|
||||
into the local filesystem.
|
2
doc/next/6-stdlib/99-minor/path/filepath/57151.md
Normal file
2
doc/next/6-stdlib/99-minor/path/filepath/57151.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
The new [`Localize`](/path/filepath#Localize) function safely converts
|
||||
a slash-separated path into an operating system path.
|
|
@ -1 +0,0 @@
|
|||
See `syscall (windows-386)/62254.md`.
|
|
@ -581,10 +581,10 @@ func TestPaxSymlink(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
hdr, err := FileInfoHeader(fileinfo, "")
|
||||
hdr.Typeflag = TypeSymlink
|
||||
if err != nil {
|
||||
t.Fatalf("os.Stat:1 %v", err)
|
||||
}
|
||||
hdr.Typeflag = TypeSymlink
|
||||
// Force a PAX long linkname to be written
|
||||
longLinkname := strings.Repeat("1234567890/1234567890", 10)
|
||||
hdr.Linkname = longLinkname
|
||||
|
@ -761,10 +761,10 @@ func TestUSTARLongName(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
hdr, err := FileInfoHeader(fileinfo, "")
|
||||
hdr.Typeflag = TypeDir
|
||||
if err != nil {
|
||||
t.Fatalf("os.Stat:1 %v", err)
|
||||
}
|
||||
hdr.Typeflag = TypeDir
|
||||
// Force a PAX long name to be written. The name was taken from a practical example
|
||||
// that fails and replaced ever char through numbers to anonymize the sample.
|
||||
longName := "/0000_0000000/00000-000000000/0000_0000000/00000-0000000000000/0000_0000000/00000-0000000-00000000/0000_0000000/00000000/0000_0000000/000/0000_0000000/00000000v00/0000_0000000/000000/0000_0000000/0000000/0000_0000000/00000y-00/0000/0000/00000000/0x000000/"
|
||||
|
|
|
@ -109,32 +109,18 @@ func testAddr2Line(t *testing.T, dbgExePath, addr string) {
|
|||
srcPath = filepath.FromSlash(srcPath)
|
||||
fi2, err := os.Stat(srcPath)
|
||||
|
||||
// If GOROOT_FINAL is set and srcPath is not the file we expect, perhaps
|
||||
// srcPath has had GOROOT_FINAL substituted for GOROOT and GOROOT hasn't been
|
||||
// moved to its final location yet. If so, try the original location instead.
|
||||
if gorootFinal := os.Getenv("GOROOT_FINAL"); gorootFinal != "" &&
|
||||
(os.IsNotExist(err) || (err == nil && !os.SameFile(fi1, fi2))) {
|
||||
// srcPath is clean, but GOROOT_FINAL itself might not be.
|
||||
// (See https://golang.org/issue/41447.)
|
||||
gorootFinal = filepath.Clean(gorootFinal)
|
||||
|
||||
if strings.HasPrefix(srcPath, gorootFinal) {
|
||||
fi2, err = os.Stat(runtime.GOROOT() + strings.TrimPrefix(srcPath, gorootFinal))
|
||||
}
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
t.Fatalf("Stat failed: %v", err)
|
||||
}
|
||||
if !os.SameFile(fi1, fi2) {
|
||||
t.Fatalf("addr2line_test.go and %s are not same file", srcPath)
|
||||
}
|
||||
if srcLineNo != "138" {
|
||||
t.Fatalf("line number = %v; want 138", srcLineNo)
|
||||
if want := "124"; srcLineNo != want {
|
||||
t.Fatalf("line number = %v; want %s", srcLineNo, want)
|
||||
}
|
||||
}
|
||||
|
||||
// This is line 137. The test depends on that.
|
||||
// This is line 123. The test depends on that.
|
||||
func TestAddr2Line(t *testing.T) {
|
||||
testenv.MustHaveGoBuild(t)
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@ import (
|
|||
"cmd/asm/internal/lex"
|
||||
"cmd/internal/obj"
|
||||
"cmd/internal/obj/ppc64"
|
||||
"cmd/internal/obj/riscv"
|
||||
"cmd/internal/obj/x86"
|
||||
"cmd/internal/sys"
|
||||
)
|
||||
|
@ -46,7 +47,11 @@ func (p *Parser) append(prog *obj.Prog, cond string, doLabel bool) {
|
|||
p.errorf("%v", err)
|
||||
return
|
||||
}
|
||||
|
||||
case sys.RISCV64:
|
||||
if err := riscv.ParseSuffix(prog, cond); err != nil {
|
||||
p.errorf("unrecognized suffix .%q", cond)
|
||||
return
|
||||
}
|
||||
default:
|
||||
p.errorf("unrecognized suffix .%q", cond)
|
||||
return
|
||||
|
|
|
@ -217,8 +217,8 @@ next:
|
|||
for {
|
||||
tok = p.nextToken()
|
||||
if len(operands) == 0 && len(items) == 0 {
|
||||
if p.arch.InFamily(sys.ARM, sys.ARM64, sys.AMD64, sys.I386) && tok == '.' {
|
||||
// Suffixes: ARM conditionals or x86 modifiers.
|
||||
if p.arch.InFamily(sys.ARM, sys.ARM64, sys.AMD64, sys.I386, sys.RISCV64) && tok == '.' {
|
||||
// Suffixes: ARM conditionals, RISCV rounding mode or x86 modifiers.
|
||||
tok = p.nextToken()
|
||||
str := p.lex.Text()
|
||||
if tok != scanner.Ident {
|
||||
|
|
40
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
40
src/cmd/asm/internal/asm/testdata/riscv64.s
vendored
|
@ -233,11 +233,31 @@ start:
|
|||
|
||||
// 11.7: Single-Precision Floating-Point Conversion and Move Instructions
|
||||
FCVTWS F0, X5 // d31200c0
|
||||
FCVTWS.RNE F0, X5 // d30200c0
|
||||
FCVTWS.RTZ F0, X5 // d31200c0
|
||||
FCVTWS.RDN F0, X5 // d32200c0
|
||||
FCVTWS.RUP F0, X5 // d33200c0
|
||||
FCVTWS.RMM F0, X5 // d34200c0
|
||||
FCVTLS F0, X5 // d31220c0
|
||||
FCVTLS.RNE F0, X5 // d30220c0
|
||||
FCVTLS.RTZ F0, X5 // d31220c0
|
||||
FCVTLS.RDN F0, X5 // d32220c0
|
||||
FCVTLS.RUP F0, X5 // d33220c0
|
||||
FCVTLS.RMM F0, X5 // d34220c0
|
||||
FCVTSW X5, F0 // 538002d0
|
||||
FCVTSL X5, F0 // 538022d0
|
||||
FCVTWUS F0, X5 // d31210c0
|
||||
FCVTWUS.RNE F0, X5 // d30210c0
|
||||
FCVTWUS.RTZ F0, X5 // d31210c0
|
||||
FCVTWUS.RDN F0, X5 // d32210c0
|
||||
FCVTWUS.RUP F0, X5 // d33210c0
|
||||
FCVTWUS.RMM F0, X5 // d34210c0
|
||||
FCVTLUS F0, X5 // d31230c0
|
||||
FCVTLUS.RNE F0, X5 // d30230c0
|
||||
FCVTLUS.RTZ F0, X5 // d31230c0
|
||||
FCVTLUS.RDN F0, X5 // d32230c0
|
||||
FCVTLUS.RUP F0, X5 // d33230c0
|
||||
FCVTLUS.RMM F0, X5 // d34230c0
|
||||
FCVTSWU X5, F0 // 538012d0
|
||||
FCVTSLU X5, F0 // 538032d0
|
||||
FSGNJS F1, F0, F2 // 53011020
|
||||
|
@ -277,11 +297,31 @@ start:
|
|||
|
||||
// 12.5: Double-Precision Floating-Point Conversion and Move Instructions
|
||||
FCVTWD F0, X5 // d31200c2
|
||||
FCVTWD.RNE F0, X5 // d30200c2
|
||||
FCVTWD.RTZ F0, X5 // d31200c2
|
||||
FCVTWD.RDN F0, X5 // d32200c2
|
||||
FCVTWD.RUP F0, X5 // d33200c2
|
||||
FCVTWD.RMM F0, X5 // d34200c2
|
||||
FCVTLD F0, X5 // d31220c2
|
||||
FCVTLD.RNE F0, X5 // d30220c2
|
||||
FCVTLD.RTZ F0, X5 // d31220c2
|
||||
FCVTLD.RDN F0, X5 // d32220c2
|
||||
FCVTLD.RUP F0, X5 // d33220c2
|
||||
FCVTLD.RMM F0, X5 // d34220c2
|
||||
FCVTDW X5, F0 // 538002d2
|
||||
FCVTDL X5, F0 // 538022d2
|
||||
FCVTWUD F0, X5 // d31210c2
|
||||
FCVTWUD.RNE F0, X5 // d30210c2
|
||||
FCVTWUD.RTZ F0, X5 // d31210c2
|
||||
FCVTWUD.RDN F0, X5 // d32210c2
|
||||
FCVTWUD.RUP F0, X5 // d33210c2
|
||||
FCVTWUD.RMM F0, X5 // d34210c2
|
||||
FCVTLUD F0, X5 // d31230c2
|
||||
FCVTLUD.RNE F0, X5 // d30230c2
|
||||
FCVTLUD.RTZ F0, X5 // d31230c2
|
||||
FCVTLUD.RDN F0, X5 // d32230c2
|
||||
FCVTLUD.RUP F0, X5 // d33230c2
|
||||
FCVTLUD.RMM F0, X5 // d34230c2
|
||||
FCVTDWU X5, F0 // 538012d2
|
||||
FCVTDLU X5, F0 // 538032d2
|
||||
FCVTSD F0, F1 // d3001040
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2024 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.
|
||||
|
||||
//go:build (ppc64 || ppc64le) && internal
|
||||
|
||||
package cgotest
|
||||
|
||||
import "testing"
|
||||
|
||||
// If gcc is used, and linking internally, __mulsc3 and __muldc3
|
||||
// will be linked in from libgcc which make several R_PPC64_TOC16_DS
|
||||
// relocations which may not be resolvable with the internal linker.
|
||||
func test8694(t *testing.T) { t.Skip("not supported on ppc64/ppc64le with internal linking") }
|
||||
func test9510(t *testing.T) { t.Skip("not supported on ppc64/ppc64le with internal linking") }
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !android
|
||||
//go:build !android && !((ppc64 || ppc64le) && internal)
|
||||
|
||||
package cgotest
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build cgo
|
||||
//go:build cgo && !((ppc64 || ppc64le) && internal)
|
||||
|
||||
// Test that we can link together two different cgo packages that both
|
||||
// use the same libgcc function.
|
||||
|
|
|
@ -218,10 +218,10 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir
|
|||
}
|
||||
typename := dwarf.InfoPrefix + types.TypeSymName(n.Type())
|
||||
decls = append(decls, n)
|
||||
abbrev := dwarf.DW_ABRV_AUTO_LOCLIST
|
||||
tag := dwarf.DW_TAG_variable
|
||||
isReturnValue := (n.Class == ir.PPARAMOUT)
|
||||
if n.Class == ir.PPARAM || n.Class == ir.PPARAMOUT {
|
||||
abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
|
||||
tag = dwarf.DW_TAG_formal_parameter
|
||||
}
|
||||
if n.Esc() == ir.EscHeap {
|
||||
// The variable in question has been promoted to the heap.
|
||||
|
@ -233,7 +233,7 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir
|
|||
if n.InlFormal() || n.InlLocal() {
|
||||
inlIndex = posInlIndex(n.Pos()) + 1
|
||||
if n.InlFormal() {
|
||||
abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
|
||||
tag = dwarf.DW_TAG_formal_parameter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -241,7 +241,8 @@ func createDwarfVars(fnsym *obj.LSym, complexOK bool, fn *ir.Func, apDecls []*ir
|
|||
vars = append(vars, &dwarf.Var{
|
||||
Name: n.Sym().Name,
|
||||
IsReturnValue: isReturnValue,
|
||||
Abbrev: abbrev,
|
||||
Tag: tag,
|
||||
WithLoclist: true,
|
||||
StackOffset: int32(n.FrameOffset()),
|
||||
Type: base.Ctxt.Lookup(typename),
|
||||
DeclFile: declpos.RelFilename(),
|
||||
|
@ -350,7 +351,7 @@ func createSimpleVars(fnsym *obj.LSym, apDecls []*ir.Name) ([]*ir.Name, []*dwarf
|
|||
}
|
||||
|
||||
func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
|
||||
var abbrev int
|
||||
var tag int
|
||||
var offs int64
|
||||
|
||||
localAutoOffset := func() int64 {
|
||||
|
@ -367,9 +368,9 @@ func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
|
|||
switch n.Class {
|
||||
case ir.PAUTO:
|
||||
offs = localAutoOffset()
|
||||
abbrev = dwarf.DW_ABRV_AUTO
|
||||
tag = dwarf.DW_TAG_variable
|
||||
case ir.PPARAM, ir.PPARAMOUT:
|
||||
abbrev = dwarf.DW_ABRV_PARAM
|
||||
tag = dwarf.DW_TAG_formal_parameter
|
||||
if n.IsOutputParamInRegisters() {
|
||||
offs = localAutoOffset()
|
||||
} else {
|
||||
|
@ -387,7 +388,7 @@ func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
|
|||
if n.InlFormal() || n.InlLocal() {
|
||||
inlIndex = posInlIndex(n.Pos()) + 1
|
||||
if n.InlFormal() {
|
||||
abbrev = dwarf.DW_ABRV_PARAM
|
||||
tag = dwarf.DW_TAG_formal_parameter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -396,7 +397,7 @@ func createSimpleVar(fnsym *obj.LSym, n *ir.Name) *dwarf.Var {
|
|||
Name: n.Sym().Name,
|
||||
IsReturnValue: n.Class == ir.PPARAMOUT,
|
||||
IsInlFormal: n.InlFormal(),
|
||||
Abbrev: abbrev,
|
||||
Tag: tag,
|
||||
StackOffset: int32(offs),
|
||||
Type: base.Ctxt.Lookup(typename),
|
||||
DeclFile: declpos.RelFilename(),
|
||||
|
@ -470,12 +471,12 @@ func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var
|
|||
debug := fn.DebugInfo.(*ssa.FuncDebug)
|
||||
n := debug.Vars[varID]
|
||||
|
||||
var abbrev int
|
||||
var tag int
|
||||
switch n.Class {
|
||||
case ir.PAUTO:
|
||||
abbrev = dwarf.DW_ABRV_AUTO_LOCLIST
|
||||
tag = dwarf.DW_TAG_variable
|
||||
case ir.PPARAM, ir.PPARAMOUT:
|
||||
abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
|
||||
tag = dwarf.DW_TAG_formal_parameter
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
@ -488,7 +489,7 @@ func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var
|
|||
if n.InlFormal() || n.InlLocal() {
|
||||
inlIndex = posInlIndex(n.Pos()) + 1
|
||||
if n.InlFormal() {
|
||||
abbrev = dwarf.DW_ABRV_PARAM_LOCLIST
|
||||
tag = dwarf.DW_TAG_formal_parameter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -497,7 +498,8 @@ func createComplexVar(fnsym *obj.LSym, fn *ir.Func, varID ssa.VarID) *dwarf.Var
|
|||
Name: n.Sym().Name,
|
||||
IsReturnValue: n.Class == ir.PPARAMOUT,
|
||||
IsInlFormal: n.InlFormal(),
|
||||
Abbrev: abbrev,
|
||||
Tag: tag,
|
||||
WithLoclist: true,
|
||||
Type: base.Ctxt.Lookup(typename),
|
||||
// The stack offset is used as a sorting key, so for decomposed
|
||||
// variables just give it the first one. It's not used otherwise.
|
||||
|
|
|
@ -358,7 +358,7 @@ func dumpInlCalls(inlcalls dwarf.InlCalls) {
|
|||
func dumpInlVars(dwvars []*dwarf.Var) {
|
||||
for i, dwv := range dwvars {
|
||||
typ := "local"
|
||||
if dwv.Abbrev == dwarf.DW_ABRV_PARAM_LOCLIST || dwv.Abbrev == dwarf.DW_ABRV_PARAM {
|
||||
if dwv.Tag == dwarf.DW_TAG_formal_parameter {
|
||||
typ = "param"
|
||||
}
|
||||
ia := 0
|
||||
|
|
|
@ -3620,6 +3620,57 @@ func usedLocals(body []ir.Node) ir.NameSet {
|
|||
}
|
||||
|
||||
// @@@ Method wrappers
|
||||
//
|
||||
// Here we handle constructing "method wrappers," alternative entry
|
||||
// points that adapt methods to different calling conventions. Given a
|
||||
// user-declared method "func (T) M(i int) bool { ... }", there are a
|
||||
// few wrappers we may need to construct:
|
||||
//
|
||||
// - Implicit dereferencing. Methods declared with a value receiver T
|
||||
// are also included in the method set of the pointer type *T, so
|
||||
// we need to construct a wrapper like "func (recv *T) M(i int)
|
||||
// bool { return (*recv).M(i) }".
|
||||
//
|
||||
// - Promoted methods. If struct type U contains an embedded field of
|
||||
// type T or *T, we need to construct a wrapper like "func (recv U)
|
||||
// M(i int) bool { return recv.T.M(i) }".
|
||||
//
|
||||
// - Method values. If x is an expression of type T, then "x.M" is
|
||||
// roughly "tmp := x; func(i int) bool { return tmp.M(i) }".
|
||||
//
|
||||
// At call sites, we always prefer to call the user-declared method
|
||||
// directly, if known, so wrappers are only needed for indirect calls
|
||||
// (for example, interface method calls that can't be devirtualized).
|
||||
// Consequently, we can save some compile time by skipping
|
||||
// construction of wrappers that are never needed.
|
||||
//
|
||||
// Alternatively, because the linker doesn't care which compilation
|
||||
// unit constructed a particular wrapper, we can instead construct
|
||||
// them as needed. However, if a wrapper is needed in multiple
|
||||
// downstream packages, we may end up needing to compile it multiple
|
||||
// times, costing us more compile time and object file size. (We mark
|
||||
// the wrappers as DUPOK, so the linker doesn't complain about the
|
||||
// duplicate symbols.)
|
||||
//
|
||||
// The current heuristics we use to balance these trade offs are:
|
||||
//
|
||||
// - For a (non-parameterized) defined type T, we construct wrappers
|
||||
// for *T and any promoted methods on T (and *T) in the same
|
||||
// compilation unit as the type declaration.
|
||||
//
|
||||
// - For a parameterized defined type, we construct wrappers in the
|
||||
// compilation units in which the type is instantiated. We
|
||||
// similarly handle wrappers for anonymous types with methods and
|
||||
// compilation units where their type literals appear in source.
|
||||
//
|
||||
// - Method value expressions are relatively uncommon, so we
|
||||
// construct their wrappers in the compilation units that they
|
||||
// appear in.
|
||||
//
|
||||
// Finally, as an opportunistic compile-time optimization, if we know
|
||||
// a wrapper was constructed in any imported package's compilation
|
||||
// unit, then we skip constructing a duplicate one. However, currently
|
||||
// this is only done on a best-effort basis.
|
||||
|
||||
// needWrapperTypes lists types for which we may need to generate
|
||||
// method wrappers.
|
||||
|
@ -3643,6 +3694,8 @@ type methodValueWrapper struct {
|
|||
method *types.Field
|
||||
}
|
||||
|
||||
// needWrapper records that wrapper methods may be needed at link
|
||||
// time.
|
||||
func (r *reader) needWrapper(typ *types.Type) {
|
||||
if typ.IsPtr() {
|
||||
return
|
||||
|
@ -3676,6 +3729,8 @@ func (r *reader) importedDef() bool {
|
|||
return r.p != localPkgReader && !r.hasTypeParams()
|
||||
}
|
||||
|
||||
// MakeWrappers constructs all wrapper methods needed for the target
|
||||
// compilation unit.
|
||||
func MakeWrappers(target *ir.Package) {
|
||||
// always generate a wrapper for error.Error (#29304)
|
||||
needWrapperTypes = append(needWrapperTypes, types.ErrorType)
|
||||
|
@ -3811,7 +3866,6 @@ func wrapMethodValue(recvType *types.Type, method *types.Field, target *ir.Packa
|
|||
|
||||
func newWrapperFunc(pos src.XPos, sym *types.Sym, wrapper *types.Type, method *types.Field) *ir.Func {
|
||||
sig := newWrapperType(wrapper, method)
|
||||
|
||||
fn := ir.NewFunc(pos, pos, sym, sig)
|
||||
fn.DeclareParams(true)
|
||||
fn.SetDupok(true) // TODO(mdempsky): Leave unset for local, non-generic wrappers?
|
||||
|
|
|
@ -1217,10 +1217,17 @@ func (w *writer) stmt(stmt syntax.Stmt) {
|
|||
func (w *writer) stmts(stmts []syntax.Stmt) {
|
||||
dead := false
|
||||
w.Sync(pkgbits.SyncStmts)
|
||||
for _, stmt := range stmts {
|
||||
if dead {
|
||||
// Any statements after a terminating statement are safe to
|
||||
// omit, at least until the next labeled statement.
|
||||
var lastLabel = -1
|
||||
for i, stmt := range stmts {
|
||||
if _, ok := stmt.(*syntax.LabeledStmt); ok {
|
||||
lastLabel = i
|
||||
}
|
||||
}
|
||||
for i, stmt := range stmts {
|
||||
if dead && i > lastLabel {
|
||||
// Any statements after a terminating and last label statement are safe to omit.
|
||||
// Otherwise, code after label statement may refer to dead stmts between terminating
|
||||
// and label statement, see issue #65593.
|
||||
if _, ok := stmt.(*syntax.LabeledStmt); !ok {
|
||||
continue
|
||||
}
|
||||
|
|
|
@ -1498,39 +1498,6 @@ func (a typesByString) Less(i, j int) bool {
|
|||
}
|
||||
func (a typesByString) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
||||
|
||||
// maxPtrmaskBytes is the maximum length of a GC ptrmask bitmap,
|
||||
// which holds 1-bit entries describing where pointers are in a given type.
|
||||
// Above this length, the GC information is recorded as a GC program,
|
||||
// which can express repetition compactly. In either form, the
|
||||
// information is used by the runtime to initialize the heap bitmap,
|
||||
// and for large types (like 128 or more words), they are roughly the
|
||||
// same speed. GC programs are never much larger and often more
|
||||
// compact. (If large arrays are involved, they can be arbitrarily
|
||||
// more compact.)
|
||||
//
|
||||
// The cutoff must be large enough that any allocation large enough to
|
||||
// use a GC program is large enough that it does not share heap bitmap
|
||||
// bytes with any other objects, allowing the GC program execution to
|
||||
// assume an aligned start and not use atomic operations. In the current
|
||||
// runtime, this means all malloc size classes larger than the cutoff must
|
||||
// be multiples of four words. On 32-bit systems that's 16 bytes, and
|
||||
// all size classes >= 16 bytes are 16-byte aligned, so no real constraint.
|
||||
// On 64-bit systems, that's 32 bytes, and 32-byte alignment is guaranteed
|
||||
// for size classes >= 256 bytes. On a 64-bit system, 256 bytes allocated
|
||||
// is 32 pointers, the bits for which fit in 4 bytes. So maxPtrmaskBytes
|
||||
// must be >= 4.
|
||||
//
|
||||
// We used to use 16 because the GC programs do have some constant overhead
|
||||
// to get started, and processing 128 pointers seems to be enough to
|
||||
// amortize that overhead well.
|
||||
//
|
||||
// To make sure that the runtime's chansend can call typeBitsBulkBarrier,
|
||||
// we raised the limit to 2048, so that even 32-bit systems are guaranteed to
|
||||
// use bitmaps for objects up to 64 kB in size.
|
||||
//
|
||||
// Also known to reflect/type.go.
|
||||
const maxPtrmaskBytes = 2048
|
||||
|
||||
// GCSym returns a data symbol containing GC information for type t, along
|
||||
// with a boolean reporting whether the UseGCProg bit should be set in the
|
||||
// type kind, and the ptrdata field to record in the reflect type information.
|
||||
|
@ -1553,7 +1520,7 @@ func GCSym(t *types.Type) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
|
|||
// When write is true, it writes the symbol data.
|
||||
func dgcsym(t *types.Type, write bool) (lsym *obj.LSym, useGCProg bool, ptrdata int64) {
|
||||
ptrdata = types.PtrDataSize(t)
|
||||
if ptrdata/int64(types.PtrSize) <= maxPtrmaskBytes*8 {
|
||||
if ptrdata/int64(types.PtrSize) <= abi.MaxPtrmaskBytes*8 {
|
||||
lsym = dgcptrmask(t, write)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -2131,8 +2131,8 @@ func logicFlags32(x int32) flagConstant {
|
|||
|
||||
func makeJumpTableSym(b *Block) *obj.LSym {
|
||||
s := base.Ctxt.Lookup(fmt.Sprintf("%s.jump%d", b.Func.fe.Func().LSym.Name, b.ID))
|
||||
s.Set(obj.AttrDuplicateOK, true)
|
||||
s.Set(obj.AttrLocal, true)
|
||||
// The jump table symbol is accessed only from the function symbol.
|
||||
s.Set(obj.AttrStatic, true)
|
||||
return s
|
||||
}
|
||||
|
||||
|
|
|
@ -267,7 +267,9 @@ func (p *parser) syntaxErrorAt(pos Pos, msg string) {
|
|||
// determine token string
|
||||
var tok string
|
||||
switch p.tok {
|
||||
case _Name, _Semi:
|
||||
case _Name:
|
||||
tok = "`" + p.lit + "'"
|
||||
case _Semi:
|
||||
tok = p.lit
|
||||
case _Literal:
|
||||
tok = "literal " + p.lit
|
||||
|
|
|
@ -6,4 +6,4 @@
|
|||
// Line 9 must end in EOF for this test (no newline).
|
||||
|
||||
package e
|
||||
func([<-chan<-[func /* ERROR unexpected u */ u){go
|
||||
func([<-chan<-[func /* ERROR unexpected `u' */ u){go
|
|
@ -7,7 +7,7 @@ package p
|
|||
func _() {
|
||||
_ = m[] // ERROR expected operand
|
||||
_ = m[x,]
|
||||
_ = m[x /* ERROR unexpected a */ a b c d]
|
||||
_ = m[x /* ERROR unexpected `a' */ a b c d]
|
||||
}
|
||||
|
||||
// test case from the issue
|
||||
|
|
|
@ -7,7 +7,7 @@ package p
|
|||
// test case from issue
|
||||
|
||||
type _ interface{
|
||||
m /* ERROR unexpected int in interface type; possibly missing semicolon or newline or } */ int
|
||||
m /* ERROR unexpected `int' in interface type; possibly missing semicolon or newline or } */ int
|
||||
}
|
||||
|
||||
// other cases where the fix for this issue affects the error message
|
||||
|
@ -16,12 +16,12 @@ const (
|
|||
x int = 10 /* ERROR unexpected literal "foo" in grouped declaration; possibly missing semicolon or newline or \) */ "foo"
|
||||
)
|
||||
|
||||
var _ = []int{1, 2, 3 /* ERROR unexpected int in composite literal; possibly missing comma or } */ int }
|
||||
var _ = []int{1, 2, 3 /* ERROR unexpected `int' in composite literal; possibly missing comma or } */ int }
|
||||
|
||||
type _ struct {
|
||||
x y /* ERROR syntax error: unexpected comma in struct type; possibly missing semicolon or newline or } */ ,
|
||||
}
|
||||
|
||||
func f(a, b c /* ERROR unexpected d in parameter list; possibly missing comma or \) */ d) {
|
||||
f(a, b, c /* ERROR unexpected d in argument list; possibly missing comma or \) */ d)
|
||||
func f(a, b c /* ERROR unexpected `d' in parameter list; possibly missing comma or \) */ d) {
|
||||
f(a, b, c /* ERROR unexpected `d' in argument list; possibly missing comma or \) */ d)
|
||||
}
|
||||
|
|
|
@ -13,5 +13,5 @@ type _ interface {
|
|||
(int) | (string)
|
||||
(int) | ~(string)
|
||||
(/* ERROR unexpected ~ */ ~int)
|
||||
(int /* ERROR unexpected \| */ | /* ERROR unexpected string */ string /* ERROR unexpected \) */ )
|
||||
(int /* ERROR unexpected \| */ | /* ERROR unexpected `string' */ string /* ERROR unexpected \) */ )
|
||||
}
|
||||
|
|
14
src/cmd/compile/internal/syntax/testdata/issue65970.go
vendored
Normal file
14
src/cmd/compile/internal/syntax/testdata/issue65970.go
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package p
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func f() {
|
||||
int status // ERROR syntax error: unexpected `status' at end of statement
|
||||
fmt.Println(status)
|
||||
}
|
|
@ -621,19 +621,6 @@ func tcIndex(n *ir.IndexExpr) ir.Node {
|
|||
return n
|
||||
}
|
||||
|
||||
if !n.Bounded() && ir.IsConst(n.Index, constant.Int) {
|
||||
x := n.Index.Val()
|
||||
if constant.Sign(x) < 0 {
|
||||
base.Errorf("invalid %s index %v (index must be non-negative)", why, n.Index)
|
||||
} else if t.IsArray() && constant.Compare(x, token.GEQ, constant.MakeInt64(t.NumElem())) {
|
||||
base.Errorf("invalid array index %v (out of bounds for %d-element array)", n.Index, t.NumElem())
|
||||
} else if ir.IsConst(n.X, constant.String) && constant.Compare(x, token.GEQ, constant.MakeInt64(int64(len(ir.StringVal(n.X))))) {
|
||||
base.Errorf("invalid string index %v (out of bounds for %d-byte string)", n.Index, len(ir.StringVal(n.X)))
|
||||
} else if ir.ConstOverflow(x, types.Types[types.TINT]) {
|
||||
base.Errorf("invalid %s index %v (index too large)", why, n.Index)
|
||||
}
|
||||
}
|
||||
|
||||
case types.TMAP:
|
||||
n.Index = AssignConv(n.Index, t.Key(), "map index")
|
||||
n.SetType(t.Elem())
|
||||
|
|
|
@ -152,7 +152,7 @@ func TestValuesInfo(t *testing.T) {
|
|||
// look for expression
|
||||
var expr syntax.Expr
|
||||
for e := range info.Types {
|
||||
if syntax.String(e) == test.expr {
|
||||
if ExprString(e) == test.expr {
|
||||
expr = e
|
||||
break
|
||||
}
|
||||
|
@ -424,7 +424,7 @@ func TestTypesInfo(t *testing.T) {
|
|||
// look for expression type
|
||||
var typ Type
|
||||
for e, tv := range info.Types {
|
||||
if syntax.String(e) == test.expr {
|
||||
if ExprString(e) == test.expr {
|
||||
typ = tv.Type
|
||||
break
|
||||
}
|
||||
|
@ -1135,8 +1135,8 @@ func TestPredicatesInfo(t *testing.T) {
|
|||
// look for expression predicates
|
||||
got := "<missing>"
|
||||
for e, tv := range info.Types {
|
||||
//println(name, syntax.String(e))
|
||||
if syntax.String(e) == test.expr {
|
||||
//println(name, ExprString(e))
|
||||
if ExprString(e) == test.expr {
|
||||
got = predString(tv)
|
||||
break
|
||||
}
|
||||
|
|
|
@ -24,7 +24,10 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
|||
switch x.mode {
|
||||
case invalid:
|
||||
return // error reported before
|
||||
case constant_, variable, mapindex, value, nilvalue, commaok, commaerr:
|
||||
case nilvalue:
|
||||
assert(isTypes2)
|
||||
// ok
|
||||
case constant_, variable, mapindex, value, commaok, commaerr:
|
||||
// ok
|
||||
default:
|
||||
// we may get here because of other problems (go.dev/issue/39634, crash 12)
|
||||
|
@ -41,14 +44,25 @@ func (check *Checker) assignment(x *operand, T Type, context string) {
|
|||
// bool, rune, int, float64, complex128 or string respectively, depending
|
||||
// on whether the value is a boolean, rune, integer, floating-point,
|
||||
// complex, or string constant."
|
||||
if x.isNil() {
|
||||
if T == nil {
|
||||
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
||||
x.mode = invalid
|
||||
return
|
||||
if isTypes2 {
|
||||
if x.isNil() {
|
||||
if T == nil {
|
||||
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
} else if T == nil || isNonTypeParamInterface(T) {
|
||||
target = Default(x.typ)
|
||||
}
|
||||
} else { // go/types
|
||||
if T == nil || isNonTypeParamInterface(T) {
|
||||
if T == nil && x.typ == Typ[UntypedNil] {
|
||||
check.errorf(x, UntypedNilUse, "use of untyped nil in %s", context)
|
||||
x.mode = invalid
|
||||
return
|
||||
}
|
||||
target = Default(x.typ)
|
||||
}
|
||||
} else if T == nil || isNonTypeParamInterface(T) {
|
||||
target = Default(x.typ)
|
||||
}
|
||||
newType, val, code := check.implicitTypeAndValue(x, target)
|
||||
if code != 0 {
|
||||
|
@ -218,7 +232,7 @@ func (check *Checker) lhsVar(lhs syntax.Expr) Type {
|
|||
var op operand
|
||||
check.expr(nil, &op, sel.X)
|
||||
if op.mode == mapindex {
|
||||
check.errorf(&x, UnaddressableFieldAssign, "cannot assign to struct field %s in map", syntax.String(x.expr))
|
||||
check.errorf(&x, UnaddressableFieldAssign, "cannot assign to struct field %s in map", ExprString(x.expr))
|
||||
return Typ[Invalid]
|
||||
}
|
||||
}
|
||||
|
@ -245,10 +259,10 @@ func (check *Checker) assignVar(lhs, rhs syntax.Expr, x *operand, context string
|
|||
|
||||
if x == nil {
|
||||
var target *target
|
||||
// avoid calling syntax.String if not needed
|
||||
// avoid calling ExprString if not needed
|
||||
if T != nil {
|
||||
if _, ok := under(T).(*Signature); ok {
|
||||
target = newTarget(T, syntax.String(lhs))
|
||||
target = newTarget(T, ExprString(lhs))
|
||||
}
|
||||
}
|
||||
x = new(operand)
|
||||
|
@ -343,12 +357,11 @@ func (check *Checker) returnError(at poser, lhs []*Var, rhs []*operand) {
|
|||
} else if r > 0 {
|
||||
at = rhs[r-1] // report at last value
|
||||
}
|
||||
var err error_
|
||||
err.code = WrongResultCount
|
||||
err.errorf(at, "%s return values", qualifier)
|
||||
err.errorf(nopos, "have %s", check.typesSummary(operandTypes(rhs), false))
|
||||
err.errorf(nopos, "want %s", check.typesSummary(varTypes(lhs), false))
|
||||
check.report(&err)
|
||||
err := check.newError(WrongResultCount)
|
||||
err.addf(at, "%s return values", qualifier)
|
||||
err.addf(nopos, "have %s", check.typesSummary(operandTypes(rhs), false))
|
||||
err.addf(nopos, "want %s", check.typesSummary(varTypes(lhs), false))
|
||||
err.report()
|
||||
}
|
||||
|
||||
// initVars type-checks assignments of initialization expressions orig_rhs
|
||||
|
@ -493,7 +506,7 @@ func (check *Checker) assignVars(lhs, orig_rhs []syntax.Expr) {
|
|||
// orig_rhs[0] was already evaluated
|
||||
}
|
||||
|
||||
func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) {
|
||||
func (check *Checker) shortVarDecl(pos poser, lhs, rhs []syntax.Expr) {
|
||||
top := len(check.delayed)
|
||||
scope := check.scope
|
||||
|
||||
|
@ -506,6 +519,7 @@ func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) {
|
|||
ident, _ := lhs.(*syntax.Name)
|
||||
if ident == nil {
|
||||
check.useLHS(lhs)
|
||||
// TODO(gri) This is redundant with a go/parser error. Consider omitting in go/types?
|
||||
check.errorf(lhs, BadDecl, "non-name %s on left side of :=", lhs)
|
||||
hasErr = true
|
||||
continue
|
||||
|
@ -568,7 +582,7 @@ func (check *Checker) shortVarDecl(pos syntax.Pos, lhs, rhs []syntax.Expr) {
|
|||
// a function begins at the end of the ConstSpec or VarSpec (ShortVarDecl
|
||||
// for short variable declarations) and ends at the end of the innermost
|
||||
// containing block."
|
||||
scopePos := syntax.EndPos(rhs[len(rhs)-1])
|
||||
scopePos := endPos(rhs[len(rhs)-1])
|
||||
for _, obj := range newVars {
|
||||
check.declare(scope, nil, obj, scopePos) // id = nil: recordDef already called
|
||||
}
|
||||
|
|
|
@ -23,8 +23,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
// append is the only built-in that permits the use of ... for the last argument
|
||||
bin := predeclaredFuncs[id]
|
||||
if hasDots(call) && id != _Append {
|
||||
//check.errorf(call.Ellipsis, invalidOp + "invalid use of ... with built-in %s", bin.name)
|
||||
check.errorf(call,
|
||||
check.errorf(dddErrPos(call),
|
||||
InvalidDotDotDot,
|
||||
invalidOp+"invalid use of ... with built-in %s", bin.name)
|
||||
check.use(argList...)
|
||||
|
@ -76,7 +75,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
msg = "too many"
|
||||
}
|
||||
if msg != "" {
|
||||
check.errorf(call, WrongArgCount, invalidOp+"%s arguments for %v (expected %d, found %d)", msg, call, bin.nargs, nargs)
|
||||
check.errorf(argErrPos(call), WrongArgCount, invalidOp+"%s arguments for %v (expected %d, found %d)", msg, call, bin.nargs, nargs)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -909,7 +908,7 @@ func (check *Checker) builtin(x *operand, call *syntax.CallExpr, id builtinId) (
|
|||
// trace is only available in test mode - no need to record signature
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
assert(x.mode != invalid)
|
||||
|
@ -948,7 +947,7 @@ func hasVarSize(t Type, seen map[*Named]bool) (varSized bool) {
|
|||
case *Interface:
|
||||
return isTypeParam(t)
|
||||
case *Named, *Union:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
@ -991,7 +990,7 @@ func (check *Checker) applyTypeFunc(f func(Type) Type, x *operand, id builtinId)
|
|||
case _Complex:
|
||||
code = InvalidComplex
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
check.softErrorf(x, code, "%s not supported as argument to %s for go1.18 (see go.dev/issue/50937)", x, predeclaredFuncs[id].name)
|
||||
|
||||
|
|
|
@ -207,7 +207,7 @@ func testBuiltinSignature(t *testing.T, name, src0, want string) {
|
|||
// the recorded type for the built-in must match the wanted signature
|
||||
typ := types[fun].Type
|
||||
if typ == nil {
|
||||
t.Errorf("%s: no type recorded for %s", src0, syntax.String(fun))
|
||||
t.Errorf("%s: no type recorded for %s", src0, ExprString(fun))
|
||||
return
|
||||
}
|
||||
if got := typ.String(); got != want {
|
||||
|
|
|
@ -108,12 +108,11 @@ func (check *Checker) funcInst(T *target, pos syntax.Pos, x *operand, inst *synt
|
|||
// Note that NewTuple(params...) below is (*Tuple)(nil) if len(params) == 0, as desired.
|
||||
tparams, params2 := check.renameTParams(pos, sig.TypeParams().list(), NewTuple(params...))
|
||||
|
||||
var err error_
|
||||
targs = check.infer(pos, tparams, targs, params2.(*Tuple), args, reverse, &err)
|
||||
err := check.newError(CannotInferTypeArgs)
|
||||
targs = check.infer(pos, tparams, targs, params2.(*Tuple), args, reverse, err)
|
||||
if targs == nil {
|
||||
if !err.empty() {
|
||||
err.code = CannotInferTypeArgs
|
||||
check.report(&err)
|
||||
err.report()
|
||||
}
|
||||
x.mode = invalid
|
||||
return nil, nil
|
||||
|
@ -528,12 +527,11 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T
|
|||
if sig.params != nil {
|
||||
params = sig.params.vars
|
||||
}
|
||||
var err error_
|
||||
err.code = WrongArgCount
|
||||
err.errorf(at, "%s arguments in call to %s", qualifier, call.Fun)
|
||||
err.errorf(nopos, "have %s", check.typesSummary(operandTypes(args), false))
|
||||
err.errorf(nopos, "want %s", check.typesSummary(varTypes(params), sig.variadic))
|
||||
check.report(&err)
|
||||
err := check.newError(WrongArgCount)
|
||||
err.addf(at, "%s arguments in call to %s", qualifier, call.Fun)
|
||||
err.addf(nopos, "have %s", check.typesSummary(operandTypes(args), false))
|
||||
err.addf(nopos, "want %s", check.typesSummary(varTypes(params), sig.variadic))
|
||||
err.report()
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -606,15 +604,15 @@ func (check *Checker) arguments(call *syntax.CallExpr, sig *Signature, targs []T
|
|||
|
||||
// infer missing type arguments of callee and function arguments
|
||||
if len(tparams) > 0 {
|
||||
var err error_
|
||||
targs = check.infer(call.Pos(), tparams, targs, sigParams, args, false, &err)
|
||||
err := check.newError(CannotInferTypeArgs)
|
||||
targs = check.infer(call.Pos(), tparams, targs, sigParams, args, false, err)
|
||||
if targs == nil {
|
||||
// TODO(gri) If infer inferred the first targs[:n], consider instantiating
|
||||
// the call signature for better error messages/gopls behavior.
|
||||
// Perhaps instantiate as much as we can, also for arguments.
|
||||
// This will require changes to how infer returns its results.
|
||||
if !err.empty() {
|
||||
check.errorf(err.pos(), CannotInferTypeArgs, "in call to %s, %s", call.Fun, err.msg(check.qualifier))
|
||||
check.errorf(err.pos(), CannotInferTypeArgs, "in call to %s, %s", call.Fun, err.msg())
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -757,7 +755,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *TypeName
|
|||
x.id = exp.id
|
||||
default:
|
||||
check.dump("%v: unexpected object %v", atPos(e.Sel), exp)
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
x.expr = e
|
||||
return
|
||||
|
@ -910,7 +908,7 @@ func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *TypeName
|
|||
check.addDeclDep(obj)
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -513,7 +513,7 @@ func (check *Checker) recordUntyped() {
|
|||
for x, info := range check.untyped {
|
||||
if debug && isTyped(info.typ) {
|
||||
check.dump("%v: %s (type %s) is typed", atPos(x), x, info.typ)
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
check.recordTypeAndValue(x, info.mode, info.typ, info.val)
|
||||
}
|
||||
|
@ -578,7 +578,7 @@ func (check *Checker) recordBuiltinType(f syntax.Expr, sig *Signature) {
|
|||
case *syntax.ParenExpr:
|
||||
f = p.X
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c
|
|||
case Uint64:
|
||||
return 0 <= x
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
// x does not fit into int64
|
||||
|
@ -159,7 +159,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c
|
|||
case UntypedFloat:
|
||||
return true
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
case isComplex(typ):
|
||||
|
@ -191,7 +191,7 @@ func representableConst(x constant.Value, check *Checker, typ *Basic, rounded *c
|
|||
case UntypedComplex:
|
||||
return true
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
case isString(typ):
|
||||
|
|
|
@ -98,17 +98,18 @@ func (check *Checker) conversion(x *operand, T Type) {
|
|||
// given a type explicitly by a constant declaration or conversion,...".
|
||||
if isUntyped(x.typ) {
|
||||
final := T
|
||||
// - For conversions to interfaces, except for untyped nil arguments,
|
||||
// use the argument's default type.
|
||||
// - For conversions to interfaces, except for untyped nil arguments
|
||||
// and isTypes2, use the argument's default type.
|
||||
// - For conversions of untyped constants to non-constant types, also
|
||||
// use the default type (e.g., []byte("foo") should report string
|
||||
// not []byte as type for the constant "foo").
|
||||
// - If !isTypes2, keep untyped nil for untyped nil arguments.
|
||||
// - For constant integer to string conversions, keep the argument type.
|
||||
// (See also the TODO below.)
|
||||
if x.typ == Typ[UntypedNil] {
|
||||
if isTypes2 && x.typ == Typ[UntypedNil] {
|
||||
// ok
|
||||
} else if isNonTypeParamInterface(T) || constArg && !isConstType(T) {
|
||||
final = Default(x.typ)
|
||||
} else if isNonTypeParamInterface(T) || constArg && !isConstType(T) || !isTypes2 && x.isNil() {
|
||||
final = Default(x.typ) // default type of untyped nil is untyped nil
|
||||
} else if x.mode == constant_ && isInteger(x.typ) && allString(T) {
|
||||
final = x.typ
|
||||
}
|
||||
|
@ -227,7 +228,7 @@ func (x *operand) convertibleTo(check *Checker, T Type, cause *string) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
errorf := func(format string, args ...interface{}) {
|
||||
errorf := func(format string, args ...any) {
|
||||
if check != nil && cause != nil {
|
||||
msg := check.sprintf(format, args...)
|
||||
if *cause != "" {
|
||||
|
|
|
@ -16,7 +16,7 @@ func (err *error_) recordAltDecl(obj Object) {
|
|||
// We use "other" rather than "previous" here because
|
||||
// the first declaration seen may not be textually
|
||||
// earlier in the source.
|
||||
err.errorf(pos, "other declaration of %s", obj.Name())
|
||||
err.addf(pos, "other declaration of %s", obj.Name())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,11 +27,10 @@ func (check *Checker) declare(scope *Scope, id *syntax.Name, obj Object, pos syn
|
|||
// binding."
|
||||
if obj.Name() != "_" {
|
||||
if alt := scope.Insert(obj); alt != nil {
|
||||
var err error_
|
||||
err.code = DuplicateDecl
|
||||
err.errorf(obj, "%s redeclared in this block", obj.Name())
|
||||
err := check.newError(DuplicateDecl)
|
||||
err.addf(obj, "%s redeclared in this block", obj.Name())
|
||||
err.recordAltDecl(alt)
|
||||
check.report(&err)
|
||||
err.report()
|
||||
return
|
||||
}
|
||||
obj.setScopePos(pos)
|
||||
|
@ -162,7 +161,7 @@ func (check *Checker) objDecl(obj Object, def *TypeName) {
|
|||
}
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
assert(obj.Type() != nil)
|
||||
return
|
||||
|
@ -171,7 +170,7 @@ func (check *Checker) objDecl(obj Object, def *TypeName) {
|
|||
d := check.objMap[obj]
|
||||
if d == nil {
|
||||
check.dump("%v: %s should have been declared", obj.Pos(), obj)
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// save/restore current environment and set up object environment
|
||||
|
@ -202,7 +201,7 @@ func (check *Checker) objDecl(obj Object, def *TypeName) {
|
|||
// functions may be recursive - no need to track dependencies
|
||||
check.funcDecl(obj, d)
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -216,7 +215,7 @@ func (check *Checker) validCycle(obj Object) (valid bool) {
|
|||
isPkgObj := obj.Parent() == check.pkg.scope
|
||||
if isPkgObj != inObjMap {
|
||||
check.dump("%v: inconsistent object map for %s (isPkgObj = %v, inObjMap = %v)", obj.Pos(), obj, isPkgObj, inObjMap)
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -266,7 +265,7 @@ loop:
|
|||
case *Func:
|
||||
// ignored for now
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,15 +342,14 @@ func (check *Checker) cycleError(cycle []Object) {
|
|||
return
|
||||
}
|
||||
|
||||
var err error_
|
||||
err.code = InvalidDeclCycle
|
||||
err := check.newError(InvalidDeclCycle)
|
||||
if tname != nil {
|
||||
err.errorf(obj, "invalid recursive type %s", objName)
|
||||
err.addf(obj, "invalid recursive type %s", objName)
|
||||
} else {
|
||||
err.errorf(obj, "invalid cycle in declaration of %s", objName)
|
||||
err.addf(obj, "invalid cycle in declaration of %s", objName)
|
||||
}
|
||||
for range cycle {
|
||||
err.errorf(obj, "%s refers to", objName)
|
||||
err.addf(obj, "%s refers to", objName)
|
||||
i++
|
||||
if i >= len(cycle) {
|
||||
i = 0
|
||||
|
@ -359,8 +357,8 @@ func (check *Checker) cycleError(cycle []Object) {
|
|||
obj = cycle[i]
|
||||
objName = name(obj)
|
||||
}
|
||||
err.errorf(obj, "%s", objName)
|
||||
check.report(&err)
|
||||
err.addf(obj, "%s", objName)
|
||||
err.report()
|
||||
}
|
||||
|
||||
// firstInSrc reports the index of the object with the "smallest"
|
||||
|
@ -433,7 +431,7 @@ func (check *Checker) varDecl(obj *Var, lhs []*Var, typ, init syntax.Expr) {
|
|||
// if any, would not be checked.
|
||||
//
|
||||
// TODO(gri) If we have no init expr, we should distribute
|
||||
// a given type otherwise we need to re-evalate the type
|
||||
// a given type otherwise we need to re-evaluate the type
|
||||
// expr for each lhs variable, leading to duplicate work.
|
||||
}
|
||||
|
||||
|
@ -721,11 +719,10 @@ func (check *Checker) checkFieldUniqueness(base *Named) {
|
|||
|
||||
// For historical consistency, we report the primary error on the
|
||||
// method, and the alt decl on the field.
|
||||
var err error_
|
||||
err.code = DuplicateFieldAndMethod
|
||||
err.errorf(alt, "field and method with the same name %s", fld.name)
|
||||
err := check.newError(DuplicateFieldAndMethod)
|
||||
err.addf(alt, "field and method with the same name %s", fld.name)
|
||||
err.recordAltDecl(fld)
|
||||
check.report(&err)
|
||||
err.report()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,16 +28,22 @@ func assert(p bool) {
|
|||
}
|
||||
}
|
||||
|
||||
func unreachable() {
|
||||
panic("unreachable")
|
||||
// An error_ represents a type-checking error.
|
||||
// A new error_ is created with Checker.newError.
|
||||
// To report an error_, call error_.report.
|
||||
type error_ struct {
|
||||
check *Checker
|
||||
desc []errorDesc
|
||||
code Code
|
||||
soft bool // TODO(gri) eventually determine this from an error code
|
||||
}
|
||||
|
||||
// An error_ represents a type-checking error.
|
||||
// To report an error_, call Checker.report.
|
||||
type error_ struct {
|
||||
desc []errorDesc
|
||||
code Code
|
||||
soft bool // TODO(gri) eventually determine this from an error code
|
||||
// newError returns a new error_ with the given error code.
|
||||
func (check *Checker) newError(code Code) *error_ {
|
||||
if code == 0 {
|
||||
panic("error code must not be 0")
|
||||
}
|
||||
return &error_{check: check, code: code}
|
||||
}
|
||||
|
||||
// An errorDesc describes part of a type-checking error.
|
||||
|
@ -58,10 +64,12 @@ func (err *error_) pos() syntax.Pos {
|
|||
return err.desc[0].pos
|
||||
}
|
||||
|
||||
func (err *error_) msg(qf Qualifier) string {
|
||||
// msg returns the formatted error message without the primary error position pos().
|
||||
func (err *error_) msg() string {
|
||||
if err.empty() {
|
||||
return "no error"
|
||||
}
|
||||
|
||||
var buf strings.Builder
|
||||
for i := range err.desc {
|
||||
p := &err.desc[i]
|
||||
|
@ -71,22 +79,18 @@ func (err *error_) msg(qf Qualifier) string {
|
|||
fmt.Fprintf(&buf, "%s: ", p.pos)
|
||||
}
|
||||
}
|
||||
buf.WriteString(sprintf(qf, false, p.format, p.args...))
|
||||
buf.WriteString(err.check.sprintf(p.format, p.args...))
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// String is for testing.
|
||||
func (err *error_) String() string {
|
||||
if err.empty() {
|
||||
return "no error"
|
||||
}
|
||||
return fmt.Sprintf("%s: %s", err.pos(), err.msg(nil))
|
||||
}
|
||||
|
||||
// errorf adds formatted error information to err.
|
||||
// addf adds formatted error information to err.
|
||||
// It may be called multiple times to provide additional information.
|
||||
func (err *error_) errorf(at poser, format string, args ...interface{}) {
|
||||
// The position of the first call to addf determines the position of the reported Error.
|
||||
// Subsequent calls to addf provide additional information in the form of additional lines
|
||||
// in the error message (types2) or continuation errors identified by a tab-indented error
|
||||
// message (go/types).
|
||||
func (err *error_) addf(at poser, format string, args ...interface{}) {
|
||||
err.desc = append(err.desc, errorDesc{atPos(at), format, args})
|
||||
}
|
||||
|
||||
|
@ -102,7 +106,7 @@ func sprintf(qf Qualifier, tpSubscripts bool, format string, args ...interface{}
|
|||
case syntax.Pos:
|
||||
arg = a.String()
|
||||
case syntax.Expr:
|
||||
arg = syntax.String(a)
|
||||
arg = ExprString(a)
|
||||
case []syntax.Expr:
|
||||
var buf strings.Builder
|
||||
buf.WriteByte('[')
|
||||
|
@ -110,7 +114,7 @@ func sprintf(qf Qualifier, tpSubscripts bool, format string, args ...interface{}
|
|||
if i > 0 {
|
||||
buf.WriteString(", ")
|
||||
}
|
||||
buf.WriteString(syntax.String(x))
|
||||
buf.WriteString(ExprString(x))
|
||||
}
|
||||
buf.WriteByte(']')
|
||||
arg = buf.String()
|
||||
|
@ -200,13 +204,6 @@ func (check *Checker) sprintf(format string, args ...interface{}) string {
|
|||
return sprintf(qf, false, format, args...)
|
||||
}
|
||||
|
||||
func (check *Checker) report(err *error_) {
|
||||
if err.empty() {
|
||||
panic("no error to report")
|
||||
}
|
||||
check.err(err.pos(), err.code, err.msg(check.qualifier), err.soft)
|
||||
}
|
||||
|
||||
func (check *Checker) trace(pos syntax.Pos, format string, args ...interface{}) {
|
||||
fmt.Printf("%s:\t%s%s\n",
|
||||
pos,
|
||||
|
@ -220,38 +217,48 @@ func (check *Checker) dump(format string, args ...interface{}) {
|
|||
fmt.Println(sprintf(check.qualifier, true, format, args...))
|
||||
}
|
||||
|
||||
func (check *Checker) err(at poser, code Code, msg string, soft bool) {
|
||||
switch code {
|
||||
case InvalidSyntaxTree:
|
||||
// report reports the error err, setting check.firstError if necessary.
|
||||
func (err *error_) report() {
|
||||
if err.empty() {
|
||||
panic("no error to report")
|
||||
}
|
||||
|
||||
msg := err.msg()
|
||||
code := err.code
|
||||
assert(code != 0)
|
||||
if code == InvalidSyntaxTree {
|
||||
msg = "invalid syntax tree: " + msg
|
||||
case 0:
|
||||
panic("no error code provided")
|
||||
}
|
||||
|
||||
// Cheap trick: Don't report errors with messages containing
|
||||
// "invalid operand" or "invalid type" as those tend to be
|
||||
// follow-on errors which don't add useful information. Only
|
||||
// exclude them if these strings are not at the beginning,
|
||||
// and only if we have at least one error already reported.
|
||||
if check.firstErr != nil && (strings.Index(msg, "invalid operand") > 0 || strings.Index(msg, "invalid type") > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
pos := atPos(at)
|
||||
|
||||
// If we are encountering an error while evaluating an inherited
|
||||
// constant initialization expression, pos is the position of in
|
||||
// the original expression, and not of the currently declared
|
||||
// constant identifier. Use the provided errpos instead.
|
||||
// TODO(gri) We may also want to augment the error message and
|
||||
// refer to the position (pos) in the original expression.
|
||||
check := err.check
|
||||
pos := err.pos()
|
||||
if check.errpos.IsKnown() {
|
||||
assert(check.iota != nil)
|
||||
pos = check.errpos
|
||||
}
|
||||
|
||||
if check.conf.Trace {
|
||||
check.trace(pos, "ERROR: %s", msg)
|
||||
}
|
||||
|
||||
// Cheap trick: Don't report errors with messages containing
|
||||
// "invalid operand" or "invalid type" as those tend to be
|
||||
// follow-on errors which don't add useful information. Only
|
||||
// exclude them if these strings are not at the beginning,
|
||||
// and only if we have at least one error already reported.
|
||||
isInvalidErr := strings.Index(msg, "invalid operand") > 0 || strings.Index(msg, "invalid type") > 0
|
||||
if check.firstErr != nil && isInvalidErr {
|
||||
return
|
||||
}
|
||||
|
||||
// If we have a URL for error codes, add a link to the first line.
|
||||
if code != 0 && check.conf.ErrorURL != "" {
|
||||
if check.conf.ErrorURL != "" {
|
||||
u := fmt.Sprintf(check.conf.ErrorURL, code)
|
||||
if i := strings.Index(msg, "\n"); i >= 0 {
|
||||
msg = msg[:i] + u + msg[i:]
|
||||
|
@ -260,20 +267,27 @@ func (check *Checker) err(at poser, code Code, msg string, soft bool) {
|
|||
}
|
||||
}
|
||||
|
||||
err := Error{pos, stripAnnotations(msg), msg, soft, code}
|
||||
if check.firstErr == nil {
|
||||
check.firstErr = err
|
||||
e := Error{
|
||||
Pos: pos,
|
||||
Msg: stripAnnotations(msg),
|
||||
Full: msg,
|
||||
Soft: err.soft,
|
||||
Code: code,
|
||||
}
|
||||
|
||||
if check.conf.Trace {
|
||||
check.trace(pos, "ERROR: %s", msg)
|
||||
if check.firstErr == nil {
|
||||
check.firstErr = e
|
||||
}
|
||||
|
||||
f := check.conf.Error
|
||||
if f == nil {
|
||||
panic(bailout{}) // report only first error
|
||||
}
|
||||
f(err)
|
||||
|
||||
// TODO(gri) If e contains \t-indented sub-errors,
|
||||
// for go/types f must be called for each
|
||||
// of those sub-errors.
|
||||
f(e)
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -286,21 +300,29 @@ type poser interface {
|
|||
}
|
||||
|
||||
func (check *Checker) error(at poser, code Code, msg string) {
|
||||
check.err(at, code, msg, false)
|
||||
err := check.newError(code)
|
||||
err.addf(at, "%s", msg)
|
||||
err.report()
|
||||
}
|
||||
|
||||
func (check *Checker) errorf(at poser, code Code, format string, args ...interface{}) {
|
||||
check.err(at, code, check.sprintf(format, args...), false)
|
||||
err := check.newError(code)
|
||||
err.addf(at, format, args...)
|
||||
err.report()
|
||||
}
|
||||
|
||||
func (check *Checker) softErrorf(at poser, code Code, format string, args ...interface{}) {
|
||||
check.err(at, code, check.sprintf(format, args...), true)
|
||||
err := check.newError(code)
|
||||
err.addf(at, format, args...)
|
||||
err.soft = true
|
||||
err.report()
|
||||
}
|
||||
|
||||
func (check *Checker) versionErrorf(at poser, v goVersion, format string, args ...interface{}) {
|
||||
msg := check.sprintf(format, args...)
|
||||
msg = fmt.Sprintf("%s requires %s or later", msg, v)
|
||||
check.err(at, UnsupportedFeature, msg, true)
|
||||
err := check.newError(UnsupportedFeature)
|
||||
err.addf(at, "%s requires %s or later", msg, v)
|
||||
err.report()
|
||||
}
|
||||
|
||||
// atPos reports the left (= start) position of at.
|
||||
|
|
|
@ -9,19 +9,19 @@ import "testing"
|
|||
func TestError(t *testing.T) {
|
||||
var err error_
|
||||
want := "no error"
|
||||
if got := err.String(); got != want {
|
||||
if got := err.msg(); got != want {
|
||||
t.Errorf("empty error: got %q, want %q", got, want)
|
||||
}
|
||||
|
||||
want = "<unknown position>: foo 42"
|
||||
err.errorf(nopos, "foo %d", 42)
|
||||
if got := err.String(); got != want {
|
||||
want = "foo 42"
|
||||
err.addf(nopos, "foo %d", 42)
|
||||
if got := err.msg(); got != want {
|
||||
t.Errorf("simple error: got %q, want %q", got, want)
|
||||
}
|
||||
|
||||
want = "<unknown position>: foo 42\n\tbar 43"
|
||||
err.errorf(nopos, "bar %d", 43)
|
||||
if got := err.String(); got != want {
|
||||
want = "foo 42\n\tbar 43"
|
||||
err.addf(nopos, "bar %d", 43)
|
||||
if got := err.msg(); got != want {
|
||||
t.Errorf("simple error: got %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -268,7 +268,7 @@ func (check *Checker) updateExprType0(parent, x syntax.Expr, typ Type, final boo
|
|||
// upon assignment or use.
|
||||
if debug {
|
||||
check.dump("%v: found old type(%s): %s (new: %s)", atPos(x), x, old.typ, typ)
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
return
|
||||
|
||||
|
@ -337,7 +337,7 @@ func (check *Checker) updateExprType0(parent, x syntax.Expr, typ Type, final boo
|
|||
}
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// If the new type is not final and still untyped, just
|
||||
|
@ -546,7 +546,7 @@ func (check *Checker) comparison(x, y *operand, op syntax.Operator, switchCase b
|
|||
}
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// comparison is ok
|
||||
|
@ -1042,7 +1042,7 @@ func (check *Checker) exprInternal(T *target, x *operand, e syntax.Expr, hint Ty
|
|||
|
||||
switch e := e.(type) {
|
||||
case nil:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
|
||||
case *syntax.BadExpr:
|
||||
goto Error // error was reported before
|
||||
|
@ -1654,7 +1654,7 @@ func (check *Checker) exclude(x *operand, modeset uint) {
|
|||
msg = "%s is not an expression"
|
||||
code = NotAnExpr
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
check.errorf(x, code, msg, x)
|
||||
x.mode = invalid
|
||||
|
|
|
@ -56,7 +56,7 @@ func (s *gcSizes) Alignof(T Type) (result int64) {
|
|||
return s.WordSize
|
||||
}
|
||||
case *TypeParam, *Union:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
a := s.Sizeof(T) // may be 0 or negative
|
||||
// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
|
||||
|
@ -154,7 +154,7 @@ func (s *gcSizes) Sizeof(T Type) int64 {
|
|||
assert(!isTypeParam(T))
|
||||
return s.WordSize * 2
|
||||
case *TypeParam, *Union:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
return s.WordSize // catch-all
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
|
|||
}
|
||||
}
|
||||
if allFailed {
|
||||
err.errorf(arg, "type %s of %s does not match %s (cannot infer %s)", targ, arg.expr, tpar, typeParamsString(tparams))
|
||||
err.addf(arg, "type %s of %s does not match %s (cannot infer %s)", targ, arg.expr, tpar, typeParamsString(tparams))
|
||||
return
|
||||
}
|
||||
}
|
||||
|
@ -140,12 +140,12 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
|
|||
// the more general CannotInferTypeArgs.
|
||||
if inferred != tpar {
|
||||
if reverse {
|
||||
err.errorf(arg, "inferred type %s for %s does not match type %s of %s", inferred, tpar, targ, arg.expr)
|
||||
err.addf(arg, "inferred type %s for %s does not match type %s of %s", inferred, tpar, targ, arg.expr)
|
||||
} else {
|
||||
err.errorf(arg, "type %s of %s does not match inferred type %s for %s", targ, arg.expr, inferred, tpar)
|
||||
err.addf(arg, "type %s of %s does not match inferred type %s for %s", targ, arg.expr, inferred, tpar)
|
||||
}
|
||||
} else {
|
||||
err.errorf(arg, "type %s of %s does not match %s", targ, arg.expr, tpar)
|
||||
err.addf(arg, "type %s of %s does not match %s", targ, arg.expr, tpar)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -252,7 +252,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
|
|||
// TODO(gri) Type parameters that appear in the constraint and
|
||||
// for which we have type arguments inferred should
|
||||
// use those type arguments for a better error message.
|
||||
err.errorf(pos, "%s (type %s) does not satisfy %s", tpar, tx, tpar.Constraint())
|
||||
err.addf(pos, "%s (type %s) does not satisfy %s", tpar, tx, tpar.Constraint())
|
||||
return nil
|
||||
}
|
||||
case single && !core.tilde:
|
||||
|
@ -277,7 +277,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
|
|||
constraint := tpar.iface()
|
||||
if m, _ := check.missingMethod(tx, constraint, true, func(x, y Type) bool { return u.unify(x, y, exact) }, &cause); m != nil {
|
||||
// TODO(gri) better error message (see TODO above)
|
||||
err.errorf(pos, "%s (type %s) does not satisfy %s %s", tpar, tx, tpar.Constraint(), cause)
|
||||
err.addf(pos, "%s (type %s) does not satisfy %s %s", tpar, tx, tpar.Constraint(), cause)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -318,7 +318,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
|
|||
} else {
|
||||
m := maxType(max, arg.typ)
|
||||
if m == nil {
|
||||
err.errorf(arg, "mismatched types %s and %s (cannot infer %s)", max, arg.typ, tpar)
|
||||
err.addf(arg, "mismatched types %s and %s (cannot infer %s)", max, arg.typ, tpar)
|
||||
return nil
|
||||
}
|
||||
max = m
|
||||
|
@ -427,7 +427,7 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
|
|||
for i, typ := range inferred {
|
||||
if typ == nil || isParameterized(tparams, typ) {
|
||||
obj := tparams[i].obj
|
||||
err.errorf(pos, "cannot infer %s (%s)", obj.name, obj.pos)
|
||||
err.addf(pos, "cannot infer %s (%s)", obj.name, obj.pos)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
|
|
@ -160,17 +160,16 @@ func (check *Checker) reportCycle(cycle []Object) {
|
|||
return
|
||||
}
|
||||
|
||||
var err error_
|
||||
err.code = InvalidInitCycle
|
||||
err.errorf(obj, "initialization cycle for %s", obj.Name())
|
||||
err := check.newError(InvalidInitCycle)
|
||||
err.addf(obj, "initialization cycle for %s", obj.Name())
|
||||
// subtle loop: print cycle[i] for i = 0, n-1, n-2, ... 1 for len(cycle) = n
|
||||
for i := len(cycle) - 1; i >= 0; i-- {
|
||||
err.errorf(obj, "%s refers to", obj.Name())
|
||||
err.addf(obj, "%s refers to", obj.Name())
|
||||
obj = cycle[i]
|
||||
}
|
||||
// print cycle[0] again to close the cycle
|
||||
err.errorf(obj, "%s", obj.Name())
|
||||
check.report(&err)
|
||||
err.addf(obj, "%s", obj.Name())
|
||||
err.report()
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
|
|
@ -698,14 +698,14 @@ func TestIssue51093(t *testing.T) {
|
|||
n++
|
||||
tpar, _ := tv.Type.(*TypeParam)
|
||||
if tpar == nil {
|
||||
t.Fatalf("%s: got type %s, want type parameter", syntax.String(x), tv.Type)
|
||||
t.Fatalf("%s: got type %s, want type parameter", ExprString(x), tv.Type)
|
||||
}
|
||||
if name := tpar.Obj().Name(); name != "P" {
|
||||
t.Fatalf("%s: got type parameter name %s, want P", syntax.String(x), name)
|
||||
t.Fatalf("%s: got type parameter name %s, want P", ExprString(x), name)
|
||||
}
|
||||
// P(val) must not be constant
|
||||
if tv.Value != nil {
|
||||
t.Errorf("%s: got constant value %s (%s), want no constant", syntax.String(x), tv.Value, tv.Value.String())
|
||||
t.Errorf("%s: got constant value %s (%s), want no constant", ExprString(x), tv.Value, tv.Value.String())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -133,12 +133,11 @@ func (check *Checker) blockBranches(all *Scope, parent *block, lstmt *syntax.Lab
|
|||
if name := s.Label.Value; name != "_" {
|
||||
lbl := NewLabel(s.Label.Pos(), check.pkg, name)
|
||||
if alt := all.Insert(lbl); alt != nil {
|
||||
var err error_
|
||||
err.code = DuplicateLabel
|
||||
err := check.newError(DuplicateLabel)
|
||||
err.soft = true
|
||||
err.errorf(lbl.pos, "label %s already declared", name)
|
||||
err.addf(lbl.pos, "label %s already declared", name)
|
||||
err.recordAltDecl(alt)
|
||||
check.report(&err)
|
||||
err.report()
|
||||
// ok to continue
|
||||
} else {
|
||||
b.insert(s)
|
||||
|
|
|
@ -472,7 +472,7 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
|
|||
case field:
|
||||
*cause = check.sprintf("(%s.%s is a field, not a method)", V, m.Name())
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -137,10 +137,9 @@ func (check *Checker) reportInstanceLoop(v int) {
|
|||
|
||||
// TODO(mdempsky): Pivot stack so we report the cycle from the top?
|
||||
|
||||
var err error_
|
||||
err.code = InvalidInstanceCycle
|
||||
err := check.newError(InvalidInstanceCycle)
|
||||
obj0 := check.mono.vertices[v].obj
|
||||
err.errorf(obj0, "instantiation cycle:")
|
||||
err.addf(obj0, "instantiation cycle:")
|
||||
|
||||
qf := RelativeTo(check.pkg)
|
||||
for _, v := range stack {
|
||||
|
@ -151,12 +150,12 @@ func (check *Checker) reportInstanceLoop(v int) {
|
|||
default:
|
||||
panic("unexpected type")
|
||||
case *Named:
|
||||
err.errorf(edge.pos, "%s implicitly parameterized by %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented
|
||||
err.addf(edge.pos, "%s implicitly parameterized by %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented
|
||||
case *TypeParam:
|
||||
err.errorf(edge.pos, "%s instantiated as %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented
|
||||
err.addf(edge.pos, "%s instantiated as %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented
|
||||
}
|
||||
}
|
||||
check.report(&err)
|
||||
err.report()
|
||||
}
|
||||
|
||||
// recordCanon records that tpar is the canonical type parameter
|
||||
|
|
|
@ -11,7 +11,6 @@ import (
|
|||
"cmd/compile/internal/syntax"
|
||||
"fmt"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
. "internal/types/errors"
|
||||
)
|
||||
|
||||
|
@ -27,7 +26,7 @@ const (
|
|||
variable // operand is an addressable variable
|
||||
mapindex // operand is a map index expression (acts like a variable on lhs, commaok on rhs of an assignment)
|
||||
value // operand is a computed value
|
||||
nilvalue // operand is the nil value
|
||||
nilvalue // operand is the nil value - only used by types2
|
||||
commaok // like value, but operand may be used in a comma,ok expression
|
||||
commaerr // like commaok, but second value is error, not boolean
|
||||
cgofunc // operand is a cgo function
|
||||
|
@ -42,7 +41,7 @@ var operandModeString = [...]string{
|
|||
variable: "variable",
|
||||
mapindex: "map index expression",
|
||||
value: "value",
|
||||
nilvalue: "nil",
|
||||
nilvalue: "nil", // only used by types2
|
||||
commaok: "comma, ok expression",
|
||||
commaerr: "comma, error expression",
|
||||
cgofunc: "cgo function",
|
||||
|
@ -109,14 +108,20 @@ func (x *operand) Pos() syntax.Pos {
|
|||
// cgofunc <expr> ( <mode> of type <typ>)
|
||||
func operandString(x *operand, qf Qualifier) string {
|
||||
// special-case nil
|
||||
if x.mode == nilvalue {
|
||||
switch x.typ {
|
||||
case nil, Typ[Invalid]:
|
||||
return "nil (with invalid type)"
|
||||
case Typ[UntypedNil]:
|
||||
if isTypes2 {
|
||||
if x.mode == nilvalue {
|
||||
switch x.typ {
|
||||
case nil, Typ[Invalid]:
|
||||
return "nil (with invalid type)"
|
||||
case Typ[UntypedNil]:
|
||||
return "nil"
|
||||
default:
|
||||
return fmt.Sprintf("nil (of type %s)", TypeString(x.typ, qf))
|
||||
}
|
||||
}
|
||||
} else { // go/types
|
||||
if x.mode == value && x.typ == Typ[UntypedNil] {
|
||||
return "nil"
|
||||
default:
|
||||
return fmt.Sprintf("nil (of type %s)", TypeString(x.typ, qf))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,7 +129,7 @@ func operandString(x *operand, qf Qualifier) string {
|
|||
|
||||
var expr string
|
||||
if x.expr != nil {
|
||||
expr = syntax.String(x.expr)
|
||||
expr = ExprString(x.expr)
|
||||
} else {
|
||||
switch x.mode {
|
||||
case builtin:
|
||||
|
@ -221,10 +226,10 @@ func (x *operand) setConst(k syntax.LitKind, lit string) {
|
|||
case syntax.StringLit:
|
||||
kind = UntypedString
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
val := constant.MakeFromLiteral(lit, kind2tok[k], 0)
|
||||
val := makeFromLiteral(lit, k)
|
||||
if val.Kind() == constant.Unknown {
|
||||
x.mode = invalid
|
||||
x.typ = Typ[Invalid]
|
||||
|
@ -236,7 +241,13 @@ func (x *operand) setConst(k syntax.LitKind, lit string) {
|
|||
}
|
||||
|
||||
// isNil reports whether x is the (untyped) nil value.
|
||||
func (x *operand) isNil() bool { return x.mode == nilvalue }
|
||||
func (x *operand) isNil() bool {
|
||||
if isTypes2 {
|
||||
return x.mode == nilvalue
|
||||
} else { // go/types
|
||||
return x.mode == value && x.typ == Typ[UntypedNil]
|
||||
}
|
||||
}
|
||||
|
||||
// assignableTo reports whether x is assignable to a variable of type T. If the
|
||||
// result is false and a non-nil cause is provided, it may be set to a more
|
||||
|
@ -332,7 +343,7 @@ func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Cod
|
|||
return false, IncompatibleAssign
|
||||
}
|
||||
|
||||
errorf := func(format string, args ...interface{}) {
|
||||
errorf := func(format string, args ...any) {
|
||||
if check != nil && cause != nil {
|
||||
msg := check.sprintf(format, args...)
|
||||
if *cause != "" {
|
||||
|
@ -385,12 +396,3 @@ func (x *operand) assignableTo(check *Checker, T Type, cause *string) (bool, Cod
|
|||
|
||||
return false, IncompatibleAssign
|
||||
}
|
||||
|
||||
// kind2tok translates syntax.LitKinds into token.Tokens.
|
||||
var kind2tok = [...]token.Token{
|
||||
syntax.IntLit: token.INT,
|
||||
syntax.FloatLit: token.FLOAT,
|
||||
syntax.ImagLit: token.IMAG,
|
||||
syntax.RuneLit: token.CHAR,
|
||||
syntax.StringLit: token.STRING,
|
||||
}
|
||||
|
|
|
@ -477,7 +477,7 @@ func (c *comparer) identical(x, y Type, p *ifacePair) bool {
|
|||
// avoid a crash in case of nil type
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
return false
|
||||
|
|
|
@ -314,11 +314,10 @@ func (check *Checker) collectObjects() {
|
|||
// the object may be imported into more than one file scope
|
||||
// concurrently. See go.dev/issue/32154.)
|
||||
if alt := fileScope.Lookup(name); alt != nil {
|
||||
var err error_
|
||||
err.code = DuplicateDecl
|
||||
err.errorf(s.LocalPkgName, "%s redeclared in this block", alt.Name())
|
||||
err := check.newError(DuplicateDecl)
|
||||
err.addf(s.LocalPkgName, "%s redeclared in this block", alt.Name())
|
||||
err.recordAltDecl(alt)
|
||||
check.report(&err)
|
||||
err.report()
|
||||
} else {
|
||||
fileScope.insert(name, obj)
|
||||
check.dotImportMap[dotImportKey{fileScope, name}] = pkgName
|
||||
|
@ -473,17 +472,16 @@ func (check *Checker) collectObjects() {
|
|||
for name, obj := range scope.elems {
|
||||
if alt := pkg.scope.Lookup(name); alt != nil {
|
||||
obj = resolve(name, obj)
|
||||
var err error_
|
||||
err.code = DuplicateDecl
|
||||
err := check.newError(DuplicateDecl)
|
||||
if pkg, ok := obj.(*PkgName); ok {
|
||||
err.errorf(alt, "%s already declared through import of %s", alt.Name(), pkg.Imported())
|
||||
err.addf(alt, "%s already declared through import of %s", alt.Name(), pkg.Imported())
|
||||
err.recordAltDecl(pkg)
|
||||
} else {
|
||||
err.errorf(alt, "%s already declared through dot-import of %s", alt.Name(), obj.Pkg())
|
||||
err.addf(alt, "%s already declared through dot-import of %s", alt.Name(), obj.Pkg())
|
||||
// TODO(gri) dot-imported objects don't have a position; recordAltDecl won't print anything
|
||||
err.recordAltDecl(obj)
|
||||
}
|
||||
check.report(&err)
|
||||
err.report()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
func (check *Checker) isTerminating(s syntax.Stmt, label string) bool {
|
||||
switch s := s.(type) {
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
|
||||
case *syntax.DeclStmt, *syntax.EmptyStmt, *syntax.SendStmt,
|
||||
*syntax.AssignStmt, *syntax.CallStmt:
|
||||
|
@ -108,7 +108,7 @@ func (check *Checker) isTerminatingSwitch(body []*syntax.CaseClause, label strin
|
|||
func hasBreak(s syntax.Stmt, label string, implicit bool) bool {
|
||||
switch s := s.(type) {
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
|
||||
case *syntax.DeclStmt, *syntax.EmptyStmt, *syntax.ExprStmt,
|
||||
*syntax.SendStmt, *syntax.AssignStmt, *syntax.CallStmt,
|
||||
|
|
|
@ -163,7 +163,7 @@ func SelectionString(s *Selection, qf Qualifier) string {
|
|||
case MethodExpr:
|
||||
k = "method expr "
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
var buf bytes.Buffer
|
||||
buf.WriteString(k)
|
||||
|
|
|
@ -186,11 +186,10 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
|
|||
params, variadic := check.collectParams(scope, ftyp.ParamList, true, scopePos)
|
||||
results, _ := check.collectParams(scope, ftyp.ResultList, false, scopePos)
|
||||
scope.Squash(func(obj, alt Object) {
|
||||
var err error_
|
||||
err.code = DuplicateDecl
|
||||
err.errorf(obj, "%s redeclared in this block", obj.Name())
|
||||
err := check.newError(DuplicateDecl)
|
||||
err.addf(obj, "%s redeclared in this block", obj.Name())
|
||||
err.recordAltDecl(alt)
|
||||
check.report(&err)
|
||||
err.report()
|
||||
})
|
||||
|
||||
if recvPar != nil {
|
||||
|
@ -247,7 +246,7 @@ func (check *Checker) funcType(sig *Signature, recvPar *syntax.Field, tparams []
|
|||
case *TypeParam:
|
||||
// The underlying type of a receiver base type cannot be a
|
||||
// type parameter: "type T[P any] P" is not a valid declaration.
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
if cause != "" {
|
||||
check.errorf(recv, InvalidRecv, "invalid receiver type %s (%s)", rtyp, cause)
|
||||
|
|
|
@ -94,7 +94,7 @@ func (s *StdSizes) Alignof(T Type) (result int64) {
|
|||
return s.WordSize
|
||||
}
|
||||
case *TypeParam, *Union:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
a := s.Sizeof(T) // may be 0 or negative
|
||||
// spec: "For a variable x of any type: unsafe.Alignof(x) is at least 1."
|
||||
|
@ -221,7 +221,7 @@ func (s *StdSizes) Sizeof(T Type) int64 {
|
|||
assert(!isTypeParam(T))
|
||||
return s.WordSize * 2
|
||||
case *TypeParam, *Union:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
return s.WordSize // catch-all
|
||||
}
|
||||
|
|
|
@ -186,7 +186,7 @@ func (check *Checker) suspendedCall(keyword string, call syntax.Expr) {
|
|||
case statement:
|
||||
return
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
check.errorf(&x, code, "%s %s %s", keyword, msg, &x)
|
||||
}
|
||||
|
@ -260,11 +260,10 @@ L:
|
|||
// (quadratic algorithm, but these lists tend to be very short)
|
||||
for _, vt := range seen[val] {
|
||||
if Identical(v.typ, vt.typ) {
|
||||
var err error_
|
||||
err.code = DuplicateCase
|
||||
err.errorf(&v, "duplicate case %s in expression switch", &v)
|
||||
err.errorf(vt.pos, "previous case")
|
||||
check.report(&err)
|
||||
err := check.newError(DuplicateCase)
|
||||
err.addf(&v, "duplicate case %s in expression switch", &v)
|
||||
err.addf(vt.pos, "previous case")
|
||||
err.report()
|
||||
continue L
|
||||
}
|
||||
}
|
||||
|
@ -307,11 +306,10 @@ L:
|
|||
if T != nil {
|
||||
Ts = TypeString(T, check.qualifier)
|
||||
}
|
||||
var err error_
|
||||
err.code = DuplicateCase
|
||||
err.errorf(e, "duplicate case %s in type switch", Ts)
|
||||
err.errorf(other, "previous case")
|
||||
check.report(&err)
|
||||
err := check.newError(DuplicateCase)
|
||||
err.addf(e, "duplicate case %s in type switch", Ts)
|
||||
err.addf(other, "previous case")
|
||||
err.report()
|
||||
continue L
|
||||
}
|
||||
}
|
||||
|
@ -350,11 +348,10 @@ L:
|
|||
// if T != nil {
|
||||
// Ts = TypeString(T, check.qualifier)
|
||||
// }
|
||||
// var err error_
|
||||
// err.code = _DuplicateCase
|
||||
// err.errorf(e, "duplicate case %s in type switch", Ts)
|
||||
// err.errorf(other, "previous case")
|
||||
// check.report(&err)
|
||||
// err := check.newError(_DuplicateCase)
|
||||
// err.addf(e, "duplicate case %s in type switch", Ts)
|
||||
// err.addf(other, "previous case")
|
||||
// err.report()
|
||||
// continue L
|
||||
// }
|
||||
// seen[hash] = e
|
||||
|
@ -498,11 +495,10 @@ func (check *Checker) stmt(ctxt stmtContext, s syntax.Stmt) {
|
|||
// with the same name as a result parameter is in scope at the place of the return."
|
||||
for _, obj := range res.vars {
|
||||
if alt := check.lookup(obj.name); alt != nil && alt != obj {
|
||||
var err error_
|
||||
err.code = OutOfScopeResult
|
||||
err.errorf(s, "result parameter %s not in scope at return", obj.name)
|
||||
err.errorf(alt, "inner declaration of %s", obj)
|
||||
check.report(&err)
|
||||
err := check.newError(OutOfScopeResult)
|
||||
err.addf(s, "result parameter %s not in scope at return", obj.name)
|
||||
err.addf(alt, "inner declaration of %s", obj)
|
||||
err.report()
|
||||
// ok to continue
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,11 +200,10 @@ func embeddedFieldIdent(e syntax.Expr) *syntax.Name {
|
|||
|
||||
func (check *Checker) declareInSet(oset *objset, pos syntax.Pos, obj Object) bool {
|
||||
if alt := oset.insert(obj); alt != nil {
|
||||
var err error_
|
||||
err.code = DuplicateDecl
|
||||
err.errorf(pos, "%s redeclared", obj.Name())
|
||||
err := check.newError(DuplicateDecl)
|
||||
err.addf(pos, "%s redeclared", obj.Name())
|
||||
err.recordAltDecl(alt)
|
||||
check.report(&err)
|
||||
err.report()
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -95,6 +95,18 @@ func (subst *subster) typ(typ Type) Type {
|
|||
case *Basic:
|
||||
// nothing to do
|
||||
|
||||
case *Alias:
|
||||
rhs := subst.typ(t.fromRHS)
|
||||
if rhs != t.fromRHS {
|
||||
// This branch cannot be reached because the RHS of an alias
|
||||
// may only contain type parameters of an enclosing function.
|
||||
// Such function bodies are never "instantiated" and thus
|
||||
// substitution is not called on locally declared alias types.
|
||||
// TODO(gri) adjust once parameterized aliases are supported
|
||||
panic("unreachable for unparameterized aliases")
|
||||
// return subst.check.newAlias(t.obj, rhs)
|
||||
}
|
||||
|
||||
case *Array:
|
||||
elem := subst.typOrNil(t.elem)
|
||||
if elem != t.elem {
|
||||
|
@ -271,7 +283,7 @@ func (subst *subster) typ(typ Type) Type {
|
|||
return subst.smap.lookup(t)
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
return typ
|
||||
|
|
|
@ -221,11 +221,10 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
|
|||
mpos[m] = pos
|
||||
case explicit:
|
||||
if check != nil {
|
||||
var err error_
|
||||
err.code = DuplicateDecl
|
||||
err.errorf(pos, "duplicate method %s", m.name)
|
||||
err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name)
|
||||
check.report(&err)
|
||||
err := check.newError(DuplicateDecl)
|
||||
err.addf(pos, "duplicate method %s", m.name)
|
||||
err.addf(mpos[other.(*Func)], "other declaration of %s", m.name)
|
||||
err.report()
|
||||
}
|
||||
default:
|
||||
// We have a duplicate method name in an embedded (not explicitly declared) method.
|
||||
|
@ -236,11 +235,10 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
|
|||
if check != nil {
|
||||
check.later(func() {
|
||||
if !check.allowVersion(m.pkg, pos, go1_14) || !Identical(m.typ, other.Type()) {
|
||||
var err error_
|
||||
err.code = DuplicateDecl
|
||||
err.errorf(pos, "duplicate method %s", m.name)
|
||||
err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name)
|
||||
check.report(&err)
|
||||
err := check.newError(DuplicateDecl)
|
||||
err.addf(pos, "duplicate method %s", m.name)
|
||||
err.addf(mpos[other.(*Func)], "other declaration of %s", m.name)
|
||||
err.report()
|
||||
}
|
||||
}).describef(pos, "duplicate method check for %s", m.name)
|
||||
}
|
||||
|
|
|
@ -16,18 +16,18 @@ import (
|
|||
)
|
||||
|
||||
// A Qualifier controls how named package-level objects are printed in
|
||||
// calls to TypeString, ObjectString, and SelectionString.
|
||||
// calls to [TypeString], [ObjectString], and [SelectionString].
|
||||
//
|
||||
// These three formatting routines call the Qualifier for each
|
||||
// package-level object O, and if the Qualifier returns a non-empty
|
||||
// string p, the object is printed in the form p.O.
|
||||
// If it returns an empty string, only the object name O is printed.
|
||||
//
|
||||
// Using a nil Qualifier is equivalent to using (*Package).Path: the
|
||||
// Using a nil Qualifier is equivalent to using (*[Package]).Path: the
|
||||
// object is qualified by the import path, e.g., "encoding/json.Marshal".
|
||||
type Qualifier func(*Package) string
|
||||
|
||||
// RelativeTo returns a Qualifier that fully qualifies members of
|
||||
// RelativeTo returns a [Qualifier] that fully qualifies members of
|
||||
// all packages other than pkg.
|
||||
func RelativeTo(pkg *Package) Qualifier {
|
||||
if pkg == nil {
|
||||
|
@ -42,7 +42,7 @@ func RelativeTo(pkg *Package) Qualifier {
|
|||
}
|
||||
|
||||
// TypeString returns the string representation of typ.
|
||||
// The Qualifier controls the printing of
|
||||
// The [Qualifier] controls the printing of
|
||||
// package-level objects, and may be nil.
|
||||
func TypeString(typ Type, qf Qualifier) string {
|
||||
var buf bytes.Buffer
|
||||
|
@ -51,14 +51,14 @@ func TypeString(typ Type, qf Qualifier) string {
|
|||
}
|
||||
|
||||
// WriteType writes the string representation of typ to buf.
|
||||
// The Qualifier controls the printing of
|
||||
// The [Qualifier] controls the printing of
|
||||
// package-level objects, and may be nil.
|
||||
func WriteType(buf *bytes.Buffer, typ Type, qf Qualifier) {
|
||||
newTypeWriter(buf, qf).typ(typ)
|
||||
}
|
||||
|
||||
// WriteSignature writes the representation of the signature sig to buf,
|
||||
// without a leading "func" keyword. The Qualifier controls the printing
|
||||
// without a leading "func" keyword. The [Qualifier] controls the printing
|
||||
// of package-level objects, and may be nil.
|
||||
func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
|
||||
newTypeWriter(buf, qf).signature(sig)
|
||||
|
@ -322,7 +322,13 @@ func (w *typeWriter) typ(typ Type) {
|
|||
// error messages. This doesn't need to be super-elegant; we just
|
||||
// need a clear indication that this is not a predeclared name.
|
||||
if w.ctxt == nil && Universe.Lookup(t.obj.name) != nil {
|
||||
w.string(fmt.Sprintf(" /* with %s declared at %s */", t.obj.name, t.obj.Pos()))
|
||||
if isTypes2 {
|
||||
w.string(fmt.Sprintf(" /* with %s declared at %v */", t.obj.name, t.obj.Pos()))
|
||||
} else {
|
||||
// Can't print position information because
|
||||
// we don't have a token.FileSet accessible.
|
||||
w.string("/* type parameter */")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -139,7 +139,7 @@ func (check *Checker) ident(x *operand, e *syntax.Name, def *TypeName, wantType
|
|||
x.mode = nilvalue
|
||||
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
x.typ = typ
|
||||
|
|
|
@ -279,7 +279,7 @@ func def(obj Object) {
|
|||
case *Builtin:
|
||||
obj.pkg = Unsafe
|
||||
default:
|
||||
unreachable()
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
if scope.Insert(obj) != nil {
|
||||
|
|
|
@ -9,7 +9,13 @@
|
|||
|
||||
package types2
|
||||
|
||||
import "cmd/compile/internal/syntax"
|
||||
import (
|
||||
"cmd/compile/internal/syntax"
|
||||
"go/constant"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
const isTypes2 = true
|
||||
|
||||
// cmpPos compares the positions p and q and returns a result r as follows:
|
||||
//
|
||||
|
@ -23,3 +29,31 @@ func cmpPos(p, q syntax.Pos) int { return p.Cmp(q) }
|
|||
|
||||
// hasDots reports whether the last argument in the call is followed by ...
|
||||
func hasDots(call *syntax.CallExpr) bool { return call.HasDots }
|
||||
|
||||
// dddErrPos returns the node (poser) for reporting an invalid ... use in a call.
|
||||
func dddErrPos(call *syntax.CallExpr) *syntax.CallExpr {
|
||||
// TODO(gri) should use "..." instead of call position
|
||||
return call
|
||||
}
|
||||
|
||||
// argErrPos returns the node (poser) for reportign an invalid argument count.
|
||||
func argErrPos(call *syntax.CallExpr) *syntax.CallExpr { return call }
|
||||
|
||||
// ExprString returns a string representation of x.
|
||||
func ExprString(x syntax.Node) string { return syntax.String(x) }
|
||||
|
||||
// endPos returns the position of the first character immediately after node n.
|
||||
func endPos(n syntax.Node) syntax.Pos { return syntax.EndPos(n) }
|
||||
|
||||
// makeFromLiteral returns the constant value for the given literal string and kind.
|
||||
func makeFromLiteral(lit string, kind syntax.LitKind) constant.Value {
|
||||
return constant.MakeFromLiteral(lit, kind2tok[kind], 0)
|
||||
}
|
||||
|
||||
var kind2tok = [...]token.Token{
|
||||
syntax.IntLit: token.INT,
|
||||
syntax.FloatLit: token.FLOAT,
|
||||
syntax.ImagLit: token.IMAG,
|
||||
syntax.RuneLit: token.CHAR,
|
||||
syntax.StringLit: token.STRING,
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ package walk
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"internal/abi"
|
||||
|
||||
"cmd/compile/internal/base"
|
||||
"cmd/compile/internal/ir"
|
||||
|
@ -183,8 +184,7 @@ var mapassign = mkmapnames("mapassign", "ptr")
|
|||
var mapdelete = mkmapnames("mapdelete", "")
|
||||
|
||||
func mapfast(t *types.Type) int {
|
||||
// Check runtime/map.go:maxElemSize before changing.
|
||||
if t.Elem().Size() > 128 {
|
||||
if t.Elem().Size() > abi.MapMaxElemBytes {
|
||||
return mapslow
|
||||
}
|
||||
switch reflectdata.AlgType(t.Key()) {
|
||||
|
|
19
src/cmd/dist/build.go
vendored
19
src/cmd/dist/build.go
vendored
|
@ -40,7 +40,6 @@ var (
|
|||
goppc64 string
|
||||
goriscv64 string
|
||||
goroot string
|
||||
goroot_final string
|
||||
goextlinkenabled string
|
||||
gogcflags string // For running built compiler
|
||||
goldflags string
|
||||
|
@ -127,12 +126,6 @@ func xinit() {
|
|||
// All exec calls rewrite "go" into gorootBinGo.
|
||||
gorootBinGo = pathf("%s/bin/go", goroot)
|
||||
|
||||
b = os.Getenv("GOROOT_FINAL")
|
||||
if b == "" {
|
||||
b = goroot
|
||||
}
|
||||
goroot_final = b
|
||||
|
||||
b = os.Getenv("GOOS")
|
||||
if b == "" {
|
||||
b = gohostos
|
||||
|
@ -245,7 +238,6 @@ func xinit() {
|
|||
os.Setenv("GOPPC64", goppc64)
|
||||
os.Setenv("GORISCV64", goriscv64)
|
||||
os.Setenv("GOROOT", goroot)
|
||||
os.Setenv("GOROOT_FINAL", goroot_final)
|
||||
|
||||
// Set GOBIN to GOROOT/bin. The meaning of GOBIN has drifted over time
|
||||
// (see https://go.dev/issue/3269, https://go.dev/cl/183058,
|
||||
|
@ -1879,10 +1871,7 @@ func banner() {
|
|||
xprintf("Installed Go for %s/%s in %s\n", goos, goarch, goroot)
|
||||
xprintf("Installed commands in %s\n", gorootBin)
|
||||
|
||||
if !xsamefile(goroot_final, goroot) {
|
||||
// If the files are to be moved, don't check that gobin
|
||||
// is on PATH; assume they know what they are doing.
|
||||
} else if gohostos == "plan9" {
|
||||
if gohostos == "plan9" {
|
||||
// Check that GOROOT/bin is bound before /bin.
|
||||
pid := strings.Replace(readfile("#c/pid"), " ", "", -1)
|
||||
ns := fmt.Sprintf("/proc/%s/ns", pid)
|
||||
|
@ -1907,12 +1896,6 @@ func banner() {
|
|||
xprintf("*** You need to add %s to your PATH.\n", gorootBin)
|
||||
}
|
||||
}
|
||||
|
||||
if !xsamefile(goroot_final, goroot) {
|
||||
xprintf("\n"+
|
||||
"The binaries expect %s to be copied or moved to %s\n",
|
||||
goroot, goroot_final)
|
||||
}
|
||||
}
|
||||
|
||||
// Version prints the Go version.
|
||||
|
|
|
@ -6,6 +6,7 @@ package main
|
|||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/version"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -13,7 +14,7 @@ func init() {
|
|||
register(buildtagFix)
|
||||
}
|
||||
|
||||
const buildtagGoVersionCutoff = 1_18
|
||||
const buildtagGoVersionCutoff = "go1.18"
|
||||
|
||||
var buildtagFix = fix{
|
||||
name: "buildtag",
|
||||
|
@ -23,7 +24,7 @@ var buildtagFix = fix{
|
|||
}
|
||||
|
||||
func buildtag(f *ast.File) bool {
|
||||
if goVersion < buildtagGoVersionCutoff {
|
||||
if version.Compare(*goVersion, buildtagGoVersionCutoff) < 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ func init() {
|
|||
var buildtagTests = []testCase{
|
||||
{
|
||||
Name: "buildtag.oldGo",
|
||||
Version: 1_10,
|
||||
Version: "go1.10",
|
||||
In: `//go:build yes
|
||||
// +build yes
|
||||
|
||||
|
@ -20,7 +20,7 @@ package main
|
|||
},
|
||||
{
|
||||
Name: "buildtag.new",
|
||||
Version: 1_99,
|
||||
Version: "go1.99",
|
||||
In: `//go:build yes
|
||||
// +build yes
|
||||
|
||||
|
|
|
@ -13,13 +13,13 @@ import (
|
|||
"go/parser"
|
||||
"go/scanner"
|
||||
"go/token"
|
||||
"go/version"
|
||||
"internal/diff"
|
||||
"io"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
|
@ -37,10 +37,8 @@ var forceRewrites = flag.String("force", "",
|
|||
var allowed, force map[string]bool
|
||||
|
||||
var (
|
||||
doDiff = flag.Bool("diff", false, "display diffs instead of rewriting files")
|
||||
goVersionStr = flag.String("go", "", "go language version for files")
|
||||
|
||||
goVersion int // 115 for go1.15
|
||||
doDiff = flag.Bool("diff", false, "display diffs instead of rewriting files")
|
||||
goVersion = flag.String("go", "", "go language version for files")
|
||||
)
|
||||
|
||||
// enable for debugging fix failures
|
||||
|
@ -68,24 +66,9 @@ func main() {
|
|||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
|
||||
if *goVersionStr != "" {
|
||||
if !strings.HasPrefix(*goVersionStr, "go") {
|
||||
report(fmt.Errorf("invalid -go=%s", *goVersionStr))
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
majorStr := (*goVersionStr)[len("go"):]
|
||||
minorStr := "0"
|
||||
if before, after, found := strings.Cut(majorStr, "."); found {
|
||||
majorStr, minorStr = before, after
|
||||
}
|
||||
major, err1 := strconv.Atoi(majorStr)
|
||||
minor, err2 := strconv.Atoi(minorStr)
|
||||
if err1 != nil || err2 != nil || major < 0 || major >= 100 || minor < 0 || minor >= 100 {
|
||||
report(fmt.Errorf("invalid -go=%s", *goVersionStr))
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
goVersion = major*100 + minor
|
||||
if !version.IsValid(*goVersion) {
|
||||
report(fmt.Errorf("invalid -go=%s", *goVersion))
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
sort.Sort(byDate(fixes))
|
||||
|
|
|
@ -17,7 +17,7 @@ import (
|
|||
type testCase struct {
|
||||
Name string
|
||||
Fn func(*ast.File) bool
|
||||
Version int
|
||||
Version string
|
||||
In string
|
||||
Out string
|
||||
}
|
||||
|
@ -96,7 +96,7 @@ func TestRewrite(t *testing.T) {
|
|||
for _, tt := range testCases {
|
||||
tt := tt
|
||||
t.Run(tt.Name, func(t *testing.T) {
|
||||
if tt.Version == 0 {
|
||||
if tt.Version == "" {
|
||||
if testing.Verbose() {
|
||||
// Don't run in parallel: cmd/fix sometimes writes directly to stderr,
|
||||
// and since -v prints which test is currently running we want that
|
||||
|
@ -105,10 +105,10 @@ func TestRewrite(t *testing.T) {
|
|||
t.Parallel()
|
||||
}
|
||||
} else {
|
||||
old := goVersion
|
||||
goVersion = tt.Version
|
||||
old := *goVersion
|
||||
*goVersion = tt.Version
|
||||
defer func() {
|
||||
goVersion = old
|
||||
*goVersion = old
|
||||
}()
|
||||
}
|
||||
|
||||
|
|
|
@ -5,13 +5,13 @@ go 1.23
|
|||
require (
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5
|
||||
golang.org/x/arch v0.7.0
|
||||
golang.org/x/build v0.0.0-20240201175143-3ee44a092755
|
||||
golang.org/x/build v0.0.0-20240222153247-cf4ed81bb19f
|
||||
golang.org/x/mod v0.15.1-0.20240207185259-766dc5df63e3
|
||||
golang.org/x/sync v0.6.0
|
||||
golang.org/x/sys v0.17.0
|
||||
golang.org/x/telemetry v0.0.0-20240208185543-e9b074dd3804
|
||||
golang.org/x/term v0.16.0
|
||||
golang.org/x/tools v0.17.1-0.20240119231502-e1555a36d006
|
||||
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808
|
||||
golang.org/x/term v0.17.0
|
||||
golang.org/x/tools v0.18.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
|
@ -10,8 +10,8 @@ github.com/gobwas/pool v0.2.1 h1:xfeeEhW7pwmX8nuLVlqbzVc7udMDrwetjEv+TZIz1og=
|
|||
github.com/gobwas/pool v0.2.1/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw=
|
||||
github.com/gobwas/ws v1.2.1 h1:F2aeBZrm2NDsc7vbovKrWSogd4wvfAxg0FQ89/iqOTk=
|
||||
github.com/gobwas/ws v1.2.1/go.mod h1:hRKAFb8wOxFROYNsT1bqfWnhX+b5MFeJM9r2ZSwg/KY=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5 h1:E/LAvt58di64hlYjx7AsNS6C/ysHWYo+2qPCZKTQhRo=
|
||||
github.com/google/pprof v0.0.0-20240207164012-fb44976bdcd5/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20230524184225-eabc099b10ab h1:BA4a7pe6ZTd9F8kXETBoijjFJ/ntaa//1wiH9BZu4zU=
|
||||
|
@ -24,21 +24,21 @@ github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68=
|
|||
github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
|
||||
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
|
||||
golang.org/x/build v0.0.0-20240201175143-3ee44a092755 h1:irSM9p93GT4I3+Pu/grZlkwIjrXA3GfyKwlSosVbmtU=
|
||||
golang.org/x/build v0.0.0-20240201175143-3ee44a092755/go.mod h1:RHSzqFUzT4+buJlGik6WptO5NxLQiR/ewD2uz3fgWuA=
|
||||
golang.org/x/build v0.0.0-20240222153247-cf4ed81bb19f h1:XQ2eu0I26WsNCKQkRehp+5mwjjChw94trD9LT8LLSq0=
|
||||
golang.org/x/build v0.0.0-20240222153247-cf4ed81bb19f/go.mod h1:HTqTCkubWT8epEK9hDWWGkoOOB7LGSrU1qvWZCSwO50=
|
||||
golang.org/x/mod v0.15.1-0.20240207185259-766dc5df63e3 h1:/p/VemLWiTsjHqHwME1Iu+xIu8s9fBtwBk8bU/ejA1A=
|
||||
golang.org/x/mod v0.15.1-0.20240207185259-766dc5df63e3/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/telemetry v0.0.0-20240208185543-e9b074dd3804 h1:mLYQpgq+cJOnmn3pR2U9o5rzEuOVgnmw59GHPgypGeo=
|
||||
golang.org/x/telemetry v0.0.0-20240208185543-e9b074dd3804/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
|
||||
golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE=
|
||||
golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY=
|
||||
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808 h1:+Kc94D8UVEVxJnLXp/+FMfqQARZtWHfVrcRtcG8aT3g=
|
||||
golang.org/x/telemetry v0.0.0-20240208230135-b75ee8823808/go.mod h1:KG1lNk5ZFNssSZLrpVb4sMXKMpGwGXOxSG3rnu2gZQQ=
|
||||
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/tools v0.17.1-0.20240119231502-e1555a36d006 h1:nQlBrWcYwVcWPZJ3VI2s/bH4yjgiWJXNTELOKrnS0qk=
|
||||
golang.org/x/tools v0.17.1-0.20240119231502-e1555a36d006/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
rsc.io/markdown v0.0.0-20240117044121-669d2fdf1650 h1:fuOABZYWclLVNotDsHVaFixLdtoC7+UQZJ0KSC1ocm0=
|
||||
rsc.io/markdown v0.0.0-20240117044121-669d2fdf1650/go.mod h1:8xcPgWmwlZONN1D9bjxtHEjrUtSEa3fakVF8iaewYKQ=
|
||||
|
|
|
@ -2331,11 +2331,6 @@
|
|||
// See src/internal/goexperiment/flags.go for currently valid values.
|
||||
// Warning: This variable is provided for the development and testing
|
||||
// of the Go toolchain itself. Use beyond that purpose is unsupported.
|
||||
// GOROOT_FINAL
|
||||
// The root of the installed Go tree, when it is
|
||||
// installed in a location other than where it is built.
|
||||
// File names in stack traces are rewritten from GOROOT to
|
||||
// GOROOT_FINAL.
|
||||
// GO_EXTLINK_ENABLED
|
||||
// Whether the linker should use external linking mode
|
||||
// when using -linkmode=auto with code that uses cgo.
|
||||
|
|
|
@ -90,10 +90,6 @@ func tooSlow(t *testing.T, reason string) {
|
|||
// (temp) directory.
|
||||
var testGOROOT string
|
||||
|
||||
// testGOROOT_FINAL is the GOROOT_FINAL with which the test binary is assumed to
|
||||
// have been built.
|
||||
var testGOROOT_FINAL = os.Getenv("GOROOT_FINAL")
|
||||
|
||||
var testGOCACHE string
|
||||
|
||||
var testGo string
|
||||
|
@ -223,10 +219,6 @@ func TestMain(m *testing.M) {
|
|||
}
|
||||
testGOROOT = goEnv("GOROOT")
|
||||
os.Setenv("TESTGO_GOROOT", testGOROOT)
|
||||
// Ensure that GOROOT is set explicitly.
|
||||
// Otherwise, if the toolchain was built with GOROOT_FINAL set but has not
|
||||
// yet been moved to its final location, programs that invoke runtime.GOROOT
|
||||
// may accidentally use the wrong path.
|
||||
os.Setenv("GOROOT", testGOROOT)
|
||||
|
||||
// The whole GOROOT/pkg tree was installed using the GOHOSTOS/GOHOSTARCH
|
||||
|
|
|
@ -64,33 +64,31 @@ func ToolExeSuffix() string {
|
|||
|
||||
// These are general "build flags" used by build and other commands.
|
||||
var (
|
||||
BuildA bool // -a flag
|
||||
BuildBuildmode string // -buildmode flag
|
||||
BuildBuildvcs = "auto" // -buildvcs flag: "true", "false", or "auto"
|
||||
BuildContext = defaultContext()
|
||||
BuildMod string // -mod flag
|
||||
BuildModExplicit bool // whether -mod was set explicitly
|
||||
BuildModReason string // reason -mod was set, if set by default
|
||||
BuildLinkshared bool // -linkshared flag
|
||||
BuildMSan bool // -msan flag
|
||||
BuildASan bool // -asan flag
|
||||
BuildCover bool // -cover flag
|
||||
BuildCoverMode string // -covermode flag
|
||||
BuildCoverPkg []string // -coverpkg flag
|
||||
BuildN bool // -n flag
|
||||
BuildO string // -o flag
|
||||
BuildP = runtime.GOMAXPROCS(0) // -p flag
|
||||
BuildPGO string // -pgo flag
|
||||
BuildPkgdir string // -pkgdir flag
|
||||
BuildRace bool // -race flag
|
||||
BuildToolexec []string // -toolexec flag
|
||||
BuildToolchainName string
|
||||
BuildToolchainCompiler func() string
|
||||
BuildToolchainLinker func() string
|
||||
BuildTrimpath bool // -trimpath flag
|
||||
BuildV bool // -v flag
|
||||
BuildWork bool // -work flag
|
||||
BuildX bool // -x flag
|
||||
BuildA bool // -a flag
|
||||
BuildBuildmode string // -buildmode flag
|
||||
BuildBuildvcs = "auto" // -buildvcs flag: "true", "false", or "auto"
|
||||
BuildContext = defaultContext()
|
||||
BuildMod string // -mod flag
|
||||
BuildModExplicit bool // whether -mod was set explicitly
|
||||
BuildModReason string // reason -mod was set, if set by default
|
||||
BuildLinkshared bool // -linkshared flag
|
||||
BuildMSan bool // -msan flag
|
||||
BuildASan bool // -asan flag
|
||||
BuildCover bool // -cover flag
|
||||
BuildCoverMode string // -covermode flag
|
||||
BuildCoverPkg []string // -coverpkg flag
|
||||
BuildN bool // -n flag
|
||||
BuildO string // -o flag
|
||||
BuildP = runtime.GOMAXPROCS(0) // -p flag
|
||||
BuildPGO string // -pgo flag
|
||||
BuildPkgdir string // -pkgdir flag
|
||||
BuildRace bool // -race flag
|
||||
BuildToolexec []string // -toolexec flag
|
||||
BuildToolchainName string
|
||||
BuildTrimpath bool // -trimpath flag
|
||||
BuildV bool // -v flag
|
||||
BuildWork bool // -work flag
|
||||
BuildX bool // -x flag
|
||||
|
||||
ModCacheRW bool // -modcacherw flag
|
||||
ModFile string // -modfile flag
|
||||
|
@ -181,8 +179,6 @@ func defaultContext() build.Context {
|
|||
|
||||
func init() {
|
||||
SetGOROOT(Getenv("GOROOT"), false)
|
||||
BuildToolchainCompiler = func() string { return "missing-compiler" }
|
||||
BuildToolchainLinker = func() string { return "missing-linker" }
|
||||
}
|
||||
|
||||
// SetGOROOT sets GOROOT and associated variables to the given values.
|
||||
|
@ -203,7 +199,6 @@ func SetGOROOT(goroot string, isTestGo bool) {
|
|||
GOROOTpkg = filepath.Join(goroot, "pkg")
|
||||
GOROOTsrc = filepath.Join(goroot, "src")
|
||||
}
|
||||
GOROOT_FINAL = findGOROOT_FINAL(goroot)
|
||||
|
||||
installedGOOS = runtime.GOOS
|
||||
installedGOARCH = runtime.GOARCH
|
||||
|
@ -402,8 +397,6 @@ var (
|
|||
GOROOTpkg string
|
||||
GOROOTsrc string
|
||||
|
||||
GOROOT_FINAL string
|
||||
|
||||
GOBIN = Getenv("GOBIN")
|
||||
GOMODCACHE = envOr("GOMODCACHE", gopathDir("pkg/mod"))
|
||||
|
||||
|
@ -536,16 +529,6 @@ func findGOROOT(env string) string {
|
|||
return def
|
||||
}
|
||||
|
||||
func findGOROOT_FINAL(goroot string) string {
|
||||
// $GOROOT_FINAL is only for use during make.bash
|
||||
// so it is not settable using go/env, so we use os.Getenv here.
|
||||
def := goroot
|
||||
if env := os.Getenv("GOROOT_FINAL"); env != "" {
|
||||
def = filepath.Clean(env)
|
||||
}
|
||||
return def
|
||||
}
|
||||
|
||||
// isSameDir reports whether dir1 and dir2 are the same directory.
|
||||
func isSameDir(dir1, dir2 string) bool {
|
||||
if dir1 == dir2 {
|
||||
|
|
|
@ -645,11 +645,6 @@ Special-purpose environment variables:
|
|||
See src/internal/goexperiment/flags.go for currently valid values.
|
||||
Warning: This variable is provided for the development and testing
|
||||
of the Go toolchain itself. Use beyond that purpose is unsupported.
|
||||
GOROOT_FINAL
|
||||
The root of the installed Go tree, when it is
|
||||
installed in a location other than where it is built.
|
||||
File names in stack traces are rewritten from GOROOT to
|
||||
GOROOT_FINAL.
|
||||
GO_EXTLINK_ENABLED
|
||||
Whether the linker should use external linking mode
|
||||
when using -linkmode=auto with code that uses cgo.
|
||||
|
|
|
@ -324,7 +324,13 @@ func vendorPkg(vdir, pkg string) {
|
|||
}
|
||||
embeds, err := load.ResolveEmbed(bp.Dir, embedPatterns)
|
||||
if err != nil {
|
||||
base.Fatal(err)
|
||||
format := "go: resolving embeds in %s: %v\n"
|
||||
if vendorE {
|
||||
fmt.Fprintf(os.Stderr, format, pkg, err)
|
||||
} else {
|
||||
base.Errorf(format, pkg, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
for _, embed := range embeds {
|
||||
embedDst := filepath.Join(dst, embed)
|
||||
|
@ -333,23 +339,30 @@ func vendorPkg(vdir, pkg string) {
|
|||
}
|
||||
|
||||
// Copy the file as is done by copyDir below.
|
||||
r, err := os.Open(filepath.Join(src, embed))
|
||||
err := func() error {
|
||||
r, err := os.Open(filepath.Join(src, embed))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(embedDst), 0777); err != nil {
|
||||
return err
|
||||
}
|
||||
w, err := os.Create(embedDst)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := io.Copy(w, r); err != nil {
|
||||
return err
|
||||
}
|
||||
r.Close()
|
||||
return w.Close()
|
||||
}()
|
||||
if err != nil {
|
||||
base.Fatal(err)
|
||||
}
|
||||
if err := os.MkdirAll(filepath.Dir(embedDst), 0777); err != nil {
|
||||
base.Fatal(err)
|
||||
}
|
||||
w, err := os.Create(embedDst)
|
||||
if err != nil {
|
||||
base.Fatal(err)
|
||||
}
|
||||
if _, err := io.Copy(w, r); err != nil {
|
||||
base.Fatal(err)
|
||||
}
|
||||
r.Close()
|
||||
if err := w.Close(); err != nil {
|
||||
base.Fatal(err)
|
||||
if vendorE {
|
||||
fmt.Fprintf(os.Stderr, "go: %v\n", err)
|
||||
} else {
|
||||
base.Error(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ func runVerify(ctx context.Context, cmd *base.Command, args []string) {
|
|||
if err != nil {
|
||||
base.Fatal(err)
|
||||
}
|
||||
mods := mg.BuildList()[modload.MainModules.Len():]
|
||||
mods := mg.BuildList()
|
||||
// Use a slice of result channels, so that the output is deterministic.
|
||||
errsChans := make([]<-chan []error, len(mods))
|
||||
|
||||
|
@ -94,6 +94,9 @@ func verifyMod(ctx context.Context, mod module.Version) []error {
|
|||
// "go" and "toolchain" have no disk footprint; nothing to verify.
|
||||
return nil
|
||||
}
|
||||
if modload.MainModules.Contains(mod.Path) {
|
||||
return nil
|
||||
}
|
||||
var errs []error
|
||||
zip, zipErr := modfetch.CachePath(ctx, mod, "zip")
|
||||
if zipErr == nil {
|
||||
|
|
|
@ -21,6 +21,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"cmd/go/internal/base"
|
||||
|
@ -540,6 +541,7 @@ var (
|
|||
testC bool // -c flag
|
||||
testCoverPkgs []*load.Package // -coverpkg flag
|
||||
testCoverProfile string // -coverprofile flag
|
||||
testFailFast bool // -failfast flag
|
||||
testFuzz string // -fuzz flag
|
||||
testJSON bool // -json flag
|
||||
testList string // -list flag
|
||||
|
@ -589,9 +591,10 @@ var (
|
|||
|
||||
testHelp bool // -help option passed to test via -args
|
||||
|
||||
testKillTimeout = 100 * 365 * 24 * time.Hour // backup alarm; defaults to about a century if no timeout is set
|
||||
testWaitDelay time.Duration // how long to wait for output to close after a test binary exits; zero means unlimited
|
||||
testCacheExpire time.Time // ignore cached test results before this time
|
||||
testKillTimeout = 100 * 365 * 24 * time.Hour // backup alarm; defaults to about a century if no timeout is set
|
||||
testWaitDelay time.Duration // how long to wait for output to close after a test binary exits; zero means unlimited
|
||||
testCacheExpire time.Time // ignore cached test results before this time
|
||||
testShouldFailFast atomic.Bool // signals pending tests to fail fast
|
||||
|
||||
testBlockProfile, testCPUProfile, testMemProfile, testMutexProfile, testTrace string // profiling flag that limits test to one package
|
||||
|
||||
|
@ -1355,6 +1358,11 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action)
|
|||
// Wait for previous test to get started and print its first json line.
|
||||
select {
|
||||
case <-r.prev:
|
||||
// If should fail fast then release next test and exit.
|
||||
if testShouldFailFast.Load() {
|
||||
close(r.next)
|
||||
return nil
|
||||
}
|
||||
case <-base.Interrupted:
|
||||
// We can't wait for the previous test action to complete: we don't start
|
||||
// new actions after an interrupt, so if that action wasn't already running
|
||||
|
@ -1631,6 +1639,10 @@ func (r *runTestActor) Act(b *work.Builder, ctx context.Context, a *work.Action)
|
|||
fmt.Fprintf(cmd.Stdout, "ok \t%s\t%s%s%s\n", a.Package.ImportPath, t, coveragePercentage(out), norun)
|
||||
r.c.saveOutput(a)
|
||||
} else {
|
||||
if testFailFast {
|
||||
testShouldFailFast.Store(true)
|
||||
}
|
||||
|
||||
base.SetExitStatus(1)
|
||||
if cancelSignaled {
|
||||
fmt.Fprintf(cmd.Stdout, "*** Test killed with %v: ran too long (%v).\n", base.SignalTrace, testKillTimeout)
|
||||
|
|
|
@ -48,7 +48,7 @@ func init() {
|
|||
cf.Int("count", 0, "")
|
||||
cf.String("cpu", "", "")
|
||||
cf.StringVar(&testCPUProfile, "cpuprofile", "", "")
|
||||
cf.Bool("failfast", false, "")
|
||||
cf.BoolVar(&testFailFast, "failfast", false, "")
|
||||
cf.StringVar(&testFuzz, "fuzz", "", "")
|
||||
cf.Bool("fullpath", false, "")
|
||||
cf.StringVar(&testList, "list", "", "")
|
||||
|
|
|
@ -276,8 +276,6 @@ func (c buildCompiler) Set(value string) error {
|
|||
return fmt.Errorf("unknown compiler %q", value)
|
||||
}
|
||||
cfg.BuildToolchainName = value
|
||||
cfg.BuildToolchainCompiler = BuildToolchain.compiler
|
||||
cfg.BuildToolchainLinker = BuildToolchain.linker
|
||||
cfg.BuildContext.Compiler = value
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -258,9 +258,12 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
|
|||
// when building things in GOROOT.
|
||||
//
|
||||
// The C compiler does not, but for packages in GOROOT we rewrite the path
|
||||
// as though -trimpath were set, so that we don't invalidate the build cache
|
||||
// (and especially any precompiled C archive files) when changing
|
||||
// GOROOT_FINAL. (See https://go.dev/issue/50183.)
|
||||
// as though -trimpath were set. This used to be so that we did not invalidate
|
||||
// the build cache (and especially precompiled archive files) when changing
|
||||
// GOROOT_FINAL, but we no longer ship precompiled archive files as of Go 1.20
|
||||
// (https://go.dev/issue/47257) and no longer support GOROOT_FINAL
|
||||
// (https://go.dev/issue/62047).
|
||||
// TODO(bcmills): Figure out whether this behavior is still useful.
|
||||
//
|
||||
// b.WorkDir is always either trimmed or rewritten to
|
||||
// the literal string "/tmp/go-build".
|
||||
|
@ -1403,11 +1406,11 @@ func (b *Builder) printLinkerConfig(h io.Writer, p *load.Package) {
|
|||
fmt.Fprintf(h, "GOEXPERIMENT=%q\n", cfg.CleanGOEXPERIMENT)
|
||||
}
|
||||
|
||||
// The linker writes source file paths that say GOROOT_FINAL, but
|
||||
// only if -trimpath is not specified (see ld() in gc.go).
|
||||
gorootFinal := cfg.GOROOT_FINAL
|
||||
// The linker writes source file paths that refer to GOROOT,
|
||||
// but only if -trimpath is not specified (see [gctoolchain.ld] in gc.go).
|
||||
gorootFinal := cfg.GOROOT
|
||||
if cfg.BuildTrimpath {
|
||||
gorootFinal = trimPathGoRootFinal
|
||||
gorootFinal = ""
|
||||
}
|
||||
fmt.Fprintf(h, "GOROOT=%s\n", gorootFinal)
|
||||
|
||||
|
@ -2130,7 +2133,7 @@ func (b *Builder) ccompile(a *Action, outfile string, flags []string, file strin
|
|||
file = mkAbs(p.Dir, file)
|
||||
outfile = mkAbs(p.Dir, outfile)
|
||||
|
||||
// Elide source directory paths if -trimpath or GOROOT_FINAL is set.
|
||||
// Elide source directory paths if -trimpath is set.
|
||||
// This is needed for source files (e.g., a .c file in a package directory).
|
||||
// TODO(golang.org/issue/36072): cgo also generates files with #line
|
||||
// directives pointing to the source directory. It should not generate those
|
||||
|
|
|
@ -29,9 +29,6 @@ import (
|
|||
// Tests can override this by setting $TESTGO_TOOLCHAIN_VERSION.
|
||||
var ToolchainVersion = runtime.Version()
|
||||
|
||||
// The 'path' used for GOROOT_FINAL when -trimpath is specified
|
||||
const trimPathGoRootFinal string = "$GOROOT"
|
||||
|
||||
// The Go toolchain.
|
||||
|
||||
type gcToolchain struct{}
|
||||
|
@ -669,8 +666,11 @@ func (gcToolchain) ld(b *Builder, root *Action, targetPath, importcfg, mainpkg s
|
|||
}
|
||||
|
||||
env := []string{}
|
||||
// When -trimpath is used, GOROOT is cleared
|
||||
if cfg.BuildTrimpath {
|
||||
env = append(env, "GOROOT_FINAL="+trimPathGoRootFinal)
|
||||
env = append(env, "GOROOT=")
|
||||
} else {
|
||||
env = append(env, "GOROOT="+cfg.GOROOT)
|
||||
}
|
||||
return b.Shell(root).run(dir, root.Package.ImportPath, env, cfg.BuildToolexec, base.Tool("link"), "-o", targetPath, "-importcfg", importcfg, ldflags, mainpkg)
|
||||
}
|
||||
|
|
|
@ -97,7 +97,7 @@ func main() {
|
|||
|
||||
flag.Usage = base.Usage
|
||||
flag.Parse()
|
||||
counter.CountFlags("cmd/go:flag-", *flag.CommandLine)
|
||||
counter.CountFlags("cmd/go/flag:", *flag.CommandLine)
|
||||
|
||||
args := flag.Args()
|
||||
if len(args) < 1 {
|
||||
|
@ -153,7 +153,7 @@ func main() {
|
|||
|
||||
cmd, used := lookupCmd(args)
|
||||
cfg.CmdName = strings.Join(args[:used], " ")
|
||||
counter.Inc("cmd/go:subcommand-" + strings.ReplaceAll(cfg.CmdName, " ", "-"))
|
||||
counter.Inc("cmd/go/subcommand:" + strings.ReplaceAll(cfg.CmdName, " ", "-"))
|
||||
if len(cmd.Commands) > 0 {
|
||||
if used >= len(args) {
|
||||
help.PrintUsage(os.Stderr, cmd)
|
||||
|
@ -241,7 +241,7 @@ func invoke(cmd *base.Command, args []string) {
|
|||
} else {
|
||||
base.SetFromGOFLAGS(&cmd.Flag)
|
||||
cmd.Flag.Parse(args[1:])
|
||||
counter.CountFlags("cmd/go/"+cmd.Name()+":flag-", cmd.Flag)
|
||||
counter.CountFlags("cmd/go/flag:"+cmd.Name()+"-", cmd.Flag)
|
||||
args = cmd.Flag.Args()
|
||||
}
|
||||
|
||||
|
|
|
@ -223,7 +223,6 @@ func scriptEnv(srv *vcstest.Server, srvCertFile string) ([]string, error) {
|
|||
"GOPROXY=" + proxyURL,
|
||||
"GOPRIVATE=",
|
||||
"GOROOT=" + testGOROOT,
|
||||
"GOROOT_FINAL=" + testGOROOT_FINAL, // causes spurious rebuilds and breaks the "stale" built-in if not propagated
|
||||
"GOTRACEBACK=system",
|
||||
"TESTGONETWORK=panic", // allow only local connections by default; the [net] condition resets this
|
||||
"TESTGO_GOROOT=" + testGOROOT,
|
||||
|
|
|
@ -51,7 +51,6 @@ func scriptConditions() map[string]script.Cond {
|
|||
add("GOEXPERIMENT", script.PrefixCondition("GOEXPERIMENT <suffix> is enabled", hasGoexperiment))
|
||||
add("go-builder", script.BoolCondition("GO_BUILDER_NAME is non-empty", testenv.Builder() != ""))
|
||||
add("link", lazyBool("testenv.HasLink()", testenv.HasLink))
|
||||
add("mismatched-goroot", script.Condition("test's GOROOT_FINAL does not match the real GOROOT", isMismatchedGoroot))
|
||||
add("msan", sysCondition("-msan", platform.MSanSupported, true))
|
||||
add("mustlinkext", script.Condition("platform always requires external linking", mustLinkExt))
|
||||
add("net", script.PrefixCondition("can connect to external network host <suffix>", hasNet))
|
||||
|
@ -85,14 +84,6 @@ func ccIs(s *script.State, want string) (bool, error) {
|
|||
return cfg.DefaultCC(GOOS, GOARCH) == want, nil
|
||||
}
|
||||
|
||||
func isMismatchedGoroot(s *script.State) (bool, error) {
|
||||
gorootFinal, _ := s.LookupEnv("GOROOT_FINAL")
|
||||
if gorootFinal == "" {
|
||||
gorootFinal, _ = s.LookupEnv("GOROOT")
|
||||
}
|
||||
return gorootFinal != testGOROOT, nil
|
||||
}
|
||||
|
||||
func sysCondition(flag string, f func(goos, goarch string) bool, needsCgo bool) script.Cond {
|
||||
return script.Condition(
|
||||
"GOOS/GOARCH supports "+flag,
|
||||
|
|
|
@ -120,7 +120,6 @@ Scripts also have access to other environment variables, including:
|
|||
GOPATH=$WORK/gopath
|
||||
GOPROXY=<local module proxy serving from cmd/go/testdata/mod>
|
||||
GOROOT=<actual GOROOT>
|
||||
GOROOT_FINAL=<actual GOROOT_FINAL>
|
||||
TESTGO_GOROOT=<GOROOT used to build cmd/go, for use in tests that may change GOROOT>
|
||||
HOME=/no-home
|
||||
PATH=<actual PATH>
|
||||
|
|
3
src/cmd/go/testdata/script/README
vendored
3
src/cmd/go/testdata/script/README
vendored
|
@ -35,7 +35,6 @@ Scripts also have access to other environment variables, including:
|
|||
GOPATH=$WORK/gopath
|
||||
GOPROXY=<local module proxy serving from cmd/go/testdata/mod>
|
||||
GOROOT=<actual GOROOT>
|
||||
GOROOT_FINAL=<actual GOROOT_FINAL>
|
||||
TESTGO_GOROOT=<GOROOT used to build cmd/go, for use in tests that may change GOROOT>
|
||||
HOME=/no-home
|
||||
PATH=<actual PATH>
|
||||
|
@ -402,8 +401,6 @@ The available conditions are:
|
|||
GO_BUILDER_NAME is non-empty
|
||||
[link]
|
||||
testenv.HasLink()
|
||||
[mismatched-goroot]
|
||||
test's GOROOT_FINAL does not match the real GOROOT
|
||||
[msan]
|
||||
GOOS/GOARCH supports -msan
|
||||
[mustlinkext]
|
||||
|
|
46
src/cmd/go/testdata/script/build_issue48319.txt
vendored
46
src/cmd/go/testdata/script/build_issue48319.txt
vendored
|
@ -1,46 +0,0 @@
|
|||
# Regression test for https://go.dev/issue/48319:
|
||||
# cgo builds should not include debug information from a stale GOROOT_FINAL.
|
||||
|
||||
[short] skip
|
||||
[!cgo] skip
|
||||
|
||||
# This test is sensitive to cache invalidation,
|
||||
# so use a separate build cache that we can control.
|
||||
env GOCACHE=$WORK/gocache
|
||||
mkdir $GOCACHE
|
||||
|
||||
# Build a binary using a specific value of GOROOT_FINAL.
|
||||
env GOROOT_FINAL=$WORK${/}goroot1
|
||||
go build -o main.exe
|
||||
mv main.exe main1.exe
|
||||
|
||||
# Now clean the cache and build using a different GOROOT_FINAL.
|
||||
# The resulting binaries should differ in their debug metadata.
|
||||
go clean -cache
|
||||
env GOROOT_FINAL=$WORK${/}goroot2
|
||||
go build -o main.exe
|
||||
mv main.exe main2.exe
|
||||
! cmp -q main2.exe main1.exe
|
||||
|
||||
# Set GOROOT_FINAL back to the first value.
|
||||
# If the build is properly reproducible, the two binaries should match.
|
||||
env GOROOT_FINAL=$WORK${/}goroot1
|
||||
go build -o main.exe
|
||||
cmp -q main.exe main1.exe
|
||||
|
||||
-- go.mod --
|
||||
module main
|
||||
|
||||
go 1.18
|
||||
-- main.go --
|
||||
package main
|
||||
|
||||
import "C"
|
||||
|
||||
import "runtime"
|
||||
|
||||
var _ C.int
|
||||
|
||||
func main() {
|
||||
println(runtime.GOROOT())
|
||||
}
|
|
@ -2,6 +2,13 @@
|
|||
[short] skip
|
||||
[!cgo] skip '-buildmode=plugin requires external linking'
|
||||
|
||||
# This test has problems when run on the LUCI darwin longtest builder,
|
||||
# which uses a more contemporary Xcode version that is unfriendly to
|
||||
# reproducible builds (see issue #64947 for the gory details). Note
|
||||
# that individual developers running "go test cmd/go" on Darwin may
|
||||
# still run into failures depending on their Xcode version.
|
||||
[GOOS:darwin] [go-builder] skip
|
||||
|
||||
go build -trimpath -buildvcs=false -buildmode=plugin -o a.so main.go
|
||||
go build -trimpath -buildvcs=false -buildmode=plugin -o b.so main.go
|
||||
cmp -q a.so b.so
|
||||
|
|
37
src/cmd/go/testdata/script/build_trimpath.txt
vendored
37
src/cmd/go/testdata/script/build_trimpath.txt
vendored
|
@ -1,8 +1,8 @@
|
|||
[short] skip
|
||||
|
||||
# If GOROOT_FINAL is set, 'go build -trimpath' bakes that into the resulting
|
||||
# binary instead of GOROOT. Explicitly unset it here.
|
||||
env GOROOT_FINAL=
|
||||
# If GOROOT is set, 'go build -trimpath' bakes that into the resulting
|
||||
# binary. Explicitly unset it here.
|
||||
env GOROOT=
|
||||
|
||||
# Set up two identical directories that can be used as GOPATH.
|
||||
env GO111MODULE=on
|
||||
|
@ -21,14 +21,13 @@ cd $WORK/a/src/paths
|
|||
go build -o $WORK/paths-dbg.exe .
|
||||
exec $WORK/paths-dbg.exe $WORK/paths-dbg.exe
|
||||
stdout 'binary contains module root: true'
|
||||
stdout 'binary contains GOROOT: true'
|
||||
stdout 'binary contains an empty GOROOT'
|
||||
|
||||
# A binary built with -trimpath should not contain the current workspace
|
||||
# or GOROOT.
|
||||
# A binary built with -trimpath should not contain the current workspace.
|
||||
go build -trimpath -o $WORK/paths-a.exe .
|
||||
exec $WORK/paths-a.exe $WORK/paths-a.exe
|
||||
stdout 'binary contains module root: false'
|
||||
stdout 'binary contains GOROOT: false'
|
||||
stdout 'binary contains an empty GOROOT'
|
||||
|
||||
# A binary from an external module built with -trimpath should not contain
|
||||
# the current workspace or GOROOT.
|
||||
|
@ -36,7 +35,7 @@ go get rsc.io/fortune
|
|||
go install -trimpath rsc.io/fortune
|
||||
exec $WORK/paths-a.exe $GOPATH/bin/fortune$GOEXE
|
||||
stdout 'binary contains module root: false'
|
||||
stdout 'binary contains GOROOT: false'
|
||||
stdout 'binary contains an empty GOROOT'
|
||||
go mod edit -droprequire rsc.io/fortune
|
||||
|
||||
# Two binaries built from identical packages in different directories
|
||||
|
@ -53,14 +52,13 @@ cd $WORK/a/src/paths
|
|||
go build -overlay overlay.json -o $WORK/paths-dbg.exe ./overlaydir
|
||||
exec $WORK/paths-dbg.exe $WORK/paths-dbg.exe
|
||||
stdout 'binary contains module root: true'
|
||||
stdout 'binary contains GOROOT: true'
|
||||
stdout 'binary contains an empty GOROOT'
|
||||
|
||||
# A binary built with -trimpath should not contain the current workspace
|
||||
# or GOROOT.
|
||||
# A binary built with -trimpath should not contain the current workspace.
|
||||
go build -overlay overlay.json -trimpath -o $WORK/paths-a.exe ./overlaydir
|
||||
exec $WORK/paths-a.exe $WORK/paths-a.exe
|
||||
stdout 'binary contains module root: false'
|
||||
stdout 'binary contains GOROOT: false'
|
||||
stdout 'binary contains an empty GOROOT'
|
||||
|
||||
# Two binaries built from identical packages in different directories
|
||||
# should be identical.
|
||||
|
@ -77,13 +75,13 @@ env GOPATH=$WORK/a
|
|||
go build -o paths-dbg.exe paths
|
||||
exec ./paths-dbg.exe paths-dbg.exe
|
||||
stdout 'binary contains GOPATH: true'
|
||||
stdout 'binary contains GOROOT: true'
|
||||
stdout 'binary contains an empty GOROOT'
|
||||
|
||||
# A binary built with -trimpath should not contain GOPATH or GOROOT.
|
||||
# A binary built with -trimpath should not contain GOPATH.
|
||||
go build -trimpath -o paths-a.exe paths
|
||||
exec ./paths-a.exe paths-a.exe
|
||||
stdout 'binary contains GOPATH: false'
|
||||
stdout 'binary contains GOROOT: false'
|
||||
stdout 'binary contains an empty GOROOT'
|
||||
|
||||
# Two binaries built from identical packages in different GOPATH roots
|
||||
# should be identical.
|
||||
|
@ -103,13 +101,14 @@ env GOPATH=$WORK/a
|
|||
go build -compiler=gccgo -o paths-dbg.exe paths
|
||||
exec ./paths-dbg.exe paths-dbg.exe
|
||||
stdout 'binary contains GOPATH: true'
|
||||
stdout 'binary contains GOROOT: false' # gccgo doesn't load std from GOROOT.
|
||||
stdout 'binary contains an empty GOROOT'
|
||||
|
||||
# gccgo doesn't load std from GOROOT.
|
||||
# A binary built with gccgo with -trimpath should not contain GOPATH or GOROOT.
|
||||
go build -compiler=gccgo -trimpath -o paths-a.exe paths
|
||||
exec ./paths-a.exe paths-a.exe
|
||||
stdout 'binary contains GOPATH: false'
|
||||
stdout 'binary contains GOROOT: false'
|
||||
stdout 'binary contains an empty GOROOT'
|
||||
|
||||
# Two binaries built from identical packages in different directories
|
||||
# should be identical.
|
||||
|
@ -152,6 +151,10 @@ func main() {
|
|||
}
|
||||
|
||||
func check(data []byte, desc, dir string) {
|
||||
if dir == "" {
|
||||
fmt.Printf("binary contains an empty %s\n", desc)
|
||||
return
|
||||
}
|
||||
containsDir := bytes.Contains(data, []byte(dir))
|
||||
containsSlashDir := bytes.Contains(data, []byte(filepath.ToSlash(dir)))
|
||||
fmt.Printf("binary contains %s: %v\n", desc, containsDir || containsSlashDir)
|
||||
|
|
|
@ -4,11 +4,6 @@
|
|||
# if GOROOT was not set explicitly in the environment.
|
||||
# It should instead return the empty string, since we know that we don't
|
||||
# have a valid path to return.
|
||||
#
|
||||
# TODO(#51483): when runtime.GOROOT() returns the empty string,
|
||||
# go/build should default to 'go env GOROOT' instead.
|
||||
|
||||
env GOROOT_FINAL=
|
||||
|
||||
[trimpath] env GOROOT=
|
||||
[trimpath] ! go env GOROOT
|
||||
|
@ -17,7 +12,7 @@ env GOROOT_FINAL=
|
|||
|
||||
[short] stop
|
||||
|
||||
# With GOROOT still set but GOROOT_FINAL unset, 'go build' and 'go test -c'
|
||||
# With GOROOT still set, 'go build' and 'go test -c'
|
||||
# should cause runtime.GOROOT() to report either the correct GOROOT
|
||||
# (without -trimpath) or no GOROOT at all (with -trimpath).
|
||||
|
||||
|
@ -52,7 +47,6 @@ stderr 'cannot find package "runtime" in any of:\n\t\(\$GOROOT not set\)\n\t'$WO
|
|||
# code).
|
||||
|
||||
[trimpath] stop
|
||||
[mismatched-goroot] stop
|
||||
|
||||
! go run -trimpath .
|
||||
stdout '^GOROOT $'
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
# Regression test for https://go.dev/issue/47215 and https://go.dev/issue/50183:
|
||||
# A mismatched $GOROOT_FINAL or missing $CC caused the C dependencies of the net
|
||||
# A missing $CC caused the C dependencies of the net
|
||||
# package to appear stale, and it could not be rebuilt due to a missing $CC.
|
||||
|
||||
[!cgo] skip
|
||||
|
@ -16,14 +16,6 @@
|
|||
go build -x runtime/cgo
|
||||
[!short] stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
|
||||
|
||||
# https://go.dev/issue/50183: a mismatched GOROOT_FINAL caused net to be stale.
|
||||
env oldGOROOT_FINAL=$GOROOT_FINAL
|
||||
env GOROOT_FINAL=$WORK${/}goroot
|
||||
go build -x runtime/cgo
|
||||
! stderr '[/\\]cgo'$GOEXE'["]? .* -importpath runtime/cgo'
|
||||
|
||||
env GOROOT_FINAL=$oldGOROOT_FINAL
|
||||
|
||||
# https://go.dev/issue/47215: a missing $(go env CC) caused the precompiled net
|
||||
# to be stale. But as of https://go.dev/cl/452457 the precompiled libraries are
|
||||
# no longer installed anyway! Since we're requiring a C compiler in order to
|
||||
|
|
|
@ -3,16 +3,9 @@
|
|||
|
||||
mkdir $WORK/new/bin
|
||||
|
||||
# In this test, we are specifically checking the logic for deriving
|
||||
# the value of GOROOT from runtime.GOROOT.
|
||||
# GOROOT_FINAL changes the default behavior of runtime.GOROOT,
|
||||
# and will thus cause the test to fail if it is set when our
|
||||
# new cmd/go is built.
|
||||
env GOROOT_FINAL=
|
||||
|
||||
# $GOROOT/bin/go is whatever the user has already installed
|
||||
# (using make.bash or similar). We can't make assumptions about what
|
||||
# options it may have been built with, such as -trimpath or GOROOT_FINAL.
|
||||
# options it may have been built with, such as -trimpath or not.
|
||||
# Instead, we build a fresh copy of the binary with known settings.
|
||||
go build -o $WORK/new/bin/go$GOEXE cmd/go &
|
||||
go build -trimpath -o $WORK/bin/check$GOEXE check.go &
|
||||
|
|
|
@ -14,13 +14,10 @@ mkdir $WORK/new/bin/${GOOS}_${GOARCH}
|
|||
# In this test, we are specifically checking the logic for deriving
|
||||
# the value of GOROOT from os.Executable when runtime.GOROOT is
|
||||
# trimmed away.
|
||||
# GOROOT_FINAL changes the default behavior of runtime.GOROOT,
|
||||
# so we explicitly clear it to remove it as a confounding variable.
|
||||
env GOROOT_FINAL=
|
||||
|
||||
# $GOROOT/bin/go is whatever the user has already installed
|
||||
# (using make.bash or similar). We can't make assumptions about what
|
||||
# options it may have been built with, such as -trimpath or GOROOT_FINAL.
|
||||
# options it may have been built with, such as -trimpath or not.
|
||||
# Instead, we build a fresh copy of the binary with known settings.
|
||||
go build -trimpath -o $WORK/new/bin/go$GOEXE cmd/go &
|
||||
go build -trimpath -o $WORK/bin/check$GOEXE check.go &
|
||||
|
|
|
@ -6,11 +6,15 @@ cmp vendor/example.com/a/subdir/test/xtest/embed.txt a/subdir/test/xtest/embed.t
|
|||
|
||||
cd broken_no_matching_files
|
||||
! go mod vendor
|
||||
stderr 'go: pattern foo.txt: no matching files found'
|
||||
stderr '^go: resolving embeds in example.com/brokendep: pattern foo.txt: no matching files found$'
|
||||
go mod vendor -e
|
||||
stderr '^go: resolving embeds in example.com/brokendep: pattern foo.txt: no matching files found$'
|
||||
|
||||
cd ../broken_bad_pattern
|
||||
! go mod vendor
|
||||
stderr 'go: pattern ../foo.txt: invalid pattern syntax'
|
||||
stderr '^go: resolving embeds in example.com/brokendep: pattern ../foo.txt: invalid pattern syntax$'
|
||||
go mod vendor -e
|
||||
stderr '^go: resolving embeds in example.com/brokendep: pattern ../foo.txt: invalid pattern syntax$'
|
||||
|
||||
cd ../embed_go122
|
||||
go mod vendor
|
||||
|
|
24
src/cmd/go/testdata/script/mod_verify_work.txt
vendored
Normal file
24
src/cmd/go/testdata/script/mod_verify_work.txt
vendored
Normal file
|
@ -0,0 +1,24 @@
|
|||
# Regression test for Issue #62663: we would filter out the toolchain and
|
||||
# main modules from the build list incorrectly, leading to the workspace
|
||||
# modules being checked for correct sums. Specifically this would happen when
|
||||
# the module name sorted after the virtual 'go' version module name because
|
||||
# it could not get chopped off when we removed the MainModules.Len() modules
|
||||
# at the beginning of the build list and we would remove the go module instead.
|
||||
|
||||
go mod verify
|
||||
|
||||
-- go.work --
|
||||
go 1.21
|
||||
|
||||
use (
|
||||
./a
|
||||
./b
|
||||
)
|
||||
-- a/go.mod --
|
||||
module hexample.com/a // important for test that module name sorts after 'go'
|
||||
|
||||
go 1.21
|
||||
-- b/go.mod --
|
||||
module hexample.com/b // important for test that module name sorts after 'go'
|
||||
|
||||
go 1.21
|
33
src/cmd/go/testdata/script/test_fail_fast.txt
vendored
33
src/cmd/go/testdata/script/test_fail_fast.txt
vendored
|
@ -48,6 +48,15 @@ stdout -count=1 'FAIL - '
|
|||
! go test ./failfast_test.go -run='TestFatal[CD]' -failfast=false
|
||||
stdout -count=2 'FAIL - '
|
||||
|
||||
# cross package failfast
|
||||
! go test -p 1 -failfast ./a ./b ./c
|
||||
stdout -count=1 'FAIL - '
|
||||
stdout -count=1 'FAIL - TestFailingPkgA'
|
||||
|
||||
-- go.mod --
|
||||
module m
|
||||
|
||||
go 1.21.0
|
||||
-- failfast_test.go --
|
||||
// Copyright 2017 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
|
@ -111,3 +120,27 @@ func TestFatalC(t *testing.T) {
|
|||
func TestFatalD(t *testing.T) {
|
||||
t.Fatalf("FAIL - %s", t.Name())
|
||||
}
|
||||
-- a/a_test.go --
|
||||
package a
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestFailingPkgA(t *testing.T) {
|
||||
t.Errorf("FAIL - %s", t.Name())
|
||||
}
|
||||
-- b/b_test.go --
|
||||
package b
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestFailingPkgB(t *testing.T) {
|
||||
t.Errorf("FAIL - %s", t.Name())
|
||||
}
|
||||
-- c/c_test.go --
|
||||
package c
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestFailingPkgC(t *testing.T) {
|
||||
t.Errorf("FAIL - %s", t.Name())
|
||||
}
|
||||
|
|
|
@ -555,7 +555,7 @@ func backupFile(filename string, data []byte, perm fs.FileMode) (string, error)
|
|||
if err == nil {
|
||||
break
|
||||
}
|
||||
if err != nil && !os.IsExist(err) {
|
||||
if !os.IsExist(err) {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue