Chromium Code Reviews| 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.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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 } |
| OLD | NEW |