| Index: compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
|
| diff --git a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
|
| index 04a68412644be64a2dc3ea8ed19ac04e57adba9b..48bb4829e0bf96d35b71b4e0838333171284c5e7 100644
|
| --- a/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
|
| +++ b/compiler/java/com/google/dart/compiler/type/TypeAnalyzer.java
|
| @@ -107,7 +107,6 @@ import com.google.dart.compiler.resolver.ClassNodeElement;
|
| import com.google.dart.compiler.resolver.ConstructorElement;
|
| import com.google.dart.compiler.resolver.CoreTypeProvider;
|
| import com.google.dart.compiler.resolver.CyclicDeclarationException;
|
| -import com.google.dart.compiler.resolver.DuplicatedInterfaceException;
|
| import com.google.dart.compiler.resolver.Element;
|
| import com.google.dart.compiler.resolver.ElementKind;
|
| import com.google.dart.compiler.resolver.Elements;
|
| @@ -478,7 +477,7 @@ public class TypeAnalyzer implements DartCompilationPhase {
|
| onError(errorTarget, TypeErrorCode.PLUS_CANNOT_BE_USED_FOR_STRING_CONCAT, operator);
|
| }
|
| }
|
| -
|
| +
|
| /**
|
| * @return the best guess for operator token location in the given {@link DartNode}.
|
| */
|
| @@ -1239,12 +1238,43 @@ public class TypeAnalyzer implements DartCompilationPhase {
|
| sb);
|
| }
|
| }
|
| +
|
| + try {
|
| + checkClassDuplicateInterfaces(node, element, element.getAllSupertypes());
|
| + } catch (CyclicDeclarationException ignored) {
|
| + }
|
| +
|
| // Finish current class.
|
| setCurrentClass(null);
|
| return type;
|
| }
|
|
|
| /**
|
| + * Check for duplicate interfaces that aren't assignable to each other due to parameterization.
|
| + *
|
| + * Issue 3803: This isn't in the spec as of 0.10, adding as a 'value added' check, because there is no
|
| + * way to satisfy the method override rules without either causing errors in checked mode or
|
| + * causing override errors for every method implemented for this interface.
|
| + *
|
| + * @param classElement
|
| + */
|
| + private void checkClassDuplicateInterfaces(DartClass node, ClassElement classElement,
|
| + List<InterfaceType> allSupertypes) {
|
| + Map<Element, InterfaceType> elementMap = Maps.newHashMap();
|
| + for (InterfaceType supertype : allSupertypes) {
|
| + Element e = supertype.getElement();
|
| + if (e != null) {
|
| + InterfaceType foundType = elementMap.get(e);
|
| + if (foundType != null && ! types.isAssignable(supertype, foundType)) {
|
| + typeError(node.getName(), TypeErrorCode.INCOMPATIBLE_TYPES_IN_HIERARCHY, foundType.toString(),
|
| + supertype.toString());
|
| + } else {
|
| + elementMap.put(e, supertype);
|
| + }
|
| + }
|
| + }
|
| + }
|
| + /**
|
| * Checks that interface constructors have corresponding methods in default class.
|
| */
|
| private void checkInterfaceConstructors(ClassElement interfaceElement) {
|
| @@ -2500,14 +2530,19 @@ public class TypeAnalyzer implements DartCompilationPhase {
|
| } catch (CyclicDeclarationException e) {
|
| // Already reported by resolver.
|
| hasCyclicDeclaration = true;
|
| - } catch (DuplicatedInterfaceException e) {
|
| - // Already reported by resolver.
|
| }
|
|
|
| // Add all super members to resolve.
|
| Element currentLibrary = currentClass.getElement().getEnclosingElement();
|
| +
|
| + // cull out duplicate elements in the supertype list - inheriting more than one interface
|
| + // of the same type is valid.
|
| + Set<ClassElement> supertypeElements = Sets.newHashSet();
|
| for (InterfaceType supertype : supertypes) {
|
| - for (Element member : supertype.getElement().getMembers()) {
|
| + supertypeElements.add(supertype.getElement());
|
| + }
|
| + for (ClassElement interfaceElement : supertypeElements) {
|
| + for (Element member : interfaceElement.getMembers()) {
|
| String name = member.getName();
|
| if (DartIdentifier.isPrivateName(name)) {
|
| if (currentLibrary != member.getEnclosingElement().getEnclosingElement()) {
|
|
|