-
Notifications
You must be signed in to change notification settings - Fork 17.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
cmd/compile: recursive anonymous interface defs compile but fail to run #10222
Comments
Yes, both these programs should compile and run. This appears to be a bug in the gc compiler and/or runtime. I suspect it's the compiler since it has other known issues with recursively defined anonymous interfaces. For comparison, the first program runs fine when compiled with gccgo. |
I had a poke at this, and I think I have an inkling of what's going on. In some sense the type symbol for T should be an infinite string interface { f() interface { f() interface { f() interface { ... (with an infinite balancing number of }s). Now it's clear that if type symbols really could be infinite, the interface string for interface { T } is the same. But in fact of course type symbols cannot be infinite and the compiler truncates at a certain level of nesting, and the levels are different for T and interface { T }. so the type symbols are different (it's something eyeball melting like "interface { main.m() interface { main.m() interface { main.m() interface { main.m() interface { main.m() interface { main.m<...> } } } } } }" vs "interface { main.m() interface { main.m() interface { main.m() interface { main.m() interface { main.m<...> } } } } }"). I'm not entirely sure why the Trecur check in TConv triggers at different depths, but I find that code fairly confusing. It's possible it could be bodged but a real fix probably needs a real computer scientist (skimming wikipedia suggests what we are doing here is trying to compute type equivalence in an equirecursive type system and this paper: http://gallium.inria.fr/~fpottier/publis/gauthier-fpottier-icfp04.pdf) |
Fundamentally, this type is recursive; internally this means that the data structure representing the type has a (pointer) loop. More generally, this can happen with any type data structure containing loops. Trying to serialize such a data structure in finite form (e.g., print it in text form) requires some mechanism to break the loop. The straight-forward algorithm to serialize cyclic data structures is to mark (e.g., number) each node, and when a node is encountered that was seen before during serialization, instead of serializing it again, use that number to refer to it. It may be possible to export nodes in a clever order (after sorting them topologically) and preserve the current textual export format that emulates source code. Cycles would be broken by using identifiers, similar to what we do when we write cyclic type definitions in the first place. Another alternative is to ditch the current format and use an algorithm that can handle cycles from the outset. x/tools/go/importer implements this for go/types. |
On 21 April 2015 at 11:53, Robert Griesemer notifications@github.com
Right. The straight-forward algorithm to serialize cyclic data structures is to
|
This is very low priority and no one is planning to fix it, unless someone provides evidence that it's important for some reason. The new export data should make this a bit easier, and at least now this is a compile failure as opposed to a death at run time. |
There's a newer issue that has more information. I'm going to close this one as duplicate of #16369. |
Should this program work?
It seems to compile but panics when run:
http://play.golang.org/p/swxTnFlwQI
By contrast this program works fine:
http://play.golang.org/p/Bxnf72xPsn
The text was updated successfully, but these errors were encountered: