Sdk: [NNBD] checking for null of final instance variable doesn't work

Created on 12 Jun 2020  路  5Comments  路  Source: dart-lang/sdk

This code should raises an unchecked_use_of_nullable_value error on the marked line. I think, the guarding if should be sufficient because the instance variable is final.

class Context {
  final Context? parent;

  Context(this.parent);

  int lookup(String name) {
    if (parent != null)
      return parent.lookup(name); // unchecked_use_of_nullable_value
    return 0;
  }
}
closed-as-intended

Most helpful comment

Absolutely would be useful to do a check+binding in one operation.

C# has if (e is Foo y) which binds y to the value of e with static type Foo, after checking that it has that type. I like that syntax, and it should be compatible with Dart.

No plans right now, though.

All 5 comments

It's not enough to be final, the class has to be sealed (which there is currently no way to do).
Otherwise someone could write:

class MyNaughtyContext extends Context {
   Context? get parent => Random().nextBool() ? null : super.parent;
}

and then your check is worthless.

A final static variable might be promotable, but an instance variable isn't. (And final static variables are usually not nullable.)

For now, Dart only promotes local variables, because it is absolutely certain it can see all reads and writes to the variable in the same file.

I recommend doing the same thing here as for non-final variables:
````dart
var parent = this.parent;
if (parent != null) return parent.lookup(name);

FWIW I think this is a very common question - maybe analyzer could make an effort to explain why the variable was not promoted even though it looks like it could be promoted?

[Ideally we should just prohibit overriding fields with getters - use cases for that are very marginal, but maybe the ship has sailed on that one. Something to consider for Dart 3.0?]

[The point of having getters at all is to remove the distinction between computed and field-backed properties, so you can switch between them seamlessly. Disallowing fields from being overridden, but not getters/setters would break that symmetry. I'd rather introduce sealed members than blanket disallowing perfectly reasonable getter/setter overrides based on the implementation choice.]

I now understand why the access to that field cannot be checked, but copying each and every value into a local variable is very cumbersome. Something like Swift's if let would be very useful in this context.

Absolutely would be useful to do a check+binding in one operation.

C# has if (e is Foo y) which binds y to the value of e with static type Foo, after checking that it has that type. I like that syntax, and it should be compatible with Dart.

No plans right now, though.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

brooth picture brooth  路  3Comments

jmesserly picture jmesserly  路  3Comments

Hixie picture Hixie  路  3Comments

matanlurey picture matanlurey  路  3Comments

sgrekhov picture sgrekhov  路  3Comments