def do_types_overlap(schema, type_a, type_b):
    """Check whether two types overlap in a given schema.

    Provided two composite types, determine if they "overlap". Two composite types
    overlap when the Sets of possible concrete types for each intersect.

    This is often used to determine if a fragment of a given type could possibly be
    visited in a context of another type.

    This function is commutative.
    """
    # Equivalent types overlap
    if type_a is type_b:
        return True

    if is_abstract_type(type_a):
        if is_abstract_type(type_b):
            # If both types are abstract, then determine if there is any intersection
            # between possible concrete types of each.
            return any(
                schema.is_possible_type(type_b, type_)
                for type_ in schema.get_possible_types(type_a)
            )
        # Determine if latter type is a possible concrete type of the former.
        return schema.is_possible_type(type_a, type_b)

    if is_abstract_type(type_b):
        # Determine if former type is a possible concrete type of the latter.
        return schema.is_possible_type(type_b, type_a)

    # Otherwise the types do not overlap.
    return False
Check whether two types overlap in a given schema.

    Provided two composite types, determine if they "overlap". Two composite types
    overlap when the Sets of possible concrete types for each intersect.

    This is often used to determine if a fragment of a given type could possibly be
    visited in a context of another type.

    This function is commutative.