Chromium Code Reviews| Index: CHANGELOG.md |
| diff --git a/CHANGELOG.md b/CHANGELOG.md |
| index b59769d32455c12691d59eca5a517bf821264727..775bcbb86a330c9dd6d751e553d7e6df7fe6dfc9 100644 |
| --- a/CHANGELOG.md |
| +++ b/CHANGELOG.md |
| @@ -33,7 +33,8 @@ |
| it is considered a subtype of every other type. |
|
eernst
2017/01/24 09:13:50
We could add the following sentence here, to addre
Bob Nystrom
2017/01/26 21:20:31
Done.
|
| Examples: |
|
eernst
2017/01/24 09:13:51
And then we might as well delete this line.
Bob Nystrom
2017/01/26 21:20:30
Done. Also came up with a more motivating example.
|
| - ``` |
| + |
| + ```dart |
| Null foo() => null; |
| int x = foo(); |
| String x = foo(); |
| @@ -43,6 +44,125 @@ |
| List<String> = bar(); |
| ``` |
| + * Introduce `covariant` modifier on parameters. Adding that indicates that the |
|
Lasse Reichstein Nielsen
2017/01/24 06:52:40
Please say very early that this is only intended f
eernst
2017/01/24 09:13:51
+1!
So at this point we could have 'Support the `
mit
2017/01/24 14:55:01
+1 for having a `### Language (strong mode only)`
Bob Nystrom
2017/01/26 21:20:31
That would be tricky because then we'd still have
|
| + parameter (and the corresponding parameter in any method that overrides it) |
| + has looser override rules which require a runtime type check to maintain |
| + soundness, but enable an architectural pattern that is useful in some code. |
| + |
| + It lets you specialize a family of classes together, like so: |
| + |
| + ```dart |
| + abstract class Predator { |
| + void chaseAndEat(covariant Prey p); |
| + } |
| + |
| + abstract class Prey {} |
| + |
| + class Cat extends Predator { |
| + void chaseAndEat(Mouse m) => ... |
| + } |
| + |
| + class Mouse extends Prey {} |
| + |
| + // Eaten by orcas. |
|
eernst
2017/01/24 09:13:51
Ought to add 'class Orca extends Predator ..', and
Bob Nystrom
2017/01/26 21:20:31
Done.
|
| + class Seal extends Prey {} |
| + ``` |
| + |
| + This isn't statically safe, because you could do: |
| + |
| + ```dart |
| + Predator predator = new Cat(); // Upcast. |
| + predator(new Seal()); // Cats can't eat seals! |
| + ``` |
| + |
| + To preserve soundness, in the body of a method that uses a covariant |
| + override (here, `Cat.chaseAndEat()`), the compiler automatically inserts |
| + a check that the parameter is of the expected type. So the compiler gives |
| + you something like: |
| + |
| + ```dart |
| + class Cat extends Predator { |
| + void chaseAndEat(o) { |
| + var m = o as Mouse; |
| + ... |
| + } |
| + } |
| + ``` |
| + |
| + Dart 1.0 allows this unsound behavior on all parameters, even though users |
| + rarely rely on it. Strong mode disallowed it initially. Now it lets you |
| + opt into in the places where you do want it using this modifier. |
|
eernst
2017/01/24 09:13:51
'opt into [it]..', or maybe just 'it lets you use
Bob Nystrom
2017/01/26 21:20:31
Done.
|
| + |
| + * Change instantiate-to-bounds rules for generic type parameters. If you leave |
|
Leaf
2017/01/24 07:55:27
"for generic type parameters when running in stron
eernst
2017/01/24 09:13:51
With a separate section for strong mode, this shou
Bob Nystrom
2017/01/26 21:20:31
Done.
|
| + off the type parameters from a generic type, we need to decide what to fill |
| + them in with. Dart 1.0 says just use `dynamic`, but that isn't sound: |
| + |
| + ```dart |
| + class Abser<T extends num> { |
| + void absThis(T n) { n.abs(); } |
| + } |
| + |
| + var a = new Abser(); // A<dynamic>. |
|
eernst
2017/01/24 09:13:51
'// Abser<dynamic>', presumably.
Bob Nystrom
2017/01/26 21:20:31
Done.
|
| + a.absThis("not a num"); |
| + ``` |
| + |
| + We want the body of `absThis()` to be able to safely assume `n` is at |
| + least a `num` -- that's why there's a constraint on T, after all. Implicitly |
| + using `dynamic` as the type parameter in this example breaks that. |
| + |
| + Instead, strong mode uses the bound. In the above example, it fills it in |
| + with `num`, and then the second line where a string is passed becomes a |
| + static error. |
| + |
| + However, there are some cases where it is hard to figure out what that |
| + default bound should be: |
| + |
| + ```dart |
| + class RuhRoh<T extends Comparable<T>> {} |
| + ``` |
| + |
| + Strong mode's initial behavior sometimes produced surprising, unintended |
| + results. For 1.22, we take a simpler approach and then report an error if |
| + a good default type argument can't be found. |
| + |
| +### Core libraries |
| + |
| + * Define `FutureOr<T>` for code that works with either a future or an |
| + immediate value of some type. Some APIs are "polymorphic over asynchrony". |
| + For example, say you have some interface for doing manipulations on text: |
| + |
| + ```dart |
| + abstract class StringSwizzler { |
| + ??? swizzle(String input); |
| + } |
| + ``` |
|
Lasse Reichstein Nielsen
2017/01/24 06:52:40
Please, please, please do not use this example. Th
Leaf
2017/01/24 07:55:27
+1 Future.value, Future.then are both good example
Bob Nystrom
2017/01/26 21:20:31
Came up with a different example. I do think the o
|
| + |
| + Users can implement this to do their own string manipulations. You'd like |
| + users to be able to write `swizzle()` methods that are synchronous or |
| + asynchronous. Either is fine. (Barback transformers are a concrete example |
| + of this.) What is the return type of this method? |
|
Lasse Reichstein Nielsen
2017/01/24 06:52:40
Again, not a choice that I recommend. I'd probably
Bob Nystrom
2017/01/26 21:20:31
Yup, fair point. Came up with a better example.
|
| + |
| + Now, it would be: |
| + |
| + ```dart |
| + abstract class StringSwizzler { |
| + FutureOr<String> swizzle(String input); |
| + } |
| + ``` |
| + |
| + In this case, that's not super useful beyond just stating a more precise |
| + type for readers of the code. It does give you a little better error |
| + checking in code that uses the result of that. |
| + |
| + But this becomes really important in generic methods like `Future.then()` |
| + where you take a callback whose return type is `FutureOr<T>`. In those |
| + cases, having the type system understand this magical union type gives you |
| + much better type inference for the type argument of the method. |
| + |
| + Previously, strong mode had hard-coded rules for handling `Future.then()` |
| + specifically. `FutureOr<T>` exposes that functionality so third-party APIs |
| + can take advantage of it. |
| + |
| ### Tool changes |
| * Dart2Js |