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 4173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4184 * bound of all types added with [addReturnOrYieldType]. | 4184 * bound of all types added with [addReturnOrYieldType]. |
4185 */ | 4185 */ |
4186 void popReturnContext(BlockFunctionBody node) { | 4186 void popReturnContext(BlockFunctionBody node) { |
4187 if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) { | 4187 if (_returnStack.isNotEmpty && _inferredReturn.isNotEmpty) { |
4188 DartType context = _returnStack.removeLast() ?? DynamicTypeImpl.instance; | 4188 DartType context = _returnStack.removeLast() ?? DynamicTypeImpl.instance; |
4189 DartType inferred = _inferredReturn.removeLast(); | 4189 DartType inferred = _inferredReturn.removeLast(); |
4190 if (inferred.isBottom) { | 4190 if (inferred.isBottom) { |
4191 return; | 4191 return; |
4192 } | 4192 } |
4193 | 4193 |
4194 if (context is FutureUnionType) { | 4194 if (_typeSystem.isSubtypeOf(inferred, context)) { |
4195 // Try and match the Future type first. | |
4196 if (_typeSystem.isSubtypeOf(inferred, context.futureOfType) || | |
4197 _typeSystem.isSubtypeOf(inferred, context.type)) { | |
4198 setType(node, inferred); | |
4199 } | |
4200 } else if (_typeSystem.isSubtypeOf(inferred, context)) { | |
4201 setType(node, inferred); | 4195 setType(node, inferred); |
4202 } | 4196 } |
4203 } else { | 4197 } else { |
4204 assert(false); | 4198 assert(false); |
4205 } | 4199 } |
4206 } | 4200 } |
4207 | 4201 |
4208 /** | 4202 /** |
4209 * Push a block function body's return type onto the return stack. | 4203 * Push a block function body's return type onto the return stack. |
4210 */ | 4204 */ |
(...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4353 /** | 4347 /** |
4354 * Look for contextual type information attached to [node]. Returns | 4348 * Look for contextual type information attached to [node]. Returns |
4355 * the type if found, otherwise null. | 4349 * the type if found, otherwise null. |
4356 * | 4350 * |
4357 * If [node] has a contextual union type like `T | Future<T>` this will be | 4351 * If [node] has a contextual union type like `T | Future<T>` this will be |
4358 * returned. You can use [getType] if you prefer to only get the `T`. | 4352 * returned. You can use [getType] if you prefer to only get the `T`. |
4359 */ | 4353 */ |
4360 static DartType getContext(AstNode node) => node?.getProperty(_typeProperty); | 4354 static DartType getContext(AstNode node) => node?.getProperty(_typeProperty); |
4361 | 4355 |
4362 /** | 4356 /** |
4363 * Look for a single contextual type attached to [node], and returns the type | 4357 * Look for a single contextual type attached to [node], and returns the type |
4364 * if found, otherwise null. | 4358 * if found, otherwise null. |
4365 * | 4359 * |
4366 * If [node] has a contextual union type like `T | Future<T>` this will | 4360 * If [node] has a contextual union type like `T | Future<T>` this will |
4367 * simplify it to only return `T`. If the caller can handle a union type, | 4361 * simplify it to only return `T`. If the caller can handle a union type, |
4368 * [getContext] should be used instead. | 4362 * [getContext] should be used instead. |
4369 */ | 4363 */ |
4370 static DartType getType(AstNode node) { | 4364 static DartType getType(AstNode node) { |
4371 DartType t = getContext(node); | 4365 DartType t = getContext(node); |
4372 if (t is FutureUnionType) { | 4366 if (t is InterfaceType && t.isDartAsyncFutureOr) { |
4373 return t.type; | 4367 return t.typeArguments[0]; // The T in FutureOr<T> |
4374 } | 4368 } |
4375 return t; | 4369 return t; |
4376 } | 4370 } |
4377 | 4371 |
4378 /** | 4372 /** |
4379 * Like [getContext] but expands a union type into a list of types. | 4373 * Like [getContext] but expands a union type into a list of types. |
4380 */ | 4374 */ |
4381 static Iterable<DartType> getTypes(AstNode node) { | 4375 Iterable<DartType> getTypes(AstNode node) { |
4382 DartType t = getContext(node); | 4376 DartType t = getContext(node); |
4383 if (t == null) { | 4377 if (t == null) { |
4384 return DartType.EMPTY_LIST; | 4378 return DartType.EMPTY_LIST; |
4385 } | 4379 } |
4386 if (t is FutureUnionType) { | 4380 if (t is InterfaceType && t.isDartAsyncFutureOr) { |
4387 return t.types; | 4381 var tArg = t.typeArguments[0]; // The T in FutureOr<T> |
4382 return [ | |
4383 _typeProvider.futureType.instantiate([tArg]), | |
4384 tArg | |
4385 ]; | |
4388 } | 4386 } |
4389 return <DartType>[t]; | 4387 return [t]; |
4390 } | 4388 } |
4391 | 4389 |
4392 /** | 4390 /** |
4393 * Attach contextual type information [type] to [node] for use during | 4391 * Attach contextual type information [type] to [node] for use during |
4394 * inference. | 4392 * inference. |
4395 */ | 4393 */ |
4396 static void setType(AstNode node, DartType type) { | 4394 static void setType(AstNode node, DartType type) { |
4397 if (type == null || type.isDynamic) { | 4395 if (type == null || type.isDynamic) { |
4398 clearType(node); | 4396 clearType(node); |
4399 } else { | 4397 } else { |
(...skipping 810 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5210 } | 5208 } |
5211 | 5209 |
5212 /** | 5210 /** |
5213 * Prepares this [ResolverVisitor] to using it for incremental resolution. | 5211 * Prepares this [ResolverVisitor] to using it for incremental resolution. |
5214 */ | 5212 */ |
5215 void initForIncrementalResolution() { | 5213 void initForIncrementalResolution() { |
5216 _overrideManager.enterScope(); | 5214 _overrideManager.enterScope(); |
5217 } | 5215 } |
5218 | 5216 |
5219 /** | 5217 /** |
5220 * Returns true if this method is `Future.then` or an override thereof. | |
5221 * | |
5222 * If so we will apply special typing rules in strong mode, to handle the | |
5223 * implicit union of `S | Future<S>` | |
5224 */ | |
5225 bool isFutureThen(Element element) { | |
5226 // If we are a method named then | |
5227 if (element is MethodElement && element.name == 'then') { | |
5228 DartType type = element.enclosingElement.type; | |
5229 // On Future or a subtype, then we're good. | |
5230 return (type.isDartAsyncFuture || isSubtypeOfFuture(type)); | |
5231 } | |
5232 return false; | |
5233 } | |
5234 | |
5235 /** | |
5236 * Returns true if this type is any subtype of the built in Future type. | 5218 * Returns true if this type is any subtype of the built in Future type. |
5237 */ | 5219 */ |
5238 bool isSubtypeOfFuture(DartType type) => | 5220 bool isSubtypeOfFuture(DartType type) => |
5239 typeSystem.isSubtypeOf(type, typeProvider.futureDynamicType); | 5221 typeSystem.isSubtypeOf(type, typeProvider.futureDynamicType); |
5240 | 5222 |
5241 /** | 5223 /** |
5242 * Given a downward inference type [fnType], and the declared | 5224 * Given a downward inference type [fnType], and the declared |
5243 * [typeParameterList] for a function expression, determines if we can enable | 5225 * [typeParameterList] for a function expression, determines if we can enable |
5244 * downward inference and if so, returns the function type to use for | 5226 * downward inference and if so, returns the function type to use for |
5245 * inference. | 5227 * inference. |
(...skipping 275 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
5521 node.rightHandSide?.accept(this); | 5503 node.rightHandSide?.accept(this); |
5522 node.accept(elementResolver); | 5504 node.accept(elementResolver); |
5523 node.accept(typeAnalyzer); | 5505 node.accept(typeAnalyzer); |
5524 return null; | 5506 return null; |
5525 } | 5507 } |
5526 | 5508 |
5527 @override | 5509 @override |
5528 Object visitAwaitExpression(AwaitExpression node) { | 5510 Object visitAwaitExpression(AwaitExpression node) { |
5529 DartType contextType = InferenceContext.getContext(node); | 5511 DartType contextType = InferenceContext.getContext(node); |
5530 if (contextType != null) { | 5512 if (contextType != null) { |
5531 var futureUnion = | 5513 var futureUnion = _createFutureOr(contextType); |
5532 FutureUnionType.from(contextType, typeProvider, typeSystem); | |
5533 InferenceContext.setType(node.expression, futureUnion); | 5514 InferenceContext.setType(node.expression, futureUnion); |
5534 } | 5515 } |
5535 return super.visitAwaitExpression(node); | 5516 return super.visitAwaitExpression(node); |
5536 } | 5517 } |
5537 | 5518 |
5538 @override | 5519 @override |
5539 Object visitBinaryExpression(BinaryExpression node) { | 5520 Object visitBinaryExpression(BinaryExpression node) { |
5540 TokenType operatorType = node.operator.type; | 5521 TokenType operatorType = node.operator.type; |
5541 Expression leftOperand = node.leftOperand; | 5522 Expression leftOperand = node.leftOperand; |
5542 Expression rightOperand = node.rightOperand; | 5523 Expression rightOperand = node.rightOperand; |
(...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6063 _currentFunctionBody = node.body; | 6044 _currentFunctionBody = node.body; |
6064 _enclosingFunction = node.element; | 6045 _enclosingFunction = node.element; |
6065 _overrideManager.enterScope(); | 6046 _overrideManager.enterScope(); |
6066 try { | 6047 try { |
6067 DartType functionType = InferenceContext.getType(node); | 6048 DartType functionType = InferenceContext.getType(node); |
6068 if (functionType is FunctionType) { | 6049 if (functionType is FunctionType) { |
6069 functionType = | 6050 functionType = |
6070 matchFunctionTypeParameters(node.typeParameters, functionType); | 6051 matchFunctionTypeParameters(node.typeParameters, functionType); |
6071 if (functionType is FunctionType) { | 6052 if (functionType is FunctionType) { |
6072 _inferFormalParameterList(node.parameters, functionType); | 6053 _inferFormalParameterList(node.parameters, functionType); |
6073 | 6054 InferenceContext.setType( |
6074 DartType returnType; | 6055 node.body, _computeReturnOrYieldType(functionType.returnType)); |
6075 ParameterElement parameterElement = | |
6076 resolutionMap.staticParameterElementForExpression(node); | |
6077 if (isFutureThen(parameterElement?.enclosingElement)) { | |
6078 var futureThenType = | |
6079 InferenceContext.getContext(node.parent) as FunctionType; | |
6080 | |
6081 // Pretend the return type of Future<T>.then<S> first parameter is | |
6082 // | |
6083 // T -> (S | Future<S>) | |
6084 // | |
6085 // We can't represent this in Dart so we populate it here during | |
6086 // inference. | |
6087 var typeParamS = | |
6088 futureThenType.returnType.flattenFutures(typeSystem); | |
6089 returnType = | |
6090 FutureUnionType.from(typeParamS, typeProvider, typeSystem); | |
6091 } else { | |
6092 returnType = _computeReturnOrYieldType(functionType.returnType); | |
6093 } | |
6094 | |
6095 InferenceContext.setType(node.body, returnType); | |
6096 } | 6056 } |
6097 } | 6057 } |
6098 super.visitFunctionExpression(node); | 6058 super.visitFunctionExpression(node); |
6099 } finally { | 6059 } finally { |
6100 _overrideManager.exitScope(); | 6060 _overrideManager.exitScope(); |
6101 } | 6061 } |
6102 } finally { | 6062 } finally { |
6103 _currentFunctionBody = outerFunctionBody; | 6063 _currentFunctionBody = outerFunctionBody; |
6104 _enclosingFunction = outerFunction; | 6064 _enclosingFunction = outerFunction; |
6105 } | 6065 } |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6214 // have not already inferred something. However, the obvious ways to | 6174 // have not already inferred something. However, the obvious ways to |
6215 // check this don't work, since we may have been instantiated | 6175 // check this don't work, since we may have been instantiated |
6216 // to bounds in an earlier phase, and we *do* want to do inference | 6176 // to bounds in an earlier phase, and we *do* want to do inference |
6217 // in that case. | 6177 // in that case. |
6218 if (classTypeName.typeArguments == null) { | 6178 if (classTypeName.typeArguments == null) { |
6219 // Given a union of context types ` T0 | T1 | ... | Tn`, find the first | 6179 // Given a union of context types ` T0 | T1 | ... | Tn`, find the first |
6220 // valid instantiation `new C<Ti>`, if it exists. | 6180 // valid instantiation `new C<Ti>`, if it exists. |
6221 // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>` | 6181 // TODO(jmesserly): if we support union types for real, `new C<Ti | Tj>` |
6222 // will become a valid possibility. Right now the only allowed union is | 6182 // will become a valid possibility. Right now the only allowed union is |
6223 // `T | Future<T>` so we can take a simple approach. | 6183 // `T | Future<T>` so we can take a simple approach. |
6224 for (var contextType in InferenceContext.getTypes(node)) { | 6184 for (var contextType in inferenceContext.getTypes(node)) { |
6225 if (contextType is InterfaceType && | 6185 if (contextType is InterfaceType && |
6226 contextType.typeArguments != null && | 6186 contextType.typeArguments != null && |
6227 contextType.typeArguments.isNotEmpty) { | 6187 contextType.typeArguments.isNotEmpty) { |
6228 // TODO(jmesserly): for generic methods we use the | 6188 // TODO(jmesserly): for generic methods we use the |
6229 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to | 6189 // StrongTypeSystemImpl.inferGenericFunctionCall, which appears to |
6230 // be a tad more powerful than matchTypes. | 6190 // be a tad more powerful than matchTypes. |
6231 // | 6191 // |
6232 // For example it can infer this case: | 6192 // For example it can infer this case: |
6233 // | 6193 // |
6234 // class E<S, T> extends A<C<S>, T> { ... } | 6194 // class E<S, T> extends A<C<S>, T> { ... } |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
6650 InterfaceType rawType = isAsynchronous | 6610 InterfaceType rawType = isAsynchronous |
6651 ? typeProvider.streamDynamicType | 6611 ? typeProvider.streamDynamicType |
6652 : typeProvider.iterableDynamicType; | 6612 : typeProvider.iterableDynamicType; |
6653 // Match the types to instantiate the type arguments if possible | 6613 // Match the types to instantiate the type arguments if possible |
6654 List<DartType> typeArgs = | 6614 List<DartType> typeArgs = |
6655 inferenceContext.matchTypes(rawType, declaredType); | 6615 inferenceContext.matchTypes(rawType, declaredType); |
6656 return (typeArgs?.length == 1) ? typeArgs[0] : null; | 6616 return (typeArgs?.length == 1) ? typeArgs[0] : null; |
6657 } | 6617 } |
6658 // async functions expect `Future<T> | T` | 6618 // async functions expect `Future<T> | T` |
6659 var futureTypeParam = declaredType.flattenFutures(typeSystem); | 6619 var futureTypeParam = declaredType.flattenFutures(typeSystem); |
6660 return FutureUnionType.from(futureTypeParam, typeProvider, typeSystem); | 6620 return _createFutureOr(futureTypeParam); |
6661 } | 6621 } |
6662 return declaredType; | 6622 return declaredType; |
6663 } | 6623 } |
6664 | 6624 |
6665 /** | 6625 /** |
6626 * Creates a union of `T | Future<T>`, unless `T` is already a future or a | |
6627 * future-union, in which case it simply returns `T`. | |
6628 * | |
6629 * Conceptually this is used as the inverse of the `flatten(T)` operation, | |
6630 * defined as: | |
6631 * | |
6632 * - `flatten(Future<T>) -> T` | |
6633 * - `flatten(T) -> T` | |
6634 * | |
6635 * Thus the inverse will give us `T | Future<T>`. | |
6636 * | |
6637 * If [type] is top (dynamic or Object) then the resulting union type is | |
Leaf
2017/01/24 21:56:26
Can you give some examples of why you want to do t
Jennifer Messerly
2017/01/25 00:33:35
This code already existed -- it was moved from "Fu
| |
6638 * equivalent to top, so we simply return it. | |
6639 * | |
6640 * If [type] is bottom, it is equivalent to `Future<bottom>` | |
6641 * | |
6642 * For a similar reason `Future<T> | Future<Future<T>>` is equivalent to just | |
Leaf
2017/01/24 21:56:26
I'd really like to avoid putting this in if at all
Jennifer Messerly
2017/01/25 00:33:35
(same comment as above -- this code already existe
| |
6643 * `Future<T>`, so we return it. Note that it is not possible to get a | |
6644 * `Future<T>` as a result of `flatten`, so a this case likely indicates a | |
6645 * type error in the code, but it will be reported elsewhere. | |
6646 */ | |
6647 DartType _createFutureOr(DartType type) { | |
6648 if (type.isObject || type.isDynamic) { | |
6649 return type; | |
6650 } | |
6651 if (!identical(type, type.flattenFutures(typeSystem))) { | |
6652 // As noted above, this most likely represents erroneous input. | |
6653 return type; | |
6654 } | |
6655 if (type.isDartAsyncFutureOr) { | |
6656 return type; | |
6657 } | |
6658 if (type.isBottom) { | |
6659 return typeProvider.futureType.instantiate([type]); | |
6660 } | |
6661 return typeProvider.futureOrType.instantiate([type]); | |
6662 } | |
6663 | |
6664 /** | |
6666 * The given expression is the expression used to compute the iterator for a | 6665 * The given expression is the expression used to compute the iterator for a |
6667 * for-each statement. Attempt to compute the type of objects that will be | 6666 * for-each statement. Attempt to compute the type of objects that will be |
6668 * assigned to the loop variable and return that type. Return `null` if the | 6667 * assigned to the loop variable and return that type. Return `null` if the |
6669 * type could not be determined. The [iteratorExpression] is the expression | 6668 * type could not be determined. The [iteratorExpression] is the expression |
6670 * that will return the Iterable being iterated over. | 6669 * that will return the Iterable being iterated over. |
6671 */ | 6670 */ |
6672 DartType _getIteratorElementType(Expression iteratorExpression) { | 6671 DartType _getIteratorElementType(Expression iteratorExpression) { |
6673 DartType expressionType = iteratorExpression.bestType; | 6672 DartType expressionType = iteratorExpression.bestType; |
6674 if (expressionType is InterfaceType) { | 6673 if (expressionType is InterfaceType) { |
6675 PropertyAccessorElement iteratorFunction = | 6674 PropertyAccessorElement iteratorFunction = |
(...skipping 1604 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
8280 if (!elementValid) { | 8279 if (!elementValid) { |
8281 if (element is MultiplyDefinedElement) { | 8280 if (element is MultiplyDefinedElement) { |
8282 _setElement(typeName, element); | 8281 _setElement(typeName, element); |
8283 } | 8282 } |
8284 typeName.staticType = undefinedType; | 8283 typeName.staticType = undefinedType; |
8285 node.type = undefinedType; | 8284 node.type = undefinedType; |
8286 return; | 8285 return; |
8287 } | 8286 } |
8288 DartType type = null; | 8287 DartType type = null; |
8289 if (element is ClassElement) { | 8288 if (element is ClassElement) { |
8289 type = element.type; | |
8290 // In non-strong mode `FutureOr<T>` is treated as `dynamic` | |
8291 if (!typeSystem.isStrong && type.isDartAsyncFutureOr) { | |
8292 type = dynamicType; | |
8293 _setElement(typeName, type.element); | |
8294 typeName.staticType = type; | |
8295 node.type = type; | |
8296 if (argumentList != null) { | |
8297 NodeList<TypeAnnotation> arguments = argumentList.arguments; | |
8298 if (arguments.length != 1) { | |
8299 reportErrorForNode(_getInvalidTypeParametersErrorCode(node), node, | |
8300 [typeName.name, 1, arguments.length]); | |
8301 } | |
8302 } | |
8303 return; | |
8304 } | |
8290 _setElement(typeName, element); | 8305 _setElement(typeName, element); |
8291 type = element.type; | |
8292 } else if (element is FunctionTypeAliasElement) { | 8306 } else if (element is FunctionTypeAliasElement) { |
8293 _setElement(typeName, element); | 8307 _setElement(typeName, element); |
8294 type = element.type; | 8308 type = element.type; |
8295 } else if (element is TypeParameterElement) { | 8309 } else if (element is TypeParameterElement) { |
8296 _setElement(typeName, element); | 8310 _setElement(typeName, element); |
8297 type = element.type; | 8311 type = element.type; |
8298 // if (argumentList != null) { | 8312 // if (argumentList != null) { |
8299 // // Type parameters cannot have type arguments. | 8313 // // Type parameters cannot have type arguments. |
8300 // // TODO(brianwilkerson) Report this error. | 8314 // // TODO(brianwilkerson) Report this error. |
8301 // // resolver.reportError(ResolverErrorCode.?, keyType); | 8315 // // resolver.reportError(ResolverErrorCode.?, keyType); |
(...skipping 2520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10822 return null; | 10836 return null; |
10823 } | 10837 } |
10824 if (identical(node.staticElement, variable)) { | 10838 if (identical(node.staticElement, variable)) { |
10825 if (node.inSetterContext()) { | 10839 if (node.inSetterContext()) { |
10826 result = true; | 10840 result = true; |
10827 } | 10841 } |
10828 } | 10842 } |
10829 return null; | 10843 return null; |
10830 } | 10844 } |
10831 } | 10845 } |
OLD | NEW |