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

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: fix names, relationship between FutureUnion and DartType 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
4693 // https://github.com/dart-lang/sdk/issues/25322
4694 final List<DartType> _returnStack = <DartType>[]; 4692 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 DartType 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 DartType context = _returnStack.last;
4723 if (context == null || context.isDynamic) { 4721 if (context == null || context is DartType && context.isDynamic) {
vsm 2016/08/09 20:29:33 Why "context is DartType"? That's the static type
Jennifer Messerly 2016/08/09 20:56:57 Good catch. Holdover from the earlier design when
4724 DartType inferred = _inferredReturn.last; 4722 DartType inferred = _inferredReturn.last;
4725 inferred = _typeSystem.getLeastUpperBound(_typeProvider, type, inferred); 4723 inferred = _typeSystem.getLeastUpperBound(_typeProvider, inferred, type);
vsm 2016/08/09 20:29:33 Does the order actually matter?
Jennifer Messerly 2016/08/09 20:56:57 no. it got swapped because I had removed and recon
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(getContext(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 * [getContext] should be used instead.
4911 */
4912 static DartType getType(AstNode node) {
4913 DartType t = getContext(node);
4914 if (t is FutureUnionType) {
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.
4923 *
4924 * If [node] has a contextual union type like `T | Future<T>` this will be
4925 * returned. You can use [getType] if you prefer to only get the `T`.
4910 */ 4926 */
4911 static DartType getType(AstNode node) => node?.getProperty(_typeProperty); 4927 static DartType getContext(AstNode node) => node?.getProperty(_typeProperty);
4928
4929 /**
4930 * Like [getContext] but expands a union type into a list of types.
4931 */
4932 static Iterable<DartType> getTypes(AstNode node) {
4933 DartType t = getContext(node);
4934 if (t == null) {
4935 return DartType.EMPTY_LIST;
4936 }
4937 if (t is FutureUnionType) {
4938 return t.types;
4939 }
4940 return <DartType>[t];
4941 }
4912 4942
4913 /** 4943 /**
4914 * Attach contextual type information [type] to [node] for use during 4944 * Attach contextual type information [type] to [node] for use during
4915 * inference. 4945 * inference.
4916 */ 4946 */
4917 static void setType(AstNode node, DartType type) { 4947 static void setType(AstNode node, DartType type) {
4918 // TODO(jmesserly): this sets the type even when it's dynamic.
4919 // Can we skip that?
4920 node?.setProperty(_typeProperty, type); 4948 node?.setProperty(_typeProperty, type);
4921 } 4949 }
4922 4950
4923 /** 4951 /**
4924 * Attach contextual type information [type] to [node] for use during 4952 * Attach contextual type information [type] to [node] for use during
4925 * inference. 4953 * inference.
4926 */ 4954 */
4927 static void setTypeFromNode(AstNode innerNode, AstNode outerNode) { 4955 static void setTypeFromNode(AstNode innerNode, AstNode outerNode) {
4928 setType(innerNode, getType(outerNode)); 4956 setType(innerNode, getContext(outerNode));
4929 } 4957 }
4930 } 4958 }
4931 4959
4932 /** 4960 /**
4933 * This enum holds one of four states of a field initialization state through a constructor 4961 * This enum holds one of four states of a field initialization state through a constructor
4934 * signature, not initialized, initialized in the field declaration, initialized in the field 4962 * signature, not initialized, initialized in the field declaration, initialized in the field
4935 * formal, and finally, initialized in the initializers list. 4963 * formal, and finally, initialized in the initializers list.
4936 */ 4964 */
4937 class INIT_STATE extends Enum<INIT_STATE> { 4965 class INIT_STATE extends Enum<INIT_STATE> {
4938 static const INIT_STATE NOT_INIT = const INIT_STATE('NOT_INIT', 0); 4966 static const INIT_STATE NOT_INIT = const INIT_STATE('NOT_INIT', 0);
(...skipping 1063 matching lines...) Expand 10 before | Expand all | Expand 10 after
6002 node.rightHandSide, node.leftHandSide.staticType); 6030 node.rightHandSide, node.leftHandSide.staticType);
6003 } 6031 }
6004 node.rightHandSide?.accept(this); 6032 node.rightHandSide?.accept(this);
6005 node.accept(elementResolver); 6033 node.accept(elementResolver);
6006 node.accept(typeAnalyzer); 6034 node.accept(typeAnalyzer);
6007 return null; 6035 return null;
6008 } 6036 }
6009 6037
6010 @override 6038 @override
6011 Object visitAwaitExpression(AwaitExpression node) { 6039 Object visitAwaitExpression(AwaitExpression node) {
6012 // TODO(leafp): Handle the implicit union type here 6040 DartType contextType = InferenceContext.getContext(node);
6013 // https://github.com/dart-lang/sdk/issues/25322
6014 DartType contextType = InferenceContext.getType(node);
6015 if (contextType != null) { 6041 if (contextType != null) {
6016 InterfaceType futureT = typeProvider.futureType 6042 var futureUnion =
6017 .instantiate([contextType.flattenFutures(typeSystem)]); 6043 FutureUnionType.from(contextType, typeProvider, typeSystem);
6018 InferenceContext.setType(node.expression, futureT); 6044 InferenceContext.setType(node.expression, futureUnion);
6019 } 6045 }
6020 return super.visitAwaitExpression(node); 6046 return super.visitAwaitExpression(node);
6021 } 6047 }
6022 6048
6023 @override 6049 @override
6024 Object visitBinaryExpression(BinaryExpression node) { 6050 Object visitBinaryExpression(BinaryExpression node) {
6025 TokenType operatorType = node.operator.type; 6051 TokenType operatorType = node.operator.type;
6026 Expression leftOperand = node.leftOperand; 6052 Expression leftOperand = node.leftOperand;
6027 Expression rightOperand = node.rightOperand; 6053 Expression rightOperand = node.rightOperand;
6028 if (operatorType == TokenType.AMPERSAND_AMPERSAND) { 6054 if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
6062 } else { 6088 } else {
6063 // TODO(leafp): Do downwards inference using the declared type 6089 // TODO(leafp): Do downwards inference using the declared type
6064 // of the binary operator for other cases. 6090 // of the binary operator for other cases.
6065 if (operatorType == TokenType.QUESTION_QUESTION) { 6091 if (operatorType == TokenType.QUESTION_QUESTION) {
6066 InferenceContext.setTypeFromNode(leftOperand, node); 6092 InferenceContext.setTypeFromNode(leftOperand, node);
6067 } 6093 }
6068 leftOperand?.accept(this); 6094 leftOperand?.accept(this);
6069 if (operatorType == TokenType.QUESTION_QUESTION) { 6095 if (operatorType == TokenType.QUESTION_QUESTION) {
6070 // Set the right side, either from the context, or using the information 6096 // Set the right side, either from the context, or using the information
6071 // from the left side if it is more precise. 6097 // from the left side if it is more precise.
6072 DartType contextType = InferenceContext.getType(node); 6098 DartType contextType = InferenceContext.getContext(node);
6073 DartType leftType = leftOperand?.staticType; 6099 DartType leftType = leftOperand?.staticType;
6074 if (contextType == null || contextType.isDynamic) { 6100 if (contextType == null || contextType.isDynamic) {
6075 contextType = leftType; 6101 contextType = leftType;
6076 } 6102 }
6077 InferenceContext.setType(rightOperand, contextType); 6103 InferenceContext.setType(rightOperand, contextType);
6078 } 6104 }
6079 rightOperand?.accept(this); 6105 rightOperand?.accept(this);
6080 } 6106 }
6081 node.accept(elementResolver); 6107 node.accept(elementResolver);
6082 node.accept(typeAnalyzer); 6108 node.accept(typeAnalyzer);
(...skipping 457 matching lines...) Expand 10 before | Expand all | Expand 10 after
6540 _currentFunctionBody = node.body; 6566 _currentFunctionBody = node.body;
6541 _enclosingFunction = node.element; 6567 _enclosingFunction = node.element;
6542 _overrideManager.enterScope(); 6568 _overrideManager.enterScope();
6543 try { 6569 try {
6544 DartType functionType = InferenceContext.getType(node); 6570 DartType functionType = InferenceContext.getType(node);
6545 if (functionType is FunctionType) { 6571 if (functionType is FunctionType) {
6546 functionType = 6572 functionType =
6547 matchFunctionTypeParameters(node.typeParameters, functionType); 6573 matchFunctionTypeParameters(node.typeParameters, functionType);
6548 if (functionType is FunctionType) { 6574 if (functionType is FunctionType) {
6549 _inferFormalParameterList(node.parameters, functionType); 6575 _inferFormalParameterList(node.parameters, functionType);
6550 DartType returnType = 6576
6551 _computeReturnOrYieldType(functionType.returnType); 6577 DartType returnType;
6578 if (_isFutureThenLambda(node)) {
6579 var futureThenType =
6580 InferenceContext.getContext(node.parent) as FunctionType;
6581
6582 // Pretend the return type of Future<T>.then<S> first parameter is
6583 //
6584 // T -> (S | Future<S>)
6585 //
6586 // We can't represent this in Dart so we populate it here during
6587 // inference.
6588 returnType = FutureUnionType.from(
6589 futureThenType.returnType, typeProvider, typeSystem);
6590 } else {
6591 returnType = _computeReturnOrYieldType(functionType.returnType);
6592 }
6593
6552 InferenceContext.setType(node.body, returnType); 6594 InferenceContext.setType(node.body, returnType);
6553 } 6595 }
6554 } 6596 }
6555 super.visitFunctionExpression(node); 6597 super.visitFunctionExpression(node);
6556 } finally { 6598 } finally {
6557 _overrideManager.exitScope(); 6599 _overrideManager.exitScope();
6558 } 6600 }
6559 } finally { 6601 } finally {
6560 _currentFunctionBody = outerFunctionBody; 6602 _currentFunctionBody = outerFunctionBody;
6561 _enclosingFunction = outerFunction; 6603 _enclosingFunction = outerFunction;
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
6657 perBranchOverrides.add(elseOverrides); 6699 perBranchOverrides.add(elseOverrides);
6658 _overrideManager.mergeOverrides(perBranchOverrides); 6700 _overrideManager.mergeOverrides(perBranchOverrides);
6659 } 6701 }
6660 return null; 6702 return null;
6661 } 6703 }
6662 6704
6663 @override 6705 @override
6664 Object visitInstanceCreationExpression(InstanceCreationExpression node) { 6706 Object visitInstanceCreationExpression(InstanceCreationExpression node) {
6665 TypeName classTypeName = node.constructorName.type; 6707 TypeName classTypeName = node.constructorName.type;
6666 if (classTypeName.typeArguments == null) { 6708 if (classTypeName.typeArguments == null) {
6667 DartType contextType = InferenceContext.getType(node); 6709 // Given a union of context types ` T0 | T1 | ... | Tn`, find the first
6668 if (contextType is InterfaceType && 6710 // valid instantiation `new C<Ti>`, if it exists.
6669 contextType.typeArguments != null && 6711 // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>`
6670 contextType.typeArguments.length > 0) { 6712 // will become a valid possibility. Right now the only allowed union is
6671 // TODO(jmesserly): for generic methods we use the 6713 // `T | Future<T>` so we can take a simple approach.
6672 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to 6714 for (var contextType in InferenceContext.getTypes(node)) {
6673 // be a tad more powerful than matchTypes. 6715 if (contextType is InterfaceType &&
6674 // 6716 contextType.typeArguments != null &&
6675 // For example it can infer this case: 6717 contextType.typeArguments.isNotEmpty) {
6676 // 6718 // TODO(jmesserly): for generic methods we use the
6677 // class E<S, T> extends A<C<S>, T> { ... } 6719 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to
6678 // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello"); 6720 // be a tad more powerful than matchTypes.
6679 // 6721 //
6680 // See _inferArgumentTypesFromContext in this file for use of it. 6722 // For example it can infer this case:
6681 List<DartType> targs = 6723 //
6682 inferenceContext.matchTypes(classTypeName.type, contextType); 6724 // class E<S, T> extends A<C<S>, T> { ... }
6683 if (targs != null && targs.any((t) => !t.isDynamic)) { 6725 // A<C<int>, String> a0 = /*infer<int, String>*/new E("hello");
6684 ClassElement classElement = classTypeName.type.element; 6726 //
6685 InterfaceType rawType = classElement.type; 6727 // See _inferArgumentTypesFromContext in this file for use of it.
6686 InterfaceType fullType = 6728 List<DartType> targs =
6687 rawType.substitute2(targs, rawType.typeArguments); 6729 inferenceContext.matchTypes(classTypeName.type, contextType);
6688 // The element resolver uses the type on the constructor name, so 6730 if (targs != null && targs.any((t) => !t.isDynamic)) {
6689 // infer it first 6731 ClassElement classElement = classTypeName.type.element;
6690 typeAnalyzer.inferConstructorName(node.constructorName, fullType); 6732 InterfaceType rawType = classElement.type;
6733 InterfaceType fullType =
6734 rawType.substitute2(targs, rawType.typeArguments);
6735 // The element resolver uses the type on the constructor name, so
6736 // infer it first
6737 typeAnalyzer.inferConstructorName(node.constructorName, fullType);
6738 break;
6739 }
6691 } 6740 }
6692 } 6741 }
6693 } 6742 }
6694 node.constructorName?.accept(this); 6743 node.constructorName?.accept(this);
6695 FunctionType constructorType = node.constructorName.staticElement?.type; 6744 FunctionType constructorType = node.constructorName.staticElement?.type;
6696 if (constructorType != null) { 6745 if (constructorType != null) {
6697 InferenceContext.setType(node.argumentList, constructorType); 6746 InferenceContext.setType(node.argumentList, constructorType);
6698 } 6747 }
6699 node.argumentList?.accept(this); 6748 node.argumentList?.accept(this);
6700 node.accept(elementResolver); 6749 node.accept(elementResolver);
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
6794 node.typeArguments?.accept(this); 6843 node.typeArguments?.accept(this);
6795 node.accept(elementResolver); 6844 node.accept(elementResolver);
6796 _inferArgumentTypesFromContext(node); 6845 _inferArgumentTypesFromContext(node);
6797 node.argumentList?.accept(this); 6846 node.argumentList?.accept(this);
6798 node.accept(typeAnalyzer); 6847 node.accept(typeAnalyzer);
6799 return null; 6848 return null;
6800 } 6849 }
6801 6850
6802 @override 6851 @override
6803 Object visitNamedExpression(NamedExpression node) { 6852 Object visitNamedExpression(NamedExpression node) {
6804 InferenceContext.setType(node.expression, InferenceContext.getType(node)); 6853 InferenceContext.setTypeFromNode(node.expression, node);
6805 return super.visitNamedExpression(node); 6854 return super.visitNamedExpression(node);
6806 } 6855 }
6807 6856
6808 @override 6857 @override
6809 Object visitNode(AstNode node) { 6858 Object visitNode(AstNode node) {
6810 node.visitChildren(this); 6859 node.visitChildren(this);
6811 node.accept(elementResolver); 6860 node.accept(elementResolver);
6812 node.accept(typeAnalyzer); 6861 node.accept(typeAnalyzer);
6813 return null; 6862 return null;
6814 } 6863 }
6815 6864
6816 @override 6865 @override
6817 Object visitParenthesizedExpression(ParenthesizedExpression node) { 6866 Object visitParenthesizedExpression(ParenthesizedExpression node) {
6818 InferenceContext.setType(node.expression, InferenceContext.getType(node)); 6867 InferenceContext.setTypeFromNode(node.expression, node);
6819 return super.visitParenthesizedExpression(node); 6868 return super.visitParenthesizedExpression(node);
6820 } 6869 }
6821 6870
6822 @override 6871 @override
6823 Object visitPrefixedIdentifier(PrefixedIdentifier node) { 6872 Object visitPrefixedIdentifier(PrefixedIdentifier node) {
6824 // 6873 //
6825 // We visit the prefix, but do not visit the identifier because it needs to 6874 // We visit the prefix, but do not visit the identifier because it needs to
6826 // be visited in the context of the prefix. 6875 // be visited in the context of the prefix.
6827 // 6876 //
6828 node.prefix?.accept(this); 6877 node.prefix?.accept(this);
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
6926 _overrideManager.applyOverrides(overrides); 6975 _overrideManager.applyOverrides(overrides);
6927 } 6976 }
6928 return null; 6977 return null;
6929 } 6978 }
6930 6979
6931 @override 6980 @override
6932 Object visitTypeName(TypeName node) => null; 6981 Object visitTypeName(TypeName node) => null;
6933 6982
6934 @override 6983 @override
6935 Object visitVariableDeclaration(VariableDeclaration node) { 6984 Object visitVariableDeclaration(VariableDeclaration node) {
6936 InferenceContext.setType(node.initializer, InferenceContext.getType(node)); 6985 InferenceContext.setTypeFromNode(node.initializer, node);
6937 super.visitVariableDeclaration(node); 6986 super.visitVariableDeclaration(node);
6938 VariableElement element = node.element; 6987 VariableElement element = node.element;
6939 if (element.initializer != null && node.initializer != null) { 6988 if (element.initializer != null && node.initializer != null) {
6940 (element.initializer as FunctionElementImpl).returnType = 6989 (element.initializer as FunctionElementImpl).returnType =
6941 node.initializer.staticType; 6990 node.initializer.staticType;
6942 } 6991 }
6943 // Note: in addition to cloning the initializers for const variables, we 6992 // Note: in addition to cloning the initializers for const variables, we
6944 // have to clone the initializers for non-static final fields (because if 6993 // have to clone the initializers for non-static final fields (because if
6945 // they occur in a class with a const constructor, they will be needed to 6994 // they occur in a class with a const constructor, they will be needed to
6946 // evaluate the const constructor). 6995 // evaluate the const constructor).
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
7070 * cannot be computed from the declared return type, return null. 7119 * cannot be computed from the declared return type, return null.
7071 */ 7120 */
7072 DartType _computeReturnOrYieldType(DartType declaredType) { 7121 DartType _computeReturnOrYieldType(DartType declaredType) {
7073 bool isGenerator = _enclosingFunction.isGenerator; 7122 bool isGenerator = _enclosingFunction.isGenerator;
7074 bool isAsynchronous = _enclosingFunction.isAsynchronous; 7123 bool isAsynchronous = _enclosingFunction.isAsynchronous;
7075 7124
7076 // Ordinary functions just return their declared types. 7125 // Ordinary functions just return their declared types.
7077 if (!isGenerator && !isAsynchronous) { 7126 if (!isGenerator && !isAsynchronous) {
7078 return declaredType; 7127 return declaredType;
7079 } 7128 }
7080 if (isGenerator) { 7129 if (declaredType is InterfaceType) {
7081 if (declaredType is! InterfaceType) { 7130 if (isGenerator) {
7082 return null; 7131 // If it's sync* we expect Iterable<T>
7132 // IF it's async* we expect Stream<T>
vsm 2016/08/09 20:29:33 IF -> If
Jennifer Messerly 2016/08/09 20:56:57 Done.
7133 InterfaceType rawType = isAsynchronous
7134 ? typeProvider.streamDynamicType
7135 : typeProvider.iterableDynamicType;
7136 // Match the types to instantiate the type arguments if possible
7137 List<DartType> typeArgs =
7138 inferenceContext.matchTypes(rawType, declaredType);
7139 return (typeArgs?.length == 1) ? typeArgs[0] : null;
7083 } 7140 }
7084 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T> 7141 // async functions expect `Future<T> | T`
7085 InterfaceType rawType = isAsynchronous 7142 return new FutureUnionType(declaredType, typeProvider, typeSystem);
7086 ? typeProvider.streamDynamicType
7087 : typeProvider.iterableDynamicType;
7088 // Match the types to instantiate the type arguments if possible
7089 List<DartType> typeArgs =
7090 inferenceContext.matchTypes(rawType, declaredType);
7091 return (typeArgs?.length == 1) ? typeArgs[0] : null;
7092 } 7143 }
7093 // Must be asynchronous to reach here, so strip off any layers of Future 7144 return declaredType;
7094 return declaredType.flattenFutures(typeSystem);
7095 } 7145 }
7096 7146
7097 /** 7147 /**
7098 * The given expression is the expression used to compute the iterator for a 7148 * The given expression is the expression used to compute the iterator for a
7099 * for-each statement. Attempt to compute the type of objects that will be 7149 * for-each statement. Attempt to compute the type of objects that will be
7100 * assigned to the loop variable and return that type. Return `null` if the 7150 * assigned to the loop variable and return that type. Return `null` if the
7101 * type could not be determined. The [iteratorExpression] is the expression 7151 * type could not be determined. The [iteratorExpression] is the expression
7102 * that will return the Iterable being iterated over. 7152 * that will return the Iterable being iterated over.
7103 */ 7153 */
7104 DartType _getIteratorElementType(Expression iteratorExpression) { 7154 DartType _getIteratorElementType(Expression iteratorExpression) {
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
7315 // 7365 //
7316 // Unsound to assume that [x = "hello";] never executed after the 7366 // Unsound to assume that [x = "hello";] never executed after the
7317 // if-statement. Of course, a dead-code analysis could point out that 7367 // if-statement. Of course, a dead-code analysis could point out that
7318 // [return] here is dead. 7368 // [return] here is dead.
7319 return _isAbruptTerminationStatement(statements[size - 1]); 7369 return _isAbruptTerminationStatement(statements[size - 1]);
7320 } 7370 }
7321 return false; 7371 return false;
7322 } 7372 }
7323 7373
7324 /** 7374 /**
7375 * Returns true if this expression is being passed to `Future.then`.
7376 *
7377 * If so we will apply special typing rules in strong mode, to handle the
7378 * implicit union of `S | Future<S>`
7379 */
7380 bool _isFutureThenLambda(FunctionExpression node) {
7381 Element element = node.staticParameterElement?.enclosingElement;
7382 return element is MethodElement &&
7383 element.name == 'then' &&
7384 element.enclosingElement.type.isDartAsyncFuture;
7385 }
7386
7387 /**
7325 * Return `true` if the given variable is accessed within a closure in the giv en 7388 * Return `true` if the given variable is accessed within a closure in the giv en
7326 * [AstNode] and also mutated somewhere in variable scope. This information is only 7389 * [AstNode] and also mutated somewhere in variable scope. This information is only
7327 * available for local variables (including parameters). 7390 * available for local variables (including parameters).
7328 * 7391 *
7329 * @param variable the variable to check 7392 * @param variable the variable to check
7330 * @param target the [AstNode] to check within 7393 * @param target the [AstNode] to check within
7331 * @return `true` if this variable is potentially mutated somewhere in the giv en ASTNode 7394 * @return `true` if this variable is potentially mutated somewhere in the giv en ASTNode
7332 */ 7395 */
7333 bool _isVariableAccessedInClosure(Element variable, AstNode target) { 7396 bool _isVariableAccessedInClosure(Element variable, AstNode target) {
7334 _ResolverVisitor_isVariableAccessedInClosure visitor = 7397 _ResolverVisitor_isVariableAccessedInClosure visitor =
(...skipping 3670 matching lines...) Expand 10 before | Expand all | Expand 10 after
11005 return null; 11068 return null;
11006 } 11069 }
11007 if (identical(node.staticElement, variable)) { 11070 if (identical(node.staticElement, variable)) {
11008 if (node.inSetterContext()) { 11071 if (node.inSetterContext()) {
11009 result = true; 11072 result = true;
11010 } 11073 }
11011 } 11074 }
11012 return null; 11075 return null;
11013 } 11076 }
11014 } 11077 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698