ast, cgen: fix receiver methods on embedded interfaces (fix #19550)#27476
ast, cgen: fix receiver methods on embedded interfaces (fix #19550)#27476Macho0x wants to merge 1 commit into
Conversation
- Only rewrite self-referential parameters for interface method declarations in new_method_with_receiver_type; keep concrete receiver method parameters unchanged. - Generate an interface-to-interface conversion for the receiver when calling a method inherited from an embedded interface, instead of reinterpreting the interface struct pointer. - Add regression test.
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 439aa2bb35
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| embed_value_type) | ||
| g.writeln(';') | ||
| g.write(stmt_str) | ||
| g.write('&${tmp}') |
There was a problem hiding this comment.
Drop stale ADDR wrapper before passing the temp receiver
When this embedded-interface method call is on a non-lvalue receiver (for example make_element().append_child(...)) or an interface smartcast, the receiver setup above has already emitted an ADDR(rec_cc_type, ... wrapper instead of a literal &. This branch only strips &, then writes &tmp, so the later cast_n close produces C like ADDR(EmbeddedIface, &tmp), wrapping a pointer where the macro expects an interface value and causing otherwise valid calls to fail to compile.
Useful? React with 👍 / 👎.
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:
Calling element.append_child(&Node(&Text{...})) on a value of type &Element failed with:
error: cannot implement interface
Elementwith a different interface&NodeEven 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
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.
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
Test
Added vlib/v/tests/interfaces/interface_receiver_method_on_embedded_interface_test.v, which exercises:
Verification