Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ jobs:

steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v6
with:
fetch-depth: 0

- name: Set up Go
uses: actions/setup-go@v2
uses: actions/setup-go@v6
with:
go-version: 1.24
go-version: '1.26'

- name: Unit tests
run: go test -coverprofile=cover.out ./...
Expand Down
3 changes: 3 additions & 0 deletions _testdata/26/bar.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
type twentysixB[T twentysixB[T]] interface {
xyz(T) T
}
3 changes: 3 additions & 0 deletions _testdata/26/foo.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
func twentysixA() *int {
return new(17)
}
42 changes: 41 additions & 1 deletion decl.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,32 @@ func (p *pkgScanner) valueSpec(spec *ast.ValueSpec) (bool, error) {
}

func (p *pkgScanner) typeSpec(spec *ast.TypeSpec) (bool, error) {
var generic bool

if spec.TypeParams != nil && len(spec.TypeParams.List) > 0 {
generic = true
p.result(posResult{
version: 18,
pos: p.fset.Position(spec.Pos()),
desc: "generic type decl",
})

v := recursiveTypeParamVisitor{name: spec.Name}
ast.Walk(&v, spec.TypeParams)
if v.found {
isMax := p.result(posResult{
version: 26,
pos: p.fset.Position(spec.Pos()),
desc: "recursive type parameter",
})
if isMax {
return true, nil
}
}
}

if spec.Assign.IsValid() {
if spec.TypeParams != nil && len(spec.TypeParams.List) > 0 {
if generic {
p.result(posResult{
version: 24,
pos: p.fset.Position(spec.Pos()),
Expand All @@ -117,3 +141,19 @@ func (p *pkgScanner) typeSpec(spec *ast.TypeSpec) (bool, error) {
}
return p.expr(spec.Type)
}

type recursiveTypeParamVisitor struct {
name *ast.Ident
found bool
}

func (v *recursiveTypeParamVisitor) Visit(node ast.Node) ast.Visitor {
if v.found {
return nil
}
if ident, ok := node.(*ast.Ident); ok && ident.Name == v.name.Name {
v.found = true
return nil
}
return v
}
15 changes: 15 additions & 0 deletions expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -450,6 +450,21 @@ func (p *pkgScanner) builtinCall(expr *ast.CallExpr) (bool, error) {
if p.result(result) {
return true, nil
}

case "new":
if len(expr.Args) == 1 {
arg := expr.Args[0]
if typ, ok := p.info.Types[arg]; ok && !typ.IsType() {
result := posResult{
version: 26,
pos: p.fset.Position(expr.Pos()),
desc: "use of new builtin with non-type argument",
}
if p.result(result) {
return true, nil
}
}
}
}

case *ast.SelectorExpr:
Expand Down
12 changes: 5 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
module github.com/bobg/mingo

go 1.23.0

toolchain go1.24.1
go 1.26

require (
github.com/bobg/errors v1.1.0
github.com/bobg/errors v1.3.0
github.com/bobg/go-generics/v4 v4.2.0
golang.org/x/mod v0.27.0
golang.org/x/tools v0.36.0
golang.org/x/mod v0.33.0
golang.org/x/tools v0.42.0
)

require golang.org/x/sync v0.16.0 // indirect
require golang.org/x/sync v0.19.0 // indirect
14 changes: 8 additions & 6 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
github.com/bobg/errors v1.1.0 h1:gsVanPzJMpZQpwY+27/GQYElZez5CuMYwiIpk2A3RGw=
github.com/bobg/errors v1.1.0/go.mod h1:Q4775qBZpnte7EGFJqmvnlB1U4pkI1XmU3qxqdp7Zcc=
github.com/bobg/errors v1.3.0 h1:LJlNiQniZ+wm+kEwRblYYAsY3+DkW4ekPdjZF0raYfk=
github.com/bobg/errors v1.3.0/go.mod h1:HExZHNKjrSozaLs3/X7HpryCMRBKV6SQXngfQJ9wYb8=
github.com/bobg/go-generics/v4 v4.2.0 h1:c3eX8rlFCRrxFnUepwQIA174JK7WuckbdRHf5ARCl7w=
github.com/bobg/go-generics/v4 v4.2.0/go.mod h1:KVwpxEYErjvcqjJSJqVNZd/JEq3SsQzb9t01+82pZGw=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/mod v0.33.0 h1:tHFzIWbBifEmbwtGz65eaWyGiGZatSrT9prnU8DbVL8=
golang.org/x/mod v0.33.0/go.mod h1:swjeQEj+6r7fODbD2cqrnje9PnziFuw4bmLbBZFrQ5w=
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
golang.org/x/tools v0.42.0 h1:uNgphsn75Tdz5Ji2q36v/nsFSfR/9BRFvqhGBaJGd5k=
golang.org/x/tools v0.42.0/go.mod h1:Ma6lCIwGZvHK6XtgbswSoWroEkhugApmsXyrUmBhfr0=
2 changes: 2 additions & 0 deletions hist.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,8 @@ func goroot() string {
if g := os.Getenv("GOROOT"); g != "" {
return g
}

//lint:ignore SA1019 We actually do want the behavior that is the reason runtime.GOROOT is deprecated.
return runtime.GOROOT()
}

Expand Down
11 changes: 3 additions & 8 deletions mingo_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,16 +163,11 @@ func TestLangChecks(t *testing.T) {
t.Run("CheckFail", func(t *testing.T) {
_, err := s.ScanDir(tmpdir)

var (
verr VersionError
lerr LoadError
)
switch {
case errors.As(err, &lerr):
if _, ok := errors.AsType[VersionError](err); ok {
// Do nothing
case errors.As(err, &verr):
} else if _, ok := errors.AsType[LoadError](err); ok {
// Do nothing
default:
} else {
t.Errorf("got error %v, want a LoadError or VersionError", err)
}
})
Expand Down
Loading