mirror of
https://github.com/golang/go
synced 2024-09-04 23:44:16 +00:00
Merge "[dev.typeparams] all: merge master (798ec73
) into dev.typeparams" into dev.typeparams
This commit is contained in:
commit
244267e8c4
|
@ -80,6 +80,7 @@ pkg net/url, method (Values) Has(string) bool
|
||||||
pkg reflect, func VisibleFields(Type) []StructField
|
pkg reflect, func VisibleFields(Type) []StructField
|
||||||
pkg reflect, method (Method) IsExported() bool
|
pkg reflect, method (Method) IsExported() bool
|
||||||
pkg reflect, method (StructField) IsExported() bool
|
pkg reflect, method (StructField) IsExported() bool
|
||||||
|
pkg reflect, method (Value) CanConvert(Type) bool
|
||||||
pkg runtime/cgo (darwin-amd64-cgo), func NewHandle(interface{}) Handle
|
pkg runtime/cgo (darwin-amd64-cgo), func NewHandle(interface{}) Handle
|
||||||
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Delete()
|
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Delete()
|
||||||
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Value() interface{}
|
pkg runtime/cgo (darwin-amd64-cgo), method (Handle) Value() interface{}
|
||||||
|
|
|
@ -989,6 +989,18 @@ func Foo() bool {
|
||||||
|
|
||||||
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
|
<dl id="reflect"><dt><a href="/pkg/reflect/">reflect</a></dt>
|
||||||
<dd>
|
<dd>
|
||||||
|
<p><!-- CL 334669 -->
|
||||||
|
The new
|
||||||
|
<a href="/pkg/reflect/#Value.CanConvert"><code>Value.CanConvert</code></a>
|
||||||
|
method reports whether a value can be converted to a type.
|
||||||
|
This may be used to avoid a panic when converting a slice to an
|
||||||
|
array pointer type if the slice is too short.
|
||||||
|
Previously it was sufficient to use
|
||||||
|
<a href="/pkg/reflect/#Type.ConvertibleTo"><code>Type.ConvertibleTo</code></a>
|
||||||
|
for this, but the newly permitted conversion from slice to array
|
||||||
|
pointer type can panic even if the types are convertible.
|
||||||
|
</p>
|
||||||
|
|
||||||
<p><!-- CL 266197 -->
|
<p><!-- CL 266197 -->
|
||||||
The new
|
The new
|
||||||
<a href="/pkg/reflect/#StructField.IsExported"><code>StructField.IsExported</code></a>
|
<a href="/pkg/reflect/#StructField.IsExported"><code>StructField.IsExported</code></a>
|
||||||
|
|
|
@ -2850,3 +2850,35 @@ func TestExecInDeletedDir(t *testing.T) {
|
||||||
// `go version` should not fail
|
// `go version` should not fail
|
||||||
tg.run("version")
|
tg.run("version")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A missing C compiler should not force the net package to be stale.
|
||||||
|
// Issue 47215.
|
||||||
|
func TestMissingCC(t *testing.T) {
|
||||||
|
if !canCgo {
|
||||||
|
t.Skip("test is only meaningful on systems with cgo")
|
||||||
|
}
|
||||||
|
cc := os.Getenv("CC")
|
||||||
|
if cc == "" {
|
||||||
|
cc = "gcc"
|
||||||
|
}
|
||||||
|
if filepath.IsAbs(cc) {
|
||||||
|
t.Skipf(`"CC" (%s) is an absolute path`, cc)
|
||||||
|
}
|
||||||
|
_, err := exec.LookPath(cc)
|
||||||
|
if err != nil {
|
||||||
|
t.Skipf(`"CC" (%s) not on PATH`, cc)
|
||||||
|
}
|
||||||
|
|
||||||
|
tg := testgo(t)
|
||||||
|
defer tg.cleanup()
|
||||||
|
netStale, _ := tg.isStale("net")
|
||||||
|
if netStale {
|
||||||
|
t.Skip(`skipping test because "net" package is currently stale`)
|
||||||
|
}
|
||||||
|
|
||||||
|
tg.setenv("PATH", "") // No C compiler on PATH.
|
||||||
|
netStale, _ = tg.isStale("net")
|
||||||
|
if netStale {
|
||||||
|
t.Error(`clearing "PATH" causes "net" to be stale`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -252,8 +252,15 @@ func (b *Builder) buildActionID(a *Action) cache.ActionID {
|
||||||
|
|
||||||
ccExe := b.ccExe()
|
ccExe := b.ccExe()
|
||||||
fmt.Fprintf(h, "CC=%q %q %q %q\n", ccExe, cppflags, cflags, ldflags)
|
fmt.Fprintf(h, "CC=%q %q %q %q\n", ccExe, cppflags, cflags, ldflags)
|
||||||
if ccID, err := b.gccToolID(ccExe[0], "c"); err == nil {
|
// Include the C compiler tool ID so that if the C
|
||||||
fmt.Fprintf(h, "CC ID=%q\n", ccID)
|
// compiler changes we rebuild the package.
|
||||||
|
// But don't do that for standard library packages like net,
|
||||||
|
// so that the prebuilt .a files from a Go binary install
|
||||||
|
// don't need to be rebuilt with the local compiler.
|
||||||
|
if !p.Standard {
|
||||||
|
if ccID, err := b.gccToolID(ccExe[0], "c"); err == nil {
|
||||||
|
fmt.Fprintf(h, "CC ID=%q\n", ccID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if len(p.CXXFiles)+len(p.SwigCXXFiles) > 0 {
|
if len(p.CXXFiles)+len(p.SwigCXXFiles) > 0 {
|
||||||
cxxExe := b.cxxExe()
|
cxxExe := b.cxxExe()
|
||||||
|
|
|
@ -4305,6 +4305,9 @@ func TestConvert(t *testing.T) {
|
||||||
|
|
||||||
// vout1 represents the in value converted to the in type.
|
// vout1 represents the in value converted to the in type.
|
||||||
v1 := tt.in
|
v1 := tt.in
|
||||||
|
if !v1.CanConvert(t1) {
|
||||||
|
t.Errorf("ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", tt.in.Interface(), t1)
|
||||||
|
}
|
||||||
vout1 := v1.Convert(t1)
|
vout1 := v1.Convert(t1)
|
||||||
out1 := vout1.Interface()
|
out1 := vout1.Interface()
|
||||||
if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {
|
if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {
|
||||||
|
@ -4312,6 +4315,9 @@ func TestConvert(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// vout2 represents the in value converted to the out type.
|
// vout2 represents the in value converted to the out type.
|
||||||
|
if !v1.CanConvert(t2) {
|
||||||
|
t.Errorf("ValueOf(%T(%[1]v)).CanConvert(%s) = false, want true", tt.in.Interface(), t2)
|
||||||
|
}
|
||||||
vout2 := v1.Convert(t2)
|
vout2 := v1.Convert(t2)
|
||||||
out2 := vout2.Interface()
|
out2 := vout2.Interface()
|
||||||
if vout2.Type() != tt.out.Type() || !DeepEqual(out2, tt.out.Interface()) {
|
if vout2.Type() != tt.out.Type() || !DeepEqual(out2, tt.out.Interface()) {
|
||||||
|
@ -4372,6 +4378,9 @@ func TestConvertPanic(t *testing.T) {
|
||||||
if !v.Type().ConvertibleTo(pt) {
|
if !v.Type().ConvertibleTo(pt) {
|
||||||
t.Errorf("[]byte should be convertible to *[8]byte")
|
t.Errorf("[]byte should be convertible to *[8]byte")
|
||||||
}
|
}
|
||||||
|
if v.CanConvert(pt) {
|
||||||
|
t.Errorf("slice with length 4 should not be convertible to *[8]byte")
|
||||||
|
}
|
||||||
shouldPanic("reflect: cannot convert slice with length 4 to pointer to array with length 8", func() {
|
shouldPanic("reflect: cannot convert slice with length 4 to pointer to array with length 8", func() {
|
||||||
_ = v.Convert(pt)
|
_ = v.Convert(pt)
|
||||||
})
|
})
|
||||||
|
|
|
@ -2807,6 +2807,26 @@ func (v Value) Convert(t Type) Value {
|
||||||
return op(v, t)
|
return op(v, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CanConvert reports whether the value v can be converted to type t.
|
||||||
|
// If v.CanConvert(t) returns true then v.Convert(t) will not panic.
|
||||||
|
func (v Value) CanConvert(t Type) bool {
|
||||||
|
vt := v.Type()
|
||||||
|
if !vt.ConvertibleTo(t) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
// Currently the only conversion that is OK in terms of type
|
||||||
|
// but that can panic depending on the value is converting
|
||||||
|
// from slice to pointer-to-array.
|
||||||
|
if vt.Kind() == Slice && t.Kind() == Ptr && t.Elem().Kind() == Array {
|
||||||
|
n := t.Elem().Len()
|
||||||
|
h := (*unsafeheader.Slice)(v.ptr)
|
||||||
|
if n > h.Len {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// convertOp returns the function to convert a value of type src
|
// convertOp returns the function to convert a value of type src
|
||||||
// to a value of type dst. If the conversion is illegal, convertOp returns nil.
|
// to a value of type dst. If the conversion is illegal, convertOp returns nil.
|
||||||
func convertOp(dst, src *rtype) func(Value, Type) Value {
|
func convertOp(dst, src *rtype) func(Value, Type) Value {
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package reflect
|
package reflect
|
||||||
|
|
||||||
// VisibleFields returns all the visible fields in t, which must be a
|
// VisibleFields returns all the visible fields in t, which must be a
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
// Copyright 2021 The Go Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
package reflect_test
|
package reflect_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
|
@ -24,6 +24,9 @@ func TestPanicOnFault(t *testing.T) {
|
||||||
if runtime.GOOS == "ios" {
|
if runtime.GOOS == "ios" {
|
||||||
t.Skip("iOS doesn't provide fault addresses")
|
t.Skip("iOS doesn't provide fault addresses")
|
||||||
}
|
}
|
||||||
|
if runtime.GOOS == "netbsd" && runtime.GOARCH == "arm" {
|
||||||
|
t.Skip("netbsd-arm doesn't provide fault address (golang.org/issue/45026)")
|
||||||
|
}
|
||||||
m, err := syscall.Mmap(-1, 0, 0x1000, syscall.PROT_READ /* Note: no PROT_WRITE */, syscall.MAP_SHARED|syscall.MAP_ANON)
|
m, err := syscall.Mmap(-1, 0, 0x1000, syscall.PROT_READ /* Note: no PROT_WRITE */, syscall.MAP_SHARED|syscall.MAP_ANON)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("can't map anonymous memory: %s", err)
|
t.Fatalf("can't map anonymous memory: %s", err)
|
||||||
|
|
|
@ -1126,13 +1126,21 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
|
||||||
msanmalloc(x, size)
|
msanmalloc(x, size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if rate := MemProfileRate; rate > 0 {
|
||||||
|
// Note cache c only valid while m acquired; see #47302
|
||||||
|
if rate != 1 && size < c.nextSample {
|
||||||
|
c.nextSample -= size
|
||||||
|
} else {
|
||||||
|
profilealloc(mp, x, size)
|
||||||
|
}
|
||||||
|
}
|
||||||
mp.mallocing = 0
|
mp.mallocing = 0
|
||||||
releasem(mp)
|
releasem(mp)
|
||||||
|
|
||||||
// Pointerfree data can be zeroed late in a context where preemption can occur.
|
// Pointerfree data can be zeroed late in a context where preemption can occur.
|
||||||
// x will keep the memory alive.
|
// x will keep the memory alive.
|
||||||
if !isZeroed && needzero {
|
if !isZeroed && needzero {
|
||||||
memclrNoHeapPointersChunked(size, x)
|
memclrNoHeapPointersChunked(size, x) // This is a possible preemption point: see #47302
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug.malloc {
|
if debug.malloc {
|
||||||
|
@ -1146,16 +1154,6 @@ func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if rate := MemProfileRate; rate > 0 {
|
|
||||||
if rate != 1 && size < c.nextSample {
|
|
||||||
c.nextSample -= size
|
|
||||||
} else {
|
|
||||||
mp := acquirem()
|
|
||||||
profilealloc(mp, x, size)
|
|
||||||
releasem(mp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if assistG != nil {
|
if assistG != nil {
|
||||||
// Account for internal fragmentation in the assist
|
// Account for internal fragmentation in the assist
|
||||||
// debt now that we know it.
|
// debt now that we know it.
|
||||||
|
|
|
@ -681,7 +681,7 @@ type p struct {
|
||||||
// timerModifiedEarlier status. Because the timer may have been
|
// timerModifiedEarlier status. Because the timer may have been
|
||||||
// modified again, there need not be any timer with this value.
|
// modified again, there need not be any timer with this value.
|
||||||
// This is updated using atomic functions.
|
// This is updated using atomic functions.
|
||||||
// This is 0 if the value is unknown.
|
// This is 0 if there are no timerModifiedEarlier timers.
|
||||||
timerModifiedEarliest uint64
|
timerModifiedEarliest uint64
|
||||||
|
|
||||||
// Per-P GC state
|
// Per-P GC state
|
||||||
|
|
|
@ -669,11 +669,6 @@ func adjusttimers(pp *p, now int64) {
|
||||||
if verifyTimers {
|
if verifyTimers {
|
||||||
verifyTimerHeap(pp)
|
verifyTimerHeap(pp)
|
||||||
}
|
}
|
||||||
// There are no timers to adjust, so it is safe to clear
|
|
||||||
// timerModifiedEarliest. Do so in case it is stale.
|
|
||||||
// Everything will work if we don't do this,
|
|
||||||
// but clearing here may save future calls to adjusttimers.
|
|
||||||
atomic.Store64(&pp.timerModifiedEarliest, 0)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -527,6 +527,40 @@ func TestZeroTimer(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test that rapidly moving a timer earlier doesn't cause it to get dropped.
|
||||||
|
// Issue 47329.
|
||||||
|
func TestTimerModifiedEarlier(t *testing.T) {
|
||||||
|
past := Until(Unix(0, 0))
|
||||||
|
count := 1000
|
||||||
|
fail := 0
|
||||||
|
for i := 0; i < count; i++ {
|
||||||
|
timer := NewTimer(Hour)
|
||||||
|
for j := 0; j < 10; j++ {
|
||||||
|
if !timer.Stop() {
|
||||||
|
<-timer.C
|
||||||
|
}
|
||||||
|
timer.Reset(past)
|
||||||
|
}
|
||||||
|
|
||||||
|
deadline := NewTimer(10 * Second)
|
||||||
|
defer deadline.Stop()
|
||||||
|
now := Now()
|
||||||
|
select {
|
||||||
|
case <-timer.C:
|
||||||
|
if since := Since(now); since > 8*Second {
|
||||||
|
t.Errorf("timer took too long (%v)", since)
|
||||||
|
fail++
|
||||||
|
}
|
||||||
|
case <-deadline.C:
|
||||||
|
t.Error("deadline expired")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if fail > 0 {
|
||||||
|
t.Errorf("%d failures", fail)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Benchmark timer latency when the thread that creates the timer is busy with
|
// Benchmark timer latency when the thread that creates the timer is busy with
|
||||||
// other work and the timers must be serviced by other threads.
|
// other work and the timers must be serviced by other threads.
|
||||||
// https://golang.org/issue/38860
|
// https://golang.org/issue/38860
|
||||||
|
|
Loading…
Reference in a new issue