prefer-const-literals-to-create-immutables
Same as prefer_const_literals_to_create_immutables in Dart lints
- Group
- Style
- Path
lint/style/prefer-const-literals-to-create-immutables- Default
- Off, opt in
- Origin
- Dart lints
- Rule
- 330 of 512
Prefers const list, set, and map literals as arguments to constructors of @immutable classes.
An instance of an @immutable class should not hold a mutable collection.
A non-const collection literal passed
directly to such a constructor — or nested only inside other collection
literals in that argument — is flagged when it could be const: every
element is a provable constant and set elements and map keys have primitive
equality. A class is immutable when it or a class on its extends chain is
annotated @immutable or @Immutable(...) from package:meta.
Literals already in a constant context are implicitly const and are left
alone, as are arguments to classes whose immutability cannot be established.
Diagnostic ranges exclude parentheses surrounding the collection literal.
@immutable
class A {
A(this.values);
final List<int> values;
}
final a = A([1]); // BAD
final b = A(const [1]); // GOOD
Invalid
import 'package:flutter/widgets.dart';
import 'package:meta/meta.dart';
import 'package:meta/meta.dart' as meta;
@immutable
class Config {
const Config(this.values, {this.names = const {}, this.lookup = const {}});
final Object values;
final Object names;
final Object lookup;
}
class Special extends Config {
const Special(super.values);
}
class Tags extends StatelessWidget {
const Tags({super.key, required this.tags});
final List<String> tags;
@override
Widget build(BuildContext context) => const SizedBox();
}
const int base = 3;
void literals() {
print(Config([1, 2, base]));
print(Config(const [], names: {'a', 'b'}));
print(Config(const [], lookup: {'a': 1}));
print(Config(([1])));
print(Config(<int>[]));
print(Config([[1], const [2]]));
print(Tags(tags: ['x', 'y']));
print(Special([1]));
}
@immutable
abstract mixin class Base {
const Base();
}
class Derived extends Base {
const Derived(this.data);
final Object data;
}
void inherited() {
const local = 1;
print(Derived({'a': local}));
print(Derived(<String>{'x'}));
}
// Constructor-form meta annotations have the same immutable identity.
@Immutable('')
class ReasonedImmutable {
const ReasonedImmutable(this.values);
final List<Object> values;
}
void constructorAnnotation() {
print(ReasonedImmutable([]));
}
@Immutable('Collection arguments must remain immutable')
class ReasonedBase {
const ReasonedBase(this.values);
final Object values;
}
class ReasonedChild extends ReasonedBase {
const ReasonedChild(super.values);
}
void inheritedConstructorAnnotation() {
print(ReasonedChild([1]));
}
@meta.Immutable('')
class PrefixedImmutable {
const PrefixedImmutable(this.values);
final Object values;
}
void prefixedConstructorAnnotation() {
print(PrefixedImmutable({'key': 1}));
}void literals() { print(Config([1, 2, base])); print(Config([1, 2, base])); print(Config(const [], names: {'a', 'b'})); print(Config(const [], names: {'a', 'b'})); print(Config(const [], lookup: {'a': 1})); print(Config(const [], lookup: {'a': 1})); print(Config(([1]))); print(Config(([1]))); print(Config(<int>[])); print(Config(<int>[])); print(Config([[1], const [2]])); print(Config(<int>[])); print(Config([[1], const [2]])); print(Config([[1], const [2]])); print(Tags(tags: ['x', 'y'])); print(Tags(tags: ['x', 'y'])); print(Special([1])); const local = 1; print(Derived({'a': local})); print(Derived({'a': local})); print(Derived(<String>{'x'}));void constructorAnnotation() { print(ReasonedImmutable([]));void inheritedConstructorAnnotation() { print(ReasonedChild([1]));void prefixedConstructorAnnotation() { print(PrefixedImmutable({'key': 1}));Valid
import 'package:meta/meta.dart';
@immutable
class Config {
const Config(this.values, {this.names = const {}});
final Object values;
final Object names;
}
class Mutable {
Mutable(this.values);
final Object values;
}
class Lookalike implements Config {
Lookalike(this.values);
@override
final Object values;
@override
Object get names => const {};
}
void literals(int x, List<int> other) {
print(Config(const [1, 2]));
print(const Config([1, 2], names: {'a'}));
print(Config([x]));
print(Config([...other]));
print(Config([for (var i = 0; i < 3; i++) i]));
print(Config([if (x > 0) 1]));
print(Mutable([1, 2]));
final values = [1, 2];
print(Config(values));
print(Config(other.toList(), names: {x}));
print(Unknown([1]));
print(Lookalike([1]));
}
class EqualityKey {
const EqualityKey();
@override
bool operator ==(Object other) => other is EqualityKey;
@override
int get hashCode => 0;
}
void keysWithoutPrimitiveEquality() {
print(Config({EqualityKey(): 1}));
print(Config({1.5}));
}
@Immutable('')
class ReasonedImmutable {
const ReasonedImmutable(this.values);
final List<Object> values;
}
void constructorAnnotation(List<Object> values) {
print(ReasonedImmutable(const []));
print(const ReasonedImmutable([]));
print(ReasonedImmutable(values));
}
class ReasonedInterface implements ReasonedImmutable {
const ReasonedInterface(this.values);
@override
final List<Object> values;
}
void constructorAnnotationInterface() {
print(ReasonedInterface([]));
}Configure prefer-const-literals-to-create-immutables
Set its severity in falcon.json. See the configuration guide.
{
"linter": {
"rules": {
"style": {
"prefer-const-literals-to-create-immutables": "error"
}
}
}
}Or silence one occurrence with a suppression comment; the reason is required.
// falcon-ignore lint/style/prefer-const-literals-to-create-immutables: <reason>More style rules
- prefer-constrained-box-over-containerflutter
Prefers
ConstrainedBoxover aContainerused only forconstraints. - prefer-constructors-over-static-methods
prefer_constructors_over_static_methodsFlags static methods that create and return an instance of their own class.
- prefer-containerflutter
Suggests collapsing compatible nested layout widgets into one
Container. - prefer-correct-callback-field-name
Match callback field names to a configured regular expression.
- prefer-correct-error-name
Require configured error parameter names in catches and SDK error callbacks.
- prefer-correct-handler-name
Match callback handler methods to a configured regular expression.
- prefer-correct-identifier-length
prefer-correct-identifier-lengthFlags declared identifiers that are shorter or longer than the allowed range.
- prefer-correct-notifier-file-nameriverpod
Requires
snake_casefile names ending in _notifier.dart for resolved Riverpod notifier classes.