Skip to content

Explain why a LateInitializationError was thrown #44361

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mit-mit opened this issue Dec 1, 2020 · 10 comments
Closed

Explain why a LateInitializationError was thrown #44361

mit-mit opened this issue Dec 1, 2020 · 10 comments
Assignees
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. NNBD Issues related to NNBD Release P1 A high priority bug; for example, a single project is unusable or has many test failures

Comments

@mit-mit
Copy link
Member

mit-mit commented Dec 1, 2020

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.

@mit-mit mit-mit added NNBD Issues related to NNBD Release P1 A high priority bug; for example, a single project is unusable or has many test failures labels Dec 1, 2020
@mit-mit
Copy link
Member Author

mit-mit commented Dec 1, 2020

cc @johnniwinther

@leafpetersen
Copy link
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
Copy link
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
Copy link
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
Copy link
Contributor

nshahan commented Dec 1, 2020

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
Copy link
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
Copy link
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
Copy link
Member

lrhn commented Dec 2, 2020

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.)

@alexmarkov alexmarkov self-assigned this Dec 2, 2020
@franklinyow franklinyow added the area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. label Dec 2, 2020
@leafpetersen
Copy link
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
Copy link
Member Author

mit-mit commented Dec 3, 2020

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. NNBD Issues related to NNBD Release P1 A high priority bug; for example, a single project is unusable or has many test failures
Projects
None yet
Development

No branches or pull requests

7 participants