def _try_decompose_into_operations_and_qubits(
    val: Any,
) -> tuple[list[cirq.Operation] | None, Sequence[cirq.Qid], tuple[int, ...]]:
    """Returns the value's decomposition (if any) and the qubits it applies to."""

    if isinstance(val, ops.Gate):
        # Gates don't specify qubits, and so must be handled specially.
        qid_shape = qid_shape_protocol.qid_shape(val)
        qubits: Sequence[cirq.Qid] = devices.LineQid.for_qid_shape(qid_shape)
        return decompose_once_with_qubits(val, qubits, None), qubits, qid_shape

    if isinstance(val, ops.Operation):
        qid_shape = qid_shape_protocol.qid_shape(val)
        return decompose_once(val, None), val.qubits, qid_shape

    result = decompose_once(val, None)
    if result is not None:
        qubit_set = set()
        qid_shape_dict: dict[cirq.Qid, int] = defaultdict(lambda: 1)
        for op in result:
            for level, q in zip(qid_shape_protocol.qid_shape(op), op.qubits):
                qubit_set.add(q)
                qid_shape_dict[q] = max(qid_shape_dict[q], level)
        qubits = sorted(qubit_set)
        return result, qubits, tuple(qid_shape_dict[q] for q in qubits)
    return None, (), ()
Returns the value's decomposition (if any) and the qubits it applies to.
cirq-core/cirq/protocols/decompose_protocol.py