Skip to content

Is is permissible for an implementation to have a single Error class? #806

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

Open
rakudrama opened this issue Jan 30, 2020 · 1 comment
Open
Labels
feature Proposed language feature that solves one or more problems

Comments

@rakudrama
Copy link
Member

rakudrama commented Jan 30, 2020

The spec describes many Errors. Is it permissible for an implementation to have one class that implements all of the described Error classes? This would make it impossible to dispatch on the subtypes of Error but would still provide a guarantee that an certain Error is thrown.

When compiling to JavaScript, it happens, or can arranged, that the generated JavaScript code would crash at the same place under the same conditions.
Typically there is a property access on a value that has a JavaScript null or undefined value, or has a missing property that is called. Both result in a JavaScript TypeError, which is opaque. This can be very efficient in terms of the generated code size (zero code to do the check!) the but it is generally not possible to map the JavaScript TypeError to a specific Dart Error. The following are examples of situations where a property access could be used to signal an error:

  • NoSuchMethodError for a null receiver (dynamic d = null;... d.foo).
  • NoSuchMethodError for dynamic calls: generated a.foo$0() where a might not have a foo method.
  • CastError for a null-check operator: a!.foo() could be folded into call which will crash anyway, compiling to a.foo$0().
  • LateInitializationError - if a final late field without initializer has a non-nullable type, a null initial value could be used as a sentinel. The read guard could be implemented as a property access of the (un)initialized value. Again, we can compile this.field.foo() to this.field.foo$(), relying on the pre-assigned value being null.

Using a JavaScript crash to implement a Dart crash is very efficient as it often requires no explicit check in the generated code. However, it does make it difficult to know exactly what the problem was. In fact a single JavaScript location could be all of the above in some sequence.

It is permissible for the implementation to have a single Error class like the following?

class _JavaScriptTypeError extends Error
    implements
      TypeError,
      CastError,
      NoSuchMethodError,
      LateInitializationError,
       ... {
...
}
@rakudrama rakudrama added the feature Proposed language feature that solves one or more problems label Jan 30, 2020
@lrhn
Copy link
Member

lrhn commented Jan 31, 2020

If you can implement all the Error-subtype interfaces on the same class (some do have members that might conflict), then I see no issue with having one object implement multiple error interfaces.

It satisfies the specification, and users should not be inspecting errors anyway.

Going through the current specification,
the error classes mentioned explicitly are:

  • Error
  • AssertionError
  • ConcurrentModificationError
  • CyclicInitializationError
  • NoSuchMethodError
  • NullThrownError
  • TypeError

Of these:

  • ConcurrentModificationError is only mentioned as a "maybe" option for iterators,
    it is not specified as actually being thrown by the specification.
  • CyclicInitializationError - goes away with NNBD
  • NullThrownError - goes away with NNBD (throw operand must be non-nullable)
  • AssertionError is only used by assert.

The phrasing "a dynamic type error occurs" is defined as throwing a TypeError.

There is no mention of FallthroughError, switch cases just "throws an error". Not sure it's even possible any more because of the "must end with a control flow statement" clause being an error, not a warning.

There is no mention of CastError. The as operation says "a dynamic type error".
The NNBD specification does mention CastError. We should make it stop doing that.

The NNBD specification introduces LateInitializationError. Maybe it should just be saying "dynamic error".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

2 participants