gomacro
gomacro copied to clipboard
Cannot use co-dependent types with each other that implement a common interface
The following code produces cannot use <*main.SceneB> as <main.Scene> in argument to switchTo:
package main
import (
"github.com/cosmos72/gomacro/fast"
)
func main() {
interp := fast.New()
interp.Eval(`
import "fmt"
type Scene interface {
Init()
Destroy()
}
var globalScene Scene
func switchTo(s Scene) {
if globalScene != nil {
globalScene.Destroy()
}
globalScene = s
s.Init()
}
type SceneA struct {
}
func (s *SceneA) Init() {
fmt.Println("Init")
switchTo(&SceneB{})
}
func (s *SceneA) Destroy() {
fmt.Println("Destroy")
}
type SceneB struct {
}
func (s *SceneB) Init() {
fmt.Println("Init")
switchTo(&SceneA{})
}
func (s *SceneB) Destroy() {
fmt.Println("Destroy")
}
switchTo(&SceneA{})
`)
}
In the actual code I'm using, where this problem cropped up, the switchTo function isn't called in the global scope, but rather by an interpreter function that is invoked by the host-side. Same problem in that context.
This deviates from expected Go behavior, as the evaluated code compiles and runs under standard Go.
Hello @kettek, your code really pushes the interpreter to its limits, for several reasons:
- support for out-of-order code, i.e. code that refers to declarations appearing later, was added as an after-thought and has some limitations.
- interpreted interfaces are emulated, because there is no
reflect.InterfaceOffunction - mutually recursive types are emulated too, because
reflect.StructOfdoes not support them. In this case, only methods of the two types mutually reference the each other, but the first call toswitchTo(Scene)appears before the typeSceneBand its methods are declared, thus I suspect gomacro will not recognize that*SceneBimplementsSceneat the call siteswitchTo(&SceneB{})