Skip to content

Commit

Permalink
Don't cache hashCode because items in collections might be mutable an…
Browse files Browse the repository at this point in the history
…d allowed to change
  • Loading branch information
passsy committed Aug 15, 2021
1 parent f38b76e commit b727893
Show file tree
Hide file tree
Showing 8 changed files with 38 additions and 9 deletions.
3 changes: 1 addition & 2 deletions lib/src/collection/impl/list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ class DartList<T> extends Object implements KtList<T> {
super();

final List<T> _list;
int? _hashCode;

@override
Iterable<T> get iter => _list;
Expand Down Expand Up @@ -76,7 +75,7 @@ class DartList<T> extends Object implements KtList<T> {
}

@override
int get hashCode => _hashCode ??= 1 + hashObjects(_list);
int get hashCode => 1 + hashObjects(_list);

@override
bool operator ==(dynamic other) {
Expand Down
3 changes: 1 addition & 2 deletions lib/src/collection/impl/map.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class DartMap<K, V> extends Object implements KtMap<K, V> {
super();

final Map<K, V> _map;
int? _hashCode;

@override
Iterable<KtMapEntry<K, V>> get iter =>
Expand Down Expand Up @@ -63,7 +62,7 @@ class DartMap<K, V> extends Object implements KtMap<K, V> {

@override
int get hashCode {
return _hashCode ??= hashObjects(_map.keys
return hashObjects(_map.keys
.map((key) => hash2(key.hashCode, _map[key].hashCode))
.toList(growable: false)
..sort());
Expand Down
3 changes: 1 addition & 2 deletions lib/src/collection/impl/set.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ class DartSet<T> extends Object implements KtSet<T> {
super();

final Set<T> _set;
int? _hashCode;

@override
Iterable<T> get iter => _set;
Expand Down Expand Up @@ -41,7 +40,7 @@ class DartSet<T> extends Object implements KtSet<T> {
int get size => _set.length;

@override
int get hashCode => _hashCode ??=
int get hashCode =>
hashObjects(_set.map((e) => e.hashCode).toList(growable: false)..sort());

@override
Expand Down
3 changes: 1 addition & 2 deletions lib/src/collection/kt_list.dart
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,6 @@ class _CastKtList<Source, T> implements KtList<T> {
_CastKtList(KtList<Source> list) : _list = list;

final KtList<Source> _list;
int? _hashCode;

@override
Iterable<T> get iter => _list.asList().cast();
Expand Down Expand Up @@ -496,7 +495,7 @@ class _CastKtList<Source, T> implements KtList<T> {
}

@override
int get hashCode => _hashCode ??= 1 + hashObjects(_list.asList());
int get hashCode => 1 + hashObjects(_list.asList());

@override
bool operator ==(dynamic other) {
Expand Down
2 changes: 1 addition & 1 deletion test/collection/list_empty_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ void main() {
group("KtList.of", () {
testEmptyList(<T>() => KtList<T>.of(), mutable: false);
});
group("KtList.of", () {
group("KtList.from", () {
testEmptyList(<T>() => KtList<T>.from(), mutable: false);
});
group("mutableListOf", () {
Expand Down
11 changes: 11 additions & 0 deletions test/collection/list_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,17 @@ void testList(
expect(list0, isNot(equals(list2)));
expect(list0.hashCode, isNot(equals(list2.hashCode)));
});

test("hashcode changes when mutable value change", () {
final list = listOf(mutableListOf('a', 'b'), mutableListOf('c'));
final hash1 = list.hashCode;

// mutate content in list, not the list itself
list[1].add('d');

final hash2 = list.hashCode;
expect(hash2, isNot(hash1));
});
});

group("reduceRight", () {
Expand Down
11 changes: 11 additions & 0 deletions test/collection/map_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -159,4 +159,15 @@ void testMap(KtMap<K, V> Function<K, V>(Map<K, V> map) mapFrom,
expect(keys, listOf(1, 2));
});
});

test("hashcode changes when mutable value change", () {
final map = mapFrom({1: mutableListOf('a', 'b')});
final hash1 = map.hashCode;

// mutate content in map, not the map itself
map[1]!.add('d');

final hash2 = map.hashCode;
expect(hash2, isNot(hash1));
});
}
11 changes: 11 additions & 0 deletions test/collection/set_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -226,5 +226,16 @@ void testSet(
catchException<UnsupportedError>(() => ktSet.asSet().add("asdf"));
expect(e.message, contains("unmodifiable"));
});

test("hashcode changes when mutable value change", () {
final set = setOf(mutableListOf('a', 'b'));
final hash1 = set.hashCode;

// mutate content in set, not the set itself
set.first().add('d');

final hash2 = set.hashCode;
expect(hash2, isNot(hash1));
});
}
}

0 comments on commit b727893

Please sign in to comment.