docs: def get_alternate_types_resolving_forwardref_union_and_typevar(typ, _memo: List[Any] = None) \
          -> Tuple[Any, ...]:
      """
      Returns a tuple of all alternate types allowed by the `typ` type annotation.
  
      If typ is a TypeVar,
       * if the typevar is bound, return get_alternate_types_resolving_forwardref_union_and_typevar(bound)
       * if the typevar has constraints, return a tuple containing all the types listed in the constraints (with
       appropriate recursive call to get_alternate_types_resolving_forwardref_union_and_typevar for each of them)
       * otherwise return (object, )
  
      If typ is a Union, return a tuple containing all the types listed in the union (with
       appropriate recursive call to get_alternate_types_resolving_forwardref_union_and_typevar for each of them)
  
      If typ is a forward reference, it is evaluated and this method is applied to the results.
  
      Otherwise (typ, ) is returned
  
      Note that this function automatically prevent infinite recursion through forward references such as in
      `A = Union[str, 'A']`, by keeping a _memo of already met symbols.
  
      :param typ: 
      :return: 
      """
      # avoid infinite recursion by using a _memo
      _memo = _memo or []
      if typ in _memo:
          return tuple()
  
      # remember that this was already explored
      _memo.append(typ)
      if is_typevar(typ):
          if hasattr(typ, '__bound__') and typ.__bound__ is not None:
              # TypeVar is 'bound' to a class
              if hasattr(typ, '__contravariant__') and typ.__contravariant__:
                  # Contravariant means that only super classes of this type are supported!
                  raise Exception('Contravariant TypeVars are not supported')
              else:
                  # only subclasses of this are allowed (even if not covariant, because as of today we cant do otherwise)
                  return get_alternate_types_resolving_forwardref_union_and_typevar(typ.__bound__, _memo=_memo)
  
          elif hasattr(typ, '__constraints__') and typ.__constraints__ is not None:
              if hasattr(typ, '__contravariant__') and typ.__contravariant__:
                  # Contravariant means that only super classes of this type are supported!
                  raise Exception('Contravariant TypeVars are not supported')
              else:
                  # TypeVar is 'constrained' to several alternate classes, meaning that subclasses of any of them are
                  # allowed (even if not covariant, because as of today we cant do otherwise)
                  return tuple(typpp for c in typ.__constraints__
                               for typpp in get_alternate_types_resolving_forwardref_union_and_typevar(c, _memo=_memo))
  
          else:
              # A non-parametrized TypeVar means 'any'
              return object,
  
      elif is_union_type(typ):
          # do not use typ.__args__, it may be wrong
          # the solution below works even in typevar+config cases such as u = Union[T, str][Optional[int]]
          return tuple(t for typpp in get_args(typ, evaluate=True)
                       for t in get_alternate_types_resolving_forwardref_union_and_typevar(typpp, _memo=_memo))
  
      elif is_forward_ref(typ):
          return get_alternate_types_resolving_forwardref_union_and_typevar(resolve_forward_ref(typ), _memo=_memo)
  
      else:
          return typ,