[release-branch.go1.20] all: merge master (245e95d) into release-branch.go1.20
Merge List:
+ 2023-01-11 245e95dfab go/types, types2: don't look up fields or methods when expecting a type
+ 2023-01-11 18625d9bec runtime: fix incorrect comment
+ 2023-01-11 6ad27161f8 cmd/compile: better error message for when a type is in a constraint but not the type set
+ 2023-01-10 76d39ae349 cmd/link, runtime: Apple libc atfork workaround take 3
+ 2023-01-10 0a0de0fc42 runtime: revert use of __fork to work around Apple atfork bugs
+ 2023-01-10 82f09b75ca os/exec: avoid leaking an exec.Cmd in TestWaitInterrupt
+ 2023-01-09 0202ad0b3a cmd/compile: prevent IsNewObject from taking quadratic time
+ 2023-01-09 64519baf38 cmd/compile/internal/pgo: add hint to missing start_line error
+ 2023-01-09 376076f3c6 runtime: skip TestCgoPprofCallback in short mode, don't run in parallel
+ 2023-01-09 0bbd67e52f runtime/pprof: document possibility of empty stacks
+ 2023-01-09 d9f23cfe78 runtime/pprof: improve output of TestLabelSystemstack
+ 2023-01-09 8232a09e3e sync/atomic: fix the note of atomic.Store
+ 2023-01-09 841c3eb166 all: fix typos in go file comments
+ 2023-01-06 f721fa3be9 syscall: skip TestUseCgroupFD if cgroupfs not mounted
+ 2023-01-06 76ec919237 net: fix typo in hosts.go
+ 2023-01-06 660d4815ea cmd/compile: describe how Go maps to wasm implementation
+ 2023-01-05 119f679a3b crypto/tls: fix typo in cacheEntry godoc
+ 2023-01-05 d50ea217f6 cmd/cover: fix problems with "go test -covermode=atomic sync/atomic"
+ 2023-01-04 bae7d772e8 doc/go1.20: fix links to new strings functions
+ 2023-01-04 4e7c838483 crypto/internal/boring: add dev.boringcrypto README.md text
+ 2023-01-04 46e3d9d12a cmd/compile: use "satisfies" (not "implements") for constraint errors
+ 2023-01-04 79cdecc852 cmd/gofmt: fix a typo in a comment
+ 2023-01-03 9955a7e9bb README.vendor: minor updates
+ 2023-01-03 d03231d9ce doc/go1.20: fix http.ResponseController example
+ 2023-01-03 cdc73f0679 .github: suggest using private browsing in pkgsite template
Change-Id: I73be496aa4163ad1d3a6cc8114f1a612968d4b10
diff --git a/.github/ISSUE_TEMPLATE/01-pkgsite.md b/.github/ISSUE_TEMPLATE/01-pkgsite.md
index fee00f5..31f0fd1 100644
--- a/.github/ISSUE_TEMPLATE/01-pkgsite.md
+++ b/.github/ISSUE_TEMPLATE/01-pkgsite.md
@@ -34,6 +34,8 @@
<!--
If possible, provide a recipe for reproducing the error.
+
+Starting with a Private/Incognito tab/window may help rule out problematic browser extensions.
-->
diff --git a/doc/go1.20.html b/doc/go1.20.html
index aec3e25..23fa82c 100644
--- a/doc/go1.20.html
+++ b/doc/go1.20.html
@@ -458,7 +458,7 @@
<pre>
func RequestHandler(w ResponseWriter, r *Request) {
rc := http.NewResponseController(w)
- rc.SetWriteDeadline(0) // disable Server.WriteTimeout when sending a large response
+ rc.SetWriteDeadline(time.Time{}) // disable Server.WriteTimeout when sending a large response
io.Copy(w, bigData)
}
</pre>
@@ -1121,10 +1121,10 @@
<dd>
<p><!-- CL 407176, https://go.dev/issue/42537 -->
The new
- <a href="/pkg/bytes/#CutPrefix"><code>CutPrefix</code></a> and
- <a href="/pkg/bytes/#CutSuffix"><code>CutSuffix</code></a> functions
- are like <a href="/pkg/bytes/#TrimPrefix"><code>TrimPrefix</code></a>
- and <a href="/pkg/bytes/#TrimSuffix"><code>TrimSuffix</code></a>
+ <a href="/pkg/strings/#CutPrefix"><code>CutPrefix</code></a> and
+ <a href="/pkg/strings/#CutSuffix"><code>CutSuffix</code></a> functions
+ are like <a href="/pkg/strings/#TrimPrefix"><code>TrimPrefix</code></a>
+ and <a href="/pkg/strings/#TrimSuffix"><code>TrimSuffix</code></a>
but also report whether the string was trimmed.
</p>
diff --git a/src/README.vendor b/src/README.vendor
index e74fc2f..4b6bdb8 100644
--- a/src/README.vendor
+++ b/src/README.vendor
@@ -4,12 +4,8 @@
The Go command maintains copies of external packages needed by the
standard library in the src/vendor and src/cmd/vendor directories.
-In GOPATH mode, imports of vendored packages are resolved to these
-directories following normal vendor directory logic
-(see golang.org/s/go15vendor).
-
-In module mode, std and cmd are modules (defined in src/go.mod and
-src/cmd/go.mod). When a package outside std or cmd is imported
+There are two modules, std and cmd, defined in src/go.mod and
+src/cmd/go.mod. When a package outside std or cmd is imported
by a package inside std or cmd, the import path is interpreted
as if it had a "vendor/" prefix. For example, within "crypto/tls",
an import of "golang.org/x/crypto/cryptobyte" resolves to
@@ -34,14 +30,15 @@
==============================
Before updating vendor directories, ensure that module mode is enabled.
-Make sure GO111MODULE=off is not set ('on' or 'auto' should work).
+Make sure that GO111MODULE is not set in the environment, or that it is
+set to 'on' or 'auto'.
Requirements may be added, updated, and removed with 'go get'.
The vendor directory may be updated with 'go mod vendor'.
A typical sequence might be:
cd src
- go get -d golang.org/x/net@latest
+ go get golang.org/x/net@latest
go mod tidy
go mod vendor
diff --git a/src/cmd/compile/internal/pgo/irgraph.go b/src/cmd/compile/internal/pgo/irgraph.go
index 311f20e..bf11e36 100644
--- a/src/cmd/compile/internal/pgo/irgraph.go
+++ b/src/cmd/compile/internal/pgo/irgraph.go
@@ -217,7 +217,7 @@
// TODO(prattic): If Function.start_line is missing we could
// fall back to using absolute line numbers, which is better
// than nothing.
- log.Fatal("PGO profile missing Function.start_line data")
+ log.Fatal("PGO profile missing Function.start_line data (Go version of profiled application too old? Go 1.20+ automatically adds this to profiles)")
}
return true
diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go
index 3b2f781..1676a93 100644
--- a/src/cmd/compile/internal/ssa/writebarrier.go
+++ b/src/cmd/compile/internal/ssa/writebarrier.go
@@ -27,7 +27,7 @@
// needwb reports whether we need write barrier for store op v.
// v must be Store/Move/Zero.
// zeroes provides known zero information (keyed by ID of memory-type values).
-func needwb(v *Value, zeroes map[ID]ZeroRegion) bool {
+func needwb(v *Value, zeroes map[ID]ZeroRegion, select1 []*Value) bool {
t, ok := v.Aux.(*types.Type)
if !ok {
v.Fatalf("store aux is not a type: %s", v.LongString())
@@ -39,7 +39,7 @@
return false // write on stack doesn't need write barrier
}
if v.Op == OpMove && IsReadOnlyGlobalAddr(v.Args[1]) {
- if mem, ok := IsNewObject(v.Args[0]); ok && mem == v.MemoryArg() {
+ if mem, ok := IsNewObject(v.Args[0], select1); ok && mem == v.MemoryArg() {
// Copying data from readonly memory into a fresh object doesn't need a write barrier.
return false
}
@@ -99,7 +99,22 @@
var sset *sparseSet
var storeNumber []int32
- zeroes := f.computeZeroMap()
+ // Compute map from a value to the SelectN [1] value that uses it.
+ select1 := f.Cache.allocValueSlice(f.NumValues())
+ defer func() { f.Cache.freeValueSlice(select1) }()
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ if v.Op != OpSelectN {
+ continue
+ }
+ if v.AuxInt != 1 {
+ continue
+ }
+ select1[v.Args[0].ID] = v
+ }
+ }
+
+ zeroes := f.computeZeroMap(select1)
for _, b := range f.Blocks { // range loop is safe since the blocks we added contain no stores to expand
// first, identify all the stores that need to insert a write barrier.
// mark them with WB ops temporarily. record presence of WB ops.
@@ -107,7 +122,7 @@
for _, v := range b.Values {
switch v.Op {
case OpStore, OpMove, OpZero:
- if needwb(v, zeroes) {
+ if needwb(v, zeroes, select1) {
switch v.Op {
case OpStore:
v.Op = OpStoreWB
@@ -376,7 +391,8 @@
// computeZeroMap returns a map from an ID of a memory value to
// a set of locations that are known to be zeroed at that memory value.
-func (f *Func) computeZeroMap() map[ID]ZeroRegion {
+func (f *Func) computeZeroMap(select1 []*Value) map[ID]ZeroRegion {
+
ptrSize := f.Config.PtrSize
// Keep track of which parts of memory are known to be zero.
// This helps with removing write barriers for various initialization patterns.
@@ -386,7 +402,7 @@
// Find new objects.
for _, b := range f.Blocks {
for _, v := range b.Values {
- if mem, ok := IsNewObject(v); ok {
+ if mem, ok := IsNewObject(v, select1); ok {
// While compiling package runtime itself, we might see user
// calls to newobject, which will have result type
// unsafe.Pointer instead. We can't easily infer how large the
@@ -584,20 +600,14 @@
// IsNewObject reports whether v is a pointer to a freshly allocated & zeroed object,
// if so, also returns the memory state mem at which v is zero.
-func IsNewObject(v *Value) (mem *Value, ok bool) {
+func IsNewObject(v *Value, select1 []*Value) (mem *Value, ok bool) {
f := v.Block.Func
c := f.Config
if f.ABIDefault == f.ABI1 && len(c.intParamRegs) >= 1 {
if v.Op != OpSelectN || v.AuxInt != 0 {
return nil, false
}
- // Find the memory
- for _, w := range v.Block.Values {
- if w.Op == OpSelectN && w.AuxInt == 1 && w.Args[0] == v.Args[0] {
- mem = w
- break
- }
- }
+ mem = select1[v.Args[0].ID]
if mem == nil {
return nil, false
}
diff --git a/src/cmd/compile/internal/types2/call.go b/src/cmd/compile/internal/types2/call.go
index 50343bf..7d660ca 100644
--- a/src/cmd/compile/internal/types2/call.go
+++ b/src/cmd/compile/internal/types2/call.go
@@ -447,7 +447,7 @@
"_Cmacro_", // function to evaluate the expanded expression
}
-func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *Named) {
+func (check *Checker) selector(x *operand, e *syntax.SelectorExpr, def *Named, wantType bool) {
// these must be declared before the "goto Error" statements
var (
obj Object
@@ -559,6 +559,25 @@
goto Error
}
+ // Avoid crashing when checking an invalid selector in a method declaration
+ // (i.e., where def is not set):
+ //
+ // type S[T any] struct{}
+ // type V = S[any]
+ // func (fs *S[T]) M(x V.M) {}
+ //
+ // All codepaths below return a non-type expression. If we get here while
+ // expecting a type expression, it is an error.
+ //
+ // See issue #57522 for more details.
+ //
+ // TODO(rfindley): We should do better by refusing to check selectors in all cases where
+ // x.typ is incomplete.
+ if wantType {
+ check.errorf(e.Sel, NotAType, "%s is not a type", syntax.Expr(e))
+ goto Error
+ }
+
obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
if obj == nil {
// Don't report another error if the underlying type was invalid (issue #49541).
diff --git a/src/cmd/compile/internal/types2/expr.go b/src/cmd/compile/internal/types2/expr.go
index 9a0348e..a3abbb9 100644
--- a/src/cmd/compile/internal/types2/expr.go
+++ b/src/cmd/compile/internal/types2/expr.go
@@ -1587,7 +1587,7 @@
return kind
case *syntax.SelectorExpr:
- check.selector(x, e, nil)
+ check.selector(x, e, nil, false)
case *syntax.IndexExpr:
if check.indexExpr(x, e) {
diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go
index 52f60d7..8193682 100644
--- a/src/cmd/compile/internal/types2/instantiate.go
+++ b/src/cmd/compile/internal/types2/instantiate.go
@@ -188,7 +188,7 @@
// is set, T is a type constraint.
//
// If the provided cause is non-nil, it may be set to an error string
-// explaining why V does not implement T.
+// explaining why V does not implement (or satisfy, for constraints) T.
func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool {
Vu := under(V)
Tu := under(T)
@@ -199,6 +199,11 @@
return true // avoid follow-on errors (see issue #49541 for an example)
}
+ verb := "implement"
+ if constraint {
+ verb = "satisfy"
+ }
+
Ti, _ := Tu.(*Interface)
if Ti == nil {
if cause != nil {
@@ -208,7 +213,7 @@
} else {
detail = check.sprintf("%s is not an interface", T)
}
- *cause = check.sprintf("%s does not implement %s (%s)", V, T, detail)
+ *cause = check.sprintf("%s does not %s %s (%s)", V, verb, T, detail)
}
return false
}
@@ -230,7 +235,7 @@
// No type with non-empty type set satisfies the empty type set.
if Ti.typeSet().IsEmpty() {
if cause != nil {
- *cause = check.sprintf("cannot implement %s (empty type set)", T)
+ *cause = check.sprintf("cannot %s %s (empty type set)", verb, T)
}
return false
}
@@ -238,7 +243,7 @@
// V must implement T's methods, if any.
if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
if cause != nil {
- *cause = check.sprintf("%s does not implement %s %s", V, T, check.missingMethodCause(V, T, m, wrong))
+ *cause = check.sprintf("%s does not %s %s %s", V, verb, T, check.missingMethodCause(V, T, m, wrong))
}
return false
}
@@ -258,7 +263,7 @@
// TODO(gri) remove this check for Go 1.21
if check != nil && check.conf.OldComparableSemantics {
if cause != nil {
- *cause = check.sprintf("%s does not implement comparable", V)
+ *cause = check.sprintf("%s does not %s comparable", V, verb)
}
return false
}
@@ -270,12 +275,12 @@
return true
}
if cause != nil {
- *cause = check.sprintf("%s to implement comparable requires go1.20 or later", V)
+ *cause = check.sprintf("%s to %s comparable requires go1.20 or later", V, verb)
}
return false
}
if cause != nil {
- *cause = check.sprintf("%s does not implement comparable", V)
+ *cause = check.sprintf("%s does not %s comparable", V, verb)
}
return false
}
@@ -293,7 +298,7 @@
if !Vi.typeSet().subsetOf(Ti.typeSet()) {
// TODO(gri) report which type is missing
if cause != nil {
- *cause = check.sprintf("%s does not implement %s", V, T)
+ *cause = check.sprintf("%s does not %s %s", V, verb, T)
}
return false
}
@@ -319,14 +324,43 @@
return false
}) {
if cause != nil {
- if alt != nil {
- *cause = check.sprintf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T)
- } else {
- *cause = check.sprintf("%s does not implement %s (%s missing in %s)", V, T, V, Ti.typeSet().terms)
+ var detail string
+ switch {
+ case alt != nil:
+ detail = check.sprintf("possibly missing ~ for %s in %s", alt, T)
+ case mentions(Ti, V):
+ detail = check.sprintf("%s mentions %s, but %s is not in the type set of %s", T, V, V, T)
+ default:
+ detail = check.sprintf("%s missing in %s", V, Ti.typeSet().terms)
}
+ *cause = check.sprintf("%s does not %s %s (%s)", V, verb, T, detail)
}
return false
}
return checkComparability()
}
+
+// mentions reports whether type T "mentions" typ in an (embedded) element or term
+// of T (whether typ is in the type set of T or not). For better error messages.
+func mentions(T, typ Type) bool {
+ switch T := T.(type) {
+ case *Interface:
+ for _, e := range T.embeddeds {
+ if mentions(e, typ) {
+ return true
+ }
+ }
+ case *Union:
+ for _, t := range T.terms {
+ if mentions(t.typ, typ) {
+ return true
+ }
+ }
+ default:
+ if Identical(T, typ) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/cmd/compile/internal/types2/typexpr.go b/src/cmd/compile/internal/types2/typexpr.go
index 4de658b..0f3106d 100644
--- a/src/cmd/compile/internal/types2/typexpr.go
+++ b/src/cmd/compile/internal/types2/typexpr.go
@@ -256,7 +256,7 @@
case *syntax.SelectorExpr:
var x operand
- check.selector(&x, e, def)
+ check.selector(&x, e, def, true)
switch x.mode {
case typexpr:
diff --git a/src/cmd/compile/internal/wasm/ssa.go b/src/cmd/compile/internal/wasm/ssa.go
index 27ba98c..0578c20 100644
--- a/src/cmd/compile/internal/wasm/ssa.go
+++ b/src/cmd/compile/internal/wasm/ssa.go
@@ -17,6 +17,119 @@
"internal/buildcfg"
)
+/*
+
+ Wasm implementation
+ -------------------
+
+ Wasm is a strange Go port because the machine isn't
+ a register-based machine, threads are different, code paths
+ are different, etc. We outline those differences here.
+
+ See the design doc for some additional info on this topic.
+ https://docs.google.com/document/d/131vjr4DH6JFnb-blm_uRdaC0_Nv3OUwjEY5qVCxCup4/edit#heading=h.mjo1bish3xni
+
+ PCs:
+
+ Wasm doesn't have PCs in the normal sense that you can jump
+ to or call to. Instead, we simulate these PCs using our own construct.
+
+ A PC in the Wasm implementation is the combination of a function
+ ID and a block ID within that function. The function ID is an index
+ into a function table which transfers control to the start of the
+ function in question, and the block ID is a sequential integer
+ indicating where in the function we are.
+
+ Every function starts with a branch table which transfers control
+ to the place in the function indicated by the block ID. The block
+ ID is provided to the function as the sole Wasm argument.
+
+ Block IDs do not encode every possible PC. They only encode places
+ in the function where it might be suspended. Typically these places
+ are call sites.
+
+ Sometimes we encode the function ID and block ID separately. When
+ recorded together as a single integer, we use the value F<<16+B.
+
+ Threads:
+
+ Wasm doesn't (yet) have threads. We have to simulate threads by
+ keeping goroutine stacks in linear memory and unwinding
+ the Wasm stack each time we want to switch goroutines.
+
+ To support unwinding a stack, each function call returns on the Wasm
+ stack a boolean that tells the function whether it should return
+ immediately or not. When returning immediately, a return address
+ is left on the top of the Go stack indicating where the goroutine
+ should be resumed.
+
+ Stack pointer:
+
+ There is a single global stack pointer which records the stack pointer
+ used by the currently active goroutine. This is just an address in
+ linear memory where the Go runtime is maintaining the stack for that
+ goroutine.
+
+ Functions cache the global stack pointer in a local variable for
+ faster access, but any changes must be spilled to the global variable
+ before any call and restored from the global variable after any call.
+
+ Calling convention:
+
+ All Go arguments and return values are passed on the Go stack, not
+ the wasm stack. In addition, return addresses are pushed on the
+ Go stack at every call point. Return addresses are not used during
+ normal execution, they are used only when resuming goroutines.
+ (So they are not really a "return address", they are a "resume address".)
+
+ All Go functions have the Wasm type (i32)->i32. The argument
+ is the block ID and the return value is the exit immediately flag.
+
+ Callsite:
+ - write arguments to the Go stack (starting at SP+0)
+ - push return address to Go stack (8 bytes)
+ - write local SP to global SP
+ - push 0 (type i32) to Wasm stack
+ - issue Call
+ - restore local SP from global SP
+ - pop int32 from top of Wasm stack. If nonzero, exit function immediately.
+ - use results from Go stack (starting at SP+sizeof(args))
+ - note that the callee will have popped the return address
+
+ Prologue:
+ - initialize local SP from global SP
+ - jump to the location indicated by the block ID argument
+ (which appears in local variable 0)
+ - at block 0
+ - check for Go stack overflow, call morestack if needed
+ - subtract frame size from SP
+ - note that arguments now start at SP+framesize+8
+
+ Normal epilogue:
+ - pop frame from Go stack
+ - pop return address from Go stack
+ - push 0 (type i32) on the Wasm stack
+ - return
+ Exit immediately epilogue:
+ - push 1 (type i32) on the Wasm stack
+ - return
+ - note that the return address and stack frame are left on the Go stack
+
+ The main loop that executes goroutines is wasm_pc_f_loop, in
+ runtime/rt0_js_wasm.s. It grabs the saved return address from
+ the top of the Go stack (actually SP-8?), splits it up into F
+ and B parts, then calls F with its Wasm argument set to B.
+
+ Note that when resuming a goroutine, only the most recent function
+ invocation of that goroutine appears on the Wasm stack. When that
+ Wasm function returns normally, the next most recent frame will
+ then be started up by wasm_pc_f_loop.
+
+ Global 0 is SP (stack pointer)
+ Global 1 is CTXT (closure pointer)
+ Global 2 is GP (goroutine pointer)
+*/
+
func Init(arch *ssagen.ArchInfo) {
arch.LinkArch = &wasm.Linkwasm
arch.REGSP = wasm.REG_SP
diff --git a/src/cmd/cover/cover.go b/src/cmd/cover/cover.go
index f4f225e..74bb500 100644
--- a/src/cmd/cover/cover.go
+++ b/src/cmd/cover/cover.go
@@ -382,8 +382,23 @@
if n.Name.Name == "_" || n.Body == nil {
return nil
}
- // Determine proper function or method name.
fname := n.Name.Name
+ // Skip AddUint32 and StoreUint32 if we're instrumenting
+ // sync/atomic itself in atomic mode (out of an abundance of
+ // caution), since as part of the instrumentation process we
+ // add calls to AddUint32/StoreUint32, and we don't want to
+ // somehow create an infinite loop.
+ //
+ // Note that in the current implementation (Go 1.20) both
+ // routines are assembly stubs that forward calls to the
+ // runtime/internal/atomic equivalents, hence the infinite
+ // loop scenario is purely theoretical (maybe if in some
+ // future implementation one of these functions might be
+ // written in Go). See #57445 for more details.
+ if atomicOnAtomic() && (fname == "AddUint32" || fname == "StoreUint32") {
+ return nil
+ }
+ // Determine proper function or method name.
if r := n.Recv; r != nil && len(r.List) == 1 {
t := r.List[0].Type
star := ""
@@ -508,8 +523,8 @@
}
if *mode == "atomic" {
hookWrite = func(cv string, which int, val string) string {
- return fmt.Sprintf("%s.StoreUint32(&%s[%d], %s)", atomicPackageName,
- cv, which, val)
+ return fmt.Sprintf("%sStoreUint32(&%s[%d], %s)",
+ atomicPackagePrefix(), cv, which, val)
}
}
@@ -612,9 +627,13 @@
// We do this even if there is an existing import, because the
// existing import may be shadowed at any given place we want
// to refer to it, and our name (_cover_atomic_) is less likely to
- // be shadowed.
- file.edit.Insert(file.offset(file.astFile.Name.End()),
- fmt.Sprintf("; import %s %q", atomicPackageName, atomicPackagePath))
+ // be shadowed. The one exception is if we're visiting the
+ // sync/atomic package itself, in which case we can refer to
+ // functions directly without an import prefix. See also #57445.
+ if pkgconfig.PkgPath != "sync/atomic" {
+ file.edit.Insert(file.offset(file.astFile.Name.End()),
+ fmt.Sprintf("; import %s %q", atomicPackageName, atomicPackagePath))
+ }
}
if pkgconfig.PkgName == "main" {
file.edit.Insert(file.offset(file.astFile.Name.End()),
@@ -637,7 +656,7 @@
// Emit a reference to the atomic package to avoid
// import and not used error when there's no code in a file.
if *mode == "atomic" {
- fmt.Fprintf(fd, "var _ = %s.LoadUint32\n", atomicPackageName)
+ fmt.Fprintf(fd, "var _ = %sLoadUint32\n", atomicPackagePrefix())
}
// Last file? Emit meta-data and converage config.
@@ -658,7 +677,7 @@
// atomicCounterStmt returns the expression: atomic.AddUint32(&__count[23], 1)
func atomicCounterStmt(f *File, counter string) string {
- return fmt.Sprintf("%s.AddUint32(&%s, 1)", atomicPackageName, counter)
+ return fmt.Sprintf("%sAddUint32(&%s, 1)", atomicPackagePrefix(), counter)
}
// newCounter creates a new counter expression of the appropriate form.
@@ -1098,3 +1117,20 @@
log.Fatalf("error writing %s: %v", pkgconfig.OutConfig, err)
}
}
+
+// atomicOnAtomic returns true if we're instrumenting
+// the sync/atomic package AND using atomic mode.
+func atomicOnAtomic() bool {
+ return *mode == "atomic" && pkgconfig.PkgPath == "sync/atomic"
+}
+
+// atomicPackagePrefix returns the import path prefix used to refer to
+// our special import of sync/atomic; this is either set to the
+// constant atomicPackageName plus a dot or the empty string if we're
+// instrumenting the sync/atomic package itself.
+func atomicPackagePrefix() string {
+ if atomicOnAtomic() {
+ return ""
+ }
+ return atomicPackageName + "."
+}
diff --git a/src/cmd/go/internal/test/test.go b/src/cmd/go/internal/test/test.go
index 0051970..fe6e733 100644
--- a/src/cmd/go/internal/test/test.go
+++ b/src/cmd/go/internal/test/test.go
@@ -825,8 +825,11 @@
// Prepare build + run + print actions for all packages being tested.
for _, p := range pkgs {
- // sync/atomic import is inserted by the cover tool. See #18486
- if cfg.BuildCover && cfg.BuildCoverMode == "atomic" {
+ // sync/atomic import is inserted by the cover tool if we're
+ // using atomic mode (and not compiling sync/atomic package itself).
+ // See #18486 and #57445.
+ if cfg.BuildCover && cfg.BuildCoverMode == "atomic" &&
+ p.ImportPath != "sync/atomic" {
load.EnsureImport(p, "sync/atomic")
}
diff --git a/src/cmd/go/testdata/script/cover_sync_atomic_import.txt b/src/cmd/go/testdata/script/cover_sync_atomic_import.txt
index ee29bcb..b933cdb 100644
--- a/src/cmd/go/testdata/script/cover_sync_atomic_import.txt
+++ b/src/cmd/go/testdata/script/cover_sync_atomic_import.txt
@@ -3,6 +3,21 @@
go test -short -cover -covermode=atomic -coverpkg=coverdep/p1 coverdep
+# In addition to the above, test to make sure there is no funny
+# business if we try "go test -cover" in atomic mode targeting
+# sync/atomic itself (see #57445). Just a short test run is needed
+# since we're mainly interested in making sure the test builds and can
+# execute at least one test.
+
+go test -short -covermode=atomic -run=TestStoreInt64 sync/atomic
+go test -short -covermode=atomic -run=TestAnd8 runtime/internal/atomic
+
+# Skip remainder if no race detector support.
+[!race] skip
+
+go test -short -cover -race -run=TestStoreInt64 sync/atomic
+go test -short -cover -race -run=TestAnd8 runtime/internal/atomic
+
-- go.mod --
module coverdep
diff --git a/src/cmd/gofmt/rewrite.go b/src/cmd/gofmt/rewrite.go
index a98c6a0..0b7e211 100644
--- a/src/cmd/gofmt/rewrite.go
+++ b/src/cmd/gofmt/rewrite.go
@@ -199,7 +199,7 @@
// object pointers and token positions always match
return true
case callExprType:
- // For calls, the Ellipsis fields (token.Position) must
+ // For calls, the Ellipsis fields (token.Pos) must
// match since that is how f(x) and f(x...) are different.
// Check them here but fall through for the remaining fields.
p := pattern.Interface().(*ast.CallExpr)
diff --git a/src/cmd/internal/obj/arm64/asm7.go b/src/cmd/internal/obj/arm64/asm7.go
index d7a2838..db18bc8 100644
--- a/src/cmd/internal/obj/arm64/asm7.go
+++ b/src/cmd/internal/obj/arm64/asm7.go
@@ -3215,7 +3215,7 @@
return SYSARG5(0, op1, Cn, Cm, op2)
}
-// checkUnpredictable checks if the sourse and transfer registers are the same register.
+// checkUnpredictable checks if the source and transfer registers are the same register.
// ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same.
func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) {
if wback && rn != REGSP && (rn == rt1 || rn == rt2) {
diff --git a/src/cmd/link/internal/ld/macho.go b/src/cmd/link/internal/ld/macho.go
index 11cbf81..d6c28e4 100644
--- a/src/cmd/link/internal/ld/macho.go
+++ b/src/cmd/link/internal/ld/macho.go
@@ -479,8 +479,11 @@
var version uint32
switch ctxt.Arch.Family {
case sys.AMD64:
- // The version must be at least 10.9; see golang.org/issues/30488.
- version = 10<<16 | 9<<8 | 0<<0 // 10.9.0
+ // This must be fairly recent for Apple signing (go.dev/issue/30488).
+ // Having too old a version here was also implicated in some problems
+ // calling into macOS libraries (go.dev/issue/56784).
+ // In general this can be the most recent supported macOS version.
+ version = 10<<16 | 13<<8 | 0<<0 // 10.13.0
case sys.ARM64:
version = 11<<16 | 0<<8 | 0<<0 // 11.0.0
}
diff --git a/src/crypto/internal/boring/README.md b/src/crypto/internal/boring/README.md
index ffacd34..ec02786 100644
--- a/src/crypto/internal/boring/README.md
+++ b/src/crypto/internal/boring/README.md
@@ -1,3 +1,21 @@
+We have been working inside Google on a fork of Go that uses
+BoringCrypto (the core of [BoringSSL](https://boringssl.googlesource.com/boringssl/))
+for various crypto primitives, in furtherance of some work related to FIPS 140.
+We have heard that some external users of Go would be
+interested in this code as well, so we have published this code
+here in the main Go repository behind the setting GOEXPERIMENT=boringcrypto.
+
+Use of GOEXPERIMENT=boringcrypto outside Google is _unsupported_.
+This mode is not part of the [Go 1 compatibility rules](https://go.dev/doc/go1compat),
+and it may change incompatibly or break in other ways at any time.
+
+To be clear, we are not making any statements or representations about
+the suitability of this code in relation to the FIPS 140 standard.
+Interested users will have to evaluate for themselves whether the code
+is useful for their own purposes.
+
+---
+
This directory holds the core of the BoringCrypto implementation
as well as the build scripts for the module itself: syso/*.syso.
@@ -16,4 +34,6 @@
to allow the x86 kernel to run arm64 binaries via QEMU.
-See build.sh for more details.
+See build.sh for more details about the build.
+
+
diff --git a/src/crypto/tls/cache.go b/src/crypto/tls/cache.go
index 2bdf2d9..fc8f2c0 100644
--- a/src/crypto/tls/cache.go
+++ b/src/crypto/tls/cache.go
@@ -27,7 +27,7 @@
// to the certificate in the cache is decremented. Once the number of references
// reaches zero, the entry is evicted from the cache.
//
-// The main difference between this implmentation and CRYPTO_BUFFER_POOL is that
+// The main difference between this implementation and CRYPTO_BUFFER_POOL is that
// CRYPTO_BUFFER_POOL is a more generic structure which supports blobs of data,
// rather than specific structures. Since we only care about x509.Certificates,
// certCache is implemented as a specific cache, rather than a generic one.
diff --git a/src/go/types/call.go b/src/go/types/call.go
index 5558244..db603b5 100644
--- a/src/go/types/call.go
+++ b/src/go/types/call.go
@@ -450,7 +450,7 @@
"_Cmacro_", // function to evaluate the expanded expression
}
-func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *Named) {
+func (check *Checker) selector(x *operand, e *ast.SelectorExpr, def *Named, wantType bool) {
// these must be declared before the "goto Error" statements
var (
obj Object
@@ -563,6 +563,25 @@
goto Error
}
+ // Avoid crashing when checking an invalid selector in a method declaration
+ // (i.e., where def is not set):
+ //
+ // type S[T any] struct{}
+ // type V = S[any]
+ // func (fs *S[T]) M(x V.M) {}
+ //
+ // All codepaths below return a non-type expression. If we get here while
+ // expecting a type expression, it is an error.
+ //
+ // See issue #57522 for more details.
+ //
+ // TODO(rfindley): We should do better by refusing to check selectors in all cases where
+ // x.typ is incomplete.
+ if wantType {
+ check.errorf(e.Sel, NotAType, "%s is not a type", ast.Expr(e))
+ goto Error
+ }
+
obj, index, indirect = LookupFieldOrMethod(x.typ, x.mode == variable, check.pkg, sel)
if obj == nil {
// Don't report another error if the underlying type was invalid (issue #49541).
diff --git a/src/go/types/expr.go b/src/go/types/expr.go
index e09b461..aa90145 100644
--- a/src/go/types/expr.go
+++ b/src/go/types/expr.go
@@ -1568,7 +1568,7 @@
return kind
case *ast.SelectorExpr:
- check.selector(x, e, nil)
+ check.selector(x, e, nil, false)
case *ast.IndexExpr, *ast.IndexListExpr:
ix := typeparams.UnpackIndexExpr(e)
diff --git a/src/go/types/instantiate.go b/src/go/types/instantiate.go
index 59ac100..2cf48c1 100644
--- a/src/go/types/instantiate.go
+++ b/src/go/types/instantiate.go
@@ -188,7 +188,7 @@
// is set, T is a type constraint.
//
// If the provided cause is non-nil, it may be set to an error string
-// explaining why V does not implement T.
+// explaining why V does not implement (or satisfy, for constraints) T.
func (check *Checker) implements(V, T Type, constraint bool, cause *string) bool {
Vu := under(V)
Tu := under(T)
@@ -199,6 +199,11 @@
return true // avoid follow-on errors (see issue #49541 for an example)
}
+ verb := "implement"
+ if constraint {
+ verb = "satisfy"
+ }
+
Ti, _ := Tu.(*Interface)
if Ti == nil {
if cause != nil {
@@ -208,7 +213,7 @@
} else {
detail = check.sprintf("%s is not an interface", T)
}
- *cause = check.sprintf("%s does not implement %s (%s)", V, T, detail)
+ *cause = check.sprintf("%s does not %s %s (%s)", V, verb, T, detail)
}
return false
}
@@ -230,7 +235,7 @@
// No type with non-empty type set satisfies the empty type set.
if Ti.typeSet().IsEmpty() {
if cause != nil {
- *cause = check.sprintf("cannot implement %s (empty type set)", T)
+ *cause = check.sprintf("cannot %s %s (empty type set)", verb, T)
}
return false
}
@@ -238,7 +243,7 @@
// V must implement T's methods, if any.
if m, wrong := check.missingMethod(V, Ti, true); m != nil /* !Implements(V, Ti) */ {
if cause != nil {
- *cause = check.sprintf("%s does not implement %s %s", V, T, check.missingMethodCause(V, T, m, wrong))
+ *cause = check.sprintf("%s does not %s %s %s", V, verb, T, check.missingMethodCause(V, T, m, wrong))
}
return false
}
@@ -258,7 +263,7 @@
// TODO(gri) remove this check for Go 1.21
if check != nil && check.conf.oldComparableSemantics {
if cause != nil {
- *cause = check.sprintf("%s does not implement comparable", V)
+ *cause = check.sprintf("%s does not %s comparable", V, verb)
}
return false
}
@@ -270,12 +275,12 @@
return true
}
if cause != nil {
- *cause = check.sprintf("%s to implement comparable requires go1.20 or later", V)
+ *cause = check.sprintf("%s to %s comparable requires go1.20 or later", V, verb)
}
return false
}
if cause != nil {
- *cause = check.sprintf("%s does not implement comparable", V)
+ *cause = check.sprintf("%s does not %s comparable", V, verb)
}
return false
}
@@ -293,7 +298,7 @@
if !Vi.typeSet().subsetOf(Ti.typeSet()) {
// TODO(gri) report which type is missing
if cause != nil {
- *cause = check.sprintf("%s does not implement %s", V, T)
+ *cause = check.sprintf("%s does not %s %s", V, verb, T)
}
return false
}
@@ -319,14 +324,43 @@
return false
}) {
if cause != nil {
- if alt != nil {
- *cause = check.sprintf("%s does not implement %s (possibly missing ~ for %s in constraint %s)", V, T, alt, T)
- } else {
- *cause = check.sprintf("%s does not implement %s (%s missing in %s)", V, T, V, Ti.typeSet().terms)
+ var detail string
+ switch {
+ case alt != nil:
+ detail = check.sprintf("possibly missing ~ for %s in %s", alt, T)
+ case mentions(Ti, V):
+ detail = check.sprintf("%s mentions %s, but %s is not in the type set of %s", T, V, V, T)
+ default:
+ detail = check.sprintf("%s missing in %s", V, Ti.typeSet().terms)
}
+ *cause = check.sprintf("%s does not %s %s (%s)", V, verb, T, detail)
}
return false
}
return checkComparability()
}
+
+// mentions reports whether type T "mentions" typ in an (embedded) element or term
+// of T (whether typ is in the type set of T or not). For better error messages.
+func mentions(T, typ Type) bool {
+ switch T := T.(type) {
+ case *Interface:
+ for _, e := range T.embeddeds {
+ if mentions(e, typ) {
+ return true
+ }
+ }
+ case *Union:
+ for _, t := range T.terms {
+ if mentions(t.typ, typ) {
+ return true
+ }
+ }
+ default:
+ if Identical(T, typ) {
+ return true
+ }
+ }
+ return false
+}
diff --git a/src/go/types/typexpr.go b/src/go/types/typexpr.go
index 3d1f0b8..03817dd 100644
--- a/src/go/types/typexpr.go
+++ b/src/go/types/typexpr.go
@@ -256,7 +256,7 @@
case *ast.SelectorExpr:
var x operand
- check.selector(&x, e, def)
+ check.selector(&x, e, def, true)
switch x.mode {
case typexpr:
diff --git a/src/internal/types/testdata/check/cycles0.go b/src/internal/types/testdata/check/cycles0.go
index d4e7e60..7c00c7d 100644
--- a/src/internal/types/testdata/check/cycles0.go
+++ b/src/internal/types/testdata/check/cycles0.go
@@ -45,7 +45,7 @@
// pointers
P0 *P0
- PP *struct{ PP.f /* ERROR no field or method f */ }
+ PP *struct{ PP.f /* ERROR PP.f is not a type */ }
// functions
F0 func(F0)
diff --git a/src/internal/types/testdata/check/decls0.go b/src/internal/types/testdata/check/decls0.go
index 6002a9e..868b318 100644
--- a/src/internal/types/testdata/check/decls0.go
+++ b/src/internal/types/testdata/check/decls0.go
@@ -63,7 +63,7 @@
type (
- p1 pi.foo /* ERROR "no field or method foo" */
+ p1 pi.foo /* ERROR "pi.foo is not a type" */
p2 unsafe.Pointer
)
@@ -189,10 +189,10 @@
// TODO(#43215) this should be detected as a cycle error
func f5([unsafe.Sizeof(f5)]int) {}
-func (S0) m1 (x S0 /* ERROR illegal cycle in method declaration */ .m1) {}
-func (S0) m2 (x *S0 /* ERROR illegal cycle in method declaration */ .m2) {}
-func (S0) m3 () (x S0 /* ERROR illegal cycle in method declaration */ .m3) { return }
-func (S0) m4 () (x *S0 /* ERROR illegal cycle in method declaration */ .m4) { return }
+func (S0) m1 (x S0.m1 /* ERROR S0.m1 is not a type */ ) {}
+func (S0) m2 (x *S0.m2 /* ERROR S0.m2 is not a type */ ) {}
+func (S0) m3 () (x S0.m3 /* ERROR S0.m3 is not a type */ ) { return }
+func (S0) m4 () (x *S0.m4 /* ERROR S0.m4 is not a type */ ) { return }
// interfaces may not have any blank methods
type BlankI interface {
diff --git a/src/internal/types/testdata/check/issues0.go b/src/internal/types/testdata/check/issues0.go
index 0cea36c..4a66641 100644
--- a/src/internal/types/testdata/check/issues0.go
+++ b/src/internal/types/testdata/check/issues0.go
@@ -97,7 +97,7 @@
nosuchpkg /* ERROR undefined: nosuchpkg */ .Nosuchtype
}
type I interface {
- I.m /* ERROR no field or method m */
+ I.m /* ERROR I.m is not a type */
m()
}
}
diff --git a/src/internal/types/testdata/check/issues1.go b/src/internal/types/testdata/check/issues1.go
index 02ad822..2f3414d 100644
--- a/src/internal/types/testdata/check/issues1.go
+++ b/src/internal/types/testdata/check/issues1.go
@@ -22,7 +22,7 @@
eql(x, x)
eql(y, y)
eql(y, nil /* ERROR cannot use nil as Y value in argument to eql */ )
- eql[io /* ERROR does not implement comparable */ .Reader](nil, nil)
+ eql[io /* ERROR does not satisfy comparable */ .Reader](nil, nil)
}
// If we have a receiver of pointer to type parameter type (below: *T)
@@ -58,7 +58,7 @@
type T1[P interface{~uint}] struct{}
func _[P any]() {
- _ = T1[P /* ERROR P does not implement interface{~uint} */ ]{}
+ _ = T1[P /* ERROR P does not satisfy interface{~uint} */ ]{}
}
// This is the original (simplified) program causing the same issue.
@@ -74,8 +74,8 @@
return u.s + 1
}
-func NewT2[U any]() T2[U /* ERROR U does not implement Unsigned */ ] {
- return T2[U /* ERROR U does not implement Unsigned */ ]{}
+func NewT2[U any]() T2[U /* ERROR U does not satisfy Unsigned */ ] {
+ return T2[U /* ERROR U does not satisfy Unsigned */ ]{}
}
func _() {
diff --git a/src/internal/types/testdata/check/typeinst1.go b/src/internal/types/testdata/check/typeinst1.go
index e7b4539..e7bb247 100644
--- a/src/internal/types/testdata/check/typeinst1.go
+++ b/src/internal/types/testdata/check/typeinst1.go
@@ -210,7 +210,7 @@
var _ = f0[int]
var _ = f0[bool]
var _ = f0[string]
-var _ = f0[float64 /* ERROR does not implement I0 */ ]
+var _ = f0[float64 /* ERROR does not satisfy I0 */ ]
type I01 interface {
E0
@@ -219,9 +219,9 @@
func f01[T I01]() {}
var _ = f01[int]
-var _ = f01[bool /* ERROR does not implement I0 */ ]
+var _ = f01[bool /* ERROR does not satisfy I0 */ ]
var _ = f01[string]
-var _ = f01[float64 /* ERROR does not implement I0 */ ]
+var _ = f01[float64 /* ERROR does not satisfy I0 */ ]
type I012 interface {
E0
@@ -230,10 +230,10 @@
}
func f012[T I012]() {}
-var _ = f012[int /* ERROR cannot implement I012.*empty type set */ ]
-var _ = f012[bool /* ERROR cannot implement I012.*empty type set */ ]
-var _ = f012[string /* ERROR cannot implement I012.*empty type set */ ]
-var _ = f012[float64 /* ERROR cannot implement I012.*empty type set */ ]
+var _ = f012[int /* ERROR cannot satisfy I012.*empty type set */ ]
+var _ = f012[bool /* ERROR cannot satisfy I012.*empty type set */ ]
+var _ = f012[string /* ERROR cannot satisfy I012.*empty type set */ ]
+var _ = f012[float64 /* ERROR cannot satisfy I012.*empty type set */ ]
type I12 interface {
E1
@@ -241,9 +241,9 @@
}
func f12[T I12]() {}
-var _ = f12[int /* ERROR does not implement I12 */ ]
-var _ = f12[bool /* ERROR does not implement I12 */ ]
-var _ = f12[string /* ERROR does not implement I12 */ ]
+var _ = f12[int /* ERROR does not satisfy I12 */ ]
+var _ = f12[bool /* ERROR does not satisfy I12 */ ]
+var _ = f12[string /* ERROR does not satisfy I12 */ ]
var _ = f12[float64]
type I0_ interface {
@@ -253,9 +253,9 @@
func f0_[T I0_]() {}
var _ = f0_[int]
-var _ = f0_[bool /* ERROR does not implement I0_ */ ]
-var _ = f0_[string /* ERROR does not implement I0_ */ ]
-var _ = f0_[float64 /* ERROR does not implement I0_ */ ]
+var _ = f0_[bool /* ERROR does not satisfy I0_ */ ]
+var _ = f0_[string /* ERROR does not satisfy I0_ */ ]
+var _ = f0_[float64 /* ERROR does not satisfy I0_ */ ]
// Using a function instance as a type is an error.
var _ f0 // ERROR not a type
@@ -273,7 +273,7 @@
func hh[T ~int]() {}
func _[T none]() {
- _ = ff[int /* ERROR cannot implement none \(empty type set\) */ ]
+ _ = ff[int /* ERROR cannot satisfy none \(empty type set\) */ ]
_ = ff[T] // pathological but ok because T's type set is empty, too
_ = gg[int]
_ = gg[T]
diff --git a/src/internal/types/testdata/examples/inference.go b/src/internal/types/testdata/examples/inference.go
index 23a3d81..073df9c 100644
--- a/src/internal/types/testdata/examples/inference.go
+++ b/src/internal/types/testdata/examples/inference.go
@@ -97,7 +97,7 @@
// last.
related2(1.2, []float64{})
related2(1.0, []int{})
- related2 /* ERROR does not implement */ (float64(1.0), []int{}) // TODO(gri) fix error position
+ related2 /* ERROR does not satisfy */ (float64(1.0), []int{}) // TODO(gri) fix error position
}
type List[P any] []P
diff --git a/src/internal/types/testdata/fixedbugs/issue39634.go b/src/internal/types/testdata/fixedbugs/issue39634.go
index 7b458f2..6ee1548 100644
--- a/src/internal/types/testdata/fixedbugs/issue39634.go
+++ b/src/internal/types/testdata/fixedbugs/issue39634.go
@@ -19,7 +19,7 @@
// func t2[T Numeric2](s[]T){0 /* ERROR not a type */ []{s /* ERROR cannot index */ [0][0]}}
// crash 3
-type t3 *interface{ t3.p /* ERROR no field or method p */ }
+type t3 *interface{ t3.p /* ERROR t3.p is not a type */ }
// crash 4
type Numeric4 interface{t4 /* ERROR not a type */ }
diff --git a/src/internal/types/testdata/fixedbugs/issue39754.go b/src/internal/types/testdata/fixedbugs/issue39754.go
index 9edd239..97365e2 100644
--- a/src/internal/types/testdata/fixedbugs/issue39754.go
+++ b/src/internal/types/testdata/fixedbugs/issue39754.go
@@ -16,6 +16,6 @@
func _() {
f[int, Optional[int], Optional[int]]()
- _ = f[int, Optional[int], Optional /* ERROR does not implement Box */ [string]]
- _ = f[int, Optional[int], Optional /* ERROR Optional.* does not implement Box.* */ [string]]
+ _ = f[int, Optional[int], Optional /* ERROR does not satisfy Box */ [string]]
+ _ = f[int, Optional[int], Optional /* ERROR Optional.* does not satisfy Box.* */ [string]]
}
diff --git a/src/internal/types/testdata/fixedbugs/issue40350.go b/src/internal/types/testdata/fixedbugs/issue40350.go
index 7ffd551..08eb426 100644
--- a/src/internal/types/testdata/fixedbugs/issue40350.go
+++ b/src/internal/types/testdata/fixedbugs/issue40350.go
@@ -12,5 +12,5 @@
func f[T number]() {}
func _() {
- _ = f[int /* ERROR int does not implement number \(int missing in float64 | ~int32\)*/]
+ _ = f[int /* ERROR int does not satisfy number \(number mentions int, but int is not in the type set of number\)*/]
}
diff --git a/src/internal/types/testdata/fixedbugs/issue45920.go b/src/internal/types/testdata/fixedbugs/issue45920.go
index d67dfc0..0a281c5 100644
--- a/src/internal/types/testdata/fixedbugs/issue45920.go
+++ b/src/internal/types/testdata/fixedbugs/issue45920.go
@@ -8,10 +8,10 @@
func _(ch chan int) { f1(ch) }
func _(ch <-chan int) { f1(ch) }
-func _(ch chan<- int) { f1 /* ERROR chan<- int does not implement chan int \| <-chan int */ (ch) }
+func _(ch chan<- int) { f1 /* ERROR chan<- int does not satisfy chan int \| <-chan int */ (ch) }
func f2[T any, C chan T | chan<- T](ch C) {}
func _(ch chan int) { f2(ch) }
-func _(ch <-chan int) { f2 /* ERROR <-chan int does not implement chan int \| chan<- int */ (ch) }
+func _(ch <-chan int) { f2 /* ERROR <-chan int does not satisfy chan int \| chan<- int */ (ch) }
func _(ch chan<- int) { f2(ch) }
diff --git a/src/internal/types/testdata/fixedbugs/issue47411.go b/src/internal/types/testdata/fixedbugs/issue47411.go
index 1230307..33b169a 100644
--- a/src/internal/types/testdata/fixedbugs/issue47411.go
+++ b/src/internal/types/testdata/fixedbugs/issue47411.go
@@ -15,12 +15,12 @@
_ = f[int]
_ = f[P]
_ = f[Q]
- _ = f[func /* ERROR does not implement comparable */ ()]
- _ = f[R /* ERROR R does not implement comparable */ ]
+ _ = f[func /* ERROR does not satisfy comparable */ ()]
+ _ = f[R /* ERROR R does not satisfy comparable */ ]
_ = g[int]
- _ = g[P /* ERROR P does not implement interface{interface{comparable; ~int \| ~string} */ ]
+ _ = g[P /* ERROR P does not satisfy interface{interface{comparable; ~int \| ~string} */ ]
_ = g[Q]
- _ = g[func /* ERROR func\(\) does not implement interface{interface{comparable; ~int \| ~string}} */ ()]
- _ = g[R /* ERROR R does not implement interface{interface{comparable; ~int \| ~string} */ ]
+ _ = g[func /* ERROR func\(\) does not satisfy interface{interface{comparable; ~int \| ~string}} */ ()]
+ _ = g[R /* ERROR R does not satisfy interface{interface{comparable; ~int \| ~string} */ ]
}
diff --git a/src/internal/types/testdata/fixedbugs/issue49112.go b/src/internal/types/testdata/fixedbugs/issue49112.go
index 61b757c..dea2608 100644
--- a/src/internal/types/testdata/fixedbugs/issue49112.go
+++ b/src/internal/types/testdata/fixedbugs/issue49112.go
@@ -8,8 +8,8 @@
func _() {
_ = f[int]
- _ = f[[ /* ERROR \[\]int does not implement int */ ]int]
+ _ = f[[ /* ERROR \[\]int does not satisfy int */ ]int]
f(0)
- f/* ERROR \[\]int does not implement int */ ([]int{})
+ f/* ERROR \[\]int does not satisfy int */ ([]int{})
}
diff --git a/src/internal/types/testdata/fixedbugs/issue49179.go b/src/internal/types/testdata/fixedbugs/issue49179.go
index 8890e92..2ddfa33 100644
--- a/src/internal/types/testdata/fixedbugs/issue49179.go
+++ b/src/internal/types/testdata/fixedbugs/issue49179.go
@@ -13,11 +13,11 @@
func _() {
_ = f1[int]
- _ = f1[myInt /* ERROR possibly missing ~ for int in constraint int \| string */]
+ _ = f1[myInt /* ERROR possibly missing ~ for int in int \| string */]
_ = f2[myInt]
- _ = f2[myFloat /* ERROR possibly missing ~ for float64 in constraint ~int \| string \| float64 */]
+ _ = f2[myFloat /* ERROR possibly missing ~ for float64 in ~int \| string \| float64 */]
var x myInt
- f3 /* ERROR myInt does not implement int \(possibly missing ~ for int in constraint int\) */ (x)
+ f3 /* ERROR myInt does not satisfy int \(possibly missing ~ for int in int\) */ (x)
}
// test case from the issue
@@ -33,5 +33,5 @@
type MySlice []int
func f(s MySlice) {
- Map[MySlice /* ERROR MySlice does not implement SliceConstraint\[int\] \(possibly missing ~ for \[\]int in constraint SliceConstraint\[int\]\) */, int](s, nil)
+ Map[MySlice /* ERROR MySlice does not satisfy SliceConstraint\[int\] \(possibly missing ~ for \[\]int in SliceConstraint\[int\]\) */, int](s, nil)
}
diff --git a/src/internal/types/testdata/fixedbugs/issue49739.go b/src/internal/types/testdata/fixedbugs/issue49739.go
index 46b1e71..7feb563 100644
--- a/src/internal/types/testdata/fixedbugs/issue49739.go
+++ b/src/internal/types/testdata/fixedbugs/issue49739.go
@@ -17,7 +17,7 @@
func h[_ C | int]() {}
func _() {
- _ = f[int /* ERROR cannot implement C \(empty type set\) */]
- _ = g[int /* ERROR cannot implement interface{C} \(empty type set\) */]
+ _ = f[int /* ERROR cannot satisfy C \(empty type set\) */]
+ _ = g[int /* ERROR cannot satisfy interface{C} \(empty type set\) */]
_ = h[int]
}
diff --git a/src/internal/types/testdata/fixedbugs/issue50417.go b/src/internal/types/testdata/fixedbugs/issue50417.go
index 2caef1b..69ebf31 100644
--- a/src/internal/types/testdata/fixedbugs/issue50417.go
+++ b/src/internal/types/testdata/fixedbugs/issue50417.go
@@ -25,8 +25,8 @@
var _ = f0[Sf]
var _ = f0t[Sf]
-var _ = f0[Sm /* ERROR does not implement */ ]
-var _ = f0t[Sm /* ERROR does not implement */ ]
+var _ = f0[Sm /* ERROR does not satisfy */ ]
+var _ = f0t[Sm /* ERROR does not satisfy */ ]
func f1[P interface{ Sf; m() }](p P) {
_ = p.f // ERROR p\.f undefined
@@ -35,7 +35,7 @@
}
var _ = f1[Sf /* ERROR missing method m */ ]
-var _ = f1[Sm /* ERROR does not implement */ ]
+var _ = f1[Sm /* ERROR does not satisfy */ ]
type Sm struct {}
diff --git a/src/internal/types/testdata/fixedbugs/issue50646.go b/src/internal/types/testdata/fixedbugs/issue50646.go
index bc53700..ed7261c 100644
--- a/src/internal/types/testdata/fixedbugs/issue50646.go
+++ b/src/internal/types/testdata/fixedbugs/issue50646.go
@@ -13,16 +13,16 @@
func _[P comparable, Q ~int, R any]() {
_ = f1[int]
- _ = f1[T /* ERROR T does not implement comparable */ ]
- _ = f1[any /* ERROR any does not implement comparable */ ]
+ _ = f1[T /* ERROR T does not satisfy comparable */ ]
+ _ = f1[any /* ERROR any does not satisfy comparable */ ]
_ = f1[P]
_ = f1[Q]
- _ = f1[R /* ERROR R does not implement comparable */]
+ _ = f1[R /* ERROR R does not satisfy comparable */]
_ = f2[int]
- _ = f2[T /* ERROR T does not implement comparable */ ]
- _ = f2[any /* ERROR any does not implement comparable */ ]
+ _ = f2[T /* ERROR T does not satisfy comparable */ ]
+ _ = f2[any /* ERROR any does not satisfy comparable */ ]
_ = f2[P]
_ = f2[Q]
- _ = f2[R /* ERROR R does not implement comparable */]
+ _ = f2[R /* ERROR R does not satisfy comparable */]
}
diff --git a/src/internal/types/testdata/fixedbugs/issue50782.go b/src/internal/types/testdata/fixedbugs/issue50782.go
index fd1ab11..0e7b712 100644
--- a/src/internal/types/testdata/fixedbugs/issue50782.go
+++ b/src/internal/types/testdata/fixedbugs/issue50782.go
@@ -21,7 +21,7 @@
// AbsDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
-func absDifference[T numericAbs[T /* ERROR T does not implement Numeric */]](a, b T) T {
+func absDifference[T numericAbs[T /* ERROR T does not satisfy Numeric */]](a, b T) T {
// Field accesses are not permitted for now. Keep an error so
// we can find and fix this code once the situation changes.
return a.Value // ERROR a\.Value undefined
@@ -33,15 +33,15 @@
// The second example from the issue.
type T[P int] struct{ f P }
-func _[P T[P /* ERROR "P does not implement int" */ ]]() {}
+func _[P T[P /* ERROR "P does not satisfy int" */ ]]() {}
// Additional tests
-func _[P T[T /* ERROR "T\[P\] does not implement int" */ [P /* ERROR "P does not implement int" */ ]]]() {}
-func _[P T[Q /* ERROR "Q does not implement int" */ ], Q T[P /* ERROR "P does not implement int" */ ]]() {}
+func _[P T[T /* ERROR "T\[P\] does not satisfy int" */ [P /* ERROR "P does not satisfy int" */ ]]]() {}
+func _[P T[Q /* ERROR "Q does not satisfy int" */ ], Q T[P /* ERROR "P does not satisfy int" */ ]]() {}
func _[P T[Q], Q int]() {}
type C[P comparable] struct{ f P }
func _[P C[C[P]]]() {}
-func _[P C[C /* ERROR "C\[Q\] does not implement comparable" */ [Q /* ERROR "Q does not implement comparable" */]], Q func()]() {}
+func _[P C[C /* ERROR "C\[Q\] does not satisfy comparable" */ [Q /* ERROR "Q does not satisfy comparable" */]], Q func()]() {}
func _[P [10]C[P]]() {}
func _[P struct{ f C[C[P]]}]() {}
diff --git a/src/internal/types/testdata/fixedbugs/issue51257.go b/src/internal/types/testdata/fixedbugs/issue51257.go
index 4730c98..be4b81fe 100644
--- a/src/internal/types/testdata/fixedbugs/issue51257.go
+++ b/src/internal/types/testdata/fixedbugs/issue51257.go
@@ -14,13 +14,13 @@
func _[P1 comparable, P2 S2]() {
_ = f[S1]
- _ = f[S2 /* ERROR S2 does not implement comparable */ ]
- _ = f[S3 /* ERROR S3 does not implement comparable */ ]
+ _ = f[S2 /* ERROR S2 does not satisfy comparable */ ]
+ _ = f[S3 /* ERROR S3 does not satisfy comparable */ ]
type L1 struct { x P1 }
type L2 struct { x P2 }
_ = f[L1]
- _ = f[L2 /* ERROR L2 does not implement comparable */ ]
+ _ = f[L2 /* ERROR L2 does not satisfy comparable */ ]
}
@@ -41,7 +41,7 @@
type T struct{ x any }
func main() {
- NewSetFromSlice /* ERROR T does not implement comparable */ ([]T{
+ NewSetFromSlice /* ERROR T does not satisfy comparable */ ([]T{
{"foo"},
{5},
})
diff --git a/src/internal/types/testdata/fixedbugs/issue51376.go b/src/internal/types/testdata/fixedbugs/issue51376.go
index d51607b..3801d68 100644
--- a/src/internal/types/testdata/fixedbugs/issue51376.go
+++ b/src/internal/types/testdata/fixedbugs/issue51376.go
@@ -12,7 +12,7 @@
func _[M1 ~map[K]V, M2 map[K]V, K comparable, V any]() {
var m1 M1
f(m1)
- g /* ERROR M1 does not implement map\[K\]V */ (m1) // M1 has tilde
+ g /* ERROR M1 does not satisfy map\[K\]V */ (m1) // M1 has tilde
var m2 M2
f(m2)
@@ -20,5 +20,5 @@
var m3 Map
f(m3)
- g /* ERROR Map does not implement map\[string\]int */ (m3) // M in g does not have tilde
+ g /* ERROR Map does not satisfy map\[string\]int */ (m3) // M in g does not have tilde
}
diff --git a/src/internal/types/testdata/fixedbugs/issue51472.go b/src/internal/types/testdata/fixedbugs/issue51472.go
index 52ae09d..a0f9e9c 100644
--- a/src/internal/types/testdata/fixedbugs/issue51472.go
+++ b/src/internal/types/testdata/fixedbugs/issue51472.go
@@ -49,6 +49,6 @@
}
func _(s []byte) {
- f /* ERROR \[\]byte does not implement interface{comparable; \[\]byte \| string} */ (s)
- _ = f[[ /* ERROR does not implement */ ]byte]
+ f /* ERROR \[\]byte does not satisfy interface{comparable; \[\]byte \| string} */ (s)
+ _ = f[[ /* ERROR does not satisfy */ ]byte]
}
diff --git a/src/internal/types/testdata/fixedbugs/issue57486.go b/src/internal/types/testdata/fixedbugs/issue57486.go
index ff9e3d1..43ba1b0 100644
--- a/src/internal/types/testdata/fixedbugs/issue57486.go
+++ b/src/internal/types/testdata/fixedbugs/issue57486.go
@@ -17,13 +17,13 @@
func G2[T C2](t T) { _ = t == t }
func F1[V [2]any](v V) {
- _ = G1[V /* ERROR "V does not implement comparable" */]
+ _ = G1[V /* ERROR "V does not satisfy comparable" */]
_ = G1[[2]any]
_ = G1[int]
}
func F2[V [2]any](v V) {
- _ = G2[V /* ERROR "V does not implement C2" */]
- _ = G2[[ /* ERROR "\[2\]any does not implement C2 \(\[2\]any missing in int\)" */ 2]any]
+ _ = G2[V /* ERROR "V does not satisfy C2" */]
+ _ = G2[[ /* ERROR "\[2\]any does not satisfy C2 \(C2 mentions \[2\]any, but \[2\]any is not in the type set of C2\)" */ 2]any]
_ = G2[int]
}
diff --git a/src/internal/types/testdata/fixedbugs/issue57500.go b/src/internal/types/testdata/fixedbugs/issue57500.go
new file mode 100644
index 0000000..abdcb5e
--- /dev/null
+++ b/src/internal/types/testdata/fixedbugs/issue57500.go
@@ -0,0 +1,16 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+type C interface {
+ comparable
+ [2]any | int
+}
+
+func f[T C]() {}
+
+func _() {
+ _ = f[[ /* ERROR \[2\]any does not satisfy C \(C mentions \[2\]any, but \[2\]any is not in the type set of C\) */ 2]any]
+}
diff --git a/src/internal/types/testdata/fixedbugs/issue57522.go b/src/internal/types/testdata/fixedbugs/issue57522.go
new file mode 100644
index 0000000..d83e5b2
--- /dev/null
+++ b/src/internal/types/testdata/fixedbugs/issue57522.go
@@ -0,0 +1,24 @@
+// Copyright 2023 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package p
+
+// A simplified version of the code in the original report.
+type S[T any] struct{}
+var V = S[any]{}
+func (fs *S[T]) M(V.M /* ERROR "V.M is not a type" */) {}
+
+// Other minimal reproducers.
+type S1[T any] V1.M /* ERROR "V1.M is not a type" */
+type V1 = S1[any]
+
+type S2[T any] struct{}
+type V2 = S2[any]
+func (fs *S2[T]) M(x V2.M /* ERROR "V2.M is not a type" */ ) {}
+
+// The following still panics, as the selector is reached from check.expr
+// rather than check.typexpr. TODO(rfindley): fix this.
+// type X[T any] int
+// func (X[T]) M(x [X[int].M]int) {}
+
diff --git a/src/internal/types/testdata/spec/comparable.go b/src/internal/types/testdata/spec/comparable.go
index 03c8471..f407c35 100644
--- a/src/internal/types/testdata/spec/comparable.go
+++ b/src/internal/types/testdata/spec/comparable.go
@@ -11,16 +11,16 @@
func _[P comparable, Q ~int, R any]() {
_ = f1[int]
- _ = f1[T /* T does implement comparable */]
- _ = f1[any /* any does implement comparable */]
+ _ = f1[T /* T does satisfy comparable */]
+ _ = f1[any /* any does satisfy comparable */]
_ = f1[P]
_ = f1[Q]
- _ = f1[R /* ERROR R does not implement comparable */]
+ _ = f1[R /* ERROR R does not satisfy comparable */]
_ = f2[int]
- _ = f2[T /* T does implement comparable */]
- _ = f2[any /* any does implement comparable */]
+ _ = f2[T /* T does satisfy comparable */]
+ _ = f2[any /* any does satisfy comparable */]
_ = f2[P]
_ = f2[Q]
- _ = f2[R /* ERROR R does not implement comparable */]
+ _ = f2[R /* ERROR R does not satisfy comparable */]
}
diff --git a/src/internal/types/testdata/spec/comparable1.19.go b/src/internal/types/testdata/spec/comparable1.19.go
index c9c87e4..dc1c5fa 100644
--- a/src/internal/types/testdata/spec/comparable1.19.go
+++ b/src/internal/types/testdata/spec/comparable1.19.go
@@ -13,16 +13,16 @@
func _[P comparable, Q ~int, R any]() {
_ = f1[int]
- _ = f1[T /* ERROR T to implement comparable requires go1\.20 or later */]
- _ = f1[any /* ERROR any to implement comparable requires go1\.20 or later */]
+ _ = f1[T /* ERROR T to satisfy comparable requires go1\.20 or later */]
+ _ = f1[any /* ERROR any to satisfy comparable requires go1\.20 or later */]
_ = f1[P]
_ = f1[Q]
- _ = f1[R /* ERROR R does not implement comparable */]
+ _ = f1[R /* ERROR R does not satisfy comparable */]
_ = f2[int]
- _ = f2[T /* ERROR T to implement comparable requires go1\.20 or later */]
- _ = f2[any /* ERROR any to implement comparable requires go1\.20 or later */]
+ _ = f2[T /* ERROR T to satisfy comparable requires go1\.20 or later */]
+ _ = f2[any /* ERROR any to satisfy comparable requires go1\.20 or later */]
_ = f2[P]
_ = f2[Q]
- _ = f2[R /* ERROR R does not implement comparable */]
+ _ = f2[R /* ERROR R does not satisfy comparable */]
}
diff --git a/src/internal/types/testdata/spec/oldcomparable.go b/src/internal/types/testdata/spec/oldcomparable.go
index 9f6cf74..081d972 100644
--- a/src/internal/types/testdata/spec/oldcomparable.go
+++ b/src/internal/types/testdata/spec/oldcomparable.go
@@ -13,16 +13,16 @@
func _[P comparable, Q ~int, R any]() {
_ = f1[int]
- _ = f1[T /* ERROR T does not implement comparable */]
- _ = f1[any /* ERROR any does not implement comparable */]
+ _ = f1[T /* ERROR T does not satisfy comparable */]
+ _ = f1[any /* ERROR any does not satisfy comparable */]
_ = f1[P]
_ = f1[Q]
- _ = f1[R /* ERROR R does not implement comparable */]
+ _ = f1[R /* ERROR R does not satisfy comparable */]
_ = f2[int]
- _ = f2[T /* ERROR T does not implement comparable */]
- _ = f2[any /* ERROR any does not implement comparable */]
+ _ = f2[T /* ERROR T does not satisfy comparable */]
+ _ = f2[any /* ERROR any does not satisfy comparable */]
_ = f2[P]
_ = f2[Q]
- _ = f2[R /* ERROR R does not implement comparable */]
+ _ = f2[R /* ERROR R does not satisfy comparable */]
}
diff --git a/src/net/hosts.go b/src/net/hosts.go
index 7c8642c..dbf8fea 100644
--- a/src/net/hosts.go
+++ b/src/net/hosts.go
@@ -125,7 +125,7 @@
file.close()
}
-// lookupStaticHost looks up the addresses and the cannonical name for the given host from /etc/hosts.
+// lookupStaticHost looks up the addresses and the canonical name for the given host from /etc/hosts.
func lookupStaticHost(host string) ([]string, string) {
hosts.Lock()
defer hosts.Unlock()
diff --git a/src/os/exec/exec_test.go b/src/os/exec/exec_test.go
index edff9a2..67e2d25 100644
--- a/src/os/exec/exec_test.go
+++ b/src/os/exec/exec_test.go
@@ -1182,6 +1182,7 @@
os.Exit(1)
}
fmt.Fprintf(os.Stderr, "%d: started %d: %v\n", pid, cmd.Process.Pid, cmd)
+ go cmd.Wait() // Release resources if cmd happens not to outlive this process.
}
if *exitOnInterrupt {
diff --git a/src/runtime/crash_cgo_test.go b/src/runtime/crash_cgo_test.go
index ba0e9f4..51d7bb5 100644
--- a/src/runtime/crash_cgo_test.go
+++ b/src/runtime/crash_cgo_test.go
@@ -218,7 +218,9 @@
}
func TestCgoPprofCallback(t *testing.T) {
- t.Parallel()
+ if testing.Short() {
+ t.Skip("skipping in short mode") // takes a full second
+ }
switch runtime.GOOS {
case "windows", "plan9":
t.Skipf("skipping cgo pprof callback test on %s", runtime.GOOS)
diff --git a/src/runtime/mpagecache.go b/src/runtime/mpagecache.go
index 5bad4f7..5bc9c84 100644
--- a/src/runtime/mpagecache.go
+++ b/src/runtime/mpagecache.go
@@ -21,8 +21,7 @@
scav uint64 // 64-bit bitmap representing scavenged pages (1 means scavenged)
}
-// empty returns true if the pageCache has any free pages, and false
-// otherwise.
+// empty reports whether the page cache has no free pages.
func (c *pageCache) empty() bool {
return c.cache == 0
}
diff --git a/src/runtime/os_darwin.go b/src/runtime/os_darwin.go
index af5c18c..c4f3bb6 100644
--- a/src/runtime/os_darwin.go
+++ b/src/runtime/os_darwin.go
@@ -136,6 +136,8 @@
ncpu = getncpu()
physPageSize = getPageSize()
+
+ osinit_hack()
}
func sysctlbynameInt32(name []byte) (int32, int32) {
diff --git a/src/runtime/pprof/pprof_test.go b/src/runtime/pprof/pprof_test.go
index 39bc9d1..53688ad 100644
--- a/src/runtime/pprof/pprof_test.go
+++ b/src/runtime/pprof/pprof_test.go
@@ -607,7 +607,7 @@
var total uintptr
for i, name := range need {
total += have[i]
- t.Logf("%s: %d\n", name, have[i])
+ t.Logf("found %d samples in expected function %s\n", have[i], name)
}
if total == 0 {
t.Logf("no samples in expected functions")
@@ -727,6 +727,9 @@
}
func fprintStack(w io.Writer, stk []*profile.Location) {
+ if len(stk) == 0 {
+ fmt.Fprintf(w, " (stack empty)")
+ }
for _, loc := range stk {
fmt.Fprintf(w, " %#x", loc.Address)
fmt.Fprintf(w, " (")
@@ -1867,14 +1870,14 @@
isLabeled := s.Label != nil && contains(s.Label["key"], "value")
var (
mayBeLabeled bool
- mustBeLabeled bool
- mustNotBeLabeled bool
+ mustBeLabeled string
+ mustNotBeLabeled string
)
for _, loc := range s.Location {
for _, l := range loc.Line {
switch l.Function.Name {
case "runtime/pprof.labelHog", "runtime/pprof.parallelLabelHog", "runtime/pprof.parallelLabelHog.func1":
- mustBeLabeled = true
+ mustBeLabeled = l.Function.Name
case "runtime/pprof.Do":
// Do sets the labels, so samples may
// or may not be labeled depending on
@@ -1886,7 +1889,7 @@
// (such as those identified by
// runtime.isSystemGoroutine). These
// should never be labeled.
- mustNotBeLabeled = true
+ mustNotBeLabeled = l.Function.Name
case "gogo", "gosave_systemstack_switch", "racecall":
// These are context switch/race
// critical that we can't do a full
@@ -1908,25 +1911,28 @@
}
}
}
- if mustNotBeLabeled {
- // If this must not be labeled, then mayBeLabeled hints
- // are not relevant.
+ errorStack := func(f string, args ...any) {
+ var buf strings.Builder
+ fprintStack(&buf, s.Location)
+ t.Errorf("%s: %s", fmt.Sprintf(f, args...), buf.String())
+ }
+ if mustBeLabeled != "" && mustNotBeLabeled != "" {
+ errorStack("sample contains both %s, which must be labeled, and %s, which must not be labeled", mustBeLabeled, mustNotBeLabeled)
+ continue
+ }
+ if mustBeLabeled != "" || mustNotBeLabeled != "" {
+ // We found a definitive frame, so mayBeLabeled hints are not relevant.
mayBeLabeled = false
}
- if mustBeLabeled && !isLabeled {
- var buf strings.Builder
- fprintStack(&buf, s.Location)
- t.Errorf("Sample labeled got false want true: %s", buf.String())
+ if mayBeLabeled {
+ // This sample may or may not be labeled, so there's nothing we can check.
+ continue
}
- if mustNotBeLabeled && isLabeled {
- var buf strings.Builder
- fprintStack(&buf, s.Location)
- t.Errorf("Sample labeled got true want false: %s", buf.String())
+ if mustBeLabeled != "" && !isLabeled {
+ errorStack("sample must be labeled because of %s, but is not", mustBeLabeled)
}
- if isLabeled && !(mayBeLabeled || mustBeLabeled) {
- var buf strings.Builder
- fprintStack(&buf, s.Location)
- t.Errorf("Sample labeled got true want false: %s", buf.String())
+ if mustNotBeLabeled != "" && isLabeled {
+ errorStack("sample must not be labeled because of %s, but is", mustNotBeLabeled)
}
}
}
diff --git a/src/runtime/pprof/proto.go b/src/runtime/pprof/proto.go
index 8a49e14..b68f30d 100644
--- a/src/runtime/pprof/proto.go
+++ b/src/runtime/pprof/proto.go
@@ -395,6 +395,10 @@
// location ID slice, locs. The addresses in the stack are return PCs or 1 + the PC of
// an inline marker as the runtime traceback function returns.
//
+// It may return an empty slice even if locs is non-empty, for example if locs consists
+// solely of runtime.goexit. We still count these empty stacks in profiles in order to
+// get the right cumulative sample count.
+//
// It may emit to b.pb, so there must be no message encoding in progress.
func (b *profileBuilder) appendLocsForStack(locs []uint64, stk []uintptr) (newLocs []uint64) {
b.deck.reset()
diff --git a/src/runtime/sys_darwin.go b/src/runtime/sys_darwin.go
index 61b7f8c..8bff695 100644
--- a/src/runtime/sys_darwin.go
+++ b/src/runtime/sys_darwin.go
@@ -179,6 +179,45 @@
}
func pthread_kill_trampoline()
+// osinit_hack is a clumsy hack to work around Apple libc bugs
+// causing fork+exec to hang in the child process intermittently.
+// See go.dev/issue/33565 and go.dev/issue/56784 for a few reports.
+//
+// The stacks obtained from the hung child processes are in
+// libSystem_atfork_child, which is supposed to reinitialize various
+// parts of the C library in the new process.
+//
+// One common stack dies in _notify_fork_child calling _notify_globals
+// (inlined) calling _os_alloc_once, because _os_alloc_once detects that
+// the once lock is held by the parent process and then calls
+// _os_once_gate_corruption_abort. The allocation is setting up the
+// globals for the notification subsystem. See the source code at [1].
+// To work around this, we can allocate the globals earlier in the Go
+// program's lifetime, before any execs are involved, by calling any
+// notify routine that is exported, calls _notify_globals, and doesn't do
+// anything too expensive otherwise. notify_is_valid_token(0) fits the bill.
+//
+// The other common stack dies in xpc_atfork_child calling
+// _objc_msgSend_uncached which ends up in
+// WAITING_FOR_ANOTHER_THREAD_TO_FINISH_CALLING_+initialize. Of course,
+// whatever thread the child is waiting for is in the parent process and
+// is not going to finish anything in the child process. There is no
+// public source code for these routines, so it is unclear exactly what
+// the problem is. An Apple engineer suggests using xpc_date_create_from_current,
+// which empirically does fix the problem.
+//
+// So osinit_hack_trampoline (in sys_darwin_$GOARCH.s) calls
+// notify_is_valid_token(0) and xpc_date_create_from_current(), which makes the
+// fork+exec hangs stop happening. If Apple fixes the libc bug in
+// some future version of macOS, then we can remove this awful code.
+//
+//go:nosplit
+func osinit_hack() {
+ libcCall(unsafe.Pointer(abi.FuncPCABI0(osinit_hack_trampoline)), nil)
+ return
+}
+func osinit_hack_trampoline()
+
// mmap is used to do low-level memory allocation via mmap. Don't allow stack
// splits, since this function (used by sysAlloc) is called in a lot of low-level
// parts of the runtime and callers often assume it won't acquire any locks.
@@ -548,3 +587,6 @@
//go:cgo_import_dynamic libc_pthread_cond_wait pthread_cond_wait "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_pthread_cond_timedwait_relative_np pthread_cond_timedwait_relative_np "/usr/lib/libSystem.B.dylib"
//go:cgo_import_dynamic libc_pthread_cond_signal pthread_cond_signal "/usr/lib/libSystem.B.dylib"
+
+//go:cgo_import_dynamic libc_notify_is_valid_token notify_is_valid_token "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_xpc_date_create_from_current xpc_date_create_from_current "/usr/lib/libSystem.B.dylib"
diff --git a/src/runtime/sys_darwin_amd64.s b/src/runtime/sys_darwin_amd64.s
index 369b12e..6eaeeb9 100644
--- a/src/runtime/sys_darwin_amd64.s
+++ b/src/runtime/sys_darwin_amd64.s
@@ -597,6 +597,15 @@
POPQ BP
RET
+TEXT runtime·osinit_hack_trampoline(SB),NOSPLIT,$0
+ PUSHQ BP
+ MOVQ SP, BP
+ MOVQ $0, DI // arg 1 val
+ CALL libc_notify_is_valid_token(SB)
+ CALL libc_xpc_date_create_from_current(SB)
+ POPQ BP
+ RET
+
// syscall calls a function in libc on behalf of the syscall package.
// syscall takes a pointer to a struct like:
// struct {
diff --git a/src/runtime/sys_darwin_arm64.s b/src/runtime/sys_darwin_arm64.s
index 4fa99cc..4a51fb3 100644
--- a/src/runtime/sys_darwin_arm64.s
+++ b/src/runtime/sys_darwin_arm64.s
@@ -458,6 +458,12 @@
BL libc_pthread_setspecific(SB)
RET
+TEXT runtime·osinit_hack_trampoline(SB),NOSPLIT,$0
+ MOVD $0, R0 // arg 1 val
+ BL libc_notify_is_valid_token(SB)
+ BL libc_xpc_date_create_from_current(SB)
+ RET
+
// syscall calls a function in libc on behalf of the syscall package.
// syscall takes a pointer to a struct like:
// struct {
diff --git a/src/sync/atomic/value.go b/src/sync/atomic/value.go
index 2bef76c..8c491b4 100644
--- a/src/sync/atomic/value.go
+++ b/src/sync/atomic/value.go
@@ -41,7 +41,7 @@
var firstStoreInProgress byte
-// Store sets the value of the Value to x.
+// Store sets the value of the Value v to val.
// All calls to Store for a given Value must use values of the same concrete type.
// Store of an inconsistent type panics, as does Store(nil).
func (v *Value) Store(val any) {
diff --git a/src/syscall/exec_libc2.go b/src/syscall/exec_libc2.go
index 6e3c2bf..41bc79a 100644
--- a/src/syscall/exec_libc2.go
+++ b/src/syscall/exec_libc2.go
@@ -78,7 +78,7 @@
// About to call fork.
// No more allocation or calls of non-assembly functions.
runtime_BeforeFork()
- r1, _, err1 = rawSyscall(forkTrampoline, 0, 0, 0)
+ r1, _, err1 = rawSyscall(abi.FuncPCABI0(libc_fork_trampoline), 0, 0, 0)
if err1 != 0 {
runtime_AfterFork()
return 0, err1
@@ -276,6 +276,6 @@
// send error code on pipe
rawSyscall(abi.FuncPCABI0(libc_write_trampoline), uintptr(pipe), uintptr(unsafe.Pointer(&err1)), unsafe.Sizeof(err1))
for {
- rawSyscall(exitTrampoline, 253, 0, 0)
+ rawSyscall(abi.FuncPCABI0(libc_exit_trampoline), 253, 0, 0)
}
}
diff --git a/src/syscall/exec_linux_test.go b/src/syscall/exec_linux_test.go
index 1e21fff..a6900f9 100644
--- a/src/syscall/exec_linux_test.go
+++ b/src/syscall/exec_linux_test.go
@@ -505,8 +505,9 @@
// Need an ability to create a sub-cgroup.
subCgroup, err := os.MkdirTemp(prefix+string(bytes.TrimSpace(cg)), "subcg-")
if err != nil {
- // Running in an unprivileged container, this may also return EROFS #57262.
- if os.IsPermission(err) || errors.Is(err, syscall.EROFS) {
+ // ErrPermission or EROFS (#57262) when running in an unprivileged container.
+ // ErrNotExist when cgroupfs is not mounted in chroot/schroot.
+ if os.IsNotExist(err) || os.IsPermission(err) || errors.Is(err, syscall.EROFS) {
t.Skip(err)
}
t.Fatal(err)
diff --git a/src/syscall/syscall_darwin.go b/src/syscall/syscall_darwin.go
index 5ec3119..a39e99d 100644
--- a/src/syscall/syscall_darwin.go
+++ b/src/syscall/syscall_darwin.go
@@ -22,34 +22,7 @@
func RawSyscall(trap, a1, a2, a3 uintptr) (r1, r2 uintptr, err Errno)
func RawSyscall6(trap, a1, a2, a3, a4, a5, a6 uintptr) (r1, r2 uintptr, err Errno)
-// These are called from exec_libc2.go in the child of fork.
-// The names differ between macOS and OpenBSD, so we need
-// to declare the specific ones used here to keep the exec_libc2.go
-// code portable.
-//
-// We use __fork and __exit, not fork and exit, to avoid the libc atfork
-// and atexit handlers. The atfork handlers have caused fork child
-// hangs in the past (see #33565, #56784). The atexit handlers have
-// not, but the non-libc ports all invoke the system call, so doing
-// the same here makes sense. In general we wouldn't expect
-// atexit handlers to work terribly well in a fork child anyway.
-// (Also, perhaps the atfork handlers clear the atexit handlers,
-// in which case we definitely need to avoid calling the libc exit
-// if we bypass the libc fork.)
-//
-// Other calls that are made in the child after the fork are
-// ptrace, setsid, setpgid, getpid, ioctl, chroot, setgroups,
-// setgid, setuid, chdir, dup2, fcntl, close, execve, and write.
-// Those are all simple kernel wrappers that should be safe
-// to be called directly. The fcntl and ioctl functions do run
-// some code around the kernel call, but they don't call any
-// other functions, so for now we keep using them instead of
-// calling the lower-level __fcntl and __ioctl functions.
-var (
- dupTrampoline = abi.FuncPCABI0(libc_dup2_trampoline)
- exitTrampoline = abi.FuncPCABI0(libc___exit_trampoline)
- forkTrampoline = abi.FuncPCABI0(libc___fork_trampoline)
-)
+var dupTrampoline = abi.FuncPCABI0(libc_dup2_trampoline)
type SockaddrDatalink struct {
Len uint8
@@ -237,12 +210,11 @@
//sys writev(fd int, iovecs []Iovec) (cnt uintptr, err error)
//sys mmap(addr uintptr, length uintptr, prot int, flag int, fd int, pos int64) (ret uintptr, err error)
//sys munmap(addr uintptr, length uintptr) (err error)
-//sysnb __fork() (pid int, err error)
+//sysnb fork() (pid int, err error)
//sysnb ioctl(fd int, req int, arg int) (err error)
//sysnb ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_ioctl
//sysnb execve(path *byte, argv **byte, envp **byte) (err error)
//sysnb exit(res int) (err error)
-//sysnb __exit(res int) (err error)
//sys sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error)
//sys fcntlPtr(fd int, cmd int, arg unsafe.Pointer) (val int, err error) = SYS_fcntl
//sys unlinkat(fd int, path string, flags int) (err error)
diff --git a/src/syscall/syscall_openbsd_libc.go b/src/syscall/syscall_openbsd_libc.go
index 6358a9a..516d029 100644
--- a/src/syscall/syscall_openbsd_libc.go
+++ b/src/syscall/syscall_openbsd_libc.go
@@ -10,11 +10,7 @@
"internal/abi"
)
-var (
- dupTrampoline = abi.FuncPCABI0(libc_dup3_trampoline)
- exitTrampoline = abi.FuncPCABI0(libc_exit_trampoline)
- forkTrampoline = abi.FuncPCABI0(libc_fork_trampoline)
-)
+var dupTrampoline = abi.FuncPCABI0(libc_dup3_trampoline)
func init() {
execveOpenBSD = execve
diff --git a/src/syscall/zsyscall_darwin_amd64.go b/src/syscall/zsyscall_darwin_amd64.go
index 5e3f6cc..6b3fff3 100644
--- a/src/syscall/zsyscall_darwin_amd64.go
+++ b/src/syscall/zsyscall_darwin_amd64.go
@@ -1734,8 +1734,8 @@
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func __fork() (pid int, err error) {
- r0, _, e1 := rawSyscall(abi.FuncPCABI0(libc___fork_trampoline), 0, 0, 0)
+func fork() (pid int, err error) {
+ r0, _, e1 := rawSyscall(abi.FuncPCABI0(libc_fork_trampoline), 0, 0, 0)
pid = int(r0)
if e1 != 0 {
err = errnoErr(e1)
@@ -1743,9 +1743,9 @@
return
}
-func libc___fork_trampoline()
+func libc_fork_trampoline()
-//go:cgo_import_dynamic libc___fork __fork "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_fork fork "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1801,20 +1801,6 @@
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func __exit(res int) (err error) {
- _, _, e1 := rawSyscall(abi.FuncPCABI0(libc___exit_trampoline), uintptr(res), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc___exit_trampoline()
-
-//go:cgo_import_dynamic libc___exit __exit "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
var _p0 unsafe.Pointer
if len(mib) > 0 {
diff --git a/src/syscall/zsyscall_darwin_amd64.s b/src/syscall/zsyscall_darwin_amd64.s
index cbb4496..90e51fb 100644
--- a/src/syscall/zsyscall_darwin_amd64.s
+++ b/src/syscall/zsyscall_darwin_amd64.s
@@ -221,16 +221,14 @@
JMP libc_mmap(SB)
TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0
JMP libc_munmap(SB)
-TEXT ·libc___fork_trampoline(SB),NOSPLIT,$0-0
- JMP libc___fork(SB)
+TEXT ·libc_fork_trampoline(SB),NOSPLIT,$0-0
+ JMP libc_fork(SB)
TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0
JMP libc_ioctl(SB)
TEXT ·libc_execve_trampoline(SB),NOSPLIT,$0-0
JMP libc_execve(SB)
TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0
JMP libc_exit(SB)
-TEXT ·libc___exit_trampoline(SB),NOSPLIT,$0-0
- JMP libc___exit(SB)
TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0
JMP libc_sysctl(SB)
TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
diff --git a/src/syscall/zsyscall_darwin_arm64.go b/src/syscall/zsyscall_darwin_arm64.go
index d4c56be..6160144 100644
--- a/src/syscall/zsyscall_darwin_arm64.go
+++ b/src/syscall/zsyscall_darwin_arm64.go
@@ -1734,8 +1734,8 @@
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func __fork() (pid int, err error) {
- r0, _, e1 := rawSyscall(abi.FuncPCABI0(libc___fork_trampoline), 0, 0, 0)
+func fork() (pid int, err error) {
+ r0, _, e1 := rawSyscall(abi.FuncPCABI0(libc_fork_trampoline), 0, 0, 0)
pid = int(r0)
if e1 != 0 {
err = errnoErr(e1)
@@ -1743,9 +1743,9 @@
return
}
-func libc___fork_trampoline()
+func libc_fork_trampoline()
-//go:cgo_import_dynamic libc___fork __fork "/usr/lib/libSystem.B.dylib"
+//go:cgo_import_dynamic libc_fork fork "/usr/lib/libSystem.B.dylib"
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
@@ -1801,20 +1801,6 @@
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-func __exit(res int) (err error) {
- _, _, e1 := rawSyscall(abi.FuncPCABI0(libc___exit_trampoline), uintptr(res), 0, 0)
- if e1 != 0 {
- err = errnoErr(e1)
- }
- return
-}
-
-func libc___exit_trampoline()
-
-//go:cgo_import_dynamic libc___exit __exit "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
func sysctl(mib []_C_int, old *byte, oldlen *uintptr, new *byte, newlen uintptr) (err error) {
var _p0 unsafe.Pointer
if len(mib) > 0 {
diff --git a/src/syscall/zsyscall_darwin_arm64.s b/src/syscall/zsyscall_darwin_arm64.s
index ce1850e..f007479 100644
--- a/src/syscall/zsyscall_darwin_arm64.s
+++ b/src/syscall/zsyscall_darwin_arm64.s
@@ -221,16 +221,14 @@
JMP libc_mmap(SB)
TEXT ·libc_munmap_trampoline(SB),NOSPLIT,$0-0
JMP libc_munmap(SB)
-TEXT ·libc___fork_trampoline(SB),NOSPLIT,$0-0
- JMP libc___fork(SB)
+TEXT ·libc_fork_trampoline(SB),NOSPLIT,$0-0
+ JMP libc_fork(SB)
TEXT ·libc_ioctl_trampoline(SB),NOSPLIT,$0-0
JMP libc_ioctl(SB)
TEXT ·libc_execve_trampoline(SB),NOSPLIT,$0-0
JMP libc_execve(SB)
TEXT ·libc_exit_trampoline(SB),NOSPLIT,$0-0
JMP libc_exit(SB)
-TEXT ·libc___exit_trampoline(SB),NOSPLIT,$0-0
- JMP libc___exit(SB)
TEXT ·libc_sysctl_trampoline(SB),NOSPLIT,$0-0
JMP libc_sysctl(SB)
TEXT ·libc_unlinkat_trampoline(SB),NOSPLIT,$0-0
diff --git a/src/testing/fuzz.go b/src/testing/fuzz.go
index 6e43ae7..d31a3f8 100644
--- a/src/testing/fuzz.go
+++ b/src/testing/fuzz.go
@@ -40,7 +40,7 @@
// fuzzWorkerExitCode is used as an exit code by fuzz worker processes after an
// internal error. This distinguishes internal errors from uncontrolled panics
-// and other failiures. Keep in sync with internal/fuzz.workerExitCode.
+// and other failures. Keep in sync with internal/fuzz.workerExitCode.
const fuzzWorkerExitCode = 70
// InternalFuzzTarget is an internal type but exported because it is
diff --git a/test/fixedbugs/issue18392.go b/test/fixedbugs/issue18392.go
index e0640ed..32c39c3 100644
--- a/test/fixedbugs/issue18392.go
+++ b/test/fixedbugs/issue18392.go
@@ -10,5 +10,5 @@
// TODO(mdempsky): This should be an error, but this error is
// nonsense. The error should actually mention that there's a
// type loop.
- Fn(A.Fn) // ERROR "type A has no method Fn|A.Fn undefined"
+ Fn(A.Fn) // ERROR "type A has no method Fn|A.Fn undefined|A.Fn is not a type"
}
diff --git a/test/fixedbugs/issue47068.dir/a.go b/test/fixedbugs/issue47068.dir/a.go
index f7b780d..30a51c1 100644
--- a/test/fixedbugs/issue47068.dir/a.go
+++ b/test/fixedbugs/issue47068.dir/a.go
@@ -10,6 +10,6 @@
10: 0, 11: 0, 12: 0, 13: 0, 14: 0, 15: 0, 16: 0, 17: 0, 18: 0, 19: 0,
20: 0, 21: 0, 22: 0, 23: 0, 24: 0, 25: 0, 26: 0, 27: 0, 28: 0, 29: 0}
if len(m) != 30 {
- panic("unepexted map length")
+ panic("unexpected map length")
}
}
diff --git a/test/typeparam/graph.go b/test/typeparam/graph.go
index 38a97bc..5cd1faa 100644
--- a/test/typeparam/graph.go
+++ b/test/typeparam/graph.go
@@ -36,7 +36,7 @@
nodes []_Node
}
-// _NodeC is the contraints on a node in a graph, given the _Edge type.
+// _NodeC is the constraints on a node in a graph, given the _Edge type.
type _NodeC[_Edge any] interface {
comparable
Edges() []_Edge
diff --git a/test/typeparam/mdempsky/8.dir/b.go b/test/typeparam/mdempsky/8.dir/b.go
index 84037bf..ef2637b 100644
--- a/test/typeparam/mdempsky/8.dir/b.go
+++ b/test/typeparam/mdempsky/8.dir/b.go
@@ -7,5 +7,5 @@
import "./a"
func init() {
- a.F[func()]() // ERROR "does not implement comparable"
+ a.F[func()]() // ERROR "does not satisfy comparable"
}
diff --git a/test/typeparam/mincheck.dir/main.go b/test/typeparam/mincheck.dir/main.go
index c9ca50a..6f85f9e 100644
--- a/test/typeparam/mincheck.dir/main.go
+++ b/test/typeparam/mincheck.dir/main.go
@@ -28,11 +28,11 @@
}
const want2 = "ay"
- if got := a.Min[string]("bb", "ay"); got != want2 { // ERROR "string does not implement"
+ if got := a.Min[string]("bb", "ay"); got != want2 { // ERROR "string does not satisfy"
panic(fmt.Sprintf("got %d, want %d", got, want2))
}
- if got := a.Min("bb", "ay"); got != want2 { // ERROR "string does not implement"
+ if got := a.Min("bb", "ay"); got != want2 { // ERROR "string does not satisfy"
panic(fmt.Sprintf("got %d, want %d", got, want2))
}
}