Fix strong mode warnings.

See also https://codereview.chromium.org/1817463002/.

R=het@google.com, ochafik@google.com

Review URL: https://codereview.chromium.org//1831103004 .
diff --git a/.analysis_options b/.analysis_options
new file mode 100644
index 0000000..a10d4c5
--- /dev/null
+++ b/.analysis_options
@@ -0,0 +1,2 @@
+analyzer:
+  strong-mode: true
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1ab3393..1425177 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+## 1.4.1
+
+* Fix all strong mode warnings.
+
 ## 1.4.0
 
 * Add a `new PriorityQueue()` constructor that forwards to `new
diff --git a/lib/src/algorithms.dart b/lib/src/algorithms.dart
index 2b66d7d..57456a0 100644
--- a/lib/src/algorithms.dart
+++ b/lib/src/algorithms.dart
@@ -5,7 +5,8 @@
 import "dart:math" as math;
 
 /// Version of [binarySearch] optimized for comparable keys
-int _comparableBinarySearch(List<Comparable> list, Comparable value) {
+int _comparableBinarySearch/*<T extends Comparable<T>>*/(
+    List<Comparable/*<T>*/> list, Comparable/*<T>*/ value) {
   int min = 0;
   int max = list.length;
   while (min < max) {
@@ -31,7 +32,8 @@
 /// the objects.
 ///
 /// Returns -1 if [value] is not in the list by default.
-int binarySearch(List sortedList, value, { int compare(a, b) }) {
+int binarySearch/*<T extends Comparable<T>>*/(
+    List/*<T>*/ sortedList, /*=T*/ value, { int compare(/*=T*/ a, /*=T*/ b) }) {
   if (compare == null) {
     return _comparableBinarySearch(sortedList, value);
   }
@@ -79,7 +81,8 @@
 ///
 /// Returns [sortedList.length] if all the items in [sortedList] compare less
 /// than [value].
-int lowerBound(List sortedList, value, { int compare(a, b) }) {
+int lowerBound/*<T extends Comparable<T>>*/(
+    List/*<T>*/ sortedList, /*=T*/ value, { int compare(/*=T*/ a, /*=T*/ b) }) {
   if (compare == null) {
     return _comparableLowerBound(sortedList, value);
   }
diff --git a/lib/src/canonicalized_map.dart b/lib/src/canonicalized_map.dart
index d967f70..cc78105 100644
--- a/lib/src/canonicalized_map.dart
+++ b/lib/src/canonicalized_map.dart
@@ -6,6 +6,10 @@
 
 import 'utils.dart';
 
+typedef C _Canonicalize<C, K>(K key);
+
+typedef bool _IsValidKey(Object key);
+
 /// A map whose keys are converted to canonical values of type `C`.
 ///
 /// This is useful for using case-insensitive String keys, for example. It's
@@ -16,9 +20,9 @@
 /// By default, `null` is allowed as a key. It can be forbidden via the
 /// `isValidKey` parameter.
 class CanonicalizedMap<C, K, V> implements Map<K, V> {
-  final Function _canonicalize;
+  final _Canonicalize<C, K> _canonicalize;
 
-  final Function _isValidKeyFn;
+  final _IsValidKey _isValidKeyFn;
 
   final _base = new Map<C, Pair<K, V>>();
 
@@ -52,7 +56,7 @@
 
   V operator [](Object key) {
     if (!_isValidKey(key)) return null;
-    var pair = _base[_canonicalize(key)];
+    var pair = _base[_canonicalize(key as K)];
     return pair == null ? null : pair.last;
   }
 
@@ -71,7 +75,7 @@
 
   bool containsKey(Object key) {
     if (!_isValidKey(key)) return false;
-    return _base.containsKey(_canonicalize(key));
+    return _base.containsKey(_canonicalize(key as K));
   }
 
   bool containsValue(Object value) =>
@@ -96,7 +100,7 @@
 
   V remove(Object key) {
     if (!_isValidKey(key)) return null;
-    var pair = _base.remove(_canonicalize(key));
+    var pair = _base.remove(_canonicalize(key as K));
     return pair == null ? null : pair.last;
   }
 
diff --git a/lib/src/equality.dart b/lib/src/equality.dart
index 5a0d074..09f10a6 100644
--- a/lib/src/equality.dart
+++ b/lib/src/equality.dart
@@ -8,7 +8,7 @@
 
 /// A generic equality relation on objects.
 abstract class Equality<E> {
-  const factory Equality() = DefaultEquality;
+  const factory Equality() = DefaultEquality<E>;
 
   /// Compare two elements for being equal.
   ///
@@ -32,18 +32,18 @@
 ///
 /// This equality uses the objects' own [Object.==] and [Object.hashCode] for
 /// the equality.
-class DefaultEquality implements Equality {
+class DefaultEquality<E> implements Equality<E> {
   const DefaultEquality();
-  bool equals(Object e1, Object e2) => e1 == e2;
-  int hash(Object e) => e.hashCode;
+  bool equals(E e1, E e2) => e1 == e2;
+  int hash(E e) => e.hashCode;
   bool isValidKey(Object o) => true;
 }
 
 /// Equality of objects that compares only the identity of the objects.
-class IdentityEquality implements Equality {
+class IdentityEquality<E> implements Equality<E> {
   const IdentityEquality();
-  bool equals(Object e1, Object e2) => identical(e1, e2);
-  int hash(Object e) => identityHashCode(e);
+  bool equals(E e1, E e2) => identical(e1, e2);
+  int hash(E e) => identityHashCode(e);
   bool isValidKey(Object o) => true;
 }
 
@@ -59,8 +59,8 @@
   bool equals(Iterable<E> elements1, Iterable<E> elements2) {
     if (identical(elements1, elements2)) return true;
     if (elements1 == null || elements2 == null) return false;
-    Iterator it1 = elements1.iterator;
-    Iterator it2 = elements2.iterator;
+    var it1 = elements1.iterator;
+    var it2 = elements2.iterator;
     while (true) {
       bool hasNext = it1.moveNext();
       if (hasNext != it2.moveNext()) return false;
diff --git a/lib/src/iterable_zip.dart b/lib/src/iterable_zip.dart
index 30acb0e..638c686 100644
--- a/lib/src/iterable_zip.dart
+++ b/lib/src/iterable_zip.dart
@@ -13,24 +13,27 @@
 /// combined into a single list, which becomes the next value of this
 /// [Iterable]'s [Iterator]. As soon as any of the iterators run out,
 /// the zipped iterator also stops.
-class IterableZip extends IterableBase<List> {
-  final Iterable<Iterable> _iterables;
-  IterableZip(Iterable<Iterable> iterables)
+class IterableZip<T> extends IterableBase<List<T>> {
+  final Iterable<Iterable<T>> _iterables;
+
+  IterableZip(Iterable<Iterable<T>> iterables)
       : this._iterables = iterables;
 
   /// Returns an iterator that combines values of the iterables' iterators
   /// as long as they all have values.
-  Iterator<List> get iterator {
-    List iterators = _iterables.map((x) => x.iterator).toList(growable: false);
+  Iterator<List<T>> get iterator {
+    var iterators = _iterables.map((x) => x.iterator).toList(growable: false);
     // TODO(lrn): Return an empty iterator directly if iterators is empty?
-    return new _IteratorZip(iterators);
+    return new _IteratorZip<T>(iterators);
   }
 }
 
-class _IteratorZip implements Iterator<List> {
-  final List<Iterator> _iterators;
-  List _current;
-  _IteratorZip(List iterators) : _iterators = iterators;
+class _IteratorZip<T> implements Iterator<List<T>> {
+  final List<Iterator<T>> _iterators;
+  List<T> _current;
+
+  _IteratorZip(List<Iterator<T>> iterators) : _iterators = iterators;
+
   bool moveNext() {
     if (_iterators.isEmpty) return false;
     for (int i = 0; i < _iterators.length; i++) {
@@ -46,5 +49,5 @@
     return true;
   }
 
-  List get current => _current;
+  List<T> get current => _current;
 }
diff --git a/lib/src/priority_queue.dart b/lib/src/priority_queue.dart
index 64fd84f..de91f15 100644
--- a/lib/src/priority_queue.dart
+++ b/lib/src/priority_queue.dart
@@ -16,7 +16,9 @@
   /// elements. An element that compares as less than another element has
   /// a higher priority.
   ///
-  /// If [comparison] is omitted, it defaults to [Comparable.compare].
+  /// If [comparison] is omitted, it defaults to [Comparable.compare]. If this
+  /// is the case, `E` must implement [Comparable], and this is checked at
+  /// runtime for every comparison.
   factory PriorityQueue([int comparison(E e1, E e2)]) = HeapPriorityQueue<E>;
 
   /// Number of elements in the queue.
@@ -121,7 +123,7 @@
   static const int _INITIAL_CAPACITY = 7;
 
   /// The comparison being used to compare the priority of elements.
-  final Comparator comparison;
+  final Comparator<E> comparison;
 
   /// List implementation of a heap.
   List<E> _queue = new List<E>(_INITIAL_CAPACITY);
@@ -137,9 +139,12 @@
   /// elements. An element that compares as less than another element has
   /// a higher priority.
   ///
-  /// If [comparison] is omitted, it defaults to [Comparable.compare].
+  /// If [comparison] is omitted, it defaults to [Comparable.compare]. If this
+  /// is the case, `E` must implement [Comparable], and this is checked at
+  /// runtime for every comparison.
   HeapPriorityQueue([int comparison(E e1, E e2)])
-      : comparison = (comparison != null) ? comparison : Comparable.compare;
+      : comparison = comparison ??
+            ((e1, e2) => (e1 as Comparable).compareTo(e2));
 
   void add(E element) {
     _add(element);
diff --git a/lib/src/queue_list.dart b/lib/src/queue_list.dart
index a12f0b4..bf75f33 100644
--- a/lib/src/queue_list.dart
+++ b/lib/src/queue_list.dart
@@ -35,7 +35,7 @@
       int length = source.length;
       QueueList<E> queue = new QueueList(length + 1);
       assert(queue._table.length > length);
-      List sourceList = source;
+      var sourceList = source;
       queue._table.setRange(0, length, sourceList, 0);
       queue._tail = length;
       return queue;
@@ -52,7 +52,7 @@
 
   void addAll(Iterable<E> elements) {
     if (elements is List) {
-      List list = elements;
+      var list = elements;
       int addCount = list.length;
       int length = this.length;
       if (length + addCount >= _table.length) {
diff --git a/lib/src/unmodifiable_wrappers.dart b/lib/src/unmodifiable_wrappers.dart
index 1f78470..6003286 100644
--- a/lib/src/unmodifiable_wrappers.dart
+++ b/lib/src/unmodifiable_wrappers.dart
@@ -25,7 +25,7 @@
 /// Mixin class that implements a throwing version of all list operations that
 /// change the List's length.
 abstract class NonGrowableListMixin<E> implements List<E> {
-  static _throw() {
+  static /*=T*/ _throw/*<T>*/() {
     throw new UnsupportedError(
         "Cannot change the length of a fixed-length list");
   }
@@ -98,7 +98,7 @@
 /// Mixin class that implements a throwing version of all set operations that
 /// change the Set.
 abstract class UnmodifiableSetMixin<E> implements Set<E> {
-  _throw() {
+  static /*=T*/ _throw/*<T>*/() {
     throw new UnsupportedError("Cannot modify an unmodifiable Set");
   }
 
@@ -138,7 +138,7 @@
 /// Mixin class that implements a throwing version of all map operations that
 /// change the Map.
 abstract class UnmodifiableMapMixin<K, V> implements Map<K, V> {
-  static _throw() {
+  static /*=T*/ _throw/*<T>*/() {
     throw new UnsupportedError("Cannot modify an unmodifiable Map");
   }
 
diff --git a/lib/src/wrappers.dart b/lib/src/wrappers.dart
index ee03b5f..fcd3315 100644
--- a/lib/src/wrappers.dart
+++ b/lib/src/wrappers.dart
@@ -7,6 +7,8 @@
 
 import "unmodifiable_wrappers.dart";
 
+typedef K _KeyForValue<K, V>(V value);
+
 /// A base class for delegating iterables.
 ///
 /// Subclasses can provide a [_base] that should be delegated to. Unlike
@@ -24,14 +26,17 @@
 
   bool every(bool test(E element)) => _base.every(test);
 
-  Iterable expand(Iterable f(E element)) => _base.expand(f);
+  Iterable/*<T>*/ expand/*<T>*/(Iterable/*<T>*/ f(E element)) =>
+      _base.expand(f);
 
   E get first => _base.first;
 
   E firstWhere(bool test(E element), {E orElse()}) =>
       _base.firstWhere(test, orElse: orElse);
 
-  fold(initialValue, combine(previousValue, E element)) =>
+  /*=T*/ fold/*<T>*/(
+          /*=T*/ initialValue,
+          /*=T*/ combine(/*=T*/ previousValue, E element)) =>
       _base.fold(initialValue, combine);
 
   void forEach(void f(E element)) => _base.forEach(f);
@@ -51,7 +56,7 @@
 
   int get length => _base.length;
 
-  Iterable map(f(E element)) => _base.map(f);
+  Iterable/*<T>*/ map/*<T>*/(/*=T*/ f(E element)) => _base.map(f);
 
   E reduce(E combine(E value, E element)) => _base.reduce(combine);
 
@@ -391,7 +396,7 @@
 }
 
 /// Creates a modifiable [Set] view of the values of a [Map].
-/// 
+///
 /// The `Set` view assumes that the keys of the `Map` can be uniquely determined
 /// from the values. The `keyForValue` function passed to the constructor finds
 /// the key for a single value. The `keyForValue` function should be consistent
@@ -413,7 +418,7 @@
 /// Effectively, the map will act as a kind of index for the set.
 class MapValueSet<K, V> extends _DelegatingIterableBase<V> implements Set<V> {
   final Map<K, V> _baseMap;
-  final Function _keyForValue;
+  final _KeyForValue<K, V> _keyForValue;
 
   /// Creates a new [MapValueSet] based on [base].
   ///
@@ -428,7 +433,9 @@
 
   bool contains(Object element) {
     if (element != null && element is! V) return false;
-    return _baseMap.containsKey(_keyForValue(element));
+    var key = _keyForValue(element as V);
+
+    return _baseMap.containsKey(key);
   }
 
   bool get isEmpty => _baseMap.isEmpty;
@@ -474,11 +481,17 @@
   /// may be different than the equality operation [this] uses.
   Set<V> intersection(Set<Object> other) => where(other.contains).toSet();
 
-  V lookup(Object element) => _baseMap[_keyForValue(element)];
+  V lookup(Object element) {
+    if (element != null && element is! V) return null;
+    var key = _keyForValue(element as V);
 
-  bool remove(Object value) {
-    if (value != null && value is! V) return false;
-    var key = _keyForValue(value);
+    return _baseMap[key];
+  }
+
+  bool remove(Object element) {
+    if (element != null && element is! V) return false;
+    var key = _keyForValue(element as V);
+
     if (!_baseMap.containsKey(key)) return false;
     _baseMap.remove(key);
     return true;
@@ -498,7 +511,8 @@
     var valuesToRetain = new Set<V>.identity();
     for (var element in elements) {
       if (element != null && element is! V) continue;
-      var key = _keyForValue(element);
+      var key = _keyForValue(element as V);
+
       if (!_baseMap.containsKey(key)) continue;
       valuesToRetain.add(_baseMap[key]);
     }
diff --git a/pubspec.yaml b/pubspec.yaml
index ff2607e..16a5996 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,9 +1,9 @@
 name: collection
-version: 1.4.0
+version: 1.4.1
 author: Dart Team <misc@dartlang.org>
 description: Collections and utilities functions and classes related to collections.
 homepage: https://www.github.com/dart-lang/collection
 environment:
-  sdk: '>=1.5.0 <2.0.0'
+  sdk: '>=1.12.0 <2.0.0'
 dev_dependencies:
   test: '^0.12.0'
diff --git a/test/priority_queue_test.dart b/test/priority_queue_test.dart
index c6966d6..1aabcc1 100644
--- a/test/priority_queue_test.dart
+++ b/test/priority_queue_test.dart
@@ -6,7 +6,7 @@
 
 import "package:test/test.dart";
 
-import "package:collection/priority_queue.dart";
+import "package:collection/src/priority_queue.dart";
 
 void main() {
   testDefault();
diff --git a/test/wrapper_test.dart b/test/wrapper_test.dart
index 3f68aa9..035783e 100644
--- a/test/wrapper_test.dart
+++ b/test/wrapper_test.dart
@@ -85,7 +85,6 @@
 // argument to DelegatingIterable/Set/List.
 class IterableNSM extends NSM implements Iterable, Set, List, Queue {
   IterableNSM(action(Invocation i)) : super(action);
-  noSuchMethod(Invocation i) => super.noSuchMethod(i);  // Silence warnings
   toString() => super.noSuchMethod(TO_STRING_INVOCATION);
 }
 
@@ -120,7 +119,6 @@
 // Like NSM but implements Map to allow as argument for DelegatingMap.
 class MapNSM extends NSM implements Map {
   MapNSM(action(Invocation i)) : super(action);
-  noSuchMethod(Invocation i) => super.noSuchMethod(i);
   toString() => super.noSuchMethod(TO_STRING_INVOCATION);
 }