Repository: scikit-hep/awkward

Issue:
`ByteMaskedArray.toByteMaskedArray()` refers to `ak.Index8`
### Version of Awkward Array

main

### Description and code to reproduce

See title!


Discussion:

Resolving patch:
diff --git a/src/awkward/_typetracer.py b/src/awkward/_typetracer.py
--- a/src/awkward/_typetracer.py
+++ b/src/awkward/_typetracer.py
@@ -92,7 +92,7 @@ def _emptyarray(x):
 
 class UnknownScalar:
     def __init__(self, dtype):
-        self._dtype = dtype
+        self._dtype = np.dtype(dtype)
 
     @property
     def dtype(self):
@@ -810,29 +810,45 @@ def bitwise_or(self, *args, **kwargs):
         # array1, array2[, out=output]
         raise ak._errors.wrap_error(NotImplementedError)
 
-    def logical_and(self, x, y):
-        # array1, array2
+    def logical_and(self, x, y, *, dtype=None):
+        if dtype is None:
+            dtype = np.bool_
+
         is_array = False
         if isinstance(x, TypeTracerArray):
             is_array = True
         if isinstance(y, TypeTracerArray):
             is_array = True
         if is_array:
-            return TypeTracerArray(np.dtype(np.bool_))
+            return TypeTracerArray(dtype)
         else:
-            return UnknownScalar(np.dtype(np.bool_))
+            return UnknownScalar(dtype)
+
+    def logical_or(self, x, y, *, dtype=None):
+        if dtype is None:
+            dtype = np.bool_
 
-    def logical_or(self, x, y):
-        # array1, array2[, out=]
         is_array = False
         if isinstance(x, TypeTracerArray):
             is_array = True
         if isinstance(y, TypeTracerArray):
             is_array = True
         if is_array:
-            return TypeTracerArray(np.dtype(np.bool_))
+            return TypeTracerArray(dtype)
+        else:
+            return UnknownScalar(dtype)
+
+    def logical_not(self, x, *, dtype=None):
+        if dtype is None:
+            dtype = np.bool_
+
+        is_array = False
+        if isinstance(x, TypeTracerArray):
+            is_array = True
+        if is_array:
+            return TypeTracerArray(dtype)
         else:
-            return UnknownScalar(np.dtype(np.bool_))
+            return UnknownScalar(dtype)
 
     def equal(self, *args, **kwargs):
         # array1, array2
diff --git a/src/awkward/contents/bytemaskedarray.py b/src/awkward/contents/bytemaskedarray.py
--- a/src/awkward/contents/bytemaskedarray.py
+++ b/src/awkward/contents/bytemaskedarray.py
@@ -194,7 +194,11 @@ def toByteMaskedArray(self, valid_when):
             return self
         else:
             return ByteMaskedArray(
-                ak.Index8(~self._mask.data),
+                ak.index.Index8(
+                    self._nplike.index_nplike.logical_not(
+                        self._mask.data.astype(np.bool_)
+                    ).astype(dtype=np.int8)
+                ),
                 self._content,
                 valid_when,
                 self._parameters,
diff --git a/src/awkward/nplikes.py b/src/awkward/nplikes.py
--- a/src/awkward/nplikes.py
+++ b/src/awkward/nplikes.py
@@ -254,6 +254,10 @@ def logical_and(self, *args, **kwargs):
         # array1, array2
         return self._module.logical_and(*args, **kwargs)
 
+    def logical_not(self, *args, **kwargs):
+        # array1, array2
+        return self._module.logical_not(*args, **kwargs)
+
     def sqrt(self, *args, **kwargs):
         # array
         return self._module.sqrt(*args, **kwargs)


Test patch:
diff --git a/tests/test_1850-bytemasked-array-to-bytemaskedarray.py b/tests/test_1850-bytemasked-array-to-bytemaskedarray.py
new file mode 100644
--- /dev/null
+++ b/tests/test_1850-bytemasked-array-to-bytemaskedarray.py
@@ -0,0 +1,21 @@
+# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
+
+import numpy as np  # noqa: F401
+import pytest  # noqa: F401
+
+import awkward as ak  # noqa: F401
+
+
+def test():
+    layout = ak.contents.ByteMaskedArray(
+        ak.index.Index8(np.array([0, 1, 0, 1, 0], dtype=np.int8)),
+        ak.contents.NumpyArray(np.arange(5)),
+        valid_when=True,
+    )
+    result = layout.toByteMaskedArray(False)
+    assert layout.to_list() == [None, 1, None, 3, None]
+    assert result.to_list() == [None, 1, None, 3, None]
+    assert layout.nplike.asarray(result.mask).tolist() == [1, 0, 1, 0, 1]
+
+    # Check this works
+    layout.typetracer.toByteMaskedArray(False)