"internal/weak"
"runtime"
"sync"
- _ "unsafe"
+ "unsafe"
)
+var zero uintptr
+
// Handle is a globally unique identity for some value of type T.
//
// Two handles compare equal exactly if the two values used to create the handles
func Make[T comparable](value T) Handle[T] {
// Find the map for type T.
typ := abi.TypeFor[T]()
+ if typ.Size() == 0 {
+ return Handle[T]{(*T)(unsafe.Pointer(&zero))}
+ }
ma, ok := uniqueMaps.Load(typ)
if !ok {
// This is a good time to initialize cleanup, since we must go through
z float64
b string
}
+type testZeroSize struct{}
func TestHandle(t *testing.T) {
testHandle(t, testString("foo"))
})
testHandle(t, testStruct{0.5, "184"})
testHandle(t, testEface("hello"))
+ testHandle(t, testZeroSize(struct{}{}))
}
func testHandle[T comparable](t *testing.T, value T) {
t.Error("v0 != v1")
}
- drainMaps(t)
+ drainMaps[T](t)
checkMapsFor(t, value)
})
}
// drainMaps ensures that the internal maps are drained.
-func drainMaps(t *testing.T) {
+func drainMaps[T comparable](t *testing.T) {
t.Helper()
+ if unsafe.Sizeof(*(new(T))) == 0 {
+ return // zero-size types are not inserted.
+ }
+
wait := make(chan struct{}, 1)
// Set up a one-time notification for the next time the cleanup runs.