def METHOD_NAME(args):
    """
    Try to infer type by traversing arguments in order:
    * If we encounter a magma Type/Protocol, use that
    * BitVector/Bit/bool are converted to their magma equivalent Bits/Bit
    * Python tuple is converted to m.Tuple (note this will invoke m.tuple_ on
      all the arguments, which may raise an error if the tuple arguments are
      not well formed)
    Note that we do not infer from standard python int arguments because we
    cannot, in general, determine the correct bit width (use BitVector instead)
    """
    T = None
    for arg in args:
        if isinstance(arg, (Type, MagmaProtocol)):
            next_T = type(arg).qualify(Direction.Undirected)
        elif isinstance(arg, UIntVector):
            next_T = UInt[len(arg)]
        elif isinstance(arg, SIntVector):
            next_T = SInt[len(arg)]
        elif isinstance(arg, BitVector):
            next_T = Bits[len(arg)]
        elif isinstance(arg, (ht.Bit, bool)):
            next_T = Bit
        elif isinstance(arg, tuple):
            next_T = type(tuple_(arg))
        elif isinstance(arg, int):
            # Cannot infer type without width, use wiring implicit coercion to
            # handle (or raise type error there)
            continue
        if T is not None:
            if issubclass(T, next_T):
                # upcast
                T = next_T
            elif not next_T.is_wireable(T) and not T.is_wireable(next_T):
                raise TypeError(
                    f"Found incompatible types {next_T} and {T} in mux"
                    " inference"
                )
        else:
            T = next_T
    if T is None:
        raise TypeError(
            f"Could not infer mux type from {args}\n"
            "Need at least one magma value, BitVector, bool or tuple")
    if issubclass(T, Tuple):
        args = [tuple_(a) for a in args]
    return T, args