dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.11k stars 1.57k forks source link

Static analysis for a `@returnType` annotation for Function types #48183

Open srawlins opened 2 years ago

srawlins commented 2 years ago

This request is specifically for the Angular team, but can be used generally. The problem is as follows: given a function with the following signature:

void foo(Function cb)

there is no way to specify that cb must return a non-nullable type. For whatever reason, the type of cb cannot be function-typed (like int Function(bool)), and the most narrow type that can be specified is Function. The return value can be null-checked at runtime, but it would be much better to catch this statically. One idea is an annotation like so:

With recent language versions of Dart, either of these could specify a function type or a type with type arguments:

I think I prefer the @returnType<Object> API.

The rules for this annotation are:

Open questions:

CC @leonsenft @jakemac53 who helped design this yesterday.

jakemac53 commented 2 years ago
  • What about inheritance? If a method D.f overrides a method C.f, with a parameter annotated with @returnType, must the corresponding parameter in D.f also be explicitly annotated?

Given normal override rules I would say no, it's allowed to expand the type to a more general type (ie: Function) in this case. If it wanted to call super though then it would have to duplicate the annotation.

leonsenft commented 2 years ago

Would or could such an annotation affect type flow analysis?

For example, would you need to still null check the return value from an annotated function?

int square(@returnType<int Function()> Function cb) {
  final value = cb()!; // Would the ! still be necessary, or could it be omitted?
  return cb * cb;
}

Or would this simply produce an error at the call site of square()?

srawlins commented 2 years ago

Would or could such an annotation affect type flow analysis?

Nope.

For example, would you need to still null check the return value from an annotated function?

Yes, if it does today. (E.g. if the default return type is dynamic, which I think it is. Then value would be dynamic without the ! and cb * cb would be dynamic invocation.

matanlurey commented 3 months ago

Does this still make sense? Perhaps if there was no other user, and it wasn't needed so far, let's close the issue?

srawlins commented 3 months ago

I think this request still makes sense. Our team keeps issues open even if we have no plans to implement it, for searching, tracking, and discussion purposes. But we can make it P4 if Angular has chugged along OK without it, and no one else has chimed in that it would be useful.