@Override protected boolean isSubtypeTypeArguments(AnnotatedDeclaredType rhs, AnnotatedDeclaredType lhs) { List<AnnotatedTypeMirror> rhsTypeArgs = rhs.getTypeArguments(); List<AnnotatedTypeMirror> lhsTypeArgs = lhs.getTypeArguments(); if (rhsTypeArgs.isEmpty() || lhsTypeArgs.isEmpty()) return true; TypeElement lhsElem = (TypeElement) lhs.getUnderlyingType().asElement(); // TypeElement rhsElem = (TypeElement) lhs.getUnderlyingType().asElement(); // the following would be needed if Covariant were per type parameter // AnnotatedDeclaredType lhsDecl = currentATF.fromElement(lhsElem); // AnnotatedDeclaredType rhsDecl = currentATF.fromElement(rhsElem); // List<AnnotatedTypeMirror> lhsTVs = lhsDecl.getTypeArguments(); // List<AnnotatedTypeMirror> rhsTVs = rhsDecl.getTypeArguments(); int[] covarVals = null; if (lhsElem.getAnnotation(Covariant.class) != null) { covarVals = lhsElem.getAnnotation(Covariant.class).value(); } if (lhsTypeArgs.size() != rhsTypeArgs.size()) { // This test fails e.g. for casts from a type with one type // argument to a type with two type arguments. // See test case nullness/generics/GenericsCasts // TODO: shouldn't the type be brought to a common type before // this? return true; } for (int i = 0; i < lhsTypeArgs.size(); ++i) { boolean covar = false; if (covarVals != null) { for (int cvv = 0; cvv < covarVals.length; ++cvv) { if (covarVals[cvv] == i) { covar = true; } } } if (covar) { if (!isSubtype(rhsTypeArgs.get(i), lhsTypeArgs.get(i))) return false; } else { if (!isSubtypeAsTypeArgument(rhsTypeArgs.get(i), lhsTypeArgs.get(i))) return false; } } return true; }
@Override public Void visitDeclared(AnnotatedDeclaredType type, ElementKind p) { Element elt = type.getElement(); if (!type.isAnnotated() && ( /*checker.isDefaultAnyType(type) ||*/ elt != null && ElementUtils.isStatic(elt) && (elt.getKind() == ElementKind.FIELD || elt.getKind() == ElementKind.LOCAL_VARIABLE || elt.getKind() == ElementKind.EXCEPTION_PARAMETER || elt.getKind() == ElementKind.ENUM_CONSTANT || elt.getKind() == ElementKind.PARAMETER))) { type.clearAnnotations(); Set<AnnotationMirror> set = AnnotationUtils.createAnnotationSet(); set.add(checker.ANY); if (elt != null && ElementUtils.isStatic(elt)) set.add(checker.PEER); annotateConstants(type, set); } return super.visitDeclared(type, p); }
/** Tests whether t1 is a subtype of t2, with respect to IGJ Subtyping rules */ @Override public boolean isSubtype(AnnotatedTypeMirror sup, AnnotatedTypeMirror sub) { // TODO: Check that they are up to the same base // Err... cannot handle type variables quite yet if (sup.getKind() == TypeKind.TYPEVAR || sup.getKind() == TypeKind.WILDCARD || sub.getKind() == TypeKind.TYPEVAR || sub.getKind() == TypeKind.WILDCARD) return true; AnnotatedTypes annoUtils = new AnnotatedTypes(env, factory); AnnotatedTypeMirror valueBaseType = annoUtils.asSuper(sub, sup); if (valueBaseType == null) // For now valueBaseType = sub; boolean isSubtype = isSubtypeOneLevel(sup, valueBaseType); boolean typeArgShouldBeSame = sup.hasAnnotation(MUTABLE); if ((sup.getKind() == TypeKind.DECLARED) && (valueBaseType.getKind() == TypeKind.DECLARED)) { AnnotatedDeclaredType supDecl = (AnnotatedDeclaredType) sup; AnnotatedDeclaredType subDecl = (AnnotatedDeclaredType) valueBaseType; // if (supDecl.getTypeArguments().size() != subDecl.getTypeArguments().size()) // System.out.println("Investigate this " + supDecl + " " + subDecl); for (int i = 0; i < supDecl.getTypeArguments().size() && i < subDecl.getTypeArguments().size(); ++i) { AnnotatedTypeMirror supArg = supDecl.getTypeArguments().get(i); AnnotatedTypeMirror subArg = subDecl.getTypeArguments().get(i); if (typeArgShouldBeSame) isSubtype &= isSameImmutability(supArg, subArg); else isSubtype &= isSubtype(supArg, subArg); } } else if ((sup.getKind() == TypeKind.ARRAY) && (valueBaseType.getKind() == TypeKind.ARRAY)) { AnnotatedArrayType supArr = (AnnotatedArrayType) sup; AnnotatedArrayType subArr = (AnnotatedArrayType) valueBaseType; if (typeArgShouldBeSame) isSubtype &= isSameImmutability(supArr.getComponentType(), subArr.getComponentType()); else isSubtype &= isSubtype(supArr.getComponentType(), subArr.getComponentType()); } return isSubtype; }
@Override public final R visitDeclared(AnnotatedDeclaredType type, AnnotatedTypeMirror p) { assert p instanceof AnnotatedDeclaredType : p; R r = scan(type.getTypeArguments(), ((AnnotatedDeclaredType) p).getTypeArguments()); return r; }