Skip to content

Commit

Permalink
Correct finding type variables of enclosing classes
Browse files Browse the repository at this point in the history
  • Loading branch information
smillst authored Oct 21, 2021
1 parent 42255c9 commit 8c9f352
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -211,33 +211,58 @@ public List<AnnotatedDeclaredType> visitDeclared(AnnotatedDeclaredType type, Voi
* type parameters of {@code type}, its enclosing types, and all super types of all {@code
* type}'s enclosing types.
*
* <p>It does not get the type parameters of the supertypes of {@code type} because the result
* of this method is used to substitute the type arguments of the supertypes of {@code type}.
*
* @param type a type
* @return a mapping from each type parameter to its corresponding annotated type argument
*/
private Map<TypeVariable, AnnotatedTypeMirror> getTypeVarToTypeArg(AnnotatedDeclaredType type) {
Map<TypeVariable, AnnotatedTypeMirror> mapping = new HashMap<>();
AnnotatedDeclaredType enclosing = type;
while (enclosing != null) {
TypeElement enclosingTypeElement = (TypeElement) enclosing.getUnderlyingType().asElement();
List<? extends TypeParameterElement> typeParams = enclosingTypeElement.getTypeParameters();
List<AnnotatedTypeMirror> typeArgs = enclosing.getTypeArguments();
for (int i = 0; i < enclosing.getTypeArguments().size(); ++i) {
AnnotatedTypeMirror typArg = typeArgs.get(i);
TypeParameterElement ele = typeParams.get(i);
mapping.put((TypeVariable) ele.asType(), typArg);
}
// addTypeVarsFromEnclosingTypes can't be called with `type` because it calls
// `directSupertypes(types)`, which then calls this method. Add the type variables from `type`
// and then call addTypeVarsFromEnclosingTypes on the enclosing type.
addTypeVariablesToMapping(type, mapping);
addTypeVarsFromEnclosingTypes(type.getEnclosingType(), mapping);
return mapping;
}

@SuppressWarnings("interning:not.interned") // First time through type == enclosing.
boolean notType = enclosing != type;
if (notType) {
for (AnnotatedDeclaredType enclSuper : directSupertypes(enclosing)) {
mapping.putAll(getTypeVarToTypeArg(enclSuper));
}
}
/**
* Adds a mapping from a type parameter to its corresponding annotated type argument for all
* type parameters of {@code type}.
*
* @param type a type
* @param mapping type variable to type argument map; side-effected by this method
*/
private void addTypeVariablesToMapping(
AnnotatedDeclaredType type, Map<TypeVariable, AnnotatedTypeMirror> mapping) {
TypeElement enclosingTypeElement = (TypeElement) type.getUnderlyingType().asElement();
List<? extends TypeParameterElement> typeParams = enclosingTypeElement.getTypeParameters();
List<AnnotatedTypeMirror> typeArgs = type.getTypeArguments();
for (int i = 0; i < type.getTypeArguments().size(); ++i) {
AnnotatedTypeMirror typArg = typeArgs.get(i);
TypeParameterElement ele = typeParams.get(i);
mapping.put((TypeVariable) ele.asType(), typArg);
}
}

/**
* Adds a mapping from a type parameter to its corresponding annotated type argument for all
* type parameters of {@code enclosing} and its enclosing types. This method recurs on all the
* super types of {@code enclosing}.
*
* @param mapping type variable to type argument map; side-effected by this method
* @param enclosing a type
*/
private void addTypeVarsFromEnclosingTypes(
AnnotatedDeclaredType enclosing, Map<TypeVariable, AnnotatedTypeMirror> mapping) {
while (enclosing != null) {
addTypeVariablesToMapping(enclosing, mapping);
for (AnnotatedDeclaredType enclSuper : directSupertypes(enclosing)) {
addTypeVarsFromEnclosingTypes(enclSuper, mapping);
}
enclosing = enclosing.getEnclosingType();
}
return mapping;
}

private List<AnnotatedDeclaredType> supertypesFromElement(
Expand Down
15 changes: 15 additions & 0 deletions framework/tests/all-systems/Issue4924.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
public class Issue4924 {
interface Callback<A> {}

static class Template<B> {
class Adapter implements Callback<B> {}
}

static class Super<C> extends Template<C> {}

static class Issue extends Super<String> {
void foo() {
Callback<String> f = new Adapter();
}
}
}

0 comments on commit 8c9f352

Please sign in to comment.