mirror of https://github.com/knative/pkg.git
Bump a few assorted dependencies (#2292)
This commit is contained in:
parent
7d6d325b8b
commit
b708bdee24
6
go.mod
6
go.mod
|
|
@ -41,12 +41,12 @@ require (
|
|||
go.opencensus.io v0.23.0
|
||||
go.uber.org/atomic v1.9.0
|
||||
go.uber.org/automaxprocs v1.4.0
|
||||
go.uber.org/zap v1.19.0
|
||||
go.uber.org/zap v1.19.1
|
||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 // indirect
|
||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a
|
||||
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf
|
||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||
golang.org/x/tools v0.1.5
|
||||
golang.org/x/tools v0.1.6
|
||||
gomodules.xyz/jsonpatch/v2 v2.2.0
|
||||
google.golang.org/api v0.36.0
|
||||
google.golang.org/genproto v0.0.0-20210416161957-9910b6c460de // indirect
|
||||
|
|
|
|||
21
go.sum
21
go.sum
|
|
@ -523,6 +523,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
|
||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
|
|
@ -543,14 +544,14 @@ go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
|
|||
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/automaxprocs v1.4.0 h1:CpDZl6aOlLhReez+8S3eEotD7Jx0Os++lemPlMULQP0=
|
||||
go.uber.org/automaxprocs v1.4.0/go.mod h1:/mTEdr7LvHhs0v7mjdxDreTz1OG5zdZGqgOnhWiR/+Q=
|
||||
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
|
||||
go.uber.org/zap v1.19.0 h1:mZQZefskPPCMIBCSEH0v2/iUqqLrYtaeqwD6FUGUnFE=
|
||||
go.uber.org/zap v1.19.0/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI=
|
||||
go.uber.org/zap v1.19.1 h1:ue41HOKd1vGURxrmeKIgELGb3jPW9DMUDGtsinblHwI=
|
||||
go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
|
||||
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
|
|
@ -645,8 +646,9 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw=
|
||||
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf h1:R150MpwJIv1MpS0N/pc+NhTM8ajzvlmxlY5OYsrevXQ=
|
||||
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
|
@ -723,8 +725,9 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA=
|
||||
golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d h1:SZxvLBoTP5yHO3Frd4z4vrF+DBX9vMVanchswa69toE=
|
||||
|
|
@ -765,7 +768,6 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn
|
|||
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
|
|
@ -799,8 +801,9 @@ golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4f
|
|||
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.6 h1:SIasE1FVIQOWz2GEAHFOmoW7xchJcqlucjSULTL0Ag4=
|
||||
golang.org/x/tools v0.1.6/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
|
|||
|
|
@ -1,4 +1,16 @@
|
|||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
This project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## 1.19.1 (8 Sep 2021)
|
||||
|
||||
### Fixed
|
||||
* [#1001][]: JSON: Fix complex number encoding with negative imaginary part. Thanks to @hemantjadon.
|
||||
* [#1003][]: JSON: Fix inaccurate precision when encoding float32.
|
||||
|
||||
[#1001]: https://github.com/uber-go/zap/pull/1001
|
||||
[#1003]: https://github.com/uber-go/zap/pull/1003
|
||||
|
||||
## 1.19.0 (9 Aug 2021)
|
||||
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ require (
|
|||
github.com/pkg/errors v0.8.1
|
||||
github.com/stretchr/testify v1.7.0
|
||||
go.uber.org/atomic v1.7.0
|
||||
go.uber.org/goleak v1.1.10
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723
|
||||
go.uber.org/multierr v1.6.0
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
||||
|
|
|
|||
|
|
@ -14,31 +14,48 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
|||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
go.uber.org/goleak v1.1.10 h1:z+mqJhf6ss6BSfSM671tgKyZBFPTTJM+HLxnhPC3wu0=
|
||||
go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723 h1:sHOAIxRGBp443oHZIPB+HsUGaksVCXVQENPxwTfQdH4=
|
||||
go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
|
||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs=
|
||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11 h1:Yq9t9jnGoR+dBuitxdo9l6Q7xh/zOyNnYUtDKaQ3x0E=
|
||||
golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
|
||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
|
|||
|
|
@ -128,6 +128,11 @@ func (enc *jsonEncoder) AddFloat64(key string, val float64) {
|
|||
enc.AppendFloat64(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddFloat32(key string, val float32) {
|
||||
enc.addKey(key)
|
||||
enc.AppendFloat32(val)
|
||||
}
|
||||
|
||||
func (enc *jsonEncoder) AddInt64(key string, val int64) {
|
||||
enc.addKey(key)
|
||||
enc.AppendInt64(val)
|
||||
|
|
@ -228,7 +233,11 @@ func (enc *jsonEncoder) AppendComplex128(val complex128) {
|
|||
// Because we're always in a quoted string, we can use strconv without
|
||||
// special-casing NaN and +/-Inf.
|
||||
enc.buf.AppendFloat(r, 64)
|
||||
enc.buf.AppendByte('+')
|
||||
// If imaginary part is less than 0, minus (-) sign is added by default
|
||||
// by AppendFloat.
|
||||
if i >= 0 {
|
||||
enc.buf.AppendByte('+')
|
||||
}
|
||||
enc.buf.AppendFloat(i, 64)
|
||||
enc.buf.AppendByte('i')
|
||||
enc.buf.AppendByte('"')
|
||||
|
|
@ -293,7 +302,6 @@ func (enc *jsonEncoder) AppendUint64(val uint64) {
|
|||
}
|
||||
|
||||
func (enc *jsonEncoder) AddComplex64(k string, v complex64) { enc.AddComplex128(k, complex128(v)) }
|
||||
func (enc *jsonEncoder) AddFloat32(k string, v float32) { enc.AddFloat64(k, float64(v)) }
|
||||
func (enc *jsonEncoder) AddInt(k string, v int) { enc.AddInt64(k, int64(v)) }
|
||||
func (enc *jsonEncoder) AddInt32(k string, v int32) { enc.AddInt64(k, int64(v)) }
|
||||
func (enc *jsonEncoder) AddInt16(k string, v int16) { enc.AddInt64(k, int64(v)) }
|
||||
|
|
|
|||
|
|
@ -53,6 +53,13 @@ func (e ErrCode) String() string {
|
|||
return fmt.Sprintf("unknown error code 0x%x", uint32(e))
|
||||
}
|
||||
|
||||
func (e ErrCode) stringToken() string {
|
||||
if s, ok := errCodeName[e]; ok {
|
||||
return s
|
||||
}
|
||||
return fmt.Sprintf("ERR_UNKNOWN_%d", uint32(e))
|
||||
}
|
||||
|
||||
// ConnectionError is an error that results in the termination of the
|
||||
// entire connection.
|
||||
type ConnectionError ErrCode
|
||||
|
|
@ -67,6 +74,11 @@ type StreamError struct {
|
|||
Cause error // optional additional detail
|
||||
}
|
||||
|
||||
// errFromPeer is a sentinel error value for StreamError.Cause to
|
||||
// indicate that the StreamError was sent from the peer over the wire
|
||||
// and wasn't locally generated in the Transport.
|
||||
var errFromPeer = errors.New("received from peer")
|
||||
|
||||
func streamError(id uint32, code ErrCode) StreamError {
|
||||
return StreamError{StreamID: id, Code: code}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1018,7 +1018,7 @@ func parseHeadersFrame(_ *frameCache, fh FrameHeader, p []byte) (_ Frame, err er
|
|||
return nil, err
|
||||
}
|
||||
}
|
||||
if len(p)-int(padLength) <= 0 {
|
||||
if len(p)-int(padLength) < 0 {
|
||||
return nil, streamError(fh.StreamID, ErrCodeProtocol)
|
||||
}
|
||||
hf.headerFragBuf = p[:len(p)-int(padLength)]
|
||||
|
|
|
|||
|
|
@ -130,6 +130,12 @@ type Server struct {
|
|||
// If nil, a default scheduler is chosen.
|
||||
NewWriteScheduler func() WriteScheduler
|
||||
|
||||
// CountError, if non-nil, is called on HTTP/2 server errors.
|
||||
// It's intended to increment a metric for monitoring, such
|
||||
// as an expvar or Prometheus metric.
|
||||
// The errType consists of only ASCII word characters.
|
||||
CountError func(errType string)
|
||||
|
||||
// Internal state. This is a pointer (rather than embedded directly)
|
||||
// so that we don't embed a Mutex in this struct, which will make the
|
||||
// struct non-copyable, which might break some callers.
|
||||
|
|
@ -1399,7 +1405,7 @@ func (sc *serverConn) processFrame(f Frame) error {
|
|||
// First frame received must be SETTINGS.
|
||||
if !sc.sawFirstSettings {
|
||||
if _, ok := f.(*SettingsFrame); !ok {
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
return sc.countError("first_settings", ConnectionError(ErrCodeProtocol))
|
||||
}
|
||||
sc.sawFirstSettings = true
|
||||
}
|
||||
|
|
@ -1424,7 +1430,7 @@ func (sc *serverConn) processFrame(f Frame) error {
|
|||
case *PushPromiseFrame:
|
||||
// A client cannot push. Thus, servers MUST treat the receipt of a PUSH_PROMISE
|
||||
// frame as a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
return sc.countError("push_promise", ConnectionError(ErrCodeProtocol))
|
||||
default:
|
||||
sc.vlogf("http2: server ignoring frame: %v", f.Header())
|
||||
return nil
|
||||
|
|
@ -1444,7 +1450,7 @@ func (sc *serverConn) processPing(f *PingFrame) error {
|
|||
// identifier field value other than 0x0, the recipient MUST
|
||||
// respond with a connection error (Section 5.4.1) of type
|
||||
// PROTOCOL_ERROR."
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
return sc.countError("ping_on_stream", ConnectionError(ErrCodeProtocol))
|
||||
}
|
||||
if sc.inGoAway && sc.goAwayCode != ErrCodeNo {
|
||||
return nil
|
||||
|
|
@ -1463,7 +1469,7 @@ func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
|
|||
// or PRIORITY on a stream in this state MUST be
|
||||
// treated as a connection error (Section 5.4.1) of
|
||||
// type PROTOCOL_ERROR."
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
return sc.countError("stream_idle", ConnectionError(ErrCodeProtocol))
|
||||
}
|
||||
if st == nil {
|
||||
// "WINDOW_UPDATE can be sent by a peer that has sent a
|
||||
|
|
@ -1474,7 +1480,7 @@ func (sc *serverConn) processWindowUpdate(f *WindowUpdateFrame) error {
|
|||
return nil
|
||||
}
|
||||
if !st.flow.add(int32(f.Increment)) {
|
||||
return streamError(f.StreamID, ErrCodeFlowControl)
|
||||
return sc.countError("bad_flow", streamError(f.StreamID, ErrCodeFlowControl))
|
||||
}
|
||||
default: // connection-level flow control
|
||||
if !sc.flow.add(int32(f.Increment)) {
|
||||
|
|
@ -1495,7 +1501,7 @@ func (sc *serverConn) processResetStream(f *RSTStreamFrame) error {
|
|||
// identifying an idle stream is received, the
|
||||
// recipient MUST treat this as a connection error
|
||||
// (Section 5.4.1) of type PROTOCOL_ERROR.
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
return sc.countError("reset_idle_stream", ConnectionError(ErrCodeProtocol))
|
||||
}
|
||||
if st != nil {
|
||||
st.cancelCtx()
|
||||
|
|
@ -1547,7 +1553,7 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
|
|||
// Why is the peer ACKing settings we never sent?
|
||||
// The spec doesn't mention this case, but
|
||||
// hang up on them anyway.
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
return sc.countError("ack_mystery", ConnectionError(ErrCodeProtocol))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1555,7 +1561,7 @@ func (sc *serverConn) processSettings(f *SettingsFrame) error {
|
|||
// This isn't actually in the spec, but hang up on
|
||||
// suspiciously large settings frames or those with
|
||||
// duplicate entries.
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
return sc.countError("settings_big_or_dups", ConnectionError(ErrCodeProtocol))
|
||||
}
|
||||
if err := f.ForeachSetting(sc.processSetting); err != nil {
|
||||
return err
|
||||
|
|
@ -1622,7 +1628,7 @@ func (sc *serverConn) processSettingInitialWindowSize(val uint32) error {
|
|||
// control window to exceed the maximum size as a
|
||||
// connection error (Section 5.4.1) of type
|
||||
// FLOW_CONTROL_ERROR."
|
||||
return ConnectionError(ErrCodeFlowControl)
|
||||
return sc.countError("setting_win_size", ConnectionError(ErrCodeFlowControl))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
|
|
@ -1655,7 +1661,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||
// or PRIORITY on a stream in this state MUST be
|
||||
// treated as a connection error (Section 5.4.1) of
|
||||
// type PROTOCOL_ERROR."
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
return sc.countError("data_on_idle", ConnectionError(ErrCodeProtocol))
|
||||
}
|
||||
|
||||
// "If a DATA frame is received whose stream is not in "open"
|
||||
|
|
@ -1672,7 +1678,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||
// and return any flow control bytes since we're not going
|
||||
// to consume them.
|
||||
if sc.inflow.available() < int32(f.Length) {
|
||||
return streamError(id, ErrCodeFlowControl)
|
||||
return sc.countError("data_flow", streamError(id, ErrCodeFlowControl))
|
||||
}
|
||||
// Deduct the flow control from inflow, since we're
|
||||
// going to immediately add it back in
|
||||
|
|
@ -1685,7 +1691,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||
// Already have a stream error in flight. Don't send another.
|
||||
return nil
|
||||
}
|
||||
return streamError(id, ErrCodeStreamClosed)
|
||||
return sc.countError("closed", streamError(id, ErrCodeStreamClosed))
|
||||
}
|
||||
if st.body == nil {
|
||||
panic("internal error: should have a body in this state")
|
||||
|
|
@ -1697,12 +1703,12 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||
// RFC 7540, sec 8.1.2.6: A request or response is also malformed if the
|
||||
// value of a content-length header field does not equal the sum of the
|
||||
// DATA frame payload lengths that form the body.
|
||||
return streamError(id, ErrCodeProtocol)
|
||||
return sc.countError("send_too_much", streamError(id, ErrCodeProtocol))
|
||||
}
|
||||
if f.Length > 0 {
|
||||
// Check whether the client has flow control quota.
|
||||
if st.inflow.available() < int32(f.Length) {
|
||||
return streamError(id, ErrCodeFlowControl)
|
||||
return sc.countError("flow_on_data_length", streamError(id, ErrCodeFlowControl))
|
||||
}
|
||||
st.inflow.take(int32(f.Length))
|
||||
|
||||
|
|
@ -1710,7 +1716,7 @@ func (sc *serverConn) processData(f *DataFrame) error {
|
|||
wrote, err := st.body.Write(data)
|
||||
if err != nil {
|
||||
sc.sendWindowUpdate(nil, int(f.Length)-wrote)
|
||||
return streamError(id, ErrCodeStreamClosed)
|
||||
return sc.countError("body_write_err", streamError(id, ErrCodeStreamClosed))
|
||||
}
|
||||
if wrote != len(data) {
|
||||
panic("internal error: bad Writer")
|
||||
|
|
@ -1796,7 +1802,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||
// stream identifier MUST respond with a connection error
|
||||
// (Section 5.4.1) of type PROTOCOL_ERROR.
|
||||
if id%2 != 1 {
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
return sc.countError("headers_even", ConnectionError(ErrCodeProtocol))
|
||||
}
|
||||
// A HEADERS frame can be used to create a new stream or
|
||||
// send a trailer for an open one. If we already have a stream
|
||||
|
|
@ -1813,7 +1819,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||
// this state, it MUST respond with a stream error (Section 5.4.2) of
|
||||
// type STREAM_CLOSED.
|
||||
if st.state == stateHalfClosedRemote {
|
||||
return streamError(id, ErrCodeStreamClosed)
|
||||
return sc.countError("headers_half_closed", streamError(id, ErrCodeStreamClosed))
|
||||
}
|
||||
return st.processTrailerHeaders(f)
|
||||
}
|
||||
|
|
@ -1824,7 +1830,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||
// receives an unexpected stream identifier MUST respond with
|
||||
// a connection error (Section 5.4.1) of type PROTOCOL_ERROR.
|
||||
if id <= sc.maxClientStreamID {
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
return sc.countError("stream_went_down", ConnectionError(ErrCodeProtocol))
|
||||
}
|
||||
sc.maxClientStreamID = id
|
||||
|
||||
|
|
@ -1841,14 +1847,14 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||
if sc.curClientStreams+1 > sc.advMaxStreams {
|
||||
if sc.unackedSettings == 0 {
|
||||
// They should know better.
|
||||
return streamError(id, ErrCodeProtocol)
|
||||
return sc.countError("over_max_streams", streamError(id, ErrCodeProtocol))
|
||||
}
|
||||
// Assume it's a network race, where they just haven't
|
||||
// received our last SETTINGS update. But actually
|
||||
// this can't happen yet, because we don't yet provide
|
||||
// a way for users to adjust server parameters at
|
||||
// runtime.
|
||||
return streamError(id, ErrCodeRefusedStream)
|
||||
return sc.countError("over_max_streams_race", streamError(id, ErrCodeRefusedStream))
|
||||
}
|
||||
|
||||
initialState := stateOpen
|
||||
|
|
@ -1858,7 +1864,7 @@ func (sc *serverConn) processHeaders(f *MetaHeadersFrame) error {
|
|||
st := sc.newStream(id, 0, initialState)
|
||||
|
||||
if f.HasPriority() {
|
||||
if err := checkPriority(f.StreamID, f.Priority); err != nil {
|
||||
if err := sc.checkPriority(f.StreamID, f.Priority); err != nil {
|
||||
return err
|
||||
}
|
||||
sc.writeSched.AdjustStream(st.id, f.Priority)
|
||||
|
|
@ -1902,15 +1908,15 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
|
|||
sc := st.sc
|
||||
sc.serveG.check()
|
||||
if st.gotTrailerHeader {
|
||||
return ConnectionError(ErrCodeProtocol)
|
||||
return sc.countError("dup_trailers", ConnectionError(ErrCodeProtocol))
|
||||
}
|
||||
st.gotTrailerHeader = true
|
||||
if !f.StreamEnded() {
|
||||
return streamError(st.id, ErrCodeProtocol)
|
||||
return sc.countError("trailers_not_ended", streamError(st.id, ErrCodeProtocol))
|
||||
}
|
||||
|
||||
if len(f.PseudoFields()) > 0 {
|
||||
return streamError(st.id, ErrCodeProtocol)
|
||||
return sc.countError("trailers_pseudo", streamError(st.id, ErrCodeProtocol))
|
||||
}
|
||||
if st.trailer != nil {
|
||||
for _, hf := range f.RegularFields() {
|
||||
|
|
@ -1919,7 +1925,7 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
|
|||
// TODO: send more details to the peer somehow. But http2 has
|
||||
// no way to send debug data at a stream level. Discuss with
|
||||
// HTTP folk.
|
||||
return streamError(st.id, ErrCodeProtocol)
|
||||
return sc.countError("trailers_bogus", streamError(st.id, ErrCodeProtocol))
|
||||
}
|
||||
st.trailer[key] = append(st.trailer[key], hf.Value)
|
||||
}
|
||||
|
|
@ -1928,13 +1934,13 @@ func (st *stream) processTrailerHeaders(f *MetaHeadersFrame) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func checkPriority(streamID uint32, p PriorityParam) error {
|
||||
func (sc *serverConn) checkPriority(streamID uint32, p PriorityParam) error {
|
||||
if streamID == p.StreamDep {
|
||||
// Section 5.3.1: "A stream cannot depend on itself. An endpoint MUST treat
|
||||
// this as a stream error (Section 5.4.2) of type PROTOCOL_ERROR."
|
||||
// Section 5.3.3 says that a stream can depend on one of its dependencies,
|
||||
// so it's only self-dependencies that are forbidden.
|
||||
return streamError(streamID, ErrCodeProtocol)
|
||||
return sc.countError("priority", streamError(streamID, ErrCodeProtocol))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -1943,7 +1949,7 @@ func (sc *serverConn) processPriority(f *PriorityFrame) error {
|
|||
if sc.inGoAway {
|
||||
return nil
|
||||
}
|
||||
if err := checkPriority(f.StreamID, f.PriorityParam); err != nil {
|
||||
if err := sc.checkPriority(f.StreamID, f.PriorityParam); err != nil {
|
||||
return err
|
||||
}
|
||||
sc.writeSched.AdjustStream(f.StreamID, f.PriorityParam)
|
||||
|
|
@ -2013,13 +2019,13 @@ func (sc *serverConn) newWriterAndRequest(st *stream, f *MetaHeadersFrame) (*res
|
|||
// "All HTTP/2 requests MUST include exactly one valid
|
||||
// value for the :method, :scheme, and :path
|
||||
// pseudo-header fields"
|
||||
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
|
||||
return nil, nil, sc.countError("bad_path_method", streamError(f.StreamID, ErrCodeProtocol))
|
||||
}
|
||||
|
||||
bodyOpen := !f.StreamEnded()
|
||||
if rp.method == "HEAD" && bodyOpen {
|
||||
// HEAD requests can't have bodies
|
||||
return nil, nil, streamError(f.StreamID, ErrCodeProtocol)
|
||||
return nil, nil, sc.countError("head_body", streamError(f.StreamID, ErrCodeProtocol))
|
||||
}
|
||||
|
||||
rp.header = make(http.Header)
|
||||
|
|
@ -2102,7 +2108,7 @@ func (sc *serverConn) newWriterAndRequestNoBody(st *stream, rp requestParam) (*r
|
|||
var err error
|
||||
url_, err = url.ParseRequestURI(rp.path)
|
||||
if err != nil {
|
||||
return nil, nil, streamError(st.id, ErrCodeProtocol)
|
||||
return nil, nil, sc.countError("bad_path", streamError(st.id, ErrCodeProtocol))
|
||||
}
|
||||
requestURI = rp.path
|
||||
}
|
||||
|
|
@ -2985,3 +2991,31 @@ func h1ServerKeepAlivesDisabled(hs *http.Server) bool {
|
|||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (sc *serverConn) countError(name string, err error) error {
|
||||
if sc == nil || sc.srv == nil {
|
||||
return err
|
||||
}
|
||||
f := sc.srv.CountError
|
||||
if f == nil {
|
||||
return err
|
||||
}
|
||||
var typ string
|
||||
var code ErrCode
|
||||
switch e := err.(type) {
|
||||
case ConnectionError:
|
||||
typ = "conn"
|
||||
code = ErrCode(e)
|
||||
case StreamError:
|
||||
typ = "stream"
|
||||
code = ErrCode(e.Code)
|
||||
default:
|
||||
return err
|
||||
}
|
||||
codeStr := errCodeName[code]
|
||||
if codeStr == "" {
|
||||
codeStr = strconv.Itoa(int(code))
|
||||
}
|
||||
f(fmt.Sprintf("%s_%s_%s", typ, codeStr, name))
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,15 @@ const (
|
|||
transportDefaultStreamMinRefresh = 4 << 10
|
||||
|
||||
defaultUserAgent = "Go-http-client/2.0"
|
||||
|
||||
// initialMaxConcurrentStreams is a connections maxConcurrentStreams until
|
||||
// it's received servers initial SETTINGS frame, which corresponds with the
|
||||
// spec's minimum recommended value.
|
||||
initialMaxConcurrentStreams = 100
|
||||
|
||||
// defaultMaxConcurrentStreams is a connections default maxConcurrentStreams
|
||||
// if the server doesn't include one in its initial SETTINGS frame.
|
||||
defaultMaxConcurrentStreams = 1000
|
||||
)
|
||||
|
||||
// Transport is an HTTP/2 Transport.
|
||||
|
|
@ -121,6 +130,12 @@ type Transport struct {
|
|||
// Defaults to 15s.
|
||||
PingTimeout time.Duration
|
||||
|
||||
// CountError, if non-nil, is called on HTTP/2 transport errors.
|
||||
// It's intended to increment a metric for monitoring, such
|
||||
// as an expvar or Prometheus metric.
|
||||
// The errType consists of only ASCII word characters.
|
||||
CountError func(errType string)
|
||||
|
||||
// t1, if non-nil, is the standard library Transport using
|
||||
// this transport. Its settings are used (but not its
|
||||
// RoundTrip method, etc).
|
||||
|
|
@ -244,8 +259,10 @@ type ClientConn struct {
|
|||
cond *sync.Cond // hold mu; broadcast on flow/closed changes
|
||||
flow flow // our conn-level flow control quota (cs.flow is per stream)
|
||||
inflow flow // peer's conn-level flow control
|
||||
doNotReuse bool // whether conn is marked to not be reused for any future requests
|
||||
closing bool
|
||||
closed bool
|
||||
seenSettings bool // true if we've seen a settings frame, false otherwise
|
||||
wantSettingsAck bool // we sent a SETTINGS frame and haven't heard back
|
||||
goAway *GoAwayFrame // if non-nil, the GoAwayFrame we received
|
||||
goAwayDebug string // goAway frame's debug data, retained as a string
|
||||
|
|
@ -253,22 +270,29 @@ type ClientConn struct {
|
|||
nextStreamID uint32
|
||||
pendingRequests int // requests blocked and waiting to be sent because len(streams) == maxConcurrentStreams
|
||||
pings map[[8]byte]chan struct{} // in flight ping data to notification channel
|
||||
bw *bufio.Writer
|
||||
br *bufio.Reader
|
||||
fr *Framer
|
||||
lastActive time.Time
|
||||
lastIdle time.Time // time last idle
|
||||
// Settings from peer: (also guarded by mu)
|
||||
// Settings from peer: (also guarded by wmu)
|
||||
maxFrameSize uint32
|
||||
maxConcurrentStreams uint32
|
||||
peerMaxHeaderListSize uint64
|
||||
initialWindowSize uint32
|
||||
|
||||
// reqHeaderMu is a 1-element semaphore channel controlling access to sending new requests.
|
||||
// Write to reqHeaderMu to lock it, read from it to unlock.
|
||||
// Lock reqmu BEFORE mu or wmu.
|
||||
reqHeaderMu chan struct{}
|
||||
|
||||
// wmu is held while writing.
|
||||
// Acquire BEFORE mu when holding both, to avoid blocking mu on network writes.
|
||||
// Only acquire both at the same time when changing peer settings.
|
||||
wmu sync.Mutex
|
||||
bw *bufio.Writer
|
||||
fr *Framer
|
||||
werr error // first write error that has occurred
|
||||
hbuf bytes.Buffer // HPACK encoder writes into this
|
||||
henc *hpack.Encoder
|
||||
|
||||
wmu sync.Mutex // held while writing; acquire AFTER mu if holding both
|
||||
werr error // first write error that has occurred
|
||||
}
|
||||
|
||||
// clientStream is the state for a single HTTP/2 stream. One of these
|
||||
|
|
@ -387,10 +411,11 @@ func (cs *clientStream) abortRequestBodyWrite(err error) {
|
|||
cc.mu.Lock()
|
||||
if cs.stopReqBody == nil {
|
||||
cs.stopReqBody = err
|
||||
if cs.req.Body != nil {
|
||||
cs.req.Body.Close()
|
||||
}
|
||||
cc.cond.Broadcast()
|
||||
// Close the body after releasing the mutex, in case it blocks.
|
||||
if body := cs.req.Body; body != nil {
|
||||
defer body.Close()
|
||||
}
|
||||
}
|
||||
cc.mu.Unlock()
|
||||
}
|
||||
|
|
@ -479,6 +504,7 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
|
|||
}
|
||||
reused := !atomic.CompareAndSwapUint32(&cc.reused, 0, 1)
|
||||
traceGotConn(req, cc, reused)
|
||||
body := req.Body
|
||||
res, gotErrAfterReqBodyWrite, err := cc.roundTrip(req)
|
||||
if err != nil && retry <= 6 {
|
||||
if req, err = shouldRetryRequest(req, err, gotErrAfterReqBodyWrite); err == nil {
|
||||
|
|
@ -492,12 +518,17 @@ func (t *Transport) RoundTripOpt(req *http.Request, opt RoundTripOpt) (*http.Res
|
|||
case <-time.After(time.Second * time.Duration(backoff)):
|
||||
continue
|
||||
case <-req.Context().Done():
|
||||
return nil, req.Context().Err()
|
||||
err = req.Context().Err()
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
t.vlogf("RoundTrip failure: %v", err)
|
||||
// If the error occurred after the body write started,
|
||||
// the body writer will close the body. Otherwise, do so here.
|
||||
if body != nil && !gotErrAfterReqBodyWrite {
|
||||
body.Close()
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
return res, nil
|
||||
|
|
@ -536,7 +567,7 @@ func shouldRetryRequest(req *http.Request, err error, afterBodyWrite bool) (*htt
|
|||
// If the request body can be reset back to its original
|
||||
// state via the optional req.GetBody, do that.
|
||||
if req.GetBody != nil {
|
||||
// TODO: consider a req.Body.Close here? or audit that all caller paths do?
|
||||
req.Body.Close()
|
||||
body, err := req.GetBody()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -563,6 +594,10 @@ func canRetryError(err error) bool {
|
|||
return true
|
||||
}
|
||||
if se, ok := err.(StreamError); ok {
|
||||
if se.Code == ErrCodeProtocol && se.Cause == errFromPeer {
|
||||
// See golang/go#47635, golang/go#42777
|
||||
return true
|
||||
}
|
||||
return se.Code == ErrCodeRefusedStream
|
||||
}
|
||||
return false
|
||||
|
|
@ -637,14 +672,15 @@ func (t *Transport) newClientConn(c net.Conn, singleUse bool) (*ClientConn, erro
|
|||
tconn: c,
|
||||
readerDone: make(chan struct{}),
|
||||
nextStreamID: 1,
|
||||
maxFrameSize: 16 << 10, // spec default
|
||||
initialWindowSize: 65535, // spec default
|
||||
maxConcurrentStreams: 1000, // "infinite", per spec. 1000 seems good enough.
|
||||
peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
|
||||
maxFrameSize: 16 << 10, // spec default
|
||||
initialWindowSize: 65535, // spec default
|
||||
maxConcurrentStreams: initialMaxConcurrentStreams, // "infinite", per spec. Use a smaller value until we have received server settings.
|
||||
peerMaxHeaderListSize: 0xffffffffffffffff, // "infinite", per spec. Use 2^64-1 instead.
|
||||
streams: make(map[uint32]*clientStream),
|
||||
singleUse: singleUse,
|
||||
wantSettingsAck: true,
|
||||
pings: make(map[[8]byte]chan struct{}),
|
||||
reqHeaderMu: make(chan struct{}, 1),
|
||||
}
|
||||
if d := t.idleConnTimeout(); d != 0 {
|
||||
cc.idleTimeout = d
|
||||
|
|
@ -714,6 +750,13 @@ func (cc *ClientConn) healthCheck() {
|
|||
}
|
||||
}
|
||||
|
||||
// SetDoNotReuse marks cc as not reusable for future HTTP requests.
|
||||
func (cc *ClientConn) SetDoNotReuse() {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
cc.doNotReuse = true
|
||||
}
|
||||
|
||||
func (cc *ClientConn) setGoAway(f *GoAwayFrame) {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
|
|
@ -772,10 +815,11 @@ func (cc *ClientConn) idleStateLocked() (st clientConnIdleState) {
|
|||
// writing it.
|
||||
maxConcurrentOkay = true
|
||||
} else {
|
||||
maxConcurrentOkay = int64(len(cc.streams)+1) < int64(cc.maxConcurrentStreams)
|
||||
maxConcurrentOkay = int64(len(cc.streams)+1) <= int64(cc.maxConcurrentStreams)
|
||||
}
|
||||
|
||||
st.canTakeNewRequest = cc.goAway == nil && !cc.closed && !cc.closing && maxConcurrentOkay &&
|
||||
!cc.doNotReuse &&
|
||||
int64(cc.nextStreamID)+2*int64(cc.pendingRequests) < math.MaxInt32 &&
|
||||
!cc.tooIdleLocked()
|
||||
st.freshConn = cc.nextStreamID == 1 && st.canTakeNewRequest
|
||||
|
|
@ -865,15 +909,18 @@ func (cc *ClientConn) Shutdown(ctx context.Context) error {
|
|||
|
||||
func (cc *ClientConn) sendGoAway() error {
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
cc.wmu.Lock()
|
||||
defer cc.wmu.Unlock()
|
||||
if cc.closing {
|
||||
closing := cc.closing
|
||||
cc.closing = true
|
||||
maxStreamID := cc.nextStreamID
|
||||
cc.mu.Unlock()
|
||||
if closing {
|
||||
// GOAWAY sent already
|
||||
return nil
|
||||
}
|
||||
|
||||
cc.wmu.Lock()
|
||||
defer cc.wmu.Unlock()
|
||||
// Send a graceful shutdown frame to server
|
||||
maxStreamID := cc.nextStreamID
|
||||
if err := cc.fr.WriteGoAway(maxStreamID, ErrCodeNo, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -881,7 +928,6 @@ func (cc *ClientConn) sendGoAway() error {
|
|||
return err
|
||||
}
|
||||
// Prevent new requests
|
||||
cc.closing = true
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -889,17 +935,22 @@ func (cc *ClientConn) sendGoAway() error {
|
|||
// err is sent to streams.
|
||||
func (cc *ClientConn) closeForError(err error) error {
|
||||
cc.mu.Lock()
|
||||
defer cc.cond.Broadcast()
|
||||
defer cc.mu.Unlock()
|
||||
for id, cs := range cc.streams {
|
||||
streams := cc.streams
|
||||
cc.streams = nil
|
||||
cc.closed = true
|
||||
cc.mu.Unlock()
|
||||
|
||||
for _, cs := range streams {
|
||||
select {
|
||||
case cs.resc <- resAndError{err: err}:
|
||||
default:
|
||||
}
|
||||
cs.bufPipe.CloseWithError(err)
|
||||
delete(cc.streams, id)
|
||||
}
|
||||
cc.closed = true
|
||||
|
||||
cc.mu.Lock()
|
||||
defer cc.cond.Broadcast()
|
||||
defer cc.mu.Unlock()
|
||||
return cc.tconn.Close()
|
||||
}
|
||||
|
||||
|
|
@ -914,6 +965,9 @@ func (cc *ClientConn) Close() error {
|
|||
// closes the client connection immediately. In-flight requests are interrupted.
|
||||
func (cc *ClientConn) closeForLostPing() error {
|
||||
err := errors.New("http2: client connection lost")
|
||||
if f := cc.t.CountError; f != nil {
|
||||
f("conn_close_lost_ping")
|
||||
}
|
||||
return cc.closeForError(err)
|
||||
}
|
||||
|
||||
|
|
@ -984,6 +1038,7 @@ func (cc *ClientConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
|||
}
|
||||
|
||||
func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAfterReqBodyWrite bool, err error) {
|
||||
ctx := req.Context()
|
||||
if err := checkConnHeaders(req); err != nil {
|
||||
return nil, false, err
|
||||
}
|
||||
|
|
@ -997,6 +1052,26 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
|||
}
|
||||
hasTrailers := trailers != ""
|
||||
|
||||
// Acquire the new-request lock by writing to reqHeaderMu.
|
||||
// This lock guards the critical section covering allocating a new stream ID
|
||||
// (requires mu) and creating the stream (requires wmu).
|
||||
if cc.reqHeaderMu == nil {
|
||||
panic("RoundTrip on initialized ClientConn") // for tests
|
||||
}
|
||||
select {
|
||||
case cc.reqHeaderMu <- struct{}{}:
|
||||
case <-req.Cancel:
|
||||
return nil, false, errRequestCanceled
|
||||
case <-ctx.Done():
|
||||
return nil, false, ctx.Err()
|
||||
}
|
||||
reqHeaderMuNeedsUnlock := true
|
||||
defer func() {
|
||||
if reqHeaderMuNeedsUnlock {
|
||||
<-cc.reqHeaderMu
|
||||
}
|
||||
}()
|
||||
|
||||
cc.mu.Lock()
|
||||
if err := cc.awaitOpenSlotForRequest(req); err != nil {
|
||||
cc.mu.Unlock()
|
||||
|
|
@ -1028,21 +1103,23 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
|||
requestedGzip = true
|
||||
}
|
||||
|
||||
// we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is
|
||||
// sent by writeRequestBody below, along with any Trailers,
|
||||
// again in form HEADERS{1}, CONTINUATION{0,})
|
||||
hdrs, err := cc.encodeHeaders(req, requestedGzip, trailers, contentLen)
|
||||
if err != nil {
|
||||
cc.mu.Unlock()
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
cs := cc.newStream()
|
||||
cs.req = req
|
||||
cs.trace = httptrace.ContextClientTrace(req.Context())
|
||||
cs.requestedGzip = requestedGzip
|
||||
bodyWriter := cc.t.getBodyWriterState(cs, body)
|
||||
cs.on100 = bodyWriter.on100
|
||||
cc.mu.Unlock()
|
||||
|
||||
// we send: HEADERS{1}, CONTINUATION{0,} + DATA{0,} (DATA is
|
||||
// sent by writeRequestBody below, along with any Trailers,
|
||||
// again in form HEADERS{1}, CONTINUATION{0,})
|
||||
cc.wmu.Lock()
|
||||
hdrs, err := cc.encodeHeaders(req, requestedGzip, trailers, contentLen)
|
||||
if err != nil {
|
||||
cc.wmu.Unlock()
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
cc.wmu.Lock()
|
||||
|
|
@ -1053,23 +1130,24 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
|||
}
|
||||
}()
|
||||
|
||||
cc.wmu.Lock()
|
||||
endStream := !hasBody && !hasTrailers
|
||||
werr := cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs)
|
||||
err = cc.writeHeaders(cs.ID, endStream, int(cc.maxFrameSize), hdrs)
|
||||
cc.wmu.Unlock()
|
||||
<-cc.reqHeaderMu // release the new-request lock
|
||||
reqHeaderMuNeedsUnlock = false
|
||||
traceWroteHeaders(cs.trace)
|
||||
cc.mu.Unlock()
|
||||
|
||||
if werr != nil {
|
||||
if err != nil {
|
||||
if hasBody {
|
||||
req.Body.Close() // per RoundTripper contract
|
||||
bodyWriter.cancel()
|
||||
}
|
||||
cc.forgetStreamID(cs.ID)
|
||||
// Don't bother sending a RST_STREAM (our write already failed;
|
||||
// no need to keep writing)
|
||||
traceWroteRequest(cs.trace, werr)
|
||||
return nil, false, werr
|
||||
traceWroteRequest(cs.trace, err)
|
||||
// TODO(dneil): An error occurred while writing the headers.
|
||||
// Should we return an error indicating that this request can be retried?
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
var respHeaderTimer <-chan time.Time
|
||||
|
|
@ -1086,7 +1164,6 @@ func (cc *ClientConn) roundTrip(req *http.Request) (res *http.Response, gotErrAf
|
|||
|
||||
readLoopResCh := cs.resc
|
||||
bodyWritten := false
|
||||
ctx := req.Context()
|
||||
|
||||
handleReadLoopResponse := func(re resAndError) (*http.Response, bool, error) {
|
||||
res := re.res
|
||||
|
|
@ -1177,7 +1254,7 @@ func (cc *ClientConn) awaitOpenSlotForRequest(req *http.Request) error {
|
|||
return errClientConnUnusable
|
||||
}
|
||||
cc.lastIdle = time.Time{}
|
||||
if int64(len(cc.streams))+1 <= int64(cc.maxConcurrentStreams) {
|
||||
if int64(len(cc.streams)) < int64(cc.maxConcurrentStreams) {
|
||||
if waitingForConn != nil {
|
||||
close(waitingForConn)
|
||||
}
|
||||
|
|
@ -1388,19 +1465,17 @@ func (cs *clientStream) writeRequestBody(body io.Reader, bodyCloser io.Closer) (
|
|||
return nil
|
||||
}
|
||||
|
||||
cc.wmu.Lock()
|
||||
var trls []byte
|
||||
if hasTrailers {
|
||||
cc.mu.Lock()
|
||||
trls, err = cc.encodeTrailers(req)
|
||||
cc.mu.Unlock()
|
||||
if err != nil {
|
||||
cc.wmu.Unlock()
|
||||
cc.writeStreamReset(cs.ID, ErrCodeInternal, err)
|
||||
cc.forgetStreamID(cs.ID)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
cc.wmu.Lock()
|
||||
defer cc.wmu.Unlock()
|
||||
|
||||
// Two ways to send END_STREAM: either with trailers, or
|
||||
|
|
@ -1450,7 +1525,7 @@ func (cs *clientStream) awaitFlowControl(maxBytes int) (taken int32, err error)
|
|||
}
|
||||
}
|
||||
|
||||
// requires cc.mu be held.
|
||||
// requires cc.wmu be held.
|
||||
func (cc *ClientConn) encodeHeaders(req *http.Request, addGzipHeader bool, trailers string, contentLength int64) ([]byte, error) {
|
||||
cc.hbuf.Reset()
|
||||
|
||||
|
|
@ -1638,7 +1713,7 @@ func shouldSendReqContentLength(method string, contentLength int64) bool {
|
|||
}
|
||||
}
|
||||
|
||||
// requires cc.mu be held.
|
||||
// requires cc.wmu be held.
|
||||
func (cc *ClientConn) encodeTrailers(req *http.Request) ([]byte, error) {
|
||||
cc.hbuf.Reset()
|
||||
|
||||
|
|
@ -1787,7 +1862,11 @@ func (rl *clientConnReadLoop) cleanup() {
|
|||
} else if err == io.EOF {
|
||||
err = io.ErrUnexpectedEOF
|
||||
}
|
||||
for _, cs := range cc.streams {
|
||||
cc.closed = true
|
||||
streams := cc.streams
|
||||
cc.streams = nil
|
||||
cc.mu.Unlock()
|
||||
for _, cs := range streams {
|
||||
cs.bufPipe.CloseWithError(err) // no-op if already closed
|
||||
select {
|
||||
case cs.resc <- resAndError{err: err}:
|
||||
|
|
@ -1795,11 +1874,38 @@ func (rl *clientConnReadLoop) cleanup() {
|
|||
}
|
||||
close(cs.done)
|
||||
}
|
||||
cc.closed = true
|
||||
cc.mu.Lock()
|
||||
cc.cond.Broadcast()
|
||||
cc.mu.Unlock()
|
||||
}
|
||||
|
||||
// countReadFrameError calls Transport.CountError with a string
|
||||
// representing err.
|
||||
func (cc *ClientConn) countReadFrameError(err error) {
|
||||
f := cc.t.CountError
|
||||
if f == nil || err == nil {
|
||||
return
|
||||
}
|
||||
if ce, ok := err.(ConnectionError); ok {
|
||||
errCode := ErrCode(ce)
|
||||
f(fmt.Sprintf("read_frame_conn_error_%s", errCode.stringToken()))
|
||||
return
|
||||
}
|
||||
if errors.Is(err, io.EOF) {
|
||||
f("read_frame_eof")
|
||||
return
|
||||
}
|
||||
if errors.Is(err, io.ErrUnexpectedEOF) {
|
||||
f("read_frame_unexpected_eof")
|
||||
return
|
||||
}
|
||||
if errors.Is(err, ErrFrameTooLarge) {
|
||||
f("read_frame_too_large")
|
||||
return
|
||||
}
|
||||
f("read_frame_other")
|
||||
}
|
||||
|
||||
func (rl *clientConnReadLoop) run() error {
|
||||
cc := rl.cc
|
||||
rl.closeWhenIdle = cc.t.disableKeepAlives() || cc.singleUse
|
||||
|
|
@ -1830,6 +1936,7 @@ func (rl *clientConnReadLoop) run() error {
|
|||
}
|
||||
continue
|
||||
} else if err != nil {
|
||||
cc.countReadFrameError(err)
|
||||
return err
|
||||
}
|
||||
if VerboseLogs {
|
||||
|
|
@ -2125,8 +2232,6 @@ func (b transportResponseBody) Read(p []byte) (n int, err error) {
|
|||
}
|
||||
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
|
||||
var connAdd, streamAdd int32
|
||||
// Check the conn-level first, before the stream-level.
|
||||
if v := cc.inflow.available(); v < transportDefaultConnFlow/2 {
|
||||
|
|
@ -2143,6 +2248,8 @@ func (b transportResponseBody) Read(p []byte) (n int, err error) {
|
|||
cs.inflow.add(streamAdd)
|
||||
}
|
||||
}
|
||||
cc.mu.Unlock()
|
||||
|
||||
if connAdd != 0 || streamAdd != 0 {
|
||||
cc.wmu.Lock()
|
||||
defer cc.wmu.Unlock()
|
||||
|
|
@ -2168,19 +2275,25 @@ func (b transportResponseBody) Close() error {
|
|||
|
||||
if unread > 0 || !serverSentStreamEnd {
|
||||
cc.mu.Lock()
|
||||
cc.wmu.Lock()
|
||||
if !serverSentStreamEnd {
|
||||
cc.fr.WriteRSTStream(cs.ID, ErrCodeCancel)
|
||||
cs.didReset = true
|
||||
}
|
||||
// Return connection-level flow control.
|
||||
if unread > 0 {
|
||||
cc.inflow.add(int32(unread))
|
||||
}
|
||||
cc.mu.Unlock()
|
||||
|
||||
cc.wmu.Lock()
|
||||
if !serverSentStreamEnd {
|
||||
cc.fr.WriteRSTStream(cs.ID, ErrCodeCancel)
|
||||
}
|
||||
// Return connection-level flow control.
|
||||
if unread > 0 {
|
||||
cc.fr.WriteWindowUpdate(0, uint32(unread))
|
||||
}
|
||||
cc.bw.Flush()
|
||||
cc.wmu.Unlock()
|
||||
cc.mu.Unlock()
|
||||
}
|
||||
|
||||
cs.bufPipe.BreakWithError(errClosedResponseBody)
|
||||
|
|
@ -2258,6 +2371,10 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
|
|||
}
|
||||
if refund > 0 {
|
||||
cc.inflow.add(int32(refund))
|
||||
}
|
||||
cc.mu.Unlock()
|
||||
|
||||
if refund > 0 {
|
||||
cc.wmu.Lock()
|
||||
cc.fr.WriteWindowUpdate(0, uint32(refund))
|
||||
if !didReset {
|
||||
|
|
@ -2267,7 +2384,6 @@ func (rl *clientConnReadLoop) processData(f *DataFrame) error {
|
|||
cc.bw.Flush()
|
||||
cc.wmu.Unlock()
|
||||
}
|
||||
cc.mu.Unlock()
|
||||
|
||||
if len(data) > 0 && !didReset {
|
||||
if _, err := cs.bufPipe.Write(data); err != nil {
|
||||
|
|
@ -2322,12 +2438,33 @@ func (rl *clientConnReadLoop) processGoAway(f *GoAwayFrame) error {
|
|||
if f.ErrCode != 0 {
|
||||
// TODO: deal with GOAWAY more. particularly the error code
|
||||
cc.vlogf("transport got GOAWAY with error code = %v", f.ErrCode)
|
||||
if fn := cc.t.CountError; fn != nil {
|
||||
fn("recv_goaway_" + f.ErrCode.stringToken())
|
||||
}
|
||||
|
||||
}
|
||||
cc.setGoAway(f)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rl *clientConnReadLoop) processSettings(f *SettingsFrame) error {
|
||||
cc := rl.cc
|
||||
// Locking both mu and wmu here allows frame encoding to read settings with only wmu held.
|
||||
// Acquiring wmu when f.IsAck() is unnecessary, but convenient and mostly harmless.
|
||||
cc.wmu.Lock()
|
||||
defer cc.wmu.Unlock()
|
||||
|
||||
if err := rl.processSettingsNoWrite(f); err != nil {
|
||||
return err
|
||||
}
|
||||
if !f.IsAck() {
|
||||
cc.fr.WriteSettingsAck()
|
||||
cc.bw.Flush()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rl *clientConnReadLoop) processSettingsNoWrite(f *SettingsFrame) error {
|
||||
cc := rl.cc
|
||||
cc.mu.Lock()
|
||||
defer cc.mu.Unlock()
|
||||
|
|
@ -2340,12 +2477,14 @@ func (rl *clientConnReadLoop) processSettings(f *SettingsFrame) error {
|
|||
return ConnectionError(ErrCodeProtocol)
|
||||
}
|
||||
|
||||
var seenMaxConcurrentStreams bool
|
||||
err := f.ForeachSetting(func(s Setting) error {
|
||||
switch s.ID {
|
||||
case SettingMaxFrameSize:
|
||||
cc.maxFrameSize = s.Val
|
||||
case SettingMaxConcurrentStreams:
|
||||
cc.maxConcurrentStreams = s.Val
|
||||
seenMaxConcurrentStreams = true
|
||||
case SettingMaxHeaderListSize:
|
||||
cc.peerMaxHeaderListSize = uint64(s.Val)
|
||||
case SettingInitialWindowSize:
|
||||
|
|
@ -2377,12 +2516,18 @@ func (rl *clientConnReadLoop) processSettings(f *SettingsFrame) error {
|
|||
return err
|
||||
}
|
||||
|
||||
cc.wmu.Lock()
|
||||
defer cc.wmu.Unlock()
|
||||
if !cc.seenSettings {
|
||||
if !seenMaxConcurrentStreams {
|
||||
// This was the servers initial SETTINGS frame and it
|
||||
// didn't contain a MAX_CONCURRENT_STREAMS field so
|
||||
// increase the number of concurrent streams this
|
||||
// connection can establish to our default.
|
||||
cc.maxConcurrentStreams = defaultMaxConcurrentStreams
|
||||
}
|
||||
cc.seenSettings = true
|
||||
}
|
||||
|
||||
cc.fr.WriteSettingsAck()
|
||||
cc.bw.Flush()
|
||||
return cc.werr
|
||||
return nil
|
||||
}
|
||||
|
||||
func (rl *clientConnReadLoop) processWindowUpdate(f *WindowUpdateFrame) error {
|
||||
|
|
@ -2419,10 +2564,17 @@ func (rl *clientConnReadLoop) processResetStream(f *RSTStreamFrame) error {
|
|||
// which closes this, so there
|
||||
// isn't a race.
|
||||
default:
|
||||
err := streamError(cs.ID, f.ErrCode)
|
||||
cs.resetErr = err
|
||||
serr := streamError(cs.ID, f.ErrCode)
|
||||
if f.ErrCode == ErrCodeProtocol {
|
||||
rl.cc.SetDoNotReuse()
|
||||
serr.Cause = errFromPeer
|
||||
}
|
||||
if fn := cs.cc.t.CountError; fn != nil {
|
||||
fn("recv_rststream_" + f.ErrCode.stringToken())
|
||||
}
|
||||
cs.resetErr = serr
|
||||
close(cs.peerReset)
|
||||
cs.bufPipe.CloseWithError(err)
|
||||
cs.bufPipe.CloseWithError(serr)
|
||||
cs.cc.cond.Broadcast() // wake up checkResetOrDone via clientStream.awaitFlowControl
|
||||
}
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package unix
|
||||
|
||||
import "unsafe"
|
||||
|
||||
// Helpers for dealing with ifreq since it contains a union and thus requires a
|
||||
// lot of unsafe.Pointer casts to use properly.
|
||||
|
||||
// newIfreq creates an ifreq with the input network interface name after
|
||||
// validating the name does not exceed IFNAMSIZ-1 (trailing NULL required)
|
||||
// bytes.
|
||||
func newIfreq(name string) (*ifreq, error) {
|
||||
// Leave room for terminating NULL byte.
|
||||
if len(name) >= IFNAMSIZ {
|
||||
return nil, EINVAL
|
||||
}
|
||||
|
||||
var ifr ifreq
|
||||
copy(ifr.Ifrn[:], name)
|
||||
|
||||
return &ifr, nil
|
||||
}
|
||||
|
||||
// An ifreqData is an ifreq but with a typed unsafe.Pointer field for data in
|
||||
// the union. This is required in order to comply with the unsafe.Pointer rules
|
||||
// since the "pointer-ness" of data would not be preserved if it were cast into
|
||||
// the byte array of a raw ifreq.
|
||||
type ifreqData struct {
|
||||
name [IFNAMSIZ]byte
|
||||
data unsafe.Pointer
|
||||
// Pad to the same size as ifreq.
|
||||
_ [len(ifreq{}.Ifru) - SizeofPtr]byte
|
||||
}
|
||||
|
||||
// SetData produces an ifreqData with the pointer p set for ioctls which require
|
||||
// arbitrary pointer data.
|
||||
func (ifr ifreq) SetData(p unsafe.Pointer) ifreqData {
|
||||
return ifreqData{
|
||||
name: ifr.Ifrn,
|
||||
data: p,
|
||||
}
|
||||
}
|
||||
|
|
@ -5,7 +5,6 @@
|
|||
package unix
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
|
|
@ -22,56 +21,42 @@ func IoctlRetInt(fd int, req uint) (int, error) {
|
|||
|
||||
func IoctlGetUint32(fd int, req uint) (uint32, error) {
|
||||
var value uint32
|
||||
err := ioctl(fd, req, uintptr(unsafe.Pointer(&value)))
|
||||
err := ioctlPtr(fd, req, unsafe.Pointer(&value))
|
||||
return value, err
|
||||
}
|
||||
|
||||
func IoctlGetRTCTime(fd int) (*RTCTime, error) {
|
||||
var value RTCTime
|
||||
err := ioctl(fd, RTC_RD_TIME, uintptr(unsafe.Pointer(&value)))
|
||||
err := ioctlPtr(fd, RTC_RD_TIME, unsafe.Pointer(&value))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
func IoctlSetRTCTime(fd int, value *RTCTime) error {
|
||||
err := ioctl(fd, RTC_SET_TIME, uintptr(unsafe.Pointer(value)))
|
||||
runtime.KeepAlive(value)
|
||||
return err
|
||||
return ioctlPtr(fd, RTC_SET_TIME, unsafe.Pointer(value))
|
||||
}
|
||||
|
||||
func IoctlGetRTCWkAlrm(fd int) (*RTCWkAlrm, error) {
|
||||
var value RTCWkAlrm
|
||||
err := ioctl(fd, RTC_WKALM_RD, uintptr(unsafe.Pointer(&value)))
|
||||
err := ioctlPtr(fd, RTC_WKALM_RD, unsafe.Pointer(&value))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
func IoctlSetRTCWkAlrm(fd int, value *RTCWkAlrm) error {
|
||||
err := ioctl(fd, RTC_WKALM_SET, uintptr(unsafe.Pointer(value)))
|
||||
runtime.KeepAlive(value)
|
||||
return err
|
||||
}
|
||||
|
||||
type ifreqEthtool struct {
|
||||
name [IFNAMSIZ]byte
|
||||
data unsafe.Pointer
|
||||
return ioctlPtr(fd, RTC_WKALM_SET, unsafe.Pointer(value))
|
||||
}
|
||||
|
||||
// IoctlGetEthtoolDrvinfo fetches ethtool driver information for the network
|
||||
// device specified by ifname.
|
||||
func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) {
|
||||
// Leave room for terminating NULL byte.
|
||||
if len(ifname) >= IFNAMSIZ {
|
||||
return nil, EINVAL
|
||||
ifr, err := newIfreq(ifname)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
value := EthtoolDrvinfo{
|
||||
Cmd: ETHTOOL_GDRVINFO,
|
||||
}
|
||||
ifreq := ifreqEthtool{
|
||||
data: unsafe.Pointer(&value),
|
||||
}
|
||||
copy(ifreq.name[:], ifname)
|
||||
err := ioctl(fd, SIOCETHTOOL, uintptr(unsafe.Pointer(&ifreq)))
|
||||
runtime.KeepAlive(ifreq)
|
||||
value := EthtoolDrvinfo{Cmd: ETHTOOL_GDRVINFO}
|
||||
ifrd := ifr.SetData(unsafe.Pointer(&value))
|
||||
|
||||
err = ioctlPtr(fd, SIOCETHTOOL, unsafe.Pointer(&ifrd))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
|
|
@ -80,7 +65,7 @@ func IoctlGetEthtoolDrvinfo(fd int, ifname string) (*EthtoolDrvinfo, error) {
|
|||
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
|
||||
func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) {
|
||||
var value WatchdogInfo
|
||||
err := ioctl(fd, WDIOC_GETSUPPORT, uintptr(unsafe.Pointer(&value)))
|
||||
err := ioctlPtr(fd, WDIOC_GETSUPPORT, unsafe.Pointer(&value))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
|
|
@ -88,6 +73,7 @@ func IoctlGetWatchdogInfo(fd int) (*WatchdogInfo, error) {
|
|||
// more information, see:
|
||||
// https://www.kernel.org/doc/html/latest/watchdog/watchdog-api.html.
|
||||
func IoctlWatchdogKeepalive(fd int) error {
|
||||
// arg is ignored and not a pointer, so ioctl is fine instead of ioctlPtr.
|
||||
return ioctl(fd, WDIOC_KEEPALIVE, 0)
|
||||
}
|
||||
|
||||
|
|
@ -95,9 +81,7 @@ func IoctlWatchdogKeepalive(fd int) error {
|
|||
// range of data conveyed in value to the file associated with the file
|
||||
// descriptor destFd. See the ioctl_ficlonerange(2) man page for details.
|
||||
func IoctlFileCloneRange(destFd int, value *FileCloneRange) error {
|
||||
err := ioctl(destFd, FICLONERANGE, uintptr(unsafe.Pointer(value)))
|
||||
runtime.KeepAlive(value)
|
||||
return err
|
||||
return ioctlPtr(destFd, FICLONERANGE, unsafe.Pointer(value))
|
||||
}
|
||||
|
||||
// IoctlFileClone performs an FICLONE ioctl operation to clone the entire file
|
||||
|
|
@ -148,7 +132,7 @@ func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error {
|
|||
rawinfo.Reserved = value.Info[i].Reserved
|
||||
}
|
||||
|
||||
err := ioctl(srcFd, FIDEDUPERANGE, uintptr(unsafe.Pointer(&buf[0])))
|
||||
err := ioctlPtr(srcFd, FIDEDUPERANGE, unsafe.Pointer(&buf[0]))
|
||||
|
||||
// Output
|
||||
for i := range value.Info {
|
||||
|
|
@ -166,31 +150,29 @@ func IoctlFileDedupeRange(srcFd int, value *FileDedupeRange) error {
|
|||
}
|
||||
|
||||
func IoctlHIDGetDesc(fd int, value *HIDRawReportDescriptor) error {
|
||||
err := ioctl(fd, HIDIOCGRDESC, uintptr(unsafe.Pointer(value)))
|
||||
runtime.KeepAlive(value)
|
||||
return err
|
||||
return ioctlPtr(fd, HIDIOCGRDESC, unsafe.Pointer(value))
|
||||
}
|
||||
|
||||
func IoctlHIDGetRawInfo(fd int) (*HIDRawDevInfo, error) {
|
||||
var value HIDRawDevInfo
|
||||
err := ioctl(fd, HIDIOCGRAWINFO, uintptr(unsafe.Pointer(&value)))
|
||||
err := ioctlPtr(fd, HIDIOCGRAWINFO, unsafe.Pointer(&value))
|
||||
return &value, err
|
||||
}
|
||||
|
||||
func IoctlHIDGetRawName(fd int) (string, error) {
|
||||
var value [_HIDIOCGRAWNAME_LEN]byte
|
||||
err := ioctl(fd, _HIDIOCGRAWNAME, uintptr(unsafe.Pointer(&value[0])))
|
||||
err := ioctlPtr(fd, _HIDIOCGRAWNAME, unsafe.Pointer(&value[0]))
|
||||
return ByteSliceToString(value[:]), err
|
||||
}
|
||||
|
||||
func IoctlHIDGetRawPhys(fd int) (string, error) {
|
||||
var value [_HIDIOCGRAWPHYS_LEN]byte
|
||||
err := ioctl(fd, _HIDIOCGRAWPHYS, uintptr(unsafe.Pointer(&value[0])))
|
||||
err := ioctlPtr(fd, _HIDIOCGRAWPHYS, unsafe.Pointer(&value[0]))
|
||||
return ByteSliceToString(value[:]), err
|
||||
}
|
||||
|
||||
func IoctlHIDGetRawUniq(fd int) (string, error) {
|
||||
var value [_HIDIOCGRAWUNIQ_LEN]byte
|
||||
err := ioctl(fd, _HIDIOCGRAWUNIQ, uintptr(unsafe.Pointer(&value[0])))
|
||||
err := ioctlPtr(fd, _HIDIOCGRAWUNIQ, unsafe.Pointer(&value[0]))
|
||||
return ByteSliceToString(value[:]), err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -563,6 +563,7 @@ ccflags="$@"
|
|||
$2 ~ /^KEYCTL_/ ||
|
||||
$2 ~ /^PERF_/ ||
|
||||
$2 ~ /^SECCOMP_MODE_/ ||
|
||||
$2 ~ /^SEEK_/ ||
|
||||
$2 ~ /^SPLICE_/ ||
|
||||
$2 ~ /^SYNC_FILE_RANGE_/ ||
|
||||
$2 !~ /^AUDIT_RECORD_MAGIC/ &&
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
package unix
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
|
@ -398,6 +399,38 @@ func GetsockoptXucred(fd, level, opt int) (*Xucred, error) {
|
|||
return x, err
|
||||
}
|
||||
|
||||
func SysctlKinfoProcSlice(name string) ([]KinfoProc, error) {
|
||||
mib, err := sysctlmib(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Find size.
|
||||
n := uintptr(0)
|
||||
if err := sysctl(mib, nil, &n, nil, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if n%SizeofKinfoProc != 0 {
|
||||
return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
|
||||
}
|
||||
|
||||
// Read into buffer of that size.
|
||||
buf := make([]KinfoProc, n/SizeofKinfoProc)
|
||||
if err := sysctl(mib, (*byte)(unsafe.Pointer(&buf[0])), &n, nil, 0); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n%SizeofKinfoProc != 0 {
|
||||
return nil, fmt.Errorf("sysctl() returned a size of %d, which is not a multiple of %d", n, SizeofKinfoProc)
|
||||
}
|
||||
|
||||
// The actual call may return less than the original reported required
|
||||
// size so ensure we deal with that.
|
||||
return buf[:n/SizeofKinfoProc], nil
|
||||
}
|
||||
|
||||
//sys sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error)
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -66,11 +66,18 @@ func Fchmodat(dirfd int, path string, mode uint32, flags int) (err error) {
|
|||
return fchmodat(dirfd, path, mode)
|
||||
}
|
||||
|
||||
//sys ioctl(fd int, req uint, arg uintptr) (err error)
|
||||
//sys ioctl(fd int, req uint, arg uintptr) (err error) = SYS_IOCTL
|
||||
//sys ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) = SYS_IOCTL
|
||||
|
||||
// ioctl itself should not be exposed directly, but additional get/set
|
||||
// functions for specific types are permissible.
|
||||
// These are defined in ioctl.go and ioctl_linux.go.
|
||||
// ioctl itself should not be exposed directly, but additional get/set functions
|
||||
// for specific types are permissible. These are defined in ioctl.go and
|
||||
// ioctl_linux.go.
|
||||
//
|
||||
// The third argument to ioctl is often a pointer but sometimes an integer.
|
||||
// Callers should use ioctlPtr when the third argument is a pointer and ioctl
|
||||
// when the third argument is an integer.
|
||||
//
|
||||
// TODO: some existing code incorrectly uses ioctl when it should use ioctlPtr.
|
||||
|
||||
//sys Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error)
|
||||
|
||||
|
|
|
|||
|
|
@ -1262,6 +1262,11 @@ const (
|
|||
SCM_RIGHTS = 0x1
|
||||
SCM_TIMESTAMP = 0x2
|
||||
SCM_TIMESTAMP_MONOTONIC = 0x4
|
||||
SEEK_CUR = 0x1
|
||||
SEEK_DATA = 0x4
|
||||
SEEK_END = 0x2
|
||||
SEEK_HOLE = 0x3
|
||||
SEEK_SET = 0x0
|
||||
SHUT_RD = 0x0
|
||||
SHUT_RDWR = 0x2
|
||||
SHUT_WR = 0x1
|
||||
|
|
|
|||
|
|
@ -1262,6 +1262,11 @@ const (
|
|||
SCM_RIGHTS = 0x1
|
||||
SCM_TIMESTAMP = 0x2
|
||||
SCM_TIMESTAMP_MONOTONIC = 0x4
|
||||
SEEK_CUR = 0x1
|
||||
SEEK_DATA = 0x4
|
||||
SEEK_END = 0x2
|
||||
SEEK_HOLE = 0x3
|
||||
SEEK_SET = 0x0
|
||||
SHUT_RD = 0x0
|
||||
SHUT_RDWR = 0x2
|
||||
SHUT_WR = 0x1
|
||||
|
|
|
|||
|
|
@ -1297,6 +1297,11 @@ const (
|
|||
SCM_RIGHTS = 0x1
|
||||
SCM_TIMESTAMP = 0x2
|
||||
SCM_TIME_INFO = 0x7
|
||||
SEEK_CUR = 0x1
|
||||
SEEK_DATA = 0x3
|
||||
SEEK_END = 0x2
|
||||
SEEK_HOLE = 0x4
|
||||
SEEK_SET = 0x0
|
||||
SHUT_RD = 0x0
|
||||
SHUT_RDWR = 0x2
|
||||
SHUT_WR = 0x1
|
||||
|
|
|
|||
|
|
@ -1298,6 +1298,11 @@ const (
|
|||
SCM_RIGHTS = 0x1
|
||||
SCM_TIMESTAMP = 0x2
|
||||
SCM_TIME_INFO = 0x7
|
||||
SEEK_CUR = 0x1
|
||||
SEEK_DATA = 0x3
|
||||
SEEK_END = 0x2
|
||||
SEEK_HOLE = 0x4
|
||||
SEEK_SET = 0x0
|
||||
SHUT_RD = 0x0
|
||||
SHUT_RDWR = 0x2
|
||||
SHUT_WR = 0x1
|
||||
|
|
|
|||
|
|
@ -1276,6 +1276,11 @@ const (
|
|||
SCM_CREDS = 0x3
|
||||
SCM_RIGHTS = 0x1
|
||||
SCM_TIMESTAMP = 0x2
|
||||
SEEK_CUR = 0x1
|
||||
SEEK_DATA = 0x3
|
||||
SEEK_END = 0x2
|
||||
SEEK_HOLE = 0x4
|
||||
SEEK_SET = 0x0
|
||||
SHUT_RD = 0x0
|
||||
SHUT_RDWR = 0x2
|
||||
SHUT_WR = 0x1
|
||||
|
|
|
|||
|
|
@ -1298,6 +1298,11 @@ const (
|
|||
SCM_RIGHTS = 0x1
|
||||
SCM_TIMESTAMP = 0x2
|
||||
SCM_TIME_INFO = 0x7
|
||||
SEEK_CUR = 0x1
|
||||
SEEK_DATA = 0x3
|
||||
SEEK_END = 0x2
|
||||
SEEK_HOLE = 0x4
|
||||
SEEK_SET = 0x0
|
||||
SHUT_RD = 0x0
|
||||
SHUT_RDWR = 0x2
|
||||
SHUT_WR = 0x1
|
||||
|
|
|
|||
|
|
@ -2284,6 +2284,12 @@ const (
|
|||
SECCOMP_MODE_FILTER = 0x2
|
||||
SECCOMP_MODE_STRICT = 0x1
|
||||
SECURITYFS_MAGIC = 0x73636673
|
||||
SEEK_CUR = 0x1
|
||||
SEEK_DATA = 0x3
|
||||
SEEK_END = 0x2
|
||||
SEEK_HOLE = 0x4
|
||||
SEEK_MAX = 0x4
|
||||
SEEK_SET = 0x0
|
||||
SELINUX_MAGIC = 0xf97cff8c
|
||||
SHUT_RD = 0x0
|
||||
SHUT_RDWR = 0x2
|
||||
|
|
|
|||
|
|
@ -48,6 +48,16 @@ func ioctl(fd int, req uint, arg uintptr) (err error) {
|
|||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func ioctlPtr(fd int, req uint, arg unsafe.Pointer) (err error) {
|
||||
_, _, e1 := Syscall(SYS_IOCTL, uintptr(fd), uintptr(req), uintptr(arg))
|
||||
if e1 != 0 {
|
||||
err = errnoErr(e1)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
|
||||
|
||||
func Linkat(olddirfd int, oldpath string, newdirfd int, newpath string, flags int) (err error) {
|
||||
var _p0 *byte
|
||||
_p0, err = BytePtrFromString(oldpath)
|
||||
|
|
|
|||
|
|
@ -535,3 +535,107 @@ type CtlInfo struct {
|
|||
Id uint32
|
||||
Name [96]byte
|
||||
}
|
||||
|
||||
const SizeofKinfoProc = 0x288
|
||||
|
||||
type Eproc struct {
|
||||
Paddr uintptr
|
||||
Sess uintptr
|
||||
Pcred Pcred
|
||||
Ucred Ucred
|
||||
Vm Vmspace
|
||||
Ppid int32
|
||||
Pgid int32
|
||||
Jobc int16
|
||||
Tdev int32
|
||||
Tpgid int32
|
||||
Tsess uintptr
|
||||
Wmesg [8]int8
|
||||
Xsize int32
|
||||
Xrssize int16
|
||||
Xccount int16
|
||||
Xswrss int16
|
||||
Flag int32
|
||||
Login [12]int8
|
||||
Spare [4]int32
|
||||
_ [4]byte
|
||||
}
|
||||
|
||||
type ExternProc struct {
|
||||
P_starttime Timeval
|
||||
P_vmspace *Vmspace
|
||||
P_sigacts uintptr
|
||||
P_flag int32
|
||||
P_stat int8
|
||||
P_pid int32
|
||||
P_oppid int32
|
||||
P_dupfd int32
|
||||
User_stack *int8
|
||||
Exit_thread *byte
|
||||
P_debugger int32
|
||||
Sigwait int32
|
||||
P_estcpu uint32
|
||||
P_cpticks int32
|
||||
P_pctcpu uint32
|
||||
P_wchan *byte
|
||||
P_wmesg *int8
|
||||
P_swtime uint32
|
||||
P_slptime uint32
|
||||
P_realtimer Itimerval
|
||||
P_rtime Timeval
|
||||
P_uticks uint64
|
||||
P_sticks uint64
|
||||
P_iticks uint64
|
||||
P_traceflag int32
|
||||
P_tracep uintptr
|
||||
P_siglist int32
|
||||
P_textvp uintptr
|
||||
P_holdcnt int32
|
||||
P_sigmask uint32
|
||||
P_sigignore uint32
|
||||
P_sigcatch uint32
|
||||
P_priority uint8
|
||||
P_usrpri uint8
|
||||
P_nice int8
|
||||
P_comm [17]int8
|
||||
P_pgrp uintptr
|
||||
P_addr uintptr
|
||||
P_xstat uint16
|
||||
P_acflag uint16
|
||||
P_ru *Rusage
|
||||
}
|
||||
|
||||
type Itimerval struct {
|
||||
Interval Timeval
|
||||
Value Timeval
|
||||
}
|
||||
|
||||
type KinfoProc struct {
|
||||
Proc ExternProc
|
||||
Eproc Eproc
|
||||
}
|
||||
|
||||
type Vmspace struct {
|
||||
Dummy int32
|
||||
Dummy2 *int8
|
||||
Dummy3 [5]int32
|
||||
Dummy4 [3]*int8
|
||||
}
|
||||
|
||||
type Pcred struct {
|
||||
Pc_lock [72]int8
|
||||
Pc_ucred uintptr
|
||||
P_ruid uint32
|
||||
P_svuid uint32
|
||||
P_rgid uint32
|
||||
P_svgid uint32
|
||||
P_refcnt int32
|
||||
_ [4]byte
|
||||
}
|
||||
|
||||
type Ucred struct {
|
||||
Ref int32
|
||||
Uid uint32
|
||||
Ngroups int16
|
||||
Groups [16]uint32
|
||||
}
|
||||
|
|
|
|||
|
|
@ -535,3 +535,107 @@ type CtlInfo struct {
|
|||
Id uint32
|
||||
Name [96]byte
|
||||
}
|
||||
|
||||
const SizeofKinfoProc = 0x288
|
||||
|
||||
type Eproc struct {
|
||||
Paddr uintptr
|
||||
Sess uintptr
|
||||
Pcred Pcred
|
||||
Ucred Ucred
|
||||
Vm Vmspace
|
||||
Ppid int32
|
||||
Pgid int32
|
||||
Jobc int16
|
||||
Tdev int32
|
||||
Tpgid int32
|
||||
Tsess uintptr
|
||||
Wmesg [8]int8
|
||||
Xsize int32
|
||||
Xrssize int16
|
||||
Xccount int16
|
||||
Xswrss int16
|
||||
Flag int32
|
||||
Login [12]int8
|
||||
Spare [4]int32
|
||||
_ [4]byte
|
||||
}
|
||||
|
||||
type ExternProc struct {
|
||||
P_starttime Timeval
|
||||
P_vmspace *Vmspace
|
||||
P_sigacts uintptr
|
||||
P_flag int32
|
||||
P_stat int8
|
||||
P_pid int32
|
||||
P_oppid int32
|
||||
P_dupfd int32
|
||||
User_stack *int8
|
||||
Exit_thread *byte
|
||||
P_debugger int32
|
||||
Sigwait int32
|
||||
P_estcpu uint32
|
||||
P_cpticks int32
|
||||
P_pctcpu uint32
|
||||
P_wchan *byte
|
||||
P_wmesg *int8
|
||||
P_swtime uint32
|
||||
P_slptime uint32
|
||||
P_realtimer Itimerval
|
||||
P_rtime Timeval
|
||||
P_uticks uint64
|
||||
P_sticks uint64
|
||||
P_iticks uint64
|
||||
P_traceflag int32
|
||||
P_tracep uintptr
|
||||
P_siglist int32
|
||||
P_textvp uintptr
|
||||
P_holdcnt int32
|
||||
P_sigmask uint32
|
||||
P_sigignore uint32
|
||||
P_sigcatch uint32
|
||||
P_priority uint8
|
||||
P_usrpri uint8
|
||||
P_nice int8
|
||||
P_comm [17]int8
|
||||
P_pgrp uintptr
|
||||
P_addr uintptr
|
||||
P_xstat uint16
|
||||
P_acflag uint16
|
||||
P_ru *Rusage
|
||||
}
|
||||
|
||||
type Itimerval struct {
|
||||
Interval Timeval
|
||||
Value Timeval
|
||||
}
|
||||
|
||||
type KinfoProc struct {
|
||||
Proc ExternProc
|
||||
Eproc Eproc
|
||||
}
|
||||
|
||||
type Vmspace struct {
|
||||
Dummy int32
|
||||
Dummy2 *int8
|
||||
Dummy3 [5]int32
|
||||
Dummy4 [3]*int8
|
||||
}
|
||||
|
||||
type Pcred struct {
|
||||
Pc_lock [72]int8
|
||||
Pc_ucred uintptr
|
||||
P_ruid uint32
|
||||
P_svuid uint32
|
||||
P_rgid uint32
|
||||
P_svgid uint32
|
||||
P_refcnt int32
|
||||
_ [4]byte
|
||||
}
|
||||
|
||||
type Ucred struct {
|
||||
Ref int32
|
||||
Uid uint32
|
||||
Ngroups int16
|
||||
Groups [16]uint32
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1773,6 +1773,8 @@ const (
|
|||
NFPROTO_NUMPROTO = 0xd
|
||||
)
|
||||
|
||||
const SO_ORIGINAL_DST = 0x50
|
||||
|
||||
type Nfgenmsg struct {
|
||||
Nfgen_family uint8
|
||||
Version uint8
|
||||
|
|
|
|||
|
|
@ -170,6 +170,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [16]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x58
|
||||
SizeofIovec = 0x8
|
||||
|
|
|
|||
|
|
@ -173,6 +173,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [24]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x60
|
||||
SizeofIovec = 0x10
|
||||
|
|
|
|||
|
|
@ -176,6 +176,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [16]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x58
|
||||
SizeofIovec = 0x8
|
||||
|
|
|
|||
|
|
@ -174,6 +174,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [24]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x60
|
||||
SizeofIovec = 0x10
|
||||
|
|
|
|||
|
|
@ -175,6 +175,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [16]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x58
|
||||
SizeofIovec = 0x8
|
||||
|
|
|
|||
|
|
@ -174,6 +174,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [24]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x60
|
||||
SizeofIovec = 0x10
|
||||
|
|
|
|||
|
|
@ -174,6 +174,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [24]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x60
|
||||
SizeofIovec = 0x10
|
||||
|
|
|
|||
|
|
@ -175,6 +175,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [16]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x58
|
||||
SizeofIovec = 0x8
|
||||
|
|
|
|||
|
|
@ -176,6 +176,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [16]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x58
|
||||
SizeofIovec = 0x8
|
||||
|
|
|
|||
|
|
@ -175,6 +175,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [24]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x60
|
||||
SizeofIovec = 0x10
|
||||
|
|
|
|||
|
|
@ -175,6 +175,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [24]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x60
|
||||
SizeofIovec = 0x10
|
||||
|
|
|
|||
|
|
@ -174,6 +174,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [24]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x60
|
||||
SizeofIovec = 0x10
|
||||
|
|
|
|||
|
|
@ -173,6 +173,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [24]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x60
|
||||
SizeofIovec = 0x10
|
||||
|
|
|
|||
|
|
@ -177,6 +177,11 @@ type Cmsghdr struct {
|
|||
Type int32
|
||||
}
|
||||
|
||||
type ifreq struct {
|
||||
Ifrn [16]byte
|
||||
Ifru [24]byte
|
||||
}
|
||||
|
||||
const (
|
||||
SizeofSockaddrNFCLLCP = 0x60
|
||||
SizeofIovec = 0x10
|
||||
|
|
|
|||
|
|
@ -680,7 +680,7 @@ const (
|
|||
WTD_CHOICE_CERT = 5
|
||||
|
||||
WTD_STATEACTION_IGNORE = 0x00000000
|
||||
WTD_STATEACTION_VERIFY = 0x00000010
|
||||
WTD_STATEACTION_VERIFY = 0x00000001
|
||||
WTD_STATEACTION_CLOSE = 0x00000002
|
||||
WTD_STATEACTION_AUTO_CACHE = 0x00000003
|
||||
WTD_STATEACTION_AUTO_CACHE_FLUSH = 0x00000004
|
||||
|
|
|
|||
|
|
@ -439,8 +439,10 @@ func (a *application) apply(parent ast.Node, name string, iter *iterator, n ast.
|
|||
}
|
||||
|
||||
default:
|
||||
if typeparams.IsListExpr(n) {
|
||||
a.applyList(n, "ElemList")
|
||||
if ix := typeparams.GetIndexExprData(n); ix != nil {
|
||||
a.apply(n, "X", nil, ix.X)
|
||||
// *ast.IndexExpr was handled above, so n must be an *ast.MultiIndexExpr.
|
||||
a.applyList(n, "Indices")
|
||||
} else {
|
||||
panic(fmt.Sprintf("Apply: unexpected node type %T", n))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1029,6 +1029,7 @@ func predeclared() []types.Type {
|
|||
// used internally by gc; never used by this package or in .a files
|
||||
anyType{},
|
||||
}
|
||||
predecl = append(predecl, additionalPredeclared()...)
|
||||
})
|
||||
return predecl
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ import (
|
|||
"go/types"
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"golang.org/x/tools/internal/typeparams"
|
||||
)
|
||||
|
||||
type intReader struct {
|
||||
|
|
@ -41,6 +43,21 @@ func (r *intReader) uint64() uint64 {
|
|||
return i
|
||||
}
|
||||
|
||||
// Keep this in sync with constants in iexport.go.
|
||||
const (
|
||||
iexportVersionGo1_11 = 0
|
||||
iexportVersionPosCol = 1
|
||||
// TODO: before release, change this back to 2.
|
||||
iexportVersionGenerics = iexportVersionPosCol
|
||||
|
||||
iexportVersionCurrent = iexportVersionGenerics
|
||||
)
|
||||
|
||||
type ident struct {
|
||||
pkg string
|
||||
name string
|
||||
}
|
||||
|
||||
const predeclReserved = 32
|
||||
|
||||
type itag uint64
|
||||
|
|
@ -56,6 +73,9 @@ const (
|
|||
signatureType
|
||||
structType
|
||||
interfaceType
|
||||
typeParamType
|
||||
instanceType
|
||||
unionType
|
||||
)
|
||||
|
||||
// IImportData imports a package from the serialized package data
|
||||
|
|
@ -101,9 +121,13 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
|||
|
||||
version = int64(r.uint64())
|
||||
switch version {
|
||||
case currentVersion, 0:
|
||||
case /* iexportVersionGenerics, */ iexportVersionPosCol, iexportVersionGo1_11:
|
||||
default:
|
||||
errorf("unknown iexport format version %d", version)
|
||||
if version > iexportVersionGenerics {
|
||||
errorf("unstable iexport format version %d, just rebuild compiler and std library", version)
|
||||
} else {
|
||||
errorf("unknown iexport format version %d", version)
|
||||
}
|
||||
}
|
||||
|
||||
sLen := int64(r.uint64())
|
||||
|
|
@ -115,8 +139,9 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
|||
r.Seek(sLen+dLen, io.SeekCurrent)
|
||||
|
||||
p := iimporter{
|
||||
ipath: path,
|
||||
version: int(version),
|
||||
exportVersion: version,
|
||||
ipath: path,
|
||||
version: int(version),
|
||||
|
||||
stringData: stringData,
|
||||
stringCache: make(map[uint64]string),
|
||||
|
|
@ -125,6 +150,9 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
|||
declData: declData,
|
||||
pkgIndex: make(map[*types.Package]map[string]uint64),
|
||||
typCache: make(map[uint64]types.Type),
|
||||
// Separate map for typeparams, keyed by their package and unique
|
||||
// name (name with subscript).
|
||||
tparamIndex: make(map[ident]types.Type),
|
||||
|
||||
fake: fakeFileSet{
|
||||
fset: fset,
|
||||
|
|
@ -216,16 +244,18 @@ func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data
|
|||
}
|
||||
|
||||
type iimporter struct {
|
||||
ipath string
|
||||
version int
|
||||
exportVersion int64
|
||||
ipath string
|
||||
version int
|
||||
|
||||
stringData []byte
|
||||
stringCache map[uint64]string
|
||||
pkgCache map[uint64]*types.Package
|
||||
|
||||
declData []byte
|
||||
pkgIndex map[*types.Package]map[string]uint64
|
||||
typCache map[uint64]types.Type
|
||||
declData []byte
|
||||
pkgIndex map[*types.Package]map[string]uint64
|
||||
typCache map[uint64]types.Type
|
||||
tparamIndex map[ident]types.Type
|
||||
|
||||
fake fakeFileSet
|
||||
interfaceList []*types.Interface
|
||||
|
|
@ -315,17 +345,27 @@ func (r *importReader) obj(name string) {
|
|||
|
||||
r.declare(types.NewConst(pos, r.currPkg, name, typ, val))
|
||||
|
||||
case 'F':
|
||||
case 'F', 'G':
|
||||
var tparams []*typeparams.TypeParam
|
||||
if tag == 'G' {
|
||||
tparams = r.tparamList()
|
||||
}
|
||||
sig := r.signature(nil)
|
||||
|
||||
typeparams.SetForSignature(sig, tparams)
|
||||
r.declare(types.NewFunc(pos, r.currPkg, name, sig))
|
||||
|
||||
case 'T':
|
||||
case 'T', 'U':
|
||||
// Types can be recursive. We need to setup a stub
|
||||
// declaration before recursing.
|
||||
obj := types.NewTypeName(pos, r.currPkg, name, nil)
|
||||
named := types.NewNamed(obj, nil, nil)
|
||||
// Declare obj before calling r.tparamList, so the new type name is recognized
|
||||
// if used in the constraint of one of its own typeparams (see #48280).
|
||||
r.declare(obj)
|
||||
if tag == 'U' {
|
||||
tparams := r.tparamList()
|
||||
typeparams.SetForNamed(named, tparams)
|
||||
}
|
||||
|
||||
underlying := r.p.typAt(r.uint64(), named).Underlying()
|
||||
named.SetUnderlying(underlying)
|
||||
|
|
@ -337,10 +377,46 @@ func (r *importReader) obj(name string) {
|
|||
recv := r.param()
|
||||
msig := r.signature(recv)
|
||||
|
||||
// If the receiver has any targs, set those as the
|
||||
// rparams of the method (since those are the
|
||||
// typeparams being used in the method sig/body).
|
||||
targs := typeparams.NamedTypeArgs(baseType(msig.Recv().Type()))
|
||||
if len(targs) > 0 {
|
||||
rparams := make([]*typeparams.TypeParam, len(targs))
|
||||
for i := range rparams {
|
||||
rparams[i], _ = targs[i].(*typeparams.TypeParam)
|
||||
}
|
||||
typeparams.SetRecvTypeParams(msig, rparams)
|
||||
}
|
||||
|
||||
named.AddMethod(types.NewFunc(mpos, r.currPkg, mname, msig))
|
||||
}
|
||||
}
|
||||
|
||||
case 'P':
|
||||
// We need to "declare" a typeparam in order to have a name that
|
||||
// can be referenced recursively (if needed) in the type param's
|
||||
// bound.
|
||||
if r.p.exportVersion < iexportVersionGenerics {
|
||||
errorf("unexpected type param type")
|
||||
}
|
||||
name0, sub := parseSubscript(name)
|
||||
tn := types.NewTypeName(pos, r.currPkg, name0, nil)
|
||||
t := typeparams.NewTypeParam(tn, nil)
|
||||
if sub == 0 {
|
||||
errorf("missing subscript")
|
||||
}
|
||||
|
||||
// TODO(rfindley): can we use a different, stable ID?
|
||||
// t.SetId(sub)
|
||||
|
||||
// To handle recursive references to the typeparam within its
|
||||
// bound, save the partial type in tparamIndex before reading the bounds.
|
||||
id := ident{r.currPkg.Name(), name}
|
||||
r.p.tparamIndex[id] = t
|
||||
|
||||
typeparams.SetTypeParamConstraint(t, r.typ())
|
||||
|
||||
case 'V':
|
||||
typ := r.typ()
|
||||
|
||||
|
|
@ -618,6 +694,49 @@ func (r *importReader) doType(base *types.Named) types.Type {
|
|||
typ := newInterface(methods, embeddeds)
|
||||
r.p.interfaceList = append(r.p.interfaceList, typ)
|
||||
return typ
|
||||
|
||||
case typeParamType:
|
||||
if r.p.exportVersion < iexportVersionGenerics {
|
||||
errorf("unexpected type param type")
|
||||
}
|
||||
pkg, name := r.qualifiedIdent()
|
||||
id := ident{pkg.Name(), name}
|
||||
if t, ok := r.p.tparamIndex[id]; ok {
|
||||
// We're already in the process of importing this typeparam.
|
||||
return t
|
||||
}
|
||||
// Otherwise, import the definition of the typeparam now.
|
||||
r.p.doDecl(pkg, name)
|
||||
return r.p.tparamIndex[id]
|
||||
|
||||
case instanceType:
|
||||
if r.p.exportVersion < iexportVersionGenerics {
|
||||
errorf("unexpected instantiation type")
|
||||
}
|
||||
// pos does not matter for instances: they are positioned on the original
|
||||
// type.
|
||||
_ = r.pos()
|
||||
len := r.uint64()
|
||||
targs := make([]types.Type, len)
|
||||
for i := range targs {
|
||||
targs[i] = r.typ()
|
||||
}
|
||||
baseType := r.typ()
|
||||
// The imported instantiated type doesn't include any methods, so
|
||||
// we must always use the methods of the base (orig) type.
|
||||
// TODO provide a non-nil *Environment
|
||||
t, _ := typeparams.Instantiate(nil, baseType, targs, false)
|
||||
return t
|
||||
|
||||
case unionType:
|
||||
if r.p.exportVersion < iexportVersionGenerics {
|
||||
errorf("unexpected instantiation type")
|
||||
}
|
||||
terms := make([]*typeparams.Term, r.uint64())
|
||||
for i := range terms {
|
||||
terms[i] = typeparams.NewTerm(r.bool(), r.typ())
|
||||
}
|
||||
return typeparams.NewUnion(terms)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -632,6 +751,20 @@ func (r *importReader) signature(recv *types.Var) *types.Signature {
|
|||
return types.NewSignature(recv, params, results, variadic)
|
||||
}
|
||||
|
||||
func (r *importReader) tparamList() []*typeparams.TypeParam {
|
||||
n := r.uint64()
|
||||
if n == 0 {
|
||||
return nil
|
||||
}
|
||||
xs := make([]*typeparams.TypeParam, n)
|
||||
for i := range xs {
|
||||
// Note: the standard library importer is tolerant of nil types here,
|
||||
// though would panic in SetTypeParams.
|
||||
xs[i] = r.typ().(*typeparams.TypeParam)
|
||||
}
|
||||
return xs
|
||||
}
|
||||
|
||||
func (r *importReader) paramList() *types.Tuple {
|
||||
xs := make([]*types.Var, r.uint64())
|
||||
for i := range xs {
|
||||
|
|
@ -674,3 +807,33 @@ func (r *importReader) byte() byte {
|
|||
}
|
||||
return x
|
||||
}
|
||||
|
||||
func baseType(typ types.Type) *types.Named {
|
||||
// pointer receivers are never types.Named types
|
||||
if p, _ := typ.(*types.Pointer); p != nil {
|
||||
typ = p.Elem()
|
||||
}
|
||||
// receiver base types are always (possibly generic) types.Named types
|
||||
n, _ := typ.(*types.Named)
|
||||
return n
|
||||
}
|
||||
|
||||
func parseSubscript(name string) (string, uint64) {
|
||||
// Extract the subscript value from the type param name. We export
|
||||
// and import the subscript value, so that all type params have
|
||||
// unique names.
|
||||
sub := uint64(0)
|
||||
startsub := -1
|
||||
for i, r := range name {
|
||||
if '₀' <= r && r < '₀'+10 {
|
||||
if startsub == -1 {
|
||||
startsub = i
|
||||
}
|
||||
sub = sub*10 + uint64(r-'₀')
|
||||
}
|
||||
}
|
||||
if startsub >= 0 {
|
||||
name = name[:startsub]
|
||||
}
|
||||
return name, sub
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package gcimporter
|
||||
|
||||
import "go/types"
|
||||
|
||||
func additionalPredeclared() []types.Type {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package gcimporter
|
||||
|
||||
import "go/types"
|
||||
|
||||
// additionalPredeclared returns additional predeclared types in go.1.18.
|
||||
func additionalPredeclared() []types.Type {
|
||||
return []types.Type{
|
||||
// comparable
|
||||
types.Universe.Lookup("comparable").Type(),
|
||||
}
|
||||
}
|
||||
|
|
@ -180,6 +180,8 @@ var stdlib = map[string][]string{
|
|||
"NewReader",
|
||||
"NewWriter",
|
||||
"Order",
|
||||
"Reader",
|
||||
"Writer",
|
||||
},
|
||||
"compress/zlib": []string{
|
||||
"BestCompression",
|
||||
|
|
@ -641,7 +643,9 @@ var stdlib = map[string][]string{
|
|||
"Named",
|
||||
"NamedArg",
|
||||
"NullBool",
|
||||
"NullByte",
|
||||
"NullFloat64",
|
||||
"NullInt16",
|
||||
"NullInt32",
|
||||
"NullInt64",
|
||||
"NullString",
|
||||
|
|
@ -2248,6 +2252,7 @@ var stdlib = map[string][]string{
|
|||
"SHT_LOOS",
|
||||
"SHT_LOPROC",
|
||||
"SHT_LOUSER",
|
||||
"SHT_MIPS_ABIFLAGS",
|
||||
"SHT_NOBITS",
|
||||
"SHT_NOTE",
|
||||
"SHT_NULL",
|
||||
|
|
@ -3061,6 +3066,7 @@ var stdlib = map[string][]string{
|
|||
"ParseExpr",
|
||||
"ParseExprFrom",
|
||||
"ParseFile",
|
||||
"SkipObjectResolution",
|
||||
"SpuriousErrors",
|
||||
"Trace",
|
||||
},
|
||||
|
|
@ -3441,6 +3447,7 @@ var stdlib = map[string][]string{
|
|||
"Pt",
|
||||
"RGBA",
|
||||
"RGBA64",
|
||||
"RGBA64Image",
|
||||
"Rect",
|
||||
"Rectangle",
|
||||
"RegisterFormat",
|
||||
|
|
@ -3507,6 +3514,7 @@ var stdlib = map[string][]string{
|
|||
"Op",
|
||||
"Over",
|
||||
"Quantizer",
|
||||
"RGBA64Image",
|
||||
"Src",
|
||||
},
|
||||
"image/gif": []string{
|
||||
|
|
@ -3612,6 +3620,7 @@ var stdlib = map[string][]string{
|
|||
"FS",
|
||||
"File",
|
||||
"FileInfo",
|
||||
"FileInfoToDirEntry",
|
||||
"FileMode",
|
||||
"Glob",
|
||||
"GlobFS",
|
||||
|
|
@ -3772,15 +3781,18 @@ var stdlib = map[string][]string{
|
|||
"Max",
|
||||
"MaxFloat32",
|
||||
"MaxFloat64",
|
||||
"MaxInt",
|
||||
"MaxInt16",
|
||||
"MaxInt32",
|
||||
"MaxInt64",
|
||||
"MaxInt8",
|
||||
"MaxUint",
|
||||
"MaxUint16",
|
||||
"MaxUint32",
|
||||
"MaxUint64",
|
||||
"MaxUint8",
|
||||
"Min",
|
||||
"MinInt",
|
||||
"MinInt16",
|
||||
"MinInt32",
|
||||
"MinInt64",
|
||||
|
|
@ -4078,6 +4090,7 @@ var stdlib = map[string][]string{
|
|||
"UnknownNetworkError",
|
||||
},
|
||||
"net/http": []string{
|
||||
"AllowQuerySemicolons",
|
||||
"CanonicalHeaderKey",
|
||||
"Client",
|
||||
"CloseNotifier",
|
||||
|
|
@ -4660,6 +4673,7 @@ var stdlib = map[string][]string{
|
|||
"Value",
|
||||
"ValueError",
|
||||
"ValueOf",
|
||||
"VisibleFields",
|
||||
"Zero",
|
||||
},
|
||||
"regexp": []string{
|
||||
|
|
@ -4799,6 +4813,10 @@ var stdlib = map[string][]string{
|
|||
"UnlockOSThread",
|
||||
"Version",
|
||||
},
|
||||
"runtime/cgo": []string{
|
||||
"Handle",
|
||||
"NewHandle",
|
||||
},
|
||||
"runtime/debug": []string{
|
||||
"BuildInfo",
|
||||
"FreeOSMemory",
|
||||
|
|
@ -4915,6 +4933,7 @@ var stdlib = map[string][]string{
|
|||
"QuoteRuneToGraphic",
|
||||
"QuoteToASCII",
|
||||
"QuoteToGraphic",
|
||||
"QuotedPrefix",
|
||||
"Unquote",
|
||||
"UnquoteChar",
|
||||
},
|
||||
|
|
@ -10334,6 +10353,7 @@ var stdlib = map[string][]string{
|
|||
"PipeNode",
|
||||
"Pos",
|
||||
"RangeNode",
|
||||
"SkipFuncCheck",
|
||||
"StringNode",
|
||||
"TemplateNode",
|
||||
"TextNode",
|
||||
|
|
@ -10358,6 +10378,7 @@ var stdlib = map[string][]string{
|
|||
"July",
|
||||
"June",
|
||||
"Kitchen",
|
||||
"Layout",
|
||||
"LoadLocation",
|
||||
"LoadLocationFromTZData",
|
||||
"Local",
|
||||
|
|
@ -10406,6 +10427,8 @@ var stdlib = map[string][]string{
|
|||
"UTC",
|
||||
"Unix",
|
||||
"UnixDate",
|
||||
"UnixMicro",
|
||||
"UnixMilli",
|
||||
"Until",
|
||||
"Wednesday",
|
||||
"Weekday",
|
||||
|
|
|
|||
|
|
@ -9,3 +9,17 @@
|
|||
// This package exists to make it easier for tools to work with generic code,
|
||||
// while also compiling against older Go versions.
|
||||
package typeparams
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
)
|
||||
|
||||
// A IndexExprData holds data from both ast.IndexExpr and the new
|
||||
// ast.MultiIndexExpr, which was introduced in Go 1.18.
|
||||
type IndexExprData struct {
|
||||
X ast.Expr // expression
|
||||
Lbrack token.Pos // position of "["
|
||||
Indices []ast.Expr // index expressions
|
||||
Rbrack token.Pos // position of "]"
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package typeparams
|
||||
|
||||
// Enabled reports whether type parameters are enabled in the current build
|
||||
// environment.
|
||||
const Enabled = false
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package typeparams
|
||||
|
||||
// Note: this constant is in a separate file as this is the only acceptable
|
||||
// diff between the <1.18 API of this package and the 1.18 API.
|
||||
|
||||
// Enabled reports whether type parameters are enabled in the current build
|
||||
// environment.
|
||||
const Enabled = true
|
||||
|
|
@ -1,90 +0,0 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !typeparams || !go1.17
|
||||
// +build !typeparams !go1.17
|
||||
|
||||
package typeparams
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
// NOTE: doc comments must be kept in sync with typeparams.go.
|
||||
|
||||
// Enabled reports whether type parameters are enabled in the current build
|
||||
// environment.
|
||||
const Enabled = false
|
||||
|
||||
// UnpackIndex extracts all index expressions from e. For non-generic code this
|
||||
// is always one expression: e.Index, but may be more than one expression for
|
||||
// generic type instantiation.
|
||||
func UnpackIndex(e *ast.IndexExpr) []ast.Expr {
|
||||
return []ast.Expr{e.Index}
|
||||
}
|
||||
|
||||
// IsListExpr reports whether n is an *ast.ListExpr, which is a new node type
|
||||
// introduced to hold type arguments for generic type instantiation.
|
||||
func IsListExpr(n ast.Node) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ForTypeDecl extracts the (possibly nil) type parameter node list from n.
|
||||
func ForTypeDecl(*ast.TypeSpec) *ast.FieldList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForFuncDecl extracts the (possibly nil) type parameter node list from n.
|
||||
func ForFuncDecl(*ast.FuncDecl) *ast.FieldList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForSignature extracts the (possibly empty) type parameter object list from
|
||||
// sig.
|
||||
func ForSignature(*types.Signature) []*types.TypeName {
|
||||
return nil
|
||||
}
|
||||
|
||||
// HasTypeSet reports if iface has a type set.
|
||||
func HasTypeSet(*types.Interface) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsComparable reports if iface is the comparable interface.
|
||||
func IsComparable(*types.Interface) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsConstraint reports whether iface may only be used as a type parameter
|
||||
// constraint (i.e. has a type set or is the comparable interface).
|
||||
func IsConstraint(*types.Interface) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ForNamed extracts the (possibly empty) type parameter object list from
|
||||
// named.
|
||||
func ForNamed(*types.Named) []*types.TypeName {
|
||||
return nil
|
||||
}
|
||||
|
||||
// NamedTArgs extracts the (possibly empty) type argument list from named.
|
||||
func NamedTArgs(*types.Named) []types.Type {
|
||||
return nil
|
||||
}
|
||||
|
||||
// InitInferred initializes info to record inferred type information.
|
||||
func InitInferred(*types.Info) {
|
||||
}
|
||||
|
||||
// GetInferred extracts inferred type information from info for e.
|
||||
//
|
||||
// The expression e may have an inferred type if it is an *ast.IndexExpr
|
||||
// representing partial instantiation of a generic function type for which type
|
||||
// arguments have been inferred using constraint type inference, or if it is an
|
||||
// *ast.CallExpr for which type type arguments have be inferred using both
|
||||
// constraint type inference and function argument inference.
|
||||
func GetInferred(*types.Info, ast.Expr) ([]types.Type, *types.Signature) {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
@ -1,105 +0,0 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build typeparams && go1.17
|
||||
// +build typeparams,go1.17
|
||||
|
||||
package typeparams
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
// NOTE: doc comments must be kept in sync with notypeparams.go.
|
||||
|
||||
// Enabled reports whether type parameters are enabled in the current build
|
||||
// environment.
|
||||
const Enabled = true
|
||||
|
||||
// UnpackIndex extracts all index expressions from e. For non-generic code this
|
||||
// is always one expression: e.Index, but may be more than one expression for
|
||||
// generic type instantiation.
|
||||
func UnpackIndex(e *ast.IndexExpr) []ast.Expr {
|
||||
if x, _ := e.Index.(*ast.ListExpr); x != nil {
|
||||
return x.ElemList
|
||||
}
|
||||
if e.Index != nil {
|
||||
return []ast.Expr{e.Index}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// IsListExpr reports whether n is an *ast.ListExpr, which is a new node type
|
||||
// introduced to hold type arguments for generic type instantiation.
|
||||
func IsListExpr(n ast.Node) bool {
|
||||
_, ok := n.(*ast.ListExpr)
|
||||
return ok
|
||||
}
|
||||
|
||||
// ForTypeDecl extracts the (possibly nil) type parameter node list from n.
|
||||
func ForTypeDecl(n *ast.TypeSpec) *ast.FieldList {
|
||||
return n.TParams
|
||||
}
|
||||
|
||||
// ForFuncDecl extracts the (possibly nil) type parameter node list from n.
|
||||
func ForFuncDecl(n *ast.FuncDecl) *ast.FieldList {
|
||||
if n.Type != nil {
|
||||
return n.Type.TParams
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForSignature extracts the (possibly empty) type parameter object list from
|
||||
// sig.
|
||||
func ForSignature(sig *types.Signature) []*types.TypeName {
|
||||
return sig.TParams()
|
||||
}
|
||||
|
||||
// HasTypeSet reports if iface has a type set.
|
||||
func HasTypeSet(iface *types.Interface) bool {
|
||||
return iface.HasTypeList()
|
||||
}
|
||||
|
||||
// IsComparable reports if iface is the comparable interface.
|
||||
func IsComparable(iface *types.Interface) bool {
|
||||
return iface.IsComparable()
|
||||
}
|
||||
|
||||
// IsConstraint reports whether iface may only be used as a type parameter
|
||||
// constraint (i.e. has a type set or is the comparable interface).
|
||||
func IsConstraint(iface *types.Interface) bool {
|
||||
return iface.IsConstraint()
|
||||
}
|
||||
|
||||
// ForNamed extracts the (possibly empty) type parameter object list from
|
||||
// named.
|
||||
func ForNamed(named *types.Named) []*types.TypeName {
|
||||
return named.TParams()
|
||||
}
|
||||
|
||||
// NamedTArgs extracts the (possibly empty) type argument list from named.
|
||||
func NamedTArgs(named *types.Named) []types.Type {
|
||||
return named.TArgs()
|
||||
}
|
||||
|
||||
// InitInferred initializes info to record inferred type information.
|
||||
func InitInferred(info *types.Info) {
|
||||
info.Inferred = make(map[ast.Expr]types.Inferred)
|
||||
}
|
||||
|
||||
// GetInferred extracts inferred type information from info for e.
|
||||
//
|
||||
// The expression e may have an inferred type if it is an *ast.IndexExpr
|
||||
// representing partial instantiation of a generic function type for which type
|
||||
// arguments have been inferred using constraint type inference, or if it is an
|
||||
// *ast.CallExpr for which type type arguments have be inferred using both
|
||||
// constraint type inference and function argument inference.
|
||||
func GetInferred(info *types.Info, e ast.Expr) ([]types.Type, *types.Signature) {
|
||||
if info.Inferred == nil {
|
||||
return nil, nil
|
||||
}
|
||||
inf := info.Inferred[e]
|
||||
return inf.TArgs, inf.Sig
|
||||
}
|
||||
164
vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go
generated
vendored
Normal file
164
vendor/golang.org/x/tools/internal/typeparams/typeparams_go117.go
generated
vendored
Normal file
|
|
@ -0,0 +1,164 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !go1.18
|
||||
// +build !go1.18
|
||||
|
||||
package typeparams
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
func unsupported() {
|
||||
panic("type parameters are unsupported at this go version")
|
||||
}
|
||||
|
||||
// GetIndexExprData extracts data from *ast.IndexExpr nodes.
|
||||
// For other nodes, GetIndexExprData returns nil.
|
||||
func GetIndexExprData(n ast.Node) *IndexExprData {
|
||||
if e, _ := n.(*ast.IndexExpr); e != nil {
|
||||
return &IndexExprData{
|
||||
X: e.X,
|
||||
Lbrack: e.Lbrack,
|
||||
Indices: []ast.Expr{e.Index},
|
||||
Rbrack: e.Rbrack,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForTypeDecl returns an empty field list, as type parameters on not supported
|
||||
// at this Go version.
|
||||
func ForTypeDecl(*ast.TypeSpec) *ast.FieldList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForFuncDecl returns an empty field list, as type parameters are not
|
||||
// supported at this Go version.
|
||||
func ForFuncDecl(*ast.FuncDecl) *ast.FieldList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TypeParam is a placeholder type, as type parameters are not supported at
|
||||
// this Go version. Its methods panic on use.
|
||||
type TypeParam struct{ types.Type }
|
||||
|
||||
// TypeParamList is a placeholder for an empty type parameter list.
|
||||
type TypeParamList struct{}
|
||||
|
||||
func (*TypeParamList) Len() int { return 0 }
|
||||
func (*TypeParamList) At(int) *TypeParam { unsupported(); return nil }
|
||||
|
||||
// TypeList is a placeholder for an empty type list.
|
||||
type TypeList struct{}
|
||||
|
||||
func (*TypeList) Len() int { return 0 }
|
||||
func (*TypeList) At(int) types.Type { unsupported(); return nil }
|
||||
|
||||
// NewTypeParam is unsupported at this Go version, and panics.
|
||||
func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam {
|
||||
unsupported()
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetTypeParamConstraint is unsupported at this Go version, and panics.
|
||||
func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
// ForSignature returns an empty slice.
|
||||
func ForSignature(*types.Signature) *TypeParamList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetForSignature panics if tparams is non-empty.
|
||||
func SetForSignature(_ *types.Signature, tparams []*TypeParam) {
|
||||
if len(tparams) > 0 {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
// RecvTypeParams returns a nil slice.
|
||||
func RecvTypeParams(sig *types.Signature) *TypeParamList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetRecvTypeParams panics if rparams is non-empty.
|
||||
func SetRecvTypeParams(sig *types.Signature, rparams []*TypeParam) {
|
||||
if len(rparams) > 0 {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
// IsComparable returns false, as no interfaces are type-restricted at this Go
|
||||
// version.
|
||||
func IsComparable(*types.Interface) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsConstraint returns false, as no interfaces are type-restricted at this Go
|
||||
// version.
|
||||
func IsConstraint(*types.Interface) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// ForNamed returns an empty type parameter list, as type parameters are not
|
||||
// supported at this Go version.
|
||||
func ForNamed(*types.Named) *TypeParamList {
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetForNamed panics if tparams is non-empty.
|
||||
func SetForNamed(_ *types.Named, tparams []*TypeParam) {
|
||||
if len(tparams) > 0 {
|
||||
unsupported()
|
||||
}
|
||||
}
|
||||
|
||||
// NamedTypeArgs extracts the (possibly empty) type argument list from named.
|
||||
func NamedTypeArgs(*types.Named) []types.Type {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Term is a placeholder type, as type parameters are not supported at this Go
|
||||
// version. Its methods panic on use.
|
||||
type Term struct{ types.Type }
|
||||
|
||||
// NewTerm is unsupported at this Go version, and panics.
|
||||
func NewTerm(tilde bool, typ types.Type) *Term {
|
||||
unsupported()
|
||||
return nil
|
||||
}
|
||||
|
||||
// Union is a placeholder type, as type parameters are not supported at this Go
|
||||
// version. Its methods panic on use.
|
||||
type Union struct{ types.Type }
|
||||
|
||||
// NewUnion is unsupported at this Go version, and panics.
|
||||
func NewUnion(terms []*Term) *Union {
|
||||
unsupported()
|
||||
return nil
|
||||
}
|
||||
|
||||
// InitInferred is a noop at this Go version.
|
||||
func InitInferred(*types.Info) {
|
||||
}
|
||||
|
||||
// GetInferred returns nothing, as type parameters are not supported at this Go
|
||||
// version.
|
||||
func GetInferred(*types.Info, ast.Expr) ([]types.Type, *types.Signature) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Environment is a placeholder type, as type parameters are not supported at
|
||||
// this Go version.
|
||||
type Environment struct{}
|
||||
|
||||
// Instantiate is unsupported on this Go version, and panics.
|
||||
func Instantiate(env *Environment, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
|
||||
unsupported()
|
||||
return nil, nil
|
||||
}
|
||||
176
vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go
generated
vendored
Normal file
176
vendor/golang.org/x/tools/internal/typeparams/typeparams_go118.go
generated
vendored
Normal file
|
|
@ -0,0 +1,176 @@
|
|||
// Copyright 2021 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package typeparams
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/types"
|
||||
)
|
||||
|
||||
// GetIndexExprData extracts data from AST nodes that represent index
|
||||
// expressions.
|
||||
//
|
||||
// For an ast.IndexExpr, the resulting IndexExprData will have exactly one
|
||||
// index expression. For an ast.IndexListExpr (go1.18+), it may have a
|
||||
// variable number of index expressions.
|
||||
//
|
||||
// For nodes that don't represent index expressions, GetIndexExprData returns
|
||||
// nil.
|
||||
func GetIndexExprData(n ast.Node) *IndexExprData {
|
||||
switch e := n.(type) {
|
||||
case *ast.IndexExpr:
|
||||
return &IndexExprData{
|
||||
X: e.X,
|
||||
Lbrack: e.Lbrack,
|
||||
Indices: []ast.Expr{e.Index},
|
||||
Rbrack: e.Rbrack,
|
||||
}
|
||||
case *ast.IndexListExpr:
|
||||
return (*IndexExprData)(e)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ForTypeDecl returns n.TypeParams.
|
||||
func ForTypeDecl(n *ast.TypeSpec) *ast.FieldList {
|
||||
return n.TypeParams
|
||||
}
|
||||
|
||||
// ForFuncDecl returns n.Type.TypeParams.
|
||||
func ForFuncDecl(n *ast.FuncDecl) *ast.FieldList {
|
||||
if n.Type != nil {
|
||||
return n.Type.TypeParams
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TypeParam is an alias for types.TypeParam
|
||||
type TypeParam = types.TypeParam
|
||||
|
||||
// TypeParamList is an alias for types.TypeParamList
|
||||
type TypeParamList = types.TypeParamList
|
||||
|
||||
// TypeList is an alias for types.TypeList
|
||||
type TypeList = types.TypeList
|
||||
|
||||
// NewTypeParam calls types.NewTypeParam.
|
||||
func NewTypeParam(name *types.TypeName, constraint types.Type) *TypeParam {
|
||||
return types.NewTypeParam(name, constraint)
|
||||
}
|
||||
|
||||
// SetTypeParamConstraint calls tparam.SetConstraint(constraint).
|
||||
func SetTypeParamConstraint(tparam *TypeParam, constraint types.Type) {
|
||||
tparam.SetConstraint(constraint)
|
||||
}
|
||||
|
||||
// ForSignature returns sig.TypeParams()
|
||||
func ForSignature(sig *types.Signature) *TypeParamList {
|
||||
return sig.TypeParams()
|
||||
}
|
||||
|
||||
// SetForSignature calls sig.SetTypeParams(tparams)
|
||||
func SetForSignature(sig *types.Signature, tparams []*TypeParam) {
|
||||
sig.SetTypeParams(tparams)
|
||||
}
|
||||
|
||||
// RecvTypeParams returns sig.RecvTypeParams().
|
||||
func RecvTypeParams(sig *types.Signature) *TypeParamList {
|
||||
return sig.RecvTypeParams()
|
||||
}
|
||||
|
||||
// SetRecvTypeParams calls sig.SetRecvTypeParams(rparams).
|
||||
func SetRecvTypeParams(sig *types.Signature, rparams []*TypeParam) {
|
||||
sig.SetRecvTypeParams(rparams)
|
||||
}
|
||||
|
||||
// IsComparable calls iface.IsComparable().
|
||||
func IsComparable(iface *types.Interface) bool {
|
||||
return iface.IsComparable()
|
||||
}
|
||||
|
||||
// IsConstraint calls iface.IsConstraint().
|
||||
func IsConstraint(iface *types.Interface) bool {
|
||||
return iface.IsConstraint()
|
||||
}
|
||||
|
||||
// ForNamed extracts the (possibly empty) type parameter object list from
|
||||
// named.
|
||||
func ForNamed(named *types.Named) *TypeParamList {
|
||||
return named.TypeParams()
|
||||
}
|
||||
|
||||
// SetForNamed sets the type params tparams on n. Each tparam must be of
|
||||
// dynamic type *types.TypeParam.
|
||||
func SetForNamed(n *types.Named, tparams []*TypeParam) {
|
||||
n.SetTypeParams(tparams)
|
||||
}
|
||||
|
||||
// NamedTypeArgs extracts the (possibly empty) type argument list from named.
|
||||
func NamedTypeArgs(named *types.Named) []types.Type {
|
||||
targs := named.TypeArgs()
|
||||
numArgs := targs.Len()
|
||||
|
||||
typs := make([]types.Type, numArgs)
|
||||
for i := 0; i < numArgs; i++ {
|
||||
typs[i] = targs.At(i)
|
||||
}
|
||||
|
||||
return typs
|
||||
}
|
||||
|
||||
// Term is an alias for types.Term.
|
||||
type Term = types.Term
|
||||
|
||||
// NewTerm calls types.NewTerm.
|
||||
func NewTerm(tilde bool, typ types.Type) *Term {
|
||||
return types.NewTerm(tilde, typ)
|
||||
}
|
||||
|
||||
// Union is an alias for types.Union
|
||||
type Union = types.Union
|
||||
|
||||
// NewUnion calls types.NewUnion.
|
||||
func NewUnion(terms []*Term) *Union {
|
||||
return types.NewUnion(terms)
|
||||
}
|
||||
|
||||
// InitInferred initializes info to record inferred type information.
|
||||
func InitInferred(info *types.Info) {
|
||||
info.Inferred = make(map[ast.Expr]types.Inferred)
|
||||
}
|
||||
|
||||
// GetInferred extracts inferred type information from info for e.
|
||||
//
|
||||
// The expression e may have an inferred type if it is an *ast.IndexExpr
|
||||
// representing partial instantiation of a generic function type for which type
|
||||
// arguments have been inferred using constraint type inference, or if it is an
|
||||
// *ast.CallExpr for which type type arguments have be inferred using both
|
||||
// constraint type inference and function argument inference.
|
||||
func GetInferred(info *types.Info, e ast.Expr) ([]types.Type, *types.Signature) {
|
||||
if info.Inferred == nil {
|
||||
return nil, nil
|
||||
}
|
||||
inf := info.Inferred[e]
|
||||
|
||||
length := inf.TArgs.Len()
|
||||
|
||||
typs := make([]types.Type, length)
|
||||
for i := 0; i < length; i++ {
|
||||
typs[i] = inf.TArgs.At(i)
|
||||
}
|
||||
|
||||
return typs, inf.Sig
|
||||
}
|
||||
|
||||
// Environment is an alias for types.Environment.
|
||||
type Environment = types.Environment
|
||||
|
||||
// Instantiate calls types.Instantiate.
|
||||
func Instantiate(env *Environment, typ types.Type, targs []types.Type, validate bool) (types.Type, error) {
|
||||
return types.Instantiate(env, typ, targs, validate)
|
||||
}
|
||||
|
|
@ -247,7 +247,7 @@ go.uber.org/automaxprocs/internal/runtime
|
|||
go.uber.org/automaxprocs/maxprocs
|
||||
# go.uber.org/multierr v1.6.0
|
||||
go.uber.org/multierr
|
||||
# go.uber.org/zap v1.19.0
|
||||
# go.uber.org/zap v1.19.1
|
||||
## explicit
|
||||
go.uber.org/zap
|
||||
go.uber.org/zap/buffer
|
||||
|
|
@ -272,7 +272,7 @@ golang.org/x/lint/golint
|
|||
# golang.org/x/mod v0.4.2
|
||||
golang.org/x/mod/module
|
||||
golang.org/x/mod/semver
|
||||
# golang.org/x/net v0.0.0-20210825183410-e898025ed96a
|
||||
# golang.org/x/net v0.0.0-20210917221730-978cfadd31cf
|
||||
## explicit
|
||||
golang.org/x/net/context
|
||||
golang.org/x/net/context/ctxhttp
|
||||
|
|
@ -296,7 +296,7 @@ golang.org/x/oauth2/jwt
|
|||
## explicit
|
||||
golang.org/x/sync/errgroup
|
||||
golang.org/x/sync/semaphore
|
||||
# golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1
|
||||
# golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e
|
||||
golang.org/x/sys/execabs
|
||||
golang.org/x/sys/internal/unsafeheader
|
||||
golang.org/x/sys/plan9
|
||||
|
|
@ -312,7 +312,7 @@ golang.org/x/text/unicode/norm
|
|||
golang.org/x/text/width
|
||||
# golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||
golang.org/x/time/rate
|
||||
# golang.org/x/tools v0.1.5
|
||||
# golang.org/x/tools v0.1.6
|
||||
## explicit
|
||||
golang.org/x/tools/cmd/goimports
|
||||
golang.org/x/tools/go/ast/astutil
|
||||
|
|
|
|||
Loading…
Reference in New Issue