Skip to content

super.<prop> value-form lowering silently returns child override instead of parent #774

@proggeramlug

Description

@proggeramlug

Background

PR #754 lowered value-form super.<prop> (introduced for the NestJS smoke fixture's rxjs OperatorSubscriber pattern) by rewriting it to this.<prop> / this[expr] in crates/perry-hir/src/lower/expr_misc.rs. The inline comment is honest about the scope:

The substitution is correct when the child does not override the property (the dominant rxjs / NestJS pattern). When the child does override, this approximation will resolve to the override rather than the parent — a TODO for a future explicit super-vtable path in codegen.

This is a silent semantic regression for any user code that overrides a parent property and reaches up via super.<prop> to read the parent's value. There is no compile error, no runtime warning — the program just returns the wrong value.

Repro shape

class A {
    foo = "A";
}
class B extends A {
    foo = "B";
    parentFoo() {
        return super.foo; // strict JS: "A"; perry today: "B"
    }
}
console.log(new B().parentFoo());

Expected (node --experimental-strip-types): A
Actual (perry HEAD): B

Why this matters

The PR #754 review accepted the lowering for the merge because the rxjs/NestJS pattern (no override) is the dominant case and the alternative was a hard lower_bail!. That tradeoff is fine, but it leaves user code that does override silently broken.

Suggested fix

Carry an explicit super-vtable lookup through codegen so super.<prop> resolves through the parent's prototype regardless of any child override. The HIR variant probably wants to be an explicit Expr::SuperPropertyGet { property } rather than the current this.<prop> rewrite, so codegen can route it to the parent class's vtable.

Regression net

A parity test that pins the wrong behavior would let a future fix flip it to passing. Suggested location: test-files/test_super_property_override.ts with the snippet above.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions