Browse Source

types/structs: add structs.Incomparable annotation, use it where applicable

Shotizam before and output queries:

sqlite> select sum(size) from bin where func like 'type..%';
129067
=>
120216
Brad Fitzpatrick 5 years ago
parent
commit
fefd7e10dc

+ 3 - 0
control/controlclient/auto.go

@@ -22,6 +22,7 @@ import (
 	"tailscale.com/tailcfg"
 	"tailscale.com/types/empty"
 	"tailscale.com/types/logger"
+	"tailscale.com/types/structs"
 )
 
 // TODO(apenwarr): eliminate the 'state' variable, as it's now obsolete.
@@ -61,6 +62,7 @@ func (s state) String() string {
 }
 
 type Status struct {
+	_             structs.Incomparable
 	LoginFinished *empty.Message
 	Err           string
 	URL           string
@@ -94,6 +96,7 @@ func (s Status) String() string {
 }
 
 type LoginGoal struct {
+	_            structs.Incomparable
 	wantLoggedIn bool          // true if we *want* to be logged in
 	token        *oauth2.Token // oauth token to use when logging in
 	flags        LoginFlags    // flags to use when logging in

+ 3 - 1
control/controlclient/controlclient_test.go

@@ -13,7 +13,9 @@ import (
 
 func fieldsOf(t reflect.Type) (fields []string) {
 	for i := 0; i < t.NumField(); i++ {
-		fields = append(fields, t.Field(i).Name)
+		if name := t.Field(i).Name; name != "_" {
+			fields = append(fields, name)
+		}
 	}
 	return
 }

+ 2 - 0
control/controlclient/direct.go

@@ -30,10 +30,12 @@ import (
 	"tailscale.com/net/tlsdial"
 	"tailscale.com/tailcfg"
 	"tailscale.com/types/logger"
+	"tailscale.com/types/structs"
 	"tailscale.com/version"
 )
 
 type Persist struct {
+	_                 structs.Incomparable
 	PrivateMachineKey wgcfg.PrivateKey
 	PrivateNodeKey    wgcfg.PrivateKey
 	OldPrivateNodeKey wgcfg.PrivateKey // needed to request key rotation

+ 4 - 0
derp/derpmap/derpmap.go

@@ -7,6 +7,8 @@ package derpmap
 
 import (
 	"fmt"
+
+	"tailscale.com/types/structs"
 )
 
 // World is a set of DERP server.
@@ -109,6 +111,8 @@ func init() {
 
 // Server is configuration for a DERP server.
 type Server struct {
+	_ structs.Incomparable
+
 	ID int
 
 	// HostHTTPS is the HTTPS hostname.

+ 2 - 0
ipn/backend.go

@@ -11,6 +11,7 @@ import (
 	"tailscale.com/ipn/ipnstate"
 	"tailscale.com/tailcfg"
 	"tailscale.com/types/empty"
+	"tailscale.com/types/structs"
 	"tailscale.com/wgengine"
 )
 
@@ -46,6 +47,7 @@ type NetworkMap = controlclient.NetworkMap
 // that they have not changed.
 // They are JSON-encoded on the wire, despite the lack of struct tags.
 type Notify struct {
+	_             structs.Incomparable
 	Version       string           // version number of IPN backend
 	ErrMessage    *string          // critical error message, if any
 	LoginFinished *empty.Message   // event: non-nil when login process succeeded

+ 2 - 0
ipn/message.go

@@ -14,6 +14,7 @@ import (
 	"time"
 
 	"tailscale.com/types/logger"
+	"tailscale.com/types/structs"
 	"tailscale.com/version"
 )
 
@@ -34,6 +35,7 @@ type FakeExpireAfterArgs struct {
 // Command is a command message that is JSON encoded and sent by a
 // frontend to a backend.
 type Command struct {
+	_       structs.Incomparable
 	Version string
 
 	// Exactly one of the following must be non-nil.

+ 3 - 0
ratelimit/ratelimit.go

@@ -7,9 +7,12 @@ package ratelimit
 import (
 	"sync"
 	"time"
+
+	"tailscale.com/types/structs"
 )
 
 type Bucket struct {
+	_            structs.Incomparable
 	mu           sync.Mutex
 	FillInterval time.Duration
 	Burst        int

+ 2 - 0
stunner/stunner.go

@@ -17,6 +17,7 @@ import (
 
 	"tailscale.com/net/dnscache"
 	"tailscale.com/stun"
+	"tailscale.com/types/structs"
 )
 
 // Stunner sends a STUN request to several servers and handles a response.
@@ -86,6 +87,7 @@ func (s *Stunner) removeTX(tx stun.TxID) (request, bool) {
 }
 
 type request struct {
+	_      structs.Incomparable
 	sent   time.Time
 	server string
 }

+ 6 - 0
tailcfg/tailcfg.go

@@ -15,6 +15,7 @@ import (
 	"github.com/tailscale/wireguard-go/wgcfg"
 	"golang.org/x/oauth2"
 	"tailscale.com/types/opt"
+	"tailscale.com/types/structs"
 )
 
 type ID int64
@@ -99,6 +100,7 @@ func (u *User) Clone() *User {
 }
 
 type Login struct {
+	_             structs.Incomparable
 	ID            LoginID
 	Provider      string
 	LoginName     string
@@ -253,6 +255,7 @@ const (
 )
 
 type Service struct {
+	_           structs.Incomparable
 	Proto       ServiceProto // TCP or UDP
 	Port        uint16       // port number service is listening on
 	Description string       // text description of service
@@ -386,10 +389,12 @@ func (h *Hostinfo) Equal(h2 *Hostinfo) bool {
 // using the local machine key, and sent to:
 //	https://login.tailscale.com/machine/<mkey hex>
 type RegisterRequest struct {
+	_          structs.Incomparable
 	Version    int // currently 1
 	NodeKey    NodeKey
 	OldNodeKey NodeKey
 	Auth       struct {
+		_ structs.Incomparable
 		// One of Provider/LoginName, Oauth2Token, or AuthKey is set.
 		Provider, LoginName string
 		Oauth2Token         *oauth2.Token
@@ -452,6 +457,7 @@ var PortRangeAny = PortRange{0, 65535}
 
 // NetPortRange represents a single subnet:portrange.
 type NetPortRange struct {
+	_     structs.Incomparable
 	IP    string
 	Bits  *int // backward compatibility: if missing, means "all" bits
 	Ports PortRange

+ 4 - 4
tailcfg/tailcfg_test.go

@@ -157,13 +157,13 @@ func TestHostinfoEqual(t *testing.T) {
 		},
 
 		{
-			&Hostinfo{Services: []Service{Service{TCP, 1234, "foo"}}},
-			&Hostinfo{Services: []Service{Service{UDP, 2345, "bar"}}},
+			&Hostinfo{Services: []Service{Service{Proto: TCP, Port: 1234, Description: "foo"}}},
+			&Hostinfo{Services: []Service{Service{Proto: UDP, Port: 2345, Description: "bar"}}},
 			false,
 		},
 		{
-			&Hostinfo{Services: []Service{Service{TCP, 1234, "foo"}}},
-			&Hostinfo{Services: []Service{Service{TCP, 1234, "foo"}}},
+			&Hostinfo{Services: []Service{Service{Proto: TCP, Port: 1234, Description: "foo"}}},
+			&Hostinfo{Services: []Service{Service{Proto: TCP, Port: 1234, Description: "foo"}}},
 			true,
 		},
 	}

+ 16 - 0
types/structs/structs.go

@@ -0,0 +1,16 @@
+// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package structs contains the Incomparable type.
+package structs
+
+// Incomparable is a zero-width incomparable type. If added as the
+// first field in a struct, it marks that struct as not comparable
+// (can't do == or be a map key) and usually doesn't add any width to
+// the struct (unless the struct has only small fields).
+//
+// Be making a struct incomparable, you can prevent misuse (prevent
+// people from using ==), but also you can shrink generated binaries,
+// as the compiler can omit equality funcs from the binary.
+type Incomparable [0]func()

+ 2 - 0
wgengine/magicsock/magicsock.go

@@ -43,6 +43,7 @@ import (
 	"tailscale.com/tailcfg"
 	"tailscale.com/types/key"
 	"tailscale.com/types/logger"
+	"tailscale.com/types/structs"
 	"tailscale.com/version"
 )
 
@@ -1072,6 +1073,7 @@ func (c *Conn) findAddrSet(addr *net.UDPAddr) *AddrSet {
 }
 
 type udpReadResult struct {
+	_    structs.Incomparable
 	n    int
 	err  error
 	addr *net.UDPAddr