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/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.
    36  type 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  
    66  type flag uintptr
    67  
    68  const (
    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  
    80  func (f flag) kind() Kind {
    81  	return Kind(f & flagKindMask)
    82  }
    83  
    84  func (f flag) ro() flag {
    85  	if f&flagRO != 0 {
    86  		return flagStickyRO
    87  	}
    88  	return 0
    89  }
    90  
    91  func (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)(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
   102  func (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.
   113  func packEface(v Value) any {
   114  	t := v.typ()
   115  	var i any
   116  	e := (*emptyInterface)(unsafe.Pointer(&i))
   117  	// First, fill in the data portion of the interface.
   118  	switch {
   119  	case ifaceIndir(t):
   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  			// TODO: pass safe boolean from valueInterface so
   127  			// we don't need to copy if safe==true?
   128  			c := unsafe_New(t)
   129  			typedmemmove(t, c, ptr)
   130  			ptr = c
   131  		}
   132  		e.word = ptr
   133  	case v.flag&flagIndir != 0:
   134  		// Value is indirect, but interface is direct. We need
   135  		// to load the data at v.ptr into the interface data word.
   136  		e.word = *(*unsafe.Pointer)(v.ptr)
   137  	default:
   138  		// Value is direct, and so is the interface.
   139  		e.word = v.ptr
   140  	}
   141  	// Now, fill in the type portion. We're very careful here not
   142  	// to have any operation between the e.word and e.typ assignments
   143  	// that would let the garbage collector observe the partially-built
   144  	// interface value.
   145  	e.typ = t
   146  	return i
   147  }
   148  
   149  // unpackEface converts the empty interface i to a Value.
   150  func unpackEface(i any) Value {
   151  	e := (*emptyInterface)(unsafe.Pointer(&i))
   152  	// NOTE: don't read e.word until we know whether it is really a pointer or not.
   153  	t := e.typ
   154  	if t == nil {
   155  		return Value{}
   156  	}
   157  	f := flag(t.Kind())
   158  	if ifaceIndir(t) {
   159  		f |= flagIndir
   160  	}
   161  	return Value{t, e.word, f}
   162  }
   163  
   164  // A ValueError occurs when a Value method is invoked on
   165  // a Value that does not support it. Such cases are documented
   166  // in the description of each method.
   167  type ValueError struct {
   168  	Method string
   169  	Kind   Kind
   170  }
   171  
   172  func (e *ValueError) Error() string {
   173  	if e.Kind == 0 {
   174  		return "reflect: call of " + e.Method + " on zero Value"
   175  	}
   176  	return "reflect: call of " + e.Method + " on " + e.Kind.String() + " Value"
   177  }
   178  
   179  // methodName returns the name of the calling method,
   180  // assumed to be two stack frames above.
   181  func methodName() string {
   182  	pc, _, _, _ := runtime.Caller(2)
   183  	f := runtime.FuncForPC(pc)
   184  	if f == nil {
   185  		return "unknown method"
   186  	}
   187  	return f.Name()
   188  }
   189  
   190  // emptyInterface is the header for an interface{} value.
   191  type emptyInterface struct {
   192  	typ  *abi.Type
   193  	word unsafe.Pointer
   194  }
   195  
   196  // mustBeExported panics if f records that the value was obtained using
   197  // an unexported field.
   198  func (f flag) mustBeExported() {
   199  	if f == 0 {
   200  		panic(&ValueError{methodName(), 0})
   201  	}
   202  	if f&flagRO != 0 {
   203  		panic("reflect: " + methodName() + " using value obtained using unexported field")
   204  	}
   205  }
   206  
   207  // mustBeAssignable panics if f records that the value is not assignable,
   208  // which is to say that either it was obtained using an unexported field
   209  // or it is not addressable.
   210  func (f flag) mustBeAssignable() {
   211  	if f == 0 {
   212  		panic(&ValueError{methodName(), abi.Invalid})
   213  	}
   214  	// Assignable if addressable and not read-only.
   215  	if f&flagRO != 0 {
   216  		panic("reflect: " + methodName() + " using value obtained using unexported field")
   217  	}
   218  	if f&flagAddr == 0 {
   219  		panic("reflect: " + methodName() + " using unaddressable value")
   220  	}
   221  }
   222  
   223  // CanSet reports whether the value of v can be changed.
   224  // A Value can be changed only if it is addressable and was not
   225  // obtained by the use of unexported struct fields.
   226  // If CanSet returns false, calling Set or any type-specific
   227  // setter (e.g., SetBool, SetInt) will panic.
   228  func (v Value) CanSet() bool {
   229  	return v.flag&(flagAddr|flagRO) == flagAddr
   230  }
   231  
   232  // Elem returns the value that the interface v contains
   233  // or that the pointer v points to.
   234  // It panics if v's Kind is not Interface or Pointer.
   235  // It returns the zero Value if v is nil.
   236  func (v Value) Elem() Value {
   237  	k := v.kind()
   238  	switch k {
   239  	case abi.Interface:
   240  		var eface any
   241  		if v.typ().NumMethod() == 0 {
   242  			eface = *(*any)(v.ptr)
   243  		} else {
   244  			eface = (any)(*(*interface {
   245  				M()
   246  			})(v.ptr))
   247  		}
   248  		x := unpackEface(eface)
   249  		if x.flag != 0 {
   250  			x.flag |= v.flag.ro()
   251  		}
   252  		return x
   253  	case abi.Pointer:
   254  		ptr := v.ptr
   255  		if v.flag&flagIndir != 0 {
   256  			ptr = *(*unsafe.Pointer)(ptr)
   257  		}
   258  		// The returned value's address is v's value.
   259  		if ptr == nil {
   260  			return Value{}
   261  		}
   262  		tt := (*ptrType)(unsafe.Pointer(v.typ()))
   263  		typ := tt.Elem
   264  		fl := v.flag&flagRO | flagIndir | flagAddr
   265  		fl |= flag(typ.Kind())
   266  		return Value{typ, ptr, fl}
   267  	}
   268  	panic(&ValueError{"reflectlite.Value.Elem", v.kind()})
   269  }
   270  
   271  func valueInterface(v Value) any {
   272  	if v.flag == 0 {
   273  		panic(&ValueError{"reflectlite.Value.Interface", 0})
   274  	}
   275  
   276  	if v.kind() == abi.Interface {
   277  		// Special case: return the element inside the interface.
   278  		// Empty interface has one layout, all interfaces with
   279  		// methods have a second layout.
   280  		if v.numMethod() == 0 {
   281  			return *(*any)(v.ptr)
   282  		}
   283  		return *(*interface {
   284  			M()
   285  		})(v.ptr)
   286  	}
   287  
   288  	// TODO: pass safe to packEface so we don't need to copy if safe==true?
   289  	return packEface(v)
   290  }
   291  
   292  // IsNil reports whether its argument v is nil. The argument must be
   293  // a chan, func, interface, map, pointer, or slice value; if it is
   294  // not, IsNil panics. Note that IsNil is not always equivalent to a
   295  // regular comparison with nil in Go. For example, if v was created
   296  // by calling ValueOf with an uninitialized interface variable i,
   297  // i==nil will be true but v.IsNil will panic as v will be the zero
   298  // Value.
   299  func (v Value) IsNil() bool {
   300  	k := v.kind()
   301  	switch k {
   302  	case abi.Chan, abi.Func, abi.Map, abi.Pointer, abi.UnsafePointer:
   303  		// if v.flag&flagMethod != 0 {
   304  		// 	return false
   305  		// }
   306  		ptr := v.ptr
   307  		if v.flag&flagIndir != 0 {
   308  			ptr = *(*unsafe.Pointer)(ptr)
   309  		}
   310  		return ptr == nil
   311  	case abi.Interface, abi.Slice:
   312  		// Both interface and slice are nil if first word is 0.
   313  		// Both are always bigger than a word; assume flagIndir.
   314  		return *(*unsafe.Pointer)(v.ptr) == nil
   315  	}
   316  	panic(&ValueError{"reflectlite.Value.IsNil", v.kind()})
   317  }
   318  
   319  // IsValid reports whether v represents a value.
   320  // It returns false if v is the zero Value.
   321  // If IsValid returns false, all other methods except String panic.
   322  // Most functions and methods never return an invalid Value.
   323  // If one does, its documentation states the conditions explicitly.
   324  func (v Value) IsValid() bool {
   325  	return v.flag != 0
   326  }
   327  
   328  // Kind returns v's Kind.
   329  // If v is the zero Value (IsValid returns false), Kind returns Invalid.
   330  func (v Value) Kind() Kind {
   331  	return v.kind()
   332  }
   333  
   334  // implemented in runtime:
   335  
   336  //go:noescape
   337  func chanlen(unsafe.Pointer) int
   338  
   339  //go:noescape
   340  func maplen(unsafe.Pointer) int
   341  
   342  // Len returns v's length.
   343  // It panics if v's Kind is not Array, Chan, Map, Slice, or String.
   344  func (v Value) Len() int {
   345  	k := v.kind()
   346  	switch k {
   347  	case abi.Array:
   348  		tt := (*arrayType)(unsafe.Pointer(v.typ()))
   349  		return int(tt.Len)
   350  	case abi.Chan:
   351  		return chanlen(v.pointer())
   352  	case abi.Map:
   353  		return maplen(v.pointer())
   354  	case abi.Slice:
   355  		// Slice is bigger than a word; assume flagIndir.
   356  		return (*unsafeheader.Slice)(v.ptr).Len
   357  	case abi.String:
   358  		// String is bigger than a word; assume flagIndir.
   359  		return (*unsafeheader.String)(v.ptr).Len
   360  	}
   361  	panic(&ValueError{"reflect.Value.Len", v.kind()})
   362  }
   363  
   364  // NumMethod returns the number of exported methods in the value's method set.
   365  func (v Value) numMethod() int {
   366  	if v.typ() == nil {
   367  		panic(&ValueError{"reflectlite.Value.NumMethod", abi.Invalid})
   368  	}
   369  	return v.typ().NumMethod()
   370  }
   371  
   372  // Set assigns x to the value v.
   373  // It panics if CanSet returns false.
   374  // As in Go, x's value must be assignable to v's type.
   375  func (v Value) Set(x Value) {
   376  	v.mustBeAssignable()
   377  	x.mustBeExported() // do not let unexported x leak
   378  	var target unsafe.Pointer
   379  	if v.kind() == abi.Interface {
   380  		target = v.ptr
   381  	}
   382  	x = x.assignTo("reflectlite.Set", v.typ(), target)
   383  	if x.flag&flagIndir != 0 {
   384  		typedmemmove(v.typ(), v.ptr, x.ptr)
   385  	} else {
   386  		*(*unsafe.Pointer)(v.ptr) = x.ptr
   387  	}
   388  }
   389  
   390  // Type returns v's type.
   391  func (v Value) Type() Type {
   392  	f := v.flag
   393  	if f == 0 {
   394  		panic(&ValueError{"reflectlite.Value.Type", abi.Invalid})
   395  	}
   396  	// Method values not supported.
   397  	return toRType(v.typ())
   398  }
   399  
   400  /*
   401   * constructors
   402   */
   403  
   404  // implemented in package runtime
   405  
   406  //go:noescape
   407  func unsafe_New(*abi.Type) unsafe.Pointer
   408  
   409  // ValueOf returns a new Value initialized to the concrete value
   410  // stored in the interface i. ValueOf(nil) returns the zero Value.
   411  func ValueOf(i any) Value {
   412  	if i == nil {
   413  		return Value{}
   414  	}
   415  	return unpackEface(i)
   416  }
   417  
   418  // assignTo returns a value v that can be assigned directly to typ.
   419  // It panics if v is not assignable to typ.
   420  // For a conversion to an interface type, target is a suggested scratch space to use.
   421  func (v Value) assignTo(context string, dst *abi.Type, target unsafe.Pointer) Value {
   422  	// if v.flag&flagMethod != 0 {
   423  	// 	v = makeMethodValue(context, v)
   424  	// }
   425  
   426  	switch {
   427  	case directlyAssignable(dst, v.typ()):
   428  		// Overwrite type so that they match.
   429  		// Same memory layout, so no harm done.
   430  		fl := v.flag&(flagAddr|flagIndir) | v.flag.ro()
   431  		fl |= flag(dst.Kind())
   432  		return Value{dst, v.ptr, fl}
   433  
   434  	case implements(dst, v.typ()):
   435  		if target == nil {
   436  			target = unsafe_New(dst)
   437  		}
   438  		if v.Kind() == abi.Interface && v.IsNil() {
   439  			// A nil ReadWriter passed to nil Reader is OK,
   440  			// but using ifaceE2I below will panic.
   441  			// Avoid the panic by returning a nil dst (e.g., Reader) explicitly.
   442  			return Value{dst, nil, flag(abi.Interface)}
   443  		}
   444  		x := valueInterface(v)
   445  		if dst.NumMethod() == 0 {
   446  			*(*any)(target) = x
   447  		} else {
   448  			ifaceE2I(dst, x, target)
   449  		}
   450  		return Value{dst, target, flagIndir | flag(abi.Interface)}
   451  	}
   452  
   453  	// Failed.
   454  	panic(context + ": value of type " + toRType(v.typ()).String() + " is not assignable to type " + toRType(dst).String())
   455  }
   456  
   457  // arrayAt returns the i-th element of p,
   458  // an array whose elements are eltSize bytes wide.
   459  // The array pointed at by p must have at least i+1 elements:
   460  // it is invalid (but impossible to check here) to pass i >= len,
   461  // because then the result will point outside the array.
   462  // whySafe must explain why i < len. (Passing "i < len" is fine;
   463  // the benefit is to surface this assumption at the call site.)
   464  func arrayAt(p unsafe.Pointer, i int, eltSize uintptr, whySafe string) unsafe.Pointer {
   465  	return add(p, uintptr(i)*eltSize, "i < len")
   466  }
   467  
   468  func ifaceE2I(t *abi.Type, src any, dst unsafe.Pointer)
   469  
   470  // typedmemmove copies a value of type t to dst from src.
   471  //
   472  //go:noescape
   473  func typedmemmove(t *abi.Type, dst, src unsafe.Pointer)
   474  
   475  // Dummy annotation marking that the value x escapes,
   476  // for use in cases where the reflect code is so clever that
   477  // the compiler cannot follow.
   478  func escapes(x any) {
   479  	if dummy.b {
   480  		dummy.x = x
   481  	}
   482  }
   483  
   484  var dummy struct {
   485  	b bool
   486  	x any
   487  }
   488  
   489  //go:nosplit
   490  func noescape(p unsafe.Pointer) unsafe.Pointer {
   491  	x := uintptr(p)
   492  	return unsafe.Pointer(x ^ 0)
   493  }
   494  

View as plain text