Skip to content
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

DDC: Evaluation of e1 == e2 should detect null before any type checks #41866

Closed
eernstg opened this issue May 12, 2020 · 2 comments
Closed

DDC: Evaluation of e1 == e2 should detect null before any type checks #41866

eernstg opened this issue May 12, 2020 · 2 comments
Assignees
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. NNBD Issues related to NNBD Release type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) web-dev-compiler

Comments

@eernstg
Copy link
Member

eernstg commented May 12, 2020

Consider the following program (which is a slice of language/operator/equality_covariant_test.dart, which is added by https://dart-review.googlesource.com/c/sdk/+/145582):

import "package:expect/expect.dart";

class EqNever {
  operator ==(covariant Never other) => throw "unreachable";
}

void main() {
  Object oNever = EqNever();
  Object? myNull = null;
  Expect.isFalse(oNever == myNull);
}

This test fails on the configuration ddc-nnbd-linux-release-chrome-try (log), with the following stack trace:

Deobfuscated error and stack:
Error: Expected a value of type 'Never', but got one of type 'Null'
    at Object.throw_                               out/ReleaseX64/gen/utils/dartdevc/kernel/amd/dart_sdk.js 4029:11
    at Object.castError                            ../../../../../dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/errors.dart 62:3
    at Object.cast                                 ../../../../../dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/operations.dart 442:10
    at dart.NeverType.new.as                       ../../../../../dart-sdk/lib/_internal/js_dev_runtime/private/ddc_runtime/types.dart 82:19
    at equality_covariant_test.EqNever.new._equals out/ReleaseX64/generated_compilations/dartdevk-checked-sdk/tests_language_operator_equality_covariant_test/equality_covariant_test.js 15:18
    at Object.main                                 ../../../../../tests/language/operator/equality_covariant_test.dart 36:24
    at testMainWrapper                             out/ReleaseX64/generated_tests/dartdevk-chrome-checked-sdk/tests_language_operator_equality_covariant_test/test.html 87:93

However, evaluation of an expression of the form e1 == e2 is specified to run in phases where null is processed first. In particular, oNever == myNull should evaluate oNever to an object different from null, and evaluate myNull to null, and then yield false, and up to this point there is no type check of any of these objects.

The actual behavior is that it is checked whether null is of type Never, which is not the case in strong checking mode, and the evaluation then throws rather than yielding false.

@eernstg eernstg added type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) web-dev-compiler area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. NNBD Issues related to NNBD Release labels May 12, 2020
@nshahan nshahan self-assigned this May 12, 2020
@nshahan
Copy link
Contributor

nshahan commented May 12, 2020

Just to double check, is this an issue when testing equality with an object that has a runtime type of Null specifically? If you were perform the same equality check with an integer instead of null:

...
Object? myInt = 42;
Expect.isFalse(oNever == myInt);

Would throwing a TypeError be expected?

@eernstg
Copy link
Member Author

eernstg commented May 12, 2020

Yes. The only object that has a run-time type of Null is the null object, so any rules about the latter are also rules about the former. (It is possible to override runtimeType, so in that sense any object could have a run-time type of Null, but that won't change the outcome of language defined run-time type queries).

With oNever == myInt the special treatment of null is irrelevant (none of the operands is the null object), so we proceed to invoke operator == on oNever, which will throw a TypeError.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web Use area-web for Dart web related issues, including the DDC and dart2js compilers and JS interop. NNBD Issues related to NNBD Release type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) web-dev-compiler
Projects
None yet
Development

No branches or pull requests

2 participants