src/weak/pointer.go | 5 ++++- src/weak/pointer_test.go | 10 ++++++++++ test/weak.go | 24 ++++++++++++++++++++++++ diff --git a/src/weak/pointer.go b/src/weak/pointer.go index 39c512e76d6fe463a2e341ca925e7e8dd4e5ad3a..e9d7420880a7f92105a33a23446d08224090ef9d 100644 --- a/src/weak/pointer.go +++ b/src/weak/pointer.go @@ -56,6 +56,9 @@ // allocation may never become nil if it always exists in the same batch as a // referenced object. Typically, this batching only happens for tiny // (on the order of 16 bytes or less) and pointer-free objects. type Pointer[T any] struct { + // Mention T in the type definition to prevent conversions + // between Pointer types, like we do for sync/atomic.Pointer. + _ [0]*T u unsafe.Pointer } @@ -69,7 +72,7 @@ if ptr != nil { u = runtime_registerWeakPointer(unsafe.Pointer(ptr)) } runtime.KeepAlive(ptr) - return Pointer[T]{u} + return Pointer[T]{u: u} } // Value returns the original pointer used to create the weak pointer. diff --git a/src/weak/pointer_test.go b/src/weak/pointer_test.go index e0ef30377e9e81cc3952c9938b7a17bccec9a1eb..70c743381cacf869bd228b7ca334392bcbe9e3d5 100644 --- a/src/weak/pointer_test.go +++ b/src/weak/pointer_test.go @@ -6,10 +6,12 @@ package weak_test import ( "context" + "internal/goarch" "runtime" "sync" "testing" "time" + "unsafe" "weak" ) @@ -152,6 +154,14 @@ // The weak pointer should still be nil after the finalizer runs. runtime.GC() if wt.Value() != nil { t.Errorf("weak pointer is non-nil even after finalization: %v", wt) + } +} + +func TestPointerSize(t *testing.T) { + var p weak.Pointer[T] + size := unsafe.Sizeof(p) + if size != goarch.PtrSize { + t.Errorf("weak.Pointer[T] size = %d, want %d", size, goarch.PtrSize) } } diff --git a/test/weak.go b/test/weak.go new file mode 100644 index 0000000000000000000000000000000000000000..ca3ec797fc23662f8192644ea8f3d20be86fd4f2 --- /dev/null +++ b/test/weak.go @@ -0,0 +1,24 @@ +// errorcheck + +// Copyright 2025 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Test weak pointers. + +package p + +import ( + "runtime" + "weak" +) + +// Adapted from example in https://github.com/golang/go/issues/67552#issuecomment-2639661220 +func conversion() { + p := "hello" + a := weak.Make(&p) + b := (weak.Pointer[*byte])(a) // ERROR "cannot convert a \(variable of struct type weak\.Pointer\[string\]\) to type weak.Pointer\[\*byte\]" + c := b.Value() + println(**c) + runtime.KeepAlive(p) +}