[M] Change in dart/sdk[main]: [dart2wasm] Fix dummy initializations of cyclic types

0 views
Skip to first unread message

Ömer Ağacan (Gerrit)

unread,
Jan 7, 2026, 9:16:52 AM (4 days ago) Jan 7
to Martin Kustermann, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Martin Kustermann

New activity on the change

Open in Gerrit

Related details

Attention is currently required from:
  • Martin Kustermann
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 6
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Attention: Martin Kustermann <kuste...@google.com>
Gerrit-Comment-Date: Wed, 07 Jan 2026 14:16:47 +0000
Gerrit-HasComments: No
Gerrit-Has-Labels: No
unsatisfied_requirement
open
diffy

Martin Kustermann (Gerrit)

unread,
Jan 8, 2026, 3:18:55 AM (3 days ago) Jan 8
to Ömer Ağacan, Commit Queue, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Ömer Ağacan

Martin Kustermann added 2 comments

File pkg/dart2wasm/lib/async.dart
Line 203, Patchset 6 (Latest): .withNullability(classIsCyclic),
Martin Kustermann . unresolved

I think this is kind of a workaround.

So the core issue is that the receiver class is not instantiatable. If so, then we shouldn't compile any instance members of that class in the first place, so we shouldn't come here.

How about we modify the `visitConstructorInvocation` (which is the only place that can instantiate the class - as we cannot have cyclic constants) to evaluate the arguments and then emit an `b.unreachable()` instead of a call to the constructor. That will make us never compile the constructor, never mark the class allocated, which will make us never enqueue any instance members, ...

Then we don't have to have this workaround here.

File pkg/dart2wasm/lib/translator.dart
Line 1846, Patchset 6 (Latest): dartType = dartType.withDeclaredNullability(Nullability.nullable);
Martin Kustermann . unresolved

If the class is cyclic, then it cannot be instantiated. If it cannot be instantiated we cannot have values of it. If we don't have values of it, then this is actually bottom type (which doesn't have values).

Though the rest of compiler may need to create wasm locals for such a variable and never assign to them.

So I'd think we can use any type here, so I'd just use a very simple type that has least overhead - e.g. nullable top type.

Would that be possible?

Open in Gerrit

Related details

Attention is currently required from:
  • Ömer Ağacan
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 6
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Ömer Ağacan <ome...@google.com>
Gerrit-Comment-Date: Thu, 08 Jan 2026 08:18:50 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
unsatisfied_requirement
open
diffy

Ömer Ağacan (Gerrit)

unread,
Jan 8, 2026, 4:31:54 AM (3 days ago) Jan 8
to Commit Queue, Martin Kustermann, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Ömer Ağacan

Ömer Ağacan added 1 comment

File pkg/dart2wasm/lib/async.dart
Line 203, Patchset 6 (Latest): .withNullability(classIsCyclic),
Martin Kustermann . unresolved

I think this is kind of a workaround.

So the core issue is that the receiver class is not instantiatable. If so, then we shouldn't compile any instance members of that class in the first place, so we shouldn't come here.

How about we modify the `visitConstructorInvocation` (which is the only place that can instantiate the class - as we cannot have cyclic constants) to evaluate the arguments and then emit an `b.unreachable()` instead of a call to the constructor. That will make us never compile the constructor, never mark the class allocated, which will make us never enqueue any instance members, ...

Then we don't have to have this workaround here.

Ömer Ağacan

Yeah, generating `unreachable` could work in Wasm because stack overflows are also traps.

But in general you can't replace stack overflows with traps as stack overflows can be caught in Dart.

We can't make stack overflows catchable in Dart in dart2wasm though so it doesn't matter for us.

I'll try compiling constructors as `unreachable`.

Open in Gerrit

Related details

Attention is currently required from:
  • Ömer Ağacan
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 6
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Ömer Ağacan <ome...@google.com>
Gerrit-Comment-Date: Thu, 08 Jan 2026 09:31:48 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Martin Kustermann <kuste...@google.com>
unsatisfied_requirement
open
diffy

Ömer Ağacan (Gerrit)

unread,
Jan 8, 2026, 4:51:28 AM (3 days ago) Jan 8
to Commit Queue, Martin Kustermann, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Martin Kustermann

Ömer Ağacan added 1 comment

File pkg/dart2wasm/lib/async.dart
Line 203, Patchset 6 (Latest): .withNullability(classIsCyclic),
Martin Kustermann . unresolved

I think this is kind of a workaround.

So the core issue is that the receiver class is not instantiatable. If so, then we shouldn't compile any instance members of that class in the first place, so we shouldn't come here.

How about we modify the `visitConstructorInvocation` (which is the only place that can instantiate the class - as we cannot have cyclic constants) to evaluate the arguments and then emit an `b.unreachable()` instead of a call to the constructor. That will make us never compile the constructor, never mark the class allocated, which will make us never enqueue any instance members, ...

Then we don't have to have this workaround here.

Ömer Ağacan

Yeah, generating `unreachable` could work in Wasm because stack overflows are also traps.

But in general you can't replace stack overflows with traps as stack overflows can be caught in Dart.

We can't make stack overflows catchable in Dart in dart2wasm though so it doesn't matter for us.

I'll try compiling constructors as `unreachable`.

Ömer Ağacan

@kuste...@google.com we can avoid allocating the members and constructor but the locals will remain, and they need to be initialized somehow. For example:

```
class Foo {
final Foo next;
Foo(this.next);
}

final Foo global = Foo(global);

bool get runtimeTrue => int.parse('1') == 1;

void test() {
Foo foo; // <------- HERE
if (runtimeTrue) {
foo = global;
} else {
throw 'error';
}
print(foo);
print(foo.next);
}
```

Here `foo` will need a dummy initializer.

Note that do determine whether a type is cyclic we rely on Wasm structs to be generated. We could do the check on Dart but I wonder if that would be fragile, maybe class A refers to B but in Wasm sturct the type is actually `ref null #Top` or something, because of a subclass overriding the reference, or something like that?

So I feel like checking for cyclic types in Wasm makes more sense. It's easy to get right.

If we generate Wasm structs as before, we'll have to keep these changes to make variables of them nullable, or we could try something like:

  • Create structs as before
  • After all is created, check for cyclic structs, replace them with empty structs (drop the fields)

With this all structs will be dummy instantiable.

Thoughts?

Open in Gerrit

Related details

Attention is currently required from:
  • Martin Kustermann
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 6
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Martin Kustermann <kuste...@google.com>
Gerrit-Comment-Date: Thu, 08 Jan 2026 09:51:23 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Ömer Ağacan <ome...@google.com>
Comment-In-Reply-To: Martin Kustermann <kuste...@google.com>
unsatisfied_requirement
open
diffy

Martin Kustermann (Gerrit)

unread,
Jan 8, 2026, 4:55:29 AM (3 days ago) Jan 8
to Ömer Ağacan, Commit Queue, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Ömer Ağacan

Martin Kustermann added 1 comment

File pkg/dart2wasm/lib/async.dart
Martin Kustermann

Yes, for locals we need a solution & I mentioned that in the other comment in `translator.dart`.

A local of a type that cannot be instantiated will never receive a value. That means the type of that local could be bottom (which has no values). But because we create locals, possibly dummy initialize and then never read/write to them, I'd suggest to make them nullable top type.

Open in Gerrit

Related details

Attention is currently required from:
  • Ömer Ağacan
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 6
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Ömer Ağacan <ome...@google.com>
Gerrit-Comment-Date: Thu, 08 Jan 2026 09:55:21 +0000
unsatisfied_requirement
open
diffy

Ömer Ağacan (Gerrit)

unread,
Jan 8, 2026, 5:50:30 AM (3 days ago) Jan 8
to Commit Queue, Martin Kustermann, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Martin Kustermann

Ömer Ağacan added 1 comment

File pkg/dart2wasm/lib/async.dart
Ömer Ağacan

OK, that makes sense.

I've made progress but there seems to be a bug when compiling called functions, I think `FunctionCollector.getFunction` doesn't add member functions to pending allocations, it adds them to the compilation queue directly. So we can't avoid compiling instance members by avoiding compiling constructors. This needs to be fixed first if we want to keep the dummy value allocation for `this` locals. Or we could keep the work around when initializing `this` locals for now.

Open in Gerrit

Related details

Attention is currently required from:
  • Martin Kustermann
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 6
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Martin Kustermann <kuste...@google.com>
Gerrit-Comment-Date: Thu, 08 Jan 2026 10:50:23 +0000
unsatisfied_requirement
open
diffy

Martin Kustermann (Gerrit)

unread,
Jan 8, 2026, 6:00:59 AM (3 days ago) Jan 8
to Ömer Ağacan, Commit Queue, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Ömer Ağacan

Martin Kustermann added 1 comment

File pkg/dart2wasm/lib/async.dart
Martin Kustermann

I think this happens when we devirtualize calls to instance members. This can happen in dynamic call forwarders as well as devirtualized method calls from TFA.

If we treated the uninstantiable class just like abstract classes, then not give them entries in dispatch table, then the dynamic forwarding part is fixed.

That leave devirtualized call sites. They are basically dead code / unreachable because the receiver can never be instantiated. So one may just issue a `unreachable` instead of trying to get the wasm function and call it.

Open in Gerrit

Related details

Attention is currently required from:
  • Ömer Ağacan
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 6
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Ömer Ağacan <ome...@google.com>
Gerrit-Comment-Date: Thu, 08 Jan 2026 11:00:53 +0000
unsatisfied_requirement
open
diffy

Ömer Ağacan (Gerrit)

unread,
Jan 8, 2026, 6:21:20 AM (3 days ago) Jan 8
to Commit Queue, Martin Kustermann, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Martin Kustermann

Ömer Ağacan added 1 comment

File pkg/dart2wasm/lib/async.dart
Ömer Ağacan

There are also tear-offs that need to be special cased (similar to direct calls).

I think it would be easier to implement and maintain if we generated all referenced functions always, but leave the bodies as `unreachable` until we allocate their classes. (for top-level functions generate bodies always)

Am I right that `FunctionCollector._pendingAllocation` is not used right now?

Open in Gerrit

Related details

Attention is currently required from:
  • Martin Kustermann
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 6
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Martin Kustermann <kuste...@google.com>
Gerrit-Comment-Date: Thu, 08 Jan 2026 11:21:14 +0000
unsatisfied_requirement
open
diffy

Martin Kustermann (Gerrit)

unread,
Jan 8, 2026, 6:30:38 AM (3 days ago) Jan 8
to Ömer Ağacan, Commit Queue, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Ömer Ağacan

Martin Kustermann added 1 comment

File pkg/dart2wasm/lib/async.dart
Martin Kustermann

Am I right that FunctionCollector._pendingAllocation is not used right now?

This is only needed for non-devirtualized calls: It tells the system: Someone has called `foo` selector - so if you ever allocate class X, then enqueue X.foo.

Yes, we could also just have bodies of instance members contain `unreachable`.

Open in Gerrit

Related details

Attention is currently required from:
  • Ömer Ağacan
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 6
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Ömer Ağacan <ome...@google.com>
Gerrit-Comment-Date: Thu, 08 Jan 2026 11:30:34 +0000
unsatisfied_requirement
open
diffy

Ömer Ağacan (Gerrit)

unread,
Jan 9, 2026, 4:32:49 AM (2 days ago) Jan 9
to Commit Queue, Martin Kustermann, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Martin Kustermann

Ömer Ağacan added 1 comment

File pkg/dart2wasm/lib/async.dart
Line 203, Patchset 6: .withNullability(classIsCyclic),
Martin Kustermann . resolved
Ömer Ağacan

Done

Open in Gerrit

Related details

Attention is currently required from:
  • Martin Kustermann
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 7
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Martin Kustermann <kuste...@google.com>
Gerrit-Comment-Date: Fri, 09 Jan 2026 09:32:44 +0000
unsatisfied_requirement
open
diffy

Ömer Ağacan (Gerrit)

unread,
Jan 9, 2026, 4:53:02 AM (2 days ago) Jan 9
to Commit Queue, Martin Kustermann, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Martin Kustermann

Ömer Ağacan added 1 comment

File pkg/dart2wasm/lib/translator.dart
Line 1846, Patchset 6: dartType = dartType.withDeclaredNullability(Nullability.nullable);
Martin Kustermann . resolved

If the class is cyclic, then it cannot be instantiated. If it cannot be instantiated we cannot have values of it. If we don't have values of it, then this is actually bottom type (which doesn't have values).

Though the rest of compiler may need to create wasm locals for such a variable and never assign to them.

So I'd think we can use any type here, so I'd just use a very simple type that has least overhead - e.g. nullable top type.

Would that be possible?

Ömer Ağacan

Done

Open in Gerrit

Related details

Attention is currently required from:
  • Martin Kustermann
Submit Requirements:
  • requirement is not satisfiedCode-Owners
  • requirement is not satisfiedCode-Review
  • requirement is not satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 10
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Martin Kustermann <kuste...@google.com>
Gerrit-Comment-Date: Fri, 09 Jan 2026 09:52:57 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
Comment-In-Reply-To: Martin Kustermann <kuste...@google.com>
unsatisfied_requirement
open
diffy

Martin Kustermann (Gerrit)

unread,
Jan 9, 2026, 5:29:42 AM (2 days ago) Jan 9
to Ömer Ağacan, Commit Queue, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Ömer Ağacan

Martin Kustermann voted and added 6 comments

Votes added by Martin Kustermann

Code-Review+1

6 comments

Patchset-level comments
File-level comment, Patchset 7:
Martin Kustermann . resolved

lgtm with comments

File pkg/dart2wasm/lib/class_info.dart
Line 233, Patchset 7: bool isCyclic(Translator translator) {
Martin Kustermann . unresolved

Since we're going to call this method for each instance member we try to compile, consider pre-calculating this when we create the class information.

We can do that after the `_generateFields()` call.

Then this doesn't have to be a public method and we don't have to warn about "not calling this method in certain situations".

File pkg/dart2wasm/lib/code_generator.dart
Line 1588, Patchset 7: if (info.isCyclic(translator)) {
Martin Kustermann . unresolved

We still have to evaluate arguments first (which may actually have side effects, throw or do anything - so it's not unreachable here).

So this should move below before the call instruction.

We could alternatively also make the constructor body throw (just like with other instance members of the unreachable classes)

Line 3160, Patchset 7: final member = memberReference.asMember;
Martin Kustermann . unresolved

Could you add the same code as in `getInlinableMemberCodeGenerator` here as well?

Line 3178, Patchset 7: final asyncMarker = lambda.functionNode.asyncMarker;
Martin Kustermann . unresolved

Could you add an `assert(!translator.classInfo[enclosingMember.enclosingClass].isCyclic(translator))`

File pkg/dart2wasm/lib/translator.dart
Line 1846, Patchset 6: dartType = dartType.withDeclaredNullability(Nullability.nullable);
Martin Kustermann . unresolved

If the class is cyclic, then it cannot be instantiated. If it cannot be instantiated we cannot have values of it. If we don't have values of it, then this is actually bottom type (which doesn't have values).

Though the rest of compiler may need to create wasm locals for such a variable and never assign to them.

So I'd think we can use any type here, so I'd just use a very simple type that has least overhead - e.g. nullable top type.

Would that be possible?

Martin Kustermann

Could you try whether making this nullable top type is possible?

Open in Gerrit

Related details

Attention is currently required from:
  • Ömer Ağacan
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement satisfiedCode-Review
  • requirement satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 7
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Ömer Ağacan <ome...@google.com>
Gerrit-Comment-Date: Fri, 09 Jan 2026 10:29:37 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
Comment-In-Reply-To: Martin Kustermann <kuste...@google.com>
satisfied_requirement
open
diffy

Ömer Ağacan (Gerrit)

unread,
Jan 9, 2026, 5:34:40 AM (2 days ago) Jan 9
to Martin Kustermann, Commit Queue, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Martin Kustermann

Ömer Ağacan added 1 comment

File pkg/dart2wasm/lib/translator.dart
Line 1846, Patchset 6: dartType = dartType.withDeclaredNullability(Nullability.nullable);
Martin Kustermann . unresolved

If the class is cyclic, then it cannot be instantiated. If it cannot be instantiated we cannot have values of it. If we don't have values of it, then this is actually bottom type (which doesn't have values).

Though the rest of compiler may need to create wasm locals for such a variable and never assign to them.

So I'd think we can use any type here, so I'd just use a very simple type that has least overhead - e.g. nullable top type.

Would that be possible?

Martin Kustermann

Could you try whether making this nullable top type is possible?

Ömer Ağacan

What do you mean by "this"? `topType` is already nullable.

Open in Gerrit

Related details

Attention is currently required from:
  • Martin Kustermann
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement satisfiedCode-Review
  • requirement satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 10
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Martin Kustermann <kuste...@google.com>
Gerrit-Comment-Date: Fri, 09 Jan 2026 10:34:35 +0000
satisfied_requirement
open
diffy

Martin Kustermann (Gerrit)

unread,
Jan 9, 2026, 6:07:52 AM (2 days ago) Jan 9
to Ömer Ağacan, Commit Queue, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Ömer Ağacan

Martin Kustermann voted and added 1 comment

Votes added by Martin Kustermann

Code-Review+1

1 comment

File pkg/dart2wasm/lib/translator.dart
Line 1846, Patchset 6: dartType = dartType.withDeclaredNullability(Nullability.nullable);
Martin Kustermann . resolved

If the class is cyclic, then it cannot be instantiated. If it cannot be instantiated we cannot have values of it. If we don't have values of it, then this is actually bottom type (which doesn't have values).

Though the rest of compiler may need to create wasm locals for such a variable and never assign to them.

So I'd think we can use any type here, so I'd just use a very simple type that has least overhead - e.g. nullable top type.

Would that be possible?

Martin Kustermann

Could you try whether making this nullable top type is possible?

Ömer Ağacan

What do you mean by "this"? `topType` is already nullable.

Martin Kustermann

Ah, you already addressed it. (maybe I was looking at an old patch set)

Open in Gerrit

Related details

Attention is currently required from:
  • Ömer Ağacan
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement satisfiedCode-Review
  • requirement satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 10
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Ömer Ağacan <ome...@google.com>
Gerrit-Comment-Date: Fri, 09 Jan 2026 11:07:47 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: Yes
satisfied_requirement
open
diffy

Ömer Ağacan (Gerrit)

unread,
Jan 9, 2026, 6:19:13 AM (2 days ago) Jan 9
to Martin Kustermann, Commit Queue, dart2wasm-t...@google.com, rev...@dartlang.org

Ömer Ağacan added 5 comments

File pkg/dart2wasm/lib/class_info.dart
Line 233, Patchset 7: bool isCyclic(Translator translator) {
Martin Kustermann . resolved

Since we're going to call this method for each instance member we try to compile, consider pre-calculating this when we create the class information.

We can do that after the `_generateFields()` call.

Then this doesn't have to be a public method and we don't have to warn about "not calling this method in certain situations".

Ömer Ağacan

Done

Line 638, Patchset 11 (Latest): }
Ömer Ağacan . unresolved

@kuste...@google.com it's a bit strange that `Translator.classes` doesn't have mixins but `Translator.classesSupersFirst` does. Is this intentional? What's the reason for this?

File pkg/dart2wasm/lib/code_generator.dart
Line 1588, Patchset 7: if (info.isCyclic(translator)) {
Martin Kustermann . resolved

We still have to evaluate arguments first (which may actually have side effects, throw or do anything - so it's not unreachable here).

So this should move below before the call instruction.

We could alternatively also make the constructor body throw (just like with other instance members of the unreachable classes)

Ömer Ağacan

Done

Line 3160, Patchset 7: final member = memberReference.asMember;
Martin Kustermann . resolved

Could you add the same code as in `getInlinableMemberCodeGenerator` here as well?

Ömer Ağacan

Done

Line 3178, Patchset 7: final asyncMarker = lambda.functionNode.asyncMarker;
Martin Kustermann . resolved

Could you add an `assert(!translator.classInfo[enclosingMember.enclosingClass].isCyclic(translator))`

Ömer Ağacan

Done

Open in Gerrit

Related details

Attention set is empty
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement satisfiedCode-Review
  • requirement satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 11
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Comment-Date: Fri, 09 Jan 2026 11:19:09 +0000
satisfied_requirement
open
diffy

Martin Kustermann (Gerrit)

unread,
Jan 9, 2026, 7:10:50 AM (2 days ago) Jan 9
to Ömer Ağacan, Commit Queue, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Ömer Ağacan

Martin Kustermann voted and added 1 comment

Votes added by Martin Kustermann

Code-Review+1

1 comment

File pkg/dart2wasm/lib/class_info.dart
Ömer Ağacan . unresolved

@kuste...@google.com it's a bit strange that `Translator.classes` doesn't have mixins but `Translator.classesSupersFirst` does. Is this intentional? What's the reason for this?

Martin Kustermann

So anonymous mixin application classes are not something that one can allocate or use in type expressions. As such we don't need to assign a class id to them.

The `Translator.classes` maps class-id to class, but I guess `Translator.classesSuperFirst` will include all of the classes.

Open in Gerrit

Related details

Attention is currently required from:
  • Ömer Ağacan
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement satisfiedCode-Review
  • requirement satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 11
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Ömer Ağacan <ome...@google.com>
Gerrit-Comment-Date: Fri, 09 Jan 2026 12:10:44 +0000
satisfied_requirement
open
diffy

Ömer Ağacan (Gerrit)

unread,
Jan 9, 2026, 8:41:50 AM (2 days ago) Jan 9
to Martin Kustermann, Commit Queue, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Martin Kustermann

Ömer Ağacan added 2 comments

File pkg/dart2wasm/lib/class_info.dart
Line 638, Patchset 11: }
Ömer Ağacan . resolved

@kuste...@google.com it's a bit strange that `Translator.classes` doesn't have mixins but `Translator.classesSupersFirst` does. Is this intentional? What's the reason for this?

Martin Kustermann

So anonymous mixin application classes are not something that one can allocate or use in type expressions. As such we don't need to assign a class id to them.

The `Translator.classes` maps class-id to class, but I guess `Translator.classesSuperFirst` will include all of the classes.

Ömer Ağacan

OK, documented.

File pkg/dart2wasm/lib/code_generator.dart
Line 3178, Patchset 7: final asyncMarker = lambda.functionNode.asyncMarker;
Martin Kustermann . unresolved

Could you add an `assert(!translator.classInfo[enclosingMember.enclosingClass].isCyclic(translator))`

Ömer Ağacan

Done

Ömer Ağacan

This assertion is currently failing. I debugged it a little bit and on the way figured out how some of these cycles happen even when the original program is legit.

Example: https://github.com/dart-lang/sdk/blob/1c6496fe9211f74a31ad9c51dcbc1ff318117c8e/sdk/lib/_http/http_impl.dart#L3785-L3787

```
class _DetachedSocket extends Stream<Uint8List> implements Socket {
final Stream<Uint8List> _incoming;
final Socket _socket;
...
}
```

Note that this class is a `Socket` and has a non-nullable reference to `Socket`.

`Socket` is an abstract interface class: https://github.com/dart-lang/sdk/blob/1c6496fe9211f74a31ad9c51dcbc1ff318117c8e/sdk/lib/io/socket.dart#L836

Depending on the target there are a few implementations:

But when compiling to Wasm we don't compile all of these and based no TFA results and other things we get this struct for `_DetachedSocket`:

```
_DetachedSocket{const ref _Type, const ref _HttpDetachedIncoming, const ref _DetachedSocket}
```

and then another type that uses this (hence cyclic):

```
_HttpClientConnection{..., const ref _DetachedSocket, ...}
```

and then this lambda inside the `_HttpClientConnection` constructor: https://github.com/dart-lang/sdk/blob/1c6496fe9211f74a31ad9c51dcbc1ff318117c8e/sdk/lib/_http/http_impl.dart#L2188

triggers the assertion.

I think this answers how the reporter of the original issue got this crash. You don't have to have a cycle in your own code, things get cyclic after TFA and maybe other transformations.

I don't know why we're trying to compile this lambda. I suspect closure collector needs to take reachability of the enclosing member into account as well.

Open in Gerrit

Related details

Attention is currently required from:
  • Martin Kustermann
Submit Requirements:
  • requirement satisfiedCode-Owners
  • requirement satisfiedCode-Review
  • requirement satisfiedReview-Enforcement
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: comment
Gerrit-Project: sdk
Gerrit-Branch: main
Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
Gerrit-Change-Number: 471201
Gerrit-PatchSet: 12
Gerrit-Owner: Ömer Ağacan <ome...@google.com>
Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
Gerrit-Attention: Martin Kustermann <kuste...@google.com>
Gerrit-Comment-Date: Fri, 09 Jan 2026 13:41:44 +0000
Gerrit-HasComments: Yes
Gerrit-Has-Labels: No
satisfied_requirement
open
diffy

Ömer Ağacan (Gerrit)

unread,
Jan 9, 2026, 9:22:53 AM (2 days ago) Jan 9
to Martin Kustermann, Commit Queue, dart2wasm-t...@google.com, rev...@dartlang.org
Attention needed from Martin Kustermann

Ömer Ağacan added 1 comment

File pkg/dart2wasm/lib/code_generator.dart
Line 3178, Patchset 7: final asyncMarker = lambda.functionNode.asyncMarker;
Martin Kustermann . resolved
Ömer Ağacan

Done

Open in Gerrit

Related details

Attention is currently required from:
  • Martin Kustermann
Submit Requirements:
    • requirement is not satisfiedCode-Owners
    • requirement is not satisfiedCode-Review
    • requirement is not satisfiedReview-Enforcement
    Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
    Gerrit-MessageType: comment
    Gerrit-Project: sdk
    Gerrit-Branch: main
    Gerrit-Change-Id: Iefa1949f0175eb4757fd7cfae3b25a87d17f3e8d
    Gerrit-Change-Number: 471201
    Gerrit-PatchSet: 13
    Gerrit-Owner: Ömer Ağacan <ome...@google.com>
    Gerrit-Reviewer: Martin Kustermann <kuste...@google.com>
    Gerrit-Reviewer: Ömer Ağacan <ome...@google.com>
    Gerrit-Attention: Martin Kustermann <kuste...@google.com>
    Gerrit-Comment-Date: Fri, 09 Jan 2026 14:22:48 +0000
    unsatisfied_requirement
    open
    diffy
    Reply all
    Reply to author
    Forward
    0 new messages