mirror of https://github.com/golang/go.git
[dev.unified] all: merge master (5a1c5b8) into dev.unified
Conflicts: - test/run.go Textual conflict adding to the known failures list for the nounified frontend. Merge List: + 2022-06-245a1c5b8ae7cmd/go: add per-package indexing for modules outside mod cache + 2022-06-24b9c4d94fdbcmd/go/internal/list: update help info with Deprecated field + 2022-06-2473475ef035go/types, types2: print qualified object names in cycle errors + 2022-06-243e58ef6cc7go/types, types2: better errors for == when type sets are empty + 2022-06-24d38f1d13fadoc/go1.19: Linux race detector now requires glibc 2.17 + 2022-06-23de5329f1dedebug/dwarf: handle malformed line table with bad program offset + 2022-06-2315605ca827embed: document additional file name restrictions + 2022-06-222e773a3894test: add test that causes gofrontend crash + 2022-06-22ff17b7d0d4cmd/compile: don't use dictionary convert to shaped empty interface + 2022-06-222a3b467d5fcmd/go: make module .zip files group/world readable + 2022-06-22bdab4cf47acmd/go, cmd/link: support failure to create _cgo_import.go + 2022-06-22aca37d16a5cmd/go: avoid indexing modules in GOROOT + 2022-06-22111cdb5848all: update to current golang.org/x/sys revision + 2022-06-224045b1bc3fcmd/compile: fix assert condition in generic method call + 2022-06-226bad7e8243compress/gzip: always close bodyReader in Example_compressingReader + 2022-06-22606c6c371aencoding/xml: check nil pointer in DecodeElement + 2022-06-22f571518139cmd/cgo: dont override declared struct type + 2022-06-2292c9b81447net: don't set netGo = true on Windows with no cgo + 2022-06-22be0b2a393acmd/trace: add basic documentation to main page + 2022-06-22b004c739b5go/types, types2: fix parameter order dependence in type inference + 2022-06-21f2c7e78592spec: document operations which accept []byte|string constrained types + 2022-06-21ab422f2749runtime/trace: ignore fallback stacks in test + 2022-06-2166685fb7dddoc/go1.19: use correct link to sync/atomic docs + 2022-06-214b236b45d0runtime: convert flaky semaphore linearity test into benchmark + 2022-06-21530511bacccmd/go/internal/modindex: avoid walking modules when not needed + 2022-06-21c2d373d5d1cmd/compile: allow 128-bit values to be spilled + 2022-06-2119ed442807test: add regress test for #53477 + 2022-06-203fcbfb07a8doc/go1.19: fix HTML validation issues + 2022-06-18527ace0ffacmd/compile: skip substituting closures in unsafe builtins arguments + 2022-06-17ec58e3f327test: add regress test for #53419 + 2022-06-17103cc661f1cmd/go/internal/modfetch: prevent duplicate hashes in go.sum + 2022-06-17d42a48828fsync: add more notes about Cond behavior + 2022-06-179e2f289754cmd/go/internal/work: log clearer detail for subprocess errors in (*Builder).toolID + 2022-06-17dd2d00f9d5net: fix flaky *TimeoutMustNotReturn tests + 2022-06-176c25ba624fgo/token: delete unused File.set field + 2022-06-169068c6844dcmd/dist: add package . to 'go test' commands + 2022-06-167bad61554eruntime: write much more direct test for semaphore waiter scalability + 2022-06-16f38a580a51cmd/go: add more tracing Change-Id: I912c5879165e03f4d7f8ac3ee9241d50fc92a419
This commit is contained in:
commit
e7100adbca
|
|
@ -35,7 +35,7 @@ Do not send CLs removing the interior tags from such phrases.
|
||||||
the memory model used by C, C++, Java, JavaScript, Rust, and Swift.
|
the memory model used by C, C++, Java, JavaScript, Rust, and Swift.
|
||||||
Go only provides sequentially consistent atomics, not any of the more relaxed forms found in other languages.
|
Go only provides sequentially consistent atomics, not any of the more relaxed forms found in other languages.
|
||||||
Along with the memory model update,
|
Along with the memory model update,
|
||||||
Go 1.19 introduces <a href="#sync/atomic">new types in the <code>sync/atomic</code> package</a>
|
Go 1.19 introduces <a href="#atomic_types">new types in the <code>sync/atomic</code> package</a>
|
||||||
that make it easier to use atomic values, such as
|
that make it easier to use atomic values, such as
|
||||||
<a href="/pkg/sync/atomic/#Int64">atomic.Int64</a>
|
<a href="/pkg/sync/atomic/#Int64">atomic.Int64</a>
|
||||||
and
|
and
|
||||||
|
|
@ -741,7 +741,7 @@ as well as support for rendering them to HTML, Markdown, and text.
|
||||||
</dd>
|
</dd>
|
||||||
</dl><!-- regexp -->
|
</dl><!-- regexp -->
|
||||||
|
|
||||||
<dl id="runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
|
<dl id="pkg-runtime"><dt><a href="/pkg/runtime/">runtime</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
<p><!-- https://go.dev/issue/51461 -->
|
<p><!-- https://go.dev/issue/51461 -->
|
||||||
The <a href="/pkg/runtime/#GOROOT"><code>GOROOT</code></a> function now returns the empty string
|
The <a href="/pkg/runtime/#GOROOT"><code>GOROOT</code></a> function now returns the empty string
|
||||||
|
|
@ -807,6 +807,7 @@ as well as support for rendering them to HTML, Markdown, and text.
|
||||||
Compared to v2, it is now typically 1.5x to 2x faster, uses half
|
Compared to v2, it is now typically 1.5x to 2x faster, uses half
|
||||||
as much memory, and it supports an unlimited number of
|
as much memory, and it supports an unlimited number of
|
||||||
goroutines.
|
goroutines.
|
||||||
|
On Linux, the race detector now requires at least glibc version 2.17.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 336549 -->
|
<p><!-- CL 336549 -->
|
||||||
|
|
@ -847,7 +848,6 @@ as well as support for rendering them to HTML, Markdown, and text.
|
||||||
but often easier to use: it returns an additional boolean reporting whether an equal value was found.
|
but often easier to use: it returns an additional boolean reporting whether an equal value was found.
|
||||||
</p>
|
</p>
|
||||||
</dd>
|
</dd>
|
||||||
</dd>
|
|
||||||
</dl><!-- sort -->
|
</dl><!-- sort -->
|
||||||
|
|
||||||
<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
|
<dl id="strconv"><dt><a href="/pkg/strconv/">strconv</a></dt>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
<!--{
|
<!--{
|
||||||
"Title": "The Go Programming Language Specification",
|
"Title": "The Go Programming Language Specification",
|
||||||
"Subtitle": "Version of June 14, 2022",
|
"Subtitle": "Version of June 21, 2022",
|
||||||
"Path": "/ref/spec"
|
"Path": "/ref/spec"
|
||||||
}-->
|
}-->
|
||||||
|
|
||||||
|
|
@ -1811,6 +1811,31 @@ interface{ chan int | chan<- string } // channels have different element
|
||||||
interface{ <-chan int | chan<- int } // directional channels have different directions
|
interface{ <-chan int | chan<- int } // directional channels have different directions
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Some operations (<a href="#Slice_expressions">slice expressions</a>,
|
||||||
|
<a href="#Appending_and_copying_slices"><code>append</code> and <code>copy</code></a>)
|
||||||
|
rely on a slightly more loose form of core types which accept byte slices and strings.
|
||||||
|
Specifically, if there are exactly two types, <code>[]byte</code> and <code>string</code>,
|
||||||
|
which are the underlying types of all types in the type set of interface <code>T</code>,
|
||||||
|
the core type of <code>T</code> is called <code>bytestring</code>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Examples of interfaces with <code>bytestring</code> core types:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<pre>
|
||||||
|
interface{ int } // int (same as ordinary core type)
|
||||||
|
interface{ []byte | string } // bytestring
|
||||||
|
interface{ ~[]byte | myString } // bytestring
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Note that <code>bytestring</code> is not a real type; it cannot be used to declare
|
||||||
|
variables are compose other types. It exists solely to describe the behavior of some
|
||||||
|
operations that read from a sequence of bytes, which may be a byte slice or a string.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3 id="Type_identity">Type identity</h3>
|
<h3 id="Type_identity">Type identity</h3>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
|
|
@ -3837,7 +3862,8 @@ a[low : high]
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
constructs a substring or slice. The <a href="#Core_types">core type</a> of
|
constructs a substring or slice. The <a href="#Core_types">core type</a> of
|
||||||
<code>a</code> must be a string, array, pointer to array, or slice.
|
<code>a</code> must be a string, array, pointer to array, slice, or a
|
||||||
|
<a href="#Core_types"><code>bytestring</code></a>.
|
||||||
The <i>indices</i> <code>low</code> and
|
The <i>indices</i> <code>low</code> and
|
||||||
<code>high</code> select which elements of operand <code>a</code> appear
|
<code>high</code> select which elements of operand <code>a</code> appear
|
||||||
in the result. The result has indices starting at 0 and length equal to
|
in the result. The result has indices starting at 0 and length equal to
|
||||||
|
|
@ -5469,7 +5495,7 @@ string(runes{0x767d, 0x9d6c, 0x7fd4}) // "\u767d\u9d6c\u7fd4" == "白鵬翔"
|
||||||
|
|
||||||
type myRune rune
|
type myRune rune
|
||||||
string([]myRune{0x266b, 0x266c}) // "\u266b\u266c" == "♫♬"
|
string([]myRune{0x266b, 0x266c}) // "\u266b\u266c" == "♫♬"
|
||||||
myString([]myRune{0x1F30E}) // "\U0001f30e" == "🌎"
|
myString([]myRune{0x1f30e}) // "\U0001f30e" == "🌎"
|
||||||
</pre>
|
</pre>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
@ -7197,8 +7223,9 @@ The values <code>x</code> are passed to a parameter of type <code>...E</code>
|
||||||
and the respective <a href="#Passing_arguments_to_..._parameters">parameter
|
and the respective <a href="#Passing_arguments_to_..._parameters">parameter
|
||||||
passing rules</a> apply.
|
passing rules</a> apply.
|
||||||
As a special case, if the core type of <code>s</code> is <code>[]byte</code>,
|
As a special case, if the core type of <code>s</code> is <code>[]byte</code>,
|
||||||
<code>append</code> also accepts a second argument with core type <code>string</code>
|
<code>append</code> also accepts a second argument with core type
|
||||||
followed by <code>...</code>. This form appends the bytes of the string.
|
<a href="#Core_types"><code>bytestring</code></a> followed by <code>...</code>.
|
||||||
|
This form appends the bytes of the byte slice or string.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre class="grammar">
|
<pre class="grammar">
|
||||||
|
|
@ -7235,8 +7262,9 @@ with <a href="#Type_identity">identical</a> element type.
|
||||||
The number of elements copied is the minimum of
|
The number of elements copied is the minimum of
|
||||||
<code>len(src)</code> and <code>len(dst)</code>.
|
<code>len(src)</code> and <code>len(dst)</code>.
|
||||||
As a special case, if the destination's core type is <code>[]byte</code>,
|
As a special case, if the destination's core type is <code>[]byte</code>,
|
||||||
<code>copy</code> also accepts a source argument with core type <code>string</code>.
|
<code>copy</code> also accepts a source argument with core type
|
||||||
This form copies the bytes from the string into the byte slice.
|
</a> <a href="#Core_types"><code>bytestring</code></a>.
|
||||||
|
This form copies the bytes from the byte slice or string into the byte slice.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<pre class="grammar">
|
<pre class="grammar">
|
||||||
|
|
@ -7550,7 +7578,7 @@ and the Unicode replacement character U+FFFD.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
Assume we have compiled a package containing the package clause
|
Consider a compiled a package containing the package clause
|
||||||
<code>package math</code>, which exports function <code>Sin</code>, and
|
<code>package math</code>, which exports function <code>Sin</code>, and
|
||||||
installed the compiled package in the file identified by
|
installed the compiled package in the file identified by
|
||||||
<code>"lib/math"</code>.
|
<code>"lib/math"</code>.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
// Issue 52611: inconsistent compiler behaviour when compiling a C.struct.
|
||||||
|
// No runtime test; just make sure it compiles.
|
||||||
|
|
||||||
|
package cgotest
|
||||||
|
|
||||||
|
import (
|
||||||
|
_ "cgotest/issue52611a"
|
||||||
|
_ "cgotest/issue52611b"
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package issue52611a
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef struct Foo {
|
||||||
|
int X;
|
||||||
|
} Foo;
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func GetX1(foo *C.struct_Foo) int32 {
|
||||||
|
return int32(foo.X)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package issue52611a
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func GetX2(foo *C.struct_Foo) int32 {
|
||||||
|
return int32(foo.X)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package issue52611b
|
||||||
|
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func GetX1(bar *C.struct_Bar) int32 {
|
||||||
|
return int32(bar.X)
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package issue52611b
|
||||||
|
|
||||||
|
/*
|
||||||
|
typedef struct Bar {
|
||||||
|
int X;
|
||||||
|
} Bar;
|
||||||
|
*/
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func GetX2(bar *C.struct_Bar) int32 {
|
||||||
|
return int32(bar.X)
|
||||||
|
}
|
||||||
|
|
@ -753,6 +753,16 @@ presented to cmd/link as part of a larger program, contains:
|
||||||
_go_.o # gc-compiled object for _cgo_gotypes.go, _cgo_import.go, *.cgo1.go
|
_go_.o # gc-compiled object for _cgo_gotypes.go, _cgo_import.go, *.cgo1.go
|
||||||
_all.o # gcc-compiled object for _cgo_export.c, *.cgo2.c
|
_all.o # gcc-compiled object for _cgo_export.c, *.cgo2.c
|
||||||
|
|
||||||
|
If there is an error generating the _cgo_import.go file, then, instead
|
||||||
|
of adding _cgo_import.go to the package, the go tool adds an empty
|
||||||
|
file named dynimportfail. The _cgo_import.go file is only needed when
|
||||||
|
using internal linking mode, which is not the default when linking
|
||||||
|
programs that use cgo (as described below). If the linker sees a file
|
||||||
|
named dynimportfail it reports an error if it has been told to use
|
||||||
|
internal linking mode. This approach is taken because generating
|
||||||
|
_cgo_import.go requires doing a full C link of the package, which can
|
||||||
|
fail for reasons that are irrelevant when using external linking mode.
|
||||||
|
|
||||||
The final program will be a dynamic executable, so that cmd/link can avoid
|
The final program will be a dynamic executable, so that cmd/link can avoid
|
||||||
needing to process arbitrary .o files. It only needs to process the .o
|
needing to process arbitrary .o files. It only needs to process the .o
|
||||||
files generated from C files that cgo writes, and those are much more
|
files generated from C files that cgo writes, and those are much more
|
||||||
|
|
|
||||||
|
|
@ -2551,6 +2551,11 @@ func (c *typeConv) loadType(dtype dwarf.Type, pos token.Pos, parent string) *Typ
|
||||||
t.Go = name // publish before recursive calls
|
t.Go = name // publish before recursive calls
|
||||||
goIdent[name.Name] = name
|
goIdent[name.Name] = name
|
||||||
if dt.ByteSize < 0 {
|
if dt.ByteSize < 0 {
|
||||||
|
// Don't override old type
|
||||||
|
if _, ok := typedef[name.Name]; ok {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
// Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown),
|
// Size calculation in c.Struct/c.Opaque will die with size=-1 (unknown),
|
||||||
// so execute the basic things that the struct case would do
|
// so execute the basic things that the struct case would do
|
||||||
// other than try to determine a Go representation.
|
// other than try to determine a Go representation.
|
||||||
|
|
|
||||||
|
|
@ -78,6 +78,8 @@ func storeByType(t *types.Type) obj.As {
|
||||||
return x86.AMOVL
|
return x86.AMOVL
|
||||||
case 8:
|
case 8:
|
||||||
return x86.AMOVQ
|
return x86.AMOVQ
|
||||||
|
case 16:
|
||||||
|
return x86.AMOVUPS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
panic(fmt.Sprintf("bad store type %v", t))
|
panic(fmt.Sprintf("bad store type %v", t))
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,11 @@ func Info(fnsym *obj.LSym, infosym *obj.LSym, curfn interface{}) ([]dwarf.Scope,
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
apdecls = append(apdecls, n)
|
apdecls = append(apdecls, n)
|
||||||
|
if n.Type().Kind() == types.TSSA {
|
||||||
|
// Can happen for TypeInt128 types. This only happens for
|
||||||
|
// spill locations, so not a huge deal.
|
||||||
|
continue
|
||||||
|
}
|
||||||
fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type()))
|
fnsym.Func().RecordAutoType(reflectdata.TypeLinksym(n.Type()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -208,9 +208,15 @@ func (g *genInst) scanForGenCalls(decl ir.Node) {
|
||||||
|
|
||||||
st := g.getInstantiation(gf, targs, true).fun
|
st := g.getInstantiation(gf, targs, true).fun
|
||||||
dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true)
|
dictValue, usingSubdict := g.getDictOrSubdict(declInfo, n, gf, targs, true)
|
||||||
// We have to be using a subdictionary, since this is
|
if hasShapeTypes(targs) {
|
||||||
// a generic method call.
|
// We have to be using a subdictionary, since this is
|
||||||
assert(usingSubdict)
|
// a generic method call.
|
||||||
|
assert(usingSubdict)
|
||||||
|
} else {
|
||||||
|
// We should use main dictionary, because the receiver is
|
||||||
|
// an instantiation already, see issue #53406.
|
||||||
|
assert(!usingSubdict)
|
||||||
|
}
|
||||||
|
|
||||||
// Transform to a function call, by appending the
|
// Transform to a function call, by appending the
|
||||||
// dictionary and the receiver to the args.
|
// dictionary and the receiver to the args.
|
||||||
|
|
@ -721,11 +727,12 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe
|
||||||
// Struct containing info needed for doing the substitution as we create the
|
// Struct containing info needed for doing the substitution as we create the
|
||||||
// instantiation of a generic function with specified type arguments.
|
// instantiation of a generic function with specified type arguments.
|
||||||
type subster struct {
|
type subster struct {
|
||||||
g *genInst
|
g *genInst
|
||||||
isMethod bool // If a method is being instantiated
|
isMethod bool // If a method is being instantiated
|
||||||
newf *ir.Func // Func node for the new stenciled function
|
newf *ir.Func // Func node for the new stenciled function
|
||||||
ts typecheck.Tsubster
|
ts typecheck.Tsubster
|
||||||
info *instInfo // Place to put extra info in the instantiation
|
info *instInfo // Place to put extra info in the instantiation
|
||||||
|
skipClosure bool // Skip substituting closures
|
||||||
|
|
||||||
// Map from non-nil, non-ONAME node n to slice of all m, where m.Defn = n
|
// Map from non-nil, non-ONAME node n to slice of all m, where m.Defn = n
|
||||||
defnMap map[ir.Node][]**ir.Name
|
defnMap map[ir.Node][]**ir.Name
|
||||||
|
|
@ -978,7 +985,20 @@ func (subst *subster) node(n ir.Node) ir.Node {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
old := subst.skipClosure
|
||||||
|
// For unsafe.{Alignof,Offsetof,Sizeof}, subster will transform them to OLITERAL nodes,
|
||||||
|
// and discard their arguments. However, their children nodes were already process before,
|
||||||
|
// thus if they contain any closure, the closure was still be added to package declarations
|
||||||
|
// queue for processing later. Thus, genInst will fail to generate instantiation for the
|
||||||
|
// closure because of lacking dictionary information, see issue #53390.
|
||||||
|
if call, ok := m.(*ir.CallExpr); ok && call.X.Op() == ir.ONAME {
|
||||||
|
switch call.X.Name().BuiltinOp {
|
||||||
|
case ir.OALIGNOF, ir.OOFFSETOF, ir.OSIZEOF:
|
||||||
|
subst.skipClosure = true
|
||||||
|
}
|
||||||
|
}
|
||||||
ir.EditChildren(m, edit)
|
ir.EditChildren(m, edit)
|
||||||
|
subst.skipClosure = old
|
||||||
|
|
||||||
m.SetTypecheck(1)
|
m.SetTypecheck(1)
|
||||||
|
|
||||||
|
|
@ -1123,6 +1143,9 @@ func (subst *subster) node(n ir.Node) ir.Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
case ir.OCLOSURE:
|
case ir.OCLOSURE:
|
||||||
|
if subst.skipClosure {
|
||||||
|
break
|
||||||
|
}
|
||||||
// We're going to create a new closure from scratch, so clear m
|
// We're going to create a new closure from scratch, so clear m
|
||||||
// to avoid using the ir.Copy by accident until we reassign it.
|
// to avoid using the ir.Copy by accident until we reassign it.
|
||||||
m = nil
|
m = nil
|
||||||
|
|
@ -1326,7 +1349,7 @@ func (g *genInst) dictPass(info *instInfo) {
|
||||||
mce := m.(*ir.ConvExpr)
|
mce := m.(*ir.ConvExpr)
|
||||||
// Note: x's argument is still typed as a type parameter.
|
// Note: x's argument is still typed as a type parameter.
|
||||||
// m's argument now has an instantiated type.
|
// m's argument now has an instantiated type.
|
||||||
if mce.X.Type().HasShape() || m.Type().HasShape() {
|
if mce.X.Type().HasShape() || (m.Type().HasShape() && !m.Type().IsEmptyInterface()) {
|
||||||
m = convertUsingDictionary(info, info.dictParam, m.Pos(), mce.X, m, m.Type())
|
m = convertUsingDictionary(info, info.dictParam, m.Pos(), mce.X, m, m.Type())
|
||||||
}
|
}
|
||||||
case ir.ODOTTYPE, ir.ODOTTYPE2:
|
case ir.ODOTTYPE, ir.ODOTTYPE2:
|
||||||
|
|
@ -1423,7 +1446,7 @@ func findDictType(info *instInfo, t *types.Type) int {
|
||||||
// instantiated node of the CONVIFACE node or XDOT node (for a bound method call) that is causing the
|
// instantiated node of the CONVIFACE node or XDOT node (for a bound method call) that is causing the
|
||||||
// conversion.
|
// conversion.
|
||||||
func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type) ir.Node {
|
func convertUsingDictionary(info *instInfo, dictParam *ir.Name, pos src.XPos, v ir.Node, in ir.Node, dst *types.Type) ir.Node {
|
||||||
assert(v.Type().HasShape() || in.Type().HasShape())
|
assert(v.Type().HasShape() || (in.Type().HasShape() && !in.Type().IsEmptyInterface()))
|
||||||
assert(dst.IsInterface())
|
assert(dst.IsInterface())
|
||||||
|
|
||||||
if v.Type().IsInterface() {
|
if v.Type().IsInterface() {
|
||||||
|
|
|
||||||
|
|
@ -590,6 +590,12 @@ func PtrDataSize(t *Type) int64 {
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
case TSSA:
|
||||||
|
if t != TypeInt128 {
|
||||||
|
base.Fatalf("PtrDataSize: unexpected ssa type %v", t)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
|
||||||
default:
|
default:
|
||||||
base.Fatalf("PtrDataSize: unexpected type, %v", t)
|
base.Fatalf("PtrDataSize: unexpected type, %v", t)
|
||||||
return 0
|
return 0
|
||||||
|
|
|
||||||
|
|
@ -1705,6 +1705,11 @@ var (
|
||||||
TypeResultMem = newResults([]*Type{TypeMem})
|
TypeResultMem = newResults([]*Type{TypeMem})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
TypeInt128.width = 16
|
||||||
|
TypeInt128.align = 8
|
||||||
|
}
|
||||||
|
|
||||||
// NewNamed returns a new named type for the given type name. obj should be an
|
// NewNamed returns a new named type for the given type name. obj should be an
|
||||||
// ir.Name. The new type is incomplete (marked as TFORW kind), and the underlying
|
// ir.Name. The new type is incomplete (marked as TFORW kind), and the underlying
|
||||||
// type should be set later via SetUnderlying(). References to the type are
|
// type should be set later via SetUnderlying(). References to the type are
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package types2
|
package types2
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"cmd/compile/internal/syntax"
|
"cmd/compile/internal/syntax"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
|
|
@ -303,11 +304,23 @@ loop:
|
||||||
// cycleError reports a declaration cycle starting with
|
// cycleError reports a declaration cycle starting with
|
||||||
// the object in cycle that is "first" in the source.
|
// the object in cycle that is "first" in the source.
|
||||||
func (check *Checker) cycleError(cycle []Object) {
|
func (check *Checker) cycleError(cycle []Object) {
|
||||||
|
// name returns the (possibly qualified) object name.
|
||||||
|
// This is needed because with generic types, cycles
|
||||||
|
// may refer to imported types. See issue #50788.
|
||||||
|
// TODO(gri) Thus functionality is used elsewhere. Factor it out.
|
||||||
|
name := func(obj Object) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
writePackage(&buf, obj.Pkg(), check.qualifier)
|
||||||
|
buf.WriteString(obj.Name())
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(gri) Should we start with the last (rather than the first) object in the cycle
|
// TODO(gri) Should we start with the last (rather than the first) object in the cycle
|
||||||
// since that is the earliest point in the source where we start seeing the
|
// since that is the earliest point in the source where we start seeing the
|
||||||
// cycle? That would be more consistent with other error messages.
|
// cycle? That would be more consistent with other error messages.
|
||||||
i := firstInSrc(cycle)
|
i := firstInSrc(cycle)
|
||||||
obj := cycle[i]
|
obj := cycle[i]
|
||||||
|
objName := name(obj)
|
||||||
// If obj is a type alias, mark it as valid (not broken) in order to avoid follow-on errors.
|
// If obj is a type alias, mark it as valid (not broken) in order to avoid follow-on errors.
|
||||||
tname, _ := obj.(*TypeName)
|
tname, _ := obj.(*TypeName)
|
||||||
if tname != nil && tname.IsAlias() {
|
if tname != nil && tname.IsAlias() {
|
||||||
|
|
@ -315,19 +328,20 @@ func (check *Checker) cycleError(cycle []Object) {
|
||||||
}
|
}
|
||||||
var err error_
|
var err error_
|
||||||
if tname != nil && check.conf.CompilerErrorMessages {
|
if tname != nil && check.conf.CompilerErrorMessages {
|
||||||
err.errorf(obj, "invalid recursive type %s", obj.Name())
|
err.errorf(obj, "invalid recursive type %s", objName)
|
||||||
} else {
|
} else {
|
||||||
err.errorf(obj, "illegal cycle in declaration of %s", obj.Name())
|
err.errorf(obj, "illegal cycle in declaration of %s", objName)
|
||||||
}
|
}
|
||||||
for range cycle {
|
for range cycle {
|
||||||
err.errorf(obj, "%s refers to", obj.Name())
|
err.errorf(obj, "%s refers to", objName)
|
||||||
i++
|
i++
|
||||||
if i >= len(cycle) {
|
if i >= len(cycle) {
|
||||||
i = 0
|
i = 0
|
||||||
}
|
}
|
||||||
obj = cycle[i]
|
obj = cycle[i]
|
||||||
|
objName = name(obj)
|
||||||
}
|
}
|
||||||
err.errorf(obj, "%s", obj.Name())
|
err.errorf(obj, "%s", objName)
|
||||||
check.report(&err)
|
check.report(&err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -128,11 +128,8 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
|
||||||
// named and unnamed types are passed to parameters with identical type, different types
|
// named and unnamed types are passed to parameters with identical type, different types
|
||||||
// (named vs underlying) may be inferred depending on the order of the arguments.
|
// (named vs underlying) may be inferred depending on the order of the arguments.
|
||||||
// By ensuring that named types are seen first, order dependence is avoided and unification
|
// By ensuring that named types are seen first, order dependence is avoided and unification
|
||||||
// succeeds where it can.
|
// succeeds where it can (issue #43056).
|
||||||
//
|
const enableArgSorting = true
|
||||||
// This code is disabled for now pending decision whether we want to address cases like
|
|
||||||
// these and make the spec on type inference more complicated (see issue #43056).
|
|
||||||
const enableArgSorting = false
|
|
||||||
if m := len(args); m >= 2 && enableArgSorting {
|
if m := len(args); m >= 2 && enableArgSorting {
|
||||||
// Determine indices of arguments with named and unnamed types.
|
// Determine indices of arguments with named and unnamed types.
|
||||||
var named, unnamed []int
|
var named, unnamed []int
|
||||||
|
|
|
||||||
|
|
@ -147,7 +147,17 @@ func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, .
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
case *Interface:
|
case *Interface:
|
||||||
return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen)
|
if dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if reportf != nil {
|
||||||
|
if t.typeSet().IsEmpty() {
|
||||||
|
reportf("empty type set")
|
||||||
|
} else {
|
||||||
|
reportf("incomparable types in type set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fallthrough
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ func _() {
|
||||||
type myString string
|
type myString string
|
||||||
var s1 string
|
var s1 string
|
||||||
g3(nil, "1", myString("2"), "3")
|
g3(nil, "1", myString("2"), "3")
|
||||||
g3(&s1, "1", myString /* ERROR does not match */ ("2"), "3")
|
g3(& /* ERROR does not match */ s1, "1", myString("2"), "3")
|
||||||
_ = s1
|
_ = s1
|
||||||
|
|
||||||
type myStruct struct{x int}
|
type myStruct struct{x int}
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@ func _() {
|
||||||
var j func(F)
|
var j func(F)
|
||||||
|
|
||||||
f(i, j)
|
f(i, j)
|
||||||
// f(j, i) // disabled for now
|
f(j, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
// example from issue
|
// example from issue
|
||||||
|
|
@ -27,5 +27,5 @@ func _() {
|
||||||
var j interface{ Equal(I) bool }
|
var j interface{ Equal(I) bool }
|
||||||
|
|
||||||
g(i, j)
|
g(i, j)
|
||||||
// g(j, i) // disabled for now
|
g(j, i)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,18 +23,18 @@ func _[P comparable](x P, y any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func _[P any](x, y P) {
|
func _[P any](x, y P) {
|
||||||
_ = x /* ERROR type parameter P is not comparable with == */ == x
|
_ = x /* ERROR incomparable types in type set */ == x
|
||||||
_ = x /* ERROR type parameter P is not comparable with == */ == y
|
_ = x /* ERROR incomparable types in type set */ == y
|
||||||
_ = y /* ERROR type parameter P is not comparable with == */ == x
|
_ = y /* ERROR incomparable types in type set */ == x
|
||||||
_ = y /* ERROR type parameter P is not comparable with == */ == y
|
_ = y /* ERROR incomparable types in type set */ == y
|
||||||
|
|
||||||
_ = x /* ERROR type parameter P is not comparable with < */ < y
|
_ = x /* ERROR type parameter P is not comparable with < */ < y
|
||||||
}
|
}
|
||||||
|
|
||||||
func _[P any](x P, y any) {
|
func _[P any](x P, y any) {
|
||||||
_ = x /* ERROR type parameter P is not comparable with == */ == x
|
_ = x /* ERROR incomparable types in type set */ == x
|
||||||
_ = x /* ERROR type parameter P is not comparable with == */ == y
|
_ = x /* ERROR incomparable types in type set */ == y
|
||||||
_ = y == x // ERROR type parameter P is not comparable with ==
|
_ = y == x // ERROR incomparable types in type set
|
||||||
_ = y == y
|
_ = y == y
|
||||||
|
|
||||||
_ = x /* ERROR type parameter P is not comparable with < */ < y
|
_ = x /* ERROR type parameter P is not comparable with < */ < y
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright 2022 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package p
|
||||||
|
|
||||||
|
func _[T interface {
|
||||||
|
int
|
||||||
|
string
|
||||||
|
}](x T) {
|
||||||
|
_ = x /* ERROR empty type set */ == x
|
||||||
|
}
|
||||||
|
|
||||||
|
func _[T interface{ int | []byte }](x T) {
|
||||||
|
_ = x /* ERROR incomparable types in type set */ == x
|
||||||
|
}
|
||||||
|
|
@ -73,7 +73,7 @@ func _[
|
||||||
J comparable,
|
J comparable,
|
||||||
M map[string]int,
|
M map[string]int,
|
||||||
C chan int,
|
C chan int,
|
||||||
] (
|
](
|
||||||
b B,
|
b B,
|
||||||
a A,
|
a A,
|
||||||
l L,
|
l L,
|
||||||
|
|
@ -86,14 +86,14 @@ func _[
|
||||||
c C,
|
c C,
|
||||||
) {
|
) {
|
||||||
_ = b == b
|
_ = b == b
|
||||||
_ = a /* ERROR type parameter A is not comparable with == */ == a
|
_ = a /* ERROR incomparable types in type set */ == a
|
||||||
_ = l /* ERROR type parameter L is not comparable with == */ == l
|
_ = l /* ERROR incomparable types in type set */ == l
|
||||||
_ = s /* ERROR type parameter S is not comparable with == */ == s
|
_ = s /* ERROR incomparable types in type set */ == s
|
||||||
_ = p == p
|
_ = p == p
|
||||||
_ = f /* ERROR type parameter F is not comparable with == */ == f
|
_ = f /* ERROR incomparable types in type set */ == f
|
||||||
_ = i /* ERROR type parameter I is not comparable with == */ == i
|
_ = i /* ERROR incomparable types in type set */ == i
|
||||||
_ = j == j
|
_ = j == j
|
||||||
_ = m /* ERROR type parameter M is not comparable with == */ == m
|
_ = m /* ERROR incomparable types in type set */ == m
|
||||||
_ = c == c
|
_ = c == c
|
||||||
|
|
||||||
_ = b /* ERROR mismatched types */ == nil
|
_ = b /* ERROR mismatched types */ == nil
|
||||||
|
|
|
||||||
|
|
@ -766,7 +766,7 @@ func (t *tester) registerTests() {
|
||||||
name: "swig_stdio",
|
name: "swig_stdio",
|
||||||
heading: "../misc/swig/stdio",
|
heading: "../misc/swig/stdio",
|
||||||
fn: func(dt *distTest) error {
|
fn: func(dt *distTest) error {
|
||||||
t.addCmd(dt, "misc/swig/stdio", t.goTest())
|
t.addCmd(dt, "misc/swig/stdio", t.goTest(), ".")
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
@ -776,7 +776,7 @@ func (t *tester) registerTests() {
|
||||||
name: "swig_callback",
|
name: "swig_callback",
|
||||||
heading: "../misc/swig/callback",
|
heading: "../misc/swig/callback",
|
||||||
fn: func(dt *distTest) error {
|
fn: func(dt *distTest) error {
|
||||||
t.addCmd(dt, "misc/swig/callback", t.goTest())
|
t.addCmd(dt, "misc/swig/callback", t.goTest(), ".")
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -784,7 +784,7 @@ func (t *tester) registerTests() {
|
||||||
name: "swig_callback_lto",
|
name: "swig_callback_lto",
|
||||||
heading: "../misc/swig/callback",
|
heading: "../misc/swig/callback",
|
||||||
fn: func(dt *distTest) error {
|
fn: func(dt *distTest) error {
|
||||||
cmd := t.addCmd(dt, "misc/swig/callback", t.goTest())
|
cmd := t.addCmd(dt, "misc/swig/callback", t.goTest(), ".")
|
||||||
setEnv(cmd, "CGO_CFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
|
setEnv(cmd, "CGO_CFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
|
||||||
setEnv(cmd, "CGO_CXXFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
|
setEnv(cmd, "CGO_CXXFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
|
||||||
setEnv(cmd, "CGO_LDFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
|
setEnv(cmd, "CGO_LDFLAGS", "-flto -Wno-lto-type-mismatch -Wno-unknown-warning-option")
|
||||||
|
|
@ -1185,11 +1185,11 @@ func (t *tester) runHostTest(dir, pkg string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *tester) cgoTest(dt *distTest) error {
|
func (t *tester) cgoTest(dt *distTest) error {
|
||||||
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest())
|
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), ".")
|
||||||
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=auto")
|
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=auto")
|
||||||
|
|
||||||
if t.internalLink() {
|
if t.internalLink() {
|
||||||
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=internal")
|
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=internal", ".")
|
||||||
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=internal")
|
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=internal")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1201,15 +1201,15 @@ func (t *tester) cgoTest(dt *distTest) error {
|
||||||
if !t.extLink() {
|
if !t.extLink() {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest())
|
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), ".")
|
||||||
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external")
|
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external")
|
||||||
|
|
||||||
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s")
|
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-ldflags", "-linkmode=external -s", ".")
|
||||||
|
|
||||||
if t.supportedBuildmode("pie") {
|
if t.supportedBuildmode("pie") {
|
||||||
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie")
|
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", ".")
|
||||||
if t.internalLink() && t.internalLinkPIE() {
|
if t.internalLink() && t.internalLinkPIE() {
|
||||||
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie")
|
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie", ".")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1221,14 +1221,14 @@ func (t *tester) cgoTest(dt *distTest) error {
|
||||||
"netbsd-386", "netbsd-amd64",
|
"netbsd-386", "netbsd-amd64",
|
||||||
"openbsd-386", "openbsd-amd64", "openbsd-arm", "openbsd-arm64", "openbsd-mips64":
|
"openbsd-386", "openbsd-amd64", "openbsd-arm", "openbsd-arm64", "openbsd-mips64":
|
||||||
|
|
||||||
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest())
|
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), ".")
|
||||||
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external")
|
setEnv(cmd, "GOFLAGS", "-ldflags=-linkmode=external")
|
||||||
// cgo should be able to cope with both -g arguments and colored
|
// cgo should be able to cope with both -g arguments and colored
|
||||||
// diagnostics.
|
// diagnostics.
|
||||||
setEnv(cmd, "CGO_CFLAGS", "-g0 -fdiagnostics-color")
|
setEnv(cmd, "CGO_CFLAGS", "-g0 -fdiagnostics-color")
|
||||||
|
|
||||||
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=auto")
|
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=auto", ".")
|
||||||
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=external")
|
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", "-linkmode=external", ".")
|
||||||
|
|
||||||
switch pair {
|
switch pair {
|
||||||
case "aix-ppc64", "netbsd-386", "netbsd-amd64":
|
case "aix-ppc64", "netbsd-386", "netbsd-amd64":
|
||||||
|
|
@ -1247,28 +1247,28 @@ func (t *tester) cgoTest(dt *distTest) error {
|
||||||
fmt.Println("No support for static linking found (lacks libc.a?), skip cgo static linking test.")
|
fmt.Println("No support for static linking found (lacks libc.a?), skip cgo static linking test.")
|
||||||
} else {
|
} else {
|
||||||
if goos != "android" {
|
if goos != "android" {
|
||||||
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
|
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`, ".")
|
||||||
}
|
}
|
||||||
t.addCmd(dt, "misc/cgo/nocgo", t.goTest())
|
t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), ".")
|
||||||
t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external`)
|
t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external`, ".")
|
||||||
if goos != "android" {
|
if goos != "android" {
|
||||||
t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
|
t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-ldflags", `-linkmode=external -extldflags "-static -pthread"`, ".")
|
||||||
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`)
|
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static", "-ldflags", `-linkmode=external -extldflags "-static -pthread"`, ".")
|
||||||
// -static in CGO_LDFLAGS triggers a different code path
|
// -static in CGO_LDFLAGS triggers a different code path
|
||||||
// than -static in -extldflags, so test both.
|
// than -static in -extldflags, so test both.
|
||||||
// See issue #16651.
|
// See issue #16651.
|
||||||
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static")
|
cmd := t.addCmd(dt, "misc/cgo/test", t.goTest(), "-tags=static", ".")
|
||||||
setEnv(cmd, "CGO_LDFLAGS", "-static -pthread")
|
setEnv(cmd, "CGO_LDFLAGS", "-static -pthread")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if t.supportedBuildmode("pie") {
|
if t.supportedBuildmode("pie") {
|
||||||
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie")
|
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", ".")
|
||||||
if t.internalLink() && t.internalLinkPIE() {
|
if t.internalLink() && t.internalLinkPIE() {
|
||||||
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie")
|
t.addCmd(dt, "misc/cgo/test", t.goTest(), "-buildmode=pie", "-ldflags=-linkmode=internal", "-tags=internal,internal_pie", ".")
|
||||||
}
|
}
|
||||||
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie")
|
t.addCmd(dt, "misc/cgo/testtls", t.goTest(), "-buildmode=pie", ".")
|
||||||
t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie")
|
t.addCmd(dt, "misc/cgo/nocgo", t.goTest(), "-buildmode=pie", ".")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ require (
|
||||||
golang.org/x/arch v0.0.0-20220412001346-fc48f9fe4c15
|
golang.org/x/arch v0.0.0-20220412001346-fc48f9fe4c15
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4
|
||||||
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29
|
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29
|
||||||
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a
|
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098
|
||||||
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171
|
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171
|
||||||
golang.org/x/tools v0.1.11-0.20220516163903-1e55371df567
|
golang.org/x/tools v0.1.11-0.20220516163903-1e55371df567
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -10,8 +10,8 @@ golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVD
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4=
|
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29 h1:w8s32wxx3sY+OjLlv9qltkLU5yvJzxjjgiHWLjdIcw4=
|
||||||
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220513210516-0976fa681c29/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a h1:N2T1jUrTQE9Re6TFF5PhvEHXHCguynGhKjWVsIUt5cY=
|
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA=
|
||||||
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8=
|
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171 h1:EH1Deb8WZJ0xc0WK//leUHXcX9aLE5SymusoTmMZye8=
|
||||||
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20220411215600-e5f449aeb171/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/tools v0.1.11-0.20220516163903-1e55371df567 h1:MksUZ/zlU+pMbsq1Sw16gK6E1aWzD0rLE+eS2SxF24Y=
|
golang.org/x/tools v0.1.11-0.20220516163903-1e55371df567 h1:MksUZ/zlU+pMbsq1Sw16gK6E1aWzD0rLE+eS2SxF24Y=
|
||||||
|
|
|
||||||
|
|
@ -930,19 +930,20 @@
|
||||||
// applied to a Go struct, but now a Module struct:
|
// applied to a Go struct, but now a Module struct:
|
||||||
//
|
//
|
||||||
// type Module struct {
|
// type Module struct {
|
||||||
// Path string // module path
|
// Path string // module path
|
||||||
// Version string // module version
|
// Version string // module version
|
||||||
// Versions []string // available module versions (with -versions)
|
// Versions []string // available module versions
|
||||||
// Replace *Module // replaced by this module
|
// Replace *Module // replaced by this module
|
||||||
// Time *time.Time // time version was created
|
// Time *time.Time // time version was created
|
||||||
// Update *Module // available update, if any (with -u)
|
// Update *Module // available update (with -u)
|
||||||
// Main bool // is this the main module?
|
// Main bool // is this the main module?
|
||||||
// Indirect bool // is this module only an indirect dependency of main module?
|
// Indirect bool // module is only indirectly needed by main module
|
||||||
// Dir string // directory holding files for this module, if any
|
// Dir string // directory holding local copy of files, if any
|
||||||
// GoMod string // path to go.mod file used when loading this module, if any
|
// GoMod string // path to go.mod file describing module, if any
|
||||||
// GoVersion string // go version used in module
|
// GoVersion string // go version used in module
|
||||||
// Retracted string // retraction information, if any (with -retracted or -u)
|
// Retracted []string // retraction information, if any (with -retracted or -u)
|
||||||
// Error *ModuleError // error loading module
|
// Deprecated string // deprecation message, if any (with -u)
|
||||||
|
// Error *ModuleError // error loading module
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// type ModuleError struct {
|
// type ModuleError struct {
|
||||||
|
|
|
||||||
|
|
@ -222,19 +222,20 @@ When listing modules, the -f flag still specifies a format template
|
||||||
applied to a Go struct, but now a Module struct:
|
applied to a Go struct, but now a Module struct:
|
||||||
|
|
||||||
type Module struct {
|
type Module struct {
|
||||||
Path string // module path
|
Path string // module path
|
||||||
Version string // module version
|
Version string // module version
|
||||||
Versions []string // available module versions (with -versions)
|
Versions []string // available module versions
|
||||||
Replace *Module // replaced by this module
|
Replace *Module // replaced by this module
|
||||||
Time *time.Time // time version was created
|
Time *time.Time // time version was created
|
||||||
Update *Module // available update, if any (with -u)
|
Update *Module // available update (with -u)
|
||||||
Main bool // is this the main module?
|
Main bool // is this the main module?
|
||||||
Indirect bool // is this module only an indirect dependency of main module?
|
Indirect bool // module is only indirectly needed by main module
|
||||||
Dir string // directory holding files for this module, if any
|
Dir string // directory holding local copy of files, if any
|
||||||
GoMod string // path to go.mod file used when loading this module, if any
|
GoMod string // path to go.mod file describing module, if any
|
||||||
GoVersion string // go version used in module
|
GoVersion string // go version used in module
|
||||||
Retracted string // retraction information, if any (with -retracted or -u)
|
Retracted []string // retraction information, if any (with -retracted or -u)
|
||||||
Error *ModuleError // error loading module
|
Deprecated string // deprecation message, if any (with -u)
|
||||||
|
Error *ModuleError // error loading module
|
||||||
}
|
}
|
||||||
|
|
||||||
type ModuleError struct {
|
type ModuleError struct {
|
||||||
|
|
|
||||||
|
|
@ -686,6 +686,9 @@ func LoadImport(ctx context.Context, opts PackageOpts, path, srcDir string, pare
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
|
func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDir string, parent *Package, stk *ImportStack, importPos []token.Position, mode int) *Package {
|
||||||
|
ctx, span := trace.StartSpan(ctx, "modload.loadImport "+path)
|
||||||
|
defer span.Done()
|
||||||
|
|
||||||
if path == "" {
|
if path == "" {
|
||||||
panic("LoadImport called with empty package path")
|
panic("LoadImport called with empty package path")
|
||||||
}
|
}
|
||||||
|
|
@ -801,6 +804,9 @@ func loadImport(ctx context.Context, opts PackageOpts, pre *preload, path, srcDi
|
||||||
// loadPackageData returns a boolean, loaded, which is true if this is the
|
// loadPackageData returns a boolean, loaded, which is true if this is the
|
||||||
// first time the package was loaded. Callers may preload imports in this case.
|
// first time the package was loaded. Callers may preload imports in this case.
|
||||||
func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) {
|
func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoot string, parentIsStd bool, mode int) (bp *build.Package, loaded bool, err error) {
|
||||||
|
ctx, span := trace.StartSpan(ctx, "load.loadPackageData "+path)
|
||||||
|
defer span.Done()
|
||||||
|
|
||||||
if path == "" {
|
if path == "" {
|
||||||
panic("loadPackageData called with empty package path")
|
panic("loadPackageData called with empty package path")
|
||||||
}
|
}
|
||||||
|
|
@ -872,8 +878,8 @@ func loadPackageData(ctx context.Context, path, parentPath, parentDir, parentRoo
|
||||||
buildMode = build.ImportComment
|
buildMode = build.ImportComment
|
||||||
}
|
}
|
||||||
if modroot := modload.PackageModRoot(ctx, r.path); modroot != "" {
|
if modroot := modload.PackageModRoot(ctx, r.path); modroot != "" {
|
||||||
if mi, err := modindex.Get(modroot); err == nil {
|
if rp, err := modindex.GetPackage(modroot, r.dir); err == nil {
|
||||||
data.p, data.err = mi.Import(cfg.BuildContext, mi.RelPath(r.dir), buildMode)
|
data.p, data.err = rp.Import(cfg.BuildContext, buildMode)
|
||||||
goto Happy
|
goto Happy
|
||||||
} else if !errors.Is(err, modindex.ErrNotIndexed) {
|
} else if !errors.Is(err, modindex.ErrNotIndexed) {
|
||||||
base.Fatalf("go: %v", err)
|
base.Fatalf("go: %v", err)
|
||||||
|
|
|
||||||
|
|
@ -242,7 +242,7 @@ func downloadZip(ctx context.Context, mod module.Version, zipfile string) (err e
|
||||||
// contents of the file (by hashing it) before we commit it. Because the file
|
// contents of the file (by hashing it) before we commit it. Because the file
|
||||||
// is zip-compressed, we need an actual file — or at least an io.ReaderAt — to
|
// is zip-compressed, we need an actual file — or at least an io.ReaderAt — to
|
||||||
// validate it: we can't just tee the stream as we write it.
|
// validate it: we can't just tee the stream as we write it.
|
||||||
f, err := os.CreateTemp(filepath.Dir(zipfile), tmpPattern)
|
f, err := tempFile(filepath.Dir(zipfile), filepath.Base(zipfile), 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -833,6 +833,7 @@ Outer:
|
||||||
for _, m := range mods {
|
for _, m := range mods {
|
||||||
list := goSum.m[m]
|
list := goSum.m[m]
|
||||||
sort.Strings(list)
|
sort.Strings(list)
|
||||||
|
str.Uniq(&list)
|
||||||
for _, h := range list {
|
for _, h := range list {
|
||||||
st := goSum.status[modSum{m, h}]
|
st := goSum.status[modSum{m, h}]
|
||||||
if (!st.dirty || (st.used && keep[m])) && !sumInWorkspaceModulesLocked(m) {
|
if (!st.dirty || (st.used && keep[m])) && !sumInWorkspaceModulesLocked(m) {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,8 @@ Strings are written into the string table at the end of the file. Each string
|
||||||
is null-terminated. String offsets are relative to the start of the string table.
|
is null-terminated. String offsets are relative to the start of the string table.
|
||||||
Bools are written as uint32s: 0 for false and 1 for true.
|
Bools are written as uint32s: 0 for false and 1 for true.
|
||||||
|
|
||||||
|
The following is the format for a full module:
|
||||||
|
|
||||||
“go index v0\n”
|
“go index v0\n”
|
||||||
str uint32 - offset of string table
|
str uint32 - offset of string table
|
||||||
n uint32 - number of packages
|
n uint32 - number of packages
|
||||||
|
|
@ -40,7 +42,16 @@ for each RawPackage:
|
||||||
position - file, offset, line, column - uint32
|
position - file, offset, line, column - uint32
|
||||||
[string table]
|
[string table]
|
||||||
|
|
||||||
// parseError struct
|
The following is the format for a single indexed package:
|
||||||
|
|
||||||
|
“go index v0\n”
|
||||||
|
str uint32 - offset of string table
|
||||||
|
for the single RawPackage:
|
||||||
|
[same RawPackage format as above]
|
||||||
|
[string table]
|
||||||
|
|
||||||
|
The following is the definition of the json-serialized parseError struct:
|
||||||
|
|
||||||
type parseError struct {
|
type parseError struct {
|
||||||
ErrorList *scanner.ErrorList // non-nil if the error was an ErrorList, nil otherwise
|
ErrorList *scanner.ErrorList // non-nil if the error was an ErrorList, nil otherwise
|
||||||
ErrorString string // non-empty for all other cases
|
ErrorString string // non-empty for all other cases
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,10 @@ import (
|
||||||
"go/build"
|
"go/build"
|
||||||
"go/build/constraint"
|
"go/build/constraint"
|
||||||
"go/token"
|
"go/token"
|
||||||
|
"internal/godebug"
|
||||||
"internal/goroot"
|
"internal/goroot"
|
||||||
"internal/unsafeheader"
|
"internal/unsafeheader"
|
||||||
"io/fs"
|
|
||||||
"math"
|
"math"
|
||||||
"os"
|
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
@ -24,6 +23,7 @@ import (
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"cmd/go/internal/base"
|
"cmd/go/internal/base"
|
||||||
|
|
@ -39,79 +39,79 @@ import (
|
||||||
// It will be removed before the release.
|
// It will be removed before the release.
|
||||||
// TODO(matloob): Remove enabled once we have more confidence on the
|
// TODO(matloob): Remove enabled once we have more confidence on the
|
||||||
// module index.
|
// module index.
|
||||||
var enabled = func() bool {
|
var enabled bool = godebug.Get("goindex") != "0"
|
||||||
debug := strings.Split(os.Getenv("GODEBUG"), ",")
|
|
||||||
for _, f := range debug {
|
|
||||||
if f == "goindex=0" {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}()
|
|
||||||
|
|
||||||
// ModuleIndex represents and encoded module index file. It is used to
|
// Module represents and encoded module index file. It is used to
|
||||||
// do the equivalent of build.Import of packages in the module and answer other
|
// do the equivalent of build.Import of packages in the module and answer other
|
||||||
// questions based on the index file's data.
|
// questions based on the index file's data.
|
||||||
type ModuleIndex struct {
|
type Module struct {
|
||||||
modroot string
|
modroot string
|
||||||
od offsetDecoder
|
od offsetDecoder
|
||||||
packages map[string]int // offsets of each package
|
packages map[string]int // offsets of each package
|
||||||
packagePaths []string // paths to package directories relative to modroot; these are the keys of packages
|
packagePaths []string // paths to package directories relative to modroot; these are the keys of packages
|
||||||
}
|
}
|
||||||
|
|
||||||
var fcache par.Cache
|
// moduleHash returns an ActionID corresponding to the state of the module
|
||||||
|
// located at filesystem path modroot.
|
||||||
func moduleHash(modroot string, ismodcache bool) (cache.ActionID, error) {
|
func moduleHash(modroot string, ismodcache bool) (cache.ActionID, error) {
|
||||||
// We expect modules stored within the module cache to be checksummed and
|
// We expect modules stored within the module cache to be checksummed and
|
||||||
// immutable, and we expect released Go modules to change only infrequently
|
// immutable, and we expect released modules within GOROOT to change only
|
||||||
// (when the Go version changes).
|
// infrequently (when the Go version changes).
|
||||||
if !ismodcache || !str.HasFilePathPrefix(modroot, cfg.GOROOT) {
|
if !ismodcache {
|
||||||
|
// The contents of this module may change over time. We don't want to pay
|
||||||
|
// the cost to detect changes and re-index whenever they occur, so just
|
||||||
|
// don't index it at all.
|
||||||
|
//
|
||||||
|
// Note that this is true even for modules in GOROOT/src: non-release builds
|
||||||
|
// of the Go toolchain may have arbitrary development changes on top of the
|
||||||
|
// commit reported by runtime.Version, or could be completly artificial due
|
||||||
|
// to lacking a `git` binary (like "devel gomote.XXXXX", as synthesized by
|
||||||
|
// "gomote push" as of 2022-06-15). (Release builds shouldn't have
|
||||||
|
// modifications, but we don't want to use a behavior for releases that we
|
||||||
|
// haven't tested during development.)
|
||||||
return cache.ActionID{}, ErrNotIndexed
|
return cache.ActionID{}, ErrNotIndexed
|
||||||
}
|
}
|
||||||
|
|
||||||
h := cache.NewHash("moduleIndex")
|
h := cache.NewHash("moduleIndex")
|
||||||
fmt.Fprintf(h, "module index %s %s %v\n", runtime.Version(), indexVersion, modroot)
|
fmt.Fprintf(h, "module index %s %s %v\n", runtime.Version(), indexVersion, modroot)
|
||||||
|
return h.Sum(), nil
|
||||||
|
}
|
||||||
|
|
||||||
if strings.HasPrefix(runtime.Version(), "devel ") {
|
const modTimeCutoff = 2 * time.Second
|
||||||
// This copy of the standard library is a development version, not a
|
|
||||||
// release. It could be based on a Git commit (like "devel go1.19-2a78e8afc0
|
|
||||||
// Wed Jun 15 00:06:24 2022 +0000") with or without changes on top of that
|
|
||||||
// commit, or it could be completly artificial due to lacking a `git` binary
|
|
||||||
// (like "devel gomote.XXXXX", as synthesized by "gomote push" as of
|
|
||||||
// 2022-06-15). Compute an inexpensive hash of its files using mtimes so
|
|
||||||
// that during development we can continue to exercise the logic for cached
|
|
||||||
// GOROOT indexes.
|
|
||||||
//
|
|
||||||
// mtimes may be granular, imprecise, and loosely updated (see
|
|
||||||
// https://apenwarr.ca/log/20181113), but we don't expect Go contributors to
|
|
||||||
// be mucking around with the import graphs in GOROOT often enough for mtime
|
|
||||||
// collisions to matter essentially ever.
|
|
||||||
//
|
|
||||||
// Note that fsys.Walk walks paths in deterministic order, so this hash
|
|
||||||
// should be completely deterministic if the files are unchanged.
|
|
||||||
err := fsys.Walk(modroot, func(path string, info fs.FileInfo, err error) error {
|
|
||||||
if err := moduleWalkErr(modroot, path, info, err); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if info.IsDir() {
|
// dirHash returns an ActionID corresponding to the state of the package
|
||||||
return nil
|
// located at filesystem path pkgdir.
|
||||||
}
|
func dirHash(pkgdir string) (cache.ActionID, error) {
|
||||||
fmt.Fprintf(h, "file %v %v\n", info.Name(), info.ModTime())
|
h := cache.NewHash("moduleIndex")
|
||||||
if info.Mode()&fs.ModeSymlink != 0 {
|
fmt.Fprintf(h, "package %s %s %v\n", runtime.Version(), indexVersion, pkgdir)
|
||||||
targ, err := fsys.Stat(path)
|
entries, err := fsys.ReadDir(pkgdir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
// pkgdir might not be a directory. give up on hashing.
|
||||||
}
|
return cache.ActionID{}, ErrNotIndexed
|
||||||
fmt.Fprintf(h, "target %v %v\n", targ.Name(), targ.ModTime())
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return cache.ActionID{}, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
cutoff := time.Now().Add(-modTimeCutoff)
|
||||||
|
for _, info := range entries {
|
||||||
|
if info.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if !info.Mode().IsRegular() {
|
||||||
|
return cache.ActionID{}, ErrNotIndexed
|
||||||
|
}
|
||||||
|
// To avoid problems for very recent files where a new
|
||||||
|
// write might not change the mtime due to file system
|
||||||
|
// mtime precision, reject caching if a file was read that
|
||||||
|
// is less than modTimeCutoff old.
|
||||||
|
//
|
||||||
|
// This is the same strategy used for hashing test inputs.
|
||||||
|
// See hashOpen in cmd/go/internal/test/test.go for the
|
||||||
|
// corresponding code.
|
||||||
|
if info.ModTime().After(cutoff) {
|
||||||
|
return cache.ActionID{}, ErrNotIndexed
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt.Fprintf(h, "file %v %v %v\n", info.Name(), info.ModTime(), info.Size())
|
||||||
|
}
|
||||||
return h.Sum(), nil
|
return h.Sum(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -119,31 +119,61 @@ var modrootCache par.Cache
|
||||||
|
|
||||||
var ErrNotIndexed = errors.New("not in module index")
|
var ErrNotIndexed = errors.New("not in module index")
|
||||||
|
|
||||||
// Get returns the ModuleIndex for the module rooted at modroot.
|
var (
|
||||||
|
errDisabled = fmt.Errorf("%w: module indexing disabled", ErrNotIndexed)
|
||||||
|
errNotFromModuleCache = fmt.Errorf("%w: not from module cache", ErrNotIndexed)
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetPackage returns the IndexPackage for the package at the given path.
|
||||||
// It will return ErrNotIndexed if the directory should be read without
|
// It will return ErrNotIndexed if the directory should be read without
|
||||||
// using the index, for instance because the index is disabled, or the packgae
|
// using the index, for instance because the index is disabled, or the packgae
|
||||||
// is not in a module.
|
// is not in a module.
|
||||||
func Get(modroot string) (*ModuleIndex, error) {
|
func GetPackage(modroot, pkgdir string) (*IndexPackage, error) {
|
||||||
if !enabled || cache.DefaultDir() == "off" || cfg.BuildMod == "vendor" {
|
mi, err := GetModule(modroot)
|
||||||
return nil, ErrNotIndexed
|
if err == nil {
|
||||||
|
return mi.Package(relPath(pkgdir, modroot)), nil
|
||||||
}
|
}
|
||||||
if modroot == "" {
|
if !errors.Is(err, errNotFromModuleCache) {
|
||||||
panic("modindex.Get called with empty modroot")
|
return nil, err
|
||||||
}
|
}
|
||||||
modroot = filepath.Clean(modroot)
|
return openIndexPackage(modroot, pkgdir)
|
||||||
isModCache := str.HasFilePathPrefix(modroot, cfg.GOMODCACHE)
|
|
||||||
return openIndex(modroot, isModCache)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// openIndex returns the module index for modPath.
|
// GetModule returns the Module for the given modroot.
|
||||||
|
// It will return ErrNotIndexed if the directory should be read without
|
||||||
|
// using the index, for instance because the index is disabled, or the packgae
|
||||||
|
// is not in a module.
|
||||||
|
func GetModule(modroot string) (*Module, error) {
|
||||||
|
if !enabled || cache.DefaultDir() == "off" {
|
||||||
|
return nil, errDisabled
|
||||||
|
}
|
||||||
|
if modroot == "" {
|
||||||
|
panic("modindex.GetPackage called with empty modroot")
|
||||||
|
}
|
||||||
|
if cfg.BuildMod == "vendor" {
|
||||||
|
// Even if the main module is in the module cache,
|
||||||
|
// its vendored dependencies are not loaded from their
|
||||||
|
// usual cached locations.
|
||||||
|
return nil, errNotFromModuleCache
|
||||||
|
}
|
||||||
|
modroot = filepath.Clean(modroot)
|
||||||
|
if !str.HasFilePathPrefix(modroot, cfg.GOMODCACHE) {
|
||||||
|
return nil, errNotFromModuleCache
|
||||||
|
}
|
||||||
|
return openIndexModule(modroot, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
var mcache par.Cache
|
||||||
|
|
||||||
|
// openIndexModule returns the module index for modPath.
|
||||||
// It will return ErrNotIndexed if the module can not be read
|
// It will return ErrNotIndexed if the module can not be read
|
||||||
// using the index because it contains symlinks.
|
// using the index because it contains symlinks.
|
||||||
func openIndex(modroot string, ismodcache bool) (*ModuleIndex, error) {
|
func openIndexModule(modroot string, ismodcache bool) (*Module, error) {
|
||||||
type result struct {
|
type result struct {
|
||||||
mi *ModuleIndex
|
mi *Module
|
||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
r := fcache.Do(modroot, func() any {
|
r := mcache.Do(modroot, func() any {
|
||||||
id, err := moduleHash(modroot, ismodcache)
|
id, err := moduleHash(modroot, ismodcache)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return result{nil, err}
|
return result{nil, err}
|
||||||
|
|
@ -169,8 +199,38 @@ func openIndex(modroot string, ismodcache bool) (*ModuleIndex, error) {
|
||||||
return r.mi, r.err
|
return r.mi, r.err
|
||||||
}
|
}
|
||||||
|
|
||||||
// fromBytes returns a *ModuleIndex given the encoded representation.
|
var pcache par.Cache
|
||||||
func fromBytes(moddir string, data []byte) (mi *ModuleIndex, err error) {
|
|
||||||
|
func openIndexPackage(modroot, pkgdir string) (*IndexPackage, error) {
|
||||||
|
type result struct {
|
||||||
|
pkg *IndexPackage
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
r := pcache.Do(pkgdir, func() any {
|
||||||
|
id, err := dirHash(pkgdir)
|
||||||
|
if err != nil {
|
||||||
|
return result{nil, err}
|
||||||
|
}
|
||||||
|
data, _, err := cache.Default().GetMmap(id)
|
||||||
|
if err != nil {
|
||||||
|
// Couldn't read from index. Assume we couldn't read from
|
||||||
|
// the index because the package hasn't been indexed yet.
|
||||||
|
data = indexPackage(modroot, pkgdir)
|
||||||
|
if err = cache.Default().PutBytes(id, data); err != nil {
|
||||||
|
return result{nil, err}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pkg, err := packageFromBytes(modroot, data)
|
||||||
|
if err != nil {
|
||||||
|
return result{nil, err}
|
||||||
|
}
|
||||||
|
return result{pkg, nil}
|
||||||
|
}).(result)
|
||||||
|
return r.pkg, r.err
|
||||||
|
}
|
||||||
|
|
||||||
|
// fromBytes returns a *Module given the encoded representation.
|
||||||
|
func fromBytes(moddir string, data []byte) (mi *Module, err error) {
|
||||||
if !enabled {
|
if !enabled {
|
||||||
panic("use of index")
|
panic("use of index")
|
||||||
}
|
}
|
||||||
|
|
@ -220,7 +280,7 @@ func fromBytes(moddir string, data []byte) (mi *ModuleIndex, err error) {
|
||||||
packages[packagePaths[i]] = packageOffsets[i]
|
packages[packagePaths[i]] = packageOffsets[i]
|
||||||
}
|
}
|
||||||
|
|
||||||
return &ModuleIndex{
|
return &Module{
|
||||||
moddir,
|
moddir,
|
||||||
offsetDecoder{data, st},
|
offsetDecoder{data, st},
|
||||||
packages,
|
packages,
|
||||||
|
|
@ -228,21 +288,60 @@ func fromBytes(moddir string, data []byte) (mi *ModuleIndex, err error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// packageFromBytes returns a *IndexPackage given the encoded representation.
|
||||||
|
func packageFromBytes(modroot string, data []byte) (p *IndexPackage, err error) {
|
||||||
|
if !enabled {
|
||||||
|
panic("use of package index when not enabled")
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetPanicOnFault's errors _may_ satisfy this interface. Even though it's not guaranteed
|
||||||
|
// that all its errors satisfy this interface, we'll only check for these errors so that
|
||||||
|
// we don't suppress panics that could have been produced from other sources.
|
||||||
|
type addrer interface {
|
||||||
|
Addr() uintptr
|
||||||
|
}
|
||||||
|
|
||||||
|
// set PanicOnFault to true so that we can catch errors on the initial reads of the slice,
|
||||||
|
// in case it's mmapped (the common case).
|
||||||
|
old := debug.SetPanicOnFault(true)
|
||||||
|
defer func() {
|
||||||
|
debug.SetPanicOnFault(old)
|
||||||
|
if e := recover(); e != nil {
|
||||||
|
if _, ok := e.(addrer); ok {
|
||||||
|
// This panic was almost certainly caused by SetPanicOnFault.
|
||||||
|
err = fmt.Errorf("error reading module index: %v", e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// The panic was likely not caused by SetPanicOnFault.
|
||||||
|
panic(e)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
gotVersion, unread, _ := bytes.Cut(data, []byte{'\n'})
|
||||||
|
if string(gotVersion) != indexVersion {
|
||||||
|
return nil, fmt.Errorf("bad index version string: %q", gotVersion)
|
||||||
|
}
|
||||||
|
stringTableOffset, unread := binary.LittleEndian.Uint32(unread[:4]), unread[4:]
|
||||||
|
st := newStringTable(data[stringTableOffset:])
|
||||||
|
d := &decoder{unread, st}
|
||||||
|
p = decodePackage(d, offsetDecoder{data, st})
|
||||||
|
p.modroot = modroot
|
||||||
|
return p, nil
|
||||||
|
}
|
||||||
|
|
||||||
// Returns a list of directory paths, relative to the modroot, for
|
// Returns a list of directory paths, relative to the modroot, for
|
||||||
// packages contained in the module index.
|
// packages contained in the module index.
|
||||||
func (mi *ModuleIndex) Packages() []string {
|
func (mi *Module) Packages() []string {
|
||||||
return mi.packagePaths
|
return mi.packagePaths
|
||||||
}
|
}
|
||||||
|
|
||||||
// RelPath returns the path relative to the module's root.
|
// relPath returns the path relative to the module's root.
|
||||||
func (mi *ModuleIndex) RelPath(path string) string {
|
func relPath(path, modroot string) string {
|
||||||
return str.TrimFilePathPrefix(filepath.Clean(path), mi.modroot) // mi.modroot is already clean
|
return str.TrimFilePathPrefix(filepath.Clean(path), filepath.Clean(modroot))
|
||||||
}
|
}
|
||||||
|
|
||||||
// ImportPackage is the equivalent of build.Import given the information in ModuleIndex.
|
// Import is the equivalent of build.Import given the information in Module.
|
||||||
func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.ImportMode) (p *build.Package, err error) {
|
func (rp *IndexPackage) Import(bctxt build.Context, mode build.ImportMode) (p *build.Package, err error) {
|
||||||
rp := mi.indexPackage(relpath)
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("error reading module index: %v", e)
|
err = fmt.Errorf("error reading module index: %v", e)
|
||||||
|
|
@ -254,7 +353,7 @@ func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.Im
|
||||||
p = &build.Package{}
|
p = &build.Package{}
|
||||||
|
|
||||||
p.ImportPath = "."
|
p.ImportPath = "."
|
||||||
p.Dir = filepath.Join(mi.modroot, rp.dir)
|
p.Dir = filepath.Join(rp.modroot, rp.dir)
|
||||||
|
|
||||||
var pkgerr error
|
var pkgerr error
|
||||||
switch ctxt.Compiler {
|
switch ctxt.Compiler {
|
||||||
|
|
@ -272,7 +371,7 @@ func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.Im
|
||||||
inTestdata := func(sub string) bool {
|
inTestdata := func(sub string) bool {
|
||||||
return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || str.HasPathPrefix(sub, "testdata")
|
return strings.Contains(sub, "/testdata/") || strings.HasSuffix(sub, "/testdata") || str.HasPathPrefix(sub, "testdata")
|
||||||
}
|
}
|
||||||
if !inTestdata(relpath) {
|
if !inTestdata(rp.dir) {
|
||||||
// In build.go, p.Root should only be set in the non-local-import case, or in
|
// In build.go, p.Root should only be set in the non-local-import case, or in
|
||||||
// GOROOT or GOPATH. Since module mode only calls Import with path set to "."
|
// GOROOT or GOPATH. Since module mode only calls Import with path set to "."
|
||||||
// and the module index doesn't apply outside modules, the GOROOT case is
|
// and the module index doesn't apply outside modules, the GOROOT case is
|
||||||
|
|
@ -284,8 +383,8 @@ func (mi *ModuleIndex) Import(bctxt build.Context, relpath string, mode build.Im
|
||||||
if ctxt.GOROOT != "" && str.HasFilePathPrefix(p.Dir, cfg.GOROOTsrc) && p.Dir != cfg.GOROOTsrc {
|
if ctxt.GOROOT != "" && str.HasFilePathPrefix(p.Dir, cfg.GOROOTsrc) && p.Dir != cfg.GOROOTsrc {
|
||||||
p.Root = ctxt.GOROOT
|
p.Root = ctxt.GOROOT
|
||||||
p.Goroot = true
|
p.Goroot = true
|
||||||
modprefix := str.TrimFilePathPrefix(mi.modroot, cfg.GOROOTsrc)
|
modprefix := str.TrimFilePathPrefix(rp.modroot, cfg.GOROOTsrc)
|
||||||
p.ImportPath = relpath
|
p.ImportPath = rp.dir
|
||||||
if modprefix != "" {
|
if modprefix != "" {
|
||||||
p.ImportPath = filepath.Join(modprefix, p.ImportPath)
|
p.ImportPath = filepath.Join(modprefix, p.ImportPath)
|
||||||
}
|
}
|
||||||
|
|
@ -557,20 +656,21 @@ func IsStandardPackage(goroot_, compiler, path string) bool {
|
||||||
reldir = str.TrimFilePathPrefix(reldir, "cmd")
|
reldir = str.TrimFilePathPrefix(reldir, "cmd")
|
||||||
modroot = filepath.Join(modroot, "cmd")
|
modroot = filepath.Join(modroot, "cmd")
|
||||||
}
|
}
|
||||||
mod, err := Get(modroot)
|
if _, err := GetPackage(modroot, filepath.Join(modroot, reldir)); err == nil {
|
||||||
if err != nil {
|
// Note that goroot.IsStandardPackage doesn't check that the directory
|
||||||
|
// actually contains any go files-- merely that it exists. GetPackage
|
||||||
|
// returning a nil error is enough for us to know the directory exists.
|
||||||
|
return true
|
||||||
|
} else if errors.Is(err, ErrNotIndexed) {
|
||||||
|
// Fall back because package isn't indexable. (Probably because
|
||||||
|
// a file was modified recently)
|
||||||
return goroot.IsStandardPackage(goroot_, compiler, path)
|
return goroot.IsStandardPackage(goroot_, compiler, path)
|
||||||
}
|
}
|
||||||
|
return false
|
||||||
pkgs := mod.Packages()
|
|
||||||
i := sort.SearchStrings(pkgs, reldir)
|
|
||||||
return i != len(pkgs) && pkgs[i] == reldir
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsDirWithGoFiles is the equivalent of fsys.IsDirWithGoFiles using the information in the index.
|
// IsDirWithGoFiles is the equivalent of fsys.IsDirWithGoFiles using the information in the index.
|
||||||
func (mi *ModuleIndex) IsDirWithGoFiles(relpath string) (_ bool, err error) {
|
func (rp *IndexPackage) IsDirWithGoFiles() (_ bool, err error) {
|
||||||
rp := mi.indexPackage(relpath)
|
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
err = fmt.Errorf("error reading module index: %v", e)
|
err = fmt.Errorf("error reading module index: %v", e)
|
||||||
|
|
@ -585,9 +685,7 @@ func (mi *ModuleIndex) IsDirWithGoFiles(relpath string) (_ bool, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ScanDir implements imports.ScanDir using the information in the index.
|
// ScanDir implements imports.ScanDir using the information in the index.
|
||||||
func (mi *ModuleIndex) ScanDir(path string, tags map[string]bool) (sortedImports []string, sortedTestImports []string, err error) {
|
func (rp *IndexPackage) ScanDir(tags map[string]bool) (sortedImports []string, sortedTestImports []string, err error) {
|
||||||
rp := mi.indexPackage(path)
|
|
||||||
|
|
||||||
// TODO(matloob) dir should eventually be relative to indexed directory
|
// TODO(matloob) dir should eventually be relative to indexed directory
|
||||||
// TODO(matloob): skip reading raw package and jump straight to data we need?
|
// TODO(matloob): skip reading raw package and jump straight to data we need?
|
||||||
|
|
||||||
|
|
@ -675,20 +773,22 @@ func shouldBuild(sf *sourceFile, tags map[string]bool) bool {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// index package holds the information needed to access information in the
|
// IndexPackage holds the information needed to access information in the
|
||||||
// index about a package.
|
// index needed to load a package in a specific directory.
|
||||||
type indexPackage struct {
|
type IndexPackage struct {
|
||||||
error error
|
error error
|
||||||
dir string // directory of the package relative to the modroot
|
dir string // directory of the package relative to the modroot
|
||||||
|
|
||||||
|
modroot string
|
||||||
|
|
||||||
// Source files
|
// Source files
|
||||||
sourceFiles []*sourceFile
|
sourceFiles []*sourceFile
|
||||||
}
|
}
|
||||||
|
|
||||||
var errCannotFindPackage = errors.New("cannot find package")
|
var errCannotFindPackage = errors.New("cannot find package")
|
||||||
|
|
||||||
// indexPackage returns an indexPackage constructed using the information in the ModuleIndex.
|
// Package returns an IndexPackage constructed using the information in the Module.
|
||||||
func (mi *ModuleIndex) indexPackage(path string) *indexPackage {
|
func (mi *Module) Package(path string) *IndexPackage {
|
||||||
defer func() {
|
defer func() {
|
||||||
if e := recover(); e != nil {
|
if e := recover(); e != nil {
|
||||||
base.Fatalf("error reading module index: %v", e)
|
base.Fatalf("error reading module index: %v", e)
|
||||||
|
|
@ -696,12 +796,18 @@ func (mi *ModuleIndex) indexPackage(path string) *indexPackage {
|
||||||
}()
|
}()
|
||||||
offset, ok := mi.packages[path]
|
offset, ok := mi.packages[path]
|
||||||
if !ok {
|
if !ok {
|
||||||
return &indexPackage{error: fmt.Errorf("%w %q in:\n\t%s", errCannotFindPackage, path, filepath.Join(mi.modroot, path))}
|
return &IndexPackage{error: fmt.Errorf("%w %q in:\n\t%s", errCannotFindPackage, path, filepath.Join(mi.modroot, path))}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(matloob): do we want to lock on the module index?
|
// TODO(matloob): do we want to lock on the module index?
|
||||||
d := mi.od.decoderAt(offset)
|
d := mi.od.decoderAt(offset)
|
||||||
rp := new(indexPackage)
|
p := decodePackage(d, mi.od)
|
||||||
|
p.modroot = mi.modroot
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func decodePackage(d *decoder, od offsetDecoder) *IndexPackage {
|
||||||
|
rp := new(IndexPackage)
|
||||||
if errstr := d.string(); errstr != "" {
|
if errstr := d.string(); errstr != "" {
|
||||||
rp.error = errors.New(errstr)
|
rp.error = errors.New(errstr)
|
||||||
}
|
}
|
||||||
|
|
@ -711,7 +817,7 @@ func (mi *ModuleIndex) indexPackage(path string) *indexPackage {
|
||||||
for i := uint32(0); i < numSourceFiles; i++ {
|
for i := uint32(0); i < numSourceFiles; i++ {
|
||||||
offset := d.uint32()
|
offset := d.uint32()
|
||||||
rp.sourceFiles[i] = &sourceFile{
|
rp.sourceFiles[i] = &sourceFile{
|
||||||
od: mi.od.offsetDecoderAt(offset),
|
od: od.offsetDecoderAt(offset),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rp
|
return rp
|
||||||
|
|
|
||||||
|
|
@ -65,7 +65,15 @@ func indexModule(modroot string) ([]byte, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return encodeModule(packages), nil
|
return encodeModuleBytes(packages), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// indexModule indexes the package at the given directory and returns its
|
||||||
|
// encoded representation. It returns ErrNotIndexed if the package can't
|
||||||
|
// be indexed.
|
||||||
|
func indexPackage(modroot, pkgdir string) []byte {
|
||||||
|
p := importRaw(modroot, relPath(pkgdir, modroot))
|
||||||
|
return encodePackageBytes(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
// rawPackage holds the information from each package that's needed to
|
// rawPackage holds the information from each package that's needed to
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,9 @@ import (
|
||||||
|
|
||||||
const indexVersion = "go index v0"
|
const indexVersion = "go index v0"
|
||||||
|
|
||||||
// encodeModule produces the encoded representation of the module index.
|
// encodeModuleBytes produces the encoded representation of the module index.
|
||||||
// encodeModule may modify the packages slice.
|
// encodeModuleBytes may modify the packages slice.
|
||||||
func encodeModule(packages []*rawPackage) []byte {
|
func encodeModuleBytes(packages []*rawPackage) []byte {
|
||||||
e := newEncoder()
|
e := newEncoder()
|
||||||
e.Bytes([]byte(indexVersion))
|
e.Bytes([]byte(indexVersion))
|
||||||
e.Bytes([]byte{'\n'})
|
e.Bytes([]byte{'\n'})
|
||||||
|
|
@ -39,6 +39,18 @@ func encodeModule(packages []*rawPackage) []byte {
|
||||||
return e.b
|
return e.b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func encodePackageBytes(p *rawPackage) []byte {
|
||||||
|
e := newEncoder()
|
||||||
|
e.Bytes([]byte(indexVersion))
|
||||||
|
e.Bytes([]byte{'\n'})
|
||||||
|
stringTableOffsetPos := e.Pos() // fill this at the end
|
||||||
|
e.Uint32(0) // string table offset
|
||||||
|
encodePackage(e, p)
|
||||||
|
e.IntAt(e.Pos(), stringTableOffsetPos)
|
||||||
|
e.Bytes(e.stringTable)
|
||||||
|
return e.b
|
||||||
|
}
|
||||||
|
|
||||||
func encodePackage(e *encoder, p *rawPackage) {
|
func encodePackage(e *encoder, p *rawPackage) {
|
||||||
e.String(p.error)
|
e.String(p.error)
|
||||||
e.String(p.dir)
|
e.String(p.dir)
|
||||||
|
|
|
||||||
|
|
@ -657,11 +657,11 @@ func dirInModule(path, mpath, mdir string, isLocal bool) (dir string, haveGoFile
|
||||||
// We don't care about build tags, not even "+build ignore".
|
// We don't care about build tags, not even "+build ignore".
|
||||||
// We're just looking for a plausible directory.
|
// We're just looking for a plausible directory.
|
||||||
res := haveGoFilesCache.Do(dir, func() any {
|
res := haveGoFilesCache.Do(dir, func() any {
|
||||||
// modindex.Get will return ErrNotIndexed for any directories which
|
// modindex.GetPackage will return ErrNotIndexed for any directories which
|
||||||
// are reached through a symlink, so that they will be handled by
|
// are reached through a symlink, so that they will be handled by
|
||||||
// fsys.IsDirWithGoFiles below.
|
// fsys.IsDirWithGoFiles below.
|
||||||
if mi, err := modindex.Get(mdir); err == nil {
|
if ip, err := modindex.GetPackage(mdir, dir); err == nil {
|
||||||
isDirWithGoFiles, err := mi.IsDirWithGoFiles(mi.RelPath(dir))
|
isDirWithGoFiles, err := ip.IsDirWithGoFiles()
|
||||||
return goFilesEntry{isDirWithGoFiles, err}
|
return goFilesEntry{isDirWithGoFiles, err}
|
||||||
} else if !errors.Is(err, modindex.ErrNotIndexed) {
|
} else if !errors.Is(err, modindex.ErrNotIndexed) {
|
||||||
return goFilesEntry{err: err}
|
return goFilesEntry{err: err}
|
||||||
|
|
|
||||||
|
|
@ -2102,8 +2102,8 @@ func (ld *loader) checkTidyCompatibility(ctx context.Context, rs *Requirements)
|
||||||
// may see these legacy imports. We drop them so that the module
|
// may see these legacy imports. We drop them so that the module
|
||||||
// search does not look for modules to try to satisfy them.
|
// search does not look for modules to try to satisfy them.
|
||||||
func scanDir(modroot string, dir string, tags map[string]bool) (imports_, testImports []string, err error) {
|
func scanDir(modroot string, dir string, tags map[string]bool) (imports_, testImports []string, err error) {
|
||||||
if mi, mierr := modindex.Get(modroot); mierr == nil {
|
if ip, mierr := modindex.GetPackage(modroot, dir); mierr == nil {
|
||||||
imports_, testImports, err = mi.ScanDir(mi.RelPath(dir), tags)
|
imports_, testImports, err = ip.ScanDir(tags)
|
||||||
goto Happy
|
goto Happy
|
||||||
} else if !errors.Is(mierr, modindex.ErrNotIndexed) {
|
} else if !errors.Is(mierr, modindex.ErrNotIndexed) {
|
||||||
return nil, nil, mierr
|
return nil, nil, mierr
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,9 @@ import (
|
||||||
// If path is the path of the main module and the query is "latest",
|
// If path is the path of the main module and the query is "latest",
|
||||||
// Query returns Target.Version as the version.
|
// Query returns Target.Version as the version.
|
||||||
func Query(ctx context.Context, path, query, current string, allowed AllowedFunc) (*modfetch.RevInfo, error) {
|
func Query(ctx context.Context, path, query, current string, allowed AllowedFunc) (*modfetch.RevInfo, error) {
|
||||||
|
ctx, span := trace.StartSpan(ctx, "modload.Query "+path)
|
||||||
|
defer span.Done()
|
||||||
|
|
||||||
var info *modfetch.RevInfo
|
var info *modfetch.RevInfo
|
||||||
err := modfetch.TryProxies(func(proxy string) (err error) {
|
err := modfetch.TryProxies(func(proxy string) (err error) {
|
||||||
info, err = queryProxy(ctx, proxy, path, query, current, allowed)
|
info, err = queryProxy(ctx, proxy, path, query, current, allowed)
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import (
|
||||||
"cmd/go/internal/modindex"
|
"cmd/go/internal/modindex"
|
||||||
"cmd/go/internal/par"
|
"cmd/go/internal/par"
|
||||||
"cmd/go/internal/search"
|
"cmd/go/internal/search"
|
||||||
|
"cmd/go/internal/trace"
|
||||||
|
|
||||||
"golang.org/x/mod/module"
|
"golang.org/x/mod/module"
|
||||||
)
|
)
|
||||||
|
|
@ -38,6 +39,9 @@ const (
|
||||||
// a global) for tags, can include or exclude packages in the standard library,
|
// a global) for tags, can include or exclude packages in the standard library,
|
||||||
// and is restricted to the given list of modules.
|
// and is restricted to the given list of modules.
|
||||||
func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, filter stdFilter, modules []module.Version) {
|
func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, filter stdFilter, modules []module.Version) {
|
||||||
|
ctx, span := trace.StartSpan(ctx, "modload.matchPackages")
|
||||||
|
defer span.Done()
|
||||||
|
|
||||||
m.Pkgs = []string{}
|
m.Pkgs = []string{}
|
||||||
|
|
||||||
isMatch := func(string) bool { return true }
|
isMatch := func(string) bool { return true }
|
||||||
|
|
@ -69,6 +73,9 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f
|
||||||
q := par.NewQueue(runtime.GOMAXPROCS(0))
|
q := par.NewQueue(runtime.GOMAXPROCS(0))
|
||||||
|
|
||||||
walkPkgs := func(root, importPathRoot string, prune pruning) {
|
walkPkgs := func(root, importPathRoot string, prune pruning) {
|
||||||
|
_, span := trace.StartSpan(ctx, "walkPkgs "+root)
|
||||||
|
defer span.Done()
|
||||||
|
|
||||||
root = filepath.Clean(root)
|
root = filepath.Clean(root)
|
||||||
err := fsys.Walk(root, func(path string, fi fs.FileInfo, err error) error {
|
err := fsys.Walk(root, func(path string, fi fs.FileInfo, err error) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -188,7 +195,7 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f
|
||||||
}
|
}
|
||||||
modPrefix = mod.Path
|
modPrefix = mod.Path
|
||||||
}
|
}
|
||||||
if mi, err := modindex.Get(root); err == nil {
|
if mi, err := modindex.GetModule(root); err == nil {
|
||||||
walkFromIndex(mi, modPrefix, isMatch, treeCanMatch, tags, have, addPkg)
|
walkFromIndex(mi, modPrefix, isMatch, treeCanMatch, tags, have, addPkg)
|
||||||
continue
|
continue
|
||||||
} else if !errors.Is(err, modindex.ErrNotIndexed) {
|
} else if !errors.Is(err, modindex.ErrNotIndexed) {
|
||||||
|
|
@ -206,9 +213,9 @@ func matchPackages(ctx context.Context, m *search.Match, tags map[string]bool, f
|
||||||
}
|
}
|
||||||
|
|
||||||
// walkFromIndex matches packages in a module using the module index. modroot
|
// walkFromIndex matches packages in a module using the module index. modroot
|
||||||
// is the module's root directory on disk, index is the ModuleIndex for the
|
// is the module's root directory on disk, index is the modindex.Module for the
|
||||||
// module, and importPathRoot is the module's path prefix.
|
// module, and importPathRoot is the module's path prefix.
|
||||||
func walkFromIndex(index *modindex.ModuleIndex, importPathRoot string, isMatch, treeCanMatch func(string) bool, tags, have map[string]bool, addPkg func(string)) {
|
func walkFromIndex(index *modindex.Module, importPathRoot string, isMatch, treeCanMatch func(string) bool, tags, have map[string]bool, addPkg func(string)) {
|
||||||
loopPackages:
|
loopPackages:
|
||||||
for _, reldir := range index.Packages() {
|
for _, reldir := range index.Packages() {
|
||||||
// Avoid .foo, _foo, and testdata subdirectory trees.
|
// Avoid .foo, _foo, and testdata subdirectory trees.
|
||||||
|
|
@ -245,7 +252,7 @@ loopPackages:
|
||||||
if !have[name] {
|
if !have[name] {
|
||||||
have[name] = true
|
have[name] = true
|
||||||
if isMatch(name) {
|
if isMatch(name) {
|
||||||
if _, _, err := index.ScanDir(reldir, tags); err != imports.ErrNoGo {
|
if _, _, err := index.Package(reldir).ScanDir(tags); err != imports.ErrNoGo {
|
||||||
addPkg(name)
|
addPkg(name)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -164,13 +164,16 @@ func (b *Builder) toolID(name string) string {
|
||||||
cmd.Stdout = &stdout
|
cmd.Stdout = &stdout
|
||||||
cmd.Stderr = &stderr
|
cmd.Stderr = &stderr
|
||||||
if err := cmd.Run(); err != nil {
|
if err := cmd.Run(); err != nil {
|
||||||
base.Fatalf("%s: %v\n%s%s", desc, err, stdout.Bytes(), stderr.Bytes())
|
if stderr.Len() > 0 {
|
||||||
|
os.Stderr.Write(stderr.Bytes())
|
||||||
|
}
|
||||||
|
base.Fatalf("go: error obtaining buildID for %s: %v", desc, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
line := stdout.String()
|
line := stdout.String()
|
||||||
f := strings.Fields(line)
|
f := strings.Fields(line)
|
||||||
if len(f) < 3 || f[0] != name && path != VetTool || f[1] != "version" || f[2] == "devel" && !strings.HasPrefix(f[len(f)-1], "buildID=") {
|
if len(f) < 3 || f[0] != name && path != VetTool || f[1] != "version" || f[2] == "devel" && !strings.HasPrefix(f[len(f)-1], "buildID=") {
|
||||||
base.Fatalf("%s -V=full: unexpected output:\n\t%s", desc, line)
|
base.Fatalf("go: parsing buildID from %s -V=full: unexpected output:\n\t%s", desc, line)
|
||||||
}
|
}
|
||||||
if f[2] == "devel" {
|
if f[2] == "devel" {
|
||||||
// On the development branch, use the content ID part of the build ID.
|
// On the development branch, use the content ID part of the build ID.
|
||||||
|
|
|
||||||
|
|
@ -2405,6 +2405,7 @@ func (b *Builder) ccompile(a *Action, p *load.Package, outfile string, flags []s
|
||||||
}
|
}
|
||||||
|
|
||||||
// gccld runs the gcc linker to create an executable from a set of object files.
|
// gccld runs the gcc linker to create an executable from a set of object files.
|
||||||
|
// Any error output is only displayed for BuildN or BuildX.
|
||||||
func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flags []string, objs []string) error {
|
func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flags []string, objs []string) error {
|
||||||
var cmd []string
|
var cmd []string
|
||||||
if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 {
|
if len(p.CXXFiles) > 0 || len(p.SwigCXXFiles) > 0 {
|
||||||
|
|
@ -2450,11 +2451,8 @@ func (b *Builder) gccld(a *Action, p *load.Package, objdir, outfile string, flag
|
||||||
save = append(save, line)
|
save = append(save, line)
|
||||||
}
|
}
|
||||||
out = bytes.Join(save, nil)
|
out = bytes.Join(save, nil)
|
||||||
if len(out) > 0 {
|
if len(out) > 0 && (cfg.BuildN || cfg.BuildX) {
|
||||||
b.showOutput(nil, dir, p.ImportPath, b.processOutput(out))
|
b.showOutput(nil, dir, p.ImportPath, b.processOutput(out))
|
||||||
if err != nil {
|
|
||||||
err = errPrintedOutput
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
|
|
@ -2913,10 +2911,16 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
|
||||||
switch cfg.BuildToolchainName {
|
switch cfg.BuildToolchainName {
|
||||||
case "gc":
|
case "gc":
|
||||||
importGo := objdir + "_cgo_import.go"
|
importGo := objdir + "_cgo_import.go"
|
||||||
if err := b.dynimport(a, p, objdir, importGo, cgoExe, cflags, cgoLDFLAGS, outObj); err != nil {
|
dynOutGo, dynOutObj, err := b.dynimport(a, p, objdir, importGo, cgoExe, cflags, cgoLDFLAGS, outObj)
|
||||||
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
outGo = append(outGo, importGo)
|
if dynOutGo != "" {
|
||||||
|
outGo = append(outGo, dynOutGo)
|
||||||
|
}
|
||||||
|
if dynOutObj != "" {
|
||||||
|
outObj = append(outObj, dynOutObj)
|
||||||
|
}
|
||||||
|
|
||||||
case "gccgo":
|
case "gccgo":
|
||||||
defunC := objdir + "_cgo_defun.c"
|
defunC := objdir + "_cgo_defun.c"
|
||||||
|
|
@ -3011,11 +3015,13 @@ func (b *Builder) cgo(a *Action, cgoExe, objdir string, pcCFLAGS, pcLDFLAGS, cgo
|
||||||
// dynimport creates a Go source file named importGo containing
|
// dynimport creates a Go source file named importGo containing
|
||||||
// //go:cgo_import_dynamic directives for each symbol or library
|
// //go:cgo_import_dynamic directives for each symbol or library
|
||||||
// dynamically imported by the object files outObj.
|
// dynamically imported by the object files outObj.
|
||||||
func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) error {
|
// dynOutGo, if not empty, is a new Go file to build as part of the package.
|
||||||
|
// dynOutObj, if not empty, is a new file to add to the generated archive.
|
||||||
|
func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe string, cflags, cgoLDFLAGS, outObj []string) (dynOutGo, dynOutObj string, err error) {
|
||||||
cfile := objdir + "_cgo_main.c"
|
cfile := objdir + "_cgo_main.c"
|
||||||
ofile := objdir + "_cgo_main.o"
|
ofile := objdir + "_cgo_main.o"
|
||||||
if err := b.gcc(a, p, objdir, ofile, cflags, cfile); err != nil {
|
if err := b.gcc(a, p, objdir, ofile, cflags, cfile); err != nil {
|
||||||
return err
|
return "", "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gather .syso files from this package and all (transitive) dependencies.
|
// Gather .syso files from this package and all (transitive) dependencies.
|
||||||
|
|
@ -3060,7 +3066,22 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if err := b.gccld(a, p, objdir, dynobj, ldflags, linkobj); err != nil {
|
if err := b.gccld(a, p, objdir, dynobj, ldflags, linkobj); err != nil {
|
||||||
return err
|
// We only need this information for internal linking.
|
||||||
|
// If this link fails, mark the object as requiring
|
||||||
|
// external linking. This link can fail for things like
|
||||||
|
// syso files that have unexpected dependencies.
|
||||||
|
// cmd/link explicitly looks for the name "dynimportfail".
|
||||||
|
// See issue #52863.
|
||||||
|
fail := objdir + "dynimportfail"
|
||||||
|
if cfg.BuildN || cfg.BuildX {
|
||||||
|
b.Showcmd("", "echo > %s", fail)
|
||||||
|
}
|
||||||
|
if !cfg.BuildN {
|
||||||
|
if err := os.WriteFile(fail, nil, 0666); err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "", fail, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// cgo -dynimport
|
// cgo -dynimport
|
||||||
|
|
@ -3068,7 +3089,11 @@ func (b *Builder) dynimport(a *Action, p *load.Package, objdir, importGo, cgoExe
|
||||||
if p.Standard && p.ImportPath == "runtime/cgo" {
|
if p.Standard && p.ImportPath == "runtime/cgo" {
|
||||||
cgoflags = []string{"-dynlinker"} // record path to dynamic linker
|
cgoflags = []string{"-dynlinker"} // record path to dynamic linker
|
||||||
}
|
}
|
||||||
return b.run(a, base.Cwd(), p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
|
err = b.run(a, base.Cwd(), p.ImportPath, b.cCompilerEnv(), cfg.BuildToolexec, cgoExe, "-dynpackage", p.Name, "-dynimport", dynobj, "-dynout", importGo, cgoflags)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
return importGo, "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run SWIG on all SWIG input files.
|
// Run SWIG on all SWIG input files.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,68 @@
|
||||||
|
# Issue 52863.
|
||||||
|
|
||||||
|
# We manually create a .syso and a .a file in package a,
|
||||||
|
# such that the .syso file only works when linked against the .a file.
|
||||||
|
# Package a has #cgo LDFLAGS to make this happen.
|
||||||
|
#
|
||||||
|
# Package c imports package a, and uses cgo itself.
|
||||||
|
# The generation of the _cgo_import.go for package c will fail,
|
||||||
|
# because it won't know that it has to link against a/libb.a
|
||||||
|
# (because we don't gather the #cgo LDFLAGS from all transitively
|
||||||
|
# imported packages).
|
||||||
|
#
|
||||||
|
# The _cgo_import.go file is only needed for internal linking.
|
||||||
|
# When generating _cgo_import.go for package c fails, an ordinary
|
||||||
|
# external link should still work. But an internal link is expected
|
||||||
|
# to fail, because the failure to create _cgo_import.go should cause
|
||||||
|
# the linker to report an inability to internally link.
|
||||||
|
|
||||||
|
[short] skip
|
||||||
|
[!cgo] skip
|
||||||
|
[!exec:ar] skip
|
||||||
|
|
||||||
|
cc -c -o a/b.syso b/b.c
|
||||||
|
cc -c -o b/lib.o b/lib.c
|
||||||
|
exec ar rc a/libb.a b/lib.o
|
||||||
|
go build
|
||||||
|
! go build -ldflags=-linkmode=internal
|
||||||
|
stderr 'some packages could not be built to support internal linking.*m/c|requires external linking|does not support internal cgo'
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module m
|
||||||
|
|
||||||
|
-- a/a.go --
|
||||||
|
package a
|
||||||
|
|
||||||
|
// #cgo LDFLAGS: -L. -lb
|
||||||
|
// extern int CFn(int);
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
func GoFn(v int) int { return int(C.CFn(C.int(v))) }
|
||||||
|
|
||||||
|
-- b/b.c --
|
||||||
|
extern int LibFn(int);
|
||||||
|
int CFn(int i) { return LibFn(i); }
|
||||||
|
|
||||||
|
-- b/lib.c --
|
||||||
|
int LibFn(int i) { return i; }
|
||||||
|
|
||||||
|
-- c/c.go --
|
||||||
|
package c
|
||||||
|
|
||||||
|
// static int D(int i) { return i; }
|
||||||
|
import "C"
|
||||||
|
|
||||||
|
import "m/a"
|
||||||
|
|
||||||
|
func Fn(i int) (int, int) {
|
||||||
|
return a.GoFn(i), int(C.D(C.int(i)))
|
||||||
|
}
|
||||||
|
|
||||||
|
-- main.go --
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "m/c"
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
println(c.Fn(0))
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
env GO111MODULE=on
|
||||||
|
|
||||||
|
# Regression test for golang.org/issue/28456:
|
||||||
|
# 'go mod tidy' should not leave duplicate lines when re-writing the file.
|
||||||
|
|
||||||
|
go mod tidy
|
||||||
|
cmp go.sum golden.sum
|
||||||
|
|
||||||
|
-- go.mod --
|
||||||
|
module use
|
||||||
|
|
||||||
|
go 1.16
|
||||||
|
|
||||||
|
require rsc.io/quote v1.5.2
|
||||||
|
|
||||||
|
-- go.sum --
|
||||||
|
rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
|
||||||
|
rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
|
||||||
|
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
|
||||||
|
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
|
||||||
|
rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
|
||||||
|
rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
|
||||||
|
-- golden.sum --
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:pvCbr/wm8HzDD3fVywevekufpn6tCGPY3spdHeZJEsw=
|
||||||
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
|
rsc.io/quote v1.5.2 h1:3fEykkD9k7lYzXqCYrwGAf7iNhbk4yCjHmKBN9td4L0=
|
||||||
|
rsc.io/quote v1.5.2/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPXsUe+TKr0=
|
||||||
|
rsc.io/sampler v1.3.0 h1:HLGR/BgEtI3r0uymSP/nl2uPLsUnNJX8toRyhfpBTII=
|
||||||
|
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
|
||||||
|
rsc.io/testonly v1.0.0 h1:K/VWHdO+Jv7woUXG0GzVNx1czBXUt3Ib1deaMn+xk64=
|
||||||
|
rsc.io/testonly v1.0.0/go.mod h1:OqmGbIFOcF+XrFReLOGZ6BhMM7uMBiQwZsyNmh74SzY=
|
||||||
|
-- main.go --
|
||||||
|
package use
|
||||||
|
|
||||||
|
import _ "rsc.io/quote"
|
||||||
|
|
@ -246,6 +246,15 @@ func mustLinkExternal(ctxt *Link) (res bool, reason string) {
|
||||||
return true, "some input objects have an unrecognized file format"
|
return true, "some input objects have an unrecognized file format"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(dynimportfail) > 0 {
|
||||||
|
// This error means that we were unable to generate
|
||||||
|
// the _cgo_import.go file for some packages.
|
||||||
|
// This typically means that there are some dependencies
|
||||||
|
// that the cgo tool could not figure out.
|
||||||
|
// See issue #52863.
|
||||||
|
return true, fmt.Sprintf("some packages could not be built to support internal linking (%v)", dynimportfail)
|
||||||
|
}
|
||||||
|
|
||||||
return false, ""
|
return false, ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -344,6 +344,11 @@ var (
|
||||||
// to support internal linking mode.
|
// to support internal linking mode.
|
||||||
externalobj = false
|
externalobj = false
|
||||||
|
|
||||||
|
// dynimportfail is a list of packages for which generating
|
||||||
|
// the dynimport file, _cgo_import.go, failed. If there are
|
||||||
|
// any of these objects, we must link externally. Issue 52863.
|
||||||
|
dynimportfail []string
|
||||||
|
|
||||||
// unknownObjFormat is set to true if we see an object whose
|
// unknownObjFormat is set to true if we see an object whose
|
||||||
// format we don't recognize.
|
// format we don't recognize.
|
||||||
unknownObjFormat = false
|
unknownObjFormat = false
|
||||||
|
|
@ -1030,6 +1035,10 @@ func loadobjfile(ctxt *Link, lib *sym.Library) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if arhdr.name == "dynimportfail" {
|
||||||
|
dynimportfail = append(dynimportfail, lib.Pkg)
|
||||||
|
}
|
||||||
|
|
||||||
// Skip other special (non-object-file) sections that
|
// Skip other special (non-object-file) sections that
|
||||||
// build tools may have added. Such sections must have
|
// build tools may have added. Such sections must have
|
||||||
// short names so that the suffix is not truncated.
|
// short names so that the suffix is not truncated.
|
||||||
|
|
|
||||||
|
|
@ -185,23 +185,195 @@ func httpMain(w http.ResponseWriter, r *http.Request) {
|
||||||
|
|
||||||
var templMain = template.Must(template.New("").Parse(`
|
var templMain = template.Must(template.New("").Parse(`
|
||||||
<html>
|
<html>
|
||||||
|
<style>
|
||||||
|
/* See https://github.com/golang/pkgsite/blob/master/static/shared/typography/typography.css */
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji';
|
||||||
|
font-size: 1rem;
|
||||||
|
line-height: normal;
|
||||||
|
max-width: 9in;
|
||||||
|
margin: 1em;
|
||||||
|
}
|
||||||
|
h1 { font-size: 1.5rem; }
|
||||||
|
h2 { font-size: 1.375rem; }
|
||||||
|
h1,h2 {
|
||||||
|
font-weight: 600;
|
||||||
|
line-height: 1.25em;
|
||||||
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
p { color: grey85; font-size:85%; }
|
||||||
|
</style>
|
||||||
<body>
|
<body>
|
||||||
|
<h1>cmd/trace: the Go trace event viewer</h1>
|
||||||
|
<p>
|
||||||
|
This web server provides various visualizations of an event log gathered during
|
||||||
|
the execution of a Go program that uses the <a href='https://pkg.go.dev/runtime/trace'>runtime/trace</a> package.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Event timelines for running goroutines</h2>
|
||||||
{{if $}}
|
{{if $}}
|
||||||
|
<p>
|
||||||
|
Large traces are split into multiple sections of equal data size
|
||||||
|
(not duration) to avoid overwhelming the visualizer.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
{{range $e := $}}
|
{{range $e := $}}
|
||||||
<a href="{{$e.URL}}">View trace ({{$e.Name}})</a><br>
|
<li><a href="{{$e.URL}}">View trace ({{$e.Name}})</a></li>
|
||||||
{{end}}
|
{{end}}
|
||||||
<br>
|
</ul>
|
||||||
{{else}}
|
{{else}}
|
||||||
<a href="/trace">View trace</a><br>
|
<ul>
|
||||||
|
<li><a href="/trace">View trace</a></li>
|
||||||
|
</ul>
|
||||||
{{end}}
|
{{end}}
|
||||||
<a href="/goroutines">Goroutine analysis</a><br>
|
<p>
|
||||||
<a href="/io">Network blocking profile</a> (<a href="/io?raw=1" download="io.profile">⬇</a>)<br>
|
This view displays a timeline for each of the GOMAXPROCS logical
|
||||||
<a href="/block">Synchronization blocking profile</a> (<a href="/block?raw=1" download="block.profile">⬇</a>)<br>
|
processors, showing which goroutine (if any) was running on that
|
||||||
<a href="/syscall">Syscall blocking profile</a> (<a href="/syscall?raw=1" download="syscall.profile">⬇</a>)<br>
|
logical processor at each moment.
|
||||||
<a href="/sched">Scheduler latency profile</a> (<a href="/sche?raw=1" download="sched.profile">⬇</a>)<br>
|
|
||||||
<a href="/usertasks">User-defined tasks</a><br>
|
Each goroutine has an identifying number (e.g. G123), main function,
|
||||||
<a href="/userregions">User-defined regions</a><br>
|
and color.
|
||||||
<a href="/mmu">Minimum mutator utilization</a><br>
|
|
||||||
|
A colored bar represents an uninterrupted span of execution.
|
||||||
|
|
||||||
|
Execution of a goroutine may migrate from one logical processor to another,
|
||||||
|
causing a single colored bar to be horizontally continuous but
|
||||||
|
vertically displaced.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Clicking on a span reveals information about it, such as its
|
||||||
|
duration, its causal predecessors and successors, and the stack trace
|
||||||
|
at the final moment when it yielded the logical processor, for example
|
||||||
|
because it made a system call or tried to acquire a mutex.
|
||||||
|
|
||||||
|
Directly underneath each bar, a smaller bar or more commonly a fine
|
||||||
|
vertical line indicates an event occuring during its execution.
|
||||||
|
Some of these are related to garbage collection; most indicate that
|
||||||
|
a goroutine yielded its logical processor but then immediately resumed execution
|
||||||
|
on the same logical processor. Clicking on the event displays the stack trace
|
||||||
|
at the moment it occurred.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The causal relationships between spans of goroutine execution
|
||||||
|
can be displayed by clicking the Flow Events button at the top.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
At the top ("STATS"), there are three additional timelines that
|
||||||
|
display statistical information.
|
||||||
|
|
||||||
|
"Goroutines" is a time series of the count of existing goroutines;
|
||||||
|
clicking on it displays their breakdown by state at that moment:
|
||||||
|
running, runnable, or waiting.
|
||||||
|
|
||||||
|
"Heap" is a time series of the amount of heap memory allocated (in orange)
|
||||||
|
and (in green) the allocation limit at which the next GC cycle will begin.
|
||||||
|
|
||||||
|
"Threads" shows the number of kernel threads in existence: there is
|
||||||
|
always one kernel thread per logical processor, and additional threads
|
||||||
|
are created for calls to non-Go code such as a system call or a
|
||||||
|
function written in C.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Above the event trace for the first logical processor are
|
||||||
|
traces for various runtime-internal events.
|
||||||
|
|
||||||
|
The "GC" bar shows when the garbage collector is running, and in which stage.
|
||||||
|
Garbage collection may temporarily affect all the logical processors
|
||||||
|
and the other metrics.
|
||||||
|
|
||||||
|
The "Network", "Timers", and "Syscalls" traces indicate events in
|
||||||
|
the runtime that cause goroutines to wake up.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The visualization allows you to navigate events at scales ranging from several
|
||||||
|
seconds to a handful of nanoseconds.
|
||||||
|
|
||||||
|
Consult the documentation for the Chromium <a href='https://www.chromium.org/developers/how-tos/trace-event-profiling-tool/'>Trace Event Profiling Tool<a/>
|
||||||
|
for help navigating the view.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="/goroutines">Goroutine analysis</a></li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
This view displays information about each set of goroutines that
|
||||||
|
shares the same main function.
|
||||||
|
|
||||||
|
Clicking on a main function shows links to the four types of
|
||||||
|
blocking profile (see below) applied to that subset of goroutines.
|
||||||
|
|
||||||
|
It also shows a table of specific goroutine instances, with various
|
||||||
|
execution statistics and a link to the event timeline for each one.
|
||||||
|
|
||||||
|
The timeline displays only the selected goroutine and any others it
|
||||||
|
interacts with via block/unblock events. (The timeline is
|
||||||
|
goroutine-oriented rather than logical processor-oriented.)
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h2>Profiles</h2>
|
||||||
|
<p>
|
||||||
|
Each link below displays a global profile in zoomable graph form as
|
||||||
|
produced by <a href='https://go.dev/blog/pprof'>pprof</a>'s "web" command.
|
||||||
|
|
||||||
|
In addition there is a link to download the profile for offline
|
||||||
|
analysis with pprof.
|
||||||
|
|
||||||
|
All four profiles represent causes of delay that prevent a goroutine
|
||||||
|
from running on a logical processor: because it was waiting for the network,
|
||||||
|
for a synchronization operation on a mutex or channel, for a system call,
|
||||||
|
or for a logical processor to become available.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/io">Network blocking profile</a> (<a href="/io?raw=1" download="io.profile">⬇</a>)</li>
|
||||||
|
<li><a href="/block">Synchronization blocking profile</a> (<a href="/block?raw=1" download="block.profile">⬇</a>)</li>
|
||||||
|
<li><a href="/syscall">Syscall blocking profile</a> (<a href="/syscall?raw=1" download="syscall.profile">⬇</a>)</li>
|
||||||
|
<li><a href="/sched">Scheduler latency profile</a> (<a href="/sche?raw=1" download="sched.profile">⬇</a>)</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>User-defined tasks and regions</h2>
|
||||||
|
<p>
|
||||||
|
The trace API allows a target program to annotate a <a
|
||||||
|
href='https://pkg.go.dev/runtime/trace#Region'>region</a> of code
|
||||||
|
within a goroutine, such as a key function, so that its performance
|
||||||
|
can be analyzed.
|
||||||
|
|
||||||
|
<a href='https://pkg.go.dev/runtime/trace#Log'>Log events</a> may be
|
||||||
|
associated with a region to record progress and relevant values.
|
||||||
|
|
||||||
|
The API also allows annotation of higher-level
|
||||||
|
<a href='https://pkg.go.dev/runtime/trace#Task'>tasks</a>,
|
||||||
|
which may involve work across many goroutines.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
The links below display, for each region and task, a histogram of its execution times.
|
||||||
|
|
||||||
|
Each histogram bucket contains a sample trace that records the
|
||||||
|
sequence of events such as goroutine creations, log events, and
|
||||||
|
subregion start/end times.
|
||||||
|
|
||||||
|
For each task, you can click through to a logical-processor or
|
||||||
|
goroutine-oriented view showing the tasks and regions on the
|
||||||
|
timeline.
|
||||||
|
|
||||||
|
Such information may help uncover which steps in a region are
|
||||||
|
unexpectedly slow, or reveal relationships between the data values
|
||||||
|
logged in a request and its running time.
|
||||||
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/usertasks">User-defined tasks</a></li>
|
||||||
|
<li><a href="/userregions">User-defined regions</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<h2>Garbage collection metrics</h2>
|
||||||
|
<ul>
|
||||||
|
<li><a href="/mmu">Minimum mutator utilization</a></li>
|
||||||
|
</ul>
|
||||||
|
<p>
|
||||||
|
This chart indicates the maximum GC pause time (the largest x value
|
||||||
|
for which y is zero), and more generally, the fraction of time that
|
||||||
|
the processors are available to application goroutines ("mutators"),
|
||||||
|
for any time window of a specified size, in the worst case.
|
||||||
|
</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
`))
|
`))
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,7 @@ TEXT ·SyscallNoError(SB),NOSPLIT,$0-48
|
||||||
MOVV trap+0(FP), R11 // syscall entry
|
MOVV trap+0(FP), R11 // syscall entry
|
||||||
SYSCALL
|
SYSCALL
|
||||||
MOVV R4, r1+32(FP)
|
MOVV R4, r1+32(FP)
|
||||||
MOVV R5, r2+40(FP)
|
MOVV R0, r2+40(FP) // r2 is not used. Always set to 0
|
||||||
JAL runtime·exitsyscall(SB)
|
JAL runtime·exitsyscall(SB)
|
||||||
RET
|
RET
|
||||||
|
|
||||||
|
|
@ -50,5 +50,5 @@ TEXT ·RawSyscallNoError(SB),NOSPLIT,$0-48
|
||||||
MOVV trap+0(FP), R11 // syscall entry
|
MOVV trap+0(FP), R11 // syscall entry
|
||||||
SYSCALL
|
SYSCALL
|
||||||
MOVV R4, r1+32(FP)
|
MOVV R4, r1+32(FP)
|
||||||
MOVV R5, r2+40(FP)
|
MOVV R0, r2+40(FP) // r2 is not used. Always set to 0
|
||||||
RET
|
RET
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"unsafe"
|
"unsafe"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -45,13 +44,7 @@ func NewIfreq(name string) (*Ifreq, error) {
|
||||||
|
|
||||||
// Name returns the interface name associated with the Ifreq.
|
// Name returns the interface name associated with the Ifreq.
|
||||||
func (ifr *Ifreq) Name() string {
|
func (ifr *Ifreq) Name() string {
|
||||||
// BytePtrToString requires a NULL terminator or the program may crash. If
|
return ByteSliceToString(ifr.raw.Ifrn[:])
|
||||||
// one is not present, just return the empty string.
|
|
||||||
if !bytes.Contains(ifr.raw.Ifrn[:], []byte{0x00}) {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
return BytePtrToString(&ifr.raw.Ifrn[0])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// According to netdevice(7), only AF_INET addresses are returned for numerous
|
// According to netdevice(7), only AF_INET addresses are returned for numerous
|
||||||
|
|
|
||||||
|
|
@ -618,6 +618,7 @@ func Sendfile(outfd int, infd int, offset *int64, count int) (written int, err e
|
||||||
//sys Getpriority(which int, who int) (n int, err error)
|
//sys Getpriority(which int, who int) (n int, err error)
|
||||||
//sysnb Getrlimit(which int, lim *Rlimit) (err error)
|
//sysnb Getrlimit(which int, lim *Rlimit) (err error)
|
||||||
//sysnb Getrusage(who int, rusage *Rusage) (err error)
|
//sysnb Getrusage(who int, rusage *Rusage) (err error)
|
||||||
|
//sysnb Getsid(pid int) (sid int, err error)
|
||||||
//sysnb Gettimeofday(tv *Timeval) (err error)
|
//sysnb Gettimeofday(tv *Timeval) (err error)
|
||||||
//sysnb Getuid() (uid int)
|
//sysnb Getuid() (uid int)
|
||||||
//sys Kill(pid int, signum syscall.Signal) (err error)
|
//sys Kill(pid int, signum syscall.Signal) (err error)
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build 386,linux
|
// +build 386,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build amd64,linux
|
// +build amd64,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build arm,linux
|
// +build arm,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build arm64,linux
|
// +build arm64,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build loong64,linux
|
// +build loong64,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build mips,linux
|
// +build mips,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build mips64,linux
|
// +build mips64,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build mips64le,linux
|
// +build mips64le,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build mipsle,linux
|
// +build mipsle,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build ppc,linux
|
// +build ppc,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build ppc64,linux
|
// +build ppc64,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build ppc64le,linux
|
// +build ppc64le,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build riscv64,linux
|
// +build riscv64,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build s390x,linux
|
// +build s390x,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
// +build sparc64,linux
|
// +build sparc64,linux
|
||||||
|
|
||||||
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
// Code generated by cmd/cgo -godefs; DO NOT EDIT.
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/_const.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include _const.go
|
||||||
|
|
||||||
package unix
|
package unix
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -66,6 +66,7 @@ import (
|
||||||
//go:cgo_import_dynamic libc_getpriority getpriority "libc.so"
|
//go:cgo_import_dynamic libc_getpriority getpriority "libc.so"
|
||||||
//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so"
|
//go:cgo_import_dynamic libc_getrlimit getrlimit "libc.so"
|
||||||
//go:cgo_import_dynamic libc_getrusage getrusage "libc.so"
|
//go:cgo_import_dynamic libc_getrusage getrusage "libc.so"
|
||||||
|
//go:cgo_import_dynamic libc_getsid getsid "libc.so"
|
||||||
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so"
|
//go:cgo_import_dynamic libc_gettimeofday gettimeofday "libc.so"
|
||||||
//go:cgo_import_dynamic libc_getuid getuid "libc.so"
|
//go:cgo_import_dynamic libc_getuid getuid "libc.so"
|
||||||
//go:cgo_import_dynamic libc_kill kill "libc.so"
|
//go:cgo_import_dynamic libc_kill kill "libc.so"
|
||||||
|
|
@ -202,6 +203,7 @@ import (
|
||||||
//go:linkname procGetpriority libc_getpriority
|
//go:linkname procGetpriority libc_getpriority
|
||||||
//go:linkname procGetrlimit libc_getrlimit
|
//go:linkname procGetrlimit libc_getrlimit
|
||||||
//go:linkname procGetrusage libc_getrusage
|
//go:linkname procGetrusage libc_getrusage
|
||||||
|
//go:linkname procGetsid libc_getsid
|
||||||
//go:linkname procGettimeofday libc_gettimeofday
|
//go:linkname procGettimeofday libc_gettimeofday
|
||||||
//go:linkname procGetuid libc_getuid
|
//go:linkname procGetuid libc_getuid
|
||||||
//go:linkname procKill libc_kill
|
//go:linkname procKill libc_kill
|
||||||
|
|
@ -339,6 +341,7 @@ var (
|
||||||
procGetpriority,
|
procGetpriority,
|
||||||
procGetrlimit,
|
procGetrlimit,
|
||||||
procGetrusage,
|
procGetrusage,
|
||||||
|
procGetsid,
|
||||||
procGettimeofday,
|
procGettimeofday,
|
||||||
procGetuid,
|
procGetuid,
|
||||||
procKill,
|
procKill,
|
||||||
|
|
@ -1044,6 +1047,17 @@ func Getrusage(who int, rusage *Rusage) (err error) {
|
||||||
|
|
||||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
|
func Getsid(pid int) (sid int, err error) {
|
||||||
|
r0, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGetsid)), 1, uintptr(pid), 0, 0, 0, 0, 0)
|
||||||
|
sid = int(r0)
|
||||||
|
if e1 != 0 {
|
||||||
|
err = e1
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||||
|
|
||||||
func Gettimeofday(tv *Timeval) (err error) {
|
func Gettimeofday(tv *Timeval) (err error) {
|
||||||
_, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGettimeofday)), 1, uintptr(unsafe.Pointer(tv)), 0, 0, 0, 0, 0)
|
_, _, e1 := rawSysvicall6(uintptr(unsafe.Pointer(&procGettimeofday)), 1, uintptr(unsafe.Pointer(tv)), 0, 0, 0, 0, 0)
|
||||||
if e1 != 0 {
|
if e1 != 0 {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m32 linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build 386 && linux
|
//go:build 386 && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -m64 linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build amd64 && linux
|
//go:build amd64 && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build arm && linux
|
//go:build arm && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build arm64 && linux
|
//go:build arm64 && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build loong64 && linux
|
//go:build loong64 && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build mips && linux
|
//go:build mips && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build mips64 && linux
|
//go:build mips64 && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build mips64le && linux
|
//go:build mips64le && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build mipsle && linux
|
//go:build mipsle && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build ppc && linux
|
//go:build ppc && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build ppc64 && linux
|
//go:build ppc64 && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build ppc64le && linux
|
//go:build ppc64le && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build riscv64 && linux
|
//go:build riscv64 && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include -fsigned-char linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build s390x && linux
|
//go:build s390x && linux
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
// cgo -godefs -- -Wall -Werror -static -I/tmp/include /build/unix/linux/types.go | go run mkpost.go
|
// cgo -godefs -- -Wall -Werror -static -I/tmp/include linux/types.go | go run mkpost.go
|
||||||
// Code generated by the command above; see README.md. DO NOT EDIT.
|
// Code generated by the command above; see README.md. DO NOT EDIT.
|
||||||
|
|
||||||
//go:build sparc64 && linux
|
//go:build sparc64 && linux
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,10 @@ type Statfs_t struct {
|
||||||
F_namemax uint32
|
F_namemax uint32
|
||||||
F_owner uint32
|
F_owner uint32
|
||||||
F_ctime uint64
|
F_ctime uint64
|
||||||
F_fstypename [16]int8
|
F_fstypename [16]byte
|
||||||
F_mntonname [90]int8
|
F_mntonname [90]byte
|
||||||
F_mntfromname [90]int8
|
F_mntfromname [90]byte
|
||||||
F_mntfromspec [90]int8
|
F_mntfromspec [90]byte
|
||||||
Pad_cgo_0 [2]byte
|
Pad_cgo_0 [2]byte
|
||||||
Mount_info [160]byte
|
Mount_info [160]byte
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -96,10 +96,10 @@ type Statfs_t struct {
|
||||||
F_namemax uint32
|
F_namemax uint32
|
||||||
F_owner uint32
|
F_owner uint32
|
||||||
F_ctime uint64
|
F_ctime uint64
|
||||||
F_fstypename [16]int8
|
F_fstypename [16]byte
|
||||||
F_mntonname [90]int8
|
F_mntonname [90]byte
|
||||||
F_mntfromname [90]int8
|
F_mntfromname [90]byte
|
||||||
F_mntfromspec [90]int8
|
F_mntfromspec [90]byte
|
||||||
_ [2]byte
|
_ [2]byte
|
||||||
Mount_info [160]byte
|
Mount_info [160]byte
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -98,10 +98,10 @@ type Statfs_t struct {
|
||||||
F_namemax uint32
|
F_namemax uint32
|
||||||
F_owner uint32
|
F_owner uint32
|
||||||
F_ctime uint64
|
F_ctime uint64
|
||||||
F_fstypename [16]int8
|
F_fstypename [16]byte
|
||||||
F_mntonname [90]int8
|
F_mntonname [90]byte
|
||||||
F_mntfromname [90]int8
|
F_mntfromname [90]byte
|
||||||
F_mntfromspec [90]int8
|
F_mntfromspec [90]byte
|
||||||
_ [2]byte
|
_ [2]byte
|
||||||
Mount_info [160]byte
|
Mount_info [160]byte
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,10 @@ type Statfs_t struct {
|
||||||
F_namemax uint32
|
F_namemax uint32
|
||||||
F_owner uint32
|
F_owner uint32
|
||||||
F_ctime uint64
|
F_ctime uint64
|
||||||
F_fstypename [16]int8
|
F_fstypename [16]byte
|
||||||
F_mntonname [90]int8
|
F_mntonname [90]byte
|
||||||
F_mntfromname [90]int8
|
F_mntfromname [90]byte
|
||||||
F_mntfromspec [90]int8
|
F_mntfromspec [90]byte
|
||||||
_ [2]byte
|
_ [2]byte
|
||||||
Mount_info [160]byte
|
Mount_info [160]byte
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -94,10 +94,10 @@ type Statfs_t struct {
|
||||||
F_namemax uint32
|
F_namemax uint32
|
||||||
F_owner uint32
|
F_owner uint32
|
||||||
F_ctime uint64
|
F_ctime uint64
|
||||||
F_fstypename [16]int8
|
F_fstypename [16]byte
|
||||||
F_mntonname [90]int8
|
F_mntonname [90]byte
|
||||||
F_mntfromname [90]int8
|
F_mntfromname [90]byte
|
||||||
F_mntfromspec [90]int8
|
F_mntfromspec [90]byte
|
||||||
_ [2]byte
|
_ [2]byte
|
||||||
Mount_info [160]byte
|
Mount_info [160]byte
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ golang.org/x/mod/zip
|
||||||
# golang.org/x/sync v0.0.0-20220513210516-0976fa681c29
|
# golang.org/x/sync v0.0.0-20220513210516-0976fa681c29
|
||||||
## explicit
|
## explicit
|
||||||
golang.org/x/sync/semaphore
|
golang.org/x/sync/semaphore
|
||||||
# golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a
|
# golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098
|
||||||
## explicit; go 1.17
|
## explicit; go 1.17
|
||||||
golang.org/x/sys/internal/unsafeheader
|
golang.org/x/sys/internal/unsafeheader
|
||||||
golang.org/x/sys/plan9
|
golang.org/x/sys/plan9
|
||||||
|
|
|
||||||
|
|
@ -160,6 +160,10 @@ func Example_compressingReader() {
|
||||||
// httpWriter is the body of the HTTP request, as an io.Writer.
|
// httpWriter is the body of the HTTP request, as an io.Writer.
|
||||||
bodyReader, httpWriter := io.Pipe()
|
bodyReader, httpWriter := io.Pipe()
|
||||||
|
|
||||||
|
// Make sure that bodyReader is always closed, so that the
|
||||||
|
// goroutine below will always exit.
|
||||||
|
defer bodyReader.Close()
|
||||||
|
|
||||||
// gzipWriter compresses data to httpWriter.
|
// gzipWriter compresses data to httpWriter.
|
||||||
gzipWriter := gzip.NewWriter(httpWriter)
|
gzipWriter := gzip.NewWriter(httpWriter)
|
||||||
|
|
||||||
|
|
@ -197,7 +201,6 @@ func Example_compressingReader() {
|
||||||
|
|
||||||
// Note that passing req to http.Client.Do promises that it
|
// Note that passing req to http.Client.Do promises that it
|
||||||
// will close the body, in this case bodyReader.
|
// will close the body, in this case bodyReader.
|
||||||
// That ensures that the goroutine will exit.
|
|
||||||
resp, err := ts.Client().Do(req)
|
resp, err := ts.Client().Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
|
||||||
|
|
@ -215,7 +215,11 @@ func (r *LineReader) readHeader(compDir string) error {
|
||||||
} else {
|
} else {
|
||||||
headerLength = Offset(buf.uint32())
|
headerLength = Offset(buf.uint32())
|
||||||
}
|
}
|
||||||
r.programOffset = buf.off + headerLength
|
programOffset := buf.off + headerLength
|
||||||
|
if programOffset > r.endOffset {
|
||||||
|
return DecodeError{"line", hdrOffset, fmt.Sprintf("malformed line table: program offset %d exceeds end offset %d", programOffset, r.endOffset)}
|
||||||
|
}
|
||||||
|
r.programOffset = programOffset
|
||||||
r.minInstructionLength = int(buf.uint8())
|
r.minInstructionLength = int(buf.uint8())
|
||||||
if r.version >= 4 {
|
if r.version >= 4 {
|
||||||
// [DWARF4 6.2.4]
|
// [DWARF4 6.2.4]
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@
|
||||||
// It can only be used with variables at package scope, not with local variables.
|
// It can only be used with variables at package scope, not with local variables.
|
||||||
//
|
//
|
||||||
// Patterns must not match files outside the package's module, such as ‘.git/*’ or symbolic links.
|
// Patterns must not match files outside the package's module, such as ‘.git/*’ or symbolic links.
|
||||||
|
// Patterns must not match files whose names include the special punctuation characters " * < > ? ` ' | / \ and :.
|
||||||
// Matches for empty directories are ignored. After that, each pattern in a //go:embed line
|
// Matches for empty directories are ignored. After that, each pattern in a //go:embed line
|
||||||
// must match at least one file or non-empty directory.
|
// must match at least one file or non-empty directory.
|
||||||
//
|
//
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,10 @@ func (d *Decoder) DecodeElement(v any, start *StartElement) error {
|
||||||
if val.Kind() != reflect.Pointer {
|
if val.Kind() != reflect.Pointer {
|
||||||
return errors.New("non-pointer passed to Unmarshal")
|
return errors.New("non-pointer passed to Unmarshal")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if val.IsNil() {
|
||||||
|
return errors.New("nil pointer passed to Unmarshal")
|
||||||
|
}
|
||||||
return d.unmarshal(val.Elem(), start)
|
return d.unmarshal(val.Elem(), start)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1079,3 +1079,18 @@ func TestUnmarshalWhitespaceAttrs(t *testing.T) {
|
||||||
t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want)
|
t.Fatalf("whitespace attrs: Unmarshal:\nhave: %#+v\nwant: %#+v", v, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// golang.org/issues/53350
|
||||||
|
func TestUnmarshalIntoNil(t *testing.T) {
|
||||||
|
type T struct {
|
||||||
|
A int `xml:"A"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var nilPointer *T
|
||||||
|
err := Unmarshal([]byte("<T><A>1</A></T>"), nilPointer)
|
||||||
|
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("no error in unmarshalling")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,6 @@ require (
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a // indirect
|
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 // indirect
|
||||||
golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361 // indirect
|
golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8 h1:y+mHpWoQJNAHt26Nhh6JP7
|
||||||
golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20220516162934-403b01795ae8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/net v0.0.0-20220517181318-183a9ca12b87 h1:cCR+9mKLOGyX4Zx+uBZDXEDAQsvKQ/XbW4vreG5v1jU=
|
golang.org/x/net v0.0.0-20220517181318-183a9ca12b87 h1:cCR+9mKLOGyX4Zx+uBZDXEDAQsvKQ/XbW4vreG5v1jU=
|
||||||
golang.org/x/net v0.0.0-20220517181318-183a9ca12b87/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
golang.org/x/net v0.0.0-20220517181318-183a9ca12b87/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||||
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a h1:N2T1jUrTQE9Re6TFF5PhvEHXHCguynGhKjWVsIUt5cY=
|
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098 h1:PgOr27OhUx2IRqGJ2RxAWI4dJQ7bi9cSrB82uzFzfUA=
|
||||||
golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220614162138-6c1b26c55098/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361 h1:h+pU/hCb7sEApigI6eII3/Emx5ZHaFWS+nulUp0Az/k=
|
golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361 h1:h+pU/hCb7sEApigI6eII3/Emx5ZHaFWS+nulUp0Az/k=
|
||||||
golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361/go.mod h1:5O0TPrbzDRCcAYs9rc2W4CFPmVHJfNFe8tESfECPJPE=
|
golang.org/x/text v0.3.8-0.20220509174342-b4bca84b0361/go.mod h1:5O0TPrbzDRCcAYs9rc2W4CFPmVHJfNFe8tESfECPJPE=
|
||||||
|
|
|
||||||
|
|
@ -543,10 +543,7 @@ var depsRules = `
|
||||||
internal/fuzz, internal/testlog, runtime/pprof, regexp
|
internal/fuzz, internal/testlog, runtime/pprof, regexp
|
||||||
< testing/internal/testdeps;
|
< testing/internal/testdeps;
|
||||||
|
|
||||||
MATH, errors, testing
|
OS, flag, testing, internal/cfg
|
||||||
< internal/testmath;
|
|
||||||
|
|
||||||
OS, flag, testing, internal/cfg, internal/testmath
|
|
||||||
< internal/testenv;
|
< internal/testenv;
|
||||||
|
|
||||||
OS, encoding/base64
|
OS, encoding/base64
|
||||||
|
|
|
||||||
|
|
@ -177,6 +177,8 @@ func TestImportTypeparamTests(t *testing.T) {
|
||||||
"equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this.
|
"equal.go": "inconsistent embedded sorting", // TODO(rfindley): investigate this.
|
||||||
"nested.go": "fails to compile", // TODO(rfindley): investigate this.
|
"nested.go": "fails to compile", // TODO(rfindley): investigate this.
|
||||||
"issue50417.go": "inconsistent interface member sorting",
|
"issue50417.go": "inconsistent interface member sorting",
|
||||||
|
"issue53419.go": "fails to compile",
|
||||||
|
"issue53477.go": "fails to compile",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, entry := range list {
|
for _, entry := range list {
|
||||||
|
|
|
||||||
|
|
@ -92,7 +92,6 @@ func (p Pos) IsValid() bool {
|
||||||
// A File is a handle for a file belonging to a FileSet.
|
// A File is a handle for a file belonging to a FileSet.
|
||||||
// A File has a name, size, and line offset table.
|
// A File has a name, size, and line offset table.
|
||||||
type File struct {
|
type File struct {
|
||||||
set *FileSet
|
|
||||||
name string // file name as provided to AddFile
|
name string // file name as provided to AddFile
|
||||||
base int // Pos value range for this file is [base...base+size]
|
base int // Pos value range for this file is [base...base+size]
|
||||||
size int // file size as provided to AddFile
|
size int // file size as provided to AddFile
|
||||||
|
|
@ -418,7 +417,7 @@ func (s *FileSet) AddFile(filename string, base, size int) *File {
|
||||||
panic(fmt.Sprintf("invalid size %d (should be >= 0)", size))
|
panic(fmt.Sprintf("invalid size %d (should be >= 0)", size))
|
||||||
}
|
}
|
||||||
// base >= s.base && size >= 0
|
// base >= s.base && size >= 0
|
||||||
f := &File{set: s, name: filename, base: base, size: size, lines: []int{0}}
|
f := &File{name: filename, base: base, size: size, lines: []int{0}}
|
||||||
base += size + 1 // +1 because EOF also has a position
|
base += size + 1 // +1 because EOF also has a position
|
||||||
if base < 0 {
|
if base < 0 {
|
||||||
panic("token.Pos offset overflow (> 2G of source code in file set)")
|
panic("token.Pos offset overflow (> 2G of source code in file set)")
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,6 @@ func (s *FileSet) Read(decode func(any) error) error {
|
||||||
for i := 0; i < len(ss.Files); i++ {
|
for i := 0; i < len(ss.Files); i++ {
|
||||||
f := &ss.Files[i]
|
f := &ss.Files[i]
|
||||||
files[i] = &File{
|
files[i] = &File{
|
||||||
set: s,
|
|
||||||
name: f.Name,
|
name: f.Name,
|
||||||
base: f.Base,
|
base: f.Base,
|
||||||
size: f.Size,
|
size: f.Size,
|
||||||
|
|
|
||||||
|
|
@ -35,12 +35,6 @@ func equal(p, q *FileSet) error {
|
||||||
|
|
||||||
for i, f := range p.files {
|
for i, f := range p.files {
|
||||||
g := q.files[i]
|
g := q.files[i]
|
||||||
if f.set != p {
|
|
||||||
return fmt.Errorf("wrong fileset for %q", f.name)
|
|
||||||
}
|
|
||||||
if g.set != q {
|
|
||||||
return fmt.Errorf("wrong fileset for %q", g.name)
|
|
||||||
}
|
|
||||||
if f.name != g.name {
|
if f.name != g.name {
|
||||||
return fmt.Errorf("different filenames: %q != %q", f.name, g.name)
|
return fmt.Errorf("different filenames: %q != %q", f.name, g.name)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
package types
|
package types
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"go/ast"
|
"go/ast"
|
||||||
"go/constant"
|
"go/constant"
|
||||||
|
|
@ -302,30 +303,43 @@ loop:
|
||||||
// cycleError reports a declaration cycle starting with
|
// cycleError reports a declaration cycle starting with
|
||||||
// the object in cycle that is "first" in the source.
|
// the object in cycle that is "first" in the source.
|
||||||
func (check *Checker) cycleError(cycle []Object) {
|
func (check *Checker) cycleError(cycle []Object) {
|
||||||
|
// name returns the (possibly qualified) object name.
|
||||||
|
// This is needed because with generic types, cycles
|
||||||
|
// may refer to imported types. See issue #50788.
|
||||||
|
// TODO(gri) Thus functionality is used elsewhere. Factor it out.
|
||||||
|
name := func(obj Object) string {
|
||||||
|
var buf bytes.Buffer
|
||||||
|
writePackage(&buf, obj.Pkg(), check.qualifier)
|
||||||
|
buf.WriteString(obj.Name())
|
||||||
|
return buf.String()
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(gri) Should we start with the last (rather than the first) object in the cycle
|
// TODO(gri) Should we start with the last (rather than the first) object in the cycle
|
||||||
// since that is the earliest point in the source where we start seeing the
|
// since that is the earliest point in the source where we start seeing the
|
||||||
// cycle? That would be more consistent with other error messages.
|
// cycle? That would be more consistent with other error messages.
|
||||||
i := firstInSrc(cycle)
|
i := firstInSrc(cycle)
|
||||||
obj := cycle[i]
|
obj := cycle[i]
|
||||||
|
objName := name(obj)
|
||||||
// If obj is a type alias, mark it as valid (not broken) in order to avoid follow-on errors.
|
// If obj is a type alias, mark it as valid (not broken) in order to avoid follow-on errors.
|
||||||
tname, _ := obj.(*TypeName)
|
tname, _ := obj.(*TypeName)
|
||||||
if tname != nil && tname.IsAlias() {
|
if tname != nil && tname.IsAlias() {
|
||||||
check.validAlias(tname, Typ[Invalid])
|
check.validAlias(tname, Typ[Invalid])
|
||||||
}
|
}
|
||||||
if tname != nil && compilerErrorMessages {
|
if tname != nil && compilerErrorMessages {
|
||||||
check.errorf(obj, _InvalidDeclCycle, "invalid recursive type %s", obj.Name())
|
check.errorf(obj, _InvalidDeclCycle, "invalid recursive type %s", objName)
|
||||||
} else {
|
} else {
|
||||||
check.errorf(obj, _InvalidDeclCycle, "illegal cycle in declaration of %s", obj.Name())
|
check.errorf(obj, _InvalidDeclCycle, "illegal cycle in declaration of %s", objName)
|
||||||
}
|
}
|
||||||
for range cycle {
|
for range cycle {
|
||||||
check.errorf(obj, _InvalidDeclCycle, "\t%s refers to", obj.Name()) // secondary error, \t indented
|
check.errorf(obj, _InvalidDeclCycle, "\t%s refers to", objName) // secondary error, \t indented
|
||||||
i++
|
i++
|
||||||
if i >= len(cycle) {
|
if i >= len(cycle) {
|
||||||
i = 0
|
i = 0
|
||||||
}
|
}
|
||||||
obj = cycle[i]
|
obj = cycle[i]
|
||||||
|
objName = name(obj)
|
||||||
}
|
}
|
||||||
check.errorf(obj, _InvalidDeclCycle, "\t%s", obj.Name())
|
check.errorf(obj, _InvalidDeclCycle, "\t%s", objName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// firstInSrc reports the index of the object with the "smallest"
|
// firstInSrc reports the index of the object with the "smallest"
|
||||||
|
|
|
||||||
|
|
@ -128,11 +128,8 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
|
||||||
// named and unnamed types are passed to parameters with identical type, different types
|
// named and unnamed types are passed to parameters with identical type, different types
|
||||||
// (named vs underlying) may be inferred depending on the order of the arguments.
|
// (named vs underlying) may be inferred depending on the order of the arguments.
|
||||||
// By ensuring that named types are seen first, order dependence is avoided and unification
|
// By ensuring that named types are seen first, order dependence is avoided and unification
|
||||||
// succeeds where it can.
|
// succeeds where it can (issue #43056).
|
||||||
//
|
const enableArgSorting = true
|
||||||
// This code is disabled for now pending decision whether we want to address cases like
|
|
||||||
// these and make the spec on type inference more complicated (see issue #43056).
|
|
||||||
const enableArgSorting = false
|
|
||||||
if m := len(args); m >= 2 && enableArgSorting {
|
if m := len(args); m >= 2 && enableArgSorting {
|
||||||
// Determine indices of arguments with named and unnamed types.
|
// Determine indices of arguments with named and unnamed types.
|
||||||
var named, unnamed []int
|
var named, unnamed []int
|
||||||
|
|
|
||||||
|
|
@ -149,7 +149,17 @@ func comparable(T Type, dynamic bool, seen map[Type]bool, reportf func(string, .
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
case *Interface:
|
case *Interface:
|
||||||
return dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen)
|
if dynamic && !isTypeParam(T) || t.typeSet().IsComparable(seen) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
if reportf != nil {
|
||||||
|
if t.typeSet().IsEmpty() {
|
||||||
|
reportf("empty type set")
|
||||||
|
} else {
|
||||||
|
reportf("incomparable types in type set")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fallthrough
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,7 +182,7 @@ func _() {
|
||||||
type myString string
|
type myString string
|
||||||
var s1 string
|
var s1 string
|
||||||
g3(nil, "1", myString("2"), "3")
|
g3(nil, "1", myString("2"), "3")
|
||||||
g3(&s1, "1", myString /* ERROR does not match */ ("2"), "3")
|
g3(& /* ERROR does not match */ s1, "1", myString("2"), "3")
|
||||||
|
|
||||||
type myStruct struct{x int}
|
type myStruct struct{x int}
|
||||||
var s2 myStruct
|
var s2 myStruct
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue