dart-lang / dart-lang/language
Dart is unable to reconcile function types with the `call` method at runtime
- Dominant language
- TeX
- Stars
- 2.9k
- Forks
- 239
- Avg merge
- 2d 18h
- Merged PRs (30d)
- 14
Description
I recently came across as issue which confused me. Consider the following code:
```dart
void functionWhichTakesAFunction(String Function(int) func) {
print("Ok");
}
class FunctionClass {
String call(int i) => "";
}
final myFunction1 = (int i) => "";
final myFunction2 = FunctionClass();
functionWhichTakesAFunction(myFunction1);
functionWhichTakesAFunction(myFunction2);
```
In other words, I have two functions, `myFunction1` and `myFunction2`, both of which do the same thing, but one is expressed as a regular function and one as a class with a `call` method. I can use class in places where the type system requires a function, which is expected, and illustrates the fact that the Dart `call` function is how function objects actually work (at least in my understanding).
Now consider this change to the code above:
```dart
final dynamic myFunction1 = (int i) => "";
final dynamic myFunction2 = FunctionClass();
functionWhichTakesAFunction(myFunction1);
functionWhichTakesAFunction(myFunction2);
```
All I've done is add `dyanamic` in front of the variable declarations, and now it fails with the error `type 'FunctionClass' is not a subtype of type '(int) => String'`.
What I don't understand is: why does the code work for the regular function, but not for the function class? I had come to understand that Dart is purely object-oriented and that internally all functions are just objects with `call` methods. Is this not correct? And is the error message really accurate? Because clearly `FunctionClass` _does_ have the same interface as `(int) => String`, even if it's expressed differently?
I'm aware this example seems a bit pointless but it's something that came about from some experimentation I've been doing - I'm hoping to find a better way to dynamically mock single functions in Dart, and this just cropped up along the way!
Contributor guide
Research direction
Start with the two Dart snippets in the issue and compare the statically typed calls with the calls after both variables are declared dynamic. Trace the language specification's rules for function types, call methods, and runtime subtype checks; done means a settled explanation of the behavior and whether the error message or documentation needs correction.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- dart
- Domain
- compilers
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 25/100