Stop using 'Element.type' in ErrorVerifier.

Change-Id: I8313bccb7bf302fd80fa2da1e5256e1e40998fa8
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/119041
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2019-09-26 20:17:28 +00:00 committed by commit-bot@chromium.org
parent 1707aff921
commit 402951b399
2 changed files with 69 additions and 37 deletions

View file

@ -9,6 +9,7 @@ import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/visitor.dart';
import 'package:analyzer/error/error.dart';
@ -1378,7 +1379,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
void visitTypeParameter(TypeParameter node) {
_checkForBuiltInIdentifierAsName(node.name,
CompileTimeErrorCode.BUILT_IN_IDENTIFIER_AS_TYPE_PARAMETER_NAME);
_checkForTypeParameterSupertypeOfItsBound(node);
_checkForTypeAnnotationDeferredClass(node.bound);
_checkForImplicitDynamicType(node.bound);
_checkForGenericFunctionType(node.bound);
@ -1389,6 +1389,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
@override
void visitTypeParameterList(TypeParameterList node) {
_duplicateDefinitionVerifier.checkTypeParameters(node);
_checkForTypeParameterBoundRecursion(node.typeParameters);
super.visitTypeParameterList(node);
}
@ -3114,20 +3115,23 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
if (_enclosingFunction.isAsynchronous) {
if (_enclosingFunction.isGenerator) {
_checkForIllegalReturnTypeCode(
returnType,
_typeProvider.streamDynamicType,
StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE);
returnType,
_typeProvider.streamElement,
StaticTypeWarningCode.ILLEGAL_ASYNC_GENERATOR_RETURN_TYPE,
);
} else {
_checkForIllegalReturnTypeCode(
returnType,
_typeProvider.futureDynamicType,
StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE);
returnType,
_typeProvider.futureElement,
StaticTypeWarningCode.ILLEGAL_ASYNC_RETURN_TYPE,
);
}
} else if (_enclosingFunction.isGenerator) {
_checkForIllegalReturnTypeCode(
returnType,
_typeProvider.iterableDynamicType,
StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE);
returnType,
_typeProvider.iterableElement,
StaticTypeWarningCode.ILLEGAL_SYNC_GENERATOR_RETURN_TYPE,
);
}
}
@ -3139,7 +3143,7 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
* and if not report [errorCode].
*/
void _checkForIllegalReturnTypeCode(TypeAnnotation returnTypeName,
DartType expectedType, StaticTypeWarningCode errorCode) {
ClassElement expectedElement, StaticTypeWarningCode errorCode) {
DartType returnType = _enclosingFunction.returnType;
//
// When checking an async/sync*/async* method, we know the exact type
@ -3159,8 +3163,10 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
//
// Similar logic applies for sync* and async*.
//
InterfaceType genericType = (expectedType.element as ClassElement).type;
DartType lowerBound = genericType.instantiate([BottomTypeImpl.instance]);
var lowerBound = expectedElement.instantiate(
typeArguments: [BottomTypeImpl.instance],
nullabilitySuffix: NullabilitySuffix.star,
);
if (!_typeSystem.isSubtypeOf(lowerBound, returnType)) {
_errorReporter.reportErrorForNode(errorCode, returnTypeName);
}
@ -4931,6 +4937,44 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
}
}
/**
* Check that none of the type [parameters] references itself in its bound.
*
* See [StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND].
*/
void _checkForTypeParameterBoundRecursion(List<TypeParameter> parameters) {
Map<TypeParameterElement, TypeParameter> elementToNode;
for (var parameter in parameters) {
if (parameter.bound != null) {
if (elementToNode == null) {
elementToNode = {};
for (var parameter in parameters) {
elementToNode[parameter.declaredElement] = parameter;
}
}
TypeParameter current = parameter;
for (var step = 0; current != null; step++) {
var bound = current.bound;
if (bound is TypeName) {
current = elementToNode[bound.name.staticElement];
} else {
current = null;
}
if (step == parameters.length) {
var element = parameter.declaredElement;
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
parameter,
[element.displayName, element.bound.displayName],
);
break;
}
}
}
}
}
void _checkForTypeParameterReferencedByStatic(SimpleIdentifier identifier) {
if (_isInStaticMethod || _isInStaticVariableDeclaration) {
var element = identifier.staticElement;
@ -4945,29 +4989,6 @@ class ErrorVerifier extends RecursiveAstVisitor<void> {
}
}
/**
* Check whether the given type [parameter] is a supertype of its bound.
*
* See [StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND].
*/
void _checkForTypeParameterSupertypeOfItsBound(TypeParameter parameter) {
TypeParameterElement element = parameter.declaredElement;
// prepare bound
DartType bound = element.bound;
if (bound == null) {
return;
}
// OK, type parameter is not supertype of its bound
if (!_typeSystem.isSubtypeOf(bound, element.type)) {
return;
}
_errorReporter.reportErrorForNode(
StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND,
parameter,
[element.displayName, bound.displayName]);
}
/**
* Check that if the given generative [constructor] has neither an explicit
* super constructor invocation nor a redirecting constructor invocation, that

View file

@ -1063,7 +1063,7 @@ void main() { }
]);
}
test_typeParameterSupertypeOfItsBound() async {
test_typeParameterSupertypeOfItsBound_1of1() async {
await assertErrorsInCode(r'''
class A<T extends T> {
}
@ -1072,6 +1072,17 @@ class A<T extends T> {
]);
}
test_typeParameterSupertypeOfItsBound_2of3() async {
await assertErrorsInCode(r'''
class A<T1 extends T3, T2, T3 extends T1> {
}
''', [
error(StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND, 8, 13),
error(
StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND, 27, 13),
]);
}
test_typePromotion_booleanAnd_useInRight_accessedInClosureRight_mutated() async {
await assertErrorsInCode(r'''
callMe(f()) { f(); }