golang / go

The Go programming language
https://go.dev
BSD 3-Clause "New" or "Revised" License
124.24k stars 17.7k forks source link

cmd/go2go: assertion failed in go/types/subst.go: (makeSubstMap) #39976

Closed arl closed 4 years ago

arl commented 4 years ago

What version of Go are you using (go version)?

$ go version
go version devel +6cf6bf162c Wed Jul 1 00:31:32 2020 +0000 linux/amd64

Does this issue reproduce with the latest release?

It does with the latest commit, at time of writing, of the dev.go2go experimental branch: 6cf6bf162c

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/aurelien/.cache/go-build"
GOENV="/home/aurelien/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/aurelien/dev/go2/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/aurelien/dev/go2"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/home/aurelien/dev/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/home/aurelien/dev/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build655914420=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Running the following file:

package main

// entry stores cached entry key and value.
type entry(type K comparable, V any) struct {
    key   K
    value V

    // accessed is the number of nanoseconds elapsed between the cache epoch and the last time the key was accessed.
    accessed uint64
    // updated is the number of nanoseconds elapsed between the cache epoch and the last time the key was updated.
    updated uint64

    // hash of this key
    hash uint64
}

// any is a convenient type bounds.
type any interface{}

// policy is a cache eviction policy.
type policy(type K comparable, V any) interface {
    init(cache *Cache(K, V), maximumSize int)
    add(*entry(K, V)) *entry(K, V)
    del(*entry(K, V)) *entry(K, V)
}

// LRU is a least-frequently-used policy.
type LRU(type K comparable, V any) struct{}

func (p *LRU(K, V)) init(cache *Cache(K, V), maximumSize int) {}
func (p *LRU(K, V)) add(*entry(K, V)) *entry(K, V)            { return nil }
func (p *LRU(K, V)) del(*entry(K, V)) *entry(K, V)            { return nil }

type Cache(type K comparable, V any) struct {
    policy policy(K, V)
}

func NewCache(type K comparable, V any)(maxkeys uint64, p policy(K, V)) Cache(K, V) {
    return Cache(K, V){
        policy: p,
    }
}

func main() {
    lru := LRU(int, string){}
//  c := NewCache(int, string)(256, &lru) // ok: compiles and run
    c := NewCache(256, &lru) // nok: go2go panics
    _ = c
}

triggers:

$ go tool go2go run issue.go
panic: assertion failed [recovered]
        panic: assertion failed

goroutine 1 [running]:
go/types.(*Checker).handleBailout(0xc00011c5a0, 0xc0001879f8)
        /home/aurelien/dev/go/src/go/types/check.go:251 +0x98
panic(0x649860, 0x6db4a0)
        /home/aurelien/dev/go/src/runtime/panic.go:969 +0x175
go/types.assert(...)
        /home/aurelien/dev/go/src/go/types/errors.go:19
go/types.makeSubstMap(0xc000066ed0, 0x2, 0x2, 0xc000179080, 0x2, 0x2, 0xc000185c60)
        /home/aurelien/dev/go/src/go/types/subst.go:34 +0x2ae
go/types.(*Checker).infer.func1(0x696d0d, 0x4, 0x6e7020, 0xc000071200, 0x6e6b20, 0xc000179060, 0xc0001731c0)
        /home/aurelien/dev/go/src/go/types/infer.go:24 +0x95
go/types.(*Checker).infer(0xc00011c5a0, 0x51e, 0xc000066ed0, 0x2, 0x2, 0xc000178ec0, 0xc000067520, 0x2, 0x2, 0xc00011c5a0, ...)
        /home/aurelien/dev/go/src/go/types/infer.go:54 +0x435
go/types.(*Checker).arguments(0xc00011c5a0, 0xc000037480, 0xc0000711a0, 0xc000067520, 0x2, 0x2, 0x2)
        /home/aurelien/dev/go/src/go/types/call.go:319 +0x305
go/types.(*Checker).call(0xc00011c5a0, 0xc000173140, 0xc000037480, 0xc000172180)
        /home/aurelien/dev/go/src/go/types/call.go:117 +0x585
go/types.(*Checker).exprInternal(0xc00011c5a0, 0xc000173140, 0x6e33a0, 0xc000037480, 0x0, 0x0, 0x5883b2)
        /home/aurelien/dev/go/src/go/types/expr.go:1569 +0x1dd0
go/types.(*Checker).rawExpr(0xc00011c5a0, 0xc000173140, 0x6e33a0, 0xc000037480, 0x0, 0x0, 0x0)
        /home/aurelien/dev/go/src/go/types/expr.go:1033 +0xc5
go/types.(*Checker).multiExpr(0xc00011c5a0, 0xc000173140, 0x6e33a0, 0xc000037480)
        /home/aurelien/dev/go/src/go/types/expr.go:1692 +0x51
go/types.(*Checker).exprList(0xc00011c5a0, 0xc000066c80, 0x1, 0x1, 0x81bb00, 0x7f18ec9a0108, 0x0, 0x50, 0xc00017e6e0)
        /home/aurelien/dev/go/src/go/types/call.go:206 +0xb4
go/types.(*Checker).initVars(0xc00011c5a0, 0xc00000e468, 0x1, 0x1, 0xc000066c80, 0x1, 0x1, 0x0)
        /home/aurelien/dev/go/src/go/types/assignments.go:214 +0x94
go/types.(*Checker).shortVarDecl(0xc00011c5a0, 0x509, 0xc000066c40, 0x1, 0x1, 0xc000066c80, 0x1, 0x1)
        /home/aurelien/dev/go/src/go/types/assignments.go:326 +0x27e
go/types.(*Checker).stmt(0xc00011c5a0, 0x0, 0x6e31a0, 0xc0000374c0)
        /home/aurelien/dev/go/src/go/types/stmt.go:403 +0x351d
go/types.(*Checker).stmtList(0xc00011c5a0, 0x0, 0xc000037540, 0x3, 0x4)
        /home/aurelien/dev/go/src/go/types/stmt.go:125 +0xd1
go/types.(*Checker).funcBody(0xc00011c5a0, 0xc0000709c0, 0xc00002a75c, 0x4, 0xc000071620, 0xc0000115c0, 0x0, 0x0)
        /home/aurelien/dev/go/src/go/types/stmt.go:42 +0x257
go/types.(*Checker).funcDecl.func1()
        /home/aurelien/dev/go/src/go/types/decl.go:793 +0x67
go/types.(*Checker).processDelayed(0xc00011c5a0, 0x0)
        /home/aurelien/dev/go/src/go/types/check.go:315 +0x3e
go/types.(*Checker).checkFiles(0xc00011c5a0, 0xc00000e228, 0x1, 0x1, 0x0, 0x0)
        /home/aurelien/dev/go/src/go/types/check.go:283 +0x145
go/types.(*Checker).Files(...)
        /home/aurelien/dev/go/src/go/types/check.go:256
go/types.(*Config).Check(0xc000037580, 0xc00002a530, 0x4, 0xc000036280, 0xc00000e228, 0x1, 0x1, 0xc00007b360, 0x1, 0x0, ...)
        /home/aurelien/dev/go/src/go/types/api.go:387 +0x188
go/go2go.rewriteFilesInPath(0xc0000703c0, 0x0, 0x0, 0xc0000166a0, 0x17, 0xc000066490, 0x1, 0x1, 0x0, 0x0, ...)
        /home/aurelien/dev/go/src/go/go2go/go2go.go:93 +0x4dd
go/go2go.rewriteToPkgs(0xc0000703c0, 0x0, 0x0, 0xc0000166a0, 0x17, 0xc0000101a0, 0xc0000166a0, 0x17, 0x7ffca31cc840, 0x9)
        /home/aurelien/dev/go/src/go/go2go/go2go.go:46 +0x165
go/go2go.Rewrite(...)
        /home/aurelien/dev/go/src/go/go2go/go2go.go:30
main.translate(0xc0000703c0, 0xc0000166a0, 0x17)
        /home/aurelien/dev/go/src/cmd/go2go/translate.go:15 +0x47
main.main()
        /home/aurelien/dev/go/src/cmd/go2go/main.go:54 +0xb25

What did you expect to see?

Not sure about the type inference rule here, but I was either expecting a message telling me that the type of NewCache can't be inferred or a successful compilation.

What did you see instead?

go2go panicked.

Note I think the code is straightforward but I can always try to provide a smaller reproducer

arl commented 4 years ago

Slightly smaller reproducer with which the bottom 8 frames before the panic are the same, the rest differs since the code is different:

package main

type (
    any interface{}

    policy(type K comparable, V any) interface{}

    LRU(type K comparable, V any) struct{}

    Cache(type K comparable, V any) struct{}
)

func NewCache(type K comparable, V any)(p policy(K, V)) {}

func main() {
    lru := LRU(int, string){}
    //  NewCache(int, string)(&lru) // ok: compiles and run
    NewCache(&lru) // nok: 'go tool go2go run' panics
}
ianlancetaylor commented 4 years ago

Seems to have broken fairly recently.

griesemer commented 4 years ago

Thanks. This was triggered by the fix for #39725.

gopherbot commented 4 years ago

Change https://golang.org/cl/240718 mentions this issue: [dev.go2go] go/types: fix assertion failure, better error message for inference failure

griesemer commented 4 years ago

Fixed on dev.go2go.