private boolean isSubtypeOfInterface(Type t, InterfaceType s) { // Special handling for union. if (t instanceof InterfaceTypeUnion) { InterfaceTypeUnion tUnion = (InterfaceTypeUnion) t; for (InterfaceType unionPart : tUnion.getTypes()) { if (isSubtype(unionPart, s)) { return true; } } return false; } // class "t" implements call() and "s" is Function if (TypeKind.of(t) == TypeKind.INTERFACE && typeProvider != null && s == typeProvider.getFunctionType()) { InterfaceType ti = (InterfaceType) t; if (ti.lookupMember("call") != null) { return true; } } // Try to cast "t" to "s". final Type sup = asInstanceOf(t, s.getElement()); if (TypeKind.of(sup) == TypeKind.INTERFACE) { InterfaceType ti = (InterfaceType) sup; assert ti.getElement().equals(s.getElement()); if (ti.isRaw() || s.isRaw()) { return true; } // Type arguments are covariant. return areSubtypes(ti.getArguments().iterator(), s.getArguments().iterator()); } return false; }
boolean isApplicable(TypeConfiguration that) { List<TypeKind> actuals = that.typeKindList; List<TypeKind> formals = parameterTypes.typeKindList; if ((actuals.size() - formals.size()) < -1) return false; // not enough args for (TypeKind actual : actuals) { if (!actual.isSubtypeOf(formals.head)) return false; // type mismatch formals = formals.tail.isEmpty() ? formals : formals.tail; } return true; }
void test() throws Exception { for (TypeKind formal1 : TypeKind.values()) { VarargsMethod m1 = new VarargsMethod(formal1); for (TypeKind formal2 : TypeKind.values()) { VarargsMethod m2 = new VarargsMethod(formal2); for (TypeKind actual : TypeKind.values()) { for (ArgumentsArity argsArity : ArgumentsArity.values()) { compileAndCheck(m1, m2, actual, argsArity); } } } } System.out.println("Total checks made: " + checkCount); System.out.println("Bytecode checks made: " + bytecodeCheckCount); }
public NoType getNoType(TypeKind kind) { switch (kind) { case VOID: return syms.voidType; case NONE: return Type.noType; default: throw new IllegalArgumentException(kind.toString()); } }
public static InterfaceType ensureInterface(Type type) { TypeKind kind = TypeKind.of(type); switch (kind) { case INTERFACE: return (InterfaceType) type; case NONE: case DYNAMIC: return null; default: throw new AssertionError("unexpected kind " + kind); } }
/** * Return an interface type representing the given interface, function or variable type. * * @return An interface type or null if the argument is neither an interface function or variable * type. */ public InterfaceType getInterfaceType(Type type) { switch (TypeKind.of(type)) { case VARIABLE: { TypeVariableElement element = ((TypeVariable) type).getTypeVariableElement(); if (element.getBound() == null) { return typeProvider.getObjectType(); } else { return getInterfaceType(element.getBound()); } } case FUNCTION: case FUNCTION_ALIAS: return typeProvider.getFunctionType(); case INTERFACE: return (InterfaceType) type; case DYNAMIC: case NONE: case VOID: default: return null; } }
public Type intersection(List<Type> types) { // exclude 'dynamic' type { List<Type> newTypes = Lists.newArrayList(); for (Type type : types) { if (TypeKind.of(type) != TypeKind.DYNAMIC) { newTypes.add(type); } } types = newTypes; } // no types, so Dynamic if (types.isEmpty()) { return typeProvider.getDynamicType(); } // prepare all super types List<List<InterfaceType>> superTypesLists = Lists.newArrayList(); List<Map<InterfaceType, InterfaceType>> superTypesMaps = Lists.newArrayList(); for (Type type : types) { List<InterfaceType> superTypes = getSuperTypes(type); superTypesLists.add(superTypes); Map<InterfaceType, InterfaceType> superTypesMap = Maps.newHashMap(); for (InterfaceType superType : superTypes) { superTypesMap.put(superType.asRawType(), superType); } superTypesMaps.add(superTypesMap); } // find intersection of super types LinkedList<InterfaceType> interTypes = Lists.newLinkedList(); if (superTypesLists.size() > 0) { for (InterfaceType superType : superTypesLists.get(0)) { boolean inAll = true; for (Map<InterfaceType, InterfaceType> otherTypesMap : superTypesMaps) { InterfaceType superTypeRaw = superType.asRawType(); InterfaceType otherType = otherTypesMap.get(superTypeRaw); // no such raw type, exclude from intersection if (otherType == null) { inAll = false; break; } // if not raw, choose type arguments if (!superType.getArguments().isEmpty()) { InterfaceType t0 = superType; InterfaceType t1 = otherType; // if two-way sub-type, then has Dynamic(s), choose with least number if (isSubtype(t0, t1) && isSubtype(t1, t0)) { int dynamics0 = getDynamicArgumentsCount(t0); int dynamics1 = getDynamicArgumentsCount(t1); if (dynamics0 < dynamics1) { superType = t0; } else { superType = t1; } continue; } // use super-type of t0 and t1 if (isSubtype(t0, t1)) { superType = t1; } if (isSubtype(t1, t0)) { superType = t0; } } } if (inAll && !interTypes.contains(superType)) { interTypes.add(superType); } } } // try to remove sub-types already covered by existing types for (Iterator<InterfaceType> i = interTypes.descendingIterator(); i.hasNext(); ) { InterfaceType subType = i.next(); boolean hasSuperType = false; for (InterfaceType superType : interTypes) { if (superType != subType && isSubtype(superType, subType)) { hasSuperType = true; break; } } if (hasSuperType) { i.remove(); } } // use single type if (interTypes.size() == 0) { return typeProvider.getObjectType(); } if (interTypes.size() == 1) { return interTypes.get(0); } // create union return unionTypes(interTypes); }
private InterfaceType checkedAsInstanceOf( Type t, ClassElement element, Set<TypeVariable> variablesReferenced, Set<Type> checkedTypes) { // check for recursion if (checkedTypes.contains(t)) { return null; } checkedTypes.add(t); // check current Type switch (TypeKind.of(t)) { case FUNCTION_ALIAS: case INTERFACE: { if (t.getElement().equals(element)) { return (InterfaceType) t; } InterfaceType ti = (InterfaceType) t; ClassElement tElement = ti.getElement(); InterfaceType supertype = tElement.getSupertype(); // super type if (supertype != null) { InterfaceType result = checkedAsInstanceOf( asSupertype(ti, supertype), element, variablesReferenced, checkedTypes); if (result != null) { return result; } } // interfaces for (InterfaceType intf : tElement.getInterfaces()) { InterfaceType result = checkedAsInstanceOf( asSupertype(ti, intf), element, variablesReferenced, checkedTypes); if (result != null) { return result; } } // mixins for (InterfaceType mixin : tElement.getMixins()) { if (mixin.getElement().equals(element)) { return asSupertype(ti, mixin); } } // no return null; } case FUNCTION: { Element e = t.getElement(); switch (e.getKind()) { case CLASS: // e should be the interface Function in the core library. See the // documentation comment on FunctionType. InterfaceType ti = (InterfaceType) e.getType(); return checkedAsInstanceOf(ti, element, variablesReferenced, checkedTypes); default: return null; } } case VARIABLE: { TypeVariable v = (TypeVariable) t; Type bound = v.getTypeVariableElement().getBound(); // Check for previously encountered variables to avoid getting stuck in an infinite loop. if (variablesReferenced.contains(v)) { if (bound instanceof InterfaceType) { return (InterfaceType) bound; } return typeProvider.getObjectType(); } variablesReferenced.add(v); return checkedAsInstanceOf(bound, element, variablesReferenced, checkedTypes); } default: return null; } }
boolean isMoreSpecificThan(VarargsMethod that) { return varargsElement.isSubtypeOf(that.varargsElement); }
boolean isApplicable(TypeKind actual, ArgumentsArity argsArity) { return argsArity == ArgumentsArity.ZERO || actual.isSubtypeOf(varargsElement); }