]> Cypherpunks repositories - gostls13.git/commitdiff
unique: handle zero-size types
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Mon, 16 Sep 2024 16:58:40 +0000 (23:58 +0700)
committerGopher Robot <gobot@golang.org>
Mon, 16 Sep 2024 20:25:08 +0000 (20:25 +0000)
Fixes #69458

Change-Id: Ic7fda7f556522780b2819138dfc1277137398692
Reviewed-on: https://go-review.googlesource.com/c/go/+/613397
Reviewed-by: Carlos Amedee <carlos@golang.org>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Auto-Submit: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Reviewed-by: Michael Knyszek <mknyszek@google.com>
src/unique/handle.go
src/unique/handle_test.go

index abc620f60fe14e49f9fc57f7d253f599a40a27a2..6912e2a2dac745476f814794ed0bd2b8ad6c0ef8 100644 (file)
@@ -10,9 +10,11 @@ import (
        "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
@@ -32,6 +34,9 @@ func (h Handle[T]) Value() T {
 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
index 7d12edd4679f5bb6f0e1d408c9809ac8e2c898ee..98a1b731cfad5680c6ae800183cdc41c35452ca6 100644 (file)
@@ -31,6 +31,7 @@ type testStruct struct {
        z float64
        b string
 }
+type testZeroSize struct{}
 
 func TestHandle(t *testing.T) {
        testHandle(t, testString("foo"))
@@ -45,6 +46,7 @@ func TestHandle(t *testing.T) {
        })
        testHandle(t, testStruct{0.5, "184"})
        testHandle(t, testEface("hello"))
+       testHandle(t, testZeroSize(struct{}{}))
 }
 
 func testHandle[T comparable](t *testing.T, value T) {
@@ -65,15 +67,19 @@ 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.