diff options
author | Ian Lance Taylor <iant@golang.org> | 2019-09-06 18:12:46 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@gcc.gnu.org> | 2019-09-06 18:12:46 +0000 |
commit | aa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13 (patch) | |
tree | 7e63b06d1eec92beec6997c9d3ab47a5d6a835be /libgo/go/reflect | |
parent | 920ea3b8ba3164b61ac9490dfdfceb6936eda6dd (diff) | |
download | gcc-aa8901e9bb0399d2c16f988ba2fe46eb0c0c5d13.tar.gz |
libgo: update to Go 1.13beta1 release
Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/193497
From-SVN: r275473
Diffstat (limited to 'libgo/go/reflect')
-rw-r--r-- | libgo/go/reflect/all_test.go | 276 | ||||
-rw-r--r-- | libgo/go/reflect/makefunc_ffi.go | 11 | ||||
-rw-r--r-- | libgo/go/reflect/swapper.go | 2 | ||||
-rw-r--r-- | libgo/go/reflect/type.go | 81 | ||||
-rw-r--r-- | libgo/go/reflect/value.go | 85 |
5 files changed, 358 insertions, 97 deletions
diff --git a/libgo/go/reflect/all_test.go b/libgo/go/reflect/all_test.go index 9452255f9a6..823d43c6e88 100644 --- a/libgo/go/reflect/all_test.go +++ b/libgo/go/reflect/all_test.go @@ -9,6 +9,7 @@ import ( "encoding/base64" "flag" "fmt" + "go/token" "io" "math" "math/rand" @@ -22,8 +23,6 @@ import ( "sync/atomic" "testing" "time" - "unicode" - "unicode/utf8" "unsafe" ) @@ -1061,6 +1060,113 @@ func TestIsNil(t *testing.T) { NotNil(fi, t) } +func TestIsZero(t *testing.T) { + for i, tt := range []struct { + x interface{} + want bool + }{ + // Booleans + {true, false}, + {false, true}, + // Numeric types + {int(0), true}, + {int(1), false}, + {int8(0), true}, + {int8(1), false}, + {int16(0), true}, + {int16(1), false}, + {int32(0), true}, + {int32(1), false}, + {int64(0), true}, + {int64(1), false}, + {uint(0), true}, + {uint(1), false}, + {uint8(0), true}, + {uint8(1), false}, + {uint16(0), true}, + {uint16(1), false}, + {uint32(0), true}, + {uint32(1), false}, + {uint64(0), true}, + {uint64(1), false}, + {float32(0), true}, + {float32(1.2), false}, + {float64(0), true}, + {float64(1.2), false}, + {math.Copysign(0, -1), false}, + {complex64(0), true}, + {complex64(1.2), false}, + {complex128(0), true}, + {complex128(1.2), false}, + {complex(math.Copysign(0, -1), 0), false}, + {complex(0, math.Copysign(0, -1)), false}, + {complex(math.Copysign(0, -1), math.Copysign(0, -1)), false}, + {uintptr(0), true}, + {uintptr(128), false}, + // Array + {Zero(TypeOf([5]string{})).Interface(), true}, + {[5]string{"", "", "", "", ""}, true}, + {[5]string{}, true}, + {[5]string{"", "", "", "a", ""}, false}, + // Chan + {(chan string)(nil), true}, + {make(chan string), false}, + {time.After(1), false}, + // Func + {(func())(nil), true}, + {New, false}, + // Interface + {New(TypeOf(new(error)).Elem()).Elem(), true}, + {(io.Reader)(strings.NewReader("")), false}, + // Map + {(map[string]string)(nil), true}, + {map[string]string{}, false}, + {make(map[string]string), false}, + // Ptr + {(*func())(nil), true}, + {(*int)(nil), true}, + {new(int), false}, + // Slice + {[]string{}, false}, + {([]string)(nil), true}, + {make([]string, 0), false}, + // Strings + {"", true}, + {"not-zero", false}, + // Structs + {T{}, true}, + {T{123, 456.75, "hello", &_i}, false}, + // UnsafePointer + {(unsafe.Pointer)(nil), true}, + {(unsafe.Pointer)(new(int)), false}, + } { + var x Value + if v, ok := tt.x.(Value); ok { + x = v + } else { + x = ValueOf(tt.x) + } + + b := x.IsZero() + if b != tt.want { + t.Errorf("%d: IsZero((%s)(%+v)) = %t, want %t", i, x.Kind(), tt.x, b, tt.want) + } + + if !Zero(TypeOf(tt.x)).IsZero() { + t.Errorf("%d: IsZero(Zero(TypeOf((%s)(%+v)))) is false", i, x.Kind(), tt.x) + } + } + + func() { + defer func() { + if r := recover(); r == nil { + t.Error("should panic for invalid value") + } + }() + (Value{}).IsZero() + }() +} + func TestInterfaceExtraction(t *testing.T) { var s struct { W io.Writer @@ -1831,6 +1937,91 @@ func TestMakeFuncVariadic(t *testing.T) { } } +// Dummy type that implements io.WriteCloser +type WC struct { +} + +func (w *WC) Write(p []byte) (n int, err error) { + return 0, nil +} +func (w *WC) Close() error { + return nil +} + +func TestMakeFuncValidReturnAssignments(t *testing.T) { + // reflect.Values returned from the wrapped function should be assignment-converted + // to the types returned by the result of MakeFunc. + + // Concrete types should be promotable to interfaces they implement. + var f func() error + f = MakeFunc(TypeOf(f), func([]Value) []Value { + return []Value{ValueOf(io.EOF)} + }).Interface().(func() error) + f() + + // Super-interfaces should be promotable to simpler interfaces. + var g func() io.Writer + g = MakeFunc(TypeOf(g), func([]Value) []Value { + var w io.WriteCloser = &WC{} + return []Value{ValueOf(&w).Elem()} + }).Interface().(func() io.Writer) + g() + + // Channels should be promotable to directional channels. + var h func() <-chan int + h = MakeFunc(TypeOf(h), func([]Value) []Value { + return []Value{ValueOf(make(chan int))} + }).Interface().(func() <-chan int) + h() + + // Unnamed types should be promotable to named types. + type T struct{ a, b, c int } + var i func() T + i = MakeFunc(TypeOf(i), func([]Value) []Value { + return []Value{ValueOf(struct{ a, b, c int }{a: 1, b: 2, c: 3})} + }).Interface().(func() T) + i() +} + +func TestMakeFuncInvalidReturnAssignments(t *testing.T) { + // Type doesn't implement the required interface. + shouldPanic(func() { + var f func() error + f = MakeFunc(TypeOf(f), func([]Value) []Value { + return []Value{ValueOf(int(7))} + }).Interface().(func() error) + f() + }) + // Assigning to an interface with additional methods. + shouldPanic(func() { + var f func() io.ReadWriteCloser + f = MakeFunc(TypeOf(f), func([]Value) []Value { + var w io.WriteCloser = &WC{} + return []Value{ValueOf(&w).Elem()} + }).Interface().(func() io.ReadWriteCloser) + f() + }) + // Directional channels can't be assigned to bidirectional ones. + shouldPanic(func() { + var f func() chan int + f = MakeFunc(TypeOf(f), func([]Value) []Value { + var c <-chan int = make(chan int) + return []Value{ValueOf(c)} + }).Interface().(func() chan int) + f() + }) + // Two named types which are otherwise identical. + shouldPanic(func() { + type T struct{ a, b, c int } + type U struct{ a, b, c int } + var f func() T + f = MakeFunc(TypeOf(f), func([]Value) []Value { + return []Value{ValueOf(U{a: 1, b: 2, c: 3})} + }).Interface().(func() T) + f() + }) +} + type Point struct { x, y int } @@ -2110,6 +2301,39 @@ func TestVariadicMethodValue(t *testing.T) { } } +type DirectIfaceT struct { + p *int +} + +func (d DirectIfaceT) M() int { return *d.p } + +func TestDirectIfaceMethod(t *testing.T) { + x := 42 + v := DirectIfaceT{&x} + typ := TypeOf(v) + m, ok := typ.MethodByName("M") + if !ok { + t.Fatalf("cannot find method M") + } + in := []Value{ValueOf(v)} + out := m.Func.Call(in) + if got := out[0].Int(); got != 42 { + t.Errorf("Call with value receiver got %d, want 42", got) + } + + pv := &v + typ = TypeOf(pv) + m, ok = typ.MethodByName("M") + if !ok { + t.Fatalf("cannot find method M") + } + in = []Value{ValueOf(pv)} + out = m.Func.Call(in) + if got := out[0].Int(); got != 42 { + t.Errorf("Call with pointer receiver got %d, want 42", got) + } +} + // Reflect version of $GOROOT/test/method5.go // Concrete types implementing M method. @@ -4249,37 +4473,37 @@ func TestStructOfFieldName(t *testing.T) { // invalid field name "1nvalid" shouldPanic(func() { StructOf([]StructField{ - StructField{Name: "valid", Type: TypeOf("")}, - StructField{Name: "1nvalid", Type: TypeOf("")}, + {Name: "valid", Type: TypeOf("")}, + {Name: "1nvalid", Type: TypeOf("")}, }) }) // invalid field name "+" shouldPanic(func() { StructOf([]StructField{ - StructField{Name: "val1d", Type: TypeOf("")}, - StructField{Name: "+", Type: TypeOf("")}, + {Name: "val1d", Type: TypeOf("")}, + {Name: "+", Type: TypeOf("")}, }) }) // no field name shouldPanic(func() { StructOf([]StructField{ - StructField{Name: "", Type: TypeOf("")}, + {Name: "", Type: TypeOf("")}, }) }) // verify creation of a struct with valid struct fields validFields := []StructField{ - StructField{ + { Name: "φ", Type: TypeOf(""), }, - StructField{ + { Name: "ValidName", Type: TypeOf(""), }, - StructField{ + { Name: "Val1dNam5", Type: TypeOf(""), }, @@ -4296,21 +4520,21 @@ func TestStructOfFieldName(t *testing.T) { func TestStructOf(t *testing.T) { // check construction and use of type not in binary fields := []StructField{ - StructField{ + { Name: "S", Tag: "s", Type: TypeOf(""), }, - StructField{ + { Name: "X", Tag: "x", Type: TypeOf(byte(0)), }, - StructField{ + { Name: "Y", Type: TypeOf(uint64(0)), }, - StructField{ + { Name: "Z", Type: TypeOf([3]uint16{}), }, @@ -4393,20 +4617,20 @@ func TestStructOf(t *testing.T) { // check duplicate names shouldPanic(func() { StructOf([]StructField{ - StructField{Name: "string", Type: TypeOf("")}, - StructField{Name: "string", Type: TypeOf("")}, + {Name: "string", Type: TypeOf("")}, + {Name: "string", Type: TypeOf("")}, }) }) shouldPanic(func() { StructOf([]StructField{ - StructField{Type: TypeOf("")}, - StructField{Name: "string", Type: TypeOf("")}, + {Type: TypeOf("")}, + {Name: "string", Type: TypeOf("")}, }) }) shouldPanic(func() { StructOf([]StructField{ - StructField{Type: TypeOf("")}, - StructField{Type: TypeOf("")}, + {Type: TypeOf("")}, + {Type: TypeOf("")}, }) }) // check that type already in binary is found @@ -4416,7 +4640,7 @@ func TestStructOf(t *testing.T) { type structFieldType interface{} checkSameType(t, StructOf([]StructField{ - StructField{ + { Name: "F", Type: TypeOf((*structFieldType)(nil)).Elem(), }, @@ -4575,7 +4799,7 @@ func TestStructOfExportRules(t *testing.T) { if n == "" { panic("field.Name must not be empty") } - exported := isExported(n) + exported := token.IsExported(n) if exported != test.exported { t.Errorf("test-%d: got exported=%v want exported=%v", i, exported, test.exported) } @@ -4583,14 +4807,6 @@ func TestStructOfExportRules(t *testing.T) { } } -// isExported reports whether name is an exported Go symbol -// (that is, whether it begins with an upper-case letter). -// -func isExported(name string) bool { - ch, _ := utf8.DecodeRuneInString(name) - return unicode.IsUpper(ch) -} - func TestStructOfGC(t *testing.T) { type T *uintptr tt := TypeOf(T(nil)) diff --git a/libgo/go/reflect/makefunc_ffi.go b/libgo/go/reflect/makefunc_ffi.go index 9d9cbdec25d..4564736bc99 100644 --- a/libgo/go/reflect/makefunc_ffi.go +++ b/libgo/go/reflect/makefunc_ffi.go @@ -44,11 +44,6 @@ func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFunc off := uintptr(0) for i, typ := range ftyp.out { v := out[i] - if v.typ != typ { - panic("reflect: function created by MakeFunc using " + funcName(impl.fn) + - " returned wrong type: have " + - out[i].typ.String() + " for " + typ.String()) - } if v.flag&flagRO != 0 { panic("reflect: function created by MakeFunc using " + funcName(impl.fn) + " returned value obtained from unexported field") @@ -56,6 +51,12 @@ func FFICallbackGo(results unsafe.Pointer, params unsafe.Pointer, impl *makeFunc off = align(off, uintptr(typ.fieldAlign)) addr := unsafe.Pointer(uintptr(results) + off) + + // Convert v to type typ if v is assignable to a variable + // of type t in the language spec. + // See issue 28761. + v = v.assignTo("reflect.MakeFunc", typ, addr) + if v.flag&flagIndir == 0 && (v.kind() == Ptr || v.kind() == UnsafePointer) { *(*unsafe.Pointer)(addr) = v.ptr } else { diff --git a/libgo/go/reflect/swapper.go b/libgo/go/reflect/swapper.go index bf77b682c4d..016f95d7b01 100644 --- a/libgo/go/reflect/swapper.go +++ b/libgo/go/reflect/swapper.go @@ -29,7 +29,7 @@ func Swapper(slice interface{}) func(i, j int) { typ := v.Type().Elem().(*rtype) size := typ.Size() - hasPtr := typ.kind&kindNoPointers == 0 + hasPtr := typ.ptrdata != 0 // Some common & small cases, without using memmove: if hasPtr { diff --git a/libgo/go/reflect/type.go b/libgo/go/reflect/type.go index 8493d87f802..f82f5eb1121 100644 --- a/libgo/go/reflect/type.go +++ b/libgo/go/reflect/type.go @@ -53,6 +53,9 @@ type Type interface { // // For an interface type, the returned Method's Type field gives the // method signature, without a receiver, and the Func field is nil. + // + // Only exported methods are accessible and they are sorted in + // lexicographic order. Method(int) Method // MethodByName returns the method with that name in the type's @@ -415,7 +418,6 @@ type Method struct { const ( kindDirectIface = 1 << 5 kindGCProg = 1 << 6 // Type.gc points to GC program - kindNoPointers = 1 << 7 kindMask = (1 << 5) - 1 ) @@ -546,7 +548,7 @@ func (t *rtype) FieldAlign() int { return int(t.fieldAlign) } func (t *rtype) Kind() Kind { return Kind(t.kind & kindMask) } -func (t *rtype) pointers() bool { return t.kind&kindNoPointers == 0 } +func (t *rtype) pointers() bool { return t.ptrdata != 0 } func (t *rtype) common() *rtype { return t } @@ -1761,13 +1763,6 @@ const ( ) func bucketOf(ktyp, etyp *rtype) *rtype { - // See comment on hmap.overflow in ../runtime/map.go. - var kind uint8 - if ktyp.kind&kindNoPointers != 0 && etyp.kind&kindNoPointers != 0 && - ktyp.size <= maxKeySize && etyp.size <= maxValSize { - kind = kindNoPointers - } - if ktyp.size > maxKeySize { ktyp = PtrTo(ktyp).(*rtype) } @@ -1804,14 +1799,14 @@ func bucketOf(ktyp, etyp *rtype) *rtype { ovoff := size size += ptrSize - if kind != kindNoPointers { + if ktyp.ptrdata != 0 || etyp.ptrdata != 0 { nptr := size / ptrSize mask := make([]byte, (nptr+7)/8) psize := bucketSize psize = align(psize, uintptr(ktyp.fieldAlign)) base := psize / ptrSize - if ktyp.kind&kindNoPointers == 0 { + if ktyp.ptrdata != 0 { if ktyp.kind&kindGCProg != 0 { panic("reflect: unexpected GC program in MapOf") } @@ -1829,7 +1824,7 @@ func bucketOf(ktyp, etyp *rtype) *rtype { psize = align(psize, uintptr(etyp.fieldAlign)) base = psize / ptrSize - if etyp.kind&kindNoPointers == 0 { + if etyp.ptrdata != 0 { if etyp.kind&kindGCProg != 0 { panic("reflect: unexpected GC program in MapOf") } @@ -1859,7 +1854,7 @@ func bucketOf(ktyp, etyp *rtype) *rtype { align: int8(maxAlign), fieldAlign: uint8(maxAlign), size: size, - kind: kind, + kind: uint8(Struct), ptrdata: ptrdata, gcdata: gcdata, } @@ -1962,7 +1957,6 @@ func StructOf(fields []StructField) Type { repr = make([]byte, 0, 64) fset = map[string]struct{}{} // fields' names - hasPtr = false // records whether at least one struct-field is a pointer hasGCProg = false // records whether a struct-field type has a GCProg ) @@ -1983,9 +1977,6 @@ func StructOf(fields []StructField) Type { if ft.kind&kindGCProg != 0 { hasGCProg = true } - if ft.pointers() { - hasPtr = true - } // Update string and hash name := *f.name @@ -2129,13 +2120,9 @@ func StructOf(fields []StructField) Type { typ.string = &str typ.hash = hash typ.size = size + typ.ptrdata = typeptrdata(typ.common()) typ.align = typalign typ.fieldAlign = uint8(typalign) - if !hasPtr { - typ.kind |= kindNoPointers - } else { - typ.kind &^= kindNoPointers - } if hasGCProg { lastPtrField := 0 @@ -2145,44 +2132,50 @@ func StructOf(fields []StructField) Type { } } prog := []byte{0, 0, 0, 0} // will be length of prog + var off uintptr for i, ft := range fs { if i > lastPtrField { // gcprog should not include anything for any field after // the last field that contains pointer data break } - // FIXME(sbinet) handle padding, fields smaller than a word + if !ft.typ.pointers() { + // Ignore pointerless fields. + continue + } + // Pad to start of this field with zeros. + if ft.offset() > off { + n := (ft.offset() - off) / ptrSize + prog = append(prog, 0x01, 0x00) // emit a 0 bit + if n > 1 { + prog = append(prog, 0x81) // repeat previous bit + prog = appendVarint(prog, n-1) // n-1 times + } + off = ft.offset() + } + elemGC := (*[1 << 30]byte)(unsafe.Pointer(ft.typ.gcdata))[:] elemPtrs := ft.typ.ptrdata / ptrSize - switch { - case ft.typ.kind&kindGCProg == 0 && ft.typ.ptrdata != 0: + if ft.typ.kind&kindGCProg == 0 { // Element is small with pointer mask; use as literal bits. mask := elemGC // Emit 120-bit chunks of full bytes (max is 127 but we avoid using partial bytes). var n uintptr - for n := elemPtrs; n > 120; n -= 120 { + for n = elemPtrs; n > 120; n -= 120 { prog = append(prog, 120) prog = append(prog, mask[:15]...) mask = mask[15:] } prog = append(prog, byte(n)) prog = append(prog, mask[:(n+7)/8]...) - case ft.typ.kind&kindGCProg != 0: + } else { // Element has GC program; emit one element. elemProg := elemGC[4 : 4+*(*uint32)(unsafe.Pointer(&elemGC[0]))-1] prog = append(prog, elemProg...) } - // Pad from ptrdata to size. - elemWords := ft.typ.size / ptrSize - if elemPtrs < elemWords { - // Emit literal 0 bit, then repeat as needed. - prog = append(prog, 0x01, 0x00) - if elemPtrs+1 < elemWords { - prog = append(prog, 0x81) - prog = appendVarint(prog, elemWords-elemPtrs-1) - } - } + off += ft.typ.ptrdata } + prog = append(prog, 0) *(*uint32)(unsafe.Pointer(&prog[0])) = uint32(len(prog) - 4) typ.kind |= kindGCProg typ.gcdata = &prog[0] @@ -2276,20 +2269,20 @@ func runtimeStructField(field StructField) structField { // containing pointer data. Anything after this offset is scalar data. // keep in sync with ../cmd/compile/internal/gc/reflect.go func typeptrdata(t *rtype) uintptr { - if !t.pointers() { - return 0 - } switch t.Kind() { case Struct: st := (*structType)(unsafe.Pointer(t)) // find the last field that has pointers. - field := 0 + field := -1 for i := range st.fields { ft := st.fields[i].typ if ft.pointers() { field = i } } + if field == -1 { + return 0 + } f := st.fields[field] return f.offset() + f.typ.ptrdata @@ -2357,11 +2350,9 @@ func ArrayOf(count int, elem Type) Type { array.len = uintptr(count) array.slice = SliceOf(elem).(*rtype) - array.kind &^= kindNoPointers switch { - case typ.kind&kindNoPointers != 0 || array.size == 0: + case typ.ptrdata == 0 || array.size == 0: // No pointers. - array.kind |= kindNoPointers array.gcdata = nil array.ptrdata = 0 @@ -2522,7 +2513,7 @@ func (bv *bitVector) append(bit uint8) { } func addTypeBits(bv *bitVector, offset uintptr, t *rtype) { - if t.kind&kindNoPointers != 0 { + if t.ptrdata == 0 { return } diff --git a/libgo/go/reflect/value.go b/libgo/go/reflect/value.go index 298fbacf364..c4a62c34b83 100644 --- a/libgo/go/reflect/value.go +++ b/libgo/go/reflect/value.go @@ -201,7 +201,8 @@ type nonEmptyInterface struct { // v.flag.mustBe(Bool), which will only bother to copy the // single important word for the receiver. func (f flag) mustBe(expected Kind) { - if f.kind() != expected { + // TODO(mvdan): use f.kind() again once mid-stack inlining gets better + if Kind(f&flagKindMask) != expected { panic(&ValueError{methodName(), f.kind()}) } } @@ -209,8 +210,14 @@ func (f flag) mustBe(expected Kind) { // mustBeExported panics if f records that the value was obtained using // an unexported field. func (f flag) mustBeExported() { + if f == 0 || f&flagRO != 0 { + f.mustBeExportedSlow() + } +} + +func (f flag) mustBeExportedSlow() { if f == 0 { - panic(&ValueError{methodName(), 0}) + panic(&ValueError{methodName(), Invalid}) } if f&flagRO != 0 { panic("reflect: " + methodName() + " using value obtained using unexported field") @@ -221,6 +228,12 @@ func (f flag) mustBeExported() { // which is to say that either it was obtained using an unexported field // or it is not addressable. func (f flag) mustBeAssignable() { + if f&flagRO != 0 || f&flagAddr == 0 { + f.mustBeAssignableSlow() + } +} + +func (f flag) mustBeAssignableSlow() { if f == 0 { panic(&ValueError{methodName(), Invalid}) } @@ -790,7 +803,7 @@ func (v Value) Interface() (i interface{}) { func valueInterface(v Value, safe bool) interface{} { if v.flag == 0 { - panic(&ValueError{"reflect.Value.Interface", 0}) + panic(&ValueError{"reflect.Value.Interface", Invalid}) } if safe && v.flag&flagRO != 0 { // Do not allow access to unexported values via Interface, @@ -877,6 +890,46 @@ func (v Value) IsValid() bool { return v.flag != 0 } +// IsZero reports whether v is the zero value for its type. +// It panics if the argument is invalid. +func (v Value) IsZero() bool { + switch v.kind() { + case Bool: + return !v.Bool() + case Int, Int8, Int16, Int32, Int64: + return v.Int() == 0 + case Uint, Uint8, Uint16, Uint32, Uint64, Uintptr: + return v.Uint() == 0 + case Float32, Float64: + return math.Float64bits(v.Float()) == 0 + case Complex64, Complex128: + c := v.Complex() + return math.Float64bits(real(c)) == 0 && math.Float64bits(imag(c)) == 0 + case Array: + for i := 0; i < v.Len(); i++ { + if !v.Index(i).IsZero() { + return false + } + } + return true + case Chan, Func, Interface, Map, Ptr, Slice, UnsafePointer: + return v.IsNil() + case String: + return v.Len() == 0 + case Struct: + for i := 0; i < v.NumField(); i++ { + if !v.Field(i).IsZero() { + return false + } + } + return true + default: + // This should never happens, but will act as a safeguard for + // later, as a default value doesn't makes sense here. + panic(&ValueError{"reflect.Value.IsZero", v.Kind()}) + } +} + // Kind returns v's Kind. // If v is the zero Value (IsValid returns false), Kind returns Invalid. func (v Value) Kind() Kind { @@ -1003,7 +1056,7 @@ func (it *MapIter) Value() Value { t := (*mapType)(unsafe.Pointer(it.m.typ)) vtype := t.elem - return copyVal(vtype, it.m.flag.ro()|flag(vtype.Kind()), mapitervalue(it.it)) + return copyVal(vtype, it.m.flag.ro()|flag(vtype.Kind()), mapiterelem(it.it)) } // Next advances the map iterator and reports whether there is another @@ -1391,13 +1444,13 @@ func (v Value) SetCap(n int) { s.Cap = n } -// SetMapIndex sets the value associated with key in the map v to val. +// SetMapIndex sets the element associated with key in the map v to elem. // It panics if v's Kind is not Map. -// If val is the zero Value, SetMapIndex deletes the key from the map. +// If elem is the zero Value, SetMapIndex deletes the key from the map. // Otherwise if v holds a nil map, SetMapIndex will panic. -// As in Go, key's value must be assignable to the map's key type, -// and val's value must be assignable to the map's value type. -func (v Value) SetMapIndex(key, val Value) { +// As in Go, key's elem must be assignable to the map's key type, +// and elem's value must be assignable to the map's elem type. +func (v Value) SetMapIndex(key, elem Value) { v.mustBe(Map) v.mustBeExported() key.mustBeExported() @@ -1409,17 +1462,17 @@ func (v Value) SetMapIndex(key, val Value) { } else { k = unsafe.Pointer(&key.ptr) } - if val.typ == nil { + if elem.typ == nil { mapdelete(v.typ, v.pointer(), k) return } - val.mustBeExported() - val = val.assignTo("reflect.Value.SetMapIndex", tt.elem, nil) + elem.mustBeExported() + elem = elem.assignTo("reflect.Value.SetMapIndex", tt.elem, nil) var e unsafe.Pointer - if val.flag&flagIndir != 0 { - e = val.ptr + if elem.flag&flagIndir != 0 { + e = elem.ptr } else { - e = unsafe.Pointer(&val.ptr) + e = unsafe.Pointer(&elem.ptr) } mapassign(v.typ, v.pointer(), k, e) } @@ -2464,7 +2517,7 @@ func mapiterinit(t *rtype, m unsafe.Pointer) unsafe.Pointer func mapiterkey(it unsafe.Pointer) (key unsafe.Pointer) //go:noescape -func mapitervalue(it unsafe.Pointer) (value unsafe.Pointer) +func mapiterelem(it unsafe.Pointer) (elem unsafe.Pointer) //go:noescape func mapiternext(it unsafe.Pointer) |