public static boolean containsDistinctType(List<Type> types)
    {
        LinkedList<Type> allTypes = new LinkedList<>(types);
        while (!allTypes.isEmpty()) {
            Type type = allTypes.removeLast();
            if (isDistinctType(type)) {
                return true;
            }
            allTypes.addAll(type.getTypeParameters());
        }
        return false;
    }
@Test
    public void testContainsDistinctType()
    {
        QualifiedObjectName distinctTypeName = QualifiedObjectName.valueOf("test.dt.int00");
        DistinctTypeInfo distinctTypeInfo = new DistinctTypeInfo(distinctTypeName, INTEGER.getTypeSignature(), Optional.empty(), false);
        DistinctType distinctType = new DistinctType(distinctTypeInfo, INTEGER, null);

        // check primitives
        assertFalse(containsDistinctType(ImmutableList.of(INTEGER, VARCHAR)));

        // check top level
        assertTrue(containsDistinctType(ImmutableList.of(distinctType)));

        // check first nesting level
        assertFalse(containsDistinctType(ImmutableList.of(RowType.anonymous(ImmutableList.of(INTEGER, VARCHAR)))));
        assertFalse(containsDistinctType(ImmutableList.of(new ArrayType(INTEGER))));
        assertTrue(containsDistinctType(ImmutableList.of(RowType.anonymous(ImmutableList.of(INTEGER, distinctType)))));
        assertTrue(containsDistinctType(ImmutableList.of(new ArrayType(distinctType))));

        // check deep nesting
        assertFalse(containsDistinctType(ImmutableList.of(new ArrayType(new ArrayType(INTEGER)))));
        assertFalse(containsDistinctType(ImmutableList.of(new ArrayType(RowType.anonymous(ImmutableList.of(INTEGER, VARCHAR))))));
        assertTrue(containsDistinctType(ImmutableList.of(new ArrayType(new ArrayType(distinctType)))));
        assertTrue(containsDistinctType(ImmutableList.of(new ArrayType(RowType.anonymous(ImmutableList.of(INTEGER, distinctType))))));
    }