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

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

Issue 2253923002: fix #27088, future then upwards inference (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 4 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
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/static_type_analyzer.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/token.dart'; 10 import 'package:analyzer/dart/ast/token.dart';
(...skipping 5740 matching lines...) Expand 10 before | Expand all | Expand 10 after
5751 } 5751 }
5752 5752
5753 /** 5753 /**
5754 * Prepares this [ResolverVisitor] to using it for incremental resolution. 5754 * Prepares this [ResolverVisitor] to using it for incremental resolution.
5755 */ 5755 */
5756 void initForIncrementalResolution() { 5756 void initForIncrementalResolution() {
5757 _overrideManager.enterScope(); 5757 _overrideManager.enterScope();
5758 } 5758 }
5759 5759
5760 /** 5760 /**
5761 * Returns true if this method is `Future.then`.
5762 *
5763 * If so we will apply special typing rules in strong mode, to handle the
5764 * implicit union of `S | Future<S>`
5765 */
5766 bool isFutureThen(Element element) {
5767 return element is MethodElement &&
5768 element.name == 'then' &&
5769 element.enclosingElement.type.isDartAsyncFuture;
5770 }
5771
5772 /**
5761 * Given a downward inference type [fnType], and the declared 5773 * Given a downward inference type [fnType], and the declared
5762 * [typeParameterList] for a function expression, determines if we can enable 5774 * [typeParameterList] for a function expression, determines if we can enable
5763 * downward inference and if so, returns the function type to use for 5775 * downward inference and if so, returns the function type to use for
5764 * inference. 5776 * inference.
5765 * 5777 *
5766 * This will return null if inference is not possible. This happens when 5778 * This will return null if inference is not possible. This happens when
5767 * there is no way we can find a subtype of the function type, given the 5779 * there is no way we can find a subtype of the function type, given the
5768 * provided type parameter list. 5780 * provided type parameter list.
5769 */ 5781 */
5770 FunctionType matchFunctionTypeParameters( 5782 FunctionType matchFunctionTypeParameters(
(...skipping 805 matching lines...) Expand 10 before | Expand all | Expand 10 after
6576 _overrideManager.enterScope(); 6588 _overrideManager.enterScope();
6577 try { 6589 try {
6578 DartType functionType = InferenceContext.getType(node); 6590 DartType functionType = InferenceContext.getType(node);
6579 if (functionType is FunctionType) { 6591 if (functionType is FunctionType) {
6580 functionType = 6592 functionType =
6581 matchFunctionTypeParameters(node.typeParameters, functionType); 6593 matchFunctionTypeParameters(node.typeParameters, functionType);
6582 if (functionType is FunctionType) { 6594 if (functionType is FunctionType) {
6583 _inferFormalParameterList(node.parameters, functionType); 6595 _inferFormalParameterList(node.parameters, functionType);
6584 6596
6585 DartType returnType; 6597 DartType returnType;
6586 if (_isFutureThenLambda(node)) { 6598 if (isFutureThen(node.staticParameterElement?.enclosingElement)) {
6587 var futureThenType = 6599 var futureThenType =
6588 InferenceContext.getContext(node.parent) as FunctionType; 6600 InferenceContext.getContext(node.parent) as FunctionType;
6589 6601
6590 // Pretend the return type of Future<T>.then<S> first parameter is 6602 // Pretend the return type of Future<T>.then<S> first parameter is
6591 // 6603 //
6592 // T -> (S | Future<S>) 6604 // T -> (S | Future<S>)
6593 // 6605 //
6594 // We can't represent this in Dart so we populate it here during 6606 // We can't represent this in Dart so we populate it here during
6595 // inference. 6607 // inference.
6596 returnType = FutureUnionType.from( 6608 returnType = FutureUnionType.from(
(...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after
7387 // 7399 //
7388 // Unsound to assume that [x = "hello";] never executed after the 7400 // Unsound to assume that [x = "hello";] never executed after the
7389 // if-statement. Of course, a dead-code analysis could point out that 7401 // if-statement. Of course, a dead-code analysis could point out that
7390 // [return] here is dead. 7402 // [return] here is dead.
7391 return _isAbruptTerminationStatement(statements[size - 1]); 7403 return _isAbruptTerminationStatement(statements[size - 1]);
7392 } 7404 }
7393 return false; 7405 return false;
7394 } 7406 }
7395 7407
7396 /** 7408 /**
7397 * Returns true if this expression is being passed to `Future.then`.
7398 *
7399 * If so we will apply special typing rules in strong mode, to handle the
7400 * implicit union of `S | Future<S>`
7401 */
7402 bool _isFutureThenLambda(FunctionExpression node) {
7403 Element element = node.staticParameterElement?.enclosingElement;
7404 return element is MethodElement &&
7405 element.name == 'then' &&
7406 element.enclosingElement.type.isDartAsyncFuture;
7407 }
7408
7409 /**
7410 * Return `true` if the given variable is accessed within a closure in the giv en 7409 * Return `true` if the given variable is accessed within a closure in the giv en
7411 * [AstNode] and also mutated somewhere in variable scope. This information is only 7410 * [AstNode] and also mutated somewhere in variable scope. This information is only
7412 * available for local variables (including parameters). 7411 * available for local variables (including parameters).
7413 * 7412 *
7414 * @param variable the variable to check 7413 * @param variable the variable to check
7415 * @param target the [AstNode] to check within 7414 * @param target the [AstNode] to check within
7416 * @return `true` if this variable is potentially mutated somewhere in the giv en ASTNode 7415 * @return `true` if this variable is potentially mutated somewhere in the giv en ASTNode
7417 */ 7416 */
7418 bool _isVariableAccessedInClosure(Element variable, AstNode target) { 7417 bool _isVariableAccessedInClosure(Element variable, AstNode target) {
7419 _ResolverVisitor_isVariableAccessedInClosure visitor = 7418 _ResolverVisitor_isVariableAccessedInClosure visitor =
(...skipping 3685 matching lines...) Expand 10 before | Expand all | Expand 10 after
11105 return null; 11104 return null;
11106 } 11105 }
11107 if (identical(node.staticElement, variable)) { 11106 if (identical(node.staticElement, variable)) {
11108 if (node.inSetterContext()) { 11107 if (node.inSetterContext()) {
11109 result = true; 11108 result = true;
11110 } 11109 }
11111 } 11110 }
11112 return null; 11111 return null;
11113 } 11112 }
11114 } 11113 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/generated/static_type_analyzer.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698