-
Notifications
You must be signed in to change notification settings - Fork 87
Conversation
lib/src/wrappers.dart
Outdated
/// all elements stored in the returned are actually instance of [S], | ||
/// then the returned set can be used as a `MapKeySet<T>`. | ||
static MapKeySet<T> castFrom<S, T>(MapKeySet<S> source) { | ||
return new MapKeySet(source._baseMap.cast<T, dynamic>()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Too creative here. A MapKeySet
is just as Set
, so use Set.castFrom
and don't introduce a new castFrom
for this implementation of Set
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lib/src/wrappers.dart
Outdated
/// If all accessed elements of [source] are actually instances of [T] and if | ||
/// all elements stored in the returned are actually instance of [S], | ||
/// then the returned set can be used as a `MapKeySet<T>`. | ||
static MapValueSet<K2, V2> castFrom<K, V, K2, V2>(MapValueSet<K, V> source) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, this class is just an implementation of Set
, so just use Set.castFrom
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lib/src/queue_list.dart
Outdated
@@ -84,10 +102,10 @@ class QueueList<E> extends Object with ListMixin<E> implements Queue<E> { | |||
if (this is QueueList<T>) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
While you are here, please rewrite this as:
QueueList<Object> self = this;
return self is QueueList<T> ? self : this.retype<T>();
It generates better code for dart2js to not have an explicit cast. By up-casting first. we make sure that a successful test promotes the variable.
Ditto for the cast
methods below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
CHANGELOG.md
Outdated
|
||
* Added `QueueList.castFrom<S, T>` (similar to `List.castFrom`, `Queue.castFrom`). | ||
|
||
* Added `MapKeySet.castFrom<S, T>` (similar to `Set.castFrom`). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No need for the last two castFrom
's.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lib/src/wrappers.dart
Outdated
final Map<E, dynamic> _baseMap; | ||
|
||
MapKeySet(Map<E, dynamic> base) : _baseMap = base; | ||
|
||
Iterable<E> get _base => _baseMap.keys; | ||
|
||
Set<T> cast<T>() => _baseMap.keys.toSet().cast<T>(); | ||
MapKeySet<T> cast<T>() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just return Set<T>
and use Set.castFrom
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
lib/src/wrappers.dart
Outdated
@@ -513,7 +533,7 @@ class MapKeySet<E> extends _DelegatingIterableBase<E> | |||
E lookup(Object element) => | |||
throw new UnsupportedError("MapKeySet doesn't support lookup()."); | |||
|
|||
Set<T> retype<T>() => _baseMap.keys.toSet().retype<T>(); | |||
Set<T> retype<T>() => MapKeySet.castFrom<E, T>(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MapKeySet
-> Set
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
@@ -230,3 +248,17 @@ class QueueList<E> extends Object with ListMixin<E> implements Queue<E> { | |||
_head = 0; | |||
} | |||
} | |||
|
|||
class _CastQueueList<S, T> extends QueueList<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is creative. Tests, or it doesn't work. :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I was hoping to extend ThingImAddingRetypeTo
as well 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Take a look - tests are basic.
test/queue_list_test.dart
Outdated
expect( | ||
() => numQueue.add(1), | ||
throwsCastError, | ||
skip: isDart2 ? false : 'In checked mode (VM), CastError is not thrown', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The real reason is that cast
only works in Dart 2 because it depends on the type parameter of a generic method. It's not VM specific in any way.
(In checked mode, the add(1)
would throw because you are adding an int
to a QueueList<String>
, but it's more likely to be a TypeError
than a CastError
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Done!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like the type thrown is CastErrorImplementation
, which is not a TypeError
.
lib/src/queue_list.dart
Outdated
} | ||
return QueueList.castFrom<E, T>(this); | ||
return retype<T>(); | ||
} | ||
|
||
QueueList<T> retype<T>() => QueueList.castFrom<E, T>(this); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
TBH, after some more consideration, I'd remove QueueList.castFrom
again.
It's a very specific implementation class, not a general interface that others might implement, so you don't need to make the wrapping available to to others.
The reason for Iterable.castFrom
is that it can be used to implement Iterable.cast
for other classes that implement Iterable
, but nobody should implement QueueList
, they should just implement Queue
and List
if they want a class that is both.
So, consider making castFrom
private or just inline it here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Made it private. Thanks!
test/queue_list_test.dart
Outdated
@@ -258,6 +258,25 @@ void main() { | |||
expect(queue.cast<Pattern>(), same(queue)); | |||
}, skip: isDart2 ? false : 'Requires a Dart2 runtime'); | |||
|
|||
test("cast does not throw on mutation when the type is valid", () { | |||
var patternQueue = new QueueList<Pattern>()..addAll(['a', 'b']); | |||
QueueList<Object> untypedQueue = patternQueue; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this line? Changing the static type has no effect on cast
, you can just write patternQueue.cast<String>()
below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
test/queue_list_test.dart
Outdated
var patternQueue = new QueueList<Pattern>()..addAll(['a', 'b']); | ||
QueueList<Object> untypedQueue = patternQueue; | ||
var stringQueue = untypedQueue.cast<String>(); | ||
stringQueue.addAll(['c', 'd']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you forgot to do the cast
, the test would still succeed (either because it infers <Pattern>['c', 'd']
, or because List<String>
is-a List<Pattern>
).
At least add expect(stringQueue is List<String>, true);
, which shows that the cast
actually did something (and skip in non-dart2 mode because there cast
actually doesn't do anything).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
test/queue_list_test.dart
Outdated
var stringQueue = untypedQueue.cast<String>(); | ||
stringQueue.addAll(['c', 'd']); | ||
|
||
expect(stringQueue, ['a', 'b', 'c', 'd']); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check that patternQueue
was also modified.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM if you fix the type that you check against.
test/queue_list_test.dart
Outdated
stringQueue.addAll(['c', 'd']); | ||
expect( | ||
stringQueue, | ||
const isInstanceOf<QueueList<Pattern>>(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Check for QueueList<String>
here. That's the type you are casting to, and a type that patternQueue
doesn't have, so it checks that something did happen.
(You could throw in a check that stringQueue
and patternQueue
are not identical, but it's not important after checking that stringQueue
has a type that patternQueue
doesn't).
This is the expect
that needs the skip
parameter, because in Dart 1 mode, the type check won't be true since cast
returns patternQueue
unmodified. The two tests below will still succeed when stringQueue
and patternQueue
are the same object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Thanks @lrhn!
* Fix cast and retype implementations. * Fix and add a few tests. * Address feedbakc.
Closes dart-lang/core#590.
I had to be a little creative for
QueueList
. The others seem OK enough.