use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class AnnotatedTypes method substituteTypeVariables.
/**
* Substitute type variables.
*
* @param types type utilities
* @param atypeFactory the type factory
* @param receiverType the type of the class that contains member (or a subtype of it)
* @param member a type member, such as a method or field
* @param memberType the type of {@code member}
* @return {@code memberType}, substituted
*/
private static AnnotatedTypeMirror substituteTypeVariables(Types types, AnnotatedTypeFactory atypeFactory, AnnotatedTypeMirror receiverType, Element member, AnnotatedTypeMirror memberType) {
// Basic Algorithm:
// 1. Find the enclosingClassOfMember of the element
// 2. Find the base type of enclosingClassOfMember (e.g. type of enclosingClassOfMember as
// supertype of passed type)
// 3. Substitute for type variables if any exist
TypeElement enclosingClassOfMember = ElementUtils.enclosingTypeElement(member);
final Map<TypeVariable, AnnotatedTypeMirror> mappings = new HashMap<>();
// and collect type to be substituted for those type variables
while (enclosingClassOfMember != null) {
addTypeVarMappings(types, atypeFactory, receiverType, enclosingClassOfMember, mappings);
enclosingClassOfMember = ElementUtils.enclosingTypeElement(enclosingClassOfMember.getEnclosingElement());
}
if (!mappings.isEmpty()) {
memberType = atypeFactory.getTypeVarSubstitutor().substitute(mappings, memberType);
}
return memberType;
}
use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class TypeFromTypeTreeVisitor method getTypeVariableFromDeclaration.
/**
* If a tree is can be found for the declaration of the type variable {@code type}, then a {@link
* AnnotatedTypeVariable} is returned with explicit annotations from the type variables declared
* bounds. If a tree cannot be found, then {@code type}, converted to a use, is returned.
*
* @param type type variable used to find declaration tree
* @param f annotated type factory
* @return the AnnotatedTypeVariable from the declaration of {@code type} or {@code type} if no
* tree is found.
*/
private AnnotatedTypeVariable getTypeVariableFromDeclaration(AnnotatedTypeVariable type, AnnotatedTypeFactory f) {
TypeVariable typeVar = type.getUnderlyingType();
TypeParameterElement tpe = (TypeParameterElement) typeVar.asElement();
Element elt = tpe.getGenericElement();
if (elt instanceof TypeElement) {
TypeElement typeElt = (TypeElement) elt;
int idx = typeElt.getTypeParameters().indexOf(tpe);
ClassTree cls = (ClassTree) f.declarationFromElement(typeElt);
if (cls == null || cls.getTypeParameters().isEmpty()) {
// contains all necessary information and we can return that.
return type.asUse();
}
// will return a declaration ATV. So change it to a use.
return visitTypeParameter(cls.getTypeParameters().get(idx), f).asUse();
} else if (elt instanceof ExecutableElement) {
ExecutableElement exElt = (ExecutableElement) elt;
int idx = exElt.getTypeParameters().indexOf(tpe);
MethodTree meth = (MethodTree) f.declarationFromElement(exElt);
if (meth == null) {
// + elt);
return type.asUse();
}
// This works the same as the case above. Even though `meth` itself is not a
// type declaration tree, the elements of `meth.getTypeParameters()` still are.
AnnotatedTypeVariable result = visitTypeParameter(meth.getTypeParameters().get(idx), f).shallowCopy();
result.setDeclaration(false);
return result;
} else if (TypesUtils.isCapturedTypeVariable(typeVar)) {
// not an element at all, namely Symtab.noSymbol.
return type.asUse();
} else {
throw new BugInCF("TypeFromTree.forTypeVariable: not a supported element: " + elt);
}
}
use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class TypesUtils method simpleTypeName.
/**
* Returns the simple type name, without annotations.
*
* @param type a type
* @return the simple type name, without annotations
*/
public static String simpleTypeName(TypeMirror type) {
switch(type.getKind()) {
case ARRAY:
return simpleTypeName(((ArrayType) type).getComponentType()) + "[]";
case TYPEVAR:
return ((TypeVariable) type).asElement().getSimpleName().toString();
case DECLARED:
return ((DeclaredType) type).asElement().getSimpleName().toString();
case NULL:
return "<nulltype>";
case VOID:
return "void";
case WILDCARD:
WildcardType wildcard = (WildcardType) type;
TypeMirror extendsBound = wildcard.getExtendsBound();
TypeMirror superBound = wildcard.getSuperBound();
return "?" + (extendsBound != null ? " extends " + simpleTypeName(extendsBound) : "") + (superBound != null ? " super " + simpleTypeName(superBound) : "");
case UNION:
StringJoiner sj = new StringJoiner(" | ");
for (TypeMirror alternative : ((UnionType) type).getAlternatives()) {
sj.add(simpleTypeName(alternative));
}
return sj.toString();
default:
if (type.getKind().isPrimitive()) {
return TypeAnnotationUtils.unannotatedType(type).toString();
} else {
throw new BugInCF("simpleTypeName: unhandled type kind: %s, type: %s", type.getKind(), type);
}
}
}
use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class DefaultTypeArgumentInference method createAssignmentConstraints.
/**
* The first half of Step 6.
*
* <p>This method creates constraints:
*
* <ul>
* <li>between the bounds of types that are already inferred and their inferred arguments
* <li>between the assignment context and the return type of the method (with the previously
* inferred arguments substituted into these constraints)
* </ul>
*/
public ConstraintMap createAssignmentConstraints(final AnnotatedTypeMirror assignedTo, final AnnotatedTypeMirror boxedReturnType, final AnnotatedExecutableType methodType, final Set<AFConstraint> afArgumentConstraints, final Map<TypeVariable, AnnotatedTypeMirror> inferredArgs, final Set<TypeVariable> targets, final AnnotatedTypeFactory typeFactory) {
final ArrayDeque<AFConstraint> assignmentAfs = new ArrayDeque<>(2 * methodType.getTypeVariables().size() + afArgumentConstraints.size());
for (AnnotatedTypeVariable typeParam : methodType.getTypeVariables()) {
final TypeVariable target = typeParam.getUnderlyingType();
final AnnotatedTypeMirror inferredType = inferredArgs.get(target);
// the lower bound for all uninferred types Tu: Tu >> Bi and Lu >> Tu
if (inferredType != null) {
assignmentAfs.add(new A2F(inferredType, typeParam.getUpperBound()));
assignmentAfs.add(new F2A(typeParam.getLowerBound(), inferredType));
} else {
assignmentAfs.add(new F2A(typeParam, typeParam.getUpperBound()));
assignmentAfs.add(new A2F(typeParam.getLowerBound(), typeParam));
}
}
for (AFConstraint argConstraint : afArgumentConstraints) {
if (argConstraint instanceof F2A) {
assignmentAfs.add(argConstraint);
}
}
ArrayDeque<AFConstraint> substitutedAssignmentConstraints = new ArrayDeque<>(assignmentAfs.size() + 1);
for (AFConstraint afConstraint : assignmentAfs) {
substitutedAssignmentConstraints.add(afConstraint.substitute(inferredArgs));
}
final AnnotatedTypeMirror substitutedReturnType = TypeArgInferenceUtil.substitute(inferredArgs, boxedReturnType);
substitutedAssignmentConstraints.add(new F2A(substitutedReturnType, assignedTo));
final Set<AFConstraint> reducedConstraints = new LinkedHashSet<>();
reduceAfConstraints(typeFactory, reducedConstraints, substitutedAssignmentConstraints, targets);
final Set<TUConstraint> tuAssignmentConstraints = afToTuConstraints(reducedConstraints, targets);
addConstraintsBetweenTargets(tuAssignmentConstraints, targets, true, typeFactory);
return constraintMapBuilder.build(targets, tuAssignmentConstraints, typeFactory);
}
use of javax.lang.model.type.TypeVariable in project checker-framework by typetools.
the class TypeArgInferenceUtil method correctResults.
/**
* If the type arguments computed by DefaultTypeArgumentInference don't match the return type
* mirror of {@code invocation}, then replace those type arguments with an uninferred wildcard.
*/
protected static Map<TypeVariable, AnnotatedTypeMirror> correctResults(Map<TypeVariable, AnnotatedTypeMirror> result, ExpressionTree invocation, ExecutableType methodType, AnnotatedTypeFactory factory) {
ProcessingEnvironment env = factory.getProcessingEnv();
Types types = env.getTypeUtils();
Map<TypeVariable, TypeMirror> fromReturn = getMappingFromReturnType(invocation, methodType, env);
for (Map.Entry<TypeVariable, AnnotatedTypeMirror> entry : // result is side-effected by this loop, so iterate over a copy
new ArrayList<>(result.entrySet())) {
TypeVariable typeVariable = entry.getKey();
if (!fromReturn.containsKey(typeVariable)) {
continue;
}
TypeMirror correctType = fromReturn.get(typeVariable);
TypeMirror inferredType = entry.getValue().getUnderlyingType();
if (types.isSameType(types.erasure(correctType), types.erasure(inferredType))) {
if (areSameCapture(correctType, inferredType)) {
continue;
}
}
if (!types.isSameType(correctType, inferredType)) {
AnnotatedWildcardType wt = factory.getUninferredWildcardType((AnnotatedTypeVariable) AnnotatedTypeMirror.createType(typeVariable, factory, false));
wt.replaceAnnotations(entry.getValue().getAnnotations());
result.put(typeVariable, wt);
}
}
return result;
}
Aggregations