Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(156)

Side by Side Diff: pkg/analyzer/lib/src/generated/static_type_analyzer.dart

Issue 2647833002: fix #28008, fix #28009 implement FutureOr<T> (Closed)
Patch Set: Merge remote-tracking branch 'origin/master' into 28008_futureort Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library analyzer.src.generated.static_type_analyzer; 5 library analyzer.src.generated.static_type_analyzer;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; 10 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
(...skipping 793 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 DartType staticPropagatedType = 804 DartType staticPropagatedType =
805 _computePropagatedReturnType(staticMethodElement); 805 _computePropagatedReturnType(staticMethodElement);
806 _resolver.recordPropagatedTypeIfBetter(node, staticPropagatedType); 806 _resolver.recordPropagatedTypeIfBetter(node, staticPropagatedType);
807 // Check for special cases. 807 // Check for special cases.
808 bool needPropagatedType = true; 808 bool needPropagatedType = true;
809 String methodName = methodNameNode.name; 809 String methodName = methodNameNode.name;
810 if (!_strongMode && methodName == "then") { 810 if (!_strongMode && methodName == "then") {
811 Expression target = node.realTarget; 811 Expression target = node.realTarget;
812 if (target != null) { 812 if (target != null) {
813 DartType targetType = target.bestType; 813 DartType targetType = target.bestType;
814 if (_isAsyncFutureType(targetType)) { 814 if (targetType.isDartAsyncFuture) {
815 // Future.then(closure) return type is: 815 // Future.then(closure) return type is:
816 // 1) the returned Future type, if the closure returns a Future; 816 // 1) the returned Future type, if the closure returns a Future;
817 // 2) Future<valueType>, if the closure returns a value. 817 // 2) Future<valueType>, if the closure returns a value.
818 NodeList<Expression> arguments = node.argumentList.arguments; 818 NodeList<Expression> arguments = node.argumentList.arguments;
819 if (arguments.length == 1) { 819 if (arguments.length == 1) {
820 // TODO(brianwilkerson) Handle the case where both arguments are 820 // TODO(brianwilkerson) Handle the case where both arguments are
821 // provided. 821 // provided.
822 Expression closureArg = arguments[0]; 822 Expression closureArg = arguments[0];
823 if (closureArg is FunctionExpression) { 823 if (closureArg is FunctionExpression) {
824 FunctionExpression closureExpr = closureArg; 824 FunctionExpression closureExpr = closureArg;
(...skipping 586 matching lines...) Expand 10 before | Expand all | Expand 10 after
1411 DartType staticType1 = _getDefiniteType(expr1); 1411 DartType staticType1 = _getDefiniteType(expr1);
1412 DartType staticType2 = _getDefiniteType(expr2); 1412 DartType staticType2 = _getDefiniteType(expr2);
1413 if (staticType1 == null) { 1413 if (staticType1 == null) {
1414 // TODO(brianwilkerson) Determine whether this can still happen. 1414 // TODO(brianwilkerson) Determine whether this can still happen.
1415 staticType1 = _dynamicType; 1415 staticType1 = _dynamicType;
1416 } 1416 }
1417 if (staticType2 == null) { 1417 if (staticType2 == null) {
1418 // TODO(brianwilkerson) Determine whether this can still happen. 1418 // TODO(brianwilkerson) Determine whether this can still happen.
1419 staticType2 = _dynamicType; 1419 staticType2 = _dynamicType;
1420 } 1420 }
1421
1421 DartType staticType = 1422 DartType staticType =
1422 _typeSystem.getLeastUpperBound(staticType1, staticType2); 1423 _typeSystem.getLeastUpperBound(staticType1, staticType2) ??
1423 if (staticType == null) { 1424 _dynamicType;
1424 staticType = _dynamicType; 1425
1425 }
1426 _recordStaticType(node, staticType); 1426 _recordStaticType(node, staticType);
1427 DartType propagatedType1 = expr1.propagatedType; 1427 DartType propagatedType1 = expr1.propagatedType;
1428 DartType propagatedType2 = expr2.propagatedType; 1428 DartType propagatedType2 = expr2.propagatedType;
1429 if (propagatedType1 != null || propagatedType2 != null) { 1429 if (propagatedType1 != null || propagatedType2 != null) {
1430 if (propagatedType1 == null) { 1430 if (propagatedType1 == null) {
1431 propagatedType1 = staticType1; 1431 propagatedType1 = staticType1;
1432 } 1432 }
1433 if (propagatedType2 == null) { 1433 if (propagatedType2 == null) {
1434 propagatedType2 = staticType2; 1434 propagatedType2 = staticType2;
1435 } 1435 }
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
1512 * 1512 *
1513 * See also [FunctionBody.isAsynchronous], [FunctionBody.isGenerator]. 1513 * See also [FunctionBody.isAsynchronous], [FunctionBody.isGenerator].
1514 */ 1514 */
1515 DartType _computeReturnTypeOfFunction(FunctionBody body, DartType type) { 1515 DartType _computeReturnTypeOfFunction(FunctionBody body, DartType type) {
1516 if (body.isGenerator) { 1516 if (body.isGenerator) {
1517 InterfaceType genericType = body.isAsynchronous 1517 InterfaceType genericType = body.isAsynchronous
1518 ? _typeProvider.streamType 1518 ? _typeProvider.streamType
1519 : _typeProvider.iterableType; 1519 : _typeProvider.iterableType;
1520 return genericType.instantiate(<DartType>[type]); 1520 return genericType.instantiate(<DartType>[type]);
1521 } else if (body.isAsynchronous) { 1521 } else if (body.isAsynchronous) {
1522 if (type.isDartAsyncFutureOr) {
1523 type = (type as InterfaceType).typeArguments[0];
1524 }
1522 return _typeProvider.futureType 1525 return _typeProvider.futureType
1523 .instantiate(<DartType>[type.flattenFutures(_typeSystem)]); 1526 .instantiate(<DartType>[type.flattenFutures(_typeSystem)]);
1524 } else { 1527 } else {
1525 return type; 1528 return type;
1526 } 1529 }
1527 } 1530 }
1528 1531
1529 /** 1532 /**
1530 * Compute the static return type of the method or function represented by the given element. 1533 * Compute the static return type of the method or function represented by the given element.
1531 * 1534 *
(...skipping 422 matching lines...) Expand 10 before | Expand all | Expand 10 after
1954 1957
1955 List<DartType> paramTypes = <DartType>[]; 1958 List<DartType> paramTypes = <DartType>[];
1956 List<DartType> argTypes = <DartType>[]; 1959 List<DartType> argTypes = <DartType>[];
1957 for (int i = 0, length = rawParameters.length; i < length; i++) { 1960 for (int i = 0, length = rawParameters.length; i < length; i++) {
1958 ParameterElement parameter = rawParameters[i]; 1961 ParameterElement parameter = rawParameters[i];
1959 if (parameter != null) { 1962 if (parameter != null) {
1960 paramTypes.add(parameter.type); 1963 paramTypes.add(parameter.type);
1961 argTypes.add(argumentList.arguments[i].staticType); 1964 argTypes.add(argumentList.arguments[i].staticType);
1962 } 1965 }
1963 } 1966 }
1964
1965 // Special case Future<T>.then upwards inference. It has signature:
1966 //
1967 // <S>(T -> (S | Future<S>)) -> Future<S>
1968 //
1969 // Based on the first argument type, we'll pick one of these signatures:
1970 //
1971 // <S>(T -> S) -> Future<S>
1972 // <S>(T -> Future<S>) -> Future<S>
1973 //
1974 // ... and finish the inference using that.
1975 if (argTypes.isNotEmpty && _resolver.isFutureThen(fnType.element)) {
1976 var firstArgType = argTypes[0];
1977 var firstParamType = paramTypes[0] as FunctionType;
1978 if (firstArgType is FunctionType) {
1979 var argReturnType = firstArgType.returnType;
1980 // Skip the inference if we have the top type. It can only lead to
1981 // worse inference. For example, this happens when the lambda returns
1982 // S or Future<S> in a conditional.
1983 if (!argReturnType.isObject && !argReturnType.isDynamic) {
1984 DartType paramReturnType = fnType.typeFormals[0].type;
1985 if (_resolver.isSubtypeOfFuture(argReturnType)) {
1986 // Given an argument of (T) -> Future<S>, instantiate with <S>
1987 paramReturnType =
1988 _typeProvider.futureType.instantiate([paramReturnType]);
1989 }
1990
1991 // Adjust the expected parameter type to have this return type.
1992 var function = new FunctionElementImpl(firstParamType.name, -1)
1993 ..isSynthetic = true
1994 ..shareParameters(firstParamType.parameters)
1995 ..returnType = paramReturnType;
1996 function.type = new FunctionTypeImpl(function);
1997 // Use this as the expected 1st parameter type.
1998 paramTypes[0] = function.type;
1999 }
2000 }
2001 }
2002 return ts.inferGenericFunctionCall(fnType, paramTypes, argTypes, 1967 return ts.inferGenericFunctionCall(fnType, paramTypes, argTypes,
2003 fnType.returnType, InferenceContext.getContext(node), 1968 fnType.returnType, InferenceContext.getContext(node),
2004 errorReporter: _resolver.errorReporter, errorNode: errorNode); 1969 errorReporter: _resolver.errorReporter, errorNode: errorNode);
2005 } 1970 }
2006 return null; 1971 return null;
2007 } 1972 }
2008 1973
2009 /** 1974 /**
2010 * Given an instance creation of a possibly generic type, infer the type 1975 * Given an instance creation of a possibly generic type, infer the type
2011 * arguments using the current context type as well as the argument types. 1976 * arguments using the current context type as well as the argument types.
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
2074 2039
2075 // If we had a better type from the function body, use it. 2040 // If we had a better type from the function body, use it.
2076 // 2041 //
2077 // This helps in a few cases: 2042 // This helps in a few cases:
2078 // * ExpressionFunctionBody, when the surrounding context had a better type. 2043 // * ExpressionFunctionBody, when the surrounding context had a better type.
2079 // * BlockFunctionBody, if we inferred a type from yield/return. 2044 // * BlockFunctionBody, if we inferred a type from yield/return.
2080 // * we also normalize bottom to dynamic here. 2045 // * we also normalize bottom to dynamic here.
2081 if (_strongMode && 2046 if (_strongMode &&
2082 (computedType.isDartCoreNull || computedType.isDynamic)) { 2047 (computedType.isDartCoreNull || computedType.isDynamic)) {
2083 DartType contextType = InferenceContext.getContext(body); 2048 DartType contextType = InferenceContext.getContext(body);
2084 if (contextType is FutureUnionType) { 2049 computedType = contextType ?? _dynamicType;
2085 // TODO(jmesserly): can we do something better here?
2086 computedType = body.isAsynchronous ? contextType.type : _dynamicType;
2087 } else {
2088 computedType = contextType ?? _dynamicType;
2089 }
2090 recordInference = !computedType.isDynamic; 2050 recordInference = !computedType.isDynamic;
2091 } 2051 }
2092 2052
2093 computedType = _computeReturnTypeOfFunction(body, computedType); 2053 computedType = _computeReturnTypeOfFunction(body, computedType);
2094 functionElement.returnType = computedType; 2054 functionElement.returnType = computedType;
2095 _recordPropagatedTypeOfFunction(functionElement, node.body); 2055 _recordPropagatedTypeOfFunction(functionElement, node.body);
2096 _recordStaticType(node, functionElement.type); 2056 _recordStaticType(node, functionElement.type);
2097 if (recordInference) { 2057 if (recordInference) {
2098 _resolver.inferenceContext.recordInference(node, functionElement.type); 2058 _resolver.inferenceContext.recordInference(node, functionElement.type);
2099 } 2059 }
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
2217 inferredType != null && 2177 inferredType != null &&
2218 _typeProvider.nonSubtypableTypes.contains(inferredType)) { 2178 _typeProvider.nonSubtypableTypes.contains(inferredType)) {
2219 _recordStaticType(id, inferredType); 2179 _recordStaticType(id, inferredType);
2220 _recordStaticType(node, inferredType); 2180 _recordStaticType(node, inferredType);
2221 return true; 2181 return true;
2222 } 2182 }
2223 return false; 2183 return false;
2224 } 2184 }
2225 2185
2226 /** 2186 /**
2227 * Return `true` if the given [Type] is the `Future` form the 'dart:async'
2228 * library.
2229 */
2230 bool _isAsyncFutureType(DartType type) =>
2231 type is InterfaceType &&
2232 type.name == "Future" &&
2233 _isAsyncLibrary(type.element.library);
2234
2235 /**
2236 * Return `true` if the given library is the 'dart:async' library.
2237 *
2238 * @param library the library being tested
2239 * @return `true` if the library is 'dart:async'
2240 */
2241 bool _isAsyncLibrary(LibraryElement library) => library.name == "dart.async";
2242
2243 /**
2244 * Return `true` if the given library is the 'dart:html' library. 2187 * Return `true` if the given library is the 'dart:html' library.
2245 * 2188 *
2246 * @param library the library being tested 2189 * @param library the library being tested
2247 * @return `true` if the library is 'dart:html' 2190 * @return `true` if the library is 'dart:html'
2248 */ 2191 */
2249 bool _isHtmlLibrary(LibraryElement library) => 2192 bool _isHtmlLibrary(LibraryElement library) =>
2250 library != null && "dart.dom.html" == library.name; 2193 library != null && "dart.dom.html" == library.name;
2251 2194
2252 /** 2195 /**
2253 * Return `true` if the given [node] is not a type literal. 2196 * Return `true` if the given [node] is not a type literal.
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
2421 } 2364 }
2422 // merge types 2365 // merge types
2423 if (result == null) { 2366 if (result == null) {
2424 result = type; 2367 result = type;
2425 } else { 2368 } else {
2426 result = _typeSystem.getLeastUpperBound(result, type); 2369 result = _typeSystem.getLeastUpperBound(result, type);
2427 } 2370 }
2428 return null; 2371 return null;
2429 } 2372 }
2430 } 2373 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/resolver.dart ('k') | pkg/analyzer/lib/src/generated/testing/element_factory.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698