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

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

Issue 2260313002: Extend Future.then inference to subclasses (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: rebase Created 4 years, 4 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/token.dart'; 10 import 'package:analyzer/dart/ast/token.dart';
(...skipping 1929 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/generated/resolver.dart ('k') | pkg/analyzer/lib/src/generated/type_system.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698