dart-lang / dart-lang/language

Dart is unable to reconcile function types with the `call` method at runtime

Open
#3,158 11 comments 0 reactions 0 assignees View on GitHub
request
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

Open the contributing 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.