go: cmd/compile: internal compiler error: incomplete itab
commit 098599003ba78225152d22984f82f78892221dad
The following code panics: https://gotipplay.golang.org/p/FR0-a4NF08e
package main
type S struct{}
func (S) M() byte {
return 0
}
type I[T any] interface {
M() T
}
func F[T, A any](x I[T]) {
_ = x.(A)
}
func main() {
F[byte, string](S{})
}
The panic that I see is:
goroutine 1 [running]:
runtime/debug.Stack()
/home/rogpeppe/go/src/runtime/debug/stack.go:24 +0x65
cmd/compile/internal/base.FatalfAt({0x3f0460?, 0xc0?}, {0xd20742, 0xf}, {0x0, 0x0, 0x0})
/home/rogpeppe/go/src/cmd/compile/internal/base/print.go:227 +0x1ca
cmd/compile/internal/base.Fatalf(...)
/home/rogpeppe/go/src/cmd/compile/internal/base/print.go:196
cmd/compile/internal/reflectdata.writeITab(0xc000498700, 0xc0003f0460, 0xc00049f960)
/home/rogpeppe/go/src/cmd/compile/internal/reflectdata/reflect.go:1310 +0x42b
cmd/compile/internal/reflectdata.ITabLsym(0x138cd80?, 0xc00049d520?)
/home/rogpeppe/go/src/cmd/compile/internal/reflectdata/reflect.go:856 +0x19c
cmd/compile/internal/noder.(*genInst).finalizeSyms(0x138cd80)
/home/rogpeppe/go/src/cmd/compile/internal/noder/stencil.go:1727 +0x64d
cmd/compile/internal/noder.(*genInst).buildInstantiations(0x138cd80, 0x1)
/home/rogpeppe/go/src/cmd/compile/internal/noder/stencil.go:76 +0xb0
cmd/compile/internal/noder.BuildInstantiations(...)
/home/rogpeppe/go/src/cmd/compile/internal/noder/stencil.go:47
cmd/compile/internal/noder.(*irgen).generate(0xc0004c2000, {0xc00011eb90, 0x2, 0x203000?})
/home/rogpeppe/go/src/cmd/compile/internal/noder/irgen.go:320 +0x3db
cmd/compile/internal/noder.check2({0xc00011eb90, 0x2, 0x2})
/home/rogpeppe/go/src/cmd/compile/internal/noder/irgen.go:92 +0x16d
cmd/compile/internal/noder.LoadPackage({0xc00013a0f0, 0x2, 0x0?})
/home/rogpeppe/go/src/cmd/compile/internal/noder/noder.go:90 +0x335
cmd/compile/internal/gc.Main(0xd497d8)
/home/rogpeppe/go/src/cmd/compile/internal/gc/main.go:191 +0xb13
main.main()
/home/rogpeppe/go/src/cmd/compile/main.go:55 +0xdd
Thanks to @norunners on the Gophers Slack for reporting this.
About this issue
- Original URL
- State: closed
- Created 3 years ago
- Reactions: 1
- Comments: 24 (22 by maintainers)
I’m also leaning towards choice 2 at the moment. It seems to me that we should report a compile-time error only if there’s no possible instantiation for which the type assertion can succeed; but clearly there are instantiations for which this code can succeed.
For instance, in this case
we correctly report a compile-time error, even though we don’t in this case:
for historic reasons (and we can’t fix that for backward-compatibility reasons). In both these cases the type assertion cannot succeed, no matter the dynamic types.
I’d say that was true in this case. All instantiations are indeed valid, because the static “cannot happen” compiler check that you can have in a regular function isn’t appropriate in this case.
My concern here is that by getting people into the habit of writing
any(v).(T)
rather than justv.(T)
, we will be losing opportunities for the compiler to point out genuinely impossible type conversions.For example: https://gotipplay.golang.org/p/6blhiU8j_ZO
@rogpeppe A design principle of generics is that if a generic type/function declaration is valid, then all instantiations should be valid too. There shouldn’t be cases where changing the implementation detail of a generic function could suddenly result in some downstream uses to start failing to compile.
That design isn’t perfectly achieved today (e.g.,
chan T
will fail to instantiate forT
larger than 64KiB, but we could fix this by autoboxing large element types), but it’s something we’ve strived for in other areas.@mdempsky Why would we want to reject the declaration of
F
when it can manifestly be instantiated correctly? https://gotipplay.golang.org/p/3ytXbPMMR7hI think (1) is probably not that hard, maybe https://golang.org/cl/369774 suffices? Also, @griesemer it looks like this is fall-out from the recent change to the underlying of a type parameter to be its constraint interface.
That CL is just a proof of concept; I’m still not sure what’s correct here. However, we have thus far erred on the side of disallowing features that we’re unsure about.
Why would there be a runtime error at line 14? Surely it should just fail to select the case?