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

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

Issue 1924113002: fix #26334, allow supertypes for async function returns in strong mode (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 7 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/test/generated/static_type_warning_code_test.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.error_verifier; 5 library analyzer.src.generated.error_verifier;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import "dart:math" as math; 8 import "dart:math" as math;
9 9
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 3422 matching lines...) Expand 10 before | Expand all | Expand 10 after
3433 * respectively. If not, report the error using [returnType]. 3433 * respectively. If not, report the error using [returnType].
3434 */ 3434 */
3435 void _checkForIllegalReturnType(TypeName returnType) { 3435 void _checkForIllegalReturnType(TypeName returnType) {
3436 if (returnType == null) { 3436 if (returnType == null) {
3437 // No declared return type, so the return type must be dynamic, which is 3437 // No declared return type, so the return type must be dynamic, which is
3438 // assignable to everything. 3438 // assignable to everything.
3439 return; 3439 return;
3440 } 3440 }
3441 if (_enclosingFunction.isAsynchronous) { 3441 if (_enclosingFunction.isAsynchronous) {
3442 if (_enclosingFunction.isGenerator) { 3442 if (_enclosingFunction.isGenerator) {
3443 if (_options.strongMode) { 3443 _checkForIllegalReturnTypeCode(
3444 if (_enclosingFunction.returnType.element != 3444 returnType,
3445 _typeProvider.streamType.element) { 3445 _typeProvider.streamDynamicType,
3446 _errorReporter.reportErrorForNode( 3446 StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE);
3447 StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
3448 returnType);
3449 }
3450 } else if (!_typeSystem.isAssignableTo(
3451 _enclosingFunction.returnType, _typeProvider.streamDynamicType)) {
3452 _errorReporter.reportErrorForNode(
3453 StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
3454 returnType);
3455 }
3456 } else { 3447 } else {
3457 if (_options.strongMode) { 3448 _checkForIllegalReturnTypeCode(
3458 if (_enclosingFunction.returnType.element != 3449 returnType,
3459 _typeProvider.futureType.element) { 3450 _typeProvider.futureDynamicType,
3460 _errorReporter.reportErrorForNode( 3451 StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE);
3461 StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, returnType);
3462 }
3463 } else if (!_typeSystem.isAssignableTo(
3464 _enclosingFunction.returnType, _typeProvider.futureDynamicType)) {
3465 _errorReporter.reportErrorForNode(
3466 StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE, returnType);
3467 }
3468 } 3452 }
3469 } else if (_enclosingFunction.isGenerator) { 3453 } else if (_enclosingFunction.isGenerator) {
3470 if (!_typeSystem.isAssignableTo( 3454 _checkForIllegalReturnTypeCode(
3471 _enclosingFunction.returnType, _typeProvider.iterableDynamicType)) { 3455 returnType,
3472 _errorReporter.reportErrorForNode( 3456 _typeProvider.iterableDynamicType,
3473 StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE, 3457 StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE);
3474 returnType);
3475 }
3476 } 3458 }
3477 } 3459 }
3478 3460
3461 /**
3462 * If the current function is async, async*, or sync*, verify that its
3463 * declared return type is assignable to Future, Stream, or Iterable,
3464 * respectively. This is called by [_checkForIllegalReturnType] to check if
3465 * the declared [returnTypeName] is assignable to the required [expectedType]
3466 * and if not report [errorCode].
3467 */
3468 void _checkForIllegalReturnTypeCode(TypeName returnTypeName,
3469 DartType expectedType, StaticTypeWarningCode errorCode) {
3470 DartType returnType = _enclosingFunction.returnType;
3471 if (_options.strongMode) {
3472 //
3473 // When checking an async/sync*/async* method, we know the exact type
3474 // that will be returned (e.g. Future, Iterable, or Stream).
3475 //
3476 // For example an `async` function body will return a `Future<T>` for
3477 // some `T` (possibly `dynamic`).
3478 //
3479 // We allow the declared return type to be a supertype of that
3480 // (e.g. `dynamic`, `Object`), or Future<S> for some S.
3481 // (We assume the T <: S relation is checked elsewhere.)
3482 //
3483 // We do not allow user-defined subtypes of Future, because an `async`
3484 // method will never return those.
3485 //
3486 // To check for this, we ensure that `Future<bottom> <: returnType`.
3487 //
3488 // Similar logic applies for sync* and async*.
3489 //
3490 InterfaceType genericType = (expectedType.element as ClassElement).type;
3491 DartType lowerBound = genericType.instantiate([BottomTypeImpl.instance]);
3492 if (!_typeSystem.isSubtypeOf(lowerBound, returnType)) {
3493 _errorReporter.reportErrorForNode(errorCode, returnTypeName);
3494 }
3495 } else if (!_typeSystem.isAssignableTo(returnType, expectedType)) {
3496 _errorReporter.reportErrorForNode(errorCode, returnTypeName);
3497 }
3498 }
3499
3479 /** 3500 /**
3480 * Verify that the given implements [clause] does not implement classes that 3501 * Verify that the given implements [clause] does not implement classes that
3481 * are deferred. 3502 * are deferred.
3482 * 3503 *
3483 * See [CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS]. 3504 * See [CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS].
3484 */ 3505 */
3485 void _checkForImplementsDeferredClass(ImplementsClause clause) { 3506 void _checkForImplementsDeferredClass(ImplementsClause clause) {
3486 if (clause == null) { 3507 if (clause == null) {
3487 return; 3508 return;
3488 } 3509 }
(...skipping 2649 matching lines...) Expand 10 before | Expand all | Expand 10 after
6138 class _InvocationCollector extends RecursiveAstVisitor { 6159 class _InvocationCollector extends RecursiveAstVisitor {
6139 final List<String> superCalls = <String>[]; 6160 final List<String> superCalls = <String>[];
6140 6161
6141 @override 6162 @override
6142 visitMethodInvocation(MethodInvocation node) { 6163 visitMethodInvocation(MethodInvocation node) {
6143 if (node.target is SuperExpression) { 6164 if (node.target is SuperExpression) {
6144 superCalls.add(node.methodName.name); 6165 superCalls.add(node.methodName.name);
6145 } 6166 }
6146 } 6167 }
6147 } 6168 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/generated/static_type_warning_code_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698