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..951b6688fac0b9351b1362206d66ede3d5befb36 100644 |
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart |
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart |
@@ -1347,6 +1347,76 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> { |
if (overridingFT == null || overriddenFT == null) { |
return false; |
} |
+ |
+ // Handle generic function type parameters. |
+ // TODO(jmesserly): generic methods should work without strong mode, |
+ // however "instantiateToBounds" is currently on StrongTypeSystemImpl. |
Leaf
2015/12/09 22:02:29
The non-strong mode semantics might be different,
Jennifer Messerly
2015/12/09 22:37:41
Done. Fixed this TODO by implementing the right lo
|
+ TypeSystem ts = _typeSystem; |
+ if (ts is StrongTypeSystemImpl) { |
+ // 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". |
Leaf
2015/12/09 22:02:29
Yeah, this seems like it would work out well. May
Jennifer Messerly
2015/12/09 22:37:41
Sounds good. I don't want to try that restructure
|
+ if (!overridingFT.boundTypeParameters.isEmpty) { |
+ if (overriddenFT.boundTypeParameters.isEmpty) { |
+ overriddenFT = ts.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(p2.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 (!ts.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. |
Leaf
2015/12/09 22:02:29
The error messages that we get from the rest of th
Jennifer Messerly
2015/12/09 22:37:41
Eeeep good catch. I've switch it to use the "overr
|
+ overridingFT = overridingFT.instantiate(variablesFresh); |
+ overriddenFT = overriddenFT.instantiate(variablesFresh); |
+ } |
+ } |
+ } |
+ |
DartType overridingFTReturnType = overridingFT.returnType; |
DartType overriddenFTReturnType = overriddenFT.returnType; |
List<DartType> overridingNormalPT = overridingFT.normalParameterTypes; |