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

Side by Side Diff: pkg/analyzer/lib/src/generated/resolver.dart

Issue 2647833002: fix #28008, fix #28009 implement FutureOr<T> (Closed)
Patch Set: Merge remote-tracking branch 'origin/master' into 28008_futureort Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library analyzer.src.generated.resolver; 5 library analyzer.src.generated.resolver;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 8
9 import 'package:analyzer/dart/ast/ast.dart'; 9 import 'package:analyzer/dart/ast/ast.dart';
10 import 'package:analyzer/dart/ast/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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « pkg/analyzer/lib/src/dart/element/type.dart ('k') | pkg/analyzer/lib/src/generated/static_type_analyzer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698