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

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

Issue 2208953002: fix #25944, improve Future.then inference (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: cleanup unused code 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.resolver; 5 library analyzer.src.generated.resolver;
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 4671 matching lines...) Expand 10 before | Expand all | Expand 10 after
4682 * of all return statements in a lambda. 4682 * of all return statements in a lambda.
4683 * 4683 *
4684 * This will always be kept in sync with [_returnStack]. 4684 * This will always be kept in sync with [_returnStack].
4685 */ 4685 */
4686 final List<DartType> _inferredReturn = <DartType>[]; 4686 final List<DartType> _inferredReturn = <DartType>[];
4687 4687
4688 /** 4688 /**
4689 * A stack of return types for all of the enclosing 4689 * A stack of return types for all of the enclosing
4690 * functions and methods. 4690 * functions and methods.
4691 */ 4691 */
4692 // TODO(leafp) Handle the implicit union type for Futures 4692 final List<TypeContext> _returnStack = <TypeContext>[];
4693 // https://github.com/dart-lang/sdk/issues/25322
4694 final List<DartType> _returnStack = <DartType>[];
4695 4693
4696 InferenceContext._(this._errorReporter, TypeProvider typeProvider, 4694 InferenceContext._(this._errorReporter, TypeProvider typeProvider,
4697 this._typeSystem, this._inferenceHints) 4695 this._typeSystem, this._inferenceHints)
4698 : _typeProvider = typeProvider; 4696 : _typeProvider = typeProvider;
4699 4697
4700 /** 4698 /**
4701 * Get the return type of the current enclosing function, if any. 4699 * Get the return type of the current enclosing function, if any.
4702 * 4700 *
4703 * The type returned for a function is the type that is expected 4701 * The type returned for a function is the type that is expected
4704 * to be used in a return or yield context. For ordinary functions 4702 * to be used in a return or yield context. For ordinary functions
4705 * this is the same as the return type of the function. For async 4703 * this is the same as the return type of the function. For async
4706 * functions returning Future<T> and for generator functions 4704 * functions returning Future<T> and for generator functions
4707 * returning Stream<T> or Iterable<T>, this is T. 4705 * returning Stream<T> or Iterable<T>, this is T.
4708 */ 4706 */
4709 DartType get returnContext => 4707 TypeContext get returnContext =>
4710 _returnStack.isNotEmpty ? _returnStack.last : null; 4708 _returnStack.isNotEmpty ? _returnStack.last : null;
4711 4709
4712 /** 4710 /**
4713 * Records the type of the expression of a return statement. 4711 * Records the type of the expression of a return statement.
4714 * 4712 *
4715 * This will be used for inferring a block bodied lambda, if no context 4713 * This will be used for inferring a block bodied lambda, if no context
4716 * type was available. 4714 * type was available.
4717 */ 4715 */
4718 void addReturnOrYieldType(DartType type) { 4716 void addReturnOrYieldType(DartType type) {
4719 if (_returnStack.isEmpty) { 4717 if (_returnStack.isEmpty) {
4720 return; 4718 return;
4721 } 4719 }
4722 DartType context = _returnStack.last; 4720 TypeContext context = _returnStack.last;
4723 if (context == null || context.isDynamic) { 4721 if (context == null || context is DartType && context.isDynamic) {
4724 DartType inferred = _inferredReturn.last; 4722 DartType inferred = _inferredReturn.last;
4725 inferred = _typeSystem.getLeastUpperBound(_typeProvider, type, inferred); 4723 inferred = _typeSystem.getLeastUpperBound(_typeProvider, inferred, type);
4726 _inferredReturn[_inferredReturn.length - 1] = inferred; 4724 _inferredReturn[_inferredReturn.length - 1] = inferred;
4727 } 4725 }
4728 } 4726 }
4729 4727
4730 /** 4728 /**
4731 * Match type [t1] against type [t2] as follows. 4729 * Match type [t1] against type [t2] as follows.
4732 * If `t1 = I<dynamic, ..., dynamic>`, then look for a supertype 4730 * If `t1 = I<dynamic, ..., dynamic>`, then look for a supertype
4733 * of t1 of the form `K<S0, ..., Sm>` where `t2 = K<S0', ..., Sm'>` 4731 * of t1 of the form `K<S0, ..., Sm>` where `t2 = K<S0', ..., Sm'>`
4734 * If the supertype exists, use the constraints `S0 <: S0', ... Sm <: Sm'` 4732 * If the supertype exists, use the constraints `S0 <: S0', ... Sm <: Sm'`
4735 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`, 4733 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`,
(...skipping 19 matching lines...) Expand all
4755 if (!inferred.isBottom) { 4753 if (!inferred.isBottom) {
4756 setType(node, inferred); 4754 setType(node, inferred);
4757 } 4755 }
4758 } 4756 }
4759 } 4757 }
4760 4758
4761 /** 4759 /**
4762 * Push a block function body's return type onto the return stack. 4760 * Push a block function body's return type onto the return stack.
4763 */ 4761 */
4764 void pushReturnContext(BlockFunctionBody node) { 4762 void pushReturnContext(BlockFunctionBody node) {
4765 DartType returnType = getType(node); 4763 _returnStack.add(getType(node));
4766 _returnStack.add(returnType);
4767 _inferredReturn.add(BottomTypeImpl.instance); 4764 _inferredReturn.add(BottomTypeImpl.instance);
4768 } 4765 }
4769 4766
4770 /** 4767 /**
4771 * Place an info node into the error stream indicating that a 4768 * Place an info node into the error stream indicating that a
4772 * [type] has been inferred as the type of [node]. 4769 * [type] has been inferred as the type of [node].
4773 */ 4770 */
4774 void recordInference(Expression node, DartType type) { 4771 void recordInference(Expression node, DartType type) {
4775 if (!_inferenceHints) { 4772 if (!_inferenceHints) {
4776 return; 4773 return;
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
4898 } 4895 }
4899 4896
4900 /** 4897 /**
4901 * Clear the type information assocated with [node]. 4898 * Clear the type information assocated with [node].
4902 */ 4899 */
4903 static void clearType(AstNode node) { 4900 static void clearType(AstNode node) {
4904 node?.setProperty(_typeProperty, null); 4901 node?.setProperty(_typeProperty, null);
4905 } 4902 }
4906 4903
4907 /** 4904 /**
4905 * Look for a single contextual type attached to [node], and returns the type
4906 * if found, otherwise null.
4907 *
4908 * If [node] has a contextual union type like `T | Future<T>` this will
4909 * simplify it to only return `T`. If the caller can handle a union type,
4910 * [getType] should be used instead.
4911 */
4912 static DartType getNonFutureType(AstNode node) {
Leaf 2016/08/05 22:32:35 I don't love this name. It seems to be that it wo
Jennifer Messerly 2016/08/08 21:59:26 Great idea! Yeah I didn't like those names either.
4913 TypeContext t = getType(node);
4914 if (t is FutureUnionTypeContext) {
4915 return t.type;
4916 }
4917 return t;
4918 }
4919
4920 /**
4908 * Look for contextual type information attached to [node]. Returns 4921 * Look for contextual type information attached to [node]. Returns
4909 * the type if found, otherwise null. 4922 * the type if found, otherwise null.
4910 */ 4923 */
4911 static DartType getType(AstNode node) => node?.getProperty(_typeProperty); 4924 static TypeContext getType(AstNode node) => node?.getProperty(_typeProperty);
4925
4926 /**
4927 * Like [getType] but expands a union type into a list of types.
4928 */
4929 static Iterable<DartType> getTypes(AstNode node) {
4930 TypeContext t = getType(node);
4931 if (t == null) {
4932 return DartType.EMPTY_LIST;
4933 }
4934 if (t is FutureUnionTypeContext) {
4935 return t.types;
4936 }
4937 return <DartType>[t];
4938 }
4912 4939
4913 /** 4940 /**
4914 * Attach contextual type information [type] to [node] for use during 4941 * Attach contextual type information [type] to [node] for use during
4915 * inference. 4942 * inference.
4916 */ 4943 */
4917 static void setType(AstNode node, DartType type) { 4944 static void setType(AstNode node, TypeContext type) {
4918 node?.setProperty(_typeProperty, type); 4945 node?.setProperty(_typeProperty, type);
4919 } 4946 }
4920 4947
4921 /** 4948 /**
4922 * Attach contextual type information [type] to [node] for use during 4949 * Attach contextual type information [type] to [node] for use during
4923 * inference. 4950 * inference.
4924 */ 4951 */
4925 static void setTypeFromNode(AstNode innerNode, AstNode outerNode) { 4952 static void setTypeFromNode(AstNode innerNode, AstNode outerNode) {
4926 setType(innerNode, getType(outerNode)); 4953 setType(innerNode, getType(outerNode));
4927 } 4954 }
(...skipping 996 matching lines...) Expand 10 before | Expand all | Expand 10 after
5924 assert(parent is PartOfDirective); 5951 assert(parent is PartOfDirective);
5925 } else { 5952 } else {
5926 elementAnnotationImpl.annotationAst = 5953 elementAnnotationImpl.annotationAst =
5927 new ConstantAstCloner().cloneNode(node); 5954 new ConstantAstCloner().cloneNode(node);
5928 } 5955 }
5929 return null; 5956 return null;
5930 } 5957 }
5931 5958
5932 @override 5959 @override
5933 Object visitArgumentList(ArgumentList node) { 5960 Object visitArgumentList(ArgumentList node) {
5934 DartType callerType = InferenceContext.getType(node); 5961 DartType callerType = InferenceContext.getNonFutureType(node);
5935 if (callerType is FunctionType) { 5962 if (callerType is FunctionType) {
5936 Map<String, DartType> namedParameterTypes = 5963 Map<String, DartType> namedParameterTypes =
5937 callerType.namedParameterTypes; 5964 callerType.namedParameterTypes;
5938 List<DartType> normalParameterTypes = callerType.normalParameterTypes; 5965 List<DartType> normalParameterTypes = callerType.normalParameterTypes;
5939 List<DartType> optionalParameterTypes = callerType.optionalParameterTypes; 5966 List<DartType> optionalParameterTypes = callerType.optionalParameterTypes;
5940 int normalCount = normalParameterTypes.length; 5967 int normalCount = normalParameterTypes.length;
5941 int optionalCount = optionalParameterTypes.length; 5968 int optionalCount = optionalParameterTypes.length;
5942 5969
5943 NodeList<Expression> arguments = node.arguments; 5970 NodeList<Expression> arguments = node.arguments;
5944 Iterable<Expression> positional = 5971 Iterable<Expression> positional =
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
6000 node.rightHandSide, node.leftHandSide.staticType); 6027 node.rightHandSide, node.leftHandSide.staticType);
6001 } 6028 }
6002 node.rightHandSide?.accept(this); 6029 node.rightHandSide?.accept(this);
6003 node.accept(elementResolver); 6030 node.accept(elementResolver);
6004 node.accept(typeAnalyzer); 6031 node.accept(typeAnalyzer);
6005 return null; 6032 return null;
6006 } 6033 }
6007 6034
6008 @override 6035 @override
6009 Object visitAwaitExpression(AwaitExpression node) { 6036 Object visitAwaitExpression(AwaitExpression node) {
6010 // TODO(leafp): Handle the implicit union type here 6037 TypeContext contextType = InferenceContext.getType(node);
6011 // https://github.com/dart-lang/sdk/issues/25322
6012 DartType contextType = InferenceContext.getType(node);
6013 if (contextType != null) { 6038 if (contextType != null) {
6014 InterfaceType futureT = typeProvider.futureType 6039 var futureUnion =
6015 .instantiate([contextType.flattenFutures(typeSystem)]); 6040 FutureUnionTypeContext.from(contextType, typeProvider, typeSystem);
6016 InferenceContext.setType(node.expression, futureT); 6041 InferenceContext.setType(node.expression, futureUnion);
6017 } 6042 }
6018 return super.visitAwaitExpression(node); 6043 return super.visitAwaitExpression(node);
6019 } 6044 }
6020 6045
6021 @override 6046 @override
6022 Object visitBinaryExpression(BinaryExpression node) { 6047 Object visitBinaryExpression(BinaryExpression node) {
6023 TokenType operatorType = node.operator.type; 6048 TokenType operatorType = node.operator.type;
6024 Expression leftOperand = node.leftOperand; 6049 Expression leftOperand = node.leftOperand;
6025 Expression rightOperand = node.rightOperand; 6050 Expression rightOperand = node.rightOperand;
6026 if (operatorType == TokenType.AMPERSAND_AMPERSAND) { 6051 if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
(...skipping 496 matching lines...) Expand 10 before | Expand all | Expand 10 after
6523 6548
6524 @override 6549 @override
6525 Object visitFunctionExpression(FunctionExpression node) { 6550 Object visitFunctionExpression(FunctionExpression node) {
6526 ExecutableElement outerFunction = _enclosingFunction; 6551 ExecutableElement outerFunction = _enclosingFunction;
6527 FunctionBody outerFunctionBody = _currentFunctionBody; 6552 FunctionBody outerFunctionBody = _currentFunctionBody;
6528 try { 6553 try {
6529 _currentFunctionBody = node.body; 6554 _currentFunctionBody = node.body;
6530 _enclosingFunction = node.element; 6555 _enclosingFunction = node.element;
6531 _overrideManager.enterScope(); 6556 _overrideManager.enterScope();
6532 try { 6557 try {
6533 DartType functionType = InferenceContext.getType(node); 6558 DartType functionType = InferenceContext.getNonFutureType(node);
6534 if (functionType is FunctionType) { 6559 if (functionType is FunctionType) {
6535 functionType = 6560 functionType =
6536 matchFunctionTypeParameters(node.typeParameters, functionType); 6561 matchFunctionTypeParameters(node.typeParameters, functionType);
6537 if (functionType is FunctionType) { 6562 if (functionType is FunctionType) {
6538 _inferFormalParameterList(node.parameters, functionType); 6563 _inferFormalParameterList(node.parameters, functionType);
6539 DartType returnType = 6564
6540 _computeReturnOrYieldType(functionType.returnType); 6565 TypeContext returnType;
6566 if (_isFutureThenLambda(node)) {
6567 var futureThenType =
6568 InferenceContext.getType(node.parent) as FunctionType;
6569
6570 // Pretend the return type of Future<T>.then<S> first parameter is
6571 //
6572 // T -> (S | Future<S>)
6573 //
6574 // We can't represent this in Dart so we populate it here during
6575 // inference.
6576 returnType = FutureUnionTypeContext.from(
6577 futureThenType.returnType, typeProvider, typeSystem);
6578 } else {
6579 returnType = _computeReturnOrYieldType(functionType.returnType);
6580 }
6581
6541 InferenceContext.setType(node.body, returnType); 6582 InferenceContext.setType(node.body, returnType);
6542 } 6583 }
6543 } 6584 }
6544 super.visitFunctionExpression(node); 6585 super.visitFunctionExpression(node);
6545 } finally { 6586 } finally {
6546 _overrideManager.exitScope(); 6587 _overrideManager.exitScope();
6547 } 6588 }
6548 } finally { 6589 } finally {
6549 _currentFunctionBody = outerFunctionBody; 6590 _currentFunctionBody = outerFunctionBody;
6550 _enclosingFunction = outerFunction; 6591 _enclosingFunction = outerFunction;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
6646 perBranchOverrides.add(elseOverrides); 6687 perBranchOverrides.add(elseOverrides);
6647 _overrideManager.mergeOverrides(perBranchOverrides); 6688 _overrideManager.mergeOverrides(perBranchOverrides);
6648 } 6689 }
6649 return null; 6690 return null;
6650 } 6691 }
6651 6692
6652 @override 6693 @override
6653 Object visitInstanceCreationExpression(InstanceCreationExpression node) { 6694 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
6654 TypeName classTypeName = node.constructorName.type; 6695 TypeName classTypeName = node.constructorName.type;
6655 if (classTypeName.typeArguments == null) { 6696 if (classTypeName.typeArguments == null) {
6656 DartType contextType = InferenceContext.getType(node); 6697 // Given a union of context types ` T0 | T1 | ... | Tn`, find the first
6657 if (contextType is InterfaceType && 6698 // valid instantiation `new C<Ti>`, if it exists.
6658 contextType.typeArguments != null && 6699 // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>`
6659 contextType.typeArguments.length > 0) { 6700 // will become a valid possibility. Right now the only allowed union is
6660 // TODO(jmesserly): for generic methods we use the 6701 // `T | Future<T>` so we can take a simple approach.
6661 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to 6702 for (var contextType in InferenceContext.getTypes(node)) {
6662 // be a tad more powerful than matchTypes. 6703 if (contextType is InterfaceType &&
6663 // 6704 contextType.typeArguments != null &&
6664 // For example it can infer this case: 6705 contextType.typeArguments.isNotEmpty) {
6665 // 6706 // TODO(jmesserly): for generic methods we use the
6666 // class E<S, T> extends A<C<S>, T> { ... } 6707 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to
6667 // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello"); 6708 // be a tad more powerful than matchTypes.
6668 // 6709 //
6669 // See _inferArgumentTypesFromContext in this file for use of it. 6710 // For example it can infer this case:
6670 List<DartType> targs = 6711 //
6671 inferenceContext.matchTypes(classTypeName.type, contextType); 6712 // class E<S, T> extends A<C<S>, T> { ... }
6672 if (targs != null && targs.any((t) => !t.isDynamic)) { 6713 // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello");
6673 ClassElement classElement = classTypeName.type.element; 6714 //
6674 InterfaceType rawType = classElement.type; 6715 // See _inferArgumentTypesFromContext in this file for use of it.
6675 InterfaceType fullType = 6716 List<DartType> targs =
6676 rawType.substitute2(targs, rawType.typeArguments); 6717 inferenceContext.matchTypes(classTypeName.type, contextType);
6677 // The element resolver uses the type on the constructor name, so 6718 if (targs != null && targs.any((t) => !t.isDynamic)) {
6678 // infer it first 6719 ClassElement classElement = classTypeName.type.element;
6679 typeAnalyzer.inferConstructorName(node.constructorName, fullType); 6720 InterfaceType rawType = classElement.type;
6721 InterfaceType fullType =
6722 rawType.substitute2(targs, rawType.typeArguments);
6723 // The element resolver uses the type on the constructor name, so
6724 // infer it first
6725 typeAnalyzer.inferConstructorName(node.constructorName, fullType);
6726 break;
6727 }
6680 } 6728 }
6681 } 6729 }
6682 } 6730 }
6683 node.constructorName?.accept(this); 6731 node.constructorName?.accept(this);
6684 FunctionType constructorType = node.constructorName.staticElement?.type; 6732 FunctionType constructorType = node.constructorName.staticElement?.type;
6685 if (constructorType != null) { 6733 if (constructorType != null) {
6686 InferenceContext.setType(node.argumentList, constructorType); 6734 InferenceContext.setType(node.argumentList, constructorType);
6687 } 6735 }
6688 node.argumentList?.accept(this); 6736 node.argumentList?.accept(this);
6689 node.accept(elementResolver); 6737 node.accept(elementResolver);
6690 node.accept(typeAnalyzer); 6738 node.accept(typeAnalyzer);
6691 return null; 6739 return null;
6692 } 6740 }
6693 6741
6694 @override 6742 @override
6695 Object visitLabel(Label node) => null; 6743 Object visitLabel(Label node) => null;
6696 6744
6697 @override 6745 @override
6698 Object visitLibraryIdentifier(LibraryIdentifier node) => null; 6746 Object visitLibraryIdentifier(LibraryIdentifier node) => null;
6699 6747
6700 @override 6748 @override
6701 Object visitListLiteral(ListLiteral node) { 6749 Object visitListLiteral(ListLiteral node) {
6702 DartType contextType = InferenceContext.getType(node); 6750 DartType contextType = InferenceContext.getNonFutureType(node);
6703 List<DartType> targs = null; 6751 List<DartType> targs = null;
6704 if (node.typeArguments != null) { 6752 if (node.typeArguments != null) {
6705 targs = node.typeArguments.arguments.map((t) => t.type).toList(); 6753 targs = node.typeArguments.arguments.map((t) => t.type).toList();
6706 } else if (contextType is InterfaceType) { 6754 } else if (contextType is InterfaceType) {
6707 InterfaceType listD = 6755 InterfaceType listD =
6708 typeProvider.listType.instantiate([typeProvider.dynamicType]); 6756 typeProvider.listType.instantiate([typeProvider.dynamicType]);
6709 targs = inferenceContext.matchTypes(listD, contextType); 6757 targs = inferenceContext.matchTypes(listD, contextType);
6710 } 6758 }
6711 if (targs != null && targs.length == 1 && !targs[0].isDynamic) { 6759 if (targs != null && targs.length == 1 && !targs[0].isDynamic) {
6712 DartType eType = targs[0]; 6760 DartType eType = targs[0];
6713 InterfaceType listT = typeProvider.listType.instantiate([eType]); 6761 InterfaceType listT = typeProvider.listType.instantiate([eType]);
6714 for (Expression child in node.elements) { 6762 for (Expression child in node.elements) {
6715 InferenceContext.setType(child, eType); 6763 InferenceContext.setType(child, eType);
6716 } 6764 }
6717 InferenceContext.setType(node, listT); 6765 InferenceContext.setType(node, listT);
6718 } else { 6766 } else {
6719 InferenceContext.clearType(node); 6767 InferenceContext.clearType(node);
6720 } 6768 }
6721 super.visitListLiteral(node); 6769 super.visitListLiteral(node);
6722 return null; 6770 return null;
6723 } 6771 }
6724 6772
6725 @override 6773 @override
6726 Object visitMapLiteral(MapLiteral node) { 6774 Object visitMapLiteral(MapLiteral node) {
6727 DartType contextType = InferenceContext.getType(node); 6775 DartType contextType = InferenceContext.getNonFutureType(node);
6728 List<DartType> targs = null; 6776 List<DartType> targs = null;
6729 if (node.typeArguments != null) { 6777 if (node.typeArguments != null) {
6730 targs = node.typeArguments.arguments.map((t) => t.type).toList(); 6778 targs = node.typeArguments.arguments.map((t) => t.type).toList();
6731 } else if (contextType is InterfaceType) { 6779 } else if (contextType is InterfaceType) {
6732 InterfaceType mapD = typeProvider.mapType 6780 InterfaceType mapD = typeProvider.mapType
6733 .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]); 6781 .instantiate([typeProvider.dynamicType, typeProvider.dynamicType]);
6734 targs = inferenceContext.matchTypes(mapD, contextType); 6782 targs = inferenceContext.matchTypes(mapD, contextType);
6735 } 6783 }
6736 if (targs != null && targs.length == 2 && targs.any((t) => !t.isDynamic)) { 6784 if (targs != null && targs.length == 2 && targs.any((t) => !t.isDynamic)) {
6737 DartType kType = targs[0]; 6785 DartType kType = targs[0];
(...skipping 11 matching lines...) Expand all
6749 return null; 6797 return null;
6750 } 6798 }
6751 6799
6752 @override 6800 @override
6753 Object visitMethodDeclaration(MethodDeclaration node) { 6801 Object visitMethodDeclaration(MethodDeclaration node) {
6754 ExecutableElement outerFunction = _enclosingFunction; 6802 ExecutableElement outerFunction = _enclosingFunction;
6755 FunctionBody outerFunctionBody = _currentFunctionBody; 6803 FunctionBody outerFunctionBody = _currentFunctionBody;
6756 try { 6804 try {
6757 _currentFunctionBody = node.body; 6805 _currentFunctionBody = node.body;
6758 _enclosingFunction = node.element; 6806 _enclosingFunction = node.element;
6759 DartType returnType = 6807 TypeContext returnType =
6760 _computeReturnOrYieldType(_enclosingFunction.type?.returnType); 6808 _computeReturnOrYieldType(_enclosingFunction.type?.returnType);
6761 InferenceContext.setType(node.body, returnType); 6809 InferenceContext.setType(node.body, returnType);
6762 super.visitMethodDeclaration(node); 6810 super.visitMethodDeclaration(node);
6763 } finally { 6811 } finally {
6764 _currentFunctionBody = outerFunctionBody; 6812 _currentFunctionBody = outerFunctionBody;
6765 _enclosingFunction = outerFunction; 6813 _enclosingFunction = outerFunction;
6766 } 6814 }
6767 return null; 6815 return null;
6768 } 6816 }
6769 6817
(...skipping 13 matching lines...) Expand all
6783 node.typeArguments?.accept(this); 6831 node.typeArguments?.accept(this);
6784 node.accept(elementResolver); 6832 node.accept(elementResolver);
6785 _inferArgumentTypesFromContext(node); 6833 _inferArgumentTypesFromContext(node);
6786 node.argumentList?.accept(this); 6834 node.argumentList?.accept(this);
6787 node.accept(typeAnalyzer); 6835 node.accept(typeAnalyzer);
6788 return null; 6836 return null;
6789 } 6837 }
6790 6838
6791 @override 6839 @override
6792 Object visitNamedExpression(NamedExpression node) { 6840 Object visitNamedExpression(NamedExpression node) {
6793 InferenceContext.setType(node.expression, InferenceContext.getType(node)); 6841 InferenceContext.setTypeFromNode(node.expression, node);
6794 return super.visitNamedExpression(node); 6842 return super.visitNamedExpression(node);
6795 } 6843 }
6796 6844
6797 @override 6845 @override
6798 Object visitNode(AstNode node) { 6846 Object visitNode(AstNode node) {
6799 node.visitChildren(this); 6847 node.visitChildren(this);
6800 node.accept(elementResolver); 6848 node.accept(elementResolver);
6801 node.accept(typeAnalyzer); 6849 node.accept(typeAnalyzer);
6802 return null; 6850 return null;
6803 } 6851 }
6804 6852
6805 @override 6853 @override
6806 Object visitParenthesizedExpression(ParenthesizedExpression node) { 6854 Object visitParenthesizedExpression(ParenthesizedExpression node) {
6807 InferenceContext.setType(node.expression, InferenceContext.getType(node)); 6855 InferenceContext.setTypeFromNode(node.expression, node);
6808 return super.visitParenthesizedExpression(node); 6856 return super.visitParenthesizedExpression(node);
6809 } 6857 }
6810 6858
6811 @override 6859 @override
6812 Object visitPrefixedIdentifier(PrefixedIdentifier node) { 6860 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
6813 // 6861 //
6814 // We visit the prefix, but do not visit the identifier because it needs to 6862 // We visit the prefix, but do not visit the identifier because it needs to
6815 // be visited in the context of the prefix. 6863 // be visited in the context of the prefix.
6816 // 6864 //
6817 node.prefix?.accept(this); 6865 node.prefix?.accept(this);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
6915 _overrideManager.applyOverrides(overrides); 6963 _overrideManager.applyOverrides(overrides);
6916 } 6964 }
6917 return null; 6965 return null;
6918 } 6966 }
6919 6967
6920 @override 6968 @override
6921 Object visitTypeName(TypeName node) => null; 6969 Object visitTypeName(TypeName node) => null;
6922 6970
6923 @override 6971 @override
6924 Object visitVariableDeclaration(VariableDeclaration node) { 6972 Object visitVariableDeclaration(VariableDeclaration node) {
6925 InferenceContext.setType(node.initializer, InferenceContext.getType(node)); 6973 InferenceContext.setTypeFromNode(node.initializer, node);
6926 super.visitVariableDeclaration(node); 6974 super.visitVariableDeclaration(node);
6927 VariableElement element = node.element; 6975 VariableElement element = node.element;
6928 if (element.initializer != null && node.initializer != null) { 6976 if (element.initializer != null && node.initializer != null) {
6929 (element.initializer as FunctionElementImpl).returnType = 6977 (element.initializer as FunctionElementImpl).returnType =
6930 node.initializer.staticType; 6978 node.initializer.staticType;
6931 } 6979 }
6932 // Note: in addition to cloning the initializers for const variables, we 6980 // Note: in addition to cloning the initializers for const variables, we
6933 // have to clone the initializers for non-static final fields (because if 6981 // have to clone the initializers for non-static final fields (because if
6934 // they occur in a class with a const constructor, they will be needed to 6982 // they occur in a class with a const constructor, they will be needed to
6935 // evaluate the const constructor). 6983 // evaluate the const constructor).
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
7051 _promoteManager.setType(element, null); 7099 _promoteManager.setType(element, null);
7052 } 7100 }
7053 } 7101 }
7054 } 7102 }
7055 7103
7056 /** 7104 /**
7057 * Given the declared return type of a function, compute the type of the 7105 * Given the declared return type of a function, compute the type of the
7058 * values which should be returned or yielded as appropriate. If a type 7106 * values which should be returned or yielded as appropriate. If a type
7059 * cannot be computed from the declared return type, return null. 7107 * cannot be computed from the declared return type, return null.
7060 */ 7108 */
7061 DartType _computeReturnOrYieldType(DartType declaredType) { 7109 TypeContext _computeReturnOrYieldType(DartType declaredType) {
7062 bool isGenerator = _enclosingFunction.isGenerator; 7110 bool isGenerator = _enclosingFunction.isGenerator;
7063 bool isAsynchronous = _enclosingFunction.isAsynchronous; 7111 bool isAsynchronous = _enclosingFunction.isAsynchronous;
7064 7112
7065 // Ordinary functions just return their declared types. 7113 // Ordinary functions just return their declared types.
7066 if (!isGenerator && !isAsynchronous) { 7114 if (!isGenerator && !isAsynchronous) {
7067 return declaredType; 7115 return declaredType;
7068 } 7116 }
7069 if (isGenerator) { 7117 if (declaredType is InterfaceType) {
7070 if (declaredType is! InterfaceType) { 7118 if (isGenerator) {
7071 return null; 7119 // If it's sync* we expect Iterable<T>
7120 // IF it's async* we expect Stream<T>
7121 InterfaceType rawType = isAsynchronous
7122 ? typeProvider.streamDynamicType
7123 : typeProvider.iterableDynamicType;
7124 // Match the types to instantiate the type arguments if possible
7125 List<DartType> typeArgs =
7126 inferenceContext.matchTypes(rawType, declaredType);
7127 return (typeArgs?.length == 1) ? typeArgs[0] : null;
7072 } 7128 }
7073 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T> 7129 // async functions expect `Future<T> | T`
7074 InterfaceType rawType = isAsynchronous 7130 return new FutureUnionTypeContext(declaredType, typeProvider, typeSystem);
7075 ? typeProvider.streamDynamicType
7076 : typeProvider.iterableDynamicType;
7077 // Match the types to instantiate the type arguments if possible
7078 List<DartType> typeArgs =
7079 inferenceContext.matchTypes(rawType, declaredType);
7080 return (typeArgs?.length == 1) ? typeArgs[0] : null;
7081 } 7131 }
7082 // Must be asynchronous to reach here, so strip off any layers of Future 7132 return declaredType;
7083 return declaredType.flattenFutures(typeSystem);
7084 } 7133 }
7085 7134
7086 /** 7135 /**
7087 * The given expression is the expression used to compute the iterator for a 7136 * The given expression is the expression used to compute the iterator for a
7088 * for-each statement. Attempt to compute the type of objects that will be 7137 * for-each statement. Attempt to compute the type of objects that will be
7089 * assigned to the loop variable and return that type. Return `null` if the 7138 * assigned to the loop variable and return that type. Return `null` if the
7090 * type could not be determined. The [iteratorExpression] is the expression 7139 * type could not be determined. The [iteratorExpression] is the expression
7091 * that will return the Iterable being iterated over. 7140 * that will return the Iterable being iterated over.
7092 */ 7141 */
7093 DartType _getIteratorElementType(Expression iteratorExpression) { 7142 DartType _getIteratorElementType(Expression iteratorExpression) {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
7146 void _inferArgumentTypesFromContext(InvocationExpression node) { 7195 void _inferArgumentTypesFromContext(InvocationExpression node) {
7147 if (!strongMode) { 7196 if (!strongMode) {
7148 // Use propagated type inference for lambdas if not in strong mode. 7197 // Use propagated type inference for lambdas if not in strong mode.
7149 _inferFunctionExpressionsParametersTypes(node.argumentList); 7198 _inferFunctionExpressionsParametersTypes(node.argumentList);
7150 return; 7199 return;
7151 } 7200 }
7152 7201
7153 DartType contextType = node.staticInvokeType; 7202 DartType contextType = node.staticInvokeType;
7154 if (contextType is FunctionType) { 7203 if (contextType is FunctionType) {
7155 DartType originalType = node.function.staticType; 7204 DartType originalType = node.function.staticType;
7156 DartType returnContextType = InferenceContext.getType(node); 7205 DartType returnContextType = InferenceContext.getNonFutureType(node);
7157 TypeSystem ts = typeSystem; 7206 TypeSystem ts = typeSystem;
7158 if (returnContextType != null && 7207 if (returnContextType != null &&
7159 node.typeArguments == null && 7208 node.typeArguments == null &&
7160 originalType is FunctionType && 7209 originalType is FunctionType &&
7161 originalType.typeFormals.isNotEmpty && 7210 originalType.typeFormals.isNotEmpty &&
7162 ts is StrongTypeSystemImpl) { 7211 ts is StrongTypeSystemImpl) {
7163 contextType = ts.inferGenericFunctionCall(typeProvider, originalType, 7212 contextType = ts.inferGenericFunctionCall(typeProvider, originalType,
7164 DartType.EMPTY_LIST, DartType.EMPTY_LIST, returnContextType); 7213 DartType.EMPTY_LIST, DartType.EMPTY_LIST, returnContextType);
7165 } 7214 }
7166 7215
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
7304 // 7353 //
7305 // Unsound to assume that [x = "hello";] never executed after the 7354 // Unsound to assume that [x = "hello";] never executed after the
7306 // if-statement. Of course, a dead-code analysis could point out that 7355 // if-statement. Of course, a dead-code analysis could point out that
7307 // [return] here is dead. 7356 // [return] here is dead.
7308 return _isAbruptTerminationStatement(statements[size - 1]); 7357 return _isAbruptTerminationStatement(statements[size - 1]);
7309 } 7358 }
7310 return false; 7359 return false;
7311 } 7360 }
7312 7361
7313 /** 7362 /**
7363 * Returns true if this expression is being passed to `Future.then`.
7364 *
7365 * If so we will apply special typing rules in strong mode, to handle the
7366 * implicit union of `S | Future<S>`
7367 */
7368 bool _isFutureThenLambda(FunctionExpression node) {
7369 Element element = node.staticParameterElement?.enclosingElement;
7370 return element is MethodElement &&
7371 element.name == 'then' &&
7372 element.enclosingElement.type.isDartAsyncFuture;
7373 }
7374
7375 /**
7314 * Return `true` if the given variable is accessed within a closure in the giv en 7376 * Return `true` if the given variable is accessed within a closure in the giv en
7315 * [AstNode] and also mutated somewhere in variable scope. This information is only 7377 * [AstNode] and also mutated somewhere in variable scope. This information is only
7316 * available for local variables (including parameters). 7378 * available for local variables (including parameters).
7317 * 7379 *
7318 * @param variable the variable to check 7380 * @param variable the variable to check
7319 * @param target the [AstNode] to check within 7381 * @param target the [AstNode] to check within
7320 * @return `true` if this variable is potentially mutated somewhere in the giv en ASTNode 7382 * @return `true` if this variable is potentially mutated somewhere in the giv en ASTNode
7321 */ 7383 */
7322 bool _isVariableAccessedInClosure(Element variable, AstNode target) { 7384 bool _isVariableAccessedInClosure(Element variable, AstNode target) {
7323 _ResolverVisitor_isVariableAccessedInClosure visitor = 7385 _ResolverVisitor_isVariableAccessedInClosure visitor =
(...skipping 3670 matching lines...) Expand 10 before | Expand all | Expand 10 after
10994 return null; 11056 return null;
10995 } 11057 }
10996 if (identical(node.staticElement, variable)) { 11058 if (identical(node.staticElement, variable)) {
10997 if (node.inSetterContext()) { 11059 if (node.inSetterContext()) {
10998 result = true; 11060 result = true;
10999 } 11061 }
11000 } 11062 }
11001 return null; 11063 return null;
11002 } 11064 }
11003 } 11065 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698