| Index: pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| index 8d9f708493ed2b2e974e86ca185e152cc8a40378..a86bcdefecee5fed63ab91bd425df6454e595f11 100644
|
| --- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| +++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
|
| @@ -811,7 +811,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| Expression target = node.realTarget;
|
| if (target != null) {
|
| DartType targetType = target.bestType;
|
| - if (_isAsyncFutureType(targetType)) {
|
| + if (targetType.isDartAsyncFuture) {
|
| // Future.then(closure) return type is:
|
| // 1) the returned Future type, if the closure returns a Future;
|
| // 2) Future<valueType>, if the closure returns a value.
|
| @@ -1418,11 +1418,11 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| // TODO(brianwilkerson) Determine whether this can still happen.
|
| staticType2 = _dynamicType;
|
| }
|
| +
|
| DartType staticType =
|
| - _typeSystem.getLeastUpperBound(staticType1, staticType2);
|
| - if (staticType == null) {
|
| - staticType = _dynamicType;
|
| - }
|
| + _typeSystem.getLeastUpperBound(staticType1, staticType2) ??
|
| + _dynamicType;
|
| +
|
| _recordStaticType(node, staticType);
|
| DartType propagatedType1 = expr1.propagatedType;
|
| DartType propagatedType2 = expr2.propagatedType;
|
| @@ -1519,6 +1519,9 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| : _typeProvider.iterableType;
|
| return genericType.instantiate(<DartType>[type]);
|
| } else if (body.isAsynchronous) {
|
| + if (type.isDartAsyncFutureOr) {
|
| + type = (type as InterfaceType).typeArguments[0];
|
| + }
|
| return _typeProvider.futureType
|
| .instantiate(<DartType>[type.flattenFutures(_typeSystem)]);
|
| } else {
|
| @@ -1961,44 +1964,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| argTypes.add(argumentList.arguments[i].staticType);
|
| }
|
| }
|
| -
|
| - // Special case Future<T>.then upwards inference. It has signature:
|
| - //
|
| - // <S>(T -> (S | Future<S>)) -> Future<S>
|
| - //
|
| - // Based on the first argument type, we'll pick one of these signatures:
|
| - //
|
| - // <S>(T -> S) -> Future<S>
|
| - // <S>(T -> Future<S>) -> Future<S>
|
| - //
|
| - // ... and finish the inference using that.
|
| - if (argTypes.isNotEmpty && _resolver.isFutureThen(fnType.element)) {
|
| - var firstArgType = argTypes[0];
|
| - var firstParamType = paramTypes[0] as FunctionType;
|
| - if (firstArgType is FunctionType) {
|
| - var argReturnType = firstArgType.returnType;
|
| - // Skip the inference if we have the top type. It can only lead to
|
| - // worse inference. For example, this happens when the lambda returns
|
| - // S or Future<S> in a conditional.
|
| - if (!argReturnType.isObject && !argReturnType.isDynamic) {
|
| - DartType paramReturnType = fnType.typeFormals[0].type;
|
| - if (_resolver.isSubtypeOfFuture(argReturnType)) {
|
| - // Given an argument of (T) -> Future<S>, instantiate with <S>
|
| - paramReturnType =
|
| - _typeProvider.futureType.instantiate([paramReturnType]);
|
| - }
|
| -
|
| - // Adjust the expected parameter type to have this return type.
|
| - var function = new FunctionElementImpl(firstParamType.name, -1)
|
| - ..isSynthetic = true
|
| - ..shareParameters(firstParamType.parameters)
|
| - ..returnType = paramReturnType;
|
| - function.type = new FunctionTypeImpl(function);
|
| - // Use this as the expected 1st parameter type.
|
| - paramTypes[0] = function.type;
|
| - }
|
| - }
|
| - }
|
| return ts.inferGenericFunctionCall(fnType, paramTypes, argTypes,
|
| fnType.returnType, InferenceContext.getContext(node),
|
| errorReporter: _resolver.errorReporter, errorNode: errorNode);
|
| @@ -2081,12 +2046,7 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| if (_strongMode &&
|
| (computedType.isDartCoreNull || computedType.isDynamic)) {
|
| DartType contextType = InferenceContext.getContext(body);
|
| - if (contextType is FutureUnionType) {
|
| - // TODO(jmesserly): can we do something better here?
|
| - computedType = body.isAsynchronous ? contextType.type : _dynamicType;
|
| - } else {
|
| - computedType = contextType ?? _dynamicType;
|
| - }
|
| + computedType = contextType ?? _dynamicType;
|
| recordInference = !computedType.isDynamic;
|
| }
|
|
|
| @@ -2224,23 +2184,6 @@ class StaticTypeAnalyzer extends SimpleAstVisitor<Object> {
|
| }
|
|
|
| /**
|
| - * Return `true` if the given [Type] is the `Future` form the 'dart:async'
|
| - * library.
|
| - */
|
| - bool _isAsyncFutureType(DartType type) =>
|
| - type is InterfaceType &&
|
| - type.name == "Future" &&
|
| - _isAsyncLibrary(type.element.library);
|
| -
|
| - /**
|
| - * Return `true` if the given library is the 'dart:async' library.
|
| - *
|
| - * @param library the library being tested
|
| - * @return `true` if the library is 'dart:async'
|
| - */
|
| - bool _isAsyncLibrary(LibraryElement library) => library.name == "dart.async";
|
| -
|
| - /**
|
| * Return `true` if the given library is the 'dart:html' library.
|
| *
|
| * @param library the library being tested
|
|
|