Skip to content
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

After null-safety, compiler seems to have problems correctly "demoting" ternary expression #1679

Closed
mateusfccp opened this issue Jun 11, 2021 · 2 comments
Labels
bug There is a mistake in the language specification or in an active document

Comments

@mateusfccp
Copy link
Contributor

mateusfccp commented Jun 11, 2021

I don't know if this is expected or is a bug.

Consider the following:

Base<Object?> test1(int n) {
  return n == 1 ? A<String>() : B<int>();
}

Base<dynamic> test2(int n) {
  return n == 1 ? A<String>() : B<int>();
}

class Base<T> {}
class A<T> extends Base<T> {}
class B<T> extends Base<T> {}

In the case above, the compiler don't know that A<String> and B<int> are both Base<Object?> or Base<dynamic> and thus the ternary expression will be demoted to Object, giving a compilation error on both test1 and test2.

A value of type 'Object' can't be returned from the function 'test' because it has a return type of 'Base<Object?>'.

Using a explicitly cast will work:

// In this case, however, the linter will complain that the cast is unnecessary.
Base<Object?> test1(int n) {
  return n == 1 ? A<String>() as Base<Object?> : B<int>() as Base<Object?>;
}
Base<Object?> test1(int n) {
  return (n == 1 ? A<String>() : B<int>()) as Base<Object?>;
}

This worked before null-safety.

@mateusfccp mateusfccp added the bug There is a mistake in the language specification or in an active document label Jun 11, 2021
@leafpetersen
Copy link
Member

This worked before null-safety.

This "worked" before null-safety. :)

The computed type here is the same before null-safety and after null-safety - Object in both cases. Pre-null-safety, the system just inserted an implicit cast for you, but in the null-safety release we disallowed implicit downcasts, and so you now get an error.

It would be nice to do a better job with the upper bound computation, but the nature of the Dart type system makes upper bounds extremely challenging, and so we often fall into less than ideal solutions.

For conditional expressions specifically, I would like us to stop using upper bounds when we don't have to, which would solve your example. See my comment on this issue for details.

I'll close this issue in favor of #1618 , feel free to follow up there.

@mateusfccp
Copy link
Contributor Author

Thanks, @leafpetersen, it does makes sense

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug There is a mistake in the language specification or in an active document
Projects
None yet
Development

No branches or pull requests

2 participants