Skip to content

Report an error for super() in an arrow in a typed class constructor - #2128

Open
tmikov wants to merge 1 commit into
facebook:static_hfrom
tmikov:super-arrow-typed-error
Open

Report an error for super() in an arrow in a typed class constructor#2128
tmikov wants to merge 1 commit into
facebook:static_hfrom
tmikov:super-arrow-typed-error

Conversation

@tmikov

@tmikov tmikov commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

Typed classes only support super() as the first statement of the
derived constructor. genClassDeclaration() rejects a constructor that
doesn't start with one, and genCallExpr() builds the call out of the
constructor's own this parameter, new.target parameter and class type.

An arrow nested in the constructor gets its own FunctionContext, and
genCapturingFunction() doesn't set superClassNode_ or
typedClassContext on it. A super() in that arrow reached
genCallExpr() with a null superClassNode_ and hit an assertion:

  class A { x: number; constructor() { this.x = 1; } }
  class B extends A {
    constructor() {
      super();
      (() => { super(); })();
    }
  }

Nothing is wrong with that program as far as the compiler is concerned.
The required first statement is there, and no diagnostic was emitted
before the assertion fired. Release builds drop the assertion and call
genExpression() on a null node.

Making it work would mean routing the constructor's captured this and
new.target into the arrow. That is a feature, and it cuts against the
restriction genClassDeclaration() deliberately imposes. Report the
restriction instead. The assertion goes away with it, since it no longer
guards anything reachable.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

Typed classes only support `super()` as the first statement of the
derived constructor. `genClassDeclaration()` rejects a constructor that
doesn't start with one, and `genCallExpr()` builds the call out of the
constructor's own `this` parameter, new.target parameter and class type.

An arrow nested in the constructor gets its own `FunctionContext`, and
`genCapturingFunction()` doesn't set `superClassNode_` or
`typedClassContext` on it. A `super()` in that arrow reached
`genCallExpr()` with a null `superClassNode_` and hit an assertion:

  class A { x: number; constructor() { this.x = 1; } }
  class B extends A {
    constructor() {
      super();
      (() => { super(); })();
    }
  }

Nothing is wrong with that program as far as the compiler is concerned.
The required first statement is there, and no diagnostic was emitted
before the assertion fired. Release builds drop the assertion and call
`genExpression()` on a null node.

Making it work would mean routing the constructor's captured `this` and
new.target into the arrow. That is a feature, and it cuts against the
restriction `genClassDeclaration()` deliberately imposes. Report the
restriction instead. The assertion goes away with it, since it no longer
guards anything reachable.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@tmikov

tmikov commented Aug 9, 2026

Copy link
Copy Markdown
Contributor Author

Depends on #2127 and must land after it.

The new check fires whenever superClassNode_ is null. That only means "typed class, nested arrow" because #2127 makes every untyped derived constructor and its arrows carry a legacyClassContext and return early above it. Without #2127, an untyped super() in an async arrow falls through to the same check, so this PR on its own rejects the valid program from #2126 with error: super() is only supported as the first statement of a derived class constructor (verified by building this commit alone on top of static_h).

@meta-cla meta-cla Bot added the CLA Signed Do not delete this pull request or issue due to inactivity. label Aug 9, 2026
@meta-codesync

meta-codesync Bot commented Aug 11, 2026

Copy link
Copy Markdown

@tmikov has imported this pull request. If you are a Meta employee, you can view this in D115505157.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed Do not delete this pull request or issue due to inactivity.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant