Description
Consider the following program:
package main
import (
"fmt"
"unsafe"
)
func indir[T any]() bool {
var z T
y := any(z)
type iface struct {
itab uintptr
ptr unsafe.Pointer
}
p := (*iface)(unsafe.Pointer(&y)).ptr
return p != nil
}
func main() {
fmt.Println(
indir[int](),
indir[*int](),
indir[map[int]int](),
indir[struct{ _ *int }](),
indir[struct {
_ struct{}
_ *int
}](),
)
}
indir()
returns true if some type would need to allocate to be converted to an any
. It does so by noting that a freshly created non-nil any's data pointer will never be nil if an allocation happened, but it will be nil if it didn't, because x
is all zeros, and in the non-allocating case, this value gets splatted into the data pointer.
This prints true false false false true
. However, there is no reason this could not print true false false false false
, because the last of these types has the same shape as a pointer, and thus can be passed around as the unsafe.Pointer
in an interface value without requiring an allocation, just like is already done for one field structs and arrays of pointer shape.
The change here is essentially applying this to anything that happens to have pointer shape, rather than the current mess of special cases in reflect
(notably this excludes struct{*int; struct{}}
, which is 16, not 8 bytes wide). Whether something has pointer shape is not visible to users, so this optimization shouldn't break anyone except for very naughty unsafe
users like me.
My reason for interest in this is to have the ability to embed zero-size types into a struct, to simplify the implementation of interfaces with large method sets, or embedding e.g. _ [0]sync.Mutex
to get govet to do the right thing, a fairly common idiom in concurrency primitives (again, a thing I wind up doing a lot).
I'm not expecting this to get fixed any time soon, because of repercussions across runtime
, reflect
, and internal/abi
, but I wanted to write this up because it's a thorn in my side right now.
Metadata
Metadata
Assignees
Labels
Type
Projects
Status