Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct finding type variables of enclosing classes. #4931

Merged
merged 11 commits into from
Oct 21, 2021
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
*/
smillst marked this conversation as resolved.
Show resolved Hide resolved
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) {
smillst marked this conversation as resolved.
Show resolved Hide resolved
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();
}
}
}