mgechev / revive

🔥 ~6x faster, stricter, configurable, extensible, and beautiful drop-in replacement for golint
https://revive.run
MIT License
4.74k stars 276 forks source link

Revive process hangs on invalid recursive type #849

Closed cordis-dev closed 1 year ago

cordis-dev commented 1 year ago

To Reproduce Steps to reproduce the behavior: Given this source file:

package p

type B[T any] interface {
    B /* ERROR "invalid recursive type" */ [*T]
}

type C[T any, U B[U]] interface {
    *T
}

Try to lint it using revive v1.3.2 (Windows):

revive.exe test.go

Expected behavior Revive process should complete.

Additional context Source file is taken from https://github.com/golang/go/blob/master/src/internal/types/testdata/fixedbugs/issue56665.go

chavacava commented 1 year ago

Hi @cordis-dev thanks for filling the issue. I'll take a look on it.

denisvmedia commented 1 year ago

I checked and the problem starts here:

// check function encapsulates the call to go/types.Config.Check method and
// recovers if the called method panics (see issue #59)
func check(config *types.Config, n string, fset *token.FileSet, astFiles []*ast.File, info *types.Info) (p *types.Package, err error) {
    defer func() {
        if r := recover(); r != nil {
            err, _ = r.(error)
            p = nil
            return
        }
    }()

    return config.Check(n, fset, astFiles, info) // <=== here
}

Internally, it uses types built-in package, which then hangs in this function:

// computeInterfaceTypeSet may be called with check == nil.
func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_TypeSet {

And it seems to be a bug in go itself. Because you cannot compile this code (it also hangs):

package main

type B[T any] interface {
    B /* ERROR "invalid recursive type" */ [*T]
}

type C[T any, U B[U]] interface {
    *T
}

func main() {
}
denisvmedia commented 1 year ago

Update: the problem was in go 1.19. But it's not a problem in go 1.20 (I didn't research on a particular commit/version where it was resolved), thus revive has to be built with a version after >= 1.20.

% ./revive
p.go:1:1: should have a package comment
p.go:3:6: exported type B should have comment or be unexported
p.go:7:6: exported type C should have comment or be unexported

This is how it looks like, when revive is built with go 1.20.7 (default configuration).

chavacava commented 1 year ago

Hi @denisvmedia, thanks for the update on this issue.