| 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/standard_resolution_map.dart'; | 10 import 'package:analyzer/dart/ast/standard_resolution_map.dart'; |
| (...skipping 4175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4186 * bound of all types added with [addReturnOrYieldType]. | 4186 * bound of all types added with [addReturnOrYieldType]. |
| 4187 */ | 4187 */ |
| 4188 void popReturnContext(BlockFunctionBody node) { | 4188 void popReturnContext(BlockFunctionBody node) { |
| 4189 if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) { | 4189 if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) { |
| 4190 DartType context = _returnStack.removeLast() ?? DynamicTypeImpl.instance; | 4190 DartType context = _returnStack.removeLast() ?? DynamicTypeImpl.instance; |
| 4191 DartType inferred = _inferredReturn.removeLast(); | 4191 DartType inferred = _inferredReturn.removeLast(); |
| 4192 if (inferred.isBottom || inferred.isDartCoreNull) { | 4192 if (inferred.isBottom || inferred.isDartCoreNull) { |
| 4193 return; | 4193 return; |
| 4194 } | 4194 } |
| 4195 | 4195 |
| 4196 if (context is FutureUnionType) { | 4196 if (_typeSystem.isSubtypeOf(inferred, context)) { |
| 4197 // Try and match the Future type first. | |
| 4198 if (_typeSystem.isSubtypeOf(inferred, context.futureOfType) || | |
| 4199 _typeSystem.isSubtypeOf(inferred, context.type)) { | |
| 4200 setType(node, inferred); | |
| 4201 } | |
| 4202 } else if (_typeSystem.isSubtypeOf(inferred, context)) { | |
| 4203 setType(node, inferred); | 4197 setType(node, inferred); |
| 4204 } | 4198 } |
| 4205 } else { | 4199 } else { |
| 4206 assert(false); | 4200 assert(false); |
| 4207 } | 4201 } |
| 4208 } | 4202 } |
| 4209 | 4203 |
| 4210 /** | 4204 /** |
| 4211 * Push a block function body's return type onto the return stack. | 4205 * Push a block function body's return type onto the return stack. |
| 4212 */ | 4206 */ |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 4355 /** | 4349 /** |
| 4356 * Look for contextual type information attached to [node]. Returns | 4350 * Look for contextual type information attached to [node]. Returns |
| 4357 * the type if found, otherwise null. | 4351 * the type if found, otherwise null. |
| 4358 * | 4352 * |
| 4359 * If [node] has a contextual union type like `T | Future<T>` this will be | 4353 * If [node] has a contextual union type like `T | Future<T>` this will be |
| 4360 * returned. You can use [getType] if you prefer to only get the `T`. | 4354 * returned. You can use [getType] if you prefer to only get the `T`. |
| 4361 */ | 4355 */ |
| 4362 static DartType getContext(AstNode node) => node?.getProperty(_typeProperty); | 4356 static DartType getContext(AstNode node) => node?.getProperty(_typeProperty); |
| 4363 | 4357 |
| 4364 /** | 4358 /** |
| 4365 * Look for a single contextual type attached to [node], and returns the type | 4359 * Look for a single contextual type attached to [node], and returns the type |
| 4366 * if found, otherwise null. | 4360 * if found, otherwise null. |
| 4367 * | 4361 * |
| 4368 * If [node] has a contextual union type like `T | Future<T>` this will | 4362 * If [node] has a contextual union type like `T | Future<T>` this will |
| 4369 * simplify it to only return `T`. If the caller can handle a union type, | 4363 * simplify it to only return `T`. If the caller can handle a union type, |
| 4370 * [getContext] should be used instead. | 4364 * [getContext] should be used instead. |
| 4371 */ | 4365 */ |
| 4372 static DartType getType(AstNode node) { | 4366 static DartType getType(AstNode node) { |
| 4373 DartType t = getContext(node); | 4367 DartType t = getContext(node); |
| 4374 if (t is FutureUnionType) { | 4368 if (t is InterfaceType && t.isDartAsyncFutureOr) { |
| 4375 return t.type; | 4369 return t.typeArguments[0]; // The T in FutureOr<T> |
| 4376 } | 4370 } |
| 4377 return t; | 4371 return t; |
| 4378 } | 4372 } |
| 4379 | 4373 |
| 4380 /** | 4374 /** |
| 4381 * Like [getContext] but expands a union type into a list of types. | 4375 * Like [getContext] but expands a union type into a list of types. |
| 4382 */ | 4376 */ |
| 4383 static Iterable<DartType> getTypes(AstNode node) { | 4377 Iterable<DartType> getTypes(AstNode node) { |
| 4384 DartType t = getContext(node); | 4378 DartType t = getContext(node); |
| 4385 if (t == null) { | 4379 if (t == null) { |
| 4386 return DartType.EMPTY_LIST; | 4380 return DartType.EMPTY_LIST; |
| 4387 } | 4381 } |
| 4388 if (t is FutureUnionType) { | 4382 if (t is InterfaceType && t.isDartAsyncFutureOr) { |
| 4389 return t.types; | 4383 var tArg = t.typeArguments[0]; // The T in FutureOr<T> |
| 4384 return [ |
| 4385 _typeProvider.futureType.instantiate([tArg]), |
| 4386 tArg |
| 4387 ]; |
| 4390 } | 4388 } |
| 4391 return <DartType>[t]; | 4389 return [t]; |
| 4392 } | 4390 } |
| 4393 | 4391 |
| 4394 /** | 4392 /** |
| 4395 * Attach contextual type information [type] to [node] for use during | 4393 * Attach contextual type information [type] to [node] for use during |
| 4396 * inference. | 4394 * inference. |
| 4397 */ | 4395 */ |
| 4398 static void setType(AstNode node, DartType type) { | 4396 static void setType(AstNode node, DartType type) { |
| 4399 if (type == null || type.isDynamic) { | 4397 if (type == null || type.isDynamic) { |
| 4400 clearType(node); | 4398 clearType(node); |
| 4401 } else { | 4399 } else { |
| (...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5212 } | 5210 } |
| 5213 | 5211 |
| 5214 /** | 5212 /** |
| 5215 * Prepares this [ResolverVisitor] to using it for incremental resolution. | 5213 * Prepares this [ResolverVisitor] to using it for incremental resolution. |
| 5216 */ | 5214 */ |
| 5217 void initForIncrementalResolution() { | 5215 void initForIncrementalResolution() { |
| 5218 _overrideManager.enterScope(); | 5216 _overrideManager.enterScope(); |
| 5219 } | 5217 } |
| 5220 | 5218 |
| 5221 /** | 5219 /** |
| 5222 * Returns true if this method is `Future.then` or an override thereof. | |
| 5223 * | |
| 5224 * If so we will apply special typing rules in strong mode, to handle the | |
| 5225 * implicit union of `S | Future<S>` | |
| 5226 */ | |
| 5227 bool isFutureThen(Element element) { | |
| 5228 // If we are a method named then | |
| 5229 if (element is MethodElement && element.name == 'then') { | |
| 5230 DartType type = element.enclosingElement.type; | |
| 5231 // On Future or a subtype, then we're good. | |
| 5232 return (type.isDartAsyncFuture || isSubtypeOfFuture(type)); | |
| 5233 } | |
| 5234 return false; | |
| 5235 } | |
| 5236 | |
| 5237 /** | |
| 5238 * Returns true if this type is any subtype of the built in Future type. | 5220 * Returns true if this type is any subtype of the built in Future type. |
| 5239 */ | 5221 */ |
| 5240 bool isSubtypeOfFuture(DartType type) => | 5222 bool isSubtypeOfFuture(DartType type) => |
| 5241 typeSystem.isSubtypeOf(type, typeProvider.futureDynamicType); | 5223 typeSystem.isSubtypeOf(type, typeProvider.futureDynamicType); |
| 5242 | 5224 |
| 5243 /** | 5225 /** |
| 5244 * Given a downward inference type [fnType], and the declared | 5226 * Given a downward inference type [fnType], and the declared |
| 5245 * [typeParameterList] for a function expression, determines if we can enable | 5227 * [typeParameterList] for a function expression, determines if we can enable |
| 5246 * downward inference and if so, returns the function type to use for | 5228 * downward inference and if so, returns the function type to use for |
| 5247 * inference. | 5229 * inference. |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5529 node.rightHandSide?.accept(this); | 5511 node.rightHandSide?.accept(this); |
| 5530 node.accept(elementResolver); | 5512 node.accept(elementResolver); |
| 5531 node.accept(typeAnalyzer); | 5513 node.accept(typeAnalyzer); |
| 5532 return null; | 5514 return null; |
| 5533 } | 5515 } |
| 5534 | 5516 |
| 5535 @override | 5517 @override |
| 5536 Object visitAwaitExpression(AwaitExpression node) { | 5518 Object visitAwaitExpression(AwaitExpression node) { |
| 5537 DartType contextType = InferenceContext.getContext(node); | 5519 DartType contextType = InferenceContext.getContext(node); |
| 5538 if (contextType != null) { | 5520 if (contextType != null) { |
| 5539 var futureUnion = | 5521 var futureUnion = _createFutureOr(contextType); |
| 5540 FutureUnionType.from(contextType, typeProvider, typeSystem); | |
| 5541 InferenceContext.setType(node.expression, futureUnion); | 5522 InferenceContext.setType(node.expression, futureUnion); |
| 5542 } | 5523 } |
| 5543 return super.visitAwaitExpression(node); | 5524 return super.visitAwaitExpression(node); |
| 5544 } | 5525 } |
| 5545 | 5526 |
| 5546 @override | 5527 @override |
| 5547 Object visitBinaryExpression(BinaryExpression node) { | 5528 Object visitBinaryExpression(BinaryExpression node) { |
| 5548 TokenType operatorType = node.operator.type; | 5529 TokenType operatorType = node.operator.type; |
| 5549 Expression leftOperand = node.leftOperand; | 5530 Expression leftOperand = node.leftOperand; |
| 5550 Expression rightOperand = node.rightOperand; | 5531 Expression rightOperand = node.rightOperand; |
| (...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6071 _currentFunctionBody = node.body; | 6052 _currentFunctionBody = node.body; |
| 6072 _enclosingFunction = node.element; | 6053 _enclosingFunction = node.element; |
| 6073 _overrideManager.enterScope(); | 6054 _overrideManager.enterScope(); |
| 6074 try { | 6055 try { |
| 6075 DartType functionType = InferenceContext.getType(node); | 6056 DartType functionType = InferenceContext.getType(node); |
| 6076 if (functionType is FunctionType) { | 6057 if (functionType is FunctionType) { |
| 6077 functionType = | 6058 functionType = |
| 6078 matchFunctionTypeParameters(node.typeParameters, functionType); | 6059 matchFunctionTypeParameters(node.typeParameters, functionType); |
| 6079 if (functionType is FunctionType) { | 6060 if (functionType is FunctionType) { |
| 6080 _inferFormalParameterList(node.parameters, functionType); | 6061 _inferFormalParameterList(node.parameters, functionType); |
| 6081 | 6062 InferenceContext.setType( |
| 6082 DartType returnType; | 6063 node.body, _computeReturnOrYieldType(functionType.returnType)); |
| 6083 ParameterElement parameterElement = | |
| 6084 resolutionMap.staticParameterElementForExpression(node); | |
| 6085 if (isFutureThen(parameterElement?.enclosingElement)) { | |
| 6086 var futureThenType = | |
| 6087 InferenceContext.getContext(node.parent) as FunctionType; | |
| 6088 | |
| 6089 // Pretend the return type of Future<T>.then<S> first parameter is | |
| 6090 // | |
| 6091 // T -> (S | Future<S>) | |
| 6092 // | |
| 6093 // We can't represent this in Dart so we populate it here during | |
| 6094 // inference. | |
| 6095 var typeParamS = | |
| 6096 futureThenType.returnType.flattenFutures(typeSystem); | |
| 6097 returnType = | |
| 6098 FutureUnionType.from(typeParamS, typeProvider, typeSystem); | |
| 6099 } else { | |
| 6100 returnType = _computeReturnOrYieldType(functionType.returnType); | |
| 6101 } | |
| 6102 | |
| 6103 InferenceContext.setType(node.body, returnType); | |
| 6104 } | 6064 } |
| 6105 } | 6065 } |
| 6106 super.visitFunctionExpression(node); | 6066 super.visitFunctionExpression(node); |
| 6107 } finally { | 6067 } finally { |
| 6108 _overrideManager.exitScope(); | 6068 _overrideManager.exitScope(); |
| 6109 } | 6069 } |
| 6110 } finally { | 6070 } finally { |
| 6111 _currentFunctionBody = outerFunctionBody; | 6071 _currentFunctionBody = outerFunctionBody; |
| 6112 _enclosingFunction = outerFunction; | 6072 _enclosingFunction = outerFunction; |
| 6113 } | 6073 } |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6222 // have not already inferred something. However, the obvious ways to | 6182 // have not already inferred something. However, the obvious ways to |
| 6223 // check this don't work, since we may have been instantiated | 6183 // check this don't work, since we may have been instantiated |
| 6224 // to bounds in an earlier phase, and we *do* want to do inference | 6184 // to bounds in an earlier phase, and we *do* want to do inference |
| 6225 // in that case. | 6185 // in that case. |
| 6226 if (classTypeName.typeArguments == null) { | 6186 if (classTypeName.typeArguments == null) { |
| 6227 // Given a union of context types ` T0 | T1 | ... | Tn`, find the first | 6187 // Given a union of context types ` T0 | T1 | ... | Tn`, find the first |
| 6228 // valid instantiation `new C<Ti>`, if it exists. | 6188 // valid instantiation `new C<Ti>`, if it exists. |
| 6229 // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>` | 6189 // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>` |
| 6230 // will become a valid possibility. Right now the only allowed union is | 6190 // will become a valid possibility. Right now the only allowed union is |
| 6231 // `T | Future<T>` so we can take a simple approach. | 6191 // `T | Future<T>` so we can take a simple approach. |
| 6232 for (var contextType in InferenceContext.getTypes(node)) { | 6192 for (var contextType in inferenceContext.getTypes(node)) { |
| 6233 if (contextType is InterfaceType && | 6193 if (contextType is InterfaceType && |
| 6234 contextType.typeArguments != null && | 6194 contextType.typeArguments != null && |
| 6235 contextType.typeArguments.isNotEmpty) { | 6195 contextType.typeArguments.isNotEmpty) { |
| 6236 // TODO(jmesserly): for generic methods we use the | 6196 // TODO(jmesserly): for generic methods we use the |
| 6237 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to | 6197 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to |
| 6238 // be a tad more powerful than matchTypes. | 6198 // be a tad more powerful than matchTypes. |
| 6239 // | 6199 // |
| 6240 // For example it can infer this case: | 6200 // For example it can infer this case: |
| 6241 // | 6201 // |
| 6242 // class E<S, T> extends A<C<S>, T> { ... } | 6202 // class E<S, T> extends A<C<S>, T> { ... } |
| (...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 6658 InterfaceType rawType = isAsynchronous | 6618 InterfaceType rawType = isAsynchronous |
| 6659 ? typeProvider.streamDynamicType | 6619 ? typeProvider.streamDynamicType |
| 6660 : typeProvider.iterableDynamicType; | 6620 : typeProvider.iterableDynamicType; |
| 6661 // Match the types to instantiate the type arguments if possible | 6621 // Match the types to instantiate the type arguments if possible |
| 6662 List<DartType> typeArgs = | 6622 List<DartType> typeArgs = |
| 6663 inferenceContext.matchTypes(rawType, declaredType); | 6623 inferenceContext.matchTypes(rawType, declaredType); |
| 6664 return (typeArgs?.length == 1) ? typeArgs[0] : null; | 6624 return (typeArgs?.length == 1) ? typeArgs[0] : null; |
| 6665 } | 6625 } |
| 6666 // async functions expect `Future<T> | T` | 6626 // async functions expect `Future<T> | T` |
| 6667 var futureTypeParam = declaredType.flattenFutures(typeSystem); | 6627 var futureTypeParam = declaredType.flattenFutures(typeSystem); |
| 6668 return FutureUnionType.from(futureTypeParam, typeProvider, typeSystem); | 6628 return _createFutureOr(futureTypeParam); |
| 6669 } | 6629 } |
| 6670 return declaredType; | 6630 return declaredType; |
| 6671 } | 6631 } |
| 6672 | 6632 |
| 6673 /** | 6633 /** |
| 6634 * Creates a union of `T | Future<T>`, unless `T` is already a |
| 6635 * future-union, in which case it simply returns `T`. |
| 6636 */ |
| 6637 DartType _createFutureOr(DartType type) { |
| 6638 if (type.isDartAsyncFutureOr) { |
| 6639 return type; |
| 6640 } |
| 6641 return typeProvider.futureOrType.instantiate([type]); |
| 6642 } |
| 6643 |
| 6644 /** |
| 6674 * The given expression is the expression used to compute the iterator for a | 6645 * The given expression is the expression used to compute the iterator for a |
| 6675 * for-each statement. Attempt to compute the type of objects that will be | 6646 * for-each statement. Attempt to compute the type of objects that will be |
| 6676 * assigned to the loop variable and return that type. Return `null` if the | 6647 * assigned to the loop variable and return that type. Return `null` if the |
| 6677 * type could not be determined. The [iteratorExpression] is the expression | 6648 * type could not be determined. The [iteratorExpression] is the expression |
| 6678 * that will return the Iterable being iterated over. | 6649 * that will return the Iterable being iterated over. |
| 6679 */ | 6650 */ |
| 6680 DartType _getIteratorElementType(Expression iteratorExpression) { | 6651 DartType _getIteratorElementType(Expression iteratorExpression) { |
| 6681 DartType expressionType = iteratorExpression.bestType; | 6652 DartType expressionType = iteratorExpression.bestType; |
| 6682 if (expressionType is InterfaceType) { | 6653 if (expressionType is InterfaceType) { |
| 6683 PropertyAccessorElement iteratorFunction = | 6654 PropertyAccessorElement iteratorFunction = |
| (...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 8288 if (!elementValid) { | 8259 if (!elementValid) { |
| 8289 if (element is MultiplyDefinedElement) { | 8260 if (element is MultiplyDefinedElement) { |
| 8290 _setElement(typeName, element); | 8261 _setElement(typeName, element); |
| 8291 } | 8262 } |
| 8292 typeName.staticType = undefinedType; | 8263 typeName.staticType = undefinedType; |
| 8293 node.type = undefinedType; | 8264 node.type = undefinedType; |
| 8294 return; | 8265 return; |
| 8295 } | 8266 } |
| 8296 DartType type = null; | 8267 DartType type = null; |
| 8297 if (element is ClassElement) { | 8268 if (element is ClassElement) { |
| 8269 type = element.type; |
| 8270 // In non-strong mode `FutureOr<T>` is treated as `dynamic` |
| 8271 if (!typeSystem.isStrong && type.isDartAsyncFutureOr) { |
| 8272 type = dynamicType; |
| 8273 _setElement(typeName, type.element); |
| 8274 typeName.staticType = type; |
| 8275 node.type = type; |
| 8276 if (argumentList != null) { |
| 8277 NodeList<TypeAnnotation> arguments = argumentList.arguments; |
| 8278 if (arguments.length != 1) { |
| 8279 reportErrorForNode(_getInvalidTypeParametersErrorCode(node), node, |
| 8280 [typeName.name, 1, arguments.length]); |
| 8281 } |
| 8282 } |
| 8283 return; |
| 8284 } |
| 8298 _setElement(typeName, element); | 8285 _setElement(typeName, element); |
| 8299 type = element.type; | |
| 8300 } else if (element is FunctionTypeAliasElement) { | 8286 } else if (element is FunctionTypeAliasElement) { |
| 8301 _setElement(typeName, element); | 8287 _setElement(typeName, element); |
| 8302 type = element.type; | 8288 type = element.type; |
| 8303 } else if (element is TypeParameterElement) { | 8289 } else if (element is TypeParameterElement) { |
| 8304 _setElement(typeName, element); | 8290 _setElement(typeName, element); |
| 8305 type = element.type; | 8291 type = element.type; |
| 8306 // if (argumentList != null) { | 8292 // if (argumentList != null) { |
| 8307 // // Type parameters cannot have type arguments. | 8293 // // Type parameters cannot have type arguments. |
| 8308 // // TODO(brianwilkerson) Report this error. | 8294 // // TODO(brianwilkerson) Report this error. |
| 8309 // // resolver.reportError(ResolverErrorCode.?, keyType); | 8295 // // resolver.reportError(ResolverErrorCode.?, keyType); |
| (...skipping 2525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10835 return null; | 10821 return null; |
| 10836 } | 10822 } |
| 10837 if (identical(node.staticElement, variable)) { | 10823 if (identical(node.staticElement, variable)) { |
| 10838 if (node.inSetterContext()) { | 10824 if (node.inSetterContext()) { |
| 10839 result = true; | 10825 result = true; |
| 10840 } | 10826 } |
| 10841 } | 10827 } |
| 10842 return null; | 10828 return null; |
| 10843 } | 10829 } |
| 10844 } | 10830 } |
| OLD | NEW |