-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Dynamic invocations incorrectly access "call" field in VM, dart2js, dart2wasm #51517
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
Comments
Seems like a change in the semantics that snuck under the radar. @eernstg can you confirm that this was incorporated into the spec? |
Fixing this will probably require kernel-level changes. Currently if I compile expression
This is the exact same kernel I get when I compile |
I'm tentatively adding |
Actually I am puzzled why
So for these reasons I would have expected |
@mraleph wrote:
This distinction ("callable objects must have a The current language specification says 'method', not 'member' or 'method or getter': If $o$ has a method named \CALL{}
the following ordinary method invocation is evaluated,
and its result is then the result of evaluating $i$:
\code{$f$.call<$A_1, \ldots,\ A_r$>($a_1, \ldots,\ a_n,\ x_{n+1}$: $a_{n+1}, \ldots,\ x_{n+k}$: $a_{n+k}$)}. This text occurs without changes back to 2018-09-17 (and the change at that time was a complex reorganization, which means that this particular rule might have been the same also before that time, but I didn't try to verify that). The main rationale is that it avoids infinite loops during the method lookup step, but also that the "callable object" feature should be rather simple and limited (as opposed to an approach where we try to "do what i mean" in as many different situations as possible). Here's the loop: class C { get call => this; }
void main() => (C() as dynamic)(); This runs, and it shows (as already mentioned in earlier comments) that the actual behavior (in dart-pad, based on SDK 2.19.2) is a dynamic error:
This raises some questions:
|
/cc @stereotype441 |
The test is still sitting out there and failing on all backends. If we are not planning to fix this any time soon, then maybe we need to alter the spec instead and change the test? |
I created dart-lang/language#3482 to manage the discussion about changing the specification. |
We should consider a long-time failing test a process failure. The specification has been this way for years, as far as I remember since Dart 2.0. That should lead to either the implementations fixing the bug, or a renewed discussion about changing the spec, until we reach a print where they all agree, and implementations match specification. Instead we got crickets. Maybe nobody really cared, because everything that should work worked, and then a little more which shouldn't, and we had bigger and more urgent things to do anyway. That's why it's a process failure. Nobody had the job of following up and taking the next step, and everybody could just do something else. |
According to the spec, a call in the form e(a0,...,aN) where static type of 'e' is 'dynamic' should succeed only if (1) 'e' evaluates to a function, or (2) runtime type of 'e' has a 'call' *method*. If runtime type of 'e' has a 'call' getter this invocation should fail with NSM. This behavior is different from 'e.call(a0,...,aN)' which accepts 'call' getters. --- In order to implement this behavior in the VM, a special 'dyn:implicit:call' selector is added. It behaves similarly to 'dyn:call' except when looking for a getter target. This selector is used when CFE sets FlagImplicitCall on a DynamicInvocation node. TEST=co19/Language/Expressions/Function_Invocation/Function_Expression_Invocation/call_A04_t01 TEST=co19/Language/Expressions/Function_Invocation/Function_Expression_Invocation/call_A04_t02 Fixes #59965 Issue #59952 Issue #51517 Issue dart-lang/language#3482 Change-Id: Ic45f7743ad75571476642dcec9c91e6a77e8e321 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/407161 Reviewed-by: Slava Egorov <[email protected]> Commit-Queue: Alexander Markov <[email protected]> Reviewed-by: Ryan Macnak <[email protected]>
VM behavior was fixed in 4305541. |
The test method_must_not_be_field_test checks that dynamic invocations do not implicitly access the field "call":
sdk/tests/language/call/method_must_not_be_field_test.dart
Lines 13 to 28 in 0c32c7f
This test was introduced in https://dart-review.googlesource.com/c/sdk/+/42020, and it currently fails in VM, dart2js (at least on dartpad), and dart2wasm.
This test is in sync with the static call semantics when the receiver has a "call" field but not a method, e.g.
Fails with compile-time error:
The text was updated successfully, but these errors were encountered: