static ClassNode boundUnboundedWildcards(ClassNode type) {
        if (type.isArray()) {
            return boundUnboundedWildcards(type.getComponentType()).makeArray();
        }
        ClassNode target = type.redirect();
        if (target == null || type == target || !isUsingGenericsOrIsArrayUsingGenerics(target)) return type;
        ClassNode newType = type.getPlainNodeReference();
        newType.setGenericsPlaceHolder(type.isGenericsPlaceHolder());
        newType.setGenericsTypes(boundUnboundedWildcards(type.getGenericsTypes(), target.getGenericsTypes()));
        return newType;
    }
static ClassNode boundUnboundedWildcards ( ClassNode type ) { if ( type . isArray ( ) ) { return boundUnboundedWildcards ( type . getComponentType ( ) ) . makeArray ( ) ; } ClassNode target = type . redirect ( ) ; if ( target == null || type == target || ! isUsingGenericsOrIsArrayUsingGenerics ( target ) ) return type ; ClassNode newType = type . getPlainNodeReference ( ) ; newType . setGenericsPlaceHolder ( type . isGenericsPlaceHolder ( ) ) ; newType . setGenericsTypes ( boundUnboundedWildcards ( type . getGenericsTypes ( ) , target . getGenericsTypes ( ) ) ) ; return newType ; }
Apply the bounds from the declared type when the using type simply declares a parameter as an unbounded wildcard.

@param type A parameterized type
@return A parameterized type with more precise wildcards