Part of #1785. Design: #1772. Depends on #1786.
(2) Static-method this-binding on class-object values
Problem
After #1786, a method call on a class-object value (const A = make(x); A.greet()) is resolved statically to the template at compile time, and the class_id vtable path passes this = undefined. So typeof this is undefined inside the static method and this.field (effect's annotations/pipe read this.ast) throws. Static methods also use a different this convention than instance methods on the dispatch path.
Scope
A method call whose receiver is a class-object value must dispatch dynamically and bind this to that value:
- HIR/codegen: a
recv.method(...) where recv is a runtime value (not a statically-known class name) lowers to a dynamic method call passing recv as this — not a compile-time StaticMethodCall on the template.
- Runtime: the class_id dispatch path passes the receiver as
this for static methods (reconcile the static-vs-instance this convention).
this.field inside the static method resolves dynamically on the receiver (own field → prototype walk), not a compile-time static-field-get on the template.
Acceptance criteria
function make(a){ return class { static ast=a; static viaThis(){ return this.ast } } } → make("X").viaThis() === "X", make("Y").viaThis() === "Y".
typeof (make("X")).someStaticMethod === "function"; calling it sees this = the class object.
- No regression to static-method calls on top-level class declarations.
Blocks
(6).
Part of #1785. Design: #1772. Depends on #1786.
(2) Static-method
this-binding on class-object valuesProblem
After #1786, a method call on a class-object value (
const A = make(x); A.greet()) is resolved statically to the template at compile time, and the class_id vtable path passesthis = undefined. Sotypeof thisisundefinedinside the static method andthis.field(effect'sannotations/pipereadthis.ast) throws. Static methods also use a differentthisconvention than instance methods on the dispatch path.Scope
A method call whose receiver is a class-object value must dispatch dynamically and bind
thisto that value:recv.method(...)whererecvis a runtime value (not a statically-known class name) lowers to a dynamic method call passingrecvasthis— not a compile-timeStaticMethodCallon the template.thisfor static methods (reconcile the static-vs-instancethisconvention).this.fieldinside the static method resolves dynamically on the receiver (own field → prototype walk), not a compile-time static-field-get on the template.Acceptance criteria
function make(a){ return class { static ast=a; static viaThis(){ return this.ast } } }→make("X").viaThis() === "X",make("Y").viaThis() === "Y".typeof (make("X")).someStaticMethod === "function"; calling it seesthis= the class object.Blocks
(6).