Description
In CL 153202, I'm fixing Function::DoArgumentTypesMatch
to be NNBD-compliant, among other things. On the main branch, that method skips argument checks if the argument is null
, but that no longer happens after my CL (instead it appropriately checks the argument type using Instance::NullIsAssignableTo
). This is causing a test failure in tests/lib/mirrors/null_test.dart
, where we have:
InstanceMirror im1 = reflect(null);
Expect.equals(cm, im1.type);
Expect.isTrue(im1.invoke(const Symbol("=="), [null]).reflectee);
and in sdk/lib/core/object.dart
, we have:
external bool operator ==(Object other);
Thus, when Instance::NullIsAssignableTo
is checked with the type Object
in strong mode, it fails and causes the type error:
Unhandled exception:
type 'Null' is not a subtype of type 'Object' of 'other'
#0 _TypeError._throwNew (dart:core-patch/errors_patch.dart:98:34)
#1 _InstanceMirror._invoke (dart:mirrors-patch/mirrors_impl.dart:337:37)
#2 _InstanceMirror.invoke (dart:mirrors-patch/mirrors_impl.dart:333:25)
#3 test (file:///usr/local/google/home/sstrickl/dart/sdk/tests/lib/mirrors/null_test.dart:21:21)
#4 main (file:///usr/local/google/home/sstrickl/dart/sdk/tests/lib/mirrors/null_test.dart:12:5)
#5 _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:301:19)
#6 _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12)
For now, I'm going to approve the failure (and add comments in the test pointing at this issue). I'm happy to fix things, but I need to know which of the approaches to take here:
- We can just declare this a type error and change the test to use expect.throwsTypeError() in this and similar cases throughout the file.
- We can change
InstanceMirror.invoke
insdk/lib/_internal/vm/lib/mirrors_impl.dart
to specifically check forSymbol('==')
and a null argument, and return the correct value based on the reflectee value. This means any overrides ofObject.==
will not be taken into consideration (which may returntrue
for==
despite having a non-null receiver). - We can change
Instance::Invoke
in the VM to check to see if the function that will be invoked isObject.==
and then do the check there. However, this means that trying to invoke==
on an instance where a subclass overridesObject.==
will continue to fail, unless the subclass allows a nullable argument.
Of course, if another alternative is preferred, I can look at implementing that as well.
\cc @lrhn