Add .cast, .retype across the package. (#82)

* Add .cast, .retype across the package.

* Oops!

* Enable tests.

* Fix tests.

* Remove TODOs.

* More TODO fixing.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4f14f32..ca7f933 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,7 @@
 
 * Only the Dart 2 dev SDK (`>=2.0.0-dev.22.0`) is now supported.
 * Add support for `Map.{addEntries|entries}` for Dart 2.0.
+* Add support for `Iterable|List|Map|Set|Queue.{cast|retype}` for Dart 2.0.
 
 ## 1.14.6
 
diff --git a/lib/src/canonicalized_map.dart b/lib/src/canonicalized_map.dart
index e586420..e431116 100644
--- a/lib/src/canonicalized_map.dart
+++ b/lib/src/canonicalized_map.dart
@@ -73,9 +73,7 @@
       _base.addEntries(entries.map(
           (e) => new MapEntry(_canonicalize(e.key), new Pair(e.key, e.value))));
 
-  Map<K2, V2> cast<K2, V2>() {
-    throw new UnimplementedError('cast');
-  }
+  Map<K2, V2> cast<K2, V2>() => _base.cast<K2, V2>();
 
   void clear() {
     _base.clear();
@@ -128,10 +126,7 @@
     throw new UnimplementedError('removeWhere');
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Map<K2, V2> retype<K2, V2>() {
-    throw new UnimplementedError('retype');
-  }
+  Map<K2, V2> retype<K2, V2>() => _base.retype<K2, V2>();
 
   // TODO: Dart 2.0 requires this method to be implemented.
   V update(K key, V update(V value), {V ifAbsent()}) {
diff --git a/lib/src/queue_list.dart b/lib/src/queue_list.dart
index 224ac86..cab687a 100644
--- a/lib/src/queue_list.dart
+++ b/lib/src/queue_list.dart
@@ -80,15 +80,14 @@
     }
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
   QueueList<T> cast<T>() {
-    throw new UnimplementedError('cast');
+    if (this is QueueList<T>) {
+      return this as QueueList<T>;
+    }
+    return new QueueList<T>.from(_table.cast<T>());
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  QueueList<T> retype<T>() {
-    throw new UnimplementedError('retype');
-  }
+  QueueList<T> retype<T>() => new QueueList<T>.from(_table.retype<T>());
 
   String toString() => IterableBase.iterableToFullString(this, "{", "}");
 
diff --git a/lib/src/typed_wrappers.dart b/lib/src/typed_wrappers.dart
index f713d0b..08d17e2 100644
--- a/lib/src/typed_wrappers.dart
+++ b/lib/src/typed_wrappers.dart
@@ -21,10 +21,7 @@
 
   bool any(bool test(E element)) => _base.any(_validate(test));
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Iterable<T> cast<T>() {
-    throw new UnimplementedError('cast');
-  }
+  Iterable<T> cast<T>() => new TypeSafeIterable<T>(_base.cast<T>());
 
   bool contains(Object element) => _base.contains(element);
 
@@ -70,10 +67,7 @@
   E reduce(E combine(E value, E element)) =>
       _base.reduce((value, element) => combine(value as E, element as E)) as E;
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Iterable<T> retype<T>() {
-    throw new UnimplementedError('retype');
-  }
+  Iterable<T> retype<T>() => new TypeSafeIterable<T>(_base.retype<T>());
 
   E get single => _base.single as E;
 
@@ -153,10 +147,7 @@
 
   Map<int, E> asMap() => new TypeSafeMap<int, E>(_listBase.asMap());
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  List<T> cast<T>() {
-    throw new UnimplementedError('cast');
-  }
+  List<T> cast<T>() => new TypeSafeList<T>(_listBase.cast<T>());
 
   void clear() {
     _listBase.clear();
@@ -230,10 +221,7 @@
     _listBase.retainWhere(_validate(test));
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  List<T> retype<T>() {
-    throw new UnimplementedError('retype');
-  }
+  List<T> retype<T>() => new TypeSafeList<T>(_listBase.retype<T>());
 
   Iterable<E> get reversed => new TypeSafeIterable<E>(_listBase.reversed);
 
@@ -276,10 +264,7 @@
     _setBase.addAll(elements);
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Set<T> cast<T>() {
-    throw new UnimplementedError('cast');
-  }
+  Set<T> cast<T>() => new TypeSafeSet<T>(_setBase.cast<T>());
 
   void clear() {
     _setBase.clear();
@@ -313,10 +298,7 @@
     _setBase.retainWhere(_validate(test));
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Set<T> retype<T>() {
-    throw new UnimplementedError('retype');
-  }
+  Set<T> retype<T>() => new TypeSafeSet<T>(_setBase.retype<T>());
 
   Set<E> union(Set<E> other) => new TypeSafeSet<E>(_setBase.union(other));
 }
@@ -347,10 +329,7 @@
     _baseQueue.addLast(value);
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Queue<T> cast<T>() {
-    throw new UnimplementedError('cast');
-  }
+  Queue<T> cast<T>() => new TypeSafeQueue<T>(_baseQueue.cast<T>());
 
   void clear() {
     _baseQueue.clear();
@@ -366,10 +345,7 @@
     _baseQueue.retainWhere(_validate(test));
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Queue<T> retype<T>() {
-    throw new UnimplementedError('retype');
-  }
+  Queue<T> retype<T>() => new TypeSafeQueue<T>(_baseQueue.retype<T>());
 
   E removeFirst() => _baseQueue.removeFirst() as E;
 
@@ -399,10 +375,7 @@
     _base.addEntries(entries);
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Map<K2, V2> cast<K2, V2>() {
-    throw new UnimplementedError('cast');
-  }
+  Map<K2, V2> cast<K2, V2>() => new TypeSafeMap<K2, V2>(_base.cast<K2, V2>());
 
   void clear() {
     _base.clear();
@@ -442,10 +415,8 @@
     throw new UnimplementedError('removeWhere');
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Map<K2, V2> retype<K2, V2>() {
-    throw new UnimplementedError('retype');
-  }
+  Map<K2, V2> retype<K2, V2>() =>
+      new TypeSafeMap<K2, V2>(_base.retype<K2, V2>());
 
   Iterable<V> get values => new TypeSafeIterable<V>(_base.values);
 
diff --git a/lib/src/wrappers.dart b/lib/src/wrappers.dart
index cef99b7..d18b273 100644
--- a/lib/src/wrappers.dart
+++ b/lib/src/wrappers.dart
@@ -22,9 +22,7 @@
   bool any(bool test(E element)) => _base.any(test);
 
   // TODO: Dart 2.0 requires this method to be implemented.
-  Iterable<T> cast<T>() {
-    throw new UnimplementedError('cast');
-  }
+  Iterable<T> cast<T>() => _base.cast<T>();
 
   bool contains(Object element) => _base.contains(element);
 
@@ -68,10 +66,7 @@
 
   E reduce(E combine(E value, E element)) => _base.reduce(combine);
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Iterable<T> retype<T>() {
-    throw new UnimplementedError('retype');
-  }
+  Iterable<T> retype<T>() => _base.retype<T>();
 
   E get single => _base.single;
 
@@ -171,10 +166,7 @@
 
   Map<int, E> asMap() => _listBase.asMap();
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  List<T> cast<T>() {
-    throw new UnimplementedError('cast');
-  }
+  List<T> cast<T>() => _listBase.cast<T>();
 
   void clear() {
     _listBase.clear();
@@ -247,10 +239,7 @@
     _listBase.retainWhere(test);
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  List<T> retype<T>() {
-    throw new UnimplementedError('retype');
-  }
+  List<T> retype<T>() => _listBase.retype<T>();
 
   Iterable<E> get reversed => _listBase.reversed;
 
@@ -333,10 +322,7 @@
     _setBase.retainAll(elements);
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Set<T> retype<T>() {
-    throw new UnimplementedError('retype');
-  }
+  Set<T> retype<T>() => _setBase.retype<T>();
 
   void retainWhere(bool test(E element)) {
     _setBase.retainWhere(test);
@@ -406,10 +392,7 @@
     _baseQueue.retainWhere(test);
   }
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Queue<T> retype<T>() {
-    throw new UnimplementedError('retype');
-  }
+  Queue<T> retype<T>() => _baseQueue.retype<T>();
 
   E removeFirst() => _baseQueue.removeFirst();
 
@@ -498,9 +481,7 @@
   }
 
   // TODO: Dart 2.0 requires this method to be implemented.
-  Map<K2, V2> retype<K2, V2>() {
-    throw new UnimplementedError('retype');
-  }
+  Map<K2, V2> retype<K2, V2>() => _base.retype<K2, V2>();
 
   Iterable<V> get values => _base.values;
 
@@ -534,10 +515,7 @@
 
   Iterable<E> get _base => _baseMap.keys;
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Set<T> cast<T>() {
-    throw new UnimplementedError('cast');
-  }
+  Set<T> cast<T>() => _baseMap.keys.toSet().cast<T>();
 
   bool contains(Object element) => _baseMap.containsKey(element);
 
@@ -626,10 +604,7 @@
 
   Iterable<V> get _base => _baseMap.values;
 
-  // TODO: Dart 2.0 requires this method to be implemented.
-  Set<T> cast<T>() {
-    throw new UnimplementedError('cast');
-  }
+  Set<T> cast<T>() => _baseMap.values.toSet().cast<T>();
 
   bool contains(Object element) {
     if (element != null && element is! V) return false;
diff --git a/test/canonicalized_map_test.dart b/test/canonicalized_map_test.dart
index 9586cf3..4049d85 100644
--- a/test/canonicalized_map_test.dart
+++ b/test/canonicalized_map_test.dart
@@ -154,6 +154,10 @@
       ]);
       expect(map, {"01": "value 01", "2": "value 2"});
     });
+
+    test("retype returns a new map instance", () {
+      expect(map.retype<Pattern, Pattern>(), isNot(same(map)));
+    });
   });
 
   group("CanonicalizedMap builds an informative string representation", () {
diff --git a/test/queue_list_test.dart b/test/queue_list_test.dart
index eeb9a46..d2e7014 100644
--- a/test/queue_list_test.dart
+++ b/test/queue_list_test.dart
@@ -5,6 +5,8 @@
 import "package:collection/collection.dart";
 import "package:test/test.dart";
 
+import "utils.dart";
+
 void main() {
   group("new QueueList()", () {
     test("creates an empty QueueList", () {
@@ -250,6 +252,16 @@
           throwsConcurrentModificationError);
     });
   });
+
+  test("cast uses the same QueueList if possible", () {
+    var queue = new QueueList<String>();
+    expect(queue.cast<Pattern>(), same(queue));
+  }, skip: isDart2 ? false : 'Requires a Dart2 runtime');
+
+  test("retype returns a new QueueList", () {
+    var queue = new QueueList<String>();
+    expect(queue.retype<Pattern>(), isNot(same(queue)));
+  });
 }
 
 /// Returns a queue whose internal ring buffer is full enough that adding a new