all: use reflect.TypeFor now available in Go 1.22 (#11078)

Updates #cleanup

Signed-off-by: Joe Tsai <joetsai@digital-static.net>
This commit is contained in:
Joe Tsai 2024-02-08 17:34:22 -08:00 committed by GitHub
parent efddad7d7d
commit 94a4f701c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
18 changed files with 31 additions and 38 deletions

View File

@ -802,7 +802,7 @@ func TestPrefFlagMapping(t *testing.T) {
} }
} }
prefType := reflect.TypeOf(ipn.Prefs{}) prefType := reflect.TypeFor[ipn.Prefs]()
for i := 0; i < prefType.NumField(); i++ { for i := 0; i < prefType.NumField(); i++ {
prefName := prefType.Field(i).Name prefName := prefType.Field(i).Name
if prefHasFlag[prefName] { if prefHasFlag[prefName] {

View File

@ -726,7 +726,7 @@ func init() {
func addPrefFlagMapping(flagName string, prefNames ...string) { func addPrefFlagMapping(flagName string, prefNames ...string) {
prefsOfFlag[flagName] = prefNames prefsOfFlag[flagName] = prefNames
prefType := reflect.TypeOf(ipn.Prefs{}) prefType := reflect.TypeFor[ipn.Prefs]()
for _, pref := range prefNames { for _, pref := range prefNames {
t := prefType t := prefType
for _, name := range strings.Split(pref, ".") { for _, name := range strings.Split(pref, ".") {

View File

@ -20,7 +20,7 @@ func fieldsOf(t reflect.Type) (fields []string) {
func TestStatusEqual(t *testing.T) { func TestStatusEqual(t *testing.T) {
// Verify that the Equal method stays in sync with reality // Verify that the Equal method stays in sync with reality
equalHandles := []string{"Err", "URL", "NetMap", "Persist", "state"} equalHandles := []string{"Err", "URL", "NetMap", "Persist", "state"}
if have := fieldsOf(reflect.TypeOf(Status{})); !reflect.DeepEqual(have, equalHandles) { if have := fieldsOf(reflect.TypeFor[Status]()); !reflect.DeepEqual(have, equalHandles) {
t.Errorf("Status.Equal check might be out of sync\nfields: %q\nhandled: %q\n", t.Errorf("Status.Equal check might be out of sync\nfields: %q\nhandled: %q\n",
have, equalHandles) have, equalHandles)
} }

View File

@ -538,7 +538,7 @@ var nodeFields = sync.OnceValue(getNodeFields)
// getNodeFields returns the fails of tailcfg.Node. // getNodeFields returns the fails of tailcfg.Node.
func getNodeFields() []string { func getNodeFields() []string {
rt := reflect.TypeOf((*tailcfg.Node)(nil)).Elem() rt := reflect.TypeFor[tailcfg.Node]()
ret := make([]string, rt.NumField()) ret := make([]string, rt.NumField())
for i := 0; i < rt.NumField(); i++ { for i := 0; i < rt.NumField(); i++ {
ret[i] = rt.Field(i).Name ret[i] = rt.Field(i).Name

View File

@ -15,7 +15,7 @@ func TestAsDebugJSON(t *testing.T) {
} }
k := new(Knobs) k := new(Knobs)
got := k.AsDebugJSON() got := k.AsDebugJSON()
if want := reflect.TypeOf(Knobs{}).NumField(); len(got) != want { if want := reflect.TypeFor[Knobs]().NumField(); len(got) != want {
t.Errorf("AsDebugJSON map has %d fields; want %v", len(got), want) t.Errorf("AsDebugJSON map has %d fields; want %v", len(got), want)
} }
} }

View File

@ -64,7 +64,7 @@ func TestPrefsEqual(t *testing.T) {
"NetfilterKind", "NetfilterKind",
"Persist", "Persist",
} }
if have := fieldsOf(reflect.TypeOf(Prefs{})); !reflect.DeepEqual(have, prefsHandles) { if have := fieldsOf(reflect.TypeFor[Prefs]()); !reflect.DeepEqual(have, prefsHandles) {
t.Errorf("Prefs.Equal check might be out of sync\nfields: %q\nhandled: %q\n", t.Errorf("Prefs.Equal check might be out of sync\nfields: %q\nhandled: %q\n",
have, prefsHandles) have, prefsHandles)
} }
@ -615,14 +615,14 @@ func TestLoadPrefsFileWithZeroInIt(t *testing.T) {
func TestMaskedPrefsFields(t *testing.T) { func TestMaskedPrefsFields(t *testing.T) {
have := map[string]bool{} have := map[string]bool{}
for _, f := range fieldsOf(reflect.TypeOf(Prefs{})) { for _, f := range fieldsOf(reflect.TypeFor[Prefs]()) {
if f == "Persist" { if f == "Persist" {
// This one can't be edited. // This one can't be edited.
continue continue
} }
have[f] = true have[f] = true
} }
for _, f := range fieldsOf(reflect.TypeOf(MaskedPrefs{})) { for _, f := range fieldsOf(reflect.TypeFor[MaskedPrefs]()) {
if f == "Prefs" { if f == "Prefs" {
continue continue
} }
@ -644,8 +644,8 @@ func TestMaskedPrefsFields(t *testing.T) {
// And also make sure they line up in the right order, which // And also make sure they line up in the right order, which
// ApplyEdits assumes. // ApplyEdits assumes.
pt := reflect.TypeOf(Prefs{}) pt := reflect.TypeFor[Prefs]()
mt := reflect.TypeOf(MaskedPrefs{}) mt := reflect.TypeFor[MaskedPrefs]()
for i := 0; i < mt.NumField(); i++ { for i := 0; i < mt.NumField(); i++ {
name := mt.Field(i).Name name := mt.Field(i).Name
if i == 0 { if i == 0 {

View File

@ -1154,7 +1154,7 @@ func TestPathFromPAMEnvLineOnNixOS(t *testing.T) {
} }
func TestStdOsUserUserAssumptions(t *testing.T) { func TestStdOsUserUserAssumptions(t *testing.T) {
v := reflect.TypeOf(user.User{}) v := reflect.TypeFor[user.User]()
if got, want := v.NumField(), 5; got != want { if got, want := v.NumField(), 5; got != want {
t.Errorf("os/user.User has %v fields; this package assumes %v", got, want) t.Errorf("os/user.User has %v fields; this package assumes %v", got, want)
} }

View File

@ -67,7 +67,7 @@ func TestHostinfoEqual(t *testing.T) {
"AppConnector", "AppConnector",
"Location", "Location",
} }
if have := fieldsOf(reflect.TypeOf(Hostinfo{})); !reflect.DeepEqual(have, hiHandles) { if have := fieldsOf(reflect.TypeFor[Hostinfo]()); !reflect.DeepEqual(have, hiHandles) {
t.Errorf("Hostinfo.Equal check might be out of sync\nfields: %q\nhandled: %q\n", t.Errorf("Hostinfo.Equal check might be out of sync\nfields: %q\nhandled: %q\n",
have, hiHandles) have, hiHandles)
} }
@ -364,7 +364,7 @@ func TestNodeEqual(t *testing.T) {
"DataPlaneAuditLogID", "Expired", "SelfNodeV4MasqAddrForThisPeer", "DataPlaneAuditLogID", "Expired", "SelfNodeV4MasqAddrForThisPeer",
"SelfNodeV6MasqAddrForThisPeer", "IsWireGuardOnly", "ExitNodeDNSResolvers", "SelfNodeV6MasqAddrForThisPeer", "IsWireGuardOnly", "ExitNodeDNSResolvers",
} }
if have := fieldsOf(reflect.TypeOf(Node{})); !reflect.DeepEqual(have, nodeHandles) { if have := fieldsOf(reflect.TypeFor[Node]()); !reflect.DeepEqual(have, nodeHandles) {
t.Errorf("Node.Equal check might be out of sync\nfields: %q\nhandled: %q\n", t.Errorf("Node.Equal check might be out of sync\nfields: %q\nhandled: %q\n",
have, nodeHandles) have, nodeHandles)
} }
@ -632,7 +632,7 @@ func TestNetInfoFields(t *testing.T) {
"DERPLatency", "DERPLatency",
"FirewallMode", "FirewallMode",
} }
if have := fieldsOf(reflect.TypeOf(NetInfo{})); !reflect.DeepEqual(have, handled) { if have := fieldsOf(reflect.TypeFor[NetInfo]()); !reflect.DeepEqual(have, handled) {
t.Errorf("NetInfo.Clone/BasicallyEqually check might be out of sync\nfields: %q\nhandled: %q\n", t.Errorf("NetInfo.Clone/BasicallyEqually check might be out of sync\nfields: %q\nhandled: %q\n",
have, handled) have, handled)
} }

View File

@ -13,7 +13,7 @@ import (
func TestResolverEqual(t *testing.T) { func TestResolverEqual(t *testing.T) {
var fieldNames []string var fieldNames []string
for _, field := range reflect.VisibleFields(reflect.TypeOf(Resolver{})) { for _, field := range reflect.VisibleFields(reflect.TypeFor[Resolver]()) {
fieldNames = append(fieldNames, field.Name) fieldNames = append(fieldNames, field.Name)
} }
sort.Strings(fieldNames) sort.Strings(fieldNames)

View File

@ -72,7 +72,7 @@ func (m NodeMutationLastSeen) Apply(n *tailcfg.Node) {
var peerChangeFields = sync.OnceValue(func() []reflect.StructField { var peerChangeFields = sync.OnceValue(func() []reflect.StructField {
var fields []reflect.StructField var fields []reflect.StructField
rt := reflect.TypeOf((*tailcfg.PeerChange)(nil)).Elem() rt := reflect.TypeFor[tailcfg.PeerChange]()
for i := 0; i < rt.NumField(); i++ { for i := 0; i < rt.NumField(); i++ {
fields = append(fields, rt.Field(i)) fields = append(fields, rt.Field(i))
} }

View File

@ -27,7 +27,7 @@ func TestMapResponseContainsNonPatchFields(t *testing.T) {
case reflect.Bool: case reflect.Bool:
return reflect.ValueOf(true) return reflect.ValueOf(true)
case reflect.String: case reflect.String:
if reflect.TypeOf(opt.Bool("")) == t { if reflect.TypeFor[opt.Bool]() == t {
return reflect.ValueOf("true").Convert(t) return reflect.ValueOf("true").Convert(t)
} }
return reflect.ValueOf("foo").Convert(t) return reflect.ValueOf("foo").Convert(t)
@ -43,7 +43,7 @@ func TestMapResponseContainsNonPatchFields(t *testing.T) {
panic(fmt.Sprintf("unhandled %v", t)) panic(fmt.Sprintf("unhandled %v", t))
} }
rt := reflect.TypeOf(tailcfg.MapResponse{}) rt := reflect.TypeFor[tailcfg.MapResponse]()
for i := 0; i < rt.NumField(); i++ { for i := 0; i < rt.NumField(); i++ {
f := rt.Field(i) f := rt.Field(i)

View File

@ -22,7 +22,7 @@ func fieldsOf(t reflect.Type) (fields []string) {
func TestPersistEqual(t *testing.T) { func TestPersistEqual(t *testing.T) {
persistHandles := []string{"LegacyFrontendPrivateMachineKey", "PrivateNodeKey", "OldPrivateNodeKey", "Provider", "UserProfile", "NetworkLockKey", "NodeID", "DisallowedTKAStateIDs"} persistHandles := []string{"LegacyFrontendPrivateMachineKey", "PrivateNodeKey", "OldPrivateNodeKey", "Provider", "UserProfile", "NetworkLockKey", "NodeID", "DisallowedTKAStateIDs"}
if have := fieldsOf(reflect.TypeOf(Persist{})); !reflect.DeepEqual(have, persistHandles) { if have := fieldsOf(reflect.TypeFor[Persist]()); !reflect.DeepEqual(have, persistHandles) {
t.Errorf("Persist.Equal check might be out of sync\nfields: %q\nhandled: %q\n", t.Errorf("Persist.Equal check might be out of sync\nfields: %q\nhandled: %q\n",
have, persistHandles) have, persistHandles)
} }

View File

@ -24,11 +24,6 @@ import (
"reflect" "reflect"
) )
// TODO(https://go.dev/issue/60088): Use reflect.TypeFor instead.
func reflectTypeFor[T any]() reflect.Type {
return reflect.TypeOf((*T)(nil)).Elem()
}
// Key is a generic key type associated with a specific value type. // Key is a generic key type associated with a specific value type.
// //
// A zero Key is valid where the Value type itself is used as the context key. // A zero Key is valid where the Value type itself is used as the context key.
@ -65,7 +60,7 @@ func New[Value any](name string, defaultValue Value) Key[Value] {
// since newly allocated pointers are globally unique within a process. // since newly allocated pointers are globally unique within a process.
key := Key[Value]{name: new(stringer[string])} key := Key[Value]{name: new(stringer[string])}
if name == "" { if name == "" {
name = reflectTypeFor[Value]().String() name = reflect.TypeFor[Value]().String()
} }
key.name.v = name key.name.v = name
if v := reflect.ValueOf(defaultValue); v.IsValid() && !v.IsZero() { if v := reflect.ValueOf(defaultValue); v.IsValid() && !v.IsZero() {
@ -78,7 +73,7 @@ func New[Value any](name string, defaultValue Value) Key[Value] {
func (key Key[Value]) contextKey() any { func (key Key[Value]) contextKey() any {
if key.name == nil { if key.name == nil {
// Use the reflect.Type of the Value (implies key not created by New). // Use the reflect.Type of the Value (implies key not created by New).
return reflectTypeFor[Value]() return reflect.TypeFor[Value]()
} else { } else {
// Use the name pointer directly (implies key created by New). // Use the name pointer directly (implies key created by New).
return key.name return key.name
@ -119,7 +114,7 @@ func (key Key[Value]) Has(ctx context.Context) (ok bool) {
// String returns the name of the key. // String returns the name of the key.
func (key Key[Value]) String() string { func (key Key[Value]) String() string {
if key.name == nil { if key.name == nil {
return reflectTypeFor[Value]().String() return reflect.TypeFor[Value]().String()
} }
return key.name.String() return key.name.String()
} }

View File

@ -248,7 +248,7 @@ func Hash[T any](v *T) Sum {
// Always treat the Hash input as if it were an interface by including // Always treat the Hash input as if it were an interface by including
// a hash of the type. This ensures that hashing of two different types // a hash of the type. This ensures that hashing of two different types
// but with the same value structure produces different hashes. // but with the same value structure produces different hashes.
t := reflect.TypeOf(v).Elem() t := reflect.TypeFor[T]()
h.hashType(t) h.hashType(t)
if v == nil { if v == nil {
h.HashUint8(0) // indicates nil h.HashUint8(0) // indicates nil
@ -300,8 +300,7 @@ func ExcludeFields[T any](fields ...string) Option {
} }
func newFieldFilter[T any](include bool, fields []string) Option { func newFieldFilter[T any](include bool, fields []string) Option {
var zero T t := reflect.TypeFor[T]()
t := reflect.TypeOf(&zero).Elem()
fieldSet := set.Set[string]{} fieldSet := set.Set[string]{}
for _, f := range fields { for _, f := range fields {
if _, ok := t.FieldByName(f); !ok { if _, ok := t.FieldByName(f); !ok {
@ -321,12 +320,11 @@ func newFieldFilter[T any](include bool, fields []string) Option {
// be removed in the future, along with documentation about their precedence // be removed in the future, along with documentation about their precedence
// when combined. // when combined.
func HasherForType[T any](opts ...Option) func(*T) Sum { func HasherForType[T any](opts ...Option) func(*T) Sum {
var v *T
seedOnce.Do(initSeed) seedOnce.Do(initSeed)
if len(opts) > 1 { if len(opts) > 1 {
panic("HasherForType only accepts one optional argument") // for now panic("HasherForType only accepts one optional argument") // for now
} }
t := reflect.TypeOf(v).Elem() t := reflect.TypeFor[T]()
var hash typeHasherFunc var hash typeHasherFunc
for _, o := range opts { for _, o := range opts {
switch o := o.(type) { switch o := o.(type) {

View File

@ -823,7 +823,7 @@ func TestHashMapAcyclic(t *testing.T) {
hb := &hashBuffer{Hash: sha256.New()} hb := &hashBuffer{Hash: sha256.New()}
hash := lookupTypeHasher(reflect.TypeOf(m)) hash := lookupTypeHasher(reflect.TypeFor[map[int]string]())
for i := 0; i < 20; i++ { for i := 0; i < 20; i++ {
va := reflect.ValueOf(&m).Elem() va := reflect.ValueOf(&m).Elem()
hb.Reset() hb.Reset()

View File

@ -10,9 +10,9 @@ import (
) )
var ( var (
timeTimeType = reflect.TypeOf((*time.Time)(nil)).Elem() timeTimeType = reflect.TypeFor[time.Time]()
netipAddrType = reflect.TypeOf((*netip.Addr)(nil)).Elem() netipAddrType = reflect.TypeFor[netip.Addr]()
selfHasherType = reflect.TypeOf((*SelfHasher)(nil)).Elem() selfHasherType = reflect.TypeFor[SelfHasher]()
) )
// typeIsSpecialized reports whether this type has specialized hashing. // typeIsSpecialized reports whether this type has specialized hashing.

View File

@ -26,7 +26,7 @@ func TestConfigEqual(t *testing.T) {
"SubnetRoutes", "SNATSubnetRoutes", "NetfilterMode", "SubnetRoutes", "SNATSubnetRoutes", "NetfilterMode",
"NetfilterKind", "NetfilterKind",
} }
configType := reflect.TypeOf(Config{}) configType := reflect.TypeFor[Config]()
configFields := []string{} configFields := []string{}
for i := 0; i < configType.NumField(); i++ { for i := 0; i < configType.NumField(); i++ {
configFields = append(configFields, configType.Field(i).Name) configFields = append(configFields, configType.Field(i).Name)

View File

@ -20,7 +20,7 @@ var (
) )
func getPeerStatsOffset(name string) uintptr { func getPeerStatsOffset(name string) uintptr {
peerType := reflect.TypeOf(device.Peer{}) peerType := reflect.TypeFor[device.Peer]()
field, ok := peerType.FieldByName(name) field, ok := peerType.FieldByName(name)
if !ok { if !ok {
panic("no " + name + " field in device.Peer") panic("no " + name + " field in device.Peer")