| Index: pkg/analyzer/lib/src/generated/type_system.dart
|
| diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
|
| index 1abf232d518fffbe778f29b558fdeb9853f5e3e3..5fe01809c919444f19301184009e7854ca4b0681 100644
|
| --- a/pkg/analyzer/lib/src/generated/type_system.dart
|
| +++ b/pkg/analyzer/lib/src/generated/type_system.dart
|
| @@ -1607,21 +1607,14 @@ class FutureUnionType extends TypeImpl {
|
| final List<DartType> _types;
|
|
|
| /**
|
| - * Creates a union of `Future< flatten(T) > | flatten(T)`.
|
| + * Creates a union of `Future<T> | T`.
|
| */
|
| - factory FutureUnionType(
|
| - DartType type, TypeProvider provider, TypeSystem system) {
|
| - type = type.flattenFutures(system);
|
| -
|
| - // The order of these types is important: T could be a type variable, so
|
| - // we want to try and match `Future<T>` before we try and match `T`.
|
| - return new FutureUnionType._([
|
| - provider.futureType.instantiate([type]),
|
| - type
|
| - ]);
|
| - }
|
| -
|
| - FutureUnionType._(this._types) : super(null, null);
|
| + FutureUnionType._(DartType type, TypeProvider provider, TypeSystem system)
|
| + : _types = [
|
| + provider.futureType.instantiate([type]),
|
| + type
|
| + ],
|
| + super(null, null);
|
|
|
| DartType get futureOfType => _types[0];
|
|
|
| @@ -1676,15 +1669,39 @@ class FutureUnionType extends TypeImpl {
|
| throw new UnsupportedError('Future unions are not used in typedefs');
|
|
|
| /**
|
| - * Creates a union of `flatten(T) | Future<flatten(T)>`, unless `T` is
|
| - * already a future-union, in which case it simply returns `T`
|
| + * Creates a union of `T | Future<T>`, unless `T` is already a future or a
|
| + * future-union, in which case it simply returns `T`.
|
| + *
|
| + * Conceptually this is used as the inverse of the `flatten(T)` operation,
|
| + * defined as:
|
| + *
|
| + * - `flatten(Future<T>) -> T`
|
| + * - `flatten(T) -> T`
|
| + *
|
| + * Thus the inverse will give us `T | Future<T>`.
|
| + *
|
| + * If [type] is top (dynamic or Object) then the resulting union type is
|
| + * equivalent to top, so we simply return it.
|
| + *
|
| + * For a similar reason `Future<T> | Future<Future<T>>` is equivalent to just
|
| + * `Future<T>`, so we return it. Note that it is not possible to get a
|
| + * `Future<T>` as a result of `flatten`, so a this case likely indicates a
|
| + * type error in the code, but it will be reported elsewhere.
|
| */
|
| static DartType from(
|
| DartType type, TypeProvider provider, TypeSystem system) {
|
| + if (_isTop(type)) {
|
| + return type;
|
| + }
|
| + if (!identical(type, type.flattenFutures(system))) {
|
| + // As noted above, this most likely represents erroneous input.
|
| + return type;
|
| + }
|
| +
|
| if (type is FutureUnionType) {
|
| return type;
|
| }
|
| - return new FutureUnionType(type, provider, system);
|
| + return new FutureUnionType._(type, provider, system);
|
| }
|
| }
|
|
|
|
|