diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java index 90504dd3d53..ab963f25dd1 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/LambdaExpression.java @@ -1438,7 +1438,7 @@ public ReferenceBinding superclass() { return LambdaExpression.this.scope.getJavaLangObject(); } @Override - public ReferenceBinding[] superInterfaces() { + protected ReferenceBinding[] superInterfacesRecursive(Map visited) { return new ReferenceBinding[] { (ReferenceBinding) LambdaExpression.this.resolvedType }; } @Override diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java index 1b78c076536..7e4f9c6c8ba 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/BinaryTypeBinding.java @@ -2524,10 +2524,12 @@ private void detectCircularHierarchy() { // NOTE: superInterfaces of binary types are resolved when needed @Override -public ReferenceBinding[] superInterfaces() { - +protected ReferenceBinding[] superInterfacesRecursive(Map visited) { + if (visited.put(this, this) != null) { // do not evaluate the same type twice + return this.superInterfaces; + } if (!isPrototype()) { - return this.superInterfaces = this.prototype.superInterfaces(); + return this.superInterfaces = this.prototype.superInterfacesRecursive(visited); // TODO (visjee) protect from duplicated calls } if ((this.tagBits & TagBits.HasUnresolvedSuperinterfaces) == 0) return this.superInterfaces; @@ -2541,7 +2543,7 @@ public ReferenceBinding[] superInterfaces() { boolean wasToleratingMissingTypeProcessingAnnotations = this.environment.mayTolerateMissingType; this.environment.mayTolerateMissingType = true; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=360164 try { - this.superInterfaces[i].superclass(); + this.superInterfaces[i].superclass(); // TODO (visjee) do I need to prevent duplicated calls here too? Probably NOT. if (this.superInterfaces[i].isParameterizedType()) { ReferenceBinding superType = this.superInterfaces[i].actualType(); if (TypeBinding.equalsEquals(superType, this)) { @@ -2549,7 +2551,7 @@ public ReferenceBinding[] superInterfaces() { continue; } } - this.superInterfaces[i].superInterfaces(); + this.superInterfaces[i].superInterfacesRecursive(visited); // TODO (visjee) protect from duplicated calls } finally { this.environment.mayTolerateMissingType = wasToleratingMissingTypeProcessingAnnotations; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java index d5e49337d48..6d7a6a22d3c 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/InferenceVariable.java @@ -174,7 +174,7 @@ void collectInferenceVariables(Set variables) { } @Override - public ReferenceBinding[] superInterfaces() { + protected ReferenceBinding[] superInterfacesRecursive(Map visited) { return Binding.NO_SUPERINTERFACES; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java index 13522cfacb0..2dfee38003c 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/IntersectionTypeBinding18.java @@ -23,6 +23,7 @@ package org.eclipse.jdt.internal.compiler.lookup; +import java.util.Map; import java.util.Set; import org.eclipse.jdt.internal.compiler.ast.Wildcard; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; @@ -153,7 +154,7 @@ public ReferenceBinding superclass() { } @Override - public ReferenceBinding [] superInterfaces() { + protected ReferenceBinding[] superInterfacesRecursive(Map visited) { if (this.intersectingTypes[0].isClass()) { ReferenceBinding [] superInterfaces = new ReferenceBinding[this.length - 1]; System.arraycopy(this.intersectingTypes, 1, superInterfaces, 0, this.length - 1); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java index 84aa3367237..1b641665c22 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ParameterizedTypeBinding.java @@ -1551,11 +1551,12 @@ public ReferenceBinding superclass() { * @see org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding#superInterfaces() */ @Override - public ReferenceBinding[] superInterfaces() { - if (this.superInterfaces == null) { + protected ReferenceBinding[] superInterfacesRecursive(Map visited) { + // TODO (visjee) protect from duplicated calls + if (this.superInterfaces == null && visited.put(this, this) == null) { if (this.type.isHierarchyBeingConnected()) return Binding.NO_SUPERINTERFACES; // prevent superinterfaces from being assigned before they are connected - this.superInterfaces = Scope.substitute(this, this.type.superInterfaces()); + this.superInterfaces = Scope.substitute(this, this.type.superInterfacesRecursive(visited)); if (this.superInterfaces != null) { for (int i = this.superInterfaces.length; --i >= 0;) { this.typeBits |= (this.superInterfaces[i].typeBits & TypeIds.InheritableBits); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java index 07343f825e8..bb734656611 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ProblemReferenceBinding.java @@ -15,6 +15,7 @@ package org.eclipse.jdt.internal.compiler.lookup; import java.lang.reflect.Field; +import java.util.Map; import org.eclipse.jdt.core.compiler.CharOperation; @SuppressWarnings("rawtypes") @@ -60,10 +61,10 @@ public ReferenceBinding superclass() { } @Override -public ReferenceBinding[] superInterfaces() { +protected ReferenceBinding[] superInterfacesRecursive(Map visited) { if (this.closestMatch != null) - return this.closestMatch.superInterfaces(); - return super.superInterfaces(); + return this.closestMatch.superInterfacesRecursive(visited); // TODO (visjee) protect from duplicated calls + return super.superInterfacesRecursive(visited); } @Override diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java index 0ae383e631c..e21bcb3faf7 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/ReferenceBinding.java @@ -57,6 +57,7 @@ import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -2098,7 +2099,11 @@ public ReferenceBinding superclass() { } @Override -public ReferenceBinding[] superInterfaces() { +public final ReferenceBinding[] superInterfaces() { + return superInterfacesRecursive(new IdentityHashMap<>()); +} + +protected ReferenceBinding[] superInterfacesRecursive(Map visited) { return Binding.NO_SUPERINTERFACES; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java index dbee8e55626..0b271703448 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/SourceTypeBinding.java @@ -3178,9 +3178,9 @@ public ReferenceBinding superclass() { } @Override -public ReferenceBinding[] superInterfaces() { - if (!isPrototype()) - return this.superInterfaces = this.prototype.superInterfaces(); +protected ReferenceBinding[] superInterfacesRecursive(Map visited) { + if (!isPrototype() && visited.put(this, this) == null) + return this.superInterfaces = this.prototype.superInterfacesRecursive(visited); // TODO (visjee) protect from duplicated calls return this.superInterfaces != null ? this.superInterfaces : isAnnotationType() ? this.superInterfaces = new ReferenceBinding [] { this.scope.getJavaLangAnnotationAnnotation() } : null; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java index 22e37829296..f2e1f3c7a34 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/TypeVariableBinding.java @@ -45,16 +45,17 @@ import java.util.Arrays; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Set; import java.util.function.Consumer; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching; +import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode; import org.eclipse.jdt.internal.compiler.ast.TypeParameter; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.ast.Wildcard; -import org.eclipse.jdt.internal.compiler.ast.NullAnnotationMatching.CheckMode; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; import org.eclipse.jdt.internal.compiler.impl.CompilerOptions; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants.BoundCheckStatus; @@ -935,7 +936,7 @@ public ReferenceBinding superclass() { } @Override - public ReferenceBinding[] superInterfaces() { + protected ReferenceBinding[] superInterfacesRecursive(Map visited) { return this.superInterfaces; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java index 5594dd41e9f..2dedb9a38c3 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/lookup/WildcardBinding.java @@ -28,6 +28,7 @@ package org.eclipse.jdt.internal.compiler.lookup; import java.util.List; +import java.util.Map; import java.util.Set; import org.eclipse.jdt.core.compiler.CharOperation; import org.eclipse.jdt.internal.compiler.ast.Annotation; @@ -927,10 +928,10 @@ public ReferenceBinding superclass() { } @Override - public ReferenceBinding[] superInterfaces() { - if (this.superInterfaces == null) { + protected ReferenceBinding[] superInterfacesRecursive(Map visited) { + if (this.superInterfaces == null && visited.put(this, this) == null) { if (typeVariable() != null) { - this.superInterfaces = this.typeVariable.superInterfaces(); + this.superInterfaces = this.typeVariable.superInterfacesRecursive(visited);// TODO (visjee) protect from duplicated calls } else { this.superInterfaces = Binding.NO_SUPERINTERFACES; }