http2: mark some structs as non-comparable
Reduces binary size by not generating eq algs.
Also, remove the badStringError type that only had one use, and was
just copied from net/http where it's also not used much.
Updates golang/go#38782
Change-Id: I56bddde0bb500109e2c18bb1419e8a920a5bebf9
Reviewed-on: https://go-review.googlesource.com/c/net/+/231119
Run-TryBot: Brad Fitzpatrick <bradfitz@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/http2/client_conn_pool.go b/http2/client_conn_pool.go
index 95eb63c..3a67636 100644
--- a/http2/client_conn_pool.go
+++ b/http2/client_conn_pool.go
@@ -107,6 +107,7 @@
// dialCall is an in-flight Transport dial call to a host.
type dialCall struct {
+ _ incomparable
p *clientConnPool
done chan struct{} // closed when done
res *ClientConn // valid after done is closed
@@ -180,6 +181,7 @@
}
type addConnCall struct {
+ _ incomparable
p *clientConnPool
done chan struct{} // closed when done
err error
diff --git a/http2/flow.go b/http2/flow.go
index cea601f..b51f0e0 100644
--- a/http2/flow.go
+++ b/http2/flow.go
@@ -8,6 +8,8 @@
// flow is the flow control window's size.
type flow struct {
+ _ incomparable
+
// n is the number of DATA bytes we're allowed to send.
// A flow is kept both on a conn and a per-stream.
n int32
diff --git a/http2/frame_test.go b/http2/frame_test.go
index 3c107b9..cc0c737 100644
--- a/http2/frame_test.go
+++ b/http2/frame_test.go
@@ -160,7 +160,7 @@
}
got := f.Header()
tt.wantHeader.valid = true
- if got != tt.wantHeader {
+ if !got.Equal(tt.wantHeader) {
t.Errorf("%d. read %+v; want %+v", i, got, tt.wantHeader)
continue
}
@@ -171,6 +171,14 @@
}
}
+func (fh FrameHeader) Equal(b FrameHeader) bool {
+ return fh.valid == b.valid &&
+ fh.Type == b.Type &&
+ fh.Flags == b.Flags &&
+ fh.Length == b.Length &&
+ fh.StreamID == b.StreamID
+}
+
func TestWriteHeaders(t *testing.T) {
tests := []struct {
name string
@@ -595,7 +603,7 @@
continue
}
tt.want.valid = true
- if got != tt.want {
+ if !got.Equal(tt.want) {
t.Errorf("%d. readFrameHeader(%q) = %+v; want %+v", i, tt.in, got, tt.want)
}
}
diff --git a/http2/hpack/huffman.go b/http2/hpack/huffman.go
index b412a96..a1ab2f0 100644
--- a/http2/hpack/huffman.go
+++ b/http2/hpack/huffman.go
@@ -105,7 +105,14 @@
return nil
}
+// incomparable is a zero-width, non-comparable type. Adding it to a struct
+// makes that struct also non-comparable, and generally doesn't add
+// any size (as long as it's first).
+type incomparable [0]func()
+
type node struct {
+ _ incomparable
+
// children is non-nil for internal nodes
children *[256]*node
diff --git a/http2/http2.go b/http2/http2.go
index 27cc893..5571ccf 100644
--- a/http2/http2.go
+++ b/http2/http2.go
@@ -241,6 +241,7 @@
// Its buffered writer is lazily allocated as needed, to minimize
// idle memory usage with many connections.
type bufferedWriter struct {
+ _ incomparable
w io.Writer // immutable
bw *bufio.Writer // non-nil when data is buffered
}
@@ -313,6 +314,7 @@
}
type httpError struct {
+ _ incomparable
msg string
timeout bool
}
@@ -376,3 +378,8 @@
func validPseudoPath(v string) bool {
return (len(v) > 0 && v[0] == '/') || v == "*"
}
+
+// incomparable is a zero-width, non-comparable type. Adding it to a struct
+// makes that struct also non-comparable, and generally doesn't add
+// any size (as long as it's first).
+type incomparable [0]func()
diff --git a/http2/server.go b/http2/server.go
index bc9e41a..69e1a77 100644
--- a/http2/server.go
+++ b/http2/server.go
@@ -761,6 +761,7 @@
// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
type frameWriteResult struct {
+ _ incomparable
wr FrameWriteRequest // what was written (or attempted)
err error // result of the writeFrame call
}
@@ -771,7 +772,7 @@
// serverConn.
func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) {
err := wr.write.writeFrame(sc)
- sc.wroteFrameCh <- frameWriteResult{wr, err}
+ sc.wroteFrameCh <- frameWriteResult{wr: wr, err: err}
}
func (sc *serverConn) closeAllStreamsOnConnClose() {
@@ -1161,7 +1162,7 @@
if wr.write.staysWithinBuffer(sc.bw.Available()) {
sc.writingFrameAsync = false
err := wr.write.writeFrame(sc)
- sc.wroteFrame(frameWriteResult{wr, err})
+ sc.wroteFrame(frameWriteResult{wr: wr, err: err})
} else {
sc.writingFrameAsync = true
go sc.writeFrameAsync(wr)
@@ -2275,6 +2276,7 @@
// requestBody is the Handler's Request.Body type.
// Read and Close may be called concurrently.
type requestBody struct {
+ _ incomparable
stream *stream
conn *serverConn
closed bool // for use by Close only
diff --git a/http2/transport.go b/http2/transport.go
index e4fb025..54acc1e 100644
--- a/http2/transport.go
+++ b/http2/transport.go
@@ -916,7 +916,7 @@
k = http.CanonicalHeaderKey(k)
switch k {
case "Transfer-Encoding", "Trailer", "Content-Length":
- return "", &badStringError{"invalid Trailer key", k}
+ return "", fmt.Errorf("invalid Trailer key %q", k)
}
keys = append(keys, k)
}
@@ -1394,13 +1394,6 @@
}
}
-type badStringError struct {
- what string
- str string
-}
-
-func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
-
// requires cc.mu be held.
func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
cc.hbuf.Reset()
@@ -1616,6 +1609,7 @@
}
type resAndError struct {
+ _ incomparable
res *http.Response
err error
}
@@ -1663,6 +1657,7 @@
// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
type clientConnReadLoop struct {
+ _ incomparable
cc *ClientConn
closeWhenIdle bool
}
@@ -2479,6 +2474,7 @@
// gzipReader wraps a response body so it can lazily
// call gzip.NewReader on the first call to Read
type gzipReader struct {
+ _ incomparable
body io.ReadCloser // underlying Response.Body
zr *gzip.Reader // lazily-initialized gzip reader
zerr error // sticky error