[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-24 5a1c5b8ae7 cmd/go: add per-package indexing for modules outside mod cache
+ 2022-06-24 b9c4d94fdb cmd/go/internal/list: update help info with Deprecated field
+ 2022-06-24 73475ef035 go/types, types2: print qualified object names in cycle errors
+ 2022-06-24 3e58ef6cc7 go/types, types2: better errors for == when type sets are empty
+ 2022-06-24 d38f1d13fa doc/go1.19: Linux race detector now requires glibc 2.17
+ 2022-06-23 de5329f1de debug/dwarf: handle malformed line table with bad program offset
+ 2022-06-23 15605ca827 embed: document additional file name restrictions
+ 2022-06-22 2e773a3894 test: add test that causes gofrontend crash
+ 2022-06-22 ff17b7d0d4 cmd/compile: don't use dictionary convert to shaped empty interface
+ 2022-06-22 2a3b467d5f cmd/go: make module .zip files group/world readable
+ 2022-06-22 bdab4cf47a cmd/go, cmd/link: support failure to create _cgo_import.go
+ 2022-06-22 aca37d16a5 cmd/go: avoid indexing modules in GOROOT
+ 2022-06-22 111cdb5848 all: update to current golang.org/x/sys revision
+ 2022-06-22 4045b1bc3f cmd/compile: fix assert condition in generic method call
+ 2022-06-22 6bad7e8243 compress/gzip: always close bodyReader in Example_compressingReader
+ 2022-06-22 606c6c371a encoding/xml: check nil pointer in DecodeElement
+ 2022-06-22 f571518139 cmd/cgo: dont override declared struct type
+ 2022-06-22 92c9b81447 net: don't set netGo = true on Windows with no cgo
+ 2022-06-22 be0b2a393a cmd/trace: add basic documentation to main page
+ 2022-06-22 b004c739b5 go/types, types2: fix parameter order dependence in type inference
+ 2022-06-21 f2c7e78592 spec: document operations which accept []byte|string constrained types
+ 2022-06-21 ab422f2749 runtime/trace: ignore fallback stacks in test
+ 2022-06-21 66685fb7dd doc/go1.19: use correct link to sync/atomic docs
+ 2022-06-21 4b236b45d0 runtime: convert flaky semaphore linearity test into benchmark
+ 2022-06-21 530511bacc cmd/go/internal/modindex: avoid walking modules when not needed
+ 2022-06-21 c2d373d5d1 cmd/compile: allow 128-bit values to be spilled
+ 2022-06-21 19ed442807 test: add regress test for #53477
+ 2022-06-20 3fcbfb07a8 doc/go1.19: fix HTML validation issues
+ 2022-06-18 527ace0ffa cmd/compile: skip substituting closures in unsafe builtins arguments
+ 2022-06-17 ec58e3f327 test: add regress test for #53419
+ 2022-06-17 103cc661f1 cmd/go/internal/modfetch: prevent duplicate hashes in go.sum
+ 2022-06-17 d42a48828f sync: add more notes about Cond behavior
+ 2022-06-17 9e2f289754 cmd/go/internal/work: log clearer detail for subprocess errors in (*Builder).toolID
+ 2022-06-17 dd2d00f9d5 net: fix flaky *TimeoutMustNotReturn tests
+ 2022-06-17 6c25ba624f go/token: delete unused File.set field
+ 2022-06-16 9068c6844d cmd/dist: add package . to 'go test' commands
+ 2022-06-16 7bad61554e runtime: write much more direct test for semaphore waiter scalability
+ 2022-06-16 f38a580a51 cmd/go: add more tracing

Change-Id: I912c5879165e03f4d7f8ac3ee9241d50fc92a419
This commit is contained in:
Matthew Dempsky 2022-06-24 13:48:30 -07:00
commit e7100adbca
129 changed files with 1507 additions and 817 deletions

View File

@ -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>

View File

@ -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&lt;- string } // channels have different element
interface{ &lt;-chan int | chan&lt;- int } // directional channels have different directions interface{ &lt;-chan int | chan&lt;- 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>.

13
misc/cgo/test/testdata/issue52611.go vendored Normal file
View File

@ -0,0 +1,13 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// 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"
)

16
misc/cgo/test/testdata/issue52611a/a.go vendored Normal file
View File

@ -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)
}

11
misc/cgo/test/testdata/issue52611a/b.go vendored Normal file
View File

@ -0,0 +1,11 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package issue52611a
import "C"
func GetX2(foo *C.struct_Foo) int32 {
return int32(foo.X)
}

11
misc/cgo/test/testdata/issue52611b/a.go vendored Normal file
View File

@ -0,0 +1,11 @@
// Copyright 2022 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package issue52611b
import "C"
func GetX1(bar *C.struct_Bar) int32 {
return int32(bar.X)
}

16
misc/cgo/test/testdata/issue52611b/b.go vendored Normal file
View File

@ -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)
}

View File

@ -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

View File

@ -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.

View File

@ -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))

View File

@ -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()))
} }
} }

View File

@ -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() {

View File

@ -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

View File

@ -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

View File

@ -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)
} }

View File

@ -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

View File

@ -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
} }

View File

@ -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}

View File

@ -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)
} }

View File

@ -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

View File

@ -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
}

View File

@ -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

44
src/cmd/dist/test.go vendored
View File

@ -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", ".")
} }
} }
} }

View File

@ -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
) )

View File

@ -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=

View File

@ -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 {

View File

@ -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 {

View File

@ -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)

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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}

View File

@ -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

View File

@ -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)

View File

@ -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)
} }
} }

View File

@ -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.

View File

@ -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.

View File

@ -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))
}

View File

@ -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"

View File

@ -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, ""
} }

View File

@ -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.

View File

@ -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>
`)) `))

View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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
} }

View File

@ -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

View File

@ -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)

View File

@ -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]

View File

@ -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.
// //

View File

@ -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)
} }

View File

@ -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")
}
}

View File

@ -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
) )

View File

@ -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=

View File

@ -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

View File

@ -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 {

View File

@ -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)")

View File

@ -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,

View File

@ -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)
} }

View File

@ -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"

View File

@ -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

View File

@ -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
} }

View File

@ -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