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 |