Black Lives Matter. Support the Equal Justice Initiative.

Source file src/internal/reflectlite/value.go

Documentation: internal/reflectlite

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

View as plain text