Repository: PennyLaneAI/pennylane
Pull request #6713 (2024-12-12 17:17:42)

Update `qml.wires.Wires` to disallow `wires=None`
**Context:**

Currently, the behaviour is,
```python
>>> qml.wires.Wires(None)
Wires([None])
```
which doesn't make sense.

With this change we get the intended behaviour,
```python
>>> qml.wires.Wires(None)
TypeError: Must specify a set of wires.
```

**Description of the change:**

Had to clean-up some templates that relied on defaulting to `None` 😓. 

**Benefits:** Logical code 😃 

**Possible Drawbacks:** None

[sc-80454]


github-actions[bot]: Hello. You may have forgotten to update the changelog!
Please edit [`doc/releases/changelog-dev.md`](/PennyLaneAI/pennylane/blob/master/doc/releases/changelog-dev.md) with:
* A one-to-two sentence description of the change. You may include a small working example for new features.
* A link back to this PR.
* Your name (or GitHub username) in the contributors section.
andrijapau: @KetpuntoG, great question. The decision to move away from `wires=None` was recently escalated due to the problems it is causing in the program capture initiative. Additionally, having `wires` set to `None` (or `Wires([None])` doesn't really make sense) so this was a good opportunity to clean up the codebase.
codecov[bot]: ## [Codecov](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/6713?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
All modified and coverable lines are covered by tests :white_check_mark:
> Project coverage is 99.61%. Comparing base [(`08c1d3a`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/08c1d3ae30a632a498ef642fea753ae04f3f2512?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) to head [(`1aa3f30`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/1aa3f30b3758b2db5263b0ae7c0b7b38c2625322?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).

<details><summary>Additional details and impacted files</summary>


```diff
@@           Coverage Diff           @@
##           master    #6713   +/-   ##
=======================================
  Coverage   99.61%   99.61%           
=======================================
  Files         469      469           
  Lines       44233    44247   +14     
=======================================
+ Hits        44064    44078   +14     
  Misses        169      169           
```

</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/6713?dropdown=coverage&src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).


Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 071ed4185..cec024e66 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -451,6 +451,9 @@ same information.
 
 <h3>Bug fixes 🐛</h3>
 
+* The `Wires` object throws a `TypeError` if `wires=None`. 
+  [(#6713)](https://github.com/PennyLaneAI/pennylane/pull/6713)
+
 * The `qml.Hermitian` class no longer checks that the provided matrix is hermitian.
   The reason for this removal is to allow for faster execution and avoid incompatibilities with `jax.jit`.
   [(#6642)](https://github.com/PennyLaneAI/pennylane/pull/6642)
diff --git a/pennylane/templates/subroutines/adder.py b/pennylane/templates/subroutines/adder.py
index f4d0da209..5b1951876 100644
--- a/pennylane/templates/subroutines/adder.py
+++ b/pennylane/templates/subroutines/adder.py
@@ -17,6 +17,7 @@ Contains the Adder template.
 
 import pennylane as qml
 from pennylane.operation import Operation
+from pennylane.wires import WiresLike
 
 
 class Adder(Operation):
@@ -46,7 +47,7 @@ class Adder(Operation):
         mod (int): the modulo for performing the addition. If not provided, it will be set to its maximum value, :math:`2^{\text{len(x_wires)}}`.
         work_wires (Sequence[int]): the auxiliary wires to use for the addition. The
             work wires are not needed if :math:`mod=2^{\text{len(x_wires)}}`, otherwise two work wires
-            should be provided. Defaults to ``None``.
+            should be provided. Defaults to empty set.
 
     **Example**
 
@@ -89,7 +90,7 @@ class Adder(Operation):
 
         The second set of wires is ``work_wires`` which consist of the auxiliary qubits used to perform the modular addition operation.
 
-        - If :math:`mod = 2^{\text{len(x_wires)}}`, there will be no need for ``work_wires``, hence ``work_wires=None``. This is the case by default.
+        - If :math:`mod = 2^{\text{len(x_wires)}}`, there will be no need for ``work_wires``, hence ``work_wires=()``. This is the case by default.
 
         - If :math:`mod \neq 2^{\text{len(x_wires)}}`, two ``work_wires`` have to be provided.
 
@@ -100,12 +101,14 @@ class Adder(Operation):
     grad_method = None
 
     def __init__(
-        self, k, x_wires, mod=None, work_wires=None, id=None
+        self, k, x_wires: WiresLike, mod=None, work_wires: WiresLike = (), id=None
     ):  # pylint: disable=too-many-arguments
 
         x_wires = qml.wires.Wires(x_wires)
+        work_wires = work_wires or ()
+        work_wires = qml.wires.Wires(work_wires)
 
-        num_works_wires = 0 if work_wires is None else len(work_wires)
+        num_works_wires = len(work_wires)
 
         if mod is None:
             mod = 2 ** len(x_wires)
@@ -113,7 +116,7 @@ class Adder(Operation):
             raise ValueError(f"If mod is not 2^{len(x_wires)}, two work wires should be provided")
         if not isinstance(k, int) or not isinstance(mod, int):
             raise ValueError("Both k and mod must be integers")
-        if work_wires is not None:
+        if num_works_wires != 0:
             if any(wire in work_wires for wire in x_wires):
                 raise ValueError("None of the wires in work_wires should be included in x_wires.")
         if mod > 2 ** len(x_wires):
@@ -169,7 +172,9 @@ class Adder(Operation):
         return cls._primitive.bind(*args, **kwargs)
 
     @staticmethod
-    def compute_decomposition(k, x_wires, mod, work_wires):  # pylint: disable=arguments-differ
+    def compute_decomposition(
+        k, x_wires: WiresLike, mod, work_wires: WiresLike
+    ):  # pylint: disable=arguments-differ
         r"""Representation of the operator as a product of other operators.
 
         Args:
@@ -180,7 +185,7 @@ class Adder(Operation):
             mod (int): the modulo for performing the addition. If not provided, it will be set to its maximum value, :math:`2^{\text{len(x_wires)}}`.
             work_wires (Sequence[int]): the auxiliary wires to use for the addition. The
                 work wires are not needed if :math:`mod=2^{\text{len(x_wires)}}`, otherwise two work wires
-                should be provided. Defaults to ``None``.
+                should be provided.
         Returns:
             list[.Operator]: Decomposition of the operator
 
@@ -194,7 +199,7 @@ class Adder(Operation):
         op_list = []
         if mod == 2 ** len(x_wires):
             qft_wires = x_wires
-            work_wire = None
+            work_wire = ()
         else:
             qft_wires = work_wires[:1] + x_wires
             work_wire = work_wires[1:]
diff --git a/pennylane/templates/subroutines/mod_exp.py b/pennylane/templates/subroutines/mod_exp.py
index 37e15d016..a77c4f660 100644
--- a/pennylane/templates/subroutines/mod_exp.py
+++ b/pennylane/templates/subroutines/mod_exp.py
@@ -18,6 +18,7 @@ import numpy as np
 
 import pennylane as qml
 from pennylane.operation import Operation
+from pennylane.wires import WiresLike
 
 
 class ModExp(Operation):
@@ -49,7 +50,7 @@ class ModExp(Operation):
         mod (int): the modulo for performing the exponentiation. If not provided, it will be set to its maximum value, :math:`2^{\text{len(output_wires)}}`
         work_wires (Sequence[int]): the auxiliary wires to use for the exponentiation. If
             :math:`mod=2^{\text{len(output_wires)}}`, the number of auxiliary wires must be ``len(output_wires)``. Otherwise
-            ``len(output_wires) + 2`` auxiliary wires are needed.
+            ``len(output_wires) + 2`` auxiliary wires are needed. Defaults to empty set.
 
     **Example**
 
@@ -112,12 +113,13 @@ class ModExp(Operation):
     grad_method = None
 
     def __init__(
-        self, x_wires, output_wires, base, mod=None, work_wires=None, id=None
+        self, x_wires: WiresLike, output_wires, base, mod=None, work_wires: WiresLike = (), id=None
     ):  # pylint: disable=too-many-arguments
 
         output_wires = qml.wires.Wires(output_wires)
-
-        if work_wires is None:
+        work_wires = work_wires or ()
+        work_wires = qml.wires.Wires(work_wires)
+        if len(work_wires) == 0:
             raise ValueError("Work wires must be specified for ModExp")
 
         if mod is None:
@@ -130,7 +132,7 @@ class ModExp(Operation):
         else:
             if len(work_wires) < len(output_wires):
                 raise ValueError("ModExp needs as many work_wires as output_wires.")
-        if work_wires is not None:
+        if len(work_wires) != 0:
             if any(wire in work_wires for wire in x_wires):
                 raise ValueError("None of the wires in work_wires should be included in x_wires.")
             if any(wire in work_wires for wire in output_wires):
@@ -198,7 +200,7 @@ class ModExp(Operation):
 
     @staticmethod
     def compute_decomposition(
-        x_wires, output_wires, base, mod, work_wires
+        x_wires, output_wires: WiresLike, base, mod, work_wires: WiresLike
     ):  # pylint: disable=arguments-differ
         r"""Representation of the operator as a product of other operators.
 
diff --git a/pennylane/templates/subroutines/multiplier.py b/pennylane/templates/subroutines/multiplier.py
index ee4383ad2..5175a11d9 100644
--- a/pennylane/templates/subroutines/multiplier.py
+++ b/pennylane/templates/subroutines/multiplier.py
@@ -19,9 +19,10 @@ import numpy as np
 
 import pennylane as qml
 from pennylane.operation import Operation
+from pennylane.wires import WiresLike
 
 
-def _mul_out_k_mod(k, x_wires, mod, work_wire_aux, wires_aux):
+def _mul_out_k_mod(k, x_wires: WiresLike, mod, work_wire_aux: WiresLike, wires_aux: WiresLike):
     """Performs :math:`x \times k` in the registers wires wires_aux"""
     op_list = []
 
@@ -117,13 +118,14 @@ class Multiplier(Operation):
     grad_method = None
 
     def __init__(
-        self, k, x_wires, mod=None, work_wires=None, id=None
+        self, k, x_wires: WiresLike, mod=None, work_wires: WiresLike = (), id=None
     ):  # pylint: disable=too-many-arguments
-        if work_wires is None:
-            raise ValueError("Work wires must be specified for Multiplier")
 
         x_wires = qml.wires.Wires(x_wires)
+        work_wires = work_wires or ()
         work_wires = qml.wires.Wires(work_wires)
+        if len(work_wires) == 0:
+            raise ValueError("Work wires must be specified for Multiplier")
 
         if any(wire in work_wires for wire in x_wires):
             raise ValueError("None of the wire in work_wires should be included in x_wires.")
@@ -190,7 +192,9 @@ class Multiplier(Operation):
         return cls._primitive.bind(*args, **kwargs)
 
     @staticmethod
-    def compute_decomposition(k, x_wires, mod, work_wires):  # pylint: disable=arguments-differ
+    def compute_decomposition(
+        k, x_wires: WiresLike, mod, work_wires: WiresLike
+    ):  # pylint: disable=arguments-differ
         r"""Representation of the operator as a product of other operators.
 
         Args:
@@ -221,7 +225,7 @@ class Multiplier(Operation):
             wires_aux = work_wires[1:]
             wires_aux_swap = wires_aux[1:]
         else:
-            work_wire_aux = None
+            work_wire_aux = ()
             wires_aux = work_wires[: len(x_wires)]
             wires_aux_swap = wires_aux
         op_list.extend(_mul_out_k_mod(k, x_wires, mod, work_wire_aux, wires_aux))
diff --git a/pennylane/templates/subroutines/out_adder.py b/pennylane/templates/subroutines/out_adder.py
index 2dbcb924f..1c0094abc 100644
--- a/pennylane/templates/subroutines/out_adder.py
+++ b/pennylane/templates/subroutines/out_adder.py
@@ -17,6 +17,7 @@ Contains the OutAdder template.
 
 import pennylane as qml
 from pennylane.operation import Operation
+from pennylane.wires import WiresLike
 
 
 class OutAdder(Operation):
@@ -43,7 +44,7 @@ class OutAdder(Operation):
         y_wires (Sequence[int]): the wires that store the integer :math:`y`
         output_wires (Sequence[int]): the wires that store the addition result. If the register is in a non-zero state :math:`b`, the solution will be added to this value.
         mod (int): the modulo for performing the addition. If not provided, it will be set to its maximum value, :math:`2^{\text{len(output_wires)}}`.
-        work_wires (Sequence[int]): the auxiliary wires to use for the addition. The work wires are not needed if :math:`mod=2^{\text{len(output_wires)}}`, otherwise two work wires should be provided. Defaults to ``None``.
+        work_wires (Sequence[int]): the auxiliary wires to use for the addition. The work wires are not needed if :math:`mod=2^{\text{len(output_wires)}}`, otherwise two work wires should be provided. Defaults to empty set.
 
     **Example**
 
@@ -138,14 +139,22 @@ class OutAdder(Operation):
     grad_method = None
 
     def __init__(
-        self, x_wires, y_wires, output_wires, mod=None, work_wires=None, id=None
+        self,
+        x_wires: WiresLike,
+        y_wires: WiresLike,
+        output_wires: WiresLike,
+        mod=None,
+        work_wires: WiresLike = (),
+        id=None,
     ):  # pylint: disable=too-many-arguments
 
         x_wires = qml.wires.Wires(x_wires)
         y_wires = qml.wires.Wires(y_wires)
         output_wires = qml.wires.Wires(output_wires)
+        work_wires = work_wires or ()
+        work_wires = qml.wires.Wires(work_wires)
 
-        num_work_wires = 0 if work_wires is None else len(work_wires)
+        num_work_wires = len(work_wires)
 
         if mod is None:
             mod = 2 ** (len(output_wires))
@@ -158,7 +167,7 @@ class OutAdder(Operation):
             raise ValueError(
                 f"If mod is not 2^{len(output_wires)}, two work wires should be provided."
             )
-        if work_wires is not None:
+        if len(work_wires) != 0:
             if any(wire in work_wires for wire in x_wires):
                 raise ValueError("None of the wires in work_wires should be included in x_wires.")
             if any(wire in work_wires for wire in y_wires):
@@ -246,7 +255,7 @@ class OutAdder(Operation):
             work_wire = work_wires[1:]
         else:
             qft_new_output_wires = output_wires
-            work_wire = None
+            work_wire = ()
         op_list.append(qml.QFT(wires=qft_new_output_wires))
         op_list.append(
             qml.ControlledSequence(
diff --git a/pennylane/templates/subroutines/out_multiplier.py b/pennylane/templates/subroutines/out_multiplier.py
index 1f0f827e7..9147eadf0 100644
--- a/pennylane/templates/subroutines/out_multiplier.py
+++ b/pennylane/templates/subroutines/out_multiplier.py
@@ -17,6 +17,7 @@ Contains the OutMultiplier template.
 
 import pennylane as qml
 from pennylane.operation import Operation
+from pennylane.wires import WiresLike
 
 
 class OutMultiplier(Operation):
@@ -44,7 +45,7 @@ class OutMultiplier(Operation):
         mod (int): the modulo for performing the multiplication. If not provided, it will be set to its maximum value, :math:`2^{\text{len(output_wires)}}`
         work_wires (Sequence[int]): the auxiliary wires to use for the multiplication. The
             work wires are not needed if :math:`mod=2^{\text{len(output_wires)}}`, otherwise two work wires
-            should be provided. Defaults to ``None``.
+            should be provided. Defaults to empty set.
 
     **Example**
 
@@ -128,7 +129,7 @@ class OutMultiplier(Operation):
 
         The fourth set of wires is ``work_wires`` which consist of the auxiliary qubits used to perform the modular multiplication operation.
 
-        - If :math:`mod = 2^{\text{len(output_wires)}}`, there will be no need for ``work_wires``, hence ``work_wires=None``. This is the case by default.
+        - If :math:`mod = 2^{\text{len(output_wires)}}`, there will be no need for ``work_wires``, hence ``work_wires=()``. This is the case by default.
 
         - If :math:`mod \neq 2^{\text{len(output_wires)}}`, two ``work_wires`` have to be provided.
 
@@ -139,14 +140,22 @@ class OutMultiplier(Operation):
     grad_method = None
 
     def __init__(
-        self, x_wires, y_wires, output_wires, mod=None, work_wires=None, id=None
+        self,
+        x_wires: WiresLike,
+        y_wires: WiresLike,
+        output_wires: WiresLike,
+        mod=None,
+        work_wires: WiresLike = (),
+        id=None,
     ):  # pylint: disable=too-many-arguments
 
         x_wires = qml.wires.Wires(x_wires)
         y_wires = qml.wires.Wires(y_wires)
         output_wires = qml.wires.Wires(output_wires)
+        work_wires = work_wires or ()
+        work_wires = qml.wires.Wires(work_wires)
 
-        num_work_wires = 0 if work_wires is None else len(work_wires)
+        num_work_wires = len(work_wires)
 
         if mod is None:
             mod = 2 ** len(output_wires)
@@ -160,7 +169,7 @@ class OutMultiplier(Operation):
                 f"with len(output_wires)={len(output_wires)} is {2 ** len(output_wires)}, but received {mod}."
             )
 
-        if work_wires is not None:
+        if len(work_wires) != 0:
             if any(wire in work_wires for wire in x_wires):
                 raise ValueError("None of the wires in work_wires should be included in x_wires.")
             if any(wire in work_wires for wire in y_wires):
@@ -177,7 +186,7 @@ class OutMultiplier(Operation):
         wires_name = ["x_wires", "y_wires", "output_wires"]
         self.hyperparameters["work_wires"] = work_wires
 
-        if work_wires is not None:
+        if len(work_wires) != 0:
             wires_list.append(work_wires)
             wires_name.append("work_wires")
 
@@ -225,7 +234,7 @@ class OutMultiplier(Operation):
 
     @staticmethod
     def compute_decomposition(
-        x_wires, y_wires, output_wires, mod, work_wires
+        x_wires: WiresLike, y_wires: WiresLike, output_wires: WiresLike, mod, work_wires: WiresLike
     ):  # pylint: disable=arguments-differ
         r"""Representation of the operator as a product of other operators.
 
@@ -236,7 +245,7 @@ class OutMultiplier(Operation):
             mod (int): the modulo for performing the multiplication. If not provided, it will be set to its maximum value, :math:`2^{\text{len(output_wires)}}`
             work_wires (Sequence[int]): the auxiliary wires to use for the multiplication. The
                 work wires are not needed if :math:`mod=2^{\text{len(output_wires)}}`, otherwise two work wires
-                should be provided. Defaults to ``None``.
+                should be provided.
 
         Returns:
             list[.Operator]: Decomposition of the operator
@@ -254,7 +263,7 @@ class OutMultiplier(Operation):
             work_wire = work_wires[1:]
         else:
             qft_output_wires = output_wires
-            work_wire = None
+            work_wire = ()
         op_list.append(qml.QFT(wires=qft_output_wires))
         op_list.append(
             qml.ControlledSequence(
diff --git a/pennylane/templates/subroutines/out_poly.py b/pennylane/templates/subroutines/out_poly.py
index bc76d012f..16ae661ea 100644
--- a/pennylane/templates/subroutines/out_poly.py
+++ b/pennylane/templates/subroutines/out_poly.py
@@ -17,6 +17,7 @@ Contains the OutPoly template.
 
 import pennylane as qml
 from pennylane.operation import Operation
+from pennylane.wires import WiresLike
 
 
 def _get_polynomial(f, mod, *variable_sizes):
@@ -158,7 +159,7 @@ class OutPoly(Operation):
                              to :math:`2^{n}`, where :math:`n` is the number of qubits in the output register.
         work_wires (Union[Wires, Sequence[int]], optional): The auxiliary wires to use for performing the polynomial operation. The
                     work wires are not needed if :math:`mod=2^{\text{length(output_wires)}}`, otherwise two work wires
-                    should be provided. Default is ``None``.
+                    should be provided. Default is empty set.
 
     Raises:
         ValueError: If `mod` is not :math:`2^{\text{length(output_wires)}}` and insufficient number of work wires are provided.
@@ -262,9 +263,9 @@ class OutPoly(Operation):
         self,
         polynomial_function,
         input_registers,
-        output_wires,
+        output_wires: WiresLike,
         mod=None,
-        work_wires=None,
+        work_wires: WiresLike = (),
         id=None,
         **kwargs,
     ):  # pylint: disable=too-many-arguments
@@ -272,7 +273,9 @@ class OutPoly(Operation):
 
         registers_wires = [*input_registers, output_wires]
 
-        num_work_wires = 0 if not work_wires else len(work_wires)
+        work_wires = work_wires or ()
+        work_wires = qml.wires.Wires(work_wires)
+        num_work_wires = len(work_wires)
         if mod is None:
             mod = 2 ** len(registers_wires[-1])
         elif mod != 2 ** len(registers_wires[-1]) and num_work_wires != 2:
@@ -299,7 +302,7 @@ class OutPoly(Operation):
 
         self.hyperparameters["polynomial_function"] = polynomial_function
         self.hyperparameters["mod"] = mod
-        self.hyperparameters["work_wires"] = qml.wires.Wires(work_wires) if work_wires else None
+        self.hyperparameters["work_wires"] = qml.wires.Wires(work_wires)
 
         wires_vars = [len(w) for w in registers_wires[:-1]]
 
@@ -316,7 +319,7 @@ class OutPoly(Operation):
             coeffs, qml.math.floor(coeffs)
         ), "The polynomial function must have integer coefficients"
 
-        if work_wires:
+        if len(work_wires) != 0:
             all_wires += work_wires
 
         if len(all_wires) != sum(len(register) for register in registers_wires) + num_work_wires:
@@ -345,11 +348,7 @@ class OutPoly(Operation):
 
         new_output_wires = [wire_map[wire] for wire in self.hyperparameters["output_wires"]]
 
-        new_work_wires = (
-            [wire_map[wire] for wire in self.hyperparameters["work_wires"]]
-            if self.hyperparameters.get("work_wires")
-            else None
-        )
+        new_work_wires = [wire_map[wire] for wire in self.hyperparameters["work_wires"]]
 
         return OutPoly(
             polynomial_function=self.hyperparameters["polynomial_function"],
@@ -368,7 +367,12 @@ class OutPoly(Operation):
 
     @staticmethod
     def compute_decomposition(
-        polynomial_function, input_registers, output_wires, mod=None, work_wires=None, **kwargs
+        polynomial_function,
+        input_registers,
+        output_wires: WiresLike,
+        mod=None,
+        work_wires: WiresLike = (),
+        **kwargs,
     ):  # pylint: disable=unused-argument, arguments-differ
         r"""Representation of the operator as a product of other operators (static method).
 
@@ -400,8 +404,8 @@ class OutPoly(Operation):
         """
         registers_wires = [*input_registers, output_wires]
 
-        if not work_wires:
-            work_wires = [None, None]
+        if len(work_wires) == 0:
+            work_wires = [(), ()]
 
         list_ops = []
 
diff --git a/pennylane/templates/subroutines/phase_adder.py b/pennylane/templates/subroutines/phase_adder.py
index 47c2ca4c7..8dc8ae32e 100644
--- a/pennylane/templates/subroutines/phase_adder.py
+++ b/pennylane/templates/subroutines/phase_adder.py
@@ -19,9 +19,10 @@ import numpy as np
 
 import pennylane as qml
 from pennylane.operation import Operation
+from pennylane.wires import WiresLike
 
 
-def _add_k_fourier(k, wires):
+def _add_k_fourier(k, wires: WiresLike):
     """Adds k in the Fourier basis"""
     op_list = []
     for j, wire in enumerate(wires):
@@ -64,7 +65,7 @@ class PhaseAdder(Operation):
             value for `mod`.
         mod (int): the modulo for performing the addition. If not provided, it will be set to its maximum value, :math:`2^{\text{len(x_wires)}}`.
         work_wire (Sequence[int] or int): the auxiliary wire to use for the addition. Optional
-            when `mod` is :math:`2^{len(x\_wires)}`. Defaults to ``None``.
+            when `mod` is :math:`2^{len(x\_wires)}`. Defaults to empty set.
 
     **Example**
 
@@ -112,7 +113,7 @@ class PhaseAdder(Operation):
 
         The second set of wires is ``work_wire`` which consist of the auxiliary qubit used to perform the modular phase addition operation.
 
-        - If :math:`mod = 2^{\text{len(x_wires)}}`, there will be no need for ``work_wire``, hence ``work_wire=None``. This is the case by default.
+        - If :math:`mod = 2^{\text{len(x_wires)}}`, there will be no need for ``work_wire``, hence ``work_wire=()``. This is the case by default.
 
         - If :math:`mod \neq 2^{\text{len(x_wires)}}`, one ``work_wire`` has to be provided.
 
@@ -123,13 +124,14 @@ class PhaseAdder(Operation):
     grad_method = None
 
     def __init__(
-        self, k, x_wires, mod=None, work_wire=None, id=None
+        self, k, x_wires: WiresLike, mod=None, work_wire: WiresLike = (), id=None
     ):  # pylint: disable=too-many-arguments
 
-        work_wire = qml.wires.Wires(work_wire) if work_wire is not None else work_wire
+        work_wire = work_wire or ()
+        work_wire = qml.wires.Wires(work_wire)
         x_wires = qml.wires.Wires(x_wires)
 
-        num_work_wires = 0 if work_wire is None else len(work_wire)
+        num_work_wires = len(work_wire)
 
         if not qml.math.is_abstract(mod):
             if mod is None:
@@ -145,7 +147,7 @@ class PhaseAdder(Operation):
                     "PhaseAdder must have enough x_wires to represent mod. The maximum mod "
                     f"with len(x_wires)={len(x_wires)} is {2 ** len(x_wires)}, but received {mod}."
                 )
-            if work_wire is not None:
+            if num_work_wires != 0:
                 if any(wire in work_wire for wire in x_wires):
                     raise ValueError(
                         "None of the wires in work_wire should be included in x_wires."
@@ -178,11 +180,7 @@ class PhaseAdder(Operation):
 
     def map_wires(self, wire_map: dict):
         new_dict = {
-            key: (
-                [wire_map.get(w, w) for w in self.hyperparameters[key]]
-                if self.hyperparameters[key][0] is not None
-                else None
-            )
+            key: ([wire_map.get(w, w) for w in self.hyperparameters[key]])
             for key in ["x_wires", "work_wire"]
         }
 
@@ -201,7 +199,9 @@ class PhaseAdder(Operation):
         return cls._primitive.bind(*args, **kwargs)
 
     @staticmethod
-    def compute_decomposition(k, x_wires, mod, work_wire):  # pylint: disable=arguments-differ
+    def compute_decomposition(
+        k, x_wires: WiresLike, mod, work_wire: WiresLike
+    ):  # pylint: disable=arguments-differ
         r"""Representation of the operator as a product of other operators.
 
         Args:
@@ -212,13 +212,13 @@ class PhaseAdder(Operation):
                 value for `mod`.
             mod (int): the modulo for performing the addition. If not provided, it will be set to its maximum value, :math:`2^{\text{len(x_wires)}}`.
             work_wire (Sequence[int]): the auxiliary wire to use for the addition. Optional
-                when `mod` is :math:`2^{len(x\_wires)}`. Defaults to ``None``.
+                when `mod` is :math:`2^{len(x\_wires)}`.
         Returns:
             list[.Operator]: Decomposition of the operator
 
         **Example**
 
-        >>> qml.PhaseAdder.compute_decomposition(k = 2, x_wires = [0, 1, 2], mod = 8, work_wire = None)
+        >>> qml.PhaseAdder.compute_decomposition(k = 2, x_wires = [0, 1, 2], mod = 8, work_wire = ())
         [PhaseShift(6.283185307179586, wires=[1]),
         PhaseShift(3.141592653589793, wires=[2]),
         PhaseShift(1.5707963267948966, wires=[3])]
diff --git a/pennylane/templates/subroutines/qrom.py b/pennylane/templates/subroutines/qrom.py
index 7816cbf0e..700cae206 100644
--- a/pennylane/templates/subroutines/qrom.py
+++ b/pennylane/templates/subroutines/qrom.py
@@ -21,6 +21,7 @@ import numpy as np
 
 import pennylane as qml
 from pennylane.operation import Operation
+from pennylane.wires import WiresLike
 
 
 def _multi_swap(wires1, wires2):
@@ -104,13 +105,20 @@ class QROM(Operation):
     """
 
     def __init__(
-        self, bitstrings, control_wires, target_wires, work_wires, clean=True, id=None
+        self,
+        bitstrings,
+        control_wires: WiresLike,
+        target_wires: WiresLike,
+        work_wires: WiresLike,
+        clean=True,
+        id=None,
     ):  # pylint: disable=too-many-arguments
 
         control_wires = qml.wires.Wires(control_wires)
         target_wires = qml.wires.Wires(target_wires)
 
-        work_wires = qml.wires.Wires(work_wires) if work_wires else qml.wires.Wires([])
+        work_wires = work_wires or ()
+        work_wires = qml.wires.Wires(work_wires)
 
         self.hyperparameters["bitstrings"] = tuple(bitstrings)
         self.hyperparameters["control_wires"] = control_wires
@@ -118,7 +126,7 @@ class QROM(Operation):
         self.hyperparameters["work_wires"] = work_wires
         self.hyperparameters["clean"] = clean
 
-        if work_wires:
+        if len(work_wires) != 0:
             if any(wire in work_wires for wire in control_wires):
                 raise ValueError("Control wires should be different from work wires.")
 
diff --git a/pennylane/wires.py b/pennylane/wires.py
index e91a90977..3a1cad3f5 100644
--- a/pennylane/wires.py
+++ b/pennylane/wires.py
@@ -129,6 +129,8 @@ class Wires(Sequence):
         return cls(data, _override=True)
 
     def __init__(self, wires, _override=False):
+        if wires is None:
+            raise TypeError("Must specify a set of wires. None is not a valid wire label.")
         if _override:
             self._labels = wires
         else:


Test patch:
diff --git a/tests/data/attributes/operator/test__wires.py b/tests/data/attributes/operator/test__wires.py
index 8c9aebc9b..4a62340c3 100644
--- a/tests/data/attributes/operator/test__wires.py
+++ b/tests/data/attributes/operator/test__wires.py
@@ -28,6 +28,7 @@ pytestmark = pytest.mark.data
 
 
 class TestWiresToJson:
+
     @pytest.mark.parametrize(
         "in_, out",
         [
@@ -38,7 +39,6 @@ class TestWiresToJson:
             (["a", "b"], '["a", "b"]'),
             ([0, 1, None], "[0, 1, null]"),
             (["a", 1, None], '["a", 1, null]'),
-            (None, "[null]"),
             (1, "[1]"),
             ("a", '["a"]'),
             (np.int64(1), "[1]"),
diff --git a/tests/test_wires.py b/tests/test_wires.py
index 0f4f4c17e..3ae00ad6b 100644
--- a/tests/test_wires.py
+++ b/tests/test_wires.py
@@ -34,6 +34,11 @@ else:
 class TestWires:
     """Tests for the ``Wires`` class."""
 
+    def test_error_if_wires_none(self):
+        """Tests that a TypeError is raised if None is given as wires."""
+        with pytest.raises(TypeError, match="Must specify a set of wires."):
+            Wires(None)
+
     @pytest.mark.parametrize("iterable", [np.array([0, 1, 2]), [0, 1, 2], (0, 1, 2), range(3)])
     def test_creation_from_common_iterables(self, iterable):
         """Tests that a Wires object can be created from standard iterable inputs."""