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);
  }
Exemple #4
0
 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);
 }