-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Inconsistent call method tearoff behavior between analyzer and CFE #32864
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
Agreed. I think it fails in Analyzer because call tearoffs are done in CodeChecker, which happens after Resolver does inference. So we don't have the correct type to work with when we're doing inference. It thinks @leafpetersen what about this case? class B<S> {
S call(S x) => x;
}
T foo<T>(T Function(T) f) => null;
T bar<T>(T Function(int x) f) => null;
T baz<T>(int Function(T x) f) => null;
void main() {
foo(new B());
bar(new B());
baz(new B());
} ... do we want to infer the type parameter of |
There is no specification of the treatment of casts in dartLangSpec.tex (the "callable object" update only covered static and dynamic invocations), but I think we have had the following general approach on the table during discussions: If an expression This means that we never support insertion of Given that generic function instantiation should handle the next step, passing the type argument class A {
int call(int x) => x;
}
T foo<T>(T Function(T) f) => null;
T bar<T>(T Function(int x) f) => null;
T baz<T>(int Function(T x) f) => null;
void main() {
foo<int>(new A().call);
bar<int>(new A().call);
baz<int>(new A().call);
} Double checking: This runs fine with So we might want to discuss downcasts from One more double check, ;-), I removed the actual type arguments on |
Here's a fun one, too: import 'dart:async';
class A {
int call(int i) => i;
}
Future<Function> foo() async {
var result = new Future.value(new A());
return result;
}
main() async {
int Function(int) f = await foo();
print(f(42));
} This works fine in Dart 1, of course, because the In the update to dartLangSpec.tex that I'm currently working on it is not supported to lift a call method extraction like that — if the developer wants that semantics he/she must explicitly await the callable object ( |
Moving this to an analyzer issue. The original example in the bug should be inferred correctly, as it is in the CFE. |
A related issue in CFE: #33298 |
@bwilkerson @devoncarew @leafpetersen - is there an owner for this? Do we need it for dart2stable? |
probably. Feel free to assign to me if you need a person. |
I'm the "owner" of all dart 2 stable issues, but I don't assign myself until I've started work. @jmesserly, if you have cycles for this, that would be super helpful. It looks like you have a good idea of what's required. Basd on your description of the problem, is it just that tearoff insertion has to be moved from CodeChecker to Resolver? I could definitely take a stab but won't turn down help if its available :) |
I talked to @stereotype441 about this -- its hard to make out all of the information in here and Paul pointed out that it may have changed as well, since the original comments. However, it seems like in terms of addressing the differences between analyzer and CFE (which is what this ticket is ultimately about), the only real issue is in the error message. In the CFE, foo & baz call sites produce "(int) -> int is not assignable to (dynamic) -> _". And in the analyzer, they produce "A is not assignable to (dynamic) -> _". The front-end currently does not do tearoff insertion before inference, and so the analyzer should not (yet) do that either. That's the hard part. So the easy solution which @jmesserly is recommending, we think, is just to fix the error message in this case, rather than making any inference changes. Notably, this is not quite related to "call tear-off insertion" on the analyzer side, because we don't have any first class support for that (ie, we don't rewrite the AST, etc) but rather we just record the necessary cast from A to (int) -> int. Its possible that what's going wrong is that we don't insert the necessary cast from A to (int) -> int (or If I'm right about this...this seems like a very low priority issue, essentially related to consistency of error messages (or improvement of error messages). I may move this to dart 2.1 stable if there's something under that milestone that seems higher importance. |
@MichaelRFairhurst can you reach a conclusion about moving this to Dart2.1 ? If that is the way to go, then please move this soon. |
The analyzer's and CFE's errors are now perfectly aligned; same text, same errors:
|
The following code behaves inconsistently between CFE and the analyzer:
The analyzer seems to insert call tearoffs as follows:
emitting error messages on the call to
foo
andbaz
:The CFE seems to insert call tearoffs as follows,
producing the following error message:
If the call to
foo
is commented out, then a case failure occurs on the call tobaz
:There are two issues here:
On the inference front, it seems to me that for
foo
, we are doing downwards inference in a_ Function(_)
context. This forces a tearoff onnew A()
, and from there the upwards type should beint Function(int)
which should then resolve the type argument tofoo
appropriately.cc @lrhn @stereotype441 @kmillikin @jmesserly for thoughts on the inference and the tearoff behavior.
The text was updated successfully, but these errors were encountered: