Fix runtime cast failures. (#57)

* Fix runtime cast failures.

In strong mode, a generic type instantiated with dynamic is not a
subtype of all types. You can't pass a List<dynamic> to something
expecting, say, List<int>.

These errors are usually detected statically, and most of those have
been fixed. However, sometimes this becomes a runtime cast, as in:

    main() {
      // Store a List<dynamic> in a variable of type dynamic.
      dynamic d = [];

      // Implicit runtime downcast from dynamic to List<String>.
      List<String> s = d;
    }

In order to ease the migration to strong mode, DDC has been ignoring
these cast failures when they involve certain commonly used types. We
are now in the process of actively fixing those errors.

More context: https://github.com/dart-lang/sdk/issues/27223

* Update SDK constraints.

* Use newer dev version of the SDK on Travis.

* Bump minimum SDK constraint.
diff --git a/.gitignore b/.gitignore
index 96bc6bb..e43b40f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,4 +1,5 @@
 # Files and directories created by pub
+.dart_tool/
 .packages
 .pub/
 packages
diff --git a/.travis.yml b/.travis.yml
index 269df25..4f9b88c 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,8 @@
 language: dart
 sudo: false
 dart:
-  - stable
   - dev
-  - 1.23.0
+  - 2.0.0-dev.23.0
 addons:
   # otherwise a number of tests in test/security/html_sanitizer_test.dart fail
   firefox: "latest"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5288f3b..0c20ba4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,6 +1,9 @@
-## 0.21.0+1-dev
+## 0.21.1-dev
 
-* Updated one of observable's tests to comply with dart 2 voidness semantics
+* Updated one test to comply with Dart 2 voidness semantics.
+* Fix Dart 2 runtime cast failure in `toObservable()`.
+* Loosen `ObservableList.from()` to take `Iterable`, not `Iterable<T>`. This
+  matches `List.from()` and avoids some unnecessary cast failures.
 
 ## 0.21.0
 
diff --git a/lib/src/observable_list.dart b/lib/src/observable_list.dart
index 2549f9b..b5ae6d3 100644
--- a/lib/src/observable_list.dart
+++ b/lib/src/observable_list.dart
@@ -42,8 +42,7 @@
 
   /// Creates an observable list with the elements of [other]. The order in
   /// the list will be the order provided by the iterator of [other].
-  factory ObservableList.from(Iterable<E> other) =>
-      new ObservableList<E>()..addAll(other);
+  ObservableList.from(Iterable other) : _list = new List<E>.from(other);
 
   /// The stream of summarized list changes, delivered asynchronously.
   ///
diff --git a/lib/src/to_observable.dart b/lib/src/to_observable.dart
index 3bf24b6..be83cb2 100644
--- a/lib/src/to_observable.dart
+++ b/lib/src/to_observable.dart
@@ -6,6 +6,8 @@
 
 import 'dart:collection';
 
+import 'package:dart_internal/extract_type_arguments.dart';
+
 import 'observable.dart' show Observable;
 import 'observable_list.dart' show ObservableList;
 import 'observable_map.dart' show ObservableMap;
@@ -30,22 +32,47 @@
 
 dynamic _toObservableShallow(dynamic value) {
   if (value is Observable) return value;
-  if (value is Map) return new ObservableMap.from(value);
-  if (value is Iterable) return new ObservableList.from(value);
+
+  if (value is Map) {
+    return extractMapTypeArguments(value, <K, V>() {
+      var result = new ObservableMap<K, V>.createFromType(value);
+      value.forEach((k, v) {
+        result[_toObservableDeep(k)] = _toObservableDeep(v);
+      });
+      return result;
+    });
+  }
+
+  if (value is Iterable) {
+    return extractIterableTypeArgument(
+        value, <T>() => new ObservableList<T>.from(value));
+  }
+
   return value;
 }
 
 dynamic _toObservableDeep(dynamic value) {
   if (value is Observable) return value;
+
   if (value is Map) {
-    var result = new ObservableMap.createFromType(value);
-    value.forEach((k, v) {
-      result[_toObservableDeep(k)] = _toObservableDeep(v);
+    return extractMapTypeArguments(value, <K, V>() {
+      var result = new ObservableMap<K, V>.createFromType(value);
+      value.forEach((k, v) {
+        result[_toObservableDeep(k)] = _toObservableDeep(v);
+      });
+      return result;
     });
-    return result;
   }
+
   if (value is Iterable) {
-    return new ObservableList.from(value.map(_toObservableDeep));
+    return extractIterableTypeArgument(value, <T>() {
+      var result = new ObservableList<T>();
+      for (var element in value) {
+        result.add(_toObservableDeep(element));
+      }
+      return result;
+    });
   }
+
   return value;
 }
diff --git a/pubspec.yaml b/pubspec.yaml
index ea6c9e6..f64bcdc 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,12 +1,13 @@
 name: observable
-version: 0.21.0+1-dev
+version: 0.21.1-dev
 author: Dart Team <misc@dartlang.org>
 description: Support for marking objects as observable
 homepage: https://github.com/dart-lang/observable
 environment:
-  sdk: '>=1.23.0 <2.0.0'
+  sdk: '>=2.0.0-dev.23.0 <2.0.0'
 dependencies:
   collection: '^1.11.0'
+  dart_internal: '^0.1.1'
   meta: '^1.0.4'
   quiver: '>=0.24.0 <0.29.0'
 dev_dependencies: