diff --git a/.golangci.next.reference.yml b/.golangci.next.reference.yml index 6938157d..361b92c2 100644 --- a/.golangci.next.reference.yml +++ b/.golangci.next.reference.yml @@ -1387,14 +1387,16 @@ linters-settings: min-complexity: 4 nilnil: - # Checks that there is no simultaneous return of `nil` error and an invalid value. - # Default: ["ptr", "func", "iface", "map", "chan"] + # List of return types to check. + # Default: ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"] checked-types: - ptr - func - iface - map - chan + - uintptr + - unsafeptr nlreturn: # Size of the block (including return statement that is still "OK") diff --git a/go.mod b/go.mod index 9a7442aa..3cd592c8 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/4meepo/tagalign v1.3.4 github.com/Abirdcfly/dupword v0.0.14 github.com/Antonboom/errname v0.1.13 - github.com/Antonboom/nilnil v0.1.8 + github.com/Antonboom/nilnil v0.1.9 github.com/Antonboom/testifylint v1.2.0 github.com/BurntSushi/toml v1.3.2 github.com/Crocmagnon/fatcontext v0.2.2 diff --git a/go.sum b/go.sum index 7e95eece..694fb6ee 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/Abirdcfly/dupword v0.0.14 h1:3U4ulkc8EUo+CaT105/GJ1BQwtgyj6+VaBVbAX11 github.com/Abirdcfly/dupword v0.0.14/go.mod h1:VKDAbxdY8YbKUByLGg8EETzYSuC4crm9WwI6Y3S0cLI= github.com/Antonboom/errname v0.1.13 h1:JHICqsewj/fNckzrfVSe+T33svwQxmjC+1ntDsHOVvM= github.com/Antonboom/errname v0.1.13/go.mod h1:uWyefRYRN54lBg6HseYCFhs6Qjcy41Y3Jl/dVhA87Ns= -github.com/Antonboom/nilnil v0.1.8 h1:97QG7xrLq4TBK2U9aFq/I8Mcgz67pwMIiswnTA9gIn0= -github.com/Antonboom/nilnil v0.1.8/go.mod h1:iGe2rYwCq5/Me1khrysB4nwI7swQvjclR8/YRPl5ihQ= +github.com/Antonboom/nilnil v0.1.9 h1:eKFMejSxPSA9eLSensFmjW2XTgTwJMjZ8hUHtV4s/SQ= +github.com/Antonboom/nilnil v0.1.9/go.mod h1:iGe2rYwCq5/Me1khrysB4nwI7swQvjclR8/YRPl5ihQ= github.com/Antonboom/testifylint v1.2.0 h1:015bxD8zc5iY8QwTp4+RG9I4kIbqwvGX9TrBbb7jGdM= github.com/Antonboom/testifylint v1.2.0/go.mod h1:rkmEqjqVnHDRNsinyN6fPSLnoajzFwsCcguJgwADBkw= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= diff --git a/jsonschema/golangci.next.jsonschema.json b/jsonschema/golangci.next.jsonschema.json index e7684df3..5b008275 100644 --- a/jsonschema/golangci.next.jsonschema.json +++ b/jsonschema/golangci.next.jsonschema.json @@ -2082,11 +2082,11 @@ "properties": { "checked-types": { "type": "array", - "description": "Order of return types to check.", + "description": "List of return types to check.", "items": { - "enum": ["ptr", "func", "iface", "map", "chan"] + "enum": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"] }, - "default": ["ptr", "func", "iface", "map", "chan"] + "default": ["ptr", "func", "iface", "map", "chan", "uintptr", "unsafeptr"] } } }, diff --git a/pkg/golinters/nilnil/testdata/nilnil.go b/pkg/golinters/nilnil/testdata/nilnil.go index fd62faf5..970ef24d 100644 --- a/pkg/golinters/nilnil/testdata/nilnil.go +++ b/pkg/golinters/nilnil/testdata/nilnil.go @@ -2,7 +2,11 @@ package testdata import ( + "bytes" + "go/token" "io" + "net/http" + "os" "unsafe" ) @@ -24,6 +28,26 @@ func anonymousStructPtr() (*struct{ ID string }, error) { return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" } +func unsafePtr() (unsafe.Pointer, error) { + return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + +func uintPtr() (uintptr, error) { + return 0, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + +func uintPtr0b() (uintptr, error) { + return 0b0, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + +func uintPtr0x() (uintptr, error) { + return 0x00, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + +func uintPtr0o() (uintptr, error) { + return 0o000, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + func chBi() (chan int, error) { return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" } @@ -48,6 +72,10 @@ func iface() (interface{}, error) { return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" } +func anyType() (any, error) { + return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + func m1() (map[int]int, error) { return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" } @@ -56,6 +84,12 @@ func m2() (map[int]*User, error) { return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" } +type mapAlias = map[int]*User + +func m3() (mapAlias, error) { + return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + type Storage struct{} func (s *Storage) GetUser() (*User, error) { @@ -119,6 +153,39 @@ func deeplyNested() { } } +type MyError interface { + error + Code() string +} + +func myError() (*User, MyError) { + return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + +// Types. + +func structPtrTypeExtPkg() (*os.File, error) { + return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + +func primitivePtrTypeExtPkg() (*token.Token, error) { + return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + +func funcTypeExtPkg() (http.HandlerFunc, error) { + return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + +func ifaceTypeExtPkg() (io.Closer, error) { + return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + +type closerAlias = io.Closer + +func ifaceTypeAliasedExtPkg() (closerAlias, error) { + return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + type ( StructPtrType *User PrimitivePtrType *int @@ -147,21 +214,93 @@ func ifaceType() (Checker, error) { return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" } +type checkerAlias = Checker + +func ifaceTypeAliased() (checkerAlias, error) { + return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + +type ( + IntegerType int + PtrIntegerType *IntegerType +) + +func ptrIntegerType() (PtrIntegerType, error) { + return nil, nil // want "return both the `nil` error and invalid value: use a sentinel error instead" +} + +// Not checked at all. + func withoutArgs() {} func withoutError1() *User { return nil } func withoutError2() (*User, *User) { return nil, nil } func withoutError3() (*User, *User, *User) { return nil, nil, nil } func withoutError4() (*User, *User, *User, *User) { return nil, nil, nil, nil } -// Unsupported. - func invalidOrder() (error, *User) { return nil, nil } func withError3rd() (*User, bool, error) { return nil, false, nil } func withError4th() (*User, *User, *User, error) { return nil, nil, nil, nil } -func unsafePtr() (unsafe.Pointer, error) { return nil, nil } -func uintPtr() (uintptr, error) { return 0, nil } -func slice() ([]int, error) { return nil, nil } -func ifaceExtPkg() (io.Closer, error) { return nil, nil } + +func slice() ([]int, error) { return nil, nil } + +func strNil() (string, error) { return "nil", nil } +func strEmpty() (string, error) { return "", nil } + +// Valid. + +func primitivePtrTypeValid() (*int, error) { + if false { + return nil, io.EOF + } + return new(int), nil +} + +func structPtrTypeValid() (*User, error) { + if false { + return nil, io.EOF + } + return new(User), nil +} + +func unsafePtrValid() (unsafe.Pointer, error) { + if false { + return nil, io.EOF + } + var i int + return unsafe.Pointer(&i), nil +} + +func uintPtrValid() (uintptr, error) { + if false { + return 0, io.EOF + } + return 0xc82000c290, nil +} + +func channelTypeValid() (ChannelType, error) { + if false { + return nil, io.EOF + } + return make(ChannelType), nil +} + +func funcTypeValid() (FuncType, error) { + if false { + return nil, io.EOF + } + return func(i int) int { + return 0 + }, nil +} + +func ifaceTypeValid() (io.Reader, error) { + if false { + return nil, io.EOF + } + return new(bytes.Buffer), nil +} + +// Unsupported. func implicitNil1() (*User, error) { err := (error)(nil)