Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 2 additions & 8 deletions src/internal/reflectlite/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -453,10 +453,7 @@ func rawStructFieldFromPointer(descriptor *structType, fieldType *RawType, data
data = unsafe.Add(data, 1) // C: data+1
tagLen := uintptr(*(*byte)(data))
data = unsafe.Add(data, 1) // C: data+1
tag = *(*string)(unsafe.Pointer(&stringHeader{
data: data,
len: tagLen,
}))
tag = unsafe.String((*byte)(data), tagLen)
}

// Set the PkgPath to some (arbitrary) value if the package path is not
Expand Down Expand Up @@ -930,10 +927,7 @@ func readStringZ(data unsafe.Pointer) string {
data = unsafe.Add(data, 1) // C: data++
}

return *(*string)(unsafe.Pointer(&stringHeader{
data: start,
len: len,
}))
return unsafe.String((*byte)(start), len)
}

func (t *RawType) name() string {
Expand Down
50 changes: 15 additions & 35 deletions src/internal/reflectlite/value.go
Original file line number Diff line number Diff line change
Expand Up @@ -713,20 +713,12 @@ func (v Value) Slice(i, j int) Value {

case String:
i, j := uintptr(i), uintptr(j)
str := *(*stringHeader)(v.value)

if j < i || str.len < j {
slicePanic()
}

hdr := stringHeader{
data: unsafe.Add(str.data, i),
len: j - i,
}
str := *(*string)(v.value)
sliced := str[i:j]

return Value{
typecode: v.typecode,
value: unsafe.Pointer(&hdr),
value: unsafe.Pointer(&sliced),
flags: v.flags,
}
}
Expand Down Expand Up @@ -801,7 +793,7 @@ func (v Value) Len() int {
case Slice:
return int((*sliceHeader)(v.value).len)
case String:
return int((*stringHeader)(v.value).len)
return len(*(*string)(v.value))
default:
panic(&ValueError{Method: "Len", Kind: v.Kind()})
}
Expand Down Expand Up @@ -977,13 +969,10 @@ func (v Value) Index(i int) Value {
// Keeping valueFlagExported if set, but don't set valueFlagIndirect
// otherwise CanSet will return true for string elements (which is bad,
// strings are read-only).
s := *(*stringHeader)(v.value)
if uint(i) >= uint(s.len) {
panic("reflect: string index out of range")
}
s := *(*string)(v.value)
return Value{
typecode: uint8Type,
value: unsafe.Pointer(uintptr(*(*uint8)(unsafe.Add(s.data, i)))),
value: unsafe.Pointer(uintptr(s[i])),
Copy link
Copy Markdown
Contributor

@eliasnaur eliasnaur May 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be unsafe.Pointer(uintptr(&s[i]))? Also, can the uintptr intermediate cast be replaced with unsafe.Pointer(unsafe.StringData(s[i:]))?

Copy link
Copy Markdown
Member Author

@aykevl aykevl May 11, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. It's a string index operation (not a slice operation), so it returns the byte at the given index in the string. Since it's just a single byte, it's stored directly in the Value.value field.

flags: v.flags & valueFlagExported,
}
case Array:
Expand Down Expand Up @@ -1714,8 +1703,7 @@ const zerobufferLen = 32
func init() {
// 32 characters of zero bytes
zerobufferStr := "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
s := (*stringHeader)(unsafe.Pointer(&zerobufferStr))
zerobuffer = s.data
zerobuffer = unsafe.Pointer(unsafe.StringData(zerobufferStr))
}

func Zero(typ Type) Value {
Expand Down Expand Up @@ -1766,19 +1754,11 @@ type sliceHeader struct {
cap uintptr
}

// Like sliceHeader, this type is used internally to make sure pointer and
// non-pointer fields match those of actual strings.
type stringHeader struct {
data unsafe.Pointer
len uintptr
}

// Verify SliceHeader and StringHeader sizes.
// Verify SliceHeader size.
// See https://github.com/tinygo-org/tinygo/pull/4156
// and https://github.com/tinygo-org/tinygo/issues/1284.
var (
_ [unsafe.Sizeof([]byte{})]byte = [unsafe.Sizeof(sliceHeader{})]byte{}
_ [unsafe.Sizeof("")]byte = [unsafe.Sizeof(stringHeader{})]byte{}
)

type ValueError struct {
Expand Down Expand Up @@ -1845,29 +1825,29 @@ func Copy(dst, src Value) int {

func buflen(v Value) (unsafe.Pointer, uintptr) {
var buf unsafe.Pointer
var len uintptr
var length uintptr
switch v.typecode.Kind() {
case Slice:
hdr := (*sliceHeader)(v.value)
buf = hdr.data
len = hdr.len
length = hdr.len
case Array:
if v.isIndirect() || v.typecode.Size() > unsafe.Sizeof(uintptr(0)) {
buf = v.value
} else {
buf = unsafe.Pointer(&v.value)
}
len = uintptr(v.Len())
length = uintptr(v.Len())
case String:
hdr := (*stringHeader)(v.value)
buf = hdr.data
len = hdr.len
s := *(*string)(v.value)
buf = unsafe.Pointer(unsafe.StringData(s))
length = uintptr(len(s))
default:
// This shouldn't happen
panic("reflect.Copy: not slice or array or string")
}

return buf, len
return buf, length
}

//go:linkname sliceGrow runtime.sliceGrow
Expand Down
Loading