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

Unified Diff: pkg/analyzer/lib/src/generated/error_verifier.dart

Issue 2653873002: fix #28141, fix super generic method bounds check (Closed)
Patch Set: split loops and merge Created 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/analyzer/lib/src/dart/element/type.dart ('k') | pkg/analyzer/test/generated/strong_mode_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/generated/error_verifier.dart
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 346da5a6c23f5e2fcfded2096a5c41cfc90fb89c..ffef5db56d9e8e3af77f73dad77cd3321a68c279 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -821,7 +821,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
StaticTypeWarningCode.INVOCATION_OF_NON_FUNCTION_EXPRESSION,
functionExpression);
} else if (expressionType is FunctionType) {
- _checkTypeArguments(expressionType.element, node.typeArguments);
+ _checkTypeArguments(node);
}
_checkForImplicitDynamicInvoke(node);
return super.visitFunctionExpressionInvocation(node);
@@ -1032,8 +1032,7 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
} else {
_checkForUnqualifiedReferenceToNonLocalStaticMember(methodName);
}
- _checkTypeArguments(
- node.methodName.staticElement, node.typeArguments, target?.staticType);
+ _checkTypeArguments(node);
_checkForImplicitDynamicInvoke(node);
return super.visitMethodInvocation(node);
}
@@ -6156,72 +6155,38 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
*
* See [StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS].
*/
- void _checkTypeArguments(Element element, TypeArgumentList typeArguments,
- [DartType targetType]) {
- if (element == null || typeArguments == null) {
- return;
- }
- void reportError(TypeAnnotation argument, DartType argumentType,
- DartType parameterType) {
- _errorReporter.reportTypeErrorForNode(
- StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
- argument,
- [argumentType, parameterType]);
- }
-
- if (element is FunctionTypedElement) {
- _checkTypeArgumentsAgainstBounds(
- element.typeParameters, typeArguments, targetType, reportError);
- } else if (element is ClassElement) {
- _checkTypeArgumentsAgainstBounds(
- element.typeParameters, typeArguments, targetType, reportError);
- } else if (element is ParameterElement || element is LocalVariableElement) {
- // TODO(brianwilkerson) Implement this case
- } else {
- print('Unhandled element type: ${element.runtimeType}');
- }
- }
-
- void _checkTypeArgumentsAgainstBounds(
- List<TypeParameterElement> typeParameters,
- TypeArgumentList typeArgumentList,
- DartType targetType,
- void reportError(TypeAnnotation argument, DartType argumentType,
- DartType parameterType)) {
- NodeList<TypeAnnotation> typeArguments = typeArgumentList.arguments;
- int argumentsLength = typeArguments.length;
- int maxIndex = math.min(typeParameters.length, argumentsLength);
-
- bool shouldSubstitute =
- argumentsLength != 0 && argumentsLength == typeParameters.length;
- List<DartType> argumentTypes = shouldSubstitute
- ? typeArguments.map((TypeAnnotation type) => type.type).toList()
- : null;
- List<DartType> parameterTypes = shouldSubstitute
- ? typeParameters
- .map((TypeParameterElement element) => element.type)
- .toList()
- : null;
- List<DartType> targetTypeParameterTypes = null;
- for (int i = 0; i < maxIndex; i++) {
- TypeAnnotation argument = typeArguments[i];
- DartType argType = argument.type;
- DartType boundType = typeParameters[i].bound;
- if (argType != null && boundType != null) {
- if (targetType is ParameterizedType) {
- if (targetTypeParameterTypes == null) {
- targetTypeParameterTypes = targetType.typeParameters
- .map((TypeParameterElement element) => element.type)
- .toList();
- }
- boundType = boundType.substitute2(
- targetType.typeArguments, targetTypeParameterTypes);
- }
- if (shouldSubstitute) {
- boundType = boundType.substitute2(argumentTypes, parameterTypes);
- }
- if (!_typeSystem.isSubtypeOf(argType, boundType)) {
- reportError(argument, argType, boundType);
+ void _checkTypeArguments(InvocationExpression node) {
+ NodeList<TypeAnnotation> typeArgumentList = node.typeArguments?.arguments;
+ if (typeArgumentList == null) {
+ return;
+ }
+
+ var genericType = node.function.staticType;
+ var instantiatedType = node.staticInvokeType;
+ if (genericType is FunctionType && instantiatedType is FunctionType) {
+ var fnTypeParams =
+ TypeParameterTypeImpl.getTypes(genericType.typeFormals);
+ var typeArgs = typeArgumentList.map((t) => t.type).toList();
+
+ for (int i = 0, len = math.min(typeArgs.length, fnTypeParams.length);
+ i < len;
+ i++) {
+ // Check the `extends` clause for the type parameter, if any.
+ //
+ // Also substitute to handle cases like this:
+ //
+ // <TFrom, TTo extends TFrom>
+ // <TFrom, TTo extends Iterable<TFrom>>
+ // <T extends Clonable<T>>
+ //
+ DartType argType = typeArgs[i];
+ DartType bound =
+ fnTypeParams[i].bound.substitute2(typeArgs, fnTypeParams);
+ if (!_typeSystem.isSubtypeOf(argType, bound)) {
+ _errorReporter.reportTypeErrorForNode(
+ StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
+ typeArgumentList[i],
+ [argType, bound]);
}
}
}
« no previous file with comments | « pkg/analyzer/lib/src/dart/element/type.dart ('k') | pkg/analyzer/test/generated/strong_mode_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698