avoid-disposing-late-fields

Path
lint/correctness/avoid-disposing-late-fields
Default
Off, opt in
Origin
Falcon
Domain
flutter
Rule
42 of 512
flutter

Avoid releasing late State fields that may be unset or initialized only by cleanup.

A direct = assignment, or a direct read of a lazily initialized field, in synchronous initState is accepted in its initial straight-line prefix of expression statements, local declarations and empty statements. Any other statement ends that prefix, including assertions and pattern declarations. Arrow bodies are supported. Reads cover bare fields, property receivers, method receivers and cascade receivers, not nested arguments or callbacks. Conditional, nested, asynchronous and helper-based initialization is not proven; lazy field initializers alone still do not make cleanup safe.

Invalid

example.dartdart
import 'package:flutter/material.dart' as f;
class Resource {
  void dispose() {}
  void close() {}
  void cancel() {}
}
class S extends f.State<f.StatefulWidget> {
  late Resource unset;
  late final Resource lazy = Resource();
  late Resource stream, subscription;
  late Resource? optional;
  late Resource first = Resource(), second = Resource();
  void dispose() {
    unset.dispose();
    this.lazy.dispose();
    stream.close();
    subscription.cancel();
    optional?.dispose();
    optional!.close();
    unset..dispose();
    (this.lazy)..close();
    first.dispose();
    second.cancel();
    super.dispose();
  }
}
Initialize this `late` field unconditionally in `initState` before releasing it in `dispose`, or make it nullable.
13 void dispose() {
14 unset.dispose();
Initialize this `late` field unconditionally in `initState` before releasing it in `dispose`, or make it nullable.
14 unset.dispose();
15 this.lazy.dispose();
Initialize this `late` field unconditionally in `initState` before releasing it in `dispose`, or make it nullable.
15 this.lazy.dispose();
16 stream.close();
Initialize this `late` field unconditionally in `initState` before releasing it in `dispose`, or make it nullable.
16 stream.close();
17 subscription.cancel();
Initialize this `late` field unconditionally in `initState` before releasing it in `dispose`, or make it nullable.
17 subscription.cancel();
18 optional?.dispose();
Initialize this `late` field unconditionally in `initState` before releasing it in `dispose`, or make it nullable.
18 optional?.dispose();
19 optional!.close();
Initialize this `late` field unconditionally in `initState` before releasing it in `dispose`, or make it nullable.
19 optional!.close();
20 unset..dispose();
Initialize this `late` field unconditionally in `initState` before releasing it in `dispose`, or make it nullable.
20 unset..dispose();
21 (this.lazy)..close();
Initialize this `late` field unconditionally in `initState` before releasing it in `dispose`, or make it nullable.
21 (this.lazy)..close();
22 first.dispose();
Initialize this `late` field unconditionally in `initState` before releasing it in `dispose`, or make it nullable.
22 first.dispose();
23 second.cancel();

Valid

example.dartdart
import 'package:flutter/material.dart';
class Resource {
  void dispose() {}
  void close() {}
  void cancel() {}
}
class S extends State<StatefulWidget> {
  Resource? optional;
  final eager = Resource();
  late Resource deferred;
  static late Resource shared;
  void cleanup() { deferred.dispose(); }
  void dispose() {
    optional?.dispose();
    eager.dispose();
    shared.dispose();
    final deferred = Resource();
    deferred.dispose();
    void release(Resource deferred) { deferred.dispose(); }
    super.dispose();
  }
}
class Other {
  late Resource resource;
  void dispose() { resource.dispose(); }
}
class Holder extends State<StatefulWidget> {
  late Resource resource;
  void dispose() {
    final other = Other();
    other.resource.dispose();
    super.dispose();
  }
}

Configure avoid-disposing-late-fields

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "avoid-disposing-late-fields": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/correctness/avoid-disposing-late-fields: <reason>