Skip to content

Non-null inference with closures is confusing #51452

Closed
@liamappelbe

Description

@liamappelbe

This works:

int foo(int x) {
  int? y;
  if (x == 10) y = x;
  if (y == null) return -1;
  return y;  // y is correctly promoted to be non-nullable, due to null check above.
}

But this doesn't work:

int foo(int x) {
  int? y;
  final bar = () {
    if (x == 10) y = x;
  };
  bar();
  if (y == null) return -1;
  return y;  // y is not promoted, and is still nullable. Compile error.
}

I think this is happening because in the second case, bar is a closure, which is implemented internally by creating an anonymous class and storing x and y as fields on the class. So since class fields can't be type promoted, y is still int? at the end of foo. This is a very confusing behavior, since many users wouldn't realize that bar is actually a class.

My understanding is that class fields can't be promoted in this way because elsewhere in the code someone might write a subclass that overrides the getter to return null on the second access. However, in this case the class is anonymous, so can't be subclassed. So I think this instance could be safely special cased by allowing promotion for fields of anonymous classes.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions