Skip to content

extension type on a Function named call #55803

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

Open
mmcdon20 opened this issue May 21, 2024 · 7 comments
Open

extension type on a Function named call #55803

mmcdon20 opened this issue May 21, 2024 · 7 comments
Labels
area-dart-model For issues related to conformance to the language spec in the parser, compilers or the CLI analyzer. cfe-dysfunctionalities Issues for the CFE not behaving as intended dart-model-analyzer-spec Issues with the analyzer's implementation of the language spec legacy-area-front-end Legacy: Use area-dart-model instead. P3 A lower priority bug or feature request type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@mmcdon20
Copy link

mmcdon20 commented May 21, 2024

Dart SDK version: 3.4.0 (stable) (Mon May 6 07:59:58 2024 -0700) on "windows_x64"

The following program produces errors in the analyzer but compiles and runs successfully:

Edit: more minimal example

extension type Callable(Function call) {}

void main() {
  Callable((String name) => print('Hello $name!'))('Matthew');
}

output:

Hello Matthew!

analyzer errors:

The expression doesn't evaluate to a function, so it can't be invoked. • invocation_of_non_function_expression
@bwilkerson bwilkerson added legacy-area-analyzer Use area-devexp instead. P3 A lower priority bug or feature request dart-model-analyzer-spec Issues with the analyzer's implementation of the language spec labels May 21, 2024
@bwilkerson
Copy link
Member

@scheglov

@lrhn
Copy link
Member

lrhn commented May 21, 2024

I think the analyzer is correct, and the compilers are wrong.

Implicit call invocation/insertion is only specified to work for types with a method named call, not call getters that happen to have a function type (which this one doesn't even, it's just the type Function).

That is: The type Callable is not callable. The analyzer is correct.

See: dart-lang/language#3482, #45551, #54616, #54351

@mmcdon20
Copy link
Author

Also the following code compiles:

extension on String {
  void Function() get call => () => print(this);
}

void main() {
  'Hello World!'();
}

output:

Hello World!

analyzer errors:

The expression doesn't evaluate to a function, so it can't be invoked. • invocation_of_non_function_expression

@mmcdon20
Copy link
Author

I'll also add that this:

void main() {
  (call: print)('Hello World');
}

produces no analyzer warnings, but does not compile:

Error: The 'call' property on the record type isn't directly callable but could be invoked by `.call(...)`
  (call: print)('Hello World');
  ^

@eernstg
Copy link
Member

eernstg commented May 22, 2024

The language team decided to keep the semantics as specified (as mentioned here), that is, implicitly inserted .call invocations cannot invoke a getter.

The common front end was changed in https://dart-review.googlesource.com/c/sdk/+/346240 such that the required information is available (that is, backends can make the distinction that some invocations encoded as r.call(...) were specified as such in source code, which means that call can be a getter, or they were specified as r(...) in source code and .call was inserted implicitly, in which case call must be a method).

@johnniwinther, do those changes cover extension typed receivers as well? I'd actually expect the extension type member invocations to be processed early in the compilation pipeline such that later stages would just see an invocation of a function where the syntactic receiver is passed as an actual argument, and this might well eliminate the whole topic of .call insertion during the CFE processing...?

@johnniwinther johnniwinther added legacy-area-front-end Legacy: Use area-dart-model instead. cfe-dysfunctionalities Issues for the CFE not behaving as intended labels May 22, 2024
@johnniwinther
Copy link
Member

We have a lot of parallel code paths to handle the various calls so I would assume we just need to add some missing checks.

@lrhn
Copy link
Member

lrhn commented May 22, 2024

The last one is an analyzer error. A getter named call does not make an object callable, according to the language specification and (q.v. dart-lang/language#3482) there is no plans to change that.

The .call insertion is intended as a static, type-based feature. If you do expr(args), where expr is not of the form expr2.id (because then it's a method invocation, not a function call), then:

  • If the static type of expr is a function type, it's a plain function invocation.
  • If the static type is Function or dynamic, it's a dynamic function invocation.
  • If the static type has a call method, it invokes expr.call with the argument list of (args).
  • If the static type has a unique applicable call extension method, that is invoked with the value of expr as this and (args) as argument list.
  • Otherwise it's a compile-time error.

The current implementations fails to follow the specification in different ways.
I whipped up a test.
It shows the analyzer failing only by allowing a record call getter to be invoked.
The CFE/DDC (DartPad) fails by allowing call extension getters and extension type getters to be invoked.

I also checked the specification for dynamic function expression invocation.
If the type does not have a call method, we (should) invoke noSuchMethod with an Invocation with member name call, which isMethod and has the arguments, even if there is a call getter. That's actually pretty reasonable, and DDC does that correctly. (Haven't checked other than in DartPad yet.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-dart-model For issues related to conformance to the language spec in the parser, compilers or the CLI analyzer. cfe-dysfunctionalities Issues for the CFE not behaving as intended dart-model-analyzer-spec Issues with the analyzer's implementation of the language spec legacy-area-front-end Legacy: Use area-dart-model instead. P3 A lower priority bug or feature request type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

No branches or pull requests

6 participants