Skip to content

Commit b8c9297

Browse files
authored
Avoid setRange with potentially incompatible types (dart-archive/collection#320)
Fixes dart-lang/collection#317 Use `sublist` on the input to get a list with the same runtime generic as the input instead of constructing a new list with the static generic.
1 parent 347817c commit b8c9297

File tree

3 files changed

+17
-2
lines changed

3 files changed

+17
-2
lines changed

pkgs/collection/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
- Adds `shuffled` to `IterableExtension`.
44
- Shuffle `IterableExtension.sample` results.
5+
- Fix `mergeSort` when the runtime iterable generic is a subtype of the static
6+
generic.
57
- Require Dart `^3.1.0`
68
- Mark "mixin" classes as `mixin`.
79

pkgs/collection/lib/src/algorithms.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ void mergeSort<E>(List<E> elements,
232232
var middle = start + firstLength;
233233
var secondLength = end - middle;
234234
// secondLength is always the same as firstLength, or one greater.
235-
var scratchSpace = List<E>.filled(secondLength, elements[start]);
235+
var scratchSpace = elements.sublist(0, secondLength);
236236
_mergeSort(elements, identity<E>, compare, middle, end, scratchSpace, 0);
237237
var firstTarget = end - firstLength;
238238
_mergeSort(
@@ -268,7 +268,7 @@ void mergeSortBy<E, K>(List<E> elements, K Function(E element) keyOf,
268268
var firstLength = middle - start;
269269
var secondLength = end - middle;
270270
// secondLength is always the same as firstLength, or one greater.
271-
var scratchSpace = List<E>.filled(secondLength, elements[start]);
271+
var scratchSpace = elements.sublist(0, secondLength);
272272
_mergeSort(elements, keyOf, compare, middle, end, scratchSpace, 0);
273273
var firstTarget = end - firstLength;
274274
_mergeSort(elements, keyOf, compare, start, middle, elements, firstTarget);

pkgs/collection/test/algorithms_test.dart

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,19 @@ void main() {
368368
reverse(l, 0, 6);
369369
expect(l, equals([2, 1, 4, 3, 6, 5]));
370370
});
371+
372+
test('mergeSort works when runtime generic is a subtype of the static type',
373+
() {
374+
// Regression test for https://github.com/dart-lang/collection/issues/317
375+
final length = 1000; // Larger than _mergeSortLimit
376+
// Out of order list, with first half guaranteed to empty first during
377+
// merge.
378+
final list = [
379+
for (var i = 0; i < length / 2; i++) -i,
380+
for (var i = 0; i < length / 2; i++) i + length,
381+
];
382+
expect(() => mergeSort<num>(list), returnsNormally);
383+
});
371384
}
372385

373386
class C {

0 commit comments

Comments
 (0)