ast, cgen: fix receiver methods on embedded interfaces (fix #19550) #12
Macho0x
This PR fixes the compiler error and incorrect runtime behavior when calling a receiver method (defined outside an interface) on an interface that embeds another interface.
Fixes #19550.
## Problem
Given:
```v
interface Node {
name string
mut:
children []&Node
}
fn (mut node Node) append_child(child &Node) {
node.children << child
}
interface Element {
Node
attributes map[string]string
}
// HTMLBodyElement implements Element (and therefore Node)
```
Calling element.append_child(&Node(&Text{...})) on a value of type &Element failed with:
error: cannot implement interface `Element` with a different interface `&Node`
Even when the checker error was bypassed, the generated code reinterpreted the Element* interface struct as a Node*, leading to incorrect field offsets and broken runtime behavior.
Root cause
1. When an interface embeds another interface, new_method_with_receiver_type was rewriting self-referential parameters of concrete receiver methods to match the outer interface type. That made signatures such as fn (mut n Node) add(child &Node) appear to require &Element, which is wrong.
2. In cgen, calling a method inherited from an embedded interface used a raw pointer cast from the outer interface struct to the embedded interface struct. The two structs have different C layouts, so the cast read/wrote the wrong fields.
Fix
- vlib/v/ast/ast.v: new_method_with_receiver_type now only transforms self-referential parameters for interface method declarations (no_body == true). Concrete receiver methods keep their original parameter types.
- vlib/v/gen/c/fn.v: when the receiver is an interface and the method comes from an embedded interface, generate an interface-to-interface conversion (I_