mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 00:58:29 +00:00
Make EfficientLength extend Iterable.
This should help least-upper-bound computations to not think of EfficientLength
as completely separate from Iterable even though they are always used together.
It doesn't solve all problems with the least-upper-bound computation,
but at least some of the more often occuring ones.
R=floitsch@google.com
Review URL: https://codereview.chromium.org/2467113003 .
Committed: b08fb1373f
This commit is contained in:
parent
b20b10a0af
commit
7957a1c256
|
@ -33,7 +33,7 @@ const _GROWABLE_ARRAY_MARKER = const _GrowableArrayMarker();
|
||||||
}
|
}
|
||||||
|
|
||||||
@patch factory List.from(Iterable elements, { bool growable: true }) {
|
@patch factory List.from(Iterable elements, { bool growable: true }) {
|
||||||
if (elements is EfficientLength) {
|
if (elements is EfficientLengthIterable) {
|
||||||
int length = elements.length;
|
int length = elements.length;
|
||||||
var list = growable ? new _GrowableList<E>(length) : new _List<E>(length);
|
var list = growable ? new _GrowableList<E>(length) : new _List<E>(length);
|
||||||
if (length > 0) { // Avoid creating iterator unless necessary.
|
if (length > 0) { // Avoid creating iterator unless necessary.
|
||||||
|
|
|
@ -435,8 +435,7 @@ class _HashMapEntry {
|
||||||
_HashMapEntry(this.key, this.value, this.hashCode, this.next);
|
_HashMapEntry(this.key, this.value, this.hashCode, this.next);
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class _HashMapIterable<E> extends IterableBase<E>
|
abstract class _HashMapIterable<E> extends EfficientLengthIterable<E> {
|
||||||
implements EfficientLength {
|
|
||||||
final HashMap _map;
|
final HashMap _map;
|
||||||
_HashMapIterable(this._map);
|
_HashMapIterable(this._map);
|
||||||
int get length => _map.length;
|
int get length => _map.length;
|
||||||
|
@ -838,8 +837,7 @@ class _LinkedHashMapEntry extends _HashMapEntry {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LinkedHashMapKeyIterable<K> extends IterableBase<K>
|
class _LinkedHashMapKeyIterable<K> extends EfficientLengthIterable<K> {
|
||||||
implements EfficientLength {
|
|
||||||
LinkedHashMap<K, dynamic> _map;
|
LinkedHashMap<K, dynamic> _map;
|
||||||
_LinkedHashMapKeyIterable(this._map);
|
_LinkedHashMapKeyIterable(this._map);
|
||||||
Iterator<K> get iterator => new _LinkedHashMapKeyIterator<K>(_map);
|
Iterator<K> get iterator => new _LinkedHashMapKeyIterator<K>(_map);
|
||||||
|
@ -850,8 +848,7 @@ class _LinkedHashMapKeyIterable<K> extends IterableBase<K>
|
||||||
Set<K> toSet() => _map._newKeySet()..addAll(this);
|
Set<K> toSet() => _map._newKeySet()..addAll(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _LinkedHashMapValueIterable<V> extends IterableBase<V>
|
class _LinkedHashMapValueIterable<V> extends EfficientLengthIterable<V> {
|
||||||
implements EfficientLength {
|
|
||||||
LinkedHashMap<dynamic, V> _map;
|
LinkedHashMap<dynamic, V> _map;
|
||||||
_LinkedHashMapValueIterable(this._map);
|
_LinkedHashMapValueIterable(this._map);
|
||||||
Iterator<V> get iterator => new _LinkedHashMapValueIterator<V>(_map);
|
Iterator<V> get iterator => new _LinkedHashMapValueIterator<V>(_map);
|
||||||
|
|
|
@ -174,7 +174,7 @@ class _GrowableList<T> extends ListBase<T> {
|
||||||
(cid == ClassID.cidArray) ||
|
(cid == ClassID.cidArray) ||
|
||||||
(cid == ClassID.cidGrowableObjectArray) ||
|
(cid == ClassID.cidGrowableObjectArray) ||
|
||||||
(cid == ClassID.cidImmutableArray);
|
(cid == ClassID.cidImmutableArray);
|
||||||
if (isVMList || (iterable is EfficientLength)) {
|
if (isVMList || (iterable is EfficientLengthIterable)) {
|
||||||
var cap = _capacity;
|
var cap = _capacity;
|
||||||
// Pregrow if we know iterable.length.
|
// Pregrow if we know iterable.length.
|
||||||
var iterLen = iterable.length;
|
var iterLen = iterable.length;
|
||||||
|
|
|
@ -85,8 +85,7 @@ class ImmutableMap<K, V> implements Map<K, V> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ImmutableMapKeyIterable<E> extends IterableBase<E>
|
class _ImmutableMapKeyIterable<E> extends EfficientLengthIterable<E> {
|
||||||
implements EfficientLength {
|
|
||||||
final ImmutableMap _map;
|
final ImmutableMap _map;
|
||||||
_ImmutableMapKeyIterable(this._map);
|
_ImmutableMapKeyIterable(this._map);
|
||||||
|
|
||||||
|
@ -97,8 +96,7 @@ class _ImmutableMapKeyIterable<E> extends IterableBase<E>
|
||||||
int get length => _map.length;
|
int get length => _map.length;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ImmutableMapValueIterable<E> extends IterableBase<E>
|
class _ImmutableMapValueIterable<E> extends EfficientLengthIterable<E> {
|
||||||
implements EfficientLength {
|
|
||||||
final ImmutableMap _map;
|
final ImmutableMap _map;
|
||||||
_ImmutableMapValueIterable(this._map);
|
_ImmutableMapValueIterable(this._map);
|
||||||
|
|
||||||
|
|
|
@ -155,7 +155,7 @@ abstract class _StringBase {
|
||||||
static String _createStringFromIterable(Iterable<int> charCodes,
|
static String _createStringFromIterable(Iterable<int> charCodes,
|
||||||
int start, int end) {
|
int start, int end) {
|
||||||
// Treat charCodes as Iterable.
|
// Treat charCodes as Iterable.
|
||||||
if (charCodes is EfficientLength) {
|
if (charCodes is EfficientLengthIterable) {
|
||||||
int length = charCodes.length;
|
int length = charCodes.length;
|
||||||
end = RangeError.checkValidRange(start, end, length);
|
end = RangeError.checkValidRange(start, end, length);
|
||||||
List charCodeList = new List.from(charCodes.take(end).skip(start),
|
List charCodeList = new List.from(charCodes.take(end).skip(start),
|
||||||
|
|
|
@ -2230,9 +2230,10 @@ TEST_CASE(Debug_GetSupertype) {
|
||||||
{
|
{
|
||||||
Dart_Handle set_type = Dart_GetType(core_lib, set_name, 0, NULL);
|
Dart_Handle set_type = Dart_GetType(core_lib, set_name, 0, NULL);
|
||||||
Dart_Handle super_type = Dart_GetSupertype(set_type);
|
Dart_Handle super_type = Dart_GetSupertype(set_type);
|
||||||
|
Dart_Handle super2_type = Dart_GetSupertype(super_type);
|
||||||
Dart_Handle iterable_type = Dart_GetType(core_lib, iterable_name, 0, NULL);
|
Dart_Handle iterable_type = Dart_GetType(core_lib, iterable_name, 0, NULL);
|
||||||
const Type& expected_type = Api::UnwrapTypeHandle(zone, iterable_type);
|
const Type& expected_type = Api::UnwrapTypeHandle(zone, iterable_type);
|
||||||
const Type& actual_type = Api::UnwrapTypeHandle(zone, super_type);
|
const Type& actual_type = Api::UnwrapTypeHandle(zone, super2_type);
|
||||||
EXPECT(expected_type.raw() == actual_type.raw());
|
EXPECT(expected_type.raw() == actual_type.raw());
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
|
|
@ -431,8 +431,7 @@ class _CustomHashMap<K, V> extends _HashMap<K, V> {
|
||||||
String toString() => Maps.mapToString(this);
|
String toString() => Maps.mapToString(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _HashMapKeyIterable<E> extends Iterable<E>
|
class _HashMapKeyIterable<E> extends EfficientLengthIterable<E> {
|
||||||
implements EfficientLength {
|
|
||||||
final _map;
|
final _map;
|
||||||
_HashMapKeyIterable(this._map);
|
_HashMapKeyIterable(this._map);
|
||||||
|
|
||||||
|
@ -664,8 +663,7 @@ class _Es6LinkedIdentityHashMap<K, V>
|
||||||
String toString() => Maps.mapToString(this);
|
String toString() => Maps.mapToString(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _Es6MapIterable<E> extends Iterable<E>
|
class _Es6MapIterable<E> extends EfficientLengthIterable<E> {
|
||||||
implements EfficientLength {
|
|
||||||
final _map;
|
final _map;
|
||||||
final bool _isKeys;
|
final bool _isKeys;
|
||||||
|
|
||||||
|
|
|
@ -146,7 +146,7 @@ class JSArray<E> extends Interceptor implements List<E>, JSIndexable {
|
||||||
void insertAll(int index, Iterable<E> iterable) {
|
void insertAll(int index, Iterable<E> iterable) {
|
||||||
checkGrowable('insertAll');
|
checkGrowable('insertAll');
|
||||||
RangeError.checkValueInInterval(index, 0, this.length, "index");
|
RangeError.checkValueInInterval(index, 0, this.length, "index");
|
||||||
if (iterable is! EfficientLength) {
|
if (iterable is! EfficientLengthIterable) {
|
||||||
iterable = iterable.toList();
|
iterable = iterable.toList();
|
||||||
}
|
}
|
||||||
int insertionLength = iterable.length;
|
int insertionLength = iterable.length;
|
||||||
|
@ -463,7 +463,7 @@ class JSArray<E> extends Interceptor implements List<E>, JSIndexable {
|
||||||
void replaceRange(int start, int end, Iterable<E> replacement) {
|
void replaceRange(int start, int end, Iterable<E> replacement) {
|
||||||
checkGrowable('replace range');
|
checkGrowable('replace range');
|
||||||
RangeError.checkValidRange(start, end, this.length);
|
RangeError.checkValidRange(start, end, this.length);
|
||||||
if (replacement is! EfficientLength) {
|
if (replacement is! EfficientLengthIterable) {
|
||||||
replacement = replacement.toList();
|
replacement = replacement.toList();
|
||||||
}
|
}
|
||||||
int removeLength = end - start;
|
int removeLength = end - start;
|
||||||
|
|
|
@ -56,7 +56,7 @@ import 'dart:_foreign_helper' show
|
||||||
import 'dart:_interceptors';
|
import 'dart:_interceptors';
|
||||||
import 'dart:_internal' as _symbol_dev;
|
import 'dart:_internal' as _symbol_dev;
|
||||||
import 'dart:_internal' show
|
import 'dart:_internal' show
|
||||||
EfficientLength,
|
EfficientLengthIterable,
|
||||||
MappedIterable,
|
MappedIterable,
|
||||||
IterableElementError;
|
IterableElementError;
|
||||||
|
|
||||||
|
|
|
@ -380,8 +380,7 @@ class LinkedHashMapCell<K, V> {
|
||||||
LinkedHashMapCell(this.hashMapCellKey, this.hashMapCellValue);
|
LinkedHashMapCell(this.hashMapCellKey, this.hashMapCellValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
class LinkedHashMapKeyIterable<E> extends Iterable<E>
|
class LinkedHashMapKeyIterable<E> extends EfficientLengthIterable<E> {
|
||||||
implements EfficientLength {
|
|
||||||
final dynamic/*=JsLinkedHashMap<E, dynamic>*/ _map;
|
final dynamic/*=JsLinkedHashMap<E, dynamic>*/ _map;
|
||||||
LinkedHashMapKeyIterable(this._map);
|
LinkedHashMapKeyIterable(this._map);
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ abstract class IterableMixin<E> implements Iterable<E> {
|
||||||
Set<E> toSet() => new Set<E>.from(this);
|
Set<E> toSet() => new Set<E>.from(this);
|
||||||
|
|
||||||
int get length {
|
int get length {
|
||||||
assert(this is! EfficientLength);
|
assert(this is! EfficientLengthIterable);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
Iterator it = iterator;
|
Iterator it = iterator;
|
||||||
while (it.moveNext()) {
|
while (it.moveNext()) {
|
||||||
|
|
|
@ -395,7 +395,7 @@ abstract class ListMixin<E> implements List<E> {
|
||||||
|
|
||||||
void replaceRange(int start, int end, Iterable<E> newContents) {
|
void replaceRange(int start, int end, Iterable<E> newContents) {
|
||||||
RangeError.checkValidRange(start, end, this.length);
|
RangeError.checkValidRange(start, end, this.length);
|
||||||
if (newContents is! EfficientLength) {
|
if (newContents is! EfficientLengthIterable) {
|
||||||
newContents = newContents.toList();
|
newContents = newContents.toList();
|
||||||
}
|
}
|
||||||
int removeLength = end - start;
|
int removeLength = end - start;
|
||||||
|
@ -482,7 +482,7 @@ abstract class ListMixin<E> implements List<E> {
|
||||||
|
|
||||||
void insertAll(int index, Iterable<E> iterable) {
|
void insertAll(int index, Iterable<E> iterable) {
|
||||||
RangeError.checkValueInInterval(index, 0, length, "index");
|
RangeError.checkValueInInterval(index, 0, length, "index");
|
||||||
if (iterable is! EfficientLength || identical(iterable, this)) {
|
if (iterable is! EfficientLengthIterable || identical(iterable, this)) {
|
||||||
iterable = iterable.toList();
|
iterable = iterable.toList();
|
||||||
}
|
}
|
||||||
int insertionLength = iterable.length;
|
int insertionLength = iterable.length;
|
||||||
|
|
|
@ -111,8 +111,7 @@ abstract class UnmodifiableMapBase<K, V> =
|
||||||
* It accesses the values by iterating over the keys of the map, and using the
|
* It accesses the values by iterating over the keys of the map, and using the
|
||||||
* map's `operator[]` to lookup the keys.
|
* map's `operator[]` to lookup the keys.
|
||||||
*/
|
*/
|
||||||
class _MapBaseValueIterable<K, V> extends Iterable<V>
|
class _MapBaseValueIterable<K, V> extends EfficientLengthIterable<V> {
|
||||||
implements EfficientLength {
|
|
||||||
final Map<K, V> _map;
|
final Map<K, V> _map;
|
||||||
_MapBaseValueIterable(this._map);
|
_MapBaseValueIterable(this._map);
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ part of dart.collection;
|
||||||
* This goes both for using the [iterator] directly, or for iterating an
|
* This goes both for using the [iterator] directly, or for iterating an
|
||||||
* `Iterable` returned by a method like [map] or [where].
|
* `Iterable` returned by a method like [map] or [where].
|
||||||
*/
|
*/
|
||||||
abstract class Queue<E> implements Iterable<E>, EfficientLength {
|
abstract class Queue<E> implements EfficientLengthIterable<E> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a queue.
|
* Creates a queue.
|
||||||
|
@ -487,7 +487,7 @@ class ListQueue<E> extends ListIterable<E> implements Queue<E> {
|
||||||
return queue;
|
return queue;
|
||||||
} else {
|
} else {
|
||||||
int capacity = _INITIAL_CAPACITY;
|
int capacity = _INITIAL_CAPACITY;
|
||||||
if (elements is EfficientLength) {
|
if (elements is EfficientLengthIterable) {
|
||||||
capacity = elements.length;
|
capacity = elements.length;
|
||||||
}
|
}
|
||||||
ListQueue<E> result = new ListQueue<E>(capacity);
|
ListQueue<E> result = new ListQueue<E>(capacity);
|
||||||
|
|
|
@ -607,8 +607,7 @@ abstract class _SplayTreeIterator<K, T> implements Iterator<T> {
|
||||||
T _getValue(_SplayTreeNode<K> node);
|
T _getValue(_SplayTreeNode<K> node);
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SplayTreeKeyIterable<K> extends Iterable<K>
|
class _SplayTreeKeyIterable<K> extends EfficientLengthIterable<K> {
|
||||||
implements EfficientLength {
|
|
||||||
_SplayTree<K, _SplayTreeNode<K>> _tree;
|
_SplayTree<K, _SplayTreeNode<K>> _tree;
|
||||||
_SplayTreeKeyIterable(this._tree);
|
_SplayTreeKeyIterable(this._tree);
|
||||||
int get length => _tree._count;
|
int get length => _tree._count;
|
||||||
|
@ -624,8 +623,7 @@ class _SplayTreeKeyIterable<K> extends Iterable<K>
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SplayTreeValueIterable<K, V> extends Iterable<V>
|
class _SplayTreeValueIterable<K, V> extends EfficientLengthIterable<V> {
|
||||||
implements EfficientLength {
|
|
||||||
SplayTreeMap<K, V> _map;
|
SplayTreeMap<K, V> _map;
|
||||||
_SplayTreeValueIterable(this._map);
|
_SplayTreeValueIterable(this._map);
|
||||||
int get length => _map._count;
|
int get length => _map._count;
|
||||||
|
|
|
@ -368,7 +368,7 @@ abstract class Iterable<E> {
|
||||||
* Some iterables have a more efficient way to find the number of elements.
|
* Some iterables have a more efficient way to find the number of elements.
|
||||||
*/
|
*/
|
||||||
int get length {
|
int get length {
|
||||||
assert(this is! EfficientLength);
|
assert(this is! EfficientLengthIterable);
|
||||||
int count = 0;
|
int count = 0;
|
||||||
Iterator it = iterator;
|
Iterator it = iterator;
|
||||||
while (it.moveNext()) {
|
while (it.moveNext()) {
|
||||||
|
|
|
@ -51,7 +51,7 @@ part of dart.core;
|
||||||
* directly or through iterating an [Iterable] that is backed by the list, will
|
* directly or through iterating an [Iterable] that is backed by the list, will
|
||||||
* break the iteration.
|
* break the iteration.
|
||||||
*/
|
*/
|
||||||
abstract class List<E> implements Iterable<E>, EfficientLength {
|
abstract class List<E> implements EfficientLengthIterable<E> {
|
||||||
/**
|
/**
|
||||||
* Creates a list of the given length.
|
* Creates a list of the given length.
|
||||||
*
|
*
|
||||||
|
|
|
@ -31,7 +31,7 @@ part of dart.core;
|
||||||
* iterating either the set itself or any [Iterable] that is backed by the set,
|
* iterating either the set itself or any [Iterable] that is backed by the set,
|
||||||
* such as the ones returned by methods like [where] and [map].
|
* such as the ones returned by methods like [where] and [map].
|
||||||
*/
|
*/
|
||||||
abstract class Set<E> extends Iterable<E> implements EfficientLength {
|
abstract class Set<E> extends EfficientLengthIterable<E> {
|
||||||
/**
|
/**
|
||||||
* Creates an empty [Set].
|
* Creates an empty [Set].
|
||||||
*
|
*
|
||||||
|
|
|
@ -8,7 +8,8 @@ part of dart._internal;
|
||||||
* Marker interface for [Iterable] subclasses that have an efficient
|
* Marker interface for [Iterable] subclasses that have an efficient
|
||||||
* [length] implementation.
|
* [length] implementation.
|
||||||
*/
|
*/
|
||||||
abstract class EfficientLength {
|
abstract class EfficientLengthIterable<T> extends Iterable<T> {
|
||||||
|
const EfficientLengthIterable();
|
||||||
/**
|
/**
|
||||||
* Returns the number of elements in the iterable.
|
* Returns the number of elements in the iterable.
|
||||||
*
|
*
|
||||||
|
@ -24,8 +25,7 @@ abstract class EfficientLength {
|
||||||
* All other methods are implemented in terms of [length] and [elementAt],
|
* All other methods are implemented in terms of [length] and [elementAt],
|
||||||
* including [iterator].
|
* including [iterator].
|
||||||
*/
|
*/
|
||||||
abstract class ListIterable<E> extends Iterable<E>
|
abstract class ListIterable<E> extends EfficientLengthIterable<E> {
|
||||||
implements EfficientLength {
|
|
||||||
int get length;
|
int get length;
|
||||||
E elementAt(int i);
|
E elementAt(int i);
|
||||||
|
|
||||||
|
@ -354,7 +354,7 @@ class MappedIterable<S, T> extends Iterable<T> {
|
||||||
final _Transformation<S, T> _f;
|
final _Transformation<S, T> _f;
|
||||||
|
|
||||||
factory MappedIterable(Iterable<S> iterable, T function(S value)) {
|
factory MappedIterable(Iterable<S> iterable, T function(S value)) {
|
||||||
if (iterable is EfficientLength) {
|
if (iterable is EfficientLengthIterable) {
|
||||||
return new EfficientLengthMappedIterable<S, T>(iterable, function);
|
return new EfficientLengthMappedIterable<S, T>(iterable, function);
|
||||||
}
|
}
|
||||||
return new MappedIterable<S, T>._(iterable, function);
|
return new MappedIterable<S, T>._(iterable, function);
|
||||||
|
@ -376,7 +376,7 @@ class MappedIterable<S, T> extends Iterable<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T>
|
class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T>
|
||||||
implements EfficientLength {
|
implements EfficientLengthIterable<T> {
|
||||||
EfficientLengthMappedIterable(Iterable<S> iterable, T function(S value))
|
EfficientLengthMappedIterable(Iterable<S> iterable, T function(S value))
|
||||||
: super._(iterable, function);
|
: super._(iterable, function);
|
||||||
}
|
}
|
||||||
|
@ -406,7 +406,7 @@ class MappedIterator<S, T> extends Iterator<T> {
|
||||||
* Expects efficient `length` and `elementAt` on the source iterable.
|
* Expects efficient `length` and `elementAt` on the source iterable.
|
||||||
*/
|
*/
|
||||||
class MappedListIterable<S, T> extends ListIterable<T>
|
class MappedListIterable<S, T> extends ListIterable<T>
|
||||||
implements EfficientLength {
|
implements EfficientLengthIterable<T> {
|
||||||
final Iterable<S> _source;
|
final Iterable<S> _source;
|
||||||
final _Transformation<S, T> _f;
|
final _Transformation<S, T> _f;
|
||||||
|
|
||||||
|
@ -427,7 +427,7 @@ class WhereIterable<E> extends Iterable<E> {
|
||||||
|
|
||||||
Iterator<E> get iterator => new WhereIterator<E>(_iterable.iterator, _f);
|
Iterator<E> get iterator => new WhereIterator<E>(_iterable.iterator, _f);
|
||||||
|
|
||||||
// Specialization of [Iterable.map] to non-EfficientLength.
|
// Specialization of [Iterable.map] to non-EfficientLengthIterable.
|
||||||
Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)) =>
|
Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)) =>
|
||||||
new MappedIterable<E, dynamic/*=T*/>._(this, f);
|
new MappedIterable<E, dynamic/*=T*/>._(this, f);
|
||||||
}
|
}
|
||||||
|
@ -500,7 +500,7 @@ class TakeIterable<E> extends Iterable<E> {
|
||||||
if (takeCount is! int || takeCount < 0) {
|
if (takeCount is! int || takeCount < 0) {
|
||||||
throw new ArgumentError(takeCount);
|
throw new ArgumentError(takeCount);
|
||||||
}
|
}
|
||||||
if (iterable is EfficientLength) {
|
if (iterable is EfficientLengthIterable) {
|
||||||
return new EfficientLengthTakeIterable<E>(iterable, takeCount);
|
return new EfficientLengthTakeIterable<E>(iterable, takeCount);
|
||||||
}
|
}
|
||||||
return new TakeIterable<E>._(iterable, takeCount);
|
return new TakeIterable<E>._(iterable, takeCount);
|
||||||
|
@ -514,7 +514,7 @@ class TakeIterable<E> extends Iterable<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class EfficientLengthTakeIterable<E> extends TakeIterable<E>
|
class EfficientLengthTakeIterable<E> extends TakeIterable<E>
|
||||||
implements EfficientLength {
|
implements EfficientLengthIterable<E> {
|
||||||
EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount)
|
EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount)
|
||||||
: super._(iterable, takeCount);
|
: super._(iterable, takeCount);
|
||||||
|
|
||||||
|
@ -587,7 +587,7 @@ class SkipIterable<E> extends Iterable<E> {
|
||||||
final int _skipCount;
|
final int _skipCount;
|
||||||
|
|
||||||
factory SkipIterable(Iterable<E> iterable, int count) {
|
factory SkipIterable(Iterable<E> iterable, int count) {
|
||||||
if (iterable is EfficientLength) {
|
if (iterable is EfficientLengthIterable) {
|
||||||
return new EfficientLengthSkipIterable<E>(iterable, count);
|
return new EfficientLengthSkipIterable<E>(iterable, count);
|
||||||
}
|
}
|
||||||
return new SkipIterable<E>._(iterable, count);
|
return new SkipIterable<E>._(iterable, count);
|
||||||
|
@ -614,7 +614,7 @@ class SkipIterable<E> extends Iterable<E> {
|
||||||
}
|
}
|
||||||
|
|
||||||
class EfficientLengthSkipIterable<E> extends SkipIterable<E>
|
class EfficientLengthSkipIterable<E> extends SkipIterable<E>
|
||||||
implements EfficientLength {
|
implements EfficientLengthIterable<E> {
|
||||||
EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount)
|
EfficientLengthSkipIterable(Iterable<E> iterable, int skipCount)
|
||||||
: super._(iterable, skipCount);
|
: super._(iterable, skipCount);
|
||||||
|
|
||||||
|
@ -676,7 +676,7 @@ class SkipWhileIterator<E> extends Iterator<E> {
|
||||||
/**
|
/**
|
||||||
* The always empty [Iterable].
|
* The always empty [Iterable].
|
||||||
*/
|
*/
|
||||||
class EmptyIterable<E> extends Iterable<E> implements EfficientLength {
|
class EmptyIterable<E> extends EfficientLengthIterable<E> {
|
||||||
const EmptyIterable();
|
const EmptyIterable();
|
||||||
|
|
||||||
Iterator<E> get iterator => const EmptyIterator();
|
Iterator<E> get iterator => const EmptyIterator();
|
||||||
|
|
|
@ -34,7 +34,7 @@ class TestIterable extends TestIterableBase {
|
||||||
int get length => throw "SHOULD NOT BE CALLED";
|
int get length => throw "SHOULD NOT BE CALLED";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implement Set for private EfficientLength interface.
|
// Implement Set for private EfficientLengthIterable interface.
|
||||||
class EfficientTestIterable extends TestIterableBase
|
class EfficientTestIterable extends TestIterableBase
|
||||||
implements Set<int> {
|
implements Set<int> {
|
||||||
EfficientTestIterable(length, count, [callbackIndex = -1, callback])
|
EfficientTestIterable(length, count, [callbackIndex = -1, callback])
|
||||||
|
@ -104,7 +104,7 @@ void testConstructor() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void testConcurrentModification() {
|
void testConcurrentModification() {
|
||||||
// Without EfficientLength interface
|
// Without EfficientLengthIterable interface
|
||||||
{
|
{
|
||||||
// Change length of list after 200 additions.
|
// Change length of list after 200 additions.
|
||||||
var l = [];
|
var l = [];
|
||||||
|
@ -127,7 +127,7 @@ void testConcurrentModification() {
|
||||||
}, (e) => e is ConcurrentModificationError, "cm2");
|
}, (e) => e is ConcurrentModificationError, "cm2");
|
||||||
}
|
}
|
||||||
|
|
||||||
// With EfficientLength interface (uses length).
|
// With EfficientLengthIterable interface (uses length).
|
||||||
{
|
{
|
||||||
// Change length of list after 20 additions.
|
// Change length of list after 20 additions.
|
||||||
var l = [];
|
var l = [];
|
||||||
|
|
16
tests/language/efficient_length_warning_test.dart
Normal file
16
tests/language/efficient_length_warning_test.dart
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file
|
||||||
|
// for details. All rights reserved. Use of this source code is governed by a
|
||||||
|
// BSD-style license that can be found in the LICENSE file.
|
||||||
|
// Third dart test program.
|
||||||
|
|
||||||
|
import "dart:math";
|
||||||
|
|
||||||
|
main() {
|
||||||
|
// This should no longer cause a warning because the least-upper-bound
|
||||||
|
// of List<int> and Set<int> is Object.
|
||||||
|
// The LUB is now EfficientLengthIterable and it extends Iterable.
|
||||||
|
var x = (new Random().nextBool() // Unpredictable condition.
|
||||||
|
? <int>[1]
|
||||||
|
: new Set<int>.from([1])).first;
|
||||||
|
if (x != 1) throw "Wat?";
|
||||||
|
}
|
Loading…
Reference in a new issue