null-check-on-nullable-type-parameter

Same as null_check_on_nullable_type_parameter in Dart lints

Path
lint/correctness/null-check-on-nullable-type-parameter
Default
On (recommended)
Origin
Dart lints
Rule
301 of 512
recommended

Flags a null assertion x! on a nullable type parameter T? whose expected type is T or T? for a potentially nullable T, and null-assert patterns whose matched value is a nullable type parameter. Diagnostics underline only the terminal ! of either syntax-tree assertion node.

As in the analyzer's expected-type helper, only these positions have an expected type:

  • a returned or yielded value (also awaited) of a function declaration with a declared return type (an async function's Future argument), or of a closure or untyped local function whose block body's returns infer T or T?; methods have none;
  • a variable's initializer: its declared type, and for an untyped local or for variable the type inferred from x! itself;
  • the value (also awaited) of a plain = assignment, except x = x! and a.b = a.b!;
  • the right operand of an operator method, and an argument, including constructor-initializer super(...)/this(...) arguments; an awaited right operand or positional argument has none;
  • an element of a list or set literal, a key or value of a map literal (through the map's collection if and for elements); an awaited or parenthesized map key expects the map's value type.

Conditional branches, ?? operands, cascade targets, records, and patterns have none. Inferred types never keep the T & Object intersection of x!. Flow analysis promotes a local after its x!.

Invalid

example.dartdart
T force<T>(T? value) {
  T result = value!;
  T assigned;
  assigned = value!;
  return result;
}

T returnForce<T>(T? value) {
  return value!;
}

void pattern<T>(T? value) {
  if (value case var item!) {
    print(item);
  }
}

class Holder<T> {
  T field;
  T force(T? value) => value!;

  void assign(Holder<T> self, T? value) {
    self.field = value!;
  }
}

T closureContexts<T>(T? value) {
  final T Function(T?) callback = (T? inner) => inner!;
  final T Function<T>(T?) generic = <T>(T? inner) => inner!;
  callback(value);
  generic<T>(value);
  return value!;
}

class PatternBox<T> {
  PatternBox(this.value);
  final T? value;
}

void nestedPatterns<T>(
  (T?,) record,
  List<T?> list,
  Map<String, T?> map,
  PatternBox<T> box,
) {
  if (record case (var item!,)) {
    print(item);
  }
  if (list case [var item!]) {
    print(item);
  }
  if (map case {'x': var item!}) {
    print(item);
  }
  if (box case PatternBox(value: var item!)) {
    print(item);
  }
}

void acceptGeneric<T>(T Function() callback) {}

void explicitCallType<T>(T? value) {
  acceptGeneric<T>(() => value!);
}

T? keepNullable<T>(T? value) => value!;
void nullableAssignment<T>(T? value) {
  T? result;
  result = value!;
  print(result);
}

class Entry<T> {
  T? key;
}
void compare<T>(int Function(T, T) comparator, T key, Entry<T> entry) {
  comparator(key, entry.key!);
}

T assignment<T>(T? value) {
  T result;
  result = value!;
  return result;
}
Avoid a null assertion on a nullable type parameter.
1T force<T>(T? value) {
2 T result = value!;
Avoid a null assertion on a nullable type parameter.
8T returnForce<T>(T? value) {
9 return value!;
Avoid a null assertion on a nullable type parameter.
12void pattern<T>(T? value) {
13 if (value case var item!) {
Avoid a null assertion on a nullable type parameter.
22 void assign(Holder<T> self, T? value) {
23 self.field = value!;
Avoid a null assertion on a nullable type parameter.
31 generic<T>(value);
32 return value!;
Avoid a null assertion on a nullable type parameter.
45) {
46 if (record case (var item!,)) {
Avoid a null assertion on a nullable type parameter.
48 }
49 if (list case [var item!]) {
Avoid a null assertion on a nullable type parameter.
51 }
52 if (map case {'x': var item!}) {
Avoid a null assertion on a nullable type parameter.
54 }
55 if (box case PatternBox(value: var item!)) {
Avoid a null assertion on a nullable type parameter.
65
66T? keepNullable<T>(T? value) => value!;
Avoid a null assertion on a nullable type parameter.
68 T? result;
69 result = value!;
Avoid a null assertion on a nullable type parameter.
76void compare<T>(int Function(T, T) comparator, T key, Entry<T> entry) {
77 comparator(key, entry.key!);
Avoid a null assertion on a nullable type parameter.
81 T result;
82 result = value!;

Valid

example.dartdart
String forceString(String? value) => value!;


void concretePattern(String? value) {
  if (value case var item!) {
    print(item);
  }
}

class T {}

T classNamedT(T? value) => value!;

T outerReturnDoesNotLeak<T>(T? value) {
  final int Function() callback = () => value!;
  callback();
  return value;
}

T namedLocalDoesNotInheritContext<T>(T? value) {
  int local() => value!;
  local();
  return value;
}

T bounded<T extends Object>(T? value) => value!;
class Generic<T> {
  T force(T? value) => value!;
}
void inferredClosure<T>(T? value) {
  final T Function(T?) callback = (T? inner) => inner!;
  final T Function<T>(T?) generic = <T>(T? inner) => inner!;
  callback(value);
  generic<T>(value);
}

T checkedAssignment<T>(T? value) {
  value!;
  T result;
  result = value!;
  return result;
}

void selfAssignment<T>(T? value) {
  value = value!;
}

Configure null-check-on-nullable-type-parameter

Set its severity in falcon.json. See the configuration guide.

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "null-check-on-nullable-type-parameter": "error"
      }
    }
  }
}

Or silence one occurrence with a suppression comment; the reason is required.

example.dartdart
// falcon-ignore lint/correctness/null-check-on-nullable-type-parameter: <reason>