mirror of
https://github.com/golang/go
synced 2024-11-22 03:04:41 -07:00
unique: use TypeFor instead of TypeOf to get type in Make
Currently the first thing Make does it get the abi.Type of its argument, and uses abi.TypeOf to do it. However, this has a problem for interface types, since the type of the value stored in the interface value will bleed through. This is a classic reflection mistake. Fix this by implementing and using a generic TypeFor which matches reflect.TypeFor. This gets the type of the type parameter, which is far less ambiguous and error-prone. Fixes #68990. Change-Id: Idd8d9a1095ef017e9cd7c7779314f7d4034f01a7 Reviewed-on: https://go-review.googlesource.com/c/go/+/607355 Reviewed-by: David Chase <drchase@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
f38d42f2c4
commit
755c18ecdf
@ -177,6 +177,15 @@ func TypeOf(a any) *Type {
|
||||
return (*Type)(NoEscape(unsafe.Pointer(eface.Type)))
|
||||
}
|
||||
|
||||
// TypeFor returns the abi.Type for a type parameter.
|
||||
func TypeFor[T any]() *Type {
|
||||
var v T
|
||||
if t := TypeOf(v); t != nil {
|
||||
return t // optimize for T being a non-interface kind
|
||||
}
|
||||
return TypeOf((*T)(nil)).Elem() // only for an interface kind
|
||||
}
|
||||
|
||||
func (t *Type) Kind() Kind { return t.Kind_ & KindMask }
|
||||
|
||||
func (t *Type) HasName() bool {
|
||||
|
@ -27,7 +27,7 @@ func cSeq(stringOffsets ...uintptr) cloneSeq {
|
||||
|
||||
func testCloneSeq[T any](t *testing.T, want cloneSeq) {
|
||||
typName := reflect.TypeFor[T]().Name()
|
||||
typ := abi.TypeOf(*new(T))
|
||||
typ := abi.TypeFor[T]()
|
||||
t.Run(typName, func(t *testing.T) {
|
||||
got := makeCloneSeq(typ)
|
||||
if !reflect.DeepEqual(got, want) {
|
||||
|
@ -31,7 +31,7 @@ func (h Handle[T]) Value() T {
|
||||
// are equal if and only if the values used to produce them are equal.
|
||||
func Make[T comparable](value T) Handle[T] {
|
||||
// Find the map for type T.
|
||||
typ := abi.TypeOf(value)
|
||||
typ := abi.TypeFor[T]()
|
||||
ma, ok := uniqueMaps.Load(typ)
|
||||
if !ok {
|
||||
// This is a good time to initialize cleanup, since we must go through
|
||||
|
@ -41,6 +41,7 @@ func TestHandle(t *testing.T) {
|
||||
s: [2]testStringStruct{testStringStruct{"y"}, testStringStruct{"z"}},
|
||||
})
|
||||
testHandle[testStruct](t, testStruct{0.5, "184"})
|
||||
testHandle[testEface](t, testEface("hello"))
|
||||
}
|
||||
|
||||
func testHandle[T comparable](t *testing.T, value T) {
|
||||
@ -93,7 +94,7 @@ func drainMaps(t *testing.T) {
|
||||
|
||||
func checkMapsFor[T comparable](t *testing.T, value T) {
|
||||
// Manually load the value out of the map.
|
||||
typ := abi.TypeOf(value)
|
||||
typ := abi.TypeFor[T]()
|
||||
a, ok := uniqueMaps.Load(typ)
|
||||
if !ok {
|
||||
return
|
||||
|
Loading…
Reference in New Issue
Block a user