Skip to content

fix(js/ts/python): support explicit constructors with as and then - #5235

Merged
MangelMaxime merged 16 commits into
mainfrom
fix/explicit-ctor-as-self
Nov 7, 2026
Merged

MangelMaxime merged 16 commits into
mainfrom
fix/explicit-ctor-as-self

Conversation

@MangelMaxime

@MangelMaxime MangelMaxime commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

Fixes #5166.

Explicit constructors with a self identifier (new() as x = { ... } then ...) now work on JS, TS and Python, in a class with no base class. Constructors chaining within the class work too.

These stay a compile error, as on main:

  • A self identifier on Dart, Rust or Beam.
  • A self identifier in a class with a base class, or with [<AttachMembers>].
  • Inheriting from a class that has such a constructor, including from an object expression.

Inheriting needs the base then block to run on the derived instance, tracked in #5272.

Known gaps:

  • Reading self before initialisation doesn't throw InvalidOperationException.
  • A field written out of declaration order that reads a let mutable sees a later field's change to it. Without as, main has the same bug.
  • A generic [<DefaultValue>] field doesn't get the type's default. Without as, main has the same bug.
  • Inheriting from a precompiled class behind a .fsi isn't rejected, because the signature hides the field the check looks for.

@github-actions

Copy link
Copy Markdown
Contributor

Python Type Checking Results (Pyright)

Metric Value
Total errors 33
Files with errors 4
Excluded files 4
New errors ✅ No
Excluded files with errors (4 files)

These files have known type errors and are excluded from CI. Remove from pyrightconfig.ci.json as errors are fixed.

File Errors Status
temp/tests/Python/test_hash_set.py 18 Excluded
temp/tests/Python/test_applicative.py 11 Excluded
temp/tests/Python/test_nested_and_recursive_pattern.py 2 Excluded
temp/tests/Python/fable_modules/thoth_json_python/encode.py 2 Excluded

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Critical constructor-lowering defects break Rust and BEAM explicit constructors and leave inherited self references pointing to a separate base object rather than the derived instance.

4 open issues
What changed in this PR

This PR addresses #5166 by extending Fable’s shared F# lowering to support explicit constructors with as self bindings and then blocks.

Changes:

  • Resolves constructor self references and preserves the constructed object after then execution.
  • Supplies defaults for omitted compiler-generated fields and refactors base-constructor handling.
  • Adds JavaScript and Python regression tests for side effects, constructor chaining, and inheritance.
File Description
tests/​Python/​TestType.fs Adds explicit-constructor regression tests for Python.
tests/​Js/​Main/​TypeTests.fs Adds corresponding JavaScript constructor tests.
src/​Fable.Transforms/​FSharp2Fable.fs Implements shared lowering for self bindings, then blocks, and omitted fields.

Review effort: Balanced

Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved
Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved
Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved
Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved
@MangelMaxime MangelMaxime changed the title fix(all): support explicit constructors with as and then fix(js/ts/python): support explicit constructors with as and then Nov 3, 2026
@MangelMaxime
MangelMaxime force-pushed the fix/explicit-ctor-as-self branch from 7d1bbbc to ca388e0 Compare November 5, 2026 20:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved
Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved
Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved
Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved
Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved
Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The inheritance check incorrectly rejects imported/global derived stubs whose local base has an explicit self constructor, breaking interop stubs even though their derived constructors are discarded.

1 open issue
3 resolved since last review

Review effort: Balanced

Comment thread src/Fable.Transforms/FSharp2Fable.fs Resolved

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Shared constructor lowering spans FCS expression shapes and three target emitters, requiring .NET/JS/TS/Python runtime validation of object identity, initialization order, and constructor chaining that could not be performed in this review environment.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

@MangelMaxime
MangelMaxime marked this pull request as ready for review November 7, 2026 10:21
@MangelMaxime
MangelMaxime merged commit f8bfce3 into main Nov 7, 2026
36 checks passed
@MangelMaxime
MangelMaxime deleted the fix/explicit-ctor-as-self branch November 7, 2026 10:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

an explicit constructor with as x ... then does not compile

2 participants