diff --git a/qiskit/circuit/quantumcircuit.py b/qiskit/circuit/quantumcircuit.py index 16d5810b773c..6918a0a01805 100644 --- a/qiskit/circuit/quantumcircuit.py +++ b/qiskit/circuit/quantumcircuit.py @@ -334,8 +334,12 @@ def extend(self, rhs): if element not in self.cregs: self.cregs.append(element) + # Copy the circuit data if rhs and self are the same, otherwise the data of rhs is + # appended to both self and rhs resulting in an infinite loop + data = rhs.data.copy() if rhs is self else rhs.data + # Add new gates - for instruction_context in rhs.data: + for instruction_context in data: self._append(*instruction_context) return self diff --git a/releasenotes/notes/copy-rhs-on-extending-qc-9e65804b6b0ab4da.yaml b/releasenotes/notes/copy-rhs-on-extending-qc-9e65804b6b0ab4da.yaml new file mode 100644 index 000000000000..9a822a74c2e4 --- /dev/null +++ b/releasenotes/notes/copy-rhs-on-extending-qc-9e65804b6b0ab4da.yaml @@ -0,0 +1,8 @@ +--- +fixes: + - | + When extending a `QuantumCircuit` instance (extendee) with another circuit (extension), + the circuit is taken via reference. If a circuit is extended with itself that + leads to an infinite loop as extendee and extension are the same. + This bug is resolved by copying the extension if it is the same object as + the extendee. \ No newline at end of file diff --git a/test/python/circuit/test_circuit_operations.py b/test/python/circuit/test_circuit_operations.py index 4afc9d59ddf2..4f00778aa492 100644 --- a/test/python/circuit/test_circuit_operations.py +++ b/test/python/circuit/test_circuit_operations.py @@ -25,6 +25,22 @@ class TestCircuitOperations(QiskitTestCase): """QuantumCircuit Operations tests.""" + def test_adding_self(self): + """Test that qc += qc finishes, which can be prone to infinite while-loops. + + This can occur e.g. when a user tries + >>> other_qc = qc + >>> other_qc += qc # or qc2.extend(qc) + """ + qc = QuantumCircuit(1) + qc.x(0) # must contain at least one operation to end up in a infinite while-loop + + # attempt addition, times out if qc is added via reference + qc += qc + + # finally, qc should contain two X gates + self.assertEqual(['x', 'x'], [x[0].name for x in qc.data]) + def test_combine_circuit_common(self): """Test combining two circuits with same registers. """