collection-methods-unrelated-type

Same as collection_methods_unrelated_type in Dart lints

Path
lint/correctness/collection-methods-unrelated-type
Default
On (recommended)
Origin
Dart lints
Rule
205 of 512
recommended

Reports collection lookups whose argument type is unrelated to the collection's type argument.

With exactly one argument, Iterable<E>.contains, List<E>.remove, Map<K, V>.containsKey/containsValue/remove, Queue<E>.remove, Set<E>.lookup/remove, and Map<K, V>.[] are checked on a receiver (explicit, or the implicit this of the enclosing type) that implements the declaring collection, whatever the receiver overrides. The argument must not be unrelated (TypeRelation::RuntimeUnrelatedTo) to the type argument.

Invalid

example.dartdart
import 'dart:collection';

void bad(
  Iterable<int> iterable,
  List<String> list,
  Set<int> set,
  Queue<String> queue,
  Map<String, int> map,
) {
  iterable.contains('x');
  list.remove(1);
  set.lookup('x');
  set.remove(false);
  queue.remove(1);
  map['key'];
  map[1];
  map.containsKey(1);
  map.containsValue('value');
  map.remove(false);
}

class IntValues {
  final List<int> values;

  IntValues(this.values) {
    values.contains('x');
  }
}

class BaseValues {
  final List<int> values;

  BaseValues(this.values);
}

class ForwardedValues extends BaseValues {
  ForwardedValues(super.values) {
    values.contains('x');
  }
}

void scopedCollections(List<int> values) {
  <String>['x'].forEach((String value) {
    values.contains(value);
  });

  for (final value in <String>['x']) {
    values.remove(value);
  }

  for (final [value] in <List<String>>[
    ['x'],
  ]) {
    values.contains(value);
  }

  {
    final value = 'x';
    values.contains(value);
  }
  values.contains(1);
}

class Lookup implements Map<String, int> {
  @override
  bool containsKey(Object? key) => false;

  @override
  dynamic noSuchMethod(Invocation invocation) => null;
}

void overridden(Lookup lookup, List<int> values) {
  lookup.containsKey(1);
  values..contains('x');
}

extension IntListChecks on List<int> {
  bool hasText(String text) => contains(text);
}
The argument type is unrelated to this collection's element type.
9) {
10 iterable.contains('x');
The argument type is unrelated to this collection's element type.
10 iterable.contains('x');
11 list.remove(1);
The argument type is unrelated to this collection's element type.
11 list.remove(1);
12 set.lookup('x');
The argument type is unrelated to this collection's element type.
12 set.lookup('x');
13 set.remove(false);
The argument type is unrelated to this collection's element type.
13 set.remove(false);
14 queue.remove(1);
The argument type is unrelated to this collection's element type.
15 map['key'];
16 map[1];
The argument type is unrelated to this collection's element type.
16 map[1];
17 map.containsKey(1);
The argument type is unrelated to this collection's element type.
17 map.containsKey(1);
18 map.containsValue('value');
The argument type is unrelated to this collection's element type.
18 map.containsValue('value');
19 map.remove(false);
The argument type is unrelated to this collection's element type.
25 IntValues(this.values) {
26 values.contains('x');
The argument type is unrelated to this collection's element type.
37 ForwardedValues(super.values) {
38 values.contains('x');
The argument type is unrelated to this collection's element type.
43 <String>['x'].forEach((String value) {
44 values.contains(value);
The argument type is unrelated to this collection's element type.
47 for (final value in <String>['x']) {
48 values.remove(value);
The argument type is unrelated to this collection's element type.
53 ]) {
54 values.contains(value);
The argument type is unrelated to this collection's element type.
58 final value = 'x';
59 values.contains(value);
The argument type is unrelated to this collection's element type.
72void overridden(Lookup lookup, List<int> values) {
73 lookup.containsKey(1);
The argument type is unrelated to this collection's element type.
73 lookup.containsKey(1);
74 values..contains('x');
The argument type is unrelated to this collection's element type.
77extension IntListChecks on List<int> {
78 bool hasText(String text) => contains(text);

Valid

example.dartdart
import 'dart:collection';
import 'dart:core' as core;

void good(
  Iterable<num> iterable,
  List<String> list,
  Set<int> set,
  Queue<String> queue,
  core.Map<String, int> map,
  dynamic unknown,
) {
  iterable.contains(1);
  list.remove('x');
  set.lookup(1);
  queue.remove('x');
  map['key'];
  map.containsKey('key');
  map.containsValue(1);
  map.remove('key');
  map.containsKey(unknown);
}

class Map<K, V> {
  bool containsKey(Object? value) => false;
}

void shadowed(Map<String, int> map) {
  map.containsKey(1);
}

void functionKeys(core.Map<core.Function?, core.int> makers, core.int Function() maker) {
  makers[maker];
}

// Named record fields match by name, not by source order.
void recordKeys() {
  final byScope = <({core.String id, core.int count}), core.List<core.int>>{};
  final key = (id: 'x', count: 1);
  (byScope[key] ??= <core.int>[]).add(1);
  byScope.containsKey((id: 'y', count: 2));
}

Configure collection-methods-unrelated-type

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

falcon.jsonjson
{
  "linter": {
    "rules": {
      "correctness": {
        "collection-methods-unrelated-type": "error"
      }
    }
  }
}

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

example.dartdart
// falcon-ignore lint/correctness/collection-methods-unrelated-type: <reason>