mirror of
https://github.com/dart-lang/sdk
synced 2024-10-14 12:30:03 +00:00
Hide the existence of EfficientLengthIterable
better.
The `EfficientLengthIterable` is an internal marker interface that allows the SDK to more efficiently check, effectively, `v is List || v is Set || v is Queue`, and some other known internal types, which allows it to assume that `.length` is efficient and doesn't iterate the iterable. It's not intended for external use, but the current design both has the name mentioned specifically in the declaration of the public types `List`, `Set` and `Queue`, and possibly allows the type to leak through the least-upper-bound algorithm. This change moves the mention of `EfficientLengthIterable` from the public types to an anonymously named private type, and ensures that the private type is never the result of a least-upper-bound computation, by adding another interface with the same depth that all the public types implementing `EfficientLengthIterable` also implement. (A longer term solution to `EfficientLengthIterable` looking like it's a public name could be combining the collection- related code from `dart:collection`, `dart:core` and `dart:_internal` into a single `dart:_collection_impl`, and exporting the relevant types from there. Then we could make the interface be `_EfficientLengthIterable` again.) Change-Id: I717743f0ca253782162be0ad9ff05036fdf57159 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322320 Reviewed-by: Nate Bosch <nbosch@google.com> Reviewed-by: Slava Egorov <vegorov@google.com> Reviewed-by: Aske Simon Christensen <askesc@google.com> Reviewed-by: Stephen Adams <sra@google.com> Commit-Queue: Lasse Nielsen <lrn@google.com>
This commit is contained in:
parent
f7090efca0
commit
c15f054809
|
@ -9,7 +9,6 @@ library /*isLegacy*/;
|
|||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
static method useAddAll() → void {
|
||||
dynamic dynamicSet1 = block {
|
||||
|
@ -327,8 +326,8 @@ static method main() → dynamic {
|
|||
self::useAddAll();
|
||||
}
|
||||
static method expect(core::Set<dynamic>* set1, core::Set<dynamic>* set2) → void {
|
||||
if(!(set1.{_in::EfficientLengthIterable::length}{core::int*} =={core::num::==}{(core::Object*) →* core::bool*} set2.{_in::EfficientLengthIterable::length}{core::int*})) {
|
||||
throw "Unexpected length. Expected ${set1.{_in::EfficientLengthIterable::length}{core::int*}}, actual ${set2.{_in::EfficientLengthIterable::length}{core::int*}}.";
|
||||
if(!(set1.{core::Iterable::length}{core::int*} =={core::num::==}{(core::Object*) →* core::bool*} set2.{core::Iterable::length}{core::int*})) {
|
||||
throw "Unexpected length. Expected ${set1.{core::Iterable::length}{core::int*}}, actual ${set2.{core::Iterable::length}{core::int*}}.";
|
||||
}
|
||||
for (dynamic element in set1) {
|
||||
if(!set2.{core::Set::contains}(element){(core::Object*) →* core::bool*}) {
|
||||
|
|
|
@ -9,7 +9,6 @@ library /*isLegacy*/;
|
|||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
static method useAddAll() → void {
|
||||
dynamic dynamicSet1 = block {
|
||||
|
@ -481,8 +480,8 @@ static method main() → dynamic {
|
|||
self::useAddAll();
|
||||
}
|
||||
static method expect(core::Set<dynamic>* set1, core::Set<dynamic>* set2) → void {
|
||||
if(!(set1.{_in::EfficientLengthIterable::length}{core::int*} =={core::num::==}{(core::Object*) →* core::bool*} set2.{_in::EfficientLengthIterable::length}{core::int*})) {
|
||||
throw "Unexpected length. Expected ${set1.{_in::EfficientLengthIterable::length}{core::int*}}, actual ${set2.{_in::EfficientLengthIterable::length}{core::int*}}.";
|
||||
if(!(set1.{core::Iterable::length}{core::int*} =={core::num::==}{(core::Object*) →* core::bool*} set2.{core::Iterable::length}{core::int*})) {
|
||||
throw "Unexpected length. Expected ${set1.{core::Iterable::length}{core::int*}}, actual ${set2.{core::Iterable::length}{core::int*}}.";
|
||||
}
|
||||
{
|
||||
synthesized core::Iterator<dynamic>* :sync-for-iterator = set1.{core::Iterable::iterator}{core::Iterator<dynamic>*};
|
||||
|
|
|
@ -2,7 +2,6 @@ library /*isLegacy*/;
|
|||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
static method useAddAll() → void {
|
||||
dynamic dynamicSet1 = block {
|
||||
|
@ -320,8 +319,8 @@ static method main() → dynamic {
|
|||
self::useAddAll();
|
||||
}
|
||||
static method expect(core::Set<dynamic>* set1, core::Set<dynamic>* set2) → void {
|
||||
if(!(set1.{_in::EfficientLengthIterable::length}{core::int*} =={core::num::==}{(core::Object*) →* core::bool*} set2.{_in::EfficientLengthIterable::length}{core::int*})) {
|
||||
throw "Unexpected length. Expected ${set1.{_in::EfficientLengthIterable::length}{core::int*}}, actual ${set2.{_in::EfficientLengthIterable::length}{core::int*}}.";
|
||||
if(!(set1.{core::Iterable::length}{core::int*} =={core::num::==}{(core::Object*) →* core::bool*} set2.{core::Iterable::length}{core::int*})) {
|
||||
throw "Unexpected length. Expected ${set1.{core::Iterable::length}{core::int*}}, actual ${set2.{core::Iterable::length}{core::int*}}.";
|
||||
}
|
||||
for (dynamic element in set1) {
|
||||
if(!set2.{core::Set::contains}(element){(core::Object*) →* core::bool*}) {
|
||||
|
|
|
@ -2,7 +2,6 @@ library /*isLegacy*/;
|
|||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
static method useAddAll() → void {
|
||||
dynamic dynamicSet1 = block {
|
||||
|
@ -320,8 +319,8 @@ static method main() → dynamic {
|
|||
self::useAddAll();
|
||||
}
|
||||
static method expect(core::Set<dynamic>* set1, core::Set<dynamic>* set2) → void {
|
||||
if(!(set1.{_in::EfficientLengthIterable::length}{core::int*} =={core::num::==}{(core::Object*) →* core::bool*} set2.{_in::EfficientLengthIterable::length}{core::int*})) {
|
||||
throw "Unexpected length. Expected ${set1.{_in::EfficientLengthIterable::length}{core::int*}}, actual ${set2.{_in::EfficientLengthIterable::length}{core::int*}}.";
|
||||
if(!(set1.{core::Iterable::length}{core::int*} =={core::num::==}{(core::Object*) →* core::bool*} set2.{core::Iterable::length}{core::int*})) {
|
||||
throw "Unexpected length. Expected ${set1.{core::Iterable::length}{core::int*}}, actual ${set2.{core::Iterable::length}{core::int*}}.";
|
||||
}
|
||||
for (dynamic element in set1) {
|
||||
if(!set2.{core::Set::contains}(element){(core::Object*) →* core::bool*}) {
|
||||
|
|
|
@ -2,7 +2,6 @@ library /*isLegacy*/;
|
|||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
static method useAddAll() → void {
|
||||
dynamic dynamicSet1 = block {
|
||||
|
@ -474,8 +473,8 @@ static method main() → dynamic {
|
|||
self::useAddAll();
|
||||
}
|
||||
static method expect(core::Set<dynamic>* set1, core::Set<dynamic>* set2) → void {
|
||||
if(!(set1.{_in::EfficientLengthIterable::length}{core::int*} =={core::num::==}{(core::Object*) →* core::bool*} set2.{_in::EfficientLengthIterable::length}{core::int*})) {
|
||||
throw "Unexpected length. Expected ${set1.{_in::EfficientLengthIterable::length}{core::int*}}, actual ${set2.{_in::EfficientLengthIterable::length}{core::int*}}.";
|
||||
if(!(set1.{core::Iterable::length}{core::int*} =={core::num::==}{(core::Object*) →* core::bool*} set2.{core::Iterable::length}{core::int*})) {
|
||||
throw "Unexpected length. Expected ${set1.{core::Iterable::length}{core::int*}}, actual ${set2.{core::Iterable::length}{core::int*}}.";
|
||||
}
|
||||
{
|
||||
synthesized core::Iterator<dynamic>* :sync-for-iterator = set1.{core::Iterable::iterator}{core::Iterator<dynamic>*};
|
||||
|
|
|
@ -2,7 +2,6 @@ library;
|
|||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
static method useAddAll() → void {
|
||||
dynamic dynamicSet1 = block {
|
||||
|
@ -257,8 +256,8 @@ static method main() → dynamic {
|
|||
self::useAddAllNullable();
|
||||
}
|
||||
static method expect(core::Set<dynamic> set1, core::Set<dynamic> set2) → void {
|
||||
if(!(set1.{_in::EfficientLengthIterable::length}{core::int} =={core::num::==}{(core::Object) → core::bool} set2.{_in::EfficientLengthIterable::length}{core::int})) {
|
||||
throw "Unexpected length. Expected ${set1.{_in::EfficientLengthIterable::length}{core::int}}, actual ${set2.{_in::EfficientLengthIterable::length}{core::int}}.";
|
||||
if(!(set1.{core::Iterable::length}{core::int} =={core::num::==}{(core::Object) → core::bool} set2.{core::Iterable::length}{core::int})) {
|
||||
throw "Unexpected length. Expected ${set1.{core::Iterable::length}{core::int}}, actual ${set2.{core::Iterable::length}{core::int}}.";
|
||||
}
|
||||
for (dynamic element in set1) {
|
||||
if(!set2.{core::Set::contains}(element){(core::Object?) → core::bool}) {
|
||||
|
|
|
@ -2,7 +2,6 @@ library;
|
|||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
static method useAddAll() → void {
|
||||
dynamic dynamicSet1 = block {
|
||||
|
@ -356,8 +355,8 @@ static method main() → dynamic {
|
|||
self::useAddAllNullable();
|
||||
}
|
||||
static method expect(core::Set<dynamic> set1, core::Set<dynamic> set2) → void {
|
||||
if(!(set1.{_in::EfficientLengthIterable::length}{core::int} =={core::num::==}{(core::Object) → core::bool} set2.{_in::EfficientLengthIterable::length}{core::int})) {
|
||||
throw "Unexpected length. Expected ${set1.{_in::EfficientLengthIterable::length}{core::int}}, actual ${set2.{_in::EfficientLengthIterable::length}{core::int}}.";
|
||||
if(!(set1.{core::Iterable::length}{core::int} =={core::num::==}{(core::Object) → core::bool} set2.{core::Iterable::length}{core::int})) {
|
||||
throw "Unexpected length. Expected ${set1.{core::Iterable::length}{core::int}}, actual ${set2.{core::Iterable::length}{core::int}}.";
|
||||
}
|
||||
{
|
||||
synthesized core::Iterator<dynamic> :sync-for-iterator = set1.{core::Iterable::iterator}{core::Iterator<dynamic>};
|
||||
|
|
|
@ -2,7 +2,6 @@ library;
|
|||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
static method useAddAll() → void {
|
||||
dynamic dynamicSet1 = block {
|
||||
|
@ -257,8 +256,8 @@ static method main() → dynamic {
|
|||
self::useAddAllNullable();
|
||||
}
|
||||
static method expect(core::Set<dynamic> set1, core::Set<dynamic> set2) → void {
|
||||
if(!(set1.{_in::EfficientLengthIterable::length}{core::int} =={core::num::==}{(core::Object) → core::bool} set2.{_in::EfficientLengthIterable::length}{core::int})) {
|
||||
throw "Unexpected length. Expected ${set1.{_in::EfficientLengthIterable::length}{core::int}}, actual ${set2.{_in::EfficientLengthIterable::length}{core::int}}.";
|
||||
if(!(set1.{core::Iterable::length}{core::int} =={core::num::==}{(core::Object) → core::bool} set2.{core::Iterable::length}{core::int})) {
|
||||
throw "Unexpected length. Expected ${set1.{core::Iterable::length}{core::int}}, actual ${set2.{core::Iterable::length}{core::int}}.";
|
||||
}
|
||||
for (dynamic element in set1) {
|
||||
if(!set2.{core::Set::contains}(element){(core::Object?) → core::bool}) {
|
||||
|
|
|
@ -2,7 +2,6 @@ library;
|
|||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
static method useAddAll() → void {
|
||||
dynamic dynamicSet1 = block {
|
||||
|
@ -257,8 +256,8 @@ static method main() → dynamic {
|
|||
self::useAddAllNullable();
|
||||
}
|
||||
static method expect(core::Set<dynamic> set1, core::Set<dynamic> set2) → void {
|
||||
if(!(set1.{_in::EfficientLengthIterable::length}{core::int} =={core::num::==}{(core::Object) → core::bool} set2.{_in::EfficientLengthIterable::length}{core::int})) {
|
||||
throw "Unexpected length. Expected ${set1.{_in::EfficientLengthIterable::length}{core::int}}, actual ${set2.{_in::EfficientLengthIterable::length}{core::int}}.";
|
||||
if(!(set1.{core::Iterable::length}{core::int} =={core::num::==}{(core::Object) → core::bool} set2.{core::Iterable::length}{core::int})) {
|
||||
throw "Unexpected length. Expected ${set1.{core::Iterable::length}{core::int}}, actual ${set2.{core::Iterable::length}{core::int}}.";
|
||||
}
|
||||
for (dynamic element in set1) {
|
||||
if(!set2.{core::Set::contains}(element){(core::Object?) → core::bool}) {
|
||||
|
|
|
@ -2,7 +2,6 @@ library;
|
|||
import self as self;
|
||||
import "dart:core" as core;
|
||||
import "dart:collection" as col;
|
||||
import "dart:_internal" as _in;
|
||||
|
||||
static method useAddAll() → void {
|
||||
dynamic dynamicSet1 = block {
|
||||
|
@ -356,8 +355,8 @@ static method main() → dynamic {
|
|||
self::useAddAllNullable();
|
||||
}
|
||||
static method expect(core::Set<dynamic> set1, core::Set<dynamic> set2) → void {
|
||||
if(!(set1.{_in::EfficientLengthIterable::length}{core::int} =={core::num::==}{(core::Object) → core::bool} set2.{_in::EfficientLengthIterable::length}{core::int})) {
|
||||
throw "Unexpected length. Expected ${set1.{_in::EfficientLengthIterable::length}{core::int}}, actual ${set2.{_in::EfficientLengthIterable::length}{core::int}}.";
|
||||
if(!(set1.{core::Iterable::length}{core::int} =={core::num::==}{(core::Object) → core::bool} set2.{core::Iterable::length}{core::int})) {
|
||||
throw "Unexpected length. Expected ${set1.{core::Iterable::length}{core::int}}, actual ${set2.{core::Iterable::length}{core::int}}.";
|
||||
}
|
||||
{
|
||||
synthesized core::Iterator<dynamic> :sync-for-iterator = set1.{core::Iterable::iterator}{core::Iterator<dynamic>};
|
||||
|
|
|
@ -95,7 +95,8 @@ base class IdentityMap<K, V> extends InternalMap<K, V> {
|
|||
}
|
||||
}
|
||||
|
||||
class _JSMapIterable<E> extends EfficientLengthIterable<E> {
|
||||
class _JSMapIterable<E> extends EfficientLengthIterable<E>
|
||||
implements HideEfficientLengthIterable<E> {
|
||||
final InternalMap _map;
|
||||
@notNull
|
||||
final bool _isKeys;
|
||||
|
|
|
@ -13,6 +13,7 @@ import 'dart:_interceptors';
|
|||
import 'dart:_internal'
|
||||
show
|
||||
EfficientLengthIterable,
|
||||
HideEfficientLengthIterable,
|
||||
MappedIterable,
|
||||
IterableElementError,
|
||||
SubListIterable,
|
||||
|
|
|
@ -443,7 +443,8 @@ base class _CustomHashMap<K, V> extends _HashMap<K, V> {
|
|||
}
|
||||
}
|
||||
|
||||
class _HashMapKeyIterable<E> extends EfficientLengthIterable<E> {
|
||||
class _HashMapKeyIterable<E> extends EfficientLengthIterable<E>
|
||||
implements HideEfficientLengthIterable<E> {
|
||||
final _HashMap _map;
|
||||
_HashMapKeyIterable(this._map);
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ import 'dart:_internal'
|
|||
show
|
||||
checkNotNullable,
|
||||
EfficientLengthIterable,
|
||||
HideEfficientLengthIterable,
|
||||
MappedIterable,
|
||||
IterableElementError,
|
||||
SubListIterable;
|
||||
|
|
|
@ -339,7 +339,8 @@ class LinkedHashMapCell {
|
|||
LinkedHashMapCell(this.hashMapCellKey, this.hashMapCellValue);
|
||||
}
|
||||
|
||||
class LinkedHashMapKeyIterable<E> extends EfficientLengthIterable<E> {
|
||||
class LinkedHashMapKeyIterable<E> extends EfficientLengthIterable<E>
|
||||
implements HideEfficientLengthIterable<E> {
|
||||
final JsLinkedHashMap _map;
|
||||
LinkedHashMapKeyIterable(this._map);
|
||||
|
||||
|
|
|
@ -125,7 +125,8 @@ class JSArrayIteratorAdapter<T> implements Iterator<T> {
|
|||
|
||||
/// [JSArrayIterableAdapter] lazily adapts a [JSArray] to Dart's [Iterable]
|
||||
/// interface.
|
||||
class JSArrayIterableAdapter<T> extends EfficientLengthIterable<T> {
|
||||
class JSArrayIterableAdapter<T> extends EfficientLengthIterable<T>
|
||||
implements HideEfficientLengthIterable<T> {
|
||||
final JSArray array;
|
||||
|
||||
JSArrayIterableAdapter(this.array);
|
||||
|
|
|
@ -224,7 +224,8 @@ abstract class UnmodifiableMapBase<K, V> = MapBase<K, V>
|
|||
/// Iterable that iterates over the values of a `Map`.
|
||||
/// It accesses the values by iterating over the keys of the map, and using the
|
||||
/// map's `operator[]` to lookup the keys.
|
||||
class _MapBaseValueIterable<K, V> extends EfficientLengthIterable<V> {
|
||||
class _MapBaseValueIterable<K, V> extends EfficientLengthIterable<V>
|
||||
implements HideEfficientLengthIterable<V> {
|
||||
final Map<K, V> _map;
|
||||
_MapBaseValueIterable(this._map);
|
||||
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
|
||||
part of dart.collection;
|
||||
|
||||
/// Helper interface to hide [EfficientLengthIterable] from the public
|
||||
/// declaration of [Queue].
|
||||
abstract class _QueueIterable<E>
|
||||
implements EfficientLengthIterable<E>, HideEfficientLengthIterable<E> {}
|
||||
|
||||
/// A [Queue] is a collection that can be manipulated at both ends. One
|
||||
/// can iterate over the elements of a queue through [forEach] or with
|
||||
/// an [Iterator].
|
||||
|
@ -32,7 +37,7 @@ part of dart.collection;
|
|||
/// queue.removeLast();
|
||||
/// print(queue); // {1, 2, 3}
|
||||
/// ```
|
||||
abstract interface class Queue<E> implements EfficientLengthIterable<E> {
|
||||
abstract interface class Queue<E> implements Iterable<E>, _QueueIterable<E> {
|
||||
/// Creates a queue.
|
||||
factory Queue() = ListQueue<E>;
|
||||
|
||||
|
|
|
@ -784,7 +784,8 @@ abstract class _SplayTreeIterator<K, Node extends _SplayTreeNode<K, Node>, T>
|
|||
}
|
||||
|
||||
class _SplayTreeKeyIterable<K, Node extends _SplayTreeNode<K, Node>>
|
||||
extends EfficientLengthIterable<K> {
|
||||
extends EfficientLengthIterable<K>
|
||||
implements HideEfficientLengthIterable<K> {
|
||||
_SplayTree<K, Node> _tree;
|
||||
_SplayTreeKeyIterable(this._tree);
|
||||
int get length => _tree._count;
|
||||
|
@ -801,7 +802,8 @@ class _SplayTreeKeyIterable<K, Node extends _SplayTreeNode<K, Node>>
|
|||
}
|
||||
}
|
||||
|
||||
class _SplayTreeValueIterable<K, V> extends EfficientLengthIterable<V> {
|
||||
class _SplayTreeValueIterable<K, V> extends EfficientLengthIterable<V>
|
||||
implements HideEfficientLengthIterable<V> {
|
||||
SplayTreeMap<K, V> _map;
|
||||
_SplayTreeValueIterable(this._map);
|
||||
int get length => _map._count;
|
||||
|
@ -810,7 +812,8 @@ class _SplayTreeValueIterable<K, V> extends EfficientLengthIterable<V> {
|
|||
}
|
||||
|
||||
class _SplayTreeMapEntryIterable<K, V>
|
||||
extends EfficientLengthIterable<MapEntry<K, V>> {
|
||||
extends EfficientLengthIterable<MapEntry<K, V>>
|
||||
implements HideEfficientLengthIterable<MapEntry<K, V>> {
|
||||
SplayTreeMap<K, V> _map;
|
||||
_SplayTreeMapEntryIterable(this._map);
|
||||
int get length => _map._count;
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
|
||||
part of dart.core;
|
||||
|
||||
/// Helper interface to hide [EfficientLengthIterable] from the public
|
||||
/// declaration of [List].
|
||||
abstract class _ListIterable<E>
|
||||
implements EfficientLengthIterable<E>, HideEfficientLengthIterable<E> {}
|
||||
|
||||
/// An indexable collection of objects with a length.
|
||||
///
|
||||
/// Subclasses of this class implement different kinds of lists.
|
||||
|
@ -112,7 +117,7 @@ part of dart.core;
|
|||
/// Changing the list's length while it is being iterated, either by iterating it
|
||||
/// directly or through iterating an [Iterable] that is backed by the list, will
|
||||
/// break the iteration.
|
||||
abstract interface class List<E> implements EfficientLengthIterable<E> {
|
||||
abstract interface class List<E> implements Iterable<E>, _ListIterable<E> {
|
||||
/// Creates a list of the given length with [fill] at each position.
|
||||
///
|
||||
/// The [length] must be a non-negative integer.
|
||||
|
|
|
@ -4,6 +4,11 @@
|
|||
|
||||
part of dart.core;
|
||||
|
||||
/// Helper interface to hide [EfficientLengthIterable] from the public
|
||||
/// declaration of [Set].
|
||||
abstract class _SetIterable<E>
|
||||
implements EfficientLengthIterable<E>, HideEfficientLengthIterable<E> {}
|
||||
|
||||
/// A collection of objects in which each object can occur only once.
|
||||
///
|
||||
/// That is, for each object of the element type, the object is either considered
|
||||
|
@ -33,7 +38,7 @@ part of dart.core;
|
|||
/// It is generally not allowed to modify the equality of elements (and thus not
|
||||
/// their hashcode) while they are in the set. Some specialized subtypes may be
|
||||
/// more permissive, in which case they should document this behavior.
|
||||
abstract interface class Set<E> extends EfficientLengthIterable<E> {
|
||||
abstract interface class Set<E> implements Iterable<E>, _SetIterable<E> {
|
||||
/// Creates an empty [Set].
|
||||
///
|
||||
/// The created [Set] is a plain [LinkedHashSet].
|
||||
|
|
|
@ -78,7 +78,7 @@ class CastIterable<S, T> extends _CastIterableBase<S, T> {
|
|||
}
|
||||
|
||||
class _EfficientLengthCastIterable<S, T> extends CastIterable<S, T>
|
||||
implements EfficientLengthIterable<T> {
|
||||
implements EfficientLengthIterable<T>, HideEfficientLengthIterable<T> {
|
||||
_EfficientLengthCastIterable(EfficientLengthIterable<S> source)
|
||||
: super._(source);
|
||||
}
|
||||
|
|
|
@ -19,13 +19,23 @@ abstract class EfficientLengthIterable<T> extends Iterable<T> {
|
|||
int get length;
|
||||
}
|
||||
|
||||
/// An interface which hides [EfficientLengthIterable] from upper bounds.
|
||||
///
|
||||
/// Every type which implements [EfficientLengthIterable] also implements
|
||||
/// this interface, and they have the same *depth*, so it's impossible
|
||||
/// for the upper-bound algorithm to get [EfficientLengthIterable]
|
||||
/// as the result.
|
||||
abstract interface class HideEfficientLengthIterable<T>
|
||||
implements Iterable<T> {}
|
||||
|
||||
/**
|
||||
* An [Iterable] for classes that have efficient [length] and [elementAt].
|
||||
*
|
||||
* All other methods are implemented in terms of [length] and [elementAt],
|
||||
* including [iterator].
|
||||
*/
|
||||
abstract class ListIterable<E> extends EfficientLengthIterable<E> {
|
||||
abstract class ListIterable<E> extends EfficientLengthIterable<E>
|
||||
implements HideEfficientLengthIterable<E> {
|
||||
int get length;
|
||||
E elementAt(int i);
|
||||
|
||||
|
@ -376,7 +386,7 @@ class MappedIterable<S, T> extends Iterable<T> {
|
|||
}
|
||||
|
||||
class EfficientLengthMappedIterable<S, T> extends MappedIterable<S, T>
|
||||
implements EfficientLengthIterable<T> {
|
||||
implements EfficientLengthIterable<T>, HideEfficientLengthIterable<T> {
|
||||
EfficientLengthMappedIterable(Iterable<S> iterable, T function(S value))
|
||||
: super._(iterable, function);
|
||||
}
|
||||
|
@ -511,7 +521,7 @@ class TakeIterable<E> extends Iterable<E> {
|
|||
}
|
||||
|
||||
class EfficientLengthTakeIterable<E> extends TakeIterable<E>
|
||||
implements EfficientLengthIterable<E> {
|
||||
implements EfficientLengthIterable<E>, HideEfficientLengthIterable<E> {
|
||||
EfficientLengthTakeIterable(Iterable<E> iterable, int takeCount)
|
||||
: super._(iterable, takeCount);
|
||||
|
||||
|
@ -605,7 +615,7 @@ class SkipIterable<E> extends Iterable<E> {
|
|||
}
|
||||
|
||||
class EfficientLengthSkipIterable<E> extends SkipIterable<E>
|
||||
implements EfficientLengthIterable<E> {
|
||||
implements EfficientLengthIterable<E>, HideEfficientLengthIterable<E> {
|
||||
factory EfficientLengthSkipIterable(Iterable<E> iterable, int count) {
|
||||
return EfficientLengthSkipIterable<E>._(iterable, _checkCount(count));
|
||||
}
|
||||
|
@ -682,7 +692,8 @@ class SkipWhileIterator<E> implements Iterator<E> {
|
|||
/**
|
||||
* The always empty [Iterable].
|
||||
*/
|
||||
class EmptyIterable<E> extends EfficientLengthIterable<E> {
|
||||
class EmptyIterable<E> extends EfficientLengthIterable<E>
|
||||
implements HideEfficientLengthIterable<E> {
|
||||
const EmptyIterable();
|
||||
|
||||
Iterator<E> get iterator => const EmptyIterator<Never>();
|
||||
|
@ -816,7 +827,7 @@ class FollowedByIterable<E> extends Iterable<E> {
|
|||
}
|
||||
|
||||
class EfficientLengthFollowedByIterable<E> extends FollowedByIterable<E>
|
||||
implements EfficientLengthIterable<E> {
|
||||
implements EfficientLengthIterable<E>, HideEfficientLengthIterable<E> {
|
||||
EfficientLengthFollowedByIterable(
|
||||
EfficientLengthIterable<E> first, EfficientLengthIterable<E> second)
|
||||
: super(first, second);
|
||||
|
@ -978,7 +989,9 @@ class IndexedIterable<T> extends Iterable<(int, T)> {
|
|||
}
|
||||
|
||||
class EfficientLengthIndexedIterable<T> extends IndexedIterable<T>
|
||||
implements EfficientLengthIterable<(int, T)> {
|
||||
implements
|
||||
EfficientLengthIterable<(int, T)>,
|
||||
HideEfficientLengthIterable<(int, T)> {
|
||||
EfficientLengthIndexedIterable(super._source, super._start) : super._();
|
||||
|
||||
(int, T) get last {
|
||||
|
|
Loading…
Reference in a new issue