Skip to content

Future Then callback that returns null and a when-resolved not null Future generates an exception #48522

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

Closed
Moncader opened this issue Mar 8, 2022 · 5 comments
Assignees
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends.

Comments

@Moncader
Copy link

Moncader commented Mar 8, 2022

This only affects native dart (Flutter or the Dart CLI). dartpad does not generate this issue and executes correctly.

import 'dart:async';

void main() {
  Future.value(true).then<String?>((v) {
    if (v) {
      return Future.value('success');
    }
    return null;
  });
}

The above code when run generates this exception:

Unhandled exception:
type '(bool) => Future<String?>?' is not a subtype of type '(bool) => FutureOr<String?>'
#0      _FutureListener._onValue (dart:async/future_impl.dart:133:21)
<asynchronous suspension>

As I see it this should execute correctly, and indeed on the web (dartpad) it does.
Technically this is a FutureOr<String?>? I believe as this callback is not async and therefore is actually returning a null value.
However, if that's the case, why is the web version not generating this error?

Also, is the correct way to do something like this just make the callback async?

  • Dart SDK Version (dart --version)
    Dart SDK version: 2.16.1 (stable) (Tue Feb 8 12:02:33 2022 +0100) on "macos_x64"
@lrhn
Copy link
Member

lrhn commented Mar 9, 2022

The problem does not reproduce for me in the tip-of-tree stand-alone VM either.
I can see that it does in the checked-in SDK we use for boot-strapping, so most likely the bug has already been fixed.

@lrhn lrhn added the area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends. label Mar 9, 2022
@mraleph
Copy link
Member

mraleph commented Mar 9, 2022

I would think that closure type actually comes from CFE, so it is probably a CFE issue which infers incorrect type for the closure.

@chloestefantsova @johnniwinther does this look like anything you have recently fixed in CFE?

@johnniwinther
Copy link
Member

This has been fixed by https://dart-review.googlesource.com/c/sdk/+/230240

@mraleph
Copy link
Member

mraleph commented Mar 10, 2022

@johnniwinther that CL just removed the cast. I think there indeed a VM issue. A simpler repro:

import 'dart:async';

Future<String?>? foo() {
  return null;
}

typedef F = FutureOr<String?> Function();

void main() {
  final F v = foo;
  print(v.runtimeType);
  print(v is F); // Returns false
  print((v as dynamic) as F); // Throws.
}

Seems like subtyping algorithm in the VM does not take into account that FutureOr<T?> is the same as FutureOr<T?>?

@mraleph mraleph reopened this Mar 10, 2022
@mkustermann
Copy link
Member

@sstrickl Could you look into this one?

@sstrickl sstrickl self-assigned this Mar 14, 2022
@sstrickl sstrickl reopened this Mar 14, 2022
@sstrickl sstrickl reopened this Mar 14, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-vm Use area-vm for VM related issues, including code coverage, and the AOT and JIT backends.
Projects
None yet
Development

No branches or pull requests

6 participants