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

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

Issue 1555603002: Fix downwards inference for async and generator functions. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 11 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/element/element.dart'; 9 import 'package:analyzer/dart/element/element.dart';
10 import 'package:analyzer/dart/element/type.dart'; 10 import 'package:analyzer/dart/element/type.dart';
(...skipping 5397 matching lines...) Expand 10 before | Expand all | Expand 10 after
5408 5408
5409 /** 5409 /**
5410 * The type system in use. 5410 * The type system in use.
5411 */ 5411 */
5412 final TypeSystem _typeSystem; 5412 final TypeSystem _typeSystem;
5413 5413
5414 /** 5414 /**
5415 * A stack of return types for all of the enclosing 5415 * A stack of return types for all of the enclosing
5416 * functions and methods. 5416 * functions and methods.
5417 */ 5417 */
5418 // TODO(leafp) Handle the implicit union type for Futures
5418 List<DartType> _returnStack = <DartType>[]; 5419 List<DartType> _returnStack = <DartType>[];
5419 5420
5420 InferenceContext._(this._errorListener, TypeProvider typeProvider, 5421 InferenceContext._(this._errorListener, TypeProvider typeProvider,
5421 this._typeSystem, this._inferenceHints) 5422 this._typeSystem, this._inferenceHints)
5422 : _typeProvider = typeProvider; 5423 : _typeProvider = typeProvider;
5423 5424
5424 /** 5425 /**
5425 * Get the return type of the current enclosing function, if any. 5426 * Get the return type of the current enclosing function, if any.
5427 *
5428 * The type returned for a function is the type that is expected
5429 * to be used in a return or yield context. For ordinary functions
5430 * this is the same as the return type of the function. For async
5431 * functions returning Future<T> and for generator functions
5432 * returning Stream<T> or Iterable<T>, this is T.
5426 */ 5433 */
5427 DartType get returnContext => 5434 DartType get returnContext =>
5428 (_returnStack.isNotEmpty) ? _returnStack.last : null; 5435 (_returnStack.isNotEmpty) ? _returnStack.last : null;
Bob Nystrom 2015/12/30 01:03:39 Nit: the parentheses aren't needed here.
Leaf 2015/12/30 18:28:06 Done.
5429 5436
5430 /** 5437 /**
5431 * Match type [t1] against type [t2] as follows. 5438 * Match type [t1] against type [t2] as follows.
5432 * If `t1 = I<dynamic, ..., dynamic>`, then look for a supertype 5439 * If `t1 = I<dynamic, ..., dynamic>`, then look for a supertype
5433 * of t1 of the form `K<S0, ..., Sm>` where `t2 = K<S0', ..., Sm'>` 5440 * of t1 of the form `K<S0, ..., Sm>` where `t2 = K<S0', ..., Sm'>`
5434 * If the supertype exists, use the constraints `S0 <: S0', ... Sm <: Sm'` 5441 * If the supertype exists, use the constraints `S0 <: S0', ... Sm <: Sm'`
5435 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`, 5442 * to derive a concrete instantation for I of the form `<T0, ..., Tn>`,
5436 * such that `I<T0, .., Tn> <: t2` 5443 * such that `I<T0, .., Tn> <: t2`
5437 */ 5444 */
5438 List<DartType> matchTypes(DartType t1, DartType t2) => 5445 List<DartType> matchTypes(DartType t1, DartType t2) =>
(...skipping 2914 matching lines...) Expand 10 before | Expand all | Expand 10 after
8353 } 8360 }
8354 safelyVisit(node.rightHandSide); 8361 safelyVisit(node.rightHandSide);
8355 node.accept(elementResolver); 8362 node.accept(elementResolver);
8356 node.accept(typeAnalyzer); 8363 node.accept(typeAnalyzer);
8357 return null; 8364 return null;
8358 } 8365 }
8359 8366
8360 @override 8367 @override
8361 Object visitAwaitExpression(AwaitExpression node) { 8368 Object visitAwaitExpression(AwaitExpression node) {
8362 //TODO(leafp): Handle the implicit union type here 8369 //TODO(leafp): Handle the implicit union type here
8363 DartType contextType = InferenceContext.getType(node); 8370 DartType contextType = StaticTypeAnalyzer.flattenFutures(
8371 typeProvider, InferenceContext.getType(node));
8364 if (contextType != null) { 8372 if (contextType != null) {
8365 InterfaceType futureT = 8373 InterfaceType futureT =
8366 typeProvider.futureType.substitute4([contextType]); 8374 typeProvider.futureType.substitute4([contextType]);
8367 InferenceContext.setType(node.expression, futureT); 8375 InferenceContext.setType(node.expression, futureT);
8368 } 8376 }
8369 return super.visitAwaitExpression(node); 8377 return super.visitAwaitExpression(node);
8370 } 8378 }
8371 8379
8372 @override 8380 @override
8373 Object visitBinaryExpression(BinaryExpression node) { 8381 Object visitBinaryExpression(BinaryExpression node) {
(...skipping 513 matching lines...) Expand 10 before | Expand all | Expand 10 after
8887 @override 8895 @override
8888 Object visitFunctionExpression(FunctionExpression node) { 8896 Object visitFunctionExpression(FunctionExpression node) {
8889 ExecutableElement outerFunction = _enclosingFunction; 8897 ExecutableElement outerFunction = _enclosingFunction;
8890 try { 8898 try {
8891 _enclosingFunction = node.element; 8899 _enclosingFunction = node.element;
8892 _overrideManager.enterScope(); 8900 _overrideManager.enterScope();
8893 try { 8901 try {
8894 DartType functionType = InferenceContext.getType(node); 8902 DartType functionType = InferenceContext.getType(node);
8895 if (functionType is FunctionType) { 8903 if (functionType is FunctionType) {
8896 _inferFormalParameterList(node.parameters, functionType); 8904 _inferFormalParameterList(node.parameters, functionType);
8897 InferenceContext.setType(node.body, functionType.returnType); 8905 DartType returnType = _computeReturnOrYieldType(
8906 functionType.returnType,
8907 _enclosingFunction.isGenerator,
8908 _enclosingFunction.isAsynchronous);
8909 InferenceContext.setType(node.body, returnType);
8898 } 8910 }
8899 super.visitFunctionExpression(node); 8911 super.visitFunctionExpression(node);
8900 } finally { 8912 } finally {
8901 _overrideManager.exitScope(); 8913 _overrideManager.exitScope();
8902 } 8914 }
8903 } finally { 8915 } finally {
8904 _enclosingFunction = outerFunction; 8916 _enclosingFunction = outerFunction;
8905 } 8917 }
8906 return null; 8918 return null;
8907 } 8919 }
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after
9092 } 9104 }
9093 super.visitMapLiteral(node); 9105 super.visitMapLiteral(node);
9094 return null; 9106 return null;
9095 } 9107 }
9096 9108
9097 @override 9109 @override
9098 Object visitMethodDeclaration(MethodDeclaration node) { 9110 Object visitMethodDeclaration(MethodDeclaration node) {
9099 ExecutableElement outerFunction = _enclosingFunction; 9111 ExecutableElement outerFunction = _enclosingFunction;
9100 try { 9112 try {
9101 _enclosingFunction = node.element; 9113 _enclosingFunction = node.element;
9102 InferenceContext.setType(node.body, node.element.type?.returnType); 9114 DartType returnType = _computeReturnOrYieldType(
9115 _enclosingFunction.type?.returnType,
9116 _enclosingFunction.isGenerator,
9117 _enclosingFunction.isAsynchronous);
9118 InferenceContext.setType(node.body, returnType);
9103 super.visitMethodDeclaration(node); 9119 super.visitMethodDeclaration(node);
9104 } finally { 9120 } finally {
9105 _enclosingFunction = outerFunction; 9121 _enclosingFunction = outerFunction;
9106 } 9122 }
9107 return null; 9123 return null;
9108 } 9124 }
9109 9125
9110 @override 9126 @override
9111 void visitMethodDeclarationInScope(MethodDeclaration node) { 9127 void visitMethodDeclarationInScope(MethodDeclaration node) {
9112 super.visitMethodDeclarationInScope(node); 9128 super.visitMethodDeclarationInScope(node);
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after
9321 return null; 9337 return null;
9322 } 9338 }
9323 9339
9324 @override 9340 @override
9325 Object visitYieldStatement(YieldStatement node) { 9341 Object visitYieldStatement(YieldStatement node) {
9326 DartType returnType = inferenceContext.returnContext; 9342 DartType returnType = inferenceContext.returnContext;
9327 if (returnType != null && _enclosingFunction != null) { 9343 if (returnType != null && _enclosingFunction != null) {
9328 // If we're not in a generator ([a]sync*, then we shouldn't have a yield. 9344 // If we're not in a generator ([a]sync*, then we shouldn't have a yield.
9329 // so don't infer 9345 // so don't infer
9330 if (_enclosingFunction.isGenerator) { 9346 if (_enclosingFunction.isGenerator) {
9331 // If this is a yield*, then we just propagate the return type downwards 9347 // If this just a yield, then we just pass on the element type
9332 DartType type = returnType; 9348 DartType type = returnType;
9333 // If this just a yield, then we need to get the element type 9349 if (node.star != null) {
9334 if (node.star == null) { 9350 // If this is a yield*, then we wrap the element return type
9335 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T> 9351 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
9336 InterfaceType wrapperD = _enclosingFunction.isSynchronous 9352 InterfaceType wrapperType = _enclosingFunction.isSynchronous
9337 ? typeProvider.iterableDynamicType 9353 ? typeProvider.iterableType
9338 : typeProvider.streamDynamicType; 9354 : typeProvider.streamType;
9339 // Match the types to instantiate the type arguments if possible 9355 type = wrapperType.substitute4(<DartType>[type]);
9340 List<DartType> targs =
9341 inferenceContext.matchTypes(wrapperD, returnType);
9342 type = (targs?.length == 1) ? targs[0] : null;
9343 } 9356 }
9344 InferenceContext.setType(node.expression, type); 9357 InferenceContext.setType(node.expression, type);
9345 } 9358 }
9346 } 9359 }
9347 return super.visitYieldStatement(node); 9360 return super.visitYieldStatement(node);
9348 } 9361 }
9349 9362
9350 /** 9363 /**
9351 * Checks each promoted variable in the current scope for compliance with the following 9364 * Checks each promoted variable in the current scope for compliance with the following
9352 * specification statement: 9365 * specification statement:
(...skipping 20 matching lines...) Expand all
9373 */ 9386 */
9374 void _clearTypePromotionsIfPotentiallyMutatedIn(AstNode target) { 9387 void _clearTypePromotionsIfPotentiallyMutatedIn(AstNode target) {
9375 for (Element element in _promoteManager.promotedElements) { 9388 for (Element element in _promoteManager.promotedElements) {
9376 if (_isVariablePotentiallyMutatedIn(element, target)) { 9389 if (_isVariablePotentiallyMutatedIn(element, target)) {
9377 _promoteManager.setType(element, null); 9390 _promoteManager.setType(element, null);
9378 } 9391 }
9379 } 9392 }
9380 } 9393 }
9381 9394
9382 /** 9395 /**
9396 * Given the declared return type of a function, compute the type of the
9397 * values which should be returned or yielded as appropriate. If a type
9398 * cannot be computed from the declared return type, return null.
9399 */
9400 DartType _computeReturnOrYieldType(
9401 DartType declaredType, isGenerator, isAsynchronous) {
Bob Nystrom 2015/12/30 01:03:39 Type annotate isGenerator and isAsynchronous?
Leaf 2015/12/30 18:28:06 Done.
9402 // Ordinary functions just return their declared types.
9403 if (!isGenerator && !isAsynchronous) {
9404 return declaredType;
9405 }
9406 if (isGenerator) {
9407 if (declaredType is InterfaceType) {
Bob Nystrom 2015/12/30 01:03:39 You could avoid a little indentation by flipping t
Leaf 2015/12/30 18:28:06 Done.
9408 // If it's synchronous, we expect Iterable<T>, otherwise Stream<T>
9409 InterfaceType wrapperD = isAsynchronous
Bob Nystrom 2015/12/30 01:03:39 What does "D" mean here? "dynamic"? How about "raw
Leaf 2015/12/30 18:28:06 Done.
9410 ? typeProvider.streamDynamicType
9411 : typeProvider.iterableDynamicType;
9412 // Match the types to instantiate the type arguments if possible
9413 List<DartType> targs =
Bob Nystrom 2015/12/30 01:03:39 If "targs" isn't used much elsewhere, I'd use "typ
Leaf 2015/12/30 18:28:06 Done.
9414 inferenceContext.matchTypes(wrapperD, declaredType);
9415 return (targs?.length == 1) ? targs[0] : null;
9416 }
9417 // Not declared as an interface type, so leave it alone.
9418 return null;
9419 }
9420 // Must be asynchronous to reach here, so strip off any layers of Future
9421 return StaticTypeAnalyzer.flattenFutures(typeProvider, declaredType);
9422 }
9423
9424 /**
9383 * The given expression is the expression used to compute the iterator for a 9425 * The given expression is the expression used to compute the iterator for a
9384 * for-each statement. Attempt to compute the type of objects that will be 9426 * for-each statement. Attempt to compute the type of objects that will be
9385 * assigned to the loop variable and return that type. Return `null` if the 9427 * assigned to the loop variable and return that type. Return `null` if the
9386 * type could not be determined. The [iteratorExpression] is the expression 9428 * type could not be determined. The [iteratorExpression] is the expression
9387 * that will return the Iterable being iterated over. 9429 * that will return the Iterable being iterated over.
9388 */ 9430 */
9389 DartType _getIteratorElementType(Expression iteratorExpression) { 9431 DartType _getIteratorElementType(Expression iteratorExpression) {
9390 DartType expressionType = iteratorExpression.bestType; 9432 DartType expressionType = iteratorExpression.bestType;
9391 if (expressionType is InterfaceType) { 9433 if (expressionType is InterfaceType) {
9392 InterfaceType interfaceType = expressionType; 9434 InterfaceType interfaceType = expressionType;
(...skipping 3987 matching lines...) Expand 10 before | Expand all | Expand 10 after
13380 nonFields.add(node); 13422 nonFields.add(node);
13381 return null; 13423 return null;
13382 } 13424 }
13383 13425
13384 @override 13426 @override
13385 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this); 13427 Object visitNode(AstNode node) => node.accept(TypeResolverVisitor_this);
13386 13428
13387 @override 13429 @override
13388 Object visitWithClause(WithClause node) => null; 13430 Object visitWithClause(WithClause node) => null;
13389 } 13431 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/resolver_test.dart » ('j') | pkg/analyzer/test/generated/resolver_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698