@Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; return typeVariable.equals(((TypeVarBoundedType) o).typeVariable); }
/** Returns a new {@code TypeResolver} with {@code variable} mapping to {@code type}. */ final TypeTable where(Map<? extends TypeVariable<?>, ? extends Type> mappings) { ImmutableMap.Builder<TypeVariable<?>, Type> builder = ImmutableMap.builder(); builder.putAll(map); for (Map.Entry<? extends TypeVariable<?>, ? extends Type> mapping : mappings.entrySet()) { TypeVariable<?> variable = mapping.getKey(); Type type = mapping.getValue(); checkArgument(!variable.equals(type), "Type variable %s bound to itself", variable); builder.put(variable, type); } return new TypeTable(builder.build()); }
private static boolean isAssignable( Type paramType, TypeVariable paramTypeVariable, Map paramMap) { if (paramType == null) return true; if (paramTypeVariable == null) return false; if (paramTypeVariable.equals(paramType)) return true; if ((paramType instanceof TypeVariable)) { Type[] arrayOfType = getImplicitBounds((TypeVariable) paramType); int i = arrayOfType.length; for (int j = 0; j < i; j++) if (isAssignable(arrayOfType[j], paramTypeVariable, paramMap)) return true; } if (((paramType instanceof Class)) || ((paramType instanceof ParameterizedType)) || ((paramType instanceof GenericArrayType)) || ((paramType instanceof WildcardType))) return false; throw new IllegalStateException("found an unhandled type: " + paramType); }
/** * Checks if the subject type may be implicitly cast to the target type variable following the * Java generics rules. * * @param type the subject type to be assigned to the target type * @param toTypeVariable the target type variable * @return true if <code>type</code> is assignable to <code>toTypeVariable</code>. */ private static boolean isAssignable( Type type, TypeVariable<?> toTypeVariable, Map<TypeVariable<?>, Type> typeVarAssigns) { if (type == null) { return true; } // only a null type can be assigned to null type which // would have cause the previous to return true if (toTypeVariable == null) { return false; } // all types are assignable to themselves if (toTypeVariable.equals(type)) { return true; } if (type instanceof TypeVariable<?>) { // a type variable is assignable to another type variable, if // and only if the former is the latter, extends the latter, or // is otherwise a descendant of the latter. Type[] bounds = getImplicitBounds((TypeVariable<?>) type); for (Type bound : bounds) { if (isAssignable(bound, toTypeVariable, typeVarAssigns)) { return true; } } } if (type instanceof Class<?> || type instanceof ParameterizedType || type instanceof GenericArrayType || type instanceof WildcardType) { return false; } throw new IllegalStateException("found an unhandled type: " + type); }
private void map(final TypeVariable<?> var, final Type arg) { if (mappings.containsKey(var)) { // Mapping already established // This is possible when following both superClass -> enclosingClass // and enclosingclass -> superClass paths. // Since we follow the path of superclass first, enclosing second, // superclass mapping should take precedence. return; } // First, check whether var -> arg forms a cycle for (Type t = arg; t != null; t = mappings.get(t)) { if (var.equals(t)) { // cycle detected, remove the entire cycle from the mapping so that // each type variable resolves deterministically to itself. // Otherwise, a F -> T cycle will end up resolving both F and T // nondeterministically to either F or T. for (Type x = arg; x != null; x = mappings.remove(x)) {} return; } } mappings.put(var, arg); }