Add methods to Result. Bump version to 2.0 and remove deprecated features.

R=floitsch@google.com

Review-Url: https://codereview.chromium.org//2996143002 .
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e4a8696..a1e9683 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,12 @@
+## 2.0.0
+* Remove deprecated public `result.dart` and `stream_zip.dart` libraries and
+  deprecated classes `ReleaseStreamTransformer` and `CaptureStreamTransformer`.
+
+* Add `captureAll` and `flattenList` static methods to `Result`.
+
+* Change `ErrorResult` to not be generic and always be a `Result<Null>`.
+  That makes an error independent of the type of result it occurs instead of.
+
 ## 1.13.3
 
 * Make `TypeSafeStream` extend `Stream` instead of implementing it. This ensures
diff --git a/lib/async.dart b/lib/async.dart
index e090032..25fc0fd 100644
--- a/lib/async.dart
+++ b/lib/async.dart
@@ -17,11 +17,9 @@
 export "src/lazy_stream.dart";
 export "src/null_stream_sink.dart";
 export "src/restartable_timer.dart";
-export "src/result.dart";
-export "src/result/capture_transformer.dart";
+export "src/result/result.dart";
 export "src/result/error.dart";
 export "src/result/future.dart";
-export "src/result/release_transformer.dart";
 export "src/result/value.dart";
 export "src/single_subscription_transformer.dart";
 export "src/stream_completer.dart";
diff --git a/lib/result.dart b/lib/result.dart
deleted file mode 100644
index 627f200..0000000
--- a/lib/result.dart
+++ /dev/null
@@ -1,13 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// Import `async.dart` instead.
-@Deprecated("Will be removed in async 2.0.0.")
-library dart.pkg.async.results;
-
-export "src/result.dart";
-export "src/result/capture_transformer.dart";
-export "src/result/error.dart";
-export "src/result/release_transformer.dart";
-export "src/result/value.dart";
diff --git a/lib/src/result.dart b/lib/src/result.dart
deleted file mode 100644
index 49457c3..0000000
--- a/lib/src/result.dart
+++ /dev/null
@@ -1,150 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'result/capture_transformer.dart';
-import 'result/error.dart';
-import 'result/release_transformer.dart';
-import 'result/value.dart';
-import 'stream_sink_transformer.dart';
-
-/// The result of a computation.
-///
-/// Capturing a result (either a returned value or a thrown error) means
-/// converting it into a [Result] - either a [ValueResult] or an [ErrorResult].
-///
-/// This value can release itself by writing itself either to a [EventSink] or a
-/// [Completer], or by becoming a [Future].
-abstract class Result<T> {
-  /// A stream transformer that captures a stream of events into [Result]s.
-  ///
-  /// The result of the transformation is a stream of [Result] values and no
-  /// error events. This is the transformer used by [captureStream].
-  static const StreamTransformer<Object, Result> captureStreamTransformer =
-      const CaptureStreamTransformer();
-
-  /// A stream transformer that releases a stream of result events.
-  ///
-  /// The result of the transformation is a stream of values and error events.
-  /// This is the transformer used by [releaseStream].
-  static const StreamTransformer<Object, Result> releaseStreamTransformer =
-      const ReleaseStreamTransformer();
-
-  /// A sink transformer that captures events into [Result]s.
-  ///
-  /// The result of the transformation is a sink that only forwards [Result]
-  /// values and no error events.
-  static const StreamSinkTransformer<Object, Result> captureSinkTransformer =
-      const StreamSinkTransformer.fromStreamTransformer(
-          const CaptureStreamTransformer());
-
-  /// A sink transformer that releases result events.
-  ///
-  /// The result of the transformation is a sink that forwards of values and
-  /// error events.
-  static const StreamSinkTransformer<Object, Result> releaseSinkTransformer =
-      const StreamSinkTransformer.fromStreamTransformer(
-          const ReleaseStreamTransformer());
-
-  /// Create a `Result` with the result of calling [computation].
-  ///
-  /// This generates either a [ValueResult] with the value returned by
-  /// calling `computation`, or an [ErrorResult] with an error thrown by
-  /// the call.
-  factory Result(T computation()) {
-    try {
-      return new ValueResult(computation());
-    } catch (e, s) {
-      return new ErrorResult(e, s);
-    }
-  }
-
-  /// Create a `Result` holding a value.
-  ///
-  /// Alias for [ValueResult.ValueResult].
-  factory Result.value(T value) = ValueResult<T>;
-
-  /// Create a `Result` holding an error.
-  ///
-  /// Alias for [ErrorResult.ErrorResult].
-  factory Result.error(Object error, [StackTrace stackTrace]) =>
-      new ErrorResult(error, stackTrace);
-
-  /// Capture the result of a future into a `Result` future.
-  ///
-  /// The resulting future will never have an error.
-  /// Errors have been converted to an [ErrorResult] value.
-  static Future<Result<T>> capture<T>(Future<T> future) {
-    return future.then((value) => new ValueResult(value),
-        onError: (error, stackTrace) => new ErrorResult<T>(error, stackTrace));
-  }
-
-  /// Release the result of a captured future.
-  ///
-  /// Converts the [Result] value of the given [future] to a value or error
-  /// completion of the returned future.
-  ///
-  /// If [future] completes with an error, the returned future completes with
-  /// the same error.
-  static Future<T> release<T>(Future<Result<T>> future) =>
-      future.then<T>((result) => result.asFuture);
-
-  /// Capture the results of a stream into a stream of [Result] values.
-  ///
-  /// The returned stream will not have any error events.
-  /// Errors from the source stream have been converted to [ErrorResult]s.
-  static Stream<Result<T>> captureStream<T>(Stream<T> source) =>
-      source.transform(new CaptureStreamTransformer<T>());
-
-  /// Release a stream of [result] values into a stream of the results.
-  ///
-  /// `Result` values of the source stream become value or error events in
-  /// the returned stream as appropriate.
-  /// Errors from the source stream become errors in the returned stream.
-  static Stream<T> releaseStream<T>(Stream<Result<T>> source) =>
-      source.transform(new ReleaseStreamTransformer<T>());
-
-  /// Converts a result of a result to a single result.
-  ///
-  /// If the result is an error, or it is a `Result` value
-  /// which is then an error, then a result with that error is returned.
-  /// Otherwise both levels of results are value results, and a single
-  /// result with the value is returned.
-  static Result<T> flatten<T>(Result<Result<T>> result) {
-    if (result.isValue) return result.asValue.value;
-    return new ErrorResult<T>(result.asError.error, result.asError.stackTrace);
-  }
-
-  /// Whether this result is a value result.
-  ///
-  /// Always the opposite of [isError].
-  bool get isValue;
-
-  /// Whether this result is an error result.
-  ///
-  /// Always the opposite of [isValue].
-  bool get isError;
-
-  /// If this is a value result, return itself.
-  ///
-  /// Otherwise return `null`.
-  ValueResult<T> get asValue;
-
-  /// If this is an error result, return itself.
-  ///
-  /// Otherwise return `null`.
-  ErrorResult<T> get asError;
-
-  /// Complete a completer with this result.
-  void complete(Completer<T> completer);
-
-  /// Add this result to an [EventSink].
-  ///
-  /// Calls the sink's `add` or `addError` method as appropriate.
-  void addTo(EventSink<T> sink);
-
-  /// Creates a future completed with this result as a value or an error.
-  Future<T> get asFuture;
-}
diff --git a/lib/src/result/capture_sink.dart b/lib/src/result/capture_sink.dart
index 7474525..c85b553 100644
--- a/lib/src/result/capture_sink.dart
+++ b/lib/src/result/capture_sink.dart
@@ -4,12 +4,11 @@
 
 import 'dart:async';
 
-import '../result.dart';
+import 'result.dart';
 
-/// Use [Result.captureSinkTransformer].
-@Deprecated("Will be removed in async 2.0.0.")
+/// Used by [Result.captureSink].
 class CaptureSink<T> implements EventSink<T> {
-  final EventSink _sink;
+  final EventSink<Result<T>> _sink;
 
   CaptureSink(EventSink<Result<T>> sink) : _sink = sink;
 
diff --git a/lib/src/result/capture_transformer.dart b/lib/src/result/capture_transformer.dart
index 6b1bbf2..71e8a00 100644
--- a/lib/src/result/capture_transformer.dart
+++ b/lib/src/result/capture_transformer.dart
@@ -4,14 +4,13 @@
 
 import 'dart:async';
 
-import '../result.dart';
+import 'result.dart';
 import 'capture_sink.dart';
 
 /// A stream transformer that captures a stream of events into [Result]s.
 ///
 /// The result of the transformation is a stream of [Result] values and no
-/// error events. This is the transformer used by [captureStream].
-@Deprecated("Will be removed in async 2.0.0.")
+/// error events. Exposed by [Result.captureStream].
 class CaptureStreamTransformer<T> implements StreamTransformer<T, Result<T>> {
   const CaptureStreamTransformer();
 
@@ -19,7 +18,6 @@
     return new Stream<Result<T>>.eventTransformed(source, _createSink);
   }
 
-  static EventSink _createSink(EventSink<Result> sink) {
-    return new CaptureSink(sink);
-  }
+  // Since Stream.eventTransformed is not generic, this method can be static.
+  static EventSink _createSink(EventSink<Result> sink) => new CaptureSink(sink);
 }
diff --git a/lib/src/result/error.dart b/lib/src/result/error.dart
index b6d5859..45e06a2 100644
--- a/lib/src/result/error.dart
+++ b/lib/src/result/error.dart
@@ -4,18 +4,21 @@
 
 import 'dart:async';
 
-import '../result.dart';
+import 'result.dart';
 import 'value.dart';
 
 /// A result representing a thrown error.
-class ErrorResult<T> implements Result<T> {
+class ErrorResult implements Result<Null> {
+  /// The error object that was thrown.
   final error;
+
+  /// The stack trace corresponding to where [error] was thrown.
   final StackTrace stackTrace;
 
   bool get isValue => false;
   bool get isError => true;
-  ValueResult<T> get asValue => null;
-  ErrorResult<T> get asError => this;
+  ValueResult<Null> get asValue => null;
+  ErrorResult get asError => this;
 
   ErrorResult(this.error, this.stackTrace);
 
@@ -27,7 +30,7 @@
     sink.addError(error, stackTrace);
   }
 
-  Future<T> get asFuture => new Future.error(error, stackTrace);
+  Future<Null> get asFuture => new Future<Null>.error(error, stackTrace);
 
   /// Calls an error handler with the error and stacktrace.
   ///
@@ -42,4 +45,12 @@
       errorHandler(error);
     }
   }
+
+  int get hashCode => error.hashCode ^ stackTrace.hashCode ^ 0x1d61823f;
+
+  /// This is equal only to an error result with equal [error] and [stackTrace].
+  bool operator ==(Object other) =>
+      other is ErrorResult &&
+      error == other.error &&
+      stackTrace == other.stackTrace;
 }
diff --git a/lib/src/result/future.dart b/lib/src/result/future.dart
index 749b101..ff30546 100644
--- a/lib/src/result/future.dart
+++ b/lib/src/result/future.dart
@@ -5,7 +5,7 @@
 import 'dart:async';
 
 import '../delegate/future.dart';
-import '../result.dart';
+import 'result.dart';
 
 /// A [Future] wrapper that provides synchronous access to the result of the
 /// wrapped [Future] once it's completed.
@@ -19,15 +19,9 @@
   Result<T> get result => _result;
   Result<T> _result;
 
-  factory ResultFuture(Future<T> future) {
-    ResultFuture<T> resultFuture;
-    resultFuture = new ResultFuture._(() async {
-      var result = await Result.capture(future);
-      resultFuture._result = result;
-      return await result.asFuture;
-    }());
-    return resultFuture;
+  ResultFuture(Future<T> future) : super(future) {
+    Result.capture(future).then((result) {
+      _result = result;
+    });
   }
-
-  ResultFuture._(Future<T> future) : super(future);
 }
diff --git a/lib/src/result/release_sink.dart b/lib/src/result/release_sink.dart
index 114981b..a0715a1 100644
--- a/lib/src/result/release_sink.dart
+++ b/lib/src/result/release_sink.dart
@@ -4,22 +4,16 @@
 
 import 'dart:async';
 
-import '../result.dart';
+import 'result.dart';
 
-/// Use [Result.captureSinkTransformer].
-@Deprecated("Will be removed in async 2.0.0.")
+/// Used by [Result.releaseSink].
 class ReleaseSink<T> implements EventSink<Result<T>> {
   final EventSink _sink;
 
   ReleaseSink(EventSink<T> sink) : _sink = sink;
 
   void add(Result<T> result) {
-    if (result.isValue) {
-      _sink.add(result.asValue.value);
-    } else {
-      var error = result.asError;
-      _sink.addError(error.error, error.stackTrace);
-    }
+    result.addTo(_sink);
   }
 
   void addError(Object error, [StackTrace stackTrace]) {
diff --git a/lib/src/result/release_transformer.dart b/lib/src/result/release_transformer.dart
index 456ed0a..fc9278d 100644
--- a/lib/src/result/release_transformer.dart
+++ b/lib/src/result/release_transformer.dart
@@ -4,11 +4,10 @@
 
 import 'dart:async';
 
-import '../result.dart';
+import 'result.dart';
 import 'release_sink.dart';
 
-/// Use [Result.releaseTransformer] instead.
-@Deprecated("Will be removed in async 2.0.0.")
+/// A transformer that releases result events as data and error events.
 class ReleaseStreamTransformer<T> implements StreamTransformer<Result<T>, T> {
   const ReleaseStreamTransformer();
 
@@ -16,7 +15,6 @@
     return new Stream<T>.eventTransformed(source, _createSink);
   }
 
-  static EventSink<Result> _createSink(EventSink sink) {
-    return new ReleaseSink(sink);
-  }
+  // Since Stream.eventTransformed is not generic, this method can be static.
+  static EventSink<Result> _createSink(EventSink sink) => new ReleaseSink(sink);
 }
diff --git a/lib/src/result/result.dart b/lib/src/result/result.dart
new file mode 100644
index 0000000..98b5aa4
--- /dev/null
+++ b/lib/src/result/result.dart
@@ -0,0 +1,224 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'capture_sink.dart';
+import 'capture_transformer.dart';
+import 'error.dart';
+import 'release_sink.dart';
+import 'release_transformer.dart';
+import 'value.dart';
+import '../stream_sink_transformer.dart';
+
+/// The result of a computation.
+///
+/// Capturing a result (either a returned value or a thrown error) means
+/// converting it into a [Result] - either a [ValueResult] or an [ErrorResult].
+///
+/// This value can release itself by writing itself either to a [EventSink] or a
+/// [Completer], or by becoming a [Future].
+///
+/// A [Future] represents a potential result, one that might not have been
+/// computed yet, and a [Result] is always a completed and available result.
+abstract class Result<T> {
+  /// A stream transformer that captures a stream of events into [Result]s.
+  ///
+  /// The result of the transformation is a stream of [Result] values and no
+  /// error events. This is the transformer used by [captureStream].
+  static const StreamTransformer<Object, Result<Object>>
+      captureStreamTransformer = const CaptureStreamTransformer<Object>();
+
+  /// A stream transformer that releases a stream of result events.
+  ///
+  /// The result of the transformation is a stream of values and error events.
+  /// This is the transformer used by [releaseStream].
+  static const StreamTransformer<Result<Object>, Object>
+      releaseStreamTransformer = const ReleaseStreamTransformer<Object>();
+
+  /// A sink transformer that captures events into [Result]s.
+  ///
+  /// The result of the transformation is a sink that only forwards [Result]
+  /// values and no error events.
+  static const StreamSinkTransformer<Object, Result<Object>>
+      captureSinkTransformer =
+      const StreamSinkTransformer<Object, Result<Object>>.fromStreamTransformer(
+          const CaptureStreamTransformer<Object>());
+
+  /// A sink transformer that releases result events.
+  ///
+  /// The result of the transformation is a sink that forwards of values and
+  /// error events.
+  static const StreamSinkTransformer<Result<Object>, Object>
+      releaseSinkTransformer =
+      const StreamSinkTransformer<Result<Object>, Object>.fromStreamTransformer(
+          const ReleaseStreamTransformer<Object>());
+
+  /// Creates a `Result` with the result of calling [computation].
+  ///
+  /// This generates either a [ValueResult] with the value returned by
+  /// calling `computation`, or an [ErrorResult] with an error thrown by
+  /// the call.
+  factory Result(T computation()) {
+    try {
+      return new ValueResult<T>(computation());
+    } catch (e, s) {
+      return new ErrorResult(e, s);
+    }
+  }
+
+  /// Creates a `Result` holding a value.
+  ///
+  /// Alias for [ValueResult.ValueResult].
+  factory Result.value(T value) = ValueResult<T>;
+
+  /// Creates a `Result` holding an error.
+  ///
+  /// Alias for [ErrorResult.ErrorResult].
+  factory Result.error(Object error, [StackTrace stackTrace]) =>
+      new ErrorResult(error, stackTrace);
+
+  /// Captures the result of a future into a `Result` future.
+  ///
+  /// The resulting future will never have an error.
+  /// Errors have been converted to an [ErrorResult] value.
+  static Future<Result<T>> capture<T>(Future<T> future) {
+    return future.then((value) => new ValueResult(value),
+        onError: (error, stackTrace) => new ErrorResult(error, stackTrace));
+  }
+
+  /// Captures each future in [elements],
+  ///
+  /// Returns a (future of) a list of results for each element in [elements],
+  /// in iteration order.
+  /// Each future in [elements] is [capture]d and each non-future is
+  /// wrapped as a [Result.value].
+  /// The returned future will never have an error.
+  static Future<List<Result<T>>> captureAll<T>(Iterable<FutureOr<T>> elements) {
+    var results = <Result<T>>[];
+    int pending = 0;
+    var completer;
+    for (var element in elements) {
+      if (element is Future<T>) {
+        int i = results.length;
+        results.add(null);
+        pending++;
+        Result.capture<T>(element).then((result) {
+          results[i] = result;
+          if (--pending == 0) {
+            completer.complete(results);
+          }
+        });
+      } else {
+        results.add(new Result<T>.value(element));
+      }
+    }
+    if (pending == 0) {
+      return new Future<List<Result<T>>>.value(results);
+    }
+    completer = new Completer<List<Result<T>>>();
+    return completer.future;
+  }
+
+  /// Releases the result of a captured future.
+  ///
+  /// Converts the [Result] value of the given [future] to a value or error
+  /// completion of the returned future.
+  ///
+  /// If [future] completes with an error, the returned future completes with
+  /// the same error.
+  static Future<T> release<T>(Future<Result<T>> future) =>
+      future.then<T>((result) => result.asFuture);
+
+  /// Captures the results of a stream into a stream of [Result] values.
+  ///
+  /// The returned stream will not have any error events.
+  /// Errors from the source stream have been converted to [ErrorResult]s.
+  static Stream<Result<T>> captureStream<T>(Stream<T> source) =>
+      source.transform(new CaptureStreamTransformer<T>());
+
+  /// Releases a stream of [result] values into a stream of the results.
+  ///
+  /// `Result` values of the source stream become value or error events in
+  /// the returned stream as appropriate.
+  /// Errors from the source stream become errors in the returned stream.
+  static Stream<T> releaseStream<T>(Stream<Result<T>> source) =>
+      source.transform(new ReleaseStreamTransformer<T>());
+
+  /// Releases results added to the returned sink as data and errors on [sink].
+  ///
+  /// A [Result] added to the returned sink is added as a data or error event
+  /// on [sink]. Errors added to the returned sink are forwarded directly to
+  /// [sink] and so is the [EventSink.close] calls.
+  static EventSink<Result<T>> releaseSink<T>(EventSink<T> sink) =>
+      new ReleaseSink<T>(sink);
+
+  /// Captures the events of the returned sink into results on [sink].
+  ///
+  /// Data and error events added to the returned sink are captured into
+  /// [Result] values and added as data events on the provided [sink].
+  /// No error events are ever added to [sink].
+  ///
+  /// When the returned sink is closed, so is [sink].
+  static EventSink<T> captureSink<T>(EventSink<Result<T>> sink) =>
+      new CaptureSink<T>(sink);
+
+  /// Converts a result of a result to a single result.
+  ///
+  /// If the result is an error, or it is a `Result` value
+  /// which is then an error, then a result with that error is returned.
+  /// Otherwise both levels of results are value results, and a single
+  /// result with the value is returned.
+  static Result<T> flatten<T>(Result<Result<T>> result) {
+    if (result.isValue) return result.asValue.value;
+    return result.asError;
+  }
+
+  /// Converts a sequence of results to a result of a list.
+  ///
+  /// Returns either a list of values if [results] doesn't contain any errors,
+  /// or the first error result in [results].
+  static Result<List<T>> flattenAll<T>(Iterable<Result<T>> results) {
+    var values = <T>[];
+    for (var result in results) {
+      if (result.isValue) {
+        values.add(result.asValue.value);
+      } else {
+        return result.asError;
+      }
+    }
+    return new Result<List<T>>.value(values);
+  }
+
+  /// Whether this result is a value result.
+  ///
+  /// Always the opposite of [isError].
+  bool get isValue;
+
+  /// Whether this result is an error result.
+  ///
+  /// Always the opposite of [isValue].
+  bool get isError;
+
+  /// If this is a value result, returns itself.
+  ///
+  /// Otherwise returns `null`.
+  ValueResult<T> get asValue;
+
+  /// If this is an error result, returns itself.
+  ///
+  /// Otherwise returns `null`.
+  ErrorResult get asError;
+
+  /// Completes a completer with this result.
+  void complete(Completer<T> completer);
+
+  /// Adds this result to an [EventSink].
+  ///
+  /// Calls the sink's `add` or `addError` method as appropriate.
+  void addTo(EventSink<T> sink);
+
+  /// A future that has been completed with this result as a value or an error.
+  Future<T> get asFuture;
+}
diff --git a/lib/src/result/value.dart b/lib/src/result/value.dart
index 39fa048..edc41fb 100644
--- a/lib/src/result/value.dart
+++ b/lib/src/result/value.dart
@@ -4,17 +4,18 @@
 
 import 'dart:async';
 
-import '../result.dart';
+import 'result.dart';
 import 'error.dart';
 
 /// A result representing a returned value.
 class ValueResult<T> implements Result<T> {
+  /// The result of a successful computation.
   final T value;
 
   bool get isValue => true;
   bool get isError => false;
   ValueResult<T> get asValue => this;
-  ErrorResult<T> get asError => null;
+  ErrorResult get asError => null;
 
   ValueResult(this.value);
 
@@ -27,4 +28,9 @@
   }
 
   Future<T> get asFuture => new Future.value(value);
+
+  int get hashCode => value.hashCode ^ 0x323f1d61;
+
+  bool operator ==(Object other) =>
+      other is ValueResult && value == other.value;
 }
diff --git a/lib/src/stream_queue.dart b/lib/src/stream_queue.dart
index b9023ab..1318114 100644
--- a/lib/src/stream_queue.dart
+++ b/lib/src/stream_queue.dart
@@ -8,7 +8,7 @@
 import 'package:collection/collection.dart';
 
 import "cancelable_operation.dart";
-import "result.dart";
+import "result/result.dart";
 import "subscription_stream.dart";
 import "stream_completer.dart";
 import "stream_splitter.dart";
@@ -859,9 +859,9 @@
 /// source subscription.
 class _CancelRequest<T> implements _EventRequest<T> {
   /// Completer for the future returned by the `cancel` call.
+  /// TODO(lrn); make this Completer<void> when that is implemented.
   final _completer = new Completer();
 
-  ///
   /// When the event is completed, it needs to cancel the active subscription
   /// of the `StreamQueue` object, if any.
   final StreamQueue _streamQueue;
diff --git a/lib/src/stream_splitter.dart b/lib/src/stream_splitter.dart
index 6cec98c..ac4260d 100644
--- a/lib/src/stream_splitter.dart
+++ b/lib/src/stream_splitter.dart
@@ -5,7 +5,7 @@
 import 'dart:async';
 
 import 'future_group.dart';
-import 'result.dart';
+import 'result/result.dart';
 
 /// A class that splits a single source stream into an arbitrary number of
 /// (single-subscription) streams (called "branch") that emit the same events.
diff --git a/lib/stream_zip.dart b/lib/stream_zip.dart
deleted file mode 100644
index cdeb5c9..0000000
--- a/lib/stream_zip.dart
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-/// Import `async.dart` instead.
-@Deprecated("Will be removed in async 2.0.0.")
-library dart.pkg.async.stream_zip;
-
-export "src/stream_zip.dart";
diff --git a/pubspec.yaml b/pubspec.yaml
index 2ee2505..bb41d4f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,5 +1,5 @@
 name: async
-version: 1.13.3
+version: 2.0.0
 author: Dart Team <misc@dartlang.org>
 description: Utility functions and classes related to the 'dart:async' library.
 homepage: https://www.github.com/dart-lang/async
diff --git a/test/result/result_captureAll_test.dart b/test/result/result_captureAll_test.dart
new file mode 100644
index 0000000..172e38a
--- /dev/null
+++ b/test/result/result_captureAll_test.dart
@@ -0,0 +1,187 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "dart:async";
+import "dart:math" show Random;
+import "package:async/async.dart";
+import "package:test/test.dart";
+
+final someStack = StackTrace.current;
+Result<int> res(int n) => new Result<int>.value(n);
+Result err(n) => new ErrorResult("$n", someStack);
+
+/// Helper function creating an iterable of futures.
+Iterable<Future<int>> futures(int count, {bool throwWhen(int index)}) sync* {
+  for (int i = 0; i < count; i++) {
+    if (throwWhen != null && throwWhen(i)) {
+      yield new Future<int>.error("$i", someStack);
+    } else {
+      yield new Future<int>.value(i);
+    }
+  }
+}
+
+main() {
+  test("empty", () async {
+    var all = await Result.captureAll<int>(futures(0));
+    expect(all, []);
+  });
+
+  group("futures only,", () {
+    test("single", () async {
+      var all = await Result.captureAll<int>(futures(1));
+      expect(all, [res(0)]);
+    });
+
+    test("multiple", () async {
+      var all = await Result.captureAll<int>(futures(3));
+      expect(all, [res(0), res(1), res(2)]);
+    });
+
+    test("error only", () async {
+      var all =
+          await Result.captureAll<int>(futures(1, throwWhen: (_) => true));
+      expect(all, [err(0)]);
+    });
+
+    test("multiple error only", () async {
+      var all =
+          await Result.captureAll<int>(futures(3, throwWhen: (_) => true));
+      expect(all, [err(0), err(1), err(2)]);
+    });
+
+    test("mixed error and value", () async {
+      var all =
+          await Result.captureAll<int>(futures(4, throwWhen: (x) => x.isOdd));
+      expect(all, [res(0), err(1), res(2), err(3)]);
+    });
+
+    test("completion permutation 1-2-3", () async {
+      var cs = new List.generate(3, (_) => new Completer<int>());
+      var all = Result.captureAll<int>(cs.map((c) => c.future));
+      expect(all, completion([res(1), res(2), err(3)]));
+      await 0;
+      cs[0].complete(1);
+      await 0;
+      cs[1].complete(2);
+      await 0;
+      cs[2].completeError("3", someStack);
+    });
+
+    test("completion permutation 1-3-2", () async {
+      var cs = new List.generate(3, (_) => new Completer<int>());
+      var all = Result.captureAll<int>(cs.map((c) => c.future));
+      expect(all, completion([res(1), res(2), err(3)]));
+      await 0;
+      cs[0].complete(1);
+      await 0;
+      cs[2].completeError("3", someStack);
+      await 0;
+      cs[1].complete(2);
+    });
+
+    test("completion permutation 2-1-3", () async {
+      var cs = new List.generate(3, (_) => new Completer<int>());
+      var all = Result.captureAll<int>(cs.map((c) => c.future));
+      expect(all, completion([res(1), res(2), err(3)]));
+      await 0;
+      cs[1].complete(2);
+      await 0;
+      cs[0].complete(1);
+      await 0;
+      cs[2].completeError("3", someStack);
+    });
+
+    test("completion permutation 2-3-1", () async {
+      var cs = new List.generate(3, (_) => new Completer<int>());
+      var all = Result.captureAll<int>(cs.map((c) => c.future));
+      expect(all, completion([res(1), res(2), err(3)]));
+      await 0;
+      cs[1].complete(2);
+      await 0;
+      cs[2].completeError("3", someStack);
+      await 0;
+      cs[0].complete(1);
+    });
+
+    test("completion permutation 3-1-2", () async {
+      var cs = new List.generate(3, (_) => new Completer<int>());
+      var all = Result.captureAll<int>(cs.map((c) => c.future));
+      expect(all, completion([res(1), res(2), err(3)]));
+      await 0;
+      cs[2].completeError("3", someStack);
+      await 0;
+      cs[0].complete(1);
+      await 0;
+      cs[1].complete(2);
+    });
+
+    test("completion permutation 3-2-1", () async {
+      var cs = new List.generate(3, (_) => new Completer<int>());
+      var all = Result.captureAll<int>(cs.map((c) => c.future));
+      expect(all, completion([res(1), res(2), err(3)]));
+      await 0;
+      cs[2].completeError("3", someStack);
+      await 0;
+      cs[1].complete(2);
+      await 0;
+      cs[0].complete(1);
+    });
+
+    var seed = new Random().nextInt(0x100000000);
+    int n = 25; // max 32, otherwise rnd.nextInt(1<<n) won't work.
+    test("randomized #$n seed:${seed.toRadixString(16)}", () async {
+      var cs = new List.generate(n, (_) => new Completer<int>());
+      var all = Result.captureAll<int>(cs.map((c) => c.future));
+      var rnd = new Random(seed);
+      var throwFlags = rnd.nextInt(1 << n); // Bit-flag for throwing.
+      bool throws(index) => (throwFlags & (1 << index)) != 0;
+      var expected = new List.generate(n, (x) => throws(x) ? err(x) : res(x));
+
+      expect(all, completion(expected));
+
+      var completeFunctions = new List<Function()>.generate(n, (i) {
+        var c = cs[i];
+        return () =>
+            throws(i) ? c.completeError("$i", someStack) : c.complete(i);
+      });
+      completeFunctions.shuffle(rnd);
+      for (int i = 0; i < n; i++) {
+        await 0;
+        completeFunctions[i]();
+      }
+    });
+  });
+  group("values only,", () {
+    test("single", () async {
+      var all = await Result.captureAll<int>(<int>[1]);
+      expect(all, [res(1)]);
+    });
+    test("multiple", () async {
+      var all = await Result.captureAll<int>(<int>[1, 2, 3]);
+      expect(all, [res(1), res(2), res(3)]);
+    });
+  });
+  group("mixed futures and values,", () {
+    test("no error", () async {
+      var all = await Result.captureAll<int>(<FutureOr<int>>[
+        1,
+        new Future<int>(() => 2),
+        3,
+        new Future<int>.value(4),
+      ]);
+      expect(all, [res(1), res(2), res(3), res(4)]);
+    });
+    test("error", () async {
+      var all = await Result.captureAll<int>(<FutureOr<int>>[
+        1,
+        new Future<int>(() => 2),
+        3,
+        new Future<int>(() async => await new Future.error("4", someStack)),
+        new Future<int>.value(5)
+      ]);
+      expect(all, [res(1), res(2), res(3), err(4), res(5)]);
+    });
+  });
+}
diff --git a/test/result/result_flattenAll_test.dart b/test/result/result_flattenAll_test.dart
new file mode 100644
index 0000000..caaf668
--- /dev/null
+++ b/test/result/result_flattenAll_test.dart
@@ -0,0 +1,54 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:async/async.dart";
+import "package:test/test.dart";
+
+final someStack = StackTrace.current;
+Result<T> res<T>(T n) => new Result<T>.value(n);
+Result err(n) => new ErrorResult("$n", someStack);
+
+/// Helper function creating an iterable of results.
+Iterable<Result<int>> results(int count, {bool throwWhen(int index)}) sync* {
+  for (int i = 0; i < count; i++) {
+    if (throwWhen != null && throwWhen(i)) {
+      yield err(i);
+    } else {
+      yield res(i);
+    }
+  }
+}
+
+main() {
+  expectAll(result, expectation) {
+    if (expectation.isError) {
+      expect(result, expectation);
+    } else {
+      expect(result.isValue, true);
+      expect(result.asValue.value, expectation.asValue.value);
+    }
+  }
+
+  test("empty", () {
+    expectAll(Result.flattenAll<int>(results(0)), res([]));
+  });
+  test("single value", () {
+    expectAll(Result.flattenAll<int>(results(1)), res([0]));
+  });
+  test("single error", () {
+    expectAll(
+        Result.flattenAll<int>(results(1, throwWhen: (_) => true)), err(0));
+  });
+  test("multiple values", () {
+    expectAll(Result.flattenAll<int>(results(5)), res([0, 1, 2, 3, 4]));
+  });
+  test("multiple errors", () {
+    expectAll(Result.flattenAll<int>(results(5, throwWhen: (x) => x.isOdd)),
+        err(1)); // First error is result.
+  });
+  test("error last", () {
+    expectAll(
+        Result.flattenAll<int>(results(5, throwWhen: (x) => x == 4)), err(4));
+  });
+}
diff --git a/test/result_future_test.dart b/test/result/result_future_test.dart
similarity index 100%
rename from test/result_future_test.dart
rename to test/result/result_future_test.dart
diff --git a/test/result_test.dart b/test/result/result_test.dart
similarity index 100%
rename from test/result_test.dart
rename to test/result/result_test.dart