Source file src/internal/reflectlite/value.go
1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package reflectlite 6 7 import ( 8 "internal/goarch" 9 "internal/unsafeheader" 10 "runtime" 11 "unsafe" 12 ) 13 14 // Value is the reflection interface to a Go value. 15 // 16 // Not all methods apply to all kinds of values. Restrictions, 17 // if any, are noted in the documentation for each method. 18 // Use the Kind method to find out the kind of value before 19 // calling kind-specific methods. Calling a method 20 // inappropriate to the kind of type causes a run time panic. 21 // 22 // The zero Value represents no value. 23 // Its IsValid method returns false, its Kind method returns Invalid, 24 // its String method returns "<invalid Value>", and all other methods panic. 25 // Most functions and methods never return an invalid value. 26 // If one does, its documentation states the conditions explicitly. 27 // 28 // A Value can be used concurrently by multiple goroutines provided that 29 // the underlying Go value can be used concurrently for the equivalent 30 // direct operations. 31 // 32 // To compare two Values, compare the results of the Interface method. 33 // Using == on two Values does not compare the underlying values 34 // they represent. 35 type Value struct { 36 // typ holds the type of the value represented by a Value. 37 typ *rtype 38 39 // Pointer-valued data or, if flagIndir is set, pointer to data. 40 // Valid when either flagIndir is set or typ.pointers() is true. 41 ptr unsafe.Pointer 42 43 // flag holds metadata about the value. 44 // The lowest bits are flag bits: 45 // - flagStickyRO: obtained via unexported not embedded field, so read-only 46 // - flagEmbedRO: obtained via unexported embedded field, so read-only 47 // - flagIndir: val holds a pointer to the data 48 // - flagAddr: v.CanAddr is true (implies flagIndir) 49 // Value cannot represent method values. 50 // The next five bits give the Kind of the value. 51 // This repeats typ.Kind() except for method values. 52 // The remaining 23+ bits give a method number for method values. 53 // If flag.kind() != Func, code can assume that flagMethod is unset. 54 // If ifaceIndir(typ), code can assume that flagIndir is set. 55 flag 56 57 // A method value represents a curried method invocation 58 // like r.Read for some receiver r. The typ+val+flag bits describe 59 // the receiver r, but the flag's Kind bits say Func (methods are 60 // functions), and the top bits of the flag give the method number 61 // in r's type's method table. 62 } 63 64 type flag uintptr 65 66 const ( 67 flagKindWidth = 5 // there are 27 kinds 68 flagKindMask flag = 1<<flagKindWidth - 1 69 flagStickyRO flag = 1 << 5 70 flagEmbedRO flag = 1 << 6 71 flagIndir flag = 1 << 7 72 flagAddr flag = 1 << 8 73 flagMethod flag = 1 << 9 74 flagMethodShift = 10 75 flagRO flag = flagStickyRO | flagEmbedRO 76 ) 77 78 func (f flag) kind() Kind { 79 return Kind(f & flagKindMask) 80 } 81 82 func (f flag) ro() flag { 83 if f&flagRO != 0 { 84 return flagStickyRO 85 } 86 return 0 87 } 88 89 // pointer returns the underlying pointer represented by v. 90 // v.Kind() must be Pointer, Map, Chan, Func, or UnsafePointer 91 func (v Value) pointer() unsafe.Pointer { 92 if v.typ.size != goarch.PtrSize || !v.typ.pointers() { 93 panic("can't call pointer on a non-pointer Value") 94 } 95 if v.flag&flagIndir != 0 { 96 return *(*unsafe.Pointer)(v.ptr) 97 } 98 return v.ptr 99 } 100 101 // packEface converts v to the empty interface. 102 func packEface(v Value) any { 103 t := v.typ 104 var i any 105 e := (*emptyInterface)(unsafe.Pointer(&i)) 106 // First, fill in the data portion of the interface. 107 switch { 108 case ifaceIndir(t): 109 if v.flag&flagIndir == 0 { 110 panic("bad indir") 111 } 112 // Value is indirect, and so is the interface we're making. 113 ptr := v.ptr 114 if v.flag&flagAddr != 0 { 115 // TODO: pass safe boolean from valueInterface so 116 // we don't need to copy if safe==true? 117 c := unsafe_New(t) 118 typedmemmove(t, c, ptr) 119 ptr = c 120 } 121 e.word = ptr 122 case v.flag&flagIndir != 0: 123 // Value is indirect, but interface is direct. We need 124 // to load the data at v.ptr into the interface data word. 125 e.word = *(*unsafe.Pointer)(v.ptr) 126 default: 127 // Value is direct, and so is the interface. 128 e.word = v.ptr 129 } 130 // Now, fill in the type portion. We're very careful here not 131 // to have any operation between the e.word and e.typ assignments 132 // that would let the garbage collector observe the partially-built 133 // interface value. 134 e.typ = t 135 return i 136 } 137 138 // unpackEface converts the empty interface i to a Value. 139 func unpackEface(i any) Value { 140 e := (*emptyInterface)(unsafe.Pointer(&i)) 141 // NOTE: don't read e.word until we know whether it is really a pointer or not. 142 t := e.typ 143 if t == nil { 144 return Value{} 145 } 146 f := flag(t.Kind()) 147 if ifaceIndir(t) { 148 f |= flagIndir 149 } 150 return Value{t, e.word, f} 151 } 152 153 // A ValueError occurs when a Value method is invoked on 154 // a Value that does not support it. Such cases are documented 155 // in the description of each method. 156 type ValueError struct { 157 Method string 158 Kind Kind 159 } 160 161 func (e *ValueError) Error() string { 162 if e.Kind == 0 { 163 return "reflect: call of " + e.Method + " on zero Value" 164 } 165 return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value" 166 } 167 168 // methodName returns the name of the calling method, 169 // assumed to be two stack frames above. 170 func methodName() string { 171 pc, _, _, _ := runtime.Caller(2) 172 f := runtime.FuncForPC(pc) 173 if f == nil { 174 return "unknown method" 175 } 176 return f.Name() 177 } 178 179 // emptyInterface is the header for an interface{} value. 180 type emptyInterface struct { 181 typ *rtype 182 word unsafe.Pointer 183 } 184 185 // mustBeExported panics if f records that the value was obtained using 186 // an unexported field. 187 func (f flag) mustBeExported() { 188 if f == 0 { 189 panic(&ValueError{methodName(), 0}) 190 } 191 if f&flagRO != 0 { 192 panic("reflect: " + methodName() + " using value obtained using unexported field") 193 } 194 } 195 196 // mustBeAssignable panics if f records that the value is not assignable, 197 // which is to say that either it was obtained using an unexported field 198 // or it is not addressable. 199 func (f flag) mustBeAssignable() { 200 if f == 0 { 201 panic(&ValueError{methodName(), Invalid}) 202 } 203 // Assignable if addressable and not read-only. 204 if f&flagRO != 0 { 205 panic("reflect: " + methodName() + " using value obtained using unexported field") 206 } 207 if f&flagAddr == 0 { 208 panic("reflect: " + methodName() + " using unaddressable value") 209 } 210 } 211 212 // CanSet reports whether the value of v can be changed. 213 // A Value can be changed only if it is addressable and was not 214 // obtained by the use of unexported struct fields. 215 // If CanSet returns false, calling Set or any type-specific 216 // setter (e.g., SetBool, SetInt) will panic. 217 func (v Value) CanSet() bool { 218 return v.flag&(flagAddr|flagRO) == flagAddr 219 } 220 221 // Elem returns the value that the interface v contains 222 // or that the pointer v points to. 223 // It panics if v's Kind is not Interface or Pointer. 224 // It returns the zero Value if v is nil. 225 func (v Value) Elem() Value { 226 k := v.kind() 227 switch k { 228 case Interface: 229 var eface any 230 if v.typ.NumMethod() == 0 { 231 eface = *(*any)(v.ptr) 232 } else { 233 eface = (any)(*(*interface { 234 M() 235 })(v.ptr)) 236 } 237 x := unpackEface(eface) 238 if x.flag != 0 { 239 x.flag |= v.flag.ro() 240 } 241 return x 242 case Pointer: 243 ptr := v.ptr 244 if v.flag&flagIndir != 0 { 245 ptr = *(*unsafe.Pointer)(ptr) 246 } 247 // The returned value's address is v's value. 248 if ptr == nil { 249 return Value{} 250 } 251 tt := (*ptrType)(unsafe.Pointer(v.typ)) 252 typ := tt.elem 253 fl := v.flag&flagRO | flagIndir | flagAddr 254 fl |= flag(typ.Kind()) 255 return Value{typ, ptr, fl} 256 } 257 panic(&ValueError{"reflectlite.Value.Elem", v.kind()}) 258 } 259 260 func valueInterface(v Value) any { 261 if v.flag == 0 { 262 panic(&ValueError{"reflectlite.Value.Interface", 0}) 263 } 264 265 if v.kind() == Interface { 266 // Special case: return the element inside the interface. 267 // Empty interface has one layout, all interfaces with 268 // methods have a second layout. 269 if v.numMethod() == 0 { 270 return *(*any)(v.ptr) 271 } 272 return *(*interface { 273 M() 274 })(v.ptr) 275 } 276 277 // TODO: pass safe to packEface so we don't need to copy if safe==true? 278 return packEface(v) 279 } 280 281 // IsNil reports whether its argument v is nil. The argument must be 282 // a chan, func, interface, map, pointer, or slice value; if it is 283 // not, IsNil panics. Note that IsNil is not always equivalent to a 284 // regular comparison with nil in Go. For example, if v was created 285 // by calling ValueOf with an uninitialized interface variable i, 286 // i==nil will be true but v.IsNil will panic as v will be the zero 287 // Value. 288 func (v Value) IsNil() bool { 289 k := v.kind() 290 switch k { 291 case Chan, Func, Map, Pointer, UnsafePointer: 292 // if v.flag&flagMethod != 0 { 293 // return false 294 // } 295 ptr := v.ptr 296 if v.flag&flagIndir != 0 { 297 ptr = *(*unsafe.Pointer)(ptr) 298 } 299 return ptr == nil 300 case Interface, Slice: 301 // Both interface and slice are nil if first word is 0. 302 // Both are always bigger than a word; assume flagIndir. 303 return *(*unsafe.Pointer)(v.ptr) == nil 304 } 305 panic(&ValueError{"reflectlite.Value.IsNil", v.kind()}) 306 } 307 308 // IsValid reports whether v represents a value. 309 // It returns false if v is the zero Value. 310 // If IsValid returns false, all other methods except String panic. 311 // Most functions and methods never return an invalid Value. 312 // If one does, its documentation states the conditions explicitly. 313 func (v Value) IsValid() bool { 314 return v.flag != 0 315 } 316 317 // Kind returns v's Kind. 318 // If v is the zero Value (IsValid returns false), Kind returns Invalid. 319 func (v Value) Kind() Kind { 320 return v.kind() 321 } 322 323 // implemented in runtime: 324 func chanlen(unsafe.Pointer) int 325 func maplen(unsafe.Pointer) int 326 327 // Len returns v's length. 328 // It panics if v's Kind is not Array, Chan, Map, Slice, or String. 329 func (v Value) Len() int { 330 k := v.kind() 331 switch k { 332 case Array: 333 tt := (*arrayType)(unsafe.Pointer(v.typ)) 334 return int(tt.len) 335 case Chan: 336 return chanlen(v.pointer()) 337 case Map: 338 return maplen(v.pointer()) 339 case Slice: 340 // Slice is bigger than a word; assume flagIndir. 341 return (*unsafeheader.Slice)(v.ptr).Len 342 case String: 343 // String is bigger than a word; assume flagIndir. 344 return (*unsafeheader.String)(v.ptr).Len 345 } 346 panic(&ValueError{"reflect.Value.Len", v.kind()}) 347 } 348 349 // NumMethod returns the number of exported methods in the value's method set. 350 func (v Value) numMethod() int { 351 if v.typ == nil { 352 panic(&ValueError{"reflectlite.Value.NumMethod", Invalid}) 353 } 354 return v.typ.NumMethod() 355 } 356 357 // Set assigns x to the value v. 358 // It panics if CanSet returns false. 359 // As in Go, x's value must be assignable to v's type. 360 func (v Value) Set(x Value) { 361 v.mustBeAssignable() 362 x.mustBeExported() // do not let unexported x leak 363 var target unsafe.Pointer 364 if v.kind() == Interface { 365 target = v.ptr 366 } 367 x = x.assignTo("reflectlite.Set", v.typ, target) 368 if x.flag&flagIndir != 0 { 369 typedmemmove(v.typ, v.ptr, x.ptr) 370 } else { 371 *(*unsafe.Pointer)(v.ptr) = x.ptr 372 } 373 } 374 375 // Type returns v's type. 376 func (v Value) Type() Type { 377 f := v.flag 378 if f == 0 { 379 panic(&ValueError{"reflectlite.Value.Type", Invalid}) 380 } 381 // Method values not supported. 382 return v.typ 383 } 384 385 /* 386 * constructors 387 */ 388 389 // implemented in package runtime 390 func unsafe_New(*rtype) unsafe.Pointer 391 392 // ValueOf returns a new Value initialized to the concrete value 393 // stored in the interface i. ValueOf(nil) returns the zero Value. 394 func ValueOf(i any) Value { 395 if i == nil { 396 return Value{} 397 } 398 399 // TODO: Maybe allow contents of a Value to live on the stack. 400 // For now we make the contents always escape to the heap. It 401 // makes life easier in a few places (see chanrecv/mapassign 402 // comment below). 403 escapes(i) 404 405 return unpackEface(i) 406 } 407 408 // assignTo returns a value v that can be assigned directly to typ. 409 // It panics if v is not assignable to typ. 410 // For a conversion to an interface type, target is a suggested scratch space to use. 411 func (v Value) assignTo(context string, dst *rtype, target unsafe.Pointer) Value { 412 // if v.flag&flagMethod != 0 { 413 // v = makeMethodValue(context, v) 414 // } 415 416 switch { 417 case directlyAssignable(dst, v.typ): 418 // Overwrite type so that they match. 419 // Same memory layout, so no harm done. 420 fl := v.flag&(flagAddr|flagIndir) | v.flag.ro() 421 fl |= flag(dst.Kind()) 422 return Value{dst, v.ptr, fl} 423 424 case implements(dst, v.typ): 425 if target == nil { 426 target = unsafe_New(dst) 427 } 428 if v.Kind() == Interface && v.IsNil() { 429 // A nil ReadWriter passed to nil Reader is OK, 430 // but using ifaceE2I below will panic. 431 // Avoid the panic by returning a nil dst (e.g., Reader) explicitly. 432 return Value{dst, nil, flag(Interface)} 433 } 434 x := valueInterface(v) 435 if dst.NumMethod() == 0 { 436 *(*any)(target) = x 437 } else { 438 ifaceE2I(dst, x, target) 439 } 440 return Value{dst, target, flagIndir | flag(Interface)} 441 } 442 443 // Failed. 444 panic(context + ": value of type " + v.typ.String() + " is not assignable to type " + dst.String()) 445 } 446 447 // arrayAt returns the i-th element of p, 448 // an array whose elements are eltSize bytes wide. 449 // The array pointed at by p must have at least i+1 elements: 450 // it is invalid (but impossible to check here) to pass i >= len, 451 // because then the result will point outside the array. 452 // whySafe must explain why i < len. (Passing "i < len" is fine; 453 // the benefit is to surface this assumption at the call site.) 454 func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Pointer { 455 return add(p, uintptr(i)*eltSize, "i < len") 456 } 457 458 func ifaceE2I(t *rtype, src any, dst unsafe.Pointer) 459 460 // typedmemmove copies a value of type t to dst from src. 461 //go:noescape 462 func typedmemmove(t *rtype, dst, src unsafe.Pointer) 463 464 // Dummy annotation marking that the value x escapes, 465 // for use in cases where the reflect code is so clever that 466 // the compiler cannot follow. 467 func escapes(x any) { 468 if dummy.b { 469 dummy.x = x 470 } 471 } 472 473 var dummy struct { 474 b bool 475 x any 476 } 477