function-always-returns-null

Path
lint/correctness/function-always-returns-null
Default
Off, opt in
Origin
Falcon
Rule
239 of 512

Flags value functions with a proven explicit null return on every path. Bare returns and implicit fallthrough are deliberately not treated as proof. Only synchronous value functions are considered; getters, setters, @override-annotated methods and callbacks are excluded. Unsupported control flow (including loops, switches and exception handling) fails closed.

Invalid

example.dartdart
const empty = null;
Object? arrow() => null;
Object? direct() { return null; }
Object? both(bool flag) {
  if (flag) { return null; } else { return null; }
}
Object? trailing(bool flag) {
  if (flag) return null;
  return null;
}
Object? lexical() {
  return empty;
}
Object? nested(bool flag) {
  Object inner() => 4;
  if (flag) { if (flag) return null; else return null; }
  return null;
}
class Example {
  Object? method() => null;
}

Object? constListEquality() => const <int>[] == const <int>[] ? null : 1;
This function returns `null` on every path; remove the return value or return a meaningful value.
1const empty = null;
2Object? arrow() => null;
This function returns `null` on every path; remove the return value or return a meaningful value.
2Object? arrow() => null;
3Object? direct() { return null; }
This function returns `null` on every path; remove the return value or return a meaningful value.
3Object? direct() { return null; }
4Object? both(bool flag) {
This function returns `null` on every path; remove the return value or return a meaningful value.
6}
7Object? trailing(bool flag) {
This function returns `null` on every path; remove the return value or return a meaningful value.
10}
11Object? lexical() {
This function returns `null` on every path; remove the return value or return a meaningful value.
13}
14Object? nested(bool flag) {
This function returns `null` on every path; remove the return value or return a meaningful value.
19class Example {
20 Object? method() => null;
This function returns `null` on every path; remove the return value or return a meaningful value.
22
23Object? constListEquality() => const <int>[] == const <int>[] ? null : 1;

Valid

example.dartdart
Object? mixed(bool flag) { if (flag) return null; return 1; }
Object? fallthrough(bool flag) { if (flag) return null; }
Object? empty() {}
void bare() { return; }
void explicitVoid() { return null; }
Object? variable(Object? value) => value;
Object? shadow(Object? empty) { return empty; }
Object? nested(Object? value) {
  Object inner() => 1;
  return value;
}
Object? finallyWins() { try { return null; } finally { return 1; } }
Object? loop(bool flag) { while (flag) { return null; } return null; }
Iterable<Object?> generator() sync* { yield null; }
Future<Object?> asynchronous() async => null;
Object? get emptyGetter => null;
class Example { Object? get value => null; }

typedef VoidCallback = void Function();
void onPressed(VoidCallback callback) {}
void useEffect(Object? Function() callback) {}
void callbacks() {
  VoidCallback callback = () => null;
  onPressed(() { return null; });
  useEffect(() { return null; });
  callback();
}
abstract class Contract {
  Object? result();
  Object? get value;
}
class Implementation implements Contract {
  @override
  Object? result() => null;
  @override
  Object? get value => null;
}
const environmentValue = bool.fromEnvironment('RETURN_NULL') ? null : 1;
Object? environmentDependent() => environmentValue;
Object? capturedConstant() {
  const value = null;
  return value;
}

const shadowedResult = null;
class OwnGetterShadow {
  Object? current;
  Object? get shadowedResult => current;
  Object? result() => shadowedResult;
}
class GetterBase {
  Object? current;
  Object? get shadowedResult => current;
}
class InheritedGetterShadow extends GetterBase {
  Object? result() => shadowedResult;
}

extension NamedGetterShadow on String {
  Object? get shadowedResult => this;
  Object? namedResult() => shadowedResult;
}
extension on List<int> {
  Object? get shadowedResult => this;
  Object? unnamedResult() => shadowedResult;
}

Object? freshListEquality() => <int>[] == <int>[] ? null : 1;
Object? freshSetInequality() => <int>{} != <int>{} ? 1 : null;
Object? freshMapIdentity() => identical(<int, int>{}, <int, int>{}) ? null : 1;
class FreshValue { const FreshValue(); }
Object? freshConstructorEquality() => FreshValue() == FreshValue() ? null : 1;
Object? nestedRecordIdentity() => identical((<int>[],), (<int>[],)) ? null : 1;
Object? nestedRecordEquality() => (<int>[],) == (<int>[],) ? null : 1;

Configure function-always-returns-null

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "function-always-returns-null": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/correctness/function-always-returns-null: <reason>