Skip to content

Explain why a LateInitializationError was thrown #44361

Closed
@mit-mit

Description

@mit-mit

When the VM detects an LateInitializationError with null safety, it throws a generic error like:

00:07 +5 -2: mergeWith Test [E]
  LateInitializationError: internalHandler
  package:functional_listener/src/functional_value_notifiers.dart         FunctionalValueNotifier.internalHandler
  package:functional_listener/src/functional_value_notifiers.dart 20:38   FunctionalValueNotifier.removeListener
  package:functional_listener/src/functional_value_notifiers.dart 140:11  MergingValueNotifiers.removeListener
  package:functional_listener/functional_listener.dart 223:17             ListenableSubscription.cancel
  listenable_pipe_test.dart 160:18      

This error does not detail which of the two cases of LateInitializationError happened: did we read something that wasn't initialized, or did we write to an already initialized final late variable.

It would be nice to either add this detail in the error output, or potentially even split LateInitializationError into two errors (like LateUninitializedError and LateFinalReInitializationError).

Further it could be made a bit clearer which variable triggered the exception.

Activity

added
NNBDIssues related to NNBD Release
P1A high priority bug; for example, a single project is unusable or has many test failures
on Dec 1, 2020
mit-mit

mit-mit commented on Dec 1, 2020

@mit-mit
MemberAuthor
leafpetersen

leafpetersen commented on Dec 1, 2020

@leafpetersen
Member

Looks like the web compilers associated a different error message with the different error cases. @alexmarkov does the VM implement this itself, or does it just pick up the front end lowering of late? Is there anything stopping the VM from calling a different constructor in the two different cases?

alexmarkov

alexmarkov commented on Dec 1, 2020

@alexmarkov
Contributor

This is implemented in the VM (CFE lowering is not used for late fields/variables in the VM). We can throw different exception types or we can adjust the exception messages - please suggest what exactly we should do. Also, it would be nice to unify that across all Dart implementations (VM, dart2js, DDC).

leafpetersen

leafpetersen commented on Dec 1, 2020

@leafpetersen
Member

Yes, I think consistency would be good. I believe the web compilers both use the implementation in lib/internal/errors.dart (is that right @nshahan @sigmundch ). So if we're happy with just making the error message consistent, then we maybe we could either consolidate those implementations or make them consistent?

cc @mit-mit @lrhn @munificent @natebosch @jakemac53 for thoughts on whether custom error messages are good enough or whether there's a justification for doing the additional work to specify and implement separate error classes.

nshahan

nshahan commented on Dec 1, 2020

@nshahan
Contributor

FWIW @rakudrama and I have discussed opting out of the late lowering in some cases where we could do something more efficient in JavaScript.

I believe the web compilers both use the implementation in lib/internal/errors.dart

This is true for DDC.

rakudrama

rakudrama commented on Dec 2, 2020

@rakudrama
Member

For dart2js we will move away from using the default code patterns and Error classes.
This will be done on a case-by-case basis (e.g. treating late, late final, initialized, uninitialized, local, field, static independently).

The code size tax of the current implementation is too high (see #43361), so we want to be able to generate JavaScript where it is not possible to tell what kind of LateError is generated, or what the late variable was called, or even if the problem is a LateError or some other kind of Error. For production code we don't want to leak the names, and forcing a null dereference (NoSuchMethodError) instead of a LateError is an order of magnitude more compact.

We will try to generate accurate, actionable messages where possible, but need the freedom to do something else to make the late feature viable when widely used in production.

leafpetersen

leafpetersen commented on Dec 2, 2020

@leafpetersen
Member

Ok, so it sounds like there are no issues with making DDC and the VM consistent, and dart2js in production at least will diverge significantly no matter what. Does that seem reasonable to all? Are we happy with just making sure that there are good error messages associated with the exception (as currently implemented by DDC)?

lrhn

lrhn commented on Dec 2, 2020

@lrhn
Member

Do we want to underspecify the error?
We currently specify that a later initialization error must throw an instance of LateInitializationError. As I read it, dart2js wants to diverge from that specification, which suggests that maybe we shouldn't actually specify which error is throw, and should instead just say that "a run-time error occurs" and leave it up to the implementations which instance of a subclass of Error they want to actually throw. (If we do so, we should remove LateInitializationError, it's confusing if it exists, but isn't used by dart2js).

(The LateInitializationError is not a "default error", it's a spec mandated error, and throwing something not implementing that interface is a spec violation.)

self-assigned this
on Dec 2, 2020
added
area-vmUse area-vm for VM related issues, including code coverage, and the AOT and JIT backends.
on Dec 2, 2020
leafpetersen

leafpetersen commented on Dec 3, 2020

@leafpetersen
Member

Per discussion in the language meeting today, we would like to remove LateInitializationError from the public API, and loosen the specification to simply specify that some error is thrown. The VM and DDC may choose (hopefully will choose) to implement this consistently, e.g by using the current mechanism.

mit-mit

mit-mit commented on Dec 3, 2020

@mit-mit
MemberAuthor

As of the fix above, the new output is:

$ ../dart-sdk/bin/dart run
42
Unhandled exception:
LateInitializationError: Field 'i' has already been initialized.

$ ../dart-sdk/bin/dart run
42
Unhandled exception:
LateInitializationError: Field 'j' has not been initialized.

added this to the January 2021 milestone on Jan 5, 2021
deleted a comment from on Jun 22, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

NNBDIssues related to NNBD ReleaseP1A high priority bug; for example, a single project is unusable or has many test failuresarea-vmUse area-vm for VM related issues, including code coverage, and the AOT and JIT backends.

Type

No type

Projects

No projects

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @rakudrama@nshahan@lrhn@leafpetersen@mit-mit

      Issue actions

        Explain why a `LateInitializationError` was thrown · Issue #44361 · dart-lang/sdk