From 00be1761b76671635b478a20187d83b166991924 Mon Sep 17 00:00:00 2001 From: Brad Fitzpatrick Date: Mon, 11 Nov 2024 08:48:09 -0800 Subject: [PATCH] util/codegen: treat unique.Handle as an opaque value type It doesn't need a Clone method, like a time.Time, etc. And then, because Go 1.23+ uses unique.Handle internally for the netip package types, we can remove those special cases. Updates #14058 (pulled out from that PR) Updates tailscale/corp#24485 Change-Id: Iac3548a9417ccda5987f98e0305745a6e178b375 Signed-off-by: Brad Fitzpatrick --- util/codegen/codegen.go | 11 ++++++++--- util/codegen/codegen_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/util/codegen/codegen.go b/util/codegen/codegen.go index 2f7781b68..1b3af10e0 100644 --- a/util/codegen/codegen.go +++ b/util/codegen/codegen.go @@ -277,11 +277,16 @@ func IsInvalid(t types.Type) bool { // It has special handling for some types that contain pointers // that we know are free from memory aliasing/mutation concerns. func ContainsPointers(typ types.Type) bool { - switch typ.String() { + s := typ.String() + switch s { case "time.Time": - // time.Time contains a pointer that does not need copying + // time.Time contains a pointer that does not need cloning. return false - case "inet.af/netip.Addr", "net/netip.Addr", "net/netip.Prefix", "net/netip.AddrPort": + case "inet.af/netip.Addr": + return false + } + if strings.HasPrefix(s, "unique.Handle[") { + // unique.Handle contains a pointer that does not need cloning. return false } switch ft := typ.Underlying().(type) { diff --git a/util/codegen/codegen_test.go b/util/codegen/codegen_test.go index 28ddaed2b..74715eeca 100644 --- a/util/codegen/codegen_test.go +++ b/util/codegen/codegen_test.go @@ -10,6 +10,8 @@ import ( "strings" "sync" "testing" + "time" + "unique" "unsafe" "golang.org/x/exp/constraints" @@ -84,6 +86,16 @@ type PointerUnionParam[T netip.Prefix | BasicType | IntPtr] struct { V T } +type StructWithUniqueHandle struct{ _ unique.Handle[[32]byte] } + +type StructWithTime struct{ _ time.Time } + +type StructWithNetipTypes struct { + _ netip.Addr + _ netip.AddrPort + _ netip.Prefix +} + type Interface interface { Method() } @@ -161,6 +173,18 @@ func TestGenericContainsPointers(t *testing.T) { typ: "PointerUnionParam", wantPointer: true, }, + { + typ: "StructWithUniqueHandle", + wantPointer: false, + }, + { + typ: "StructWithTime", + wantPointer: false, + }, + { + typ: "StructWithNetipTypes", + wantPointer: false, + }, } for _, tt := range tests {