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 094b3e4b3ae5bf21a91ec67e384981f5dd6dd2dd..5a4fe450a1db043db2e2f870d7dda157f4f961e3 100644 |
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart |
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart |
@@ -1347,6 +1347,71 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
if (overridingFT == null || overriddenFT == null) { |
return false; |
} |
+ |
+ // Handle generic function type parameters. |
+ // TODO(jmesserly): this duplicates some code in isSubtypeOf and most of |
+ // _isGenericFunctionSubtypeOf. Ideally, we'd let TypeSystem produce |
+ // an error message once it's ready to "return false". |
+ if (!overridingFT.boundTypeParameters.isEmpty) { |
+ if (overriddenFT.boundTypeParameters.isEmpty) { |
+ overriddenFT = _typeSystem.instantiateToBounds(overriddenFT); |
+ } else { |
+ List<TypeParameterElement> params1 = overridingFT.boundTypeParameters; |
+ List<TypeParameterElement> params2 = overriddenFT.boundTypeParameters; |
+ int count = params1.length; |
+ if (params2.length != count) { |
+ _errorReporter.reportErrorForNode( |
+ StaticWarningCode.INVALID_METHOD_OVERRIDE_TYPE_PARAMETERS, |
+ errorNameTarget, [ |
+ count, |
+ params2.length, |
+ overriddenExecutable.enclosingElement.displayName |
+ ]); |
+ return true; |
+ } |
+ // We build up a substitution matching up the type parameters |
+ // from the two types, {variablesFresh/variables1} and |
+ // {variablesFresh/variables2} |
+ List<DartType> variables1 = new List<DartType>(); |
+ List<DartType> variables2 = new List<DartType>(); |
+ List<DartType> variablesFresh = new List<DartType>(); |
+ for (int i = 0; i < count; i++) { |
+ TypeParameterElement p1 = params1[i]; |
+ TypeParameterElement p2 = params2[i]; |
+ TypeParameterElementImpl pFresh = |
+ new TypeParameterElementImpl(p1.name, -1); |
+ |
+ DartType variable1 = p1.type; |
+ DartType variable2 = p2.type; |
+ DartType variableFresh = new TypeParameterTypeImpl(pFresh); |
+ |
+ variables1.add(variable1); |
+ variables2.add(variable2); |
+ variablesFresh.add(variableFresh); |
+ DartType bound1 = p1.bound ?? DynamicTypeImpl.instance; |
+ DartType bound2 = p2.bound ?? DynamicTypeImpl.instance; |
+ bound1 = bound1.substitute2(variablesFresh, variables1); |
+ bound2 = bound2.substitute2(variablesFresh, variables2); |
+ pFresh.bound = bound2; |
+ if (!_typeSystem.isSubtypeOf(bound2, bound1)) { |
+ _errorReporter.reportErrorForNode( |
+ StaticWarningCode.INVALID_METHOD_OVERRIDE_TYPE_PARAMETER_BOUND, |
+ errorNameTarget, [ |
+ p1.displayName, |
+ p1.bound, |
+ p2.displayName, |
+ p2.bound, |
+ overriddenExecutable.enclosingElement.displayName |
+ ]); |
+ return true; |
+ } |
+ } |
+ // Proceed with the rest of the checks, using instantiated types. |
+ overridingFT = overridingFT.instantiate(variablesFresh); |
+ overriddenFT = overriddenFT.instantiate(variablesFresh); |
+ } |
+ } |
+ |
DartType overridingFTReturnType = overridingFT.returnType; |
DartType overriddenFTReturnType = overriddenFT.returnType; |
List<DartType> overridingNormalPT = overridingFT.normalParameterTypes; |