Fix implicit casts (#97)

- Add an explicit `StackTrace` on arguments to `onError` callback
  arguments since they are statically `Function` so no type inference
  flows into argument types.
- Add a couple explicit casts.
- Add explicit types on some completers in test code.
- Use `Queue.of` constructor to allow type inference to flow.
- Fix a broken argument type on `DelegatingFuture`.
- Add some missing generic type arguments on fields or arguments.
diff --git a/analysis_options.yaml b/analysis_options.yaml
index f217697..1f502a5 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,5 +1,7 @@
 include: package:pedantic/analysis_options.yaml
 analyzer:
+  strong-mode:
+    implicit-casts: false
   errors:
     todo: ignore
     # Lint provided by pkg:pedantic – should fix this!
diff --git a/lib/src/cancelable_operation.dart b/lib/src/cancelable_operation.dart
index bac8f9b..cbbb8d0 100644
--- a/lib/src/cancelable_operation.dart
+++ b/lib/src/cancelable_operation.dart
@@ -50,7 +50,7 @@
     value.then((value) {
       controller.add(value);
       controller.close();
-    }, onError: (error, stackTrace) {
+    }, onError: (error, StackTrace stackTrace) {
       controller.addError(error, stackTrace);
       controller.close();
     });
@@ -104,7 +104,7 @@
           completer._cancel();
         }
       }
-    }, onError: (error, stackTrace) {
+    }, onError: (error, StackTrace stackTrace) {
       if (!completer.isCanceled) {
         if (onError != null) {
           completer.complete(Future.sync(() => onError(error, stackTrace)));
@@ -170,7 +170,7 @@
   ///
   /// If [value] is a [Future], this will complete to the result of that
   /// [Future] once it completes.
-  void complete([value]) {
+  void complete([FutureOr<T> value]) {
     if (_isCompleted) throw StateError('Operation already completed');
     _isCompleted = true;
 
@@ -180,16 +180,17 @@
       return;
     }
 
+    final future = value as Future<T>;
     if (_isCanceled) {
       // Make sure errors from [value] aren't top-leveled.
-      value.catchError((_) {});
+      future.catchError((_) {});
       return;
     }
 
-    value.then((result) {
+    future.then((result) {
       if (_isCanceled) return;
       _inner.complete(result);
-    }, onError: (error, stackTrace) {
+    }, onError: (error, StackTrace stackTrace) {
       if (_isCanceled) return;
       _inner.completeError(error, stackTrace);
     });
diff --git a/lib/src/delegate/future.dart b/lib/src/delegate/future.dart
index 8c5dd04..984caf6 100644
--- a/lib/src/delegate/future.dart
+++ b/lib/src/delegate/future.dart
@@ -33,7 +33,8 @@
       _future.then(onValue, onError: onError);
 
   @override
-  Future<T> whenComplete(FutureOr action) => _future.whenComplete(action);
+  Future<T> whenComplete(FutureOr Function() action) =>
+      _future.whenComplete(action);
 
   @override
   Future<T> timeout(Duration timeLimit, {FutureOr<T> Function() onTimeout}) =>
diff --git a/lib/src/future_group.dart b/lib/src/future_group.dart
index a6abff0..402ae46 100644
--- a/lib/src/future_group.dart
+++ b/lib/src/future_group.dart
@@ -76,7 +76,7 @@
       if (!_closed) return null;
       if (_onIdleController != null) _onIdleController.close();
       _completer.complete(_values);
-    }).catchError((error, stackTrace) {
+    }).catchError((error, StackTrace stackTrace) {
       if (_completer.isCompleted) return null;
       _completer.completeError(error, stackTrace);
     });
diff --git a/lib/src/result/release_sink.dart b/lib/src/result/release_sink.dart
index 78d0f42..5d8267a 100644
--- a/lib/src/result/release_sink.dart
+++ b/lib/src/result/release_sink.dart
@@ -8,9 +8,9 @@
 
 /// Used by [Result.releaseSink].
 class ReleaseSink<T> implements EventSink<Result<T>> {
-  final EventSink _sink;
+  final EventSink<T> _sink;
 
-  ReleaseSink(EventSink<T> sink) : _sink = sink;
+  ReleaseSink(this._sink);
 
   @override
   void add(Result<T> result) {
diff --git a/lib/src/result/result.dart b/lib/src/result/result.dart
index e04da9f..e604782 100644
--- a/lib/src/result/result.dart
+++ b/lib/src/result/result.dart
@@ -85,7 +85,8 @@
   /// Errors have been converted to an [ErrorResult] value.
   static Future<Result<T>> capture<T>(Future<T> future) {
     return future.then((value) => ValueResult(value),
-        onError: (error, stackTrace) => ErrorResult(error, stackTrace));
+        onError: (error, StackTrace stackTrace) =>
+            ErrorResult(error, stackTrace));
   }
 
   /// Captures each future in [elements],
@@ -111,7 +112,7 @@
           }
         });
       } else {
-        results.add(Result<T>.value(element));
+        results.add(Result<T>.value(element as T));
       }
     }
     if (pending == 0) {
diff --git a/lib/src/stream_sink_completer.dart b/lib/src/stream_sink_completer.dart
index 3b31576..ebfd717 100644
--- a/lib/src/stream_sink_completer.dart
+++ b/lib/src/stream_sink_completer.dart
@@ -27,7 +27,7 @@
   final StreamSink<T> sink = _CompleterSink<T>();
 
   /// Returns [sink] typed as a [_CompleterSink].
-  _CompleterSink<T> get _sink => sink;
+  _CompleterSink<T> get _sink => sink as _CompleterSink<T>;
 
   /// Convert a `Future<StreamSink>` to a `StreamSink`.
   ///
diff --git a/test/result/result_captureAll_test.dart b/test/result/result_captureAll_test.dart
index ba8305a..8e79872 100644
--- a/test/result/result_captureAll_test.dart
+++ b/test/result/result_captureAll_test.dart
@@ -138,7 +138,7 @@
       var all = Result.captureAll<int>(cs.map((c) => c.future));
       var rnd = Random(seed);
       var throwFlags = rnd.nextInt(1 << n); // Bit-flag for throwing.
-      bool throws(index) => (throwFlags & (1 << index)) != 0;
+      bool throws(int index) => (throwFlags & (1 << index)) != 0;
       var expected = List.generate(n, (x) => throws(x) ? err(x) : res(x));
 
       expect(all, completion(expected));
diff --git a/test/result/result_flattenAll_test.dart b/test/result/result_flattenAll_test.dart
index 890b2d0..c0a8603 100644
--- a/test/result/result_flattenAll_test.dart
+++ b/test/result/result_flattenAll_test.dart
@@ -7,7 +7,7 @@
 
 final someStack = StackTrace.current;
 Result<T> res<T>(T n) => Result<T>.value(n);
-Result err(n) => ErrorResult('$n', someStack);
+Result<T> err<T>(n) => ErrorResult('$n', someStack);
 
 /// Helper function creating an iterable of results.
 Iterable<Result<int>> results(int count,
@@ -22,7 +22,7 @@
 }
 
 void main() {
-  void expectAll(result, expectation) {
+  void expectAll<T>(Result<T> result, Result<T> expectation) {
     if (expectation.isError) {
       expect(result, expectation);
     } else {
diff --git a/test/result/result_test.dart b/test/result/result_test.dart
index 92fc6b0..adbc445 100644
--- a/test/result/result_test.dart
+++ b/test/result/result_test.dart
@@ -173,7 +173,7 @@
   test('capture stream', () {
     var c = StreamController<int>();
     var stream = Result.captureStream(c.stream);
-    var expectedList = Queue.from(
+    var expectedList = Queue.of(
         [Result.value(42), Result.error('BAD', stack), Result.value(37)]);
     void listener(Result actual) {
       expect(expectedList.isEmpty, isFalse);
@@ -197,7 +197,7 @@
       Result<int>.value(37)
     ];
     // Expect the data events, and an extra error event.
-    var expectedList = Queue.from(events)..add(Result.error('BAD2', stack));
+    var expectedList = Queue.of(events)..add(Result.error('BAD2', stack));
 
     void dataListener(int v) {
       expect(expectedList.isEmpty, isFalse);
@@ -260,7 +260,7 @@
   });
 
   test('handle unary', () {
-    ErrorResult result = Result.error('error', stack);
+    var result = ErrorResult('error', stack);
     var called = false;
     result.handle((error) {
       called = true;
@@ -270,7 +270,7 @@
   });
 
   test('handle binary', () {
-    ErrorResult result = Result.error('error', stack);
+    var result = ErrorResult('error', stack);
     var called = false;
     result.handle((error, stackTrace) {
       called = true;
@@ -281,7 +281,7 @@
   });
 
   test('handle unary and binary', () {
-    ErrorResult result = Result.error('error', stack);
+    var result = ErrorResult('error', stack);
     var called = false;
     result.handle((error, [stackTrace]) {
       called = true;
@@ -292,7 +292,7 @@
   });
 
   test('handle neither unary nor binary', () {
-    ErrorResult result = Result.error('error', stack);
+    var result = ErrorResult('error', stack);
     expect(() => result.handle(() => fail('unreachable')), throwsA(anything));
     expect(() => result.handle((a, b, c) => fail('unreachable')),
         throwsA(anything));
diff --git a/test/stream_completer_test.dart b/test/stream_completer_test.dart
index 2cf6728..0cd210a 100644
--- a/test/stream_completer_test.dart
+++ b/test/stream_completer_test.dart
@@ -74,9 +74,9 @@
   });
 
   test('cancel new stream before source is done', () async {
-    var completer = StreamCompleter();
+    var completer = StreamCompleter<int>();
     var lastEvent = -1;
-    var controller = StreamController();
+    var controller = StreamController<int>();
     StreamSubscription subscription;
     subscription = completer.stream.listen((value) {
       expect(value, lessThan(3));
diff --git a/test/stream_zip_test.dart b/test/stream_zip_test.dart
index f462996..19c3dec 100644
--- a/test/stream_zip_test.dart
+++ b/test/stream_zip_test.dart
@@ -15,9 +15,9 @@
 
 /// Make a [Stream] from an [Iterable] by adding events to a stream controller
 /// at periodic intervals.
-Stream mks(Iterable iterable) {
+Stream<T> mks<T>(Iterable<T> iterable) {
   var iterator = iterable.iterator;
-  var controller = StreamController();
+  var controller = StreamController<T>();
   // Some varying time between 3 and 10 ms.
   var ms = ((++ctr) * 5) % 7 + 3;
   Timer.periodic(Duration(milliseconds: ms), (Timer timer) {
@@ -221,7 +221,8 @@
     controller..add(7)..add(8)..add(9);
     // Transformer that puts error into controller when one of the first two
     // streams have sent a done event.
-    var trans = StreamTransformer.fromHandlers(handleDone: (EventSink s) {
+    var trans =
+        StreamTransformer<int, int>.fromHandlers(handleDone: (EventSink s) {
       Timer.run(() {
         controller.addError('BAD-6');
       });
diff --git a/test/utils.dart b/test/utils.dart
index b09d06b..a99fe9b 100644
--- a/test/utils.dart
+++ b/test/utils.dart
@@ -22,10 +22,10 @@
 // TODO(nweiz): Use the version of this in test when test#418 is fixed.
 /// A matcher that runs a callback in its own zone and asserts that that zone
 /// emits an error that matches [matcher].
-Matcher throwsZoned(matcher) => predicate((callback) {
+Matcher throwsZoned(matcher) => predicate((void Function() callback) {
       var firstError = true;
       runZoned(callback,
-          onError: expectAsync2((error, stackTrace) {
+          onError: expectAsync2((error, StackTrace stackTrace) {
             if (firstError) {
               expect(error, matcher);
               firstError = false;
@@ -89,7 +89,7 @@
   Future get done => _doneCompleter.future;
   final _doneCompleter = Completer();
 
-  final Function _onDone;
+  final void Function() _onDone;
 
   /// Creates a new sink.
   ///