| 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;
|
|
|