Cannot convert struct to interface if it has an embedded struct with a method
I upgraded a project from 23a0d19a6b1e to 3d21d22d88e2 and am now having troubles converting a struct to an interface.
The exact problem stems from converting a struct with an embedded struct, wherein both structs have unique methods, to a typed interface. If only one of the structs has methods, the problem goes away.
Minimal reproducible code:
package main
import (
"github.com/cosmos72/gomacro/fast"
)
func main() {
interp := fast.New()
src := `
type VEntity interface {
A() int
B() int
}
type BaseEntity struct {
}
func (e *BaseEntity) A() int {
return 0
}
type ExtendedEntity struct {
BaseEntity
}
func (e *ExtendedEntity) B() int {
return 1
}
entity := &ExtendedEntity{}
ventity := VEntity(entity) // <-- this line causes panic: runtime error: invalid memory address or nil pointer dereference
`
interp.Compile(src)
}
Error output:
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x111c8b9]
goroutine 1 [running]:
github.com/cosmos72/gomacro/xreflect.Type.AssignableTo(0x2193770?, 0x1?)
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/xreflect/api.go:50 +0x19
github.com/cosmos72/gomacro/fast.(*Comp).converterToEmulatedInterface(0xc0002ee300, 0xc0003dd8b0, 0xc0003dd490)
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/interface.go:194 +0x21f
github.com/cosmos72/gomacro/fast.(*Comp).Converter(0xc0002ee300, 0xc0003dd8b0, 0xc0003dd490)
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/convert.go:197 +0x292
github.com/cosmos72/gomacro/fast.(*Comp).convert(0xc0002ee300, 0xc0004c2500, 0xc0003dd490, {0x19de210?, 0xc0004b0200})
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/convert.go:150 +0xb2b
github.com/cosmos72/gomacro/fast.(*Comp).Convert(0xc0002ee300?, {0x19de210, 0xc0004b0200}, 0xc0003dd8b0?)
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/convert.go:31 +0x4b
github.com/cosmos72/gomacro/fast.(*Comp).CallExpr(0x30?, 0xc0004b4340)
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/call.go:69 +0x7d
github.com/cosmos72/gomacro/fast.(*Comp).expr(0xc0002ee300, {0x19ddf10?, 0xc0004b4340?}, 0x7ff9b19a45b8?)
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/expr.go:134 +0x345
github.com/cosmos72/gomacro/fast.(*Comp).expr1(0xc0002ee300, {0x19ddf10?, 0xc0004b4340?}, 0x87b087?)
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/expr.go:101 +0x174
github.com/cosmos72/gomacro/fast.(*Comp).exprs(0x15e0540?, {0xc0003dd1c0, 0x1, 0x7ff988bc26d0?})
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/expr.go:63 +0x99
github.com/cosmos72/gomacro/fast.(*Comp).ExprsMultipleValues(0x0?, {0xc0003dd1c0?, 0xc0003497f0?, 0x8bfd92?}, 0x8?)
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/expr.go:47 +0x38
github.com/cosmos72/gomacro/fast.(*Comp).prepareDeclConstsOrVars(0xc0003d6c88?, {0xc0003dd9a0, 0x1, 0x1}, {0x0?, 0x0?}, {0xc0003dd1c0?, 0xc0003dd910?, 0xc0003fcac0?})
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/declaration.go:228 +0xb8
github.com/cosmos72/gomacro/fast.(*Comp).DeclVarsShort(0xc0002ee300, {0xc0003dd1a0, 0x1, 0xc0003498f8?}, {0xc0003dd1c0, 0x1, 0x1})
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/declaration.go:200 +0x168
github.com/cosmos72/gomacro/fast.(*Comp).Assign(0xc0002ee300, 0xc0004b4300)
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/assignment.go:51 +0x156
github.com/cosmos72/gomacro/fast.(*Comp).Stmt(0xc0002ee300, {0x19ddd90?, 0xc0004b4300?})
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/statement.go:58 +0x825
github.com/cosmos72/gomacro/fast.(*Comp).compileNode(0xc0002ee300, {0x19db9f8?, 0xc0004b4300?}, 0x8)
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/compile.go:468 +0x47a
github.com/cosmos72/gomacro/fast.(*Comp).compileDecl(0xc0002ee300?, 0xc0004b4400?)
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/compile.go:415 +0x1f0
github.com/cosmos72/gomacro/fast.(*Comp).Compile(0xc0002ee300, {0x19e2d20, 0xc0003f9d40})
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/compile.go:375 +0x4b0
github.com/cosmos72/gomacro/fast.(*Interp).CompileAst(0xc0003dceb0?, {0x19e2d20?, 0xc0003f9d40?})
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/repl.go:95 +0x12b
github.com/cosmos72/gomacro/fast.(*Interp).Compile(0x0?, {0x17d518a?, 0xc0000061a0?})
/home/kts/go/pkg/mod/github.com/cosmos72/[email protected]/fast/repl.go:75 +0x35
main.main()
/home/kts/Develop/gotest/macro/main.go:36 +0x2a
exit status 2
The exact version where this becomes a problem is c54504072dd530e7af76a461c8423afa606016a4.
Thanks for spotting this, and more thanks for the bisection!
Commit c54504072dd530e7af76a461c8423afa606016a4 is a bugfix, which replaces a complicated (and broken) workaround with a clean implementation. But from the regression you found, it seems the bugfix is not fully correct.
I will investigate it.
Bug confirmed. Interestingly enough, executing the same code at REPL does not trigger the bug. I suspect some gomacro's implementation confusion between compile-time and runtime.
Commit 4d60a7fa0e9aa11205148fea08669e13dc0c322e detects this bug, and replaces the generic panic message
panic: runtime error: invalid memory address or nil pointer dereference
with the more detailed
panic: repl.go:24:28: cannot convert from <*main.ExtendedEntity> to <main.VEntity>: internal error, method B of <*main.ExtendedEntity> has nil type!
(known bug under investigation, see https://github.com/cosmos72/gomacro/issues/139)
It's not a solution, but at least I've narrowed it down to a method type being (unexpectedly) nil.