Skip to content

Missing compile-time type check for a default case in a null-guarded check #36952

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
decubate opened this issue May 13, 2019 · 3 comments
Closed
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language).

Comments

@decubate
Copy link

decubate commented May 13, 2019

This throws a runtime type error instead, when the null-checked argument is indeed null. I'm running Dart SDK Version 2.1.2 on MacOSX, but the issue is reproducible directly in a dartpad: https://dartpad.dartlang.org/bab95e3320cb9abbbb08282210c07ca4

class Apple {}

class Banana {}

List<Apple> bag([List<Apple> apples]) => apples ?? <Banana>[];

void main() {
  // ok
  final bag1 = bag([Apple()]);
  print(bag1);
  
  // throws runtime error, should be compile time error 
  final bag2 = bag();
  print(bag2);
}
@lrhn
Copy link
Member

lrhn commented May 13, 2019

This sadly behaves as currently expected (correct me if I'm wrong).

The apples ?? <Banana>[] expression has a type which is the "unification" of List<Apple> and List<Banana>, in particular it's List<Object>. Since Dart 2 implicit downcasts, List<Object> is assignable to List<Apple>, and you get a run-time error when the implicit downcast fails to cast List<Banana> to List<Apple>.

If we had better static semantics for ??, where the context type of List<Apple> for the implicit return was applied to both operands of the ??, then the bag method would have been a compile-time error.

@lrhn lrhn changed the title Missing compile-time type check for a default case in a ternary null check Missing compile-time type check for a default case in a null-guarded check May 13, 2019
@eernstg
Copy link
Member

eernstg commented May 13, 2019

I think it's relevant to mention --no-implicit-casts here as well (or the corresponding directive in analysis_options.yaml), especially because we're planning to include it as part of the support for non-null types.

The expression apples ?? <Banana>[] in a context where List<Apple> is expected creates an extreme loss of type information because there is an upcast to something involving a top type (here: the occurrence of Object in List<Object>) followed by a downcast (to List<Apple>), which means that a downcast to List<T> for any T is accepted. That just won't happen if the downcast must be specified explicitly.

@mit-mit mit-mit closed this as completed May 14, 2019
@mit-mit
Copy link
Member

mit-mit commented May 14, 2019

Closing as by-design (but was mentioned, we expect to improve that design in a later release)

@mit-mit mit-mit added the area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language). label May 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-language Dart language related items (some items might be better tracked at github.com/dart-lang/language).
Projects
None yet
Development

No branches or pull requests

4 participants