OLD | NEW |
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/token.dart'; | 10 import 'package:analyzer/dart/ast/token.dart'; |
(...skipping 1929 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1940 ParameterElement parameter = rawParameters[i]; | 1940 ParameterElement parameter = rawParameters[i]; |
1941 if (parameter != null) { | 1941 if (parameter != null) { |
1942 paramTypes.add(parameter.type); | 1942 paramTypes.add(parameter.type); |
1943 argTypes.add(argumentList.arguments[i].staticType); | 1943 argTypes.add(argumentList.arguments[i].staticType); |
1944 } | 1944 } |
1945 } | 1945 } |
1946 | 1946 |
1947 DartType returnContext = InferenceContext.getContext(node); | 1947 DartType returnContext = InferenceContext.getContext(node); |
1948 DartType returnType; | 1948 DartType returnType; |
1949 if (returnContext is FutureUnionType) { | 1949 if (returnContext is FutureUnionType) { |
1950 returnType = fnType.returnType.isDartAsyncFuture | 1950 returnType = _resolver.isSubtypeOfFuture(fnType.returnType) |
1951 ? returnContext.futureOfType | 1951 ? returnContext.futureOfType |
1952 : returnContext.type; | 1952 : returnContext.type; |
1953 } else { | 1953 } else { |
1954 returnType = returnContext; | 1954 returnType = returnContext; |
1955 } | 1955 } |
1956 | 1956 |
1957 // Special case Future<T>.then upwards inference. It has signature: | 1957 // Special case Future<T>.then upwards inference. It has signature: |
1958 // | 1958 // |
1959 // <S>(T -> (S | Future<S>)) -> Future<S> | 1959 // <S>(T -> (S | Future<S>)) -> Future<S> |
1960 // | 1960 // |
1961 // Based on the first argument type, we'll pick one of these signatures: | 1961 // Based on the first argument type, we'll pick one of these signatures: |
1962 // | 1962 // |
1963 // <S>(T -> S) -> Future<S> | 1963 // <S>(T -> S) -> Future<S> |
1964 // <S>(T -> Future<S>) -> Future<S> | 1964 // <S>(T -> Future<S>) -> Future<S> |
1965 // | 1965 // |
1966 // ... and finish the inference using that. | 1966 // ... and finish the inference using that. |
1967 if (argTypes.isNotEmpty && _resolver.isFutureThen(fnType.element)) { | 1967 if (argTypes.isNotEmpty && _resolver.isFutureThen(fnType.element)) { |
1968 var firstArgType = argTypes[0]; | 1968 var firstArgType = argTypes[0]; |
1969 var firstParamType = paramTypes[0] as FunctionType; | 1969 var firstParamType = paramTypes[0] as FunctionType; |
1970 if (firstArgType is FunctionType) { | 1970 if (firstArgType is FunctionType) { |
1971 var argReturnType = firstArgType.returnType; | 1971 var argReturnType = firstArgType.returnType; |
1972 // Skip the inference if we have the top type. It can only lead to | 1972 // Skip the inference if we have the top type. It can only lead to |
1973 // worse inference. For example, this happens when the lambda returns | 1973 // worse inference. For example, this happens when the lambda returns |
1974 // S or Future<S> in a conditional. | 1974 // S or Future<S> in a conditional. |
1975 if (!argReturnType.isObject && !argReturnType.isDynamic) { | 1975 if (!argReturnType.isObject && !argReturnType.isDynamic) { |
1976 DartType paramReturnType = fnType.typeFormals[0].type; | 1976 DartType paramReturnType = fnType.typeFormals[0].type; |
1977 if (argReturnType.isDartAsyncFuture) { | 1977 if (_resolver.isSubtypeOfFuture(argReturnType)) { |
1978 // Given an argument of (T) -> Future<S>, instantiate with <S> | 1978 // Given an argument of (T) -> Future<S>, instantiate with <S> |
1979 paramReturnType = | 1979 paramReturnType = |
1980 _typeProvider.futureType.instantiate([paramReturnType]); | 1980 _typeProvider.futureType.instantiate([paramReturnType]); |
1981 } | 1981 } |
1982 | 1982 |
1983 // Adjust the expected parameter type to have this return type. | 1983 // Adjust the expected parameter type to have this return type. |
1984 var function = new FunctionElementImpl(firstParamType.name, -1) | 1984 var function = new FunctionElementImpl(firstParamType.name, -1) |
1985 ..synthetic = true | 1985 ..synthetic = true |
1986 ..shareParameters(firstParamType.parameters) | 1986 ..shareParameters(firstParamType.parameters) |
1987 ..returnType = paramReturnType; | 1987 ..returnType = paramReturnType; |
1988 function.type = new FunctionTypeImpl(function); | 1988 function.type = new FunctionTypeImpl(function); |
1989 | |
1990 // Use this as the expected 1st parameter type. | 1989 // Use this as the expected 1st parameter type. |
1991 paramTypes[0] = function.type; | 1990 paramTypes[0] = function.type; |
1992 } | 1991 } |
1993 } | 1992 } |
1994 } | 1993 } |
1995 | |
1996 return ts.inferGenericFunctionCall( | 1994 return ts.inferGenericFunctionCall( |
1997 _typeProvider, fnType, paramTypes, argTypes, returnType); | 1995 _typeProvider, fnType, paramTypes, argTypes, returnType); |
1998 } | 1996 } |
1999 return null; | 1997 return null; |
2000 } | 1998 } |
2001 | 1999 |
2002 /** | 2000 /** |
2003 * Given an instance creation of a possibly generic type, infer the type | 2001 * Given an instance creation of a possibly generic type, infer the type |
2004 * arguments using the current context type as well as the argument types. | 2002 * arguments using the current context type as well as the argument types. |
2005 */ | 2003 */ |
2006 void _inferInstanceCreationExpression(InstanceCreationExpression node) { | 2004 void _inferInstanceCreationExpression(InstanceCreationExpression node) { |
2007 ConstructorName constructor = node.constructorName; | 2005 ConstructorName constructor = node.constructorName; |
2008 ConstructorElement originalElement = constructor.staticElement; | 2006 ConstructorElement originalElement = constructor.staticElement; |
2009 // If the constructor is generic, we'll have a ConstructorMember that | 2007 // If the constructor is generic, we'll have a ConstructorMember that |
2010 // substitutes in type arguments (possibly `dynamic`) from earlier in | 2008 // substitutes in type arguments (possibly `dynamic`) from earlier in |
2011 // resolution. | 2009 // resolution. |
2012 // | 2010 // |
2013 // Otherwise we'll have a ConstructorElement, and we can skip inference | 2011 // Otherwise we'll have a ConstructorElement, and we can skip inference |
2014 // because there's nothing to infer in a non-generic type. | 2012 // because there's nothing to infer in a non-generic type. |
2015 if (originalElement is! ConstructorMember) { | 2013 if (originalElement is! ConstructorMember) { |
2016 return; | 2014 return; |
2017 } | 2015 } |
2018 | 2016 |
| 2017 // TODO(leafp): Currently, we may re-infer types here, since we |
| 2018 // sometimes resolve multiple times. We should really check that we |
| 2019 // have not already inferred something. However, the obvious ways to |
| 2020 // check this don't work, since we may have been instantiated |
| 2021 // to bounds in an earlier phase, and we *do* want to do inference |
| 2022 // in that case. |
| 2023 |
2019 // Get back to the uninstantiated generic constructor. | 2024 // Get back to the uninstantiated generic constructor. |
2020 // TODO(jmesserly): should we store this earlier in resolution? | 2025 // TODO(jmesserly): should we store this earlier in resolution? |
2021 // Or look it up, instead of jumping backwards through the Member? | 2026 // Or look it up, instead of jumping backwards through the Member? |
2022 var rawElement = (originalElement as ConstructorMember).baseElement; | 2027 var rawElement = (originalElement as ConstructorMember).baseElement; |
2023 | 2028 |
2024 FunctionType constructorType = | 2029 FunctionType constructorType = |
2025 _constructorToGenericFunctionType(rawElement); | 2030 _constructorToGenericFunctionType(rawElement); |
2026 | 2031 |
2027 ArgumentList arguments = node.argumentList; | 2032 ArgumentList arguments = node.argumentList; |
2028 FunctionType inferred = _inferGenericInvoke( | 2033 FunctionType inferred = _inferGenericInvoke( |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2069 if (contextType is FutureUnionType) { | 2074 if (contextType is FutureUnionType) { |
2070 // TODO(jmesserly): can we do something better here? | 2075 // TODO(jmesserly): can we do something better here? |
2071 computedType = body.isAsynchronous ? contextType.type : _dynamicType; | 2076 computedType = body.isAsynchronous ? contextType.type : _dynamicType; |
2072 } else { | 2077 } else { |
2073 computedType = contextType ?? _dynamicType; | 2078 computedType = contextType ?? _dynamicType; |
2074 } | 2079 } |
2075 recordInference = !computedType.isDynamic; | 2080 recordInference = !computedType.isDynamic; |
2076 } | 2081 } |
2077 | 2082 |
2078 computedType = _computeReturnTypeOfFunction(body, computedType); | 2083 computedType = _computeReturnTypeOfFunction(body, computedType); |
2079 | |
2080 functionElement.returnType = computedType; | 2084 functionElement.returnType = computedType; |
2081 _recordPropagatedTypeOfFunction(functionElement, node.body); | 2085 _recordPropagatedTypeOfFunction(functionElement, node.body); |
2082 _recordStaticType(node, functionElement.type); | 2086 _recordStaticType(node, functionElement.type); |
2083 if (recordInference) { | 2087 if (recordInference) { |
2084 _resolver.inferenceContext.recordInference(node, functionElement.type); | 2088 _resolver.inferenceContext.recordInference(node, functionElement.type); |
2085 } | 2089 } |
2086 } | 2090 } |
2087 | 2091 |
2088 /** | 2092 /** |
2089 * Given a local variable declaration and its initializer, attempt to infer | 2093 * Given a local variable declaration and its initializer, attempt to infer |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2408 } | 2412 } |
2409 // merge types | 2413 // merge types |
2410 if (result == null) { | 2414 if (result == null) { |
2411 result = type; | 2415 result = type; |
2412 } else { | 2416 } else { |
2413 result = _typeSystem.getLeastUpperBound(_typeProvider, result, type); | 2417 result = _typeSystem.getLeastUpperBound(_typeProvider, result, type); |
2414 } | 2418 } |
2415 return null; | 2419 return null; |
2416 } | 2420 } |
2417 } | 2421 } |
OLD | NEW |