Repository: Qiskit/qiskit-terra (python)

Issue:
qc.qasm() does not create valid QASM when "qreg" or "creg" are register names
<!-- ⚠️ If you do not respect this template, your issue will be closed -->
<!-- ⚠️ Make sure to browse the opened and closed issues -->

### Information

- **Qiskit Terra version**:  master
- **Python version**: 3.7
- **Operating system**: MacOS

### What is the current behavior?

If you set the name of circuit register as `qreg` or `creg` in your QASM, then the parser fails.

### Steps to reproduce the problem

In general, ny name is allow for registers
```python
from qiskit import *

qr = QuantumRegister(1,'qreg')
cr = ClassicalRegister(1,'creg')
qc = QuantumCircuit(qr, cr)

print(qc.qasm())
```
```
OPENQASM 2.0;
include "qelib1.inc";
qreg qreg[1];
creg creg[1];
```
However, the parse seems not supporting `qreg` or `creg` as names:
```python
QuantumCircuit.from_qasm_str(qc.qasm())
```
```
QasmError: "Expected an ID, received 'qreg'"
```

### What is the expected behavior?

I'm not fully sure if `qreg` and `creg` are reserved words in the specification. If so, It should not be allowed to do `ClassicalRegister(1,'creg')` (or, alternatively, change the name when `qc.qasm()`, with a warning). Otherwise, the parser needs to be fixed. 



Pull request:
Relax register-naming restrictions
### Summary

Our registers were still being constrained to have names that were valid OpenQASM 2.  This was becoming unnecessarily restrictive, especially as we start considering importing from OpenQASM 3, and the general decoupling of Qiskit from the limitations of _any_ version of the OpenQASM specification.

This more properly fixes the escaping of register names (and gate names, as a side effect) in the OpenQASM 2 export, which previously could produce reserved OpenQASM 2 keywords as well.


<!--
⚠️ If you do not respect this template, your pull request will be closed.
⚠️ Your pull request title should be short detailed and understandable for all.
⚠️ Also, please add a release note file using reno if the change needs to be
  documented in the release notes.
⚠️ If your pull request fixes an open issue, please link to the issue.

- [ ] I have added the tests to cover my changes.
- [ ] I have updated the documentation accordingly.
- [ ] I have read the CONTRIBUTING document.
-->


### Details and comments

This has been biting me as I wrote a quick-and-dirty OpenQASM 3 -> Qiskit importer.  Registers can already have invalid OpenQASM 2 names (e.g. you can call a register `qreg`), so there seems to be little reason to keep a restrictive naming covenant that wasn't doing its job anyway.

Fix #5043.

Patch:
diff --git a/qiskit/circuit/classicalregister.py b/qiskit/circuit/classicalregister.py
index b4e41ba35..83fc3fdba 100644
--- a/qiskit/circuit/classicalregister.py
+++ b/qiskit/circuit/classicalregister.py
@@ -10,12 +10,17 @@
 # copyright notice, and modified files need to carry a notice indicating
 # that they have been altered from the originals.
 
+# pylint: disable=bad-docstring-quotes
+
 """
 Classical register reference object.
 """
 import itertools
 
 from qiskit.circuit.exceptions import CircuitError
+
+# Over-specific import to avoid cyclic imports.
+from qiskit.utils.deprecation import deprecate_function
 from .register import Register
 from .bit import Bit
 
@@ -53,6 +58,11 @@ class ClassicalRegister(Register):
     prefix = "c"
     bit_type = Clbit
 
+    @deprecate_function(
+        "Register.qasm() is deprecated since Terra 0.23, as correct exporting to OpenQASM 2 is "
+        "the responsibility of a larger exporter; it cannot safely be done on an object-by-object "
+        "basis without context. No replacement will be provided, because the premise is wrong."
+    )
     def qasm(self):
         """Return OPENQASM string for this register."""
         return "creg %s[%d];" % (self.name, self.size)
diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py
index 808b9d286..ca30fe556 100644
--- a/qiskit/circuit/quantumcircuit.py
+++ b/qiskit/circuit/quantumcircuit.py
@@ -15,6 +15,7 @@
 """Quantum circuit object."""
 
 from __future__ import annotations
+import collections.abc
 import copy
 import itertools
 import functools
@@ -107,6 +108,20 @@ BitType = TypeVar("BitType", Qubit, Clbit)
 
 # Regex pattern to match valid OpenQASM identifiers
 VALID_QASM2_IDENTIFIER = re.compile("[a-z][a-zA-Z_0-9]*")
+QASM2_RESERVED = {
+    "OPENQASM",
+    "qreg",
+    "creg",
+    "include",
+    "gate",
+    "opaque",
+    "U",
+    "CX",
+    "measure",
+    "reset",
+    "if",
+    "barrier",
+}
 
 
 class QuantumCircuit:
@@ -1552,23 +1567,6 @@ class QuantumCircuit:
             dag = pass_.run(dag)
         return dag_to_circuit(dag)
 
-    def _unique_register_name(self, prefix: str = "") -> str:
-        """Generate a register name with the given prefix, which is unique within this circuit."""
-        used = {
-            reg.name[len(prefix) :]
-            for reg in itertools.chain(self.qregs, self.cregs)
-            if reg.name.startswith(prefix)
-        }
-        characters = (string.digits + string.ascii_letters) if prefix else string.ascii_letters
-        for parts in itertools.chain.from_iterable(
-            itertools.product(characters, repeat=n) for n in itertools.count(1)
-        ):
-            name = "".join(parts)
-            if name not in used:
-                return prefix + name
-        # This isn't actually reachable because the above loop is infinite.
-        return prefix
-
     def qasm(
         self,
         formatted: bool = False,
@@ -1654,31 +1652,28 @@ class QuantumCircuit:
 
         string_temp = self.header + "\n"
         string_temp += self.extension_lib + "\n"
-        for register in self.qregs:
-            string_temp += register.qasm() + "\n"
-        for register in self.cregs:
-            string_temp += register.qasm() + "\n"
-
-        bit_labels = {
-            bit: "%s[%d]" % (reg.name, idx)
-            for reg in self.qregs + self.cregs
-            for (idx, bit) in enumerate(reg)
-        }
-
-        regless_qubits = set(self.qubits) - {bit for reg in self.qregs for bit in reg}
-        regless_clbits = set(self.clbits) - {bit for reg in self.cregs for bit in reg}
 
+        regless_qubits = [bit for bit in self.qubits if not self.find_bit(bit).registers]
+        regless_clbits = [bit for bit in self.clbits if not self.find_bit(bit).registers]
+        dummy_registers = []
         if regless_qubits:
-            register_name = self._unique_register_name("qregless_")
-            string_temp += f"qreg {register_name}[{len(regless_qubits)}];\n"
-            bit_labels.update(
-                {bit: f"{register_name}[{idx}]" for idx, bit in enumerate(regless_qubits)}
-            )
+            dummy_registers.append(QuantumRegister(name="qregless", bits=regless_qubits))
         if regless_clbits:
-            register_name = self._unique_register_name("cregless_")
-            string_temp += f"creg {register_name}[{len(regless_clbits)}];\n"
-            bit_labels.update(
-                {bit: f"{register_name}[{idx}]" for idx, bit in enumerate(regless_clbits)}
+            dummy_registers.append(ClassicalRegister(name="cregless", bits=regless_clbits))
+        register_escaped_names = {}
+        for regs in (self.qregs, self.cregs, dummy_registers):
+            for reg in regs:
+                register_escaped_names[
+                    _make_unique(_qasm_escape_name(reg.name, "reg_"), register_escaped_names)
+                ] = reg
+        bit_labels = {
+            bit: "%s[%d]" % (name, idx)
+            for name, register in register_escaped_names.items()
+            for (idx, bit) in enumerate(register)
+        }
+        for name, reg in register_escaped_names.items():
+            string_temp += (
+                f"{'qreg' if isinstance(reg, QuantumRegister) else 'creg'} {name}[{reg.size}];\n"
             )
 
         for instruction in self._data:
@@ -1691,10 +1686,16 @@ class QuantumCircuit:
                     bit_labels[qubit],
                     bit_labels[clbit],
                 )
+            elif operation.name == "reset":
+                string_temp += f"reset {bit_labels[instruction.qubits[0]]}\n"
+            elif operation.name == "barrier":
+                qargs = ",".join(bit_labels[q] for q in instruction.qubits)
+                string_temp += "barrier;\n" if not qargs else f"barrier {qargs};\n"
             else:
                 # Check instructions names or label are valid
-                if not VALID_QASM2_IDENTIFIER.fullmatch(operation.name):
-                    operation = operation.copy(name=_qasm_escape_gate_name(operation.name))
+                escaped = _qasm_escape_name(operation.name, "gate_")
+                if escaped != operation.name:
+                    operation = operation.copy(name=escaped)
 
                 # decompose gate using definitions if they are not defined in OpenQASM2
                 if (
@@ -4748,8 +4749,9 @@ def _add_sub_instruction_to_existing_composite_circuits(
     for sub_instruction in instruction.definition:
         sub_operation = sub_instruction.operation
         # Check instructions names are valid
-        if not VALID_QASM2_IDENTIFIER.fullmatch(sub_operation.name):
-            sub_operation = sub_operation.copy(name=_qasm_escape_gate_name(sub_operation.name))
+        escaped = _qasm_escape_name(sub_operation.name, "gate_")
+        if escaped != sub_operation.name:
+            sub_operation = sub_operation.copy(name=escaped)
         if (
             sub_operation.name not in existing_gate_names
             and sub_operation not in existing_composite_circuits
@@ -4760,17 +4762,36 @@ def _add_sub_instruction_to_existing_composite_circuits(
             )
 
 
-def _qasm_escape_gate_name(name: str) -> str:
-    """Returns a valid OpenQASM gate identifier"""
-    # Replace all non-ASCII-word characters with the underscore.
+def _qasm_escape_name(name: str, prefix: str) -> str:
+    """Returns a valid OpenQASM identifier, using `prefix` as a prefix if necessary.  `prefix` must
+    itself be a valid identifier."""
+    # Replace all non-ASCII-word characters (letters, digits, underscore) with the underscore.
     escaped_name = re.sub(r"\W", "_", name, flags=re.ASCII)
-    if not escaped_name or escaped_name[0] not in string.ascii_lowercase:
-        # Add an arbitrary, guaranteed-to-be-valid prefix.
-        escaped_name = "gate_" + escaped_name
-
+    if (
+        not escaped_name
+        or escaped_name[0] not in string.ascii_lowercase
+        or escaped_name in QASM2_RESERVED
+    ):
+        escaped_name = prefix + escaped_name
     return escaped_name
 
 
+def _make_unique(name: str, already_defined: collections.abc.Set[str]) -> str:
+    """Generate a name by suffixing the given stem that is unique within the defined set."""
+    if name not in already_defined:
+        return name
+    used = {in_use[len(name) :] for in_use in already_defined if in_use.startswith(name)}
+    characters = (string.digits + string.ascii_letters) if name else string.ascii_letters
+    for parts in itertools.chain.from_iterable(
+        itertools.product(characters, repeat=n) for n in itertools.count(1)
+    ):
+        suffix = "".join(parts)
+        if suffix not in used:
+            return name + suffix
+    # This isn't actually reachable because the above loop is infinite.
+    return name
+
+
 def _get_composite_circuit_qasm_from_instruction(instruction: Instruction) -> str:
     """Returns OpenQASM string composite circuit given an instruction.
     The given instruction should be the result of composite_circuit.to_instruction()."""
@@ -4788,8 +4809,9 @@ def _get_composite_circuit_qasm_from_instruction(instruction: Instruction) -> st
     }
     for sub_instruction in definition:
         sub_operation = sub_instruction.operation
-        if not VALID_QASM2_IDENTIFIER.fullmatch(sub_operation.name):
-            sub_operation = sub_operation.copy(name=_qasm_escape_gate_name(sub_operation.name))
+        escaped = _qasm_escape_name(sub_operation.name, "gate_")
+        if escaped != sub_operation.name:
+            sub_operation = sub_operation.copy(name=escaped)
 
         gate_qargs = ",".join(
             "q%i" % index
diff --git a/qiskit/circuit/quantumregister.py b/qiskit/circuit/quantumregister.py
index 2929fcb00..191aae53e 100644
--- a/qiskit/circuit/quantumregister.py
+++ b/qiskit/circuit/quantumregister.py
@@ -10,12 +10,17 @@
 # copyright notice, and modified files need to carry a notice indicating
 # that they have been altered from the originals.
 
+# pylint: disable=bad-docstring-quotes
+
 """
 Quantum register reference object.
 """
 import itertools
 
 from qiskit.circuit.exceptions import CircuitError
+
+# Over-specific import to avoid cyclic imports.
+from qiskit.utils.deprecation import deprecate_function
 from .register import Register
 from .bit import Bit
 
@@ -53,6 +58,11 @@ class QuantumRegister(Register):
     prefix = "q"
     bit_type = Qubit
 
+    @deprecate_function(
+        "Register.qasm() is deprecated since Terra 0.23, as correct exporting to OpenQASM 2 is "
+        "the responsibility of a larger exporter; it cannot safely be done on an object-by-object "
+        "basis without context. No replacement will be provided, because the premise is wrong."
+    )
     def qasm(self):
         """Return OPENQASM string for this register."""
         return "qreg %s[%d];" % (self.name, self.size)
diff --git a/qiskit/circuit/register.py b/qiskit/circuit/register.py
index 44252c40c..9e246a1fd 100644
--- a/qiskit/circuit/register.py
+++ b/qiskit/circuit/register.py
@@ -21,15 +21,29 @@ import numpy as np
 
 from qiskit.circuit.exceptions import CircuitError
 
+# Over-specific import to avoid cyclic imports.
+from qiskit.utils.deprecation import deprecate_function
+
 
 class Register:
     """Implement a generic register."""
 
     __slots__ = ["_name", "_size", "_bits", "_bit_indices", "_hash", "_repr"]
 
-    # Register name should conform to OpenQASM 2.0 specification
-    # See appendix A of https://arxiv.org/pdf/1707.03429v2.pdf
-    name_format = re.compile("[a-z][a-zA-Z0-9_]*")
+    _name_format = re.compile("[a-z][a-zA-Z0-9_]*")
+
+    # In historical version of Terra, registers' name had to conform to the OpenQASM 2 specification
+    # (see appendix A of https://arxiv.org/pdf/1707.03429v2.pdf), and this regex enforced it.  That
+    # restriction has been relaxed, so this is no longer necessary.
+    @property
+    @deprecate_function(
+        "Register.name_format is deprecated as of Qiskit Terra 0.23, and will be removed in a"
+        " future release. There is no longer a restriction on the names of registers, so the"
+        " attribute has no meaning any more."
+    )
+    def name_format(self):
+        # pylint: disable=missing-function-docstring
+        return self._name_format
 
     # Counter for the number of instances in this class.
     instances_counter = itertools.count()
@@ -100,11 +114,6 @@ class Register:
                     "The circuit name should be castable to a string "
                     "(or None for autogenerate a name)."
                 ) from ex
-            if self.name_format.match(name) is None:
-                raise CircuitError(
-                    "%s is an invalid OPENQASM register name. See appendix"
-                    " A of https://arxiv.org/pdf/1707.03429v2.pdf." % name
-                )
 
         self._name = name
         self._size = size
diff --git a/qiskit/extensions/unitary.py b/qiskit/extensions/unitary.py
index 60f62f674..b0e8716ba 100644
--- a/qiskit/extensions/unitary.py
+++ b/qiskit/extensions/unitary.py
@@ -21,7 +21,7 @@ from qiskit.circuit import QuantumCircuit
 from qiskit.circuit import QuantumRegister, Qubit
 from qiskit.circuit.exceptions import CircuitError
 from qiskit.circuit._utils import _compute_control_matrix
-from qiskit.circuit.quantumcircuit import _qasm_escape_gate_name
+from qiskit.circuit.quantumcircuit import _qasm_escape_name
 from qiskit.circuit.library.standard_gates import U3Gate
 from qiskit.extensions.quantum_initializer import isometry
 from qiskit.quantum_info.operators.predicates import matrix_equal
@@ -178,7 +178,7 @@ class UnitaryGate(Gate):
 
         # give this unitary a name
         self._qasm_name = (
-            _qasm_escape_gate_name(self.label) if self.label else "unitary" + str(id(self))
+            _qasm_escape_name(self.label, "gate_") if self.label else "unitary" + str(id(self))
         )
 
         qubit_to_qasm = {bit: f"p{i}" for i, bit in enumerate(self.definition.qubits)}
diff --git a/qiskit/qpy/binary_io/circuits.py b/qiskit/qpy/binary_io/circuits.py
index c0430c432..4053fb0a5 100644
--- a/qiskit/qpy/binary_io/circuits.py
+++ b/qiskit/qpy/binary_io/circuits.py
@@ -171,19 +171,10 @@ def _read_instruction(file_obj, circuit, registers, custom_operations, version,
     params = []
     condition_tuple = None
     if instruction.has_condition:
-        # If an invalid register name is used assume it's a single bit
-        # condition and treat the register name as a string of the clbit index
-        if ClassicalRegister.name_format.match(condition_register) is None:
-            # If invalid register prefixed with null character it's a clbit
-            # index for single bit condition
-            if condition_register[0] == "\x00":
-                conditional_bit = int(condition_register[1:])
-                condition_tuple = (circuit.clbits[conditional_bit], instruction.condition_value)
-            else:
-                raise ValueError(
-                    f"Invalid register name: {condition_register} for condition register of "
-                    f"instruction: {gate_name}"
-                )
+        # If register name prefixed with null character it's a clbit index for single bit condition.
+        if condition_register[0] == "\x00":
+            conditional_bit = int(condition_register[1:])
+            condition_tuple = (circuit.clbits[conditional_bit], instruction.condition_value)
         else:
             condition_tuple = (registers["c"][condition_register], instruction.condition_value)
     if circuit is not None:
diff --git a/releasenotes/notes/relax-register-naming-0e7d2dba9bf7fb38.yaml b/releasenotes/notes/relax-register-naming-0e7d2dba9bf7fb38.yaml
new file mode 100644
index 000000000..f6781d8aa
--- /dev/null
+++ b/releasenotes/notes/relax-register-naming-0e7d2dba9bf7fb38.yaml
@@ -0,0 +1,38 @@
+---
+fixes:
+  - |
+    :meth:`.QuantumCircuit.qasm` will now correctly escape gate and register
+    names that collide with reserved OpenQASM 2 keywords.  Fixes
+    `#5043 <https://github.com/Qiskit/qiskit-terra/issues/5043>`__.
+upgrade:
+  - |
+    The names of :class:`.Register` instances are no longer constrained to be
+    valid OpenQASM 2 identifiers.  This is being done as the restriction is
+    overly strict as Qiskit becomes more decoupled from OpenQASM 2, and even the
+    OpenQASM 3 specification is not so restrictive.  If you were relying on
+    registers having valid OpenQASM 2 identifier names, you will need to begin
+    escaping the names.  A simplistic version of this could be done, for example,
+    by::
+
+      import re
+      import string
+      
+      def escape(name: str) -> str:
+        out = re.sub(r"\W", "_", name, flags=re.ASCII)
+        if not out or out[0] not in string.ascii_lowercase:
+          return "reg_" + out
+        return out
+deprecations:
+  - |
+    The method :meth:`.Register.qasm` is deprecated and will be removed in a
+    future release.  This method is found on the subclasses :class:`.QuantumRegister`
+    and :class:`.ClassicalRegister`.  The deprecation is because the
+    :meth:`~.Register.qasm` method promotes a false view of the responsible
+    party for safe conversion to OpenQASM 2; a single object alone does not
+    have the context to provide a safe conversion, such as whether its name
+    clashes after escaping it to produce a valid identifier.
+  - |
+    The class-variable regular expression :attr:`.Register.name_format` is
+    deprecated and wil be removed in a future release.  The names of registers
+    are now permitted to be any valid Python string, so the regular expression
+    has no use.


Test patch:
diff --git a/test/python/circuit/test_circuit_qasm.py b/test/python/circuit/test_circuit_qasm.py
index 7c1d9c078..d02aba018 100644
--- a/test/python/circuit/test_circuit_qasm.py
+++ b/test/python/circuit/test_circuit_qasm.py
@@ -17,7 +17,7 @@ import re
 
 from qiskit import QuantumRegister, ClassicalRegister, QuantumCircuit
 from qiskit.test import QiskitTestCase
-from qiskit.circuit import Parameter, Qubit, Clbit
+from qiskit.circuit import Parameter, Qubit, Clbit, Gate
 from qiskit.qasm.exceptions import QasmError
 
 # Regex pattern to match valid OpenQASM identifiers
@@ -451,6 +451,46 @@ custom_{id(gate2)} q[1],q[0];\n"""
         for idx, instruction in enumerate(base._data):
             self.assertEqual(instruction.operation.name, names[idx])
 
+    def test_circuit_qasm_escapes_register_names(self):
+        """Test that registers that have invalid OpenQASM 2 names get correctly escaped, even when
+        they would escape to the same value."""
+        qc = QuantumCircuit(QuantumRegister(2, "?invalid"), QuantumRegister(2, "!invalid"))
+        qc.cx(0, 1)
+        qc.cx(2, 3)
+        qasm = qc.qasm()
+        match = re.fullmatch(
+            rf"""OPENQASM 2.0;
+include "qelib1.inc";
+qreg ({VALID_QASM2_IDENTIFIER.pattern})\[2\];
+qreg ({VALID_QASM2_IDENTIFIER.pattern})\[2\];
+cx \1\[0\],\1\[1\];
+cx \2\[0\],\2\[1\];
+""",
+            qasm,
+        )
+        self.assertTrue(match)
+        self.assertNotEqual(match.group(1), match.group(2))
+
+    def test_circuit_qasm_escapes_reserved(self):
+        """Test that the OpenQASM 2 exporter won't export reserved names."""
+        qc = QuantumCircuit(QuantumRegister(1, "qreg"))
+        gate = Gate("gate", 1, [])
+        gate.definition = QuantumCircuit(1)
+        qc.append(gate, [qc.qubits[0]])
+        qasm = qc.qasm()
+        match = re.fullmatch(
+            rf"""OPENQASM 2.0;
+include "qelib1.inc";
+gate ({VALID_QASM2_IDENTIFIER.pattern}) q0 {{  }}
+qreg ({VALID_QASM2_IDENTIFIER.pattern})\[1\];
+\1 \2\[0\];
+""",
+            qasm,
+        )
+        self.assertTrue(match)
+        self.assertNotEqual(match.group(1), "gate")
+        self.assertNotEqual(match.group(1), "qreg")
+
     def test_circuit_qasm_with_double_precision_rotation_angle(self):
         """Test that qasm() emits high precision rotation angles per default."""
         from qiskit.circuit.tools.pi_check import MAX_FRAC
diff --git a/test/python/circuit/test_identifiers_circuits.py b/test/python/circuit/test_identifiers_circuits.py
index 5ee0d5f4e..06634fc4e 100644
--- a/test/python/circuit/test_identifiers_circuits.py
+++ b/test/python/circuit/test_identifiers_circuits.py
@@ -79,22 +79,6 @@ class TestInvalidIds(QiskitTestCase):
         cr = ClassicalRegister(size=3)
         self.assertRaises(CircuitError, QuantumCircuit, qr, cr, name=1)
 
-    def test_invalid_type_qr_name(self):
-        """QuantumRegister() with an invalid type name."""
-        self.assertRaises(CircuitError, QuantumRegister, size=3, name=1)
-
-    def test_invalid_type_cr_name(self):
-        """ClassicalRegister() with an invalid type name."""
-        self.assertRaises(CircuitError, ClassicalRegister, size=3, name=1)
-
-    def test_invalid_qasmname_qr(self):
-        """QuantumRegister() with invalid name."""
-        self.assertRaises(CircuitError, QuantumRegister, size=3, name="Qr")
-
-    def test_invalid_qasmname_cr(self):
-        """ClassicalRegister() with invalid name."""
-        self.assertRaises(CircuitError, ClassicalRegister, size=3, name="Cr")
-
 
 if __name__ == "__main__":
     unittest.main(verbosity=2)
diff --git a/test/python/circuit/test_register.py b/test/python/circuit/test_register.py
index bd72b1a44..35ddcb3b5 100644
--- a/test/python/circuit/test_register.py
+++ b/test/python/circuit/test_register.py
@@ -52,11 +52,6 @@ class TestRegisterClass(QiskitTestCase):
         with self.assertRaisesRegex(CircuitError, "did not all match register type"):
             _ = reg_type(bits=bits)
 
-    @data(QuantumRegister, ClassicalRegister, AncillaRegister)
-    def test_init_raise_if_passed_invalid_name(self, reg_type):
-        with self.assertRaisesRegex(CircuitError, "invalid OPENQASM register name"):
-            _ = reg_type(size=1, name="_q")
-
     @data(QuantumRegister, ClassicalRegister, AncillaRegister)
     def test_init_with_zero_size(self, reg_type):
         register = reg_type(0)