-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Invocations of callable classes should be desugared in Kernel #34497
Comments
I agree. I'm surprised we don't have an issue open to track it. We generate
we should generate:
Additionally, we should introduce class Something<T> {
void Function(T) delegate;
void invoke(T value) { delegate(value); }
} we should generate:
/cc @johnniwinther |
Yuck, we are even confusing our own selves over this. I've started work on fixing it. |
Note that in general case receiver, getter and argument(s) could have side-effects and we should be careful in keeping order of evaluation. For the call via field/getter
It would be incorrect to generate
Because it evaluates expressions in a wrong order:
The correct order is
So we might need to generate something a little bit more sophisticated here. |
I have begun working on this. Obviously we will implement the correct order of evaluation and getter invocation, but it is not as described in #34497 (comment). It was changed by CL 51323 in September of 2018. |
I didn't know about that spec change, and in the comment above I assumed that we would like to keep the current behavior. The spec change you mentioned is obviously a breaking change. As far as I understand the wording of the new spec, current implementation of calls in the VM does not adhere to the new spec. How it should work in case of dynamic calls (when |
Dynamic invocations are tricky, but should always match the non-dynamic invocation if the object has a matching method or getter. The evaluation of If If
|
@alexmarkov wrote:
The change to the evaluation order which is specified in the language specification as of CL 51323 was actually about a year older: It was accepted by the language team in 2017 and reported here (thanks, @kmillikin for helping to track that down!). CL 51323 was a rather large update that fixed a number of known issues (for instance, the given specification of lookups didn't work for superinvocations, it wasn't specified that things like Adjusting the evaluation order to match that 2017 decision was one of these required corrections. It should probably have been singled out and announced explicitly as a breaking change, but it was in any case not an accident to specify the left-to-right evaluation order. The newsletter mentions that
which would suggest that some changes in some tools may be needed in any case (unless all tools have since then been fixed, such that they precisely implement the pre-51323 semantics). @alexmarkov, do you think there is a need to initiate a more elaborate breaking-change procedure for handling this? |
I'm not very familiar with breaking change process. According to https://github.com/dart-lang/sdk/blob/master/docs/process/breaking-changes.md we need to follow the procedure for all breaking changes:
@kmillikin I'm sorry for hijacking your issue for the discussion about the language change. @eernstg Is there a VM implementation issue corresponding to that language change? |
@alexmarkov the breaking change process is awesome but it is from January 2019. It was not followed in 2017, the language newsletters were used for those announcements back then. Note that the code that was broken by this change is code that (1) invokes a function-valued getter and (2) relies on side effects of an argument expression to change the value returned by that getter. Also note that our compilers themselves weren't consistent then (and still aren't, I guess). |
I've created #36744 as a meta-issue for the implementation of the left-to-right evaluation order, plus tool specific subissues. Turns out that at least the vm and dart2js do not have this behavior today (but perhaps DDC has it). I believe that the right way ahead is to get it implemented. If we need to take additional steps because this is a breaking change it can all be handled in the context of #36744. So please put comments on that topic into that issue. (@kmillikin, sorry about temporarily hijacking this issue for the evaluation order thing, it should all be encapsulated in #36744 from now on ;-). |
With https://dart-review.googlesource.com/c/sdk/+/129702 field/getter invocation is now encoded as a .call on a property get. The VM uses this encoded whereas ddc/dart2js currently opts out because breakage wrt. js-interop. This implementation hoists the arguments to preserve the old evaluation order. It is a separate (breaking) step to change the evaluation order on these to left-to-right. |
…rom TFA and bytecode generator Since https://dart-review.googlesource.com/c/sdk/+/129702 CFE desugars interface calls through fields/getters, so there is no need to handle them in the TFA and bytecode generator. Note that VM can still see such calls if they are dynamic, so handling of such calls is not removed entirely from TFA or VM. Also, VM should support those as long as it supports older kernel binary versions. Issue: #34497 Change-Id: Ic49f109b0e9264f0e20a7e1a3b7a46011fa76c86 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/137700 Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Alexander Markov <[email protected]>
For simplicity of the backends I would expect that the method
Something.invoke
below would be represented in the Kernel AST as(this.delegate).call(value)
. However currently it is represented as a method invocation ofthis.delegate(value)
instead.For simplicity on the backend site
The text was updated successfully, but these errors were encountered: