From e4bcf9008eff5751eb3b6dbac045b2190d943ab5 Mon Sep 17 00:00:00 2001 From: Justin Hwang Date: Fri, 18 Sep 2026 23:42:22 -0400 Subject: [PATCH] Require Go 1.20, test on 1.25/1.26/1.27 The CI matrix (1.17/1.18/1.19) had aged out of upstream support, and the pinned lint tooling no longer builds on any current toolchain: golang.org/x/tools@v0.12.1/internal/tokeninternal.go:78:9: invalid array length -delta * delta (constant -256 of type int64) Move the matrix to 1.25/1.26/1.27, with lint running on 1.27. Raise the module's minimum Go version only as far as the source actually requires: Pointer[T] wraps sync/atomic.Pointer[T], which landed in 1.19, so 1.20 is the floor. Neither dependency constrains this further -- testify v1.12.1 declares go 1.17 and go.yaml.in/yaml/v3 declares go 1.16. Bump honnef.co/go/tools to v0.8.1 so staticcheck and golint compile again. staticcheck v0.8.1 declares `go 1.26.0`, so the tools module sits well ahead of the library; it is build-only and does not affect consumers. This supersedes #203. With a 1.20 floor, the pointer build variants are dead code: the `go1.18 && !go1.19` constraint is unsatisfiable, so delete that file. The surviving Pointer[T] is the sync/atomic.Pointer[T] implementation that every supported toolchain already selected. With no build tags left, the go118/go119 split is meaningless, so merge the two survivors into a single pointer.go. Note that CI does not build on 1.20-1.24, so the declared floor is a compatibility promise rather than a tested configuration. Co-Authored-By: Claude Opus 5 (1M context) --- .github/workflows/go.yml | 4 +-- go.mod | 2 +- pointer_go119.go => pointer.go | 29 +++++++++++++--- pointer_go118.go | 49 --------------------------- pointer_go118_pre119.go | 60 ---------------------------------- pointer_test.go | 3 -- tools/go.mod | 14 ++++---- tools/go.sum | 29 ++++++++-------- 8 files changed, 51 insertions(+), 139 deletions(-) rename pointer_go119.go => pointer.go (77%) delete mode 100644 pointer_go118.go delete mode 100644 pointer_go118_pre119.go diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 5f813db..ba40995 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -16,9 +16,9 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - go: ["1.17.x", "1.18.x", "1.19.x"] + go: ["1.25.x", "1.26.x", "1.27.x"] include: - - go: 1.19.x + - go: 1.27.x latest: true steps: diff --git a/go.mod b/go.mod index e036492..5725741 100644 --- a/go.mod +++ b/go.mod @@ -4,4 +4,4 @@ require github.com/stretchr/testify v1.12.1 require go.yaml.in/yaml/v3 v3.0.5 // indirect -go 1.18 +go 1.20 diff --git a/pointer_go119.go b/pointer.go similarity index 77% rename from pointer_go119.go rename to pointer.go index 6726f17..6dd470e 100644 --- a/pointer_go119.go +++ b/pointer.go @@ -18,12 +18,13 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -//go:build go1.19 -// +build go1.19 - package atomic -import "sync/atomic" +import ( + "encoding/json" + "fmt" + "sync/atomic" +) // Pointer is an atomic pointer of type *T. type Pointer[T any] struct { @@ -59,3 +60,23 @@ func (p *Pointer[T]) Swap(val *T) (old *T) { func (p *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) { return p.p.CompareAndSwap(old, new) } + +// String returns a human readable representation of a Pointer's underlying value. +func (p *Pointer[T]) String() string { + return fmt.Sprint(p.Load()) +} + +// MarshalJSON encodes the wrapped pointer into JSON. +func (p *Pointer[T]) MarshalJSON() ([]byte, error) { + return json.Marshal(p.Load()) +} + +// UnmarshalJSON decodes JSON into the wrapped pointer. +func (p *Pointer[T]) UnmarshalJSON(b []byte) error { + var v T + if err := json.Unmarshal(b, &v); err != nil { + return err + } + p.Store(&v) + return nil +} diff --git a/pointer_go118.go b/pointer_go118.go deleted file mode 100644 index fb7e124..0000000 --- a/pointer_go118.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (c) 2022 Uber Technologies, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//go:build go1.18 -// +build go1.18 - -package atomic - -import ( - "encoding/json" - "fmt" -) - -// String returns a human readable representation of a Pointer's underlying value. -func (p *Pointer[T]) String() string { - return fmt.Sprint(p.Load()) -} - -// MarshalJSON encodes the wrapped pointer into JSON. -func (p *Pointer[T]) MarshalJSON() ([]byte, error) { - return json.Marshal(p.Load()) -} - -// UnmarshalJSON decodes JSON into the wrapped pointer. -func (p *Pointer[T]) UnmarshalJSON(b []byte) error { - var v T - if err := json.Unmarshal(b, &v); err != nil { - return err - } - p.Store(&v) - return nil -} diff --git a/pointer_go118_pre119.go b/pointer_go118_pre119.go deleted file mode 100644 index e0f47db..0000000 --- a/pointer_go118_pre119.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) 2022 Uber Technologies, Inc. -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in -// all copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -// THE SOFTWARE. - -//go:build go1.18 && !go1.19 -// +build go1.18,!go1.19 - -package atomic - -import "unsafe" - -type Pointer[T any] struct { - _ nocmp // disallow non-atomic comparison - p UnsafePointer -} - -// NewPointer creates a new Pointer. -func NewPointer[T any](v *T) *Pointer[T] { - var p Pointer[T] - if v != nil { - p.p.Store(unsafe.Pointer(v)) - } - return &p -} - -// Load atomically loads the wrapped value. -func (p *Pointer[T]) Load() *T { - return (*T)(p.p.Load()) -} - -// Store atomically stores the passed value. -func (p *Pointer[T]) Store(val *T) { - p.p.Store(unsafe.Pointer(val)) -} - -// Swap atomically swaps the wrapped pointer and returns the old value. -func (p *Pointer[T]) Swap(val *T) (old *T) { - return (*T)(p.p.Swap(unsafe.Pointer(val))) -} - -// CompareAndSwap is an atomic compare-and-swap. -func (p *Pointer[T]) CompareAndSwap(old, new *T) (swapped bool) { - return p.p.CompareAndSwap(unsafe.Pointer(old), unsafe.Pointer(new)) -} diff --git a/pointer_test.go b/pointer_test.go index edb2d41..1c01ec8 100644 --- a/pointer_test.go +++ b/pointer_test.go @@ -18,9 +18,6 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. -//go:build go1.18 -// +build go1.18 - package atomic import ( diff --git a/tools/go.mod b/tools/go.mod index 46d4e8f..dbe59d3 100644 --- a/tools/go.mod +++ b/tools/go.mod @@ -1,16 +1,16 @@ module go.uber.org/atomic/tools -go 1.18 +go 1.26.0 require ( golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 - honnef.co/go/tools v0.4.7 + honnef.co/go/tools v0.8.1 ) require ( - github.com/BurntSushi/toml v1.2.1 // indirect - golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a // indirect - golang.org/x/mod v0.12.0 // indirect - golang.org/x/sys v0.11.0 // indirect - golang.org/x/tools v0.12.1-0.20230825192346-2191a27a6dc5 // indirect + github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c // indirect + golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 // indirect + golang.org/x/mod v0.35.0 // indirect + golang.org/x/sync v0.20.0 // indirect + golang.org/x/tools v0.44.1-0.20260420230617-19499e7caabc // indirect ) diff --git a/tools/go.sum b/tools/go.sum index 23b9558..f276352 100644 --- a/tools/go.sum +++ b/tools/go.sum @@ -1,26 +1,29 @@ -github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak= -github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c h1:pxW6RcqyfI9/kWtOwnv/G+AzdKuy2ZrqINhenH4HyNs= +github.com/BurntSushi/toml v1.4.1-0.20240526193622-a339e1f7089c/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= 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/exp/typeparams v0.0.0-20221208152030-732eee02a75a h1:Jw5wfR+h9mnIYH+OtGT2im5wV1YGGDora5vTv/aa5bE= -golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= +golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678 h1:1P7xPZEwZMoBoz0Yze5Nx2/4pxj6nw9ZqHWXqP0iRgQ= +golang.org/x/exp/typeparams v0.0.0-20231108232855-2478ac86f678/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug= golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= -golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.35.0 h1:Ww1D637e6Pg+Zb2KrWfHQUnH2dQRLBQyAtpr/haaJeM= +golang.org/x/mod v0.35.0/go.mod h1:+GwiRhIInF8wPm+4AoT6L0FA1QWAad3OMdTRx4tFYlU= 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/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= +golang.org/x/sync v0.20.0 h1:e0PTpb7pjO8GAtTs2dQ6jYa5BWYlMuX047Dco/pItO4= +golang.org/x/sync v0.20.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0= 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.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM= -golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.12.1-0.20230825192346-2191a27a6dc5 h1:Vk4mysSz+GqQK2eqgWbo4zEO89wkeAjJiFIr9bpqa8k= -golang.org/x/tools v0.12.1-0.20230825192346-2191a27a6dc5/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= +golang.org/x/tools v0.44.1-0.20260420230617-19499e7caabc h1:vSv/HN1q9eoPD7lMyJYVJ/GPYnqtqu6adMxUmrxOB78= +golang.org/x/tools v0.44.1-0.20260420230617-19499e7caabc/go.mod h1:KA0AfVErSdxRZIsOVipbv3rQhVXTnlU6UhKxHd1seDI= +golang.org/x/tools/go/expect v0.1.1-deprecated h1:jpBZDwmgPhXsKZC6WhL20P4b/wmnpsEAGHaNy0n/rJM= +golang.org/x/tools/go/expect v0.1.1-deprecated/go.mod h1:eihoPOH+FgIqa3FpoTwguz/bVUSGBlGQU67vpBeOrBY= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -honnef.co/go/tools v0.4.7 h1:9MDAWxMoSnB6QoSqiVr7P5mtkT9pOc1kSxchzPCnqJs= -honnef.co/go/tools v0.4.7/go.mod h1:+rnGS1THNh8zMwnd2oVOTL9QF6vmfyG6ZXBULae2uc0= +honnef.co/go/tools v0.8.1 h1:+JKf3xJ1ni4CwrhVg4/pqsfPGP6vNAXcKbMXJodYx3w= +honnef.co/go/tools v0.8.1/go.mod h1:XA+OnlRA9EDh/ukGvXMNSZNKGwFQJ+5dER0ioUkOxks=