Skip to content

Fix wrong code generation for this-> in lambda type parameters#4955

Draft
SeanTAllen wants to merge 1 commit intomainfrom
fix-lambda-type-this-viewpoint
Draft

Fix wrong code generation for this-> in lambda type parameters#4955
SeanTAllen wants to merge 1 commit intomainfrom
fix-lambda-type-this-viewpoint

Conversation

@SeanTAllen
Copy link
Copy Markdown
Member

When a lambda type contains this-> (e.g., {(this->A!): Bool}), the sugar pass desugars it into an anonymous interface. The desugaring preserved this-> verbatim, but inside the generated interface, this refers to the interface's own receiver rather than the enclosing class's receiver. This caused incorrect structural subtype checks, leading to wrong vtable dispatch, incorrect results, or segfaults when the lambda was forwarded to another function rather than called directly.

The fix resolves this-> to the enclosing method's receiver cap during lambda type desugaring, so {(this->A!)} in a box method correctly becomes {(box->A!)}.

Closes #4168

Lambda types like `{(this->A!): Bool}` are desugared into anonymous
interfaces during the sugar pass. The desugaring preserved `this->`
verbatim, but inside the generated interface, `this` refers to the
interface's own receiver rather than the enclosing class's receiver.
This semantic mismatch caused incorrect structural subtype checks,
leading to wrong vtable dispatch, incorrect results, or segfaults
when the lambda was forwarded to another function.

The fix resolves `this->` to the enclosing method's receiver cap
during lambda type desugaring. Since the compiler already enforces
that `this->` can only appear in `box` methods, `{(this->A!)}` now
correctly desugars to `{(box->A!)}`.

Closes #4168
@SeanTAllen SeanTAllen added the changelog - fixed Automatically add "Fixed" CHANGELOG entry on merge label Mar 7, 2026
@ponylang-main ponylang-main added the discuss during sync Should be discussed during an upcoming sync label Mar 7, 2026
@SeanTAllen
Copy link
Copy Markdown
Member Author

i made a logic error here when working with claude. this is invalid.

@SeanTAllen SeanTAllen marked this pull request as draft March 11, 2026 19:41

The root cause: lambda types are desugared into anonymous interfaces, and `this->` was copied verbatim into the interface. Once inside the interface, `this` referred to the interface's own receiver instead of the enclosing class's receiver, producing the wrong type for structural subtype checks.

`this->` is now resolved to the enclosing method's receiver capability during desugaring, so `{(this->A!)}` in a `box` method correctly becomes `{(box->A!)}`.
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrong.

Discussed in sync.

Consider a type Foo, which has a fun box, in which a lambda is born with this->A! as the parameter type

We need the lambda to get sugared to a generic type, where the type parameter has a constraint of Foo #read. Then The generic anonymous lambda type gets instantiated at the call site with a type parameter of this->Foo'ref, which is effectively the way to "pass in" the correct constrained generic cap of the this (of the fun box).

As I said in the sync call, fun box is actually in reality fun #read but we call it fun box for historical/aesthetic reasons.

@jemc jemc removed the discuss during sync Should be discussed during an upcoming sync label Mar 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

changelog - fixed Automatically add "Fixed" CHANGELOG entry on merge

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Wrong code generation/memory errors in generic lambda parameters

3 participants