-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix a
StackOverflowError
in getLocalAndInheritedMethods
, involvin…
…g recursive type bounds. Also optimize override detection by noting that one method cannot override another if they have a different number of arguments. RELNOTES=`MoreElements.getLocalAndInheritedMethods` no longer gets a stack overflow in certain circumstances involving recursive type bounds. PiperOrigin-RevId: 542907665
- Loading branch information
1 parent
39743a8
commit 7d93867
Showing
3 changed files
with
45 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,8 +22,10 @@ | |
import com.google.common.collect.ImmutableList; | ||
import com.google.common.collect.Lists; | ||
import com.google.common.collect.Maps; | ||
import java.util.LinkedHashSet; | ||
import java.util.List; | ||
import java.util.Map; | ||
import java.util.Set; | ||
import javax.lang.model.element.Element; | ||
import javax.lang.model.element.ElementKind; | ||
import javax.lang.model.element.ExecutableElement; | ||
|
@@ -44,12 +46,12 @@ | |
import org.checkerframework.checker.nullness.qual.Nullable; | ||
|
||
/** | ||
* Determines if one method overrides another. This class defines two ways of doing that: | ||
* {@code NativeOverrides} uses the method | ||
* {@link Elements#overrides(ExecutableElement, ExecutableElement, TypeElement)} while | ||
* {@code ExplicitOverrides} reimplements that method in a way that is more consistent between | ||
* compilers, in particular between javac and ecj (the Eclipse compiler). | ||
* Determines if one method overrides another. This class defines two ways of doing that: {@code | ||
* NativeOverrides} uses the method {@link Elements#overrides(ExecutableElement, ExecutableElement, | ||
* TypeElement)} while {@code ExplicitOverrides} reimplements that method in a way that is more | ||
* consistent between compilers, in particular between javac and ecj (the Eclipse compiler). | ||
* | ||
* @see <a href="https://github.com/google/auto/issues/372">AutoValue issue about Eclipse</a> | ||
* @author [email protected] (Éamonn McManus) | ||
*/ | ||
abstract class Overrides { | ||
|
@@ -101,6 +103,14 @@ public boolean overrides( | |
// Static methods can't be overridden (though they can be hidden by other static methods). | ||
return false; | ||
} | ||
if (overrider.getParameters().size() != overridden.getParameters().size()) { | ||
// One method can't override another if they have a different number of parameters. | ||
// Varargs `Foo...` appears as `Foo[]` here; there is a separate | ||
// ExecutableElement.isVarArgs() method to tell whether a method is varargs, but that has no | ||
// effect on override logic. | ||
// The check here isn't strictly needed but avoids unnecessary work. | ||
return false; | ||
} | ||
Visibility overriddenVisibility = Visibility.ofElement(overridden); | ||
Visibility overriderVisibility = Visibility.ofElement(overrider); | ||
if (overriddenVisibility.equals(Visibility.PRIVATE) | ||
|
@@ -252,6 +262,13 @@ private class TypeSubstVisitor extends SimpleTypeVisitor8<TypeMirror, Void> { | |
*/ | ||
private final Map<TypeParameterElement, TypeMirror> typeBindings = Maps.newLinkedHashMap(); | ||
|
||
/** | ||
* Type elements that we are currently visiting. This helps us stay out of trouble when | ||
* looking at something like {@code Enum<E extends Enum<E>>}. At the second {@code Enum} we | ||
* will just return raw {@code Enum}. | ||
*/ | ||
private final Set<TypeElement> visitingTypes = new LinkedHashSet<>(); | ||
|
||
@Nullable | ||
ImmutableList<TypeMirror> erasedParameterTypes(ExecutableElement method, TypeElement in) { | ||
if (method.getEnclosingElement().equals(in)) { | ||
|
@@ -313,11 +330,18 @@ public TypeMirror visitDeclared(DeclaredType t, Void p) { | |
if (t.getTypeArguments().isEmpty()) { | ||
return t; | ||
} | ||
TypeElement typeElement = asTypeElement(t); | ||
if (!visitingTypes.add(typeElement)) { | ||
return typeUtils.erasure(t); | ||
} | ||
List<TypeMirror> newArgs = Lists.newArrayList(); | ||
for (TypeMirror arg : t.getTypeArguments()) { | ||
newArgs.add(visit(arg)); | ||
} | ||
return typeUtils.getDeclaredType(asTypeElement(t), newArgs.toArray(new TypeMirror[0])); | ||
TypeMirror result = | ||
typeUtils.getDeclaredType(asTypeElement(t), newArgs.toArray(new TypeMirror[0])); | ||
visitingTypes.remove(typeElement); | ||
return result; | ||
} | ||
|
||
@Override | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters