Skip to content

Commit e0ff5e5

Browse files
committed
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]>
1 parent ff2c4b7 commit e0ff5e5

File tree

7 files changed

+36
-12
lines changed

7 files changed

+36
-12
lines changed

http2/client_conn_pool.go

+2
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ func (p *clientConnPool) getClientConn(req *http.Request, addr string, dialOnMis
107107

108108
// dialCall is an in-flight Transport dial call to a host.
109109
type dialCall struct {
110+
_ incomparable
110111
p *clientConnPool
111112
done chan struct{} // closed when done
112113
res *ClientConn // valid after done is closed
@@ -180,6 +181,7 @@ func (p *clientConnPool) addConnIfNeeded(key string, t *Transport, c *tls.Conn)
180181
}
181182

182183
type addConnCall struct {
184+
_ incomparable
183185
p *clientConnPool
184186
done chan struct{} // closed when done
185187
err error

http2/flow.go

+2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ package http2
88

99
// flow is the flow control window's size.
1010
type flow struct {
11+
_ incomparable
12+
1113
// n is the number of DATA bytes we're allowed to send.
1214
// A flow is kept both on a conn and a per-stream.
1315
n int32

http2/frame_test.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ func TestWriteDataPadded(t *testing.T) {
160160
}
161161
got := f.Header()
162162
tt.wantHeader.valid = true
163-
if got != tt.wantHeader {
163+
if !got.Equal(tt.wantHeader) {
164164
t.Errorf("%d. read %+v; want %+v", i, got, tt.wantHeader)
165165
continue
166166
}
@@ -171,6 +171,14 @@ func TestWriteDataPadded(t *testing.T) {
171171
}
172172
}
173173

174+
func (fh FrameHeader) Equal(b FrameHeader) bool {
175+
return fh.valid == b.valid &&
176+
fh.Type == b.Type &&
177+
fh.Flags == b.Flags &&
178+
fh.Length == b.Length &&
179+
fh.StreamID == b.StreamID
180+
}
181+
174182
func TestWriteHeaders(t *testing.T) {
175183
tests := []struct {
176184
name string
@@ -595,7 +603,7 @@ func TestReadFrameHeader(t *testing.T) {
595603
continue
596604
}
597605
tt.want.valid = true
598-
if got != tt.want {
606+
if !got.Equal(tt.want) {
599607
t.Errorf("%d. readFrameHeader(%q) = %+v; want %+v", i, tt.in, got, tt.want)
600608
}
601609
}

http2/hpack/huffman.go

+7
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,14 @@ func huffmanDecode(buf *bytes.Buffer, maxLen int, v []byte) error {
105105
return nil
106106
}
107107

108+
// incomparable is a zero-width, non-comparable type. Adding it to a struct
109+
// makes that struct also non-comparable, and generally doesn't add
110+
// any size (as long as it's first).
111+
type incomparable [0]func()
112+
108113
type node struct {
114+
_ incomparable
115+
109116
// children is non-nil for internal nodes
110117
children *[256]*node
111118

http2/http2.go

+7
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,7 @@ func (cw closeWaiter) Wait() {
241241
// Its buffered writer is lazily allocated as needed, to minimize
242242
// idle memory usage with many connections.
243243
type bufferedWriter struct {
244+
_ incomparable
244245
w io.Writer // immutable
245246
bw *bufio.Writer // non-nil when data is buffered
246247
}
@@ -313,6 +314,7 @@ func bodyAllowedForStatus(status int) bool {
313314
}
314315

315316
type httpError struct {
317+
_ incomparable
316318
msg string
317319
timeout bool
318320
}
@@ -376,3 +378,8 @@ func (s *sorter) SortStrings(ss []string) {
376378
func validPseudoPath(v string) bool {
377379
return (len(v) > 0 && v[0] == '/') || v == "*"
378380
}
381+
382+
// incomparable is a zero-width, non-comparable type. Adding it to a struct
383+
// makes that struct also non-comparable, and generally doesn't add
384+
// any size (as long as it's first).
385+
type incomparable [0]func()

http2/server.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -761,6 +761,7 @@ func (sc *serverConn) readFrames() {
761761

762762
// frameWriteResult is the message passed from writeFrameAsync to the serve goroutine.
763763
type frameWriteResult struct {
764+
_ incomparable
764765
wr FrameWriteRequest // what was written (or attempted)
765766
err error // result of the writeFrame call
766767
}
@@ -771,7 +772,7 @@ type frameWriteResult struct {
771772
// serverConn.
772773
func (sc *serverConn) writeFrameAsync(wr FrameWriteRequest) {
773774
err := wr.write.writeFrame(sc)
774-
sc.wroteFrameCh <- frameWriteResult{wr, err}
775+
sc.wroteFrameCh <- frameWriteResult{wr: wr, err: err}
775776
}
776777

777778
func (sc *serverConn) closeAllStreamsOnConnClose() {
@@ -1161,7 +1162,7 @@ func (sc *serverConn) startFrameWrite(wr FrameWriteRequest) {
11611162
if wr.write.staysWithinBuffer(sc.bw.Available()) {
11621163
sc.writingFrameAsync = false
11631164
err := wr.write.writeFrame(sc)
1164-
sc.wroteFrame(frameWriteResult{wr, err})
1165+
sc.wroteFrame(frameWriteResult{wr: wr, err: err})
11651166
} else {
11661167
sc.writingFrameAsync = true
11671168
go sc.writeFrameAsync(wr)
@@ -2275,6 +2276,7 @@ func (sc *serverConn) sendWindowUpdate32(st *stream, n int32) {
22752276
// requestBody is the Handler's Request.Body type.
22762277
// Read and Close may be called concurrently.
22772278
type requestBody struct {
2279+
_ incomparable
22782280
stream *stream
22792281
conn *serverConn
22802282
closed bool // for use by Close only

http2/transport.go

+4-8
Original file line numberDiff line numberDiff line change
@@ -916,7 +916,7 @@ func commaSeparatedTrailers(req *http.Request) (string, error) {
916916
k = http.CanonicalHeaderKey(k)
917917
switch k {
918918
case "Transfer-Encoding", "Trailer", "Content-Length":
919-
return "", &badStringError{"invalid Trailer key", k}
919+
return "", fmt.Errorf("invalid Trailer key %q", k)
920920
}
921921
keys = append(keys, k)
922922
}
@@ -1394,13 +1394,6 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error)
13941394
}
13951395
}
13961396

1397-
type badStringError struct {
1398-
what string
1399-
str string
1400-
}
1401-
1402-
func (e *badStringError) Error() string { return fmt.Sprintf("%s %q", e.what, e.str) }
1403-
14041397
// requires cc.mu be held.
14051398
func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
14061399
cc.hbuf.Reset()
@@ -1616,6 +1609,7 @@ func (cc *ClientConn) writeHeader(name, value string) {
16161609
}
16171610

16181611
type resAndError struct {
1612+
_ incomparable
16191613
res *http.Response
16201614
err error
16211615
}
@@ -1663,6 +1657,7 @@ func (cc *ClientConn) streamByID(id uint32, andRemove bool) *clientStream {
16631657

16641658
// clientConnReadLoop is the state owned by the clientConn's frame-reading readLoop.
16651659
type clientConnReadLoop struct {
1660+
_ incomparable
16661661
cc *ClientConn
16671662
closeWhenIdle bool
16681663
}
@@ -2479,6 +2474,7 @@ func (rt erringRoundTripper) RoundTrip(*http.Request) (*http.Response, error) {
24792474
// gzipReader wraps a response body so it can lazily
24802475
// call gzip.NewReader on the first call to Read
24812476
type gzipReader struct {
2477+
_ incomparable
24822478
body io.ReadCloser // underlying Response.Body
24832479
zr *gzip.Reader // lazily-initialized gzip reader
24842480
zerr error // sticky error

0 commit comments

Comments
 (0)