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