We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`fill_none` doesn't move through indexed types
### Version of Awkward Array

main

### Description and code to reproduce

The failure mode here is where we have a lazy carryd `RecordArray`, which then contains an option. Our existing logic returns early if it doesn't see an option, union, or record.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/awkward/operations/ak_fill_none.py`
Content:
```
1 # BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE
2 
3 import numbers
4 
5 import awkward as ak
6 
7 np = ak._nplikes.NumpyMetadata.instance()
8 cpu = ak._backends.NumpyBackend.instance()
9 
10 
11 def fill_none(array, value, axis=-1, *, highlevel=True, behavior=None):
12     """
13     Args:
14         array: Array-like data (anything #ak.to_layout recognizes).
15         value: Data with which to replace None.
16         axis (None or int): If None, replace all None values in the array
17             with the given value; if an int, The dimension at which this
18             operation is applied. The outermost dimension is `0`, followed
19             by `1`, etc., and negative values count backward from the
20             innermost: `-1` is the innermost  dimension, `-2` is the next
21             level up, etc.
22         highlevel (bool): If True, return an #ak.Array; otherwise, return
23             a low-level #ak.contents.Content subclass.
24         behavior (None or dict): Custom #ak.behavior for the output array, if
25             high-level.
26 
27     Replaces missing values (None) with a given `value`.
28 
29     For example, in the following
30 
31         >>> array = ak.Array([[1.1, None, 2.2], [], [None, 3.3, 4.4]])
32 
33     The None values could be replaced with `0` by
34 
35         >>> ak.fill_none(array, 0)
36         <Array [[1.1, 0, 2.2], [], [0, 3.3, 4.4]] type='3 * var * float64'>
37 
38     The replacement value doesn't strictly need the same type as the
39     surrounding data. For example, the None values could also be replaced
40     by a string.
41 
42         >>> ak.fill_none(array, "hi")
43         <Array [[1.1, 'hi', 2.2], [], ['hi', ...]] type='3 * var * union[float64, s...'>
44 
45     The list content now has a union type:
46 
47         >>> ak.fill_none(array, "hi").type.show()
48         3 * var * union[
49             float64,
50             string
51         ]
52 
53     The values could be floating-point numbers or strings.
54     """
55     with ak._errors.OperationErrorContext(
56         "ak.fill_none",
57         dict(
58             array=array, value=value, axis=axis, highlevel=highlevel, behavior=behavior
59         ),
60     ):
61         return _impl(array, value, axis, highlevel, behavior)
62 
63 
64 def _impl(array, value, axis, highlevel, behavior):
65     arraylayout = ak.operations.to_layout(array, allow_record=True, allow_other=False)
66     behavior = ak._util.behavior_of(array, value, behavior=behavior)
67     backend = ak._backends.backend_of(arraylayout, default=cpu)
68 
69     # Convert value type to appropriate layout
70     if (
71         isinstance(value, np.ndarray)
72         and issubclass(value.dtype.type, (np.bool_, np.number))
73         and len(value.shape) != 0
74     ):
75         valuelayout = ak.operations.to_layout(
76             backend.nplike.asarray(value)[np.newaxis],
77             allow_record=False,
78             allow_other=False,
79         )
80     elif isinstance(value, (bool, numbers.Number, np.bool_, np.number)) or (
81         isinstance(value, np.ndarray)
82         and issubclass(value.dtype.type, (np.bool_, np.number))
83     ):
84         valuelayout = ak.operations.to_layout(
85             backend.nplike.asarray(value), allow_record=False, allow_other=False
86         )
87     elif (
88         ak._util.is_sized_iterable(value)
89         and not (isinstance(value, (str, bytes)))
90         or isinstance(value, (ak.highlevel.Record, ak.record.Record))
91     ):
92         valuelayout = ak.operations.to_layout(
93             value, allow_record=True, allow_other=False
94         )
95         if isinstance(valuelayout, ak.record.Record):
96             valuelayout = valuelayout.array[valuelayout.at : valuelayout.at + 1]
97         elif len(valuelayout) == 0:
98             offsets = ak.index.Index64(
99                 backend.index_nplike.array([0, 0], dtype=np.int64)
100             )
101             valuelayout = ak.contents.ListOffsetArray(offsets, valuelayout)
102         else:
103             valuelayout = ak.contents.RegularArray(valuelayout, len(valuelayout), 1)
104     else:
105         valuelayout = ak.operations.to_layout(
106             [value], allow_record=False, allow_other=False
107         )
108 
109     if axis is None:
110 
111         def action(layout, continuation, **kwargs):
112             if layout.is_option:
113                 return ak._do.fill_none(continuation(), valuelayout)
114 
115     else:
116 
117         def action(layout, depth, **kwargs):
118             posaxis = ak._util.maybe_posaxis(layout, axis, depth)
119             if posaxis is not None and posaxis + 1 == depth:
120                 if layout.is_union or layout.is_record:
121                     return None
122                 elif layout.is_option:
123                     return ak._do.fill_none(layout, valuelayout)
124                 else:
125                     return layout
126 
127             elif layout.is_leaf:
128                 raise ak._errors.wrap_error(
129                     np.AxisError(
130                         f"axis={axis} exceeds the depth of this array ({depth})"
131                     )
132                 )
133 
134     out = ak._do.recursively_apply(arraylayout, action, behavior)
135     return ak._util.wrap(out, behavior, highlevel)
136
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/awkward/operations/ak_fill_none.py b/src/awkward/operations/ak_fill_none.py
--- a/src/awkward/operations/ak_fill_none.py
+++ b/src/awkward/operations/ak_fill_none.py
@@ -117,10 +117,10 @@
         def action(layout, depth, **kwargs):
             posaxis = ak._util.maybe_posaxis(layout, axis, depth)
             if posaxis is not None and posaxis + 1 == depth:
-                if layout.is_union or layout.is_record:
-                    return None
-                elif layout.is_option:
+                if layout.is_option:
                     return ak._do.fill_none(layout, valuelayout)
+                elif layout.is_union or layout.is_record or layout.is_indexed:
+                    return None
                 else:
                     return layout

{"golden_diff": "diff --git a/src/awkward/operations/ak_fill_none.py b/src/awkward/operations/ak_fill_none.py\n--- a/src/awkward/operations/ak_fill_none.py\n+++ b/src/awkward/operations/ak_fill_none.py\n@@ -117,10 +117,10 @@\n         def action(layout, depth, **kwargs):\n             posaxis = ak._util.maybe_posaxis(layout, axis, depth)\n             if posaxis is not None and posaxis + 1 == depth:\n-                if layout.is_union or layout.is_record:\n-                    return None\n-                elif layout.is_option:\n+                if layout.is_option:\n                     return ak._do.fill_none(layout, valuelayout)\n+                elif layout.is_union or layout.is_record or layout.is_indexed:\n+                    return None\n                 else:\n                     return layout\n", "issue": "`fill_none` doesn't move through indexed types\n### Version of Awkward Array\n\nmain\n\n### Description and code to reproduce\n\nThe failure mode here is where we have a lazy carryd `RecordArray`, which then contains an option. Our existing logic returns early if it doesn't see an option, union, or record.\n", "before_files": [{"content": "# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE\n\nimport numbers\n\nimport awkward as ak\n\nnp = ak._nplikes.NumpyMetadata.instance()\ncpu = ak._backends.NumpyBackend.instance()\n\n\ndef fill_none(array, value, axis=-1, *, highlevel=True, behavior=None):\n    \"\"\"\n    Args:\n        array: Array-like data (anything #ak.to_layout recognizes).\n        value: Data with which to replace None.\n        axis (None or int): If None, replace all None values in the array\n            with the given value; if an int, The dimension at which this\n            operation is applied. The outermost dimension is `0`, followed\n            by `1`, etc., and negative values count backward from the\n            innermost: `-1` is the innermost  dimension, `-2` is the next\n            level up, etc.\n        highlevel (bool): If True, return an #ak.Array; otherwise, return\n            a low-level #ak.contents.Content subclass.\n        behavior (None or dict): Custom #ak.behavior for the output array, if\n            high-level.\n\n    Replaces missing values (None) with a given `value`.\n\n    For example, in the following\n\n        >>> array = ak.Array([[1.1, None, 2.2], [], [None, 3.3, 4.4]])\n\n    The None values could be replaced with `0` by\n\n        >>> ak.fill_none(array, 0)\n        <Array [[1.1, 0, 2.2], [], [0, 3.3, 4.4]] type='3 * var * float64'>\n\n    The replacement value doesn't strictly need the same type as the\n    surrounding data. For example, the None values could also be replaced\n    by a string.\n\n        >>> ak.fill_none(array, \"hi\")\n        <Array [[1.1, 'hi', 2.2], [], ['hi', ...]] type='3 * var * union[float64, s...'>\n\n    The list content now has a union type:\n\n        >>> ak.fill_none(array, \"hi\").type.show()\n        3 * var * union[\n            float64,\n            string\n        ]\n\n    The values could be floating-point numbers or strings.\n    \"\"\"\n    with ak._errors.OperationErrorContext(\n        \"ak.fill_none\",\n        dict(\n            array=array, value=value, axis=axis, highlevel=highlevel, behavior=behavior\n        ),\n    ):\n        return _impl(array, value, axis, highlevel, behavior)\n\n\ndef _impl(array, value, axis, highlevel, behavior):\n    arraylayout = ak.operations.to_layout(array, allow_record=True, allow_other=False)\n    behavior = ak._util.behavior_of(array, value, behavior=behavior)\n    backend = ak._backends.backend_of(arraylayout, default=cpu)\n\n    # Convert value type to appropriate layout\n    if (\n        isinstance(value, np.ndarray)\n        and issubclass(value.dtype.type, (np.bool_, np.number))\n        and len(value.shape) != 0\n    ):\n        valuelayout = ak.operations.to_layout(\n            backend.nplike.asarray(value)[np.newaxis],\n            allow_record=False,\n            allow_other=False,\n        )\n    elif isinstance(value, (bool, numbers.Number, np.bool_, np.number)) or (\n        isinstance(value, np.ndarray)\n        and issubclass(value.dtype.type, (np.bool_, np.number))\n    ):\n        valuelayout = ak.operations.to_layout(\n            backend.nplike.asarray(value), allow_record=False, allow_other=False\n        )\n    elif (\n        ak._util.is_sized_iterable(value)\n        and not (isinstance(value, (str, bytes)))\n        or isinstance(value, (ak.highlevel.Record, ak.record.Record))\n    ):\n        valuelayout = ak.operations.to_layout(\n            value, allow_record=True, allow_other=False\n        )\n        if isinstance(valuelayout, ak.record.Record):\n            valuelayout = valuelayout.array[valuelayout.at : valuelayout.at + 1]\n        elif len(valuelayout) == 0:\n            offsets = ak.index.Index64(\n                backend.index_nplike.array([0, 0], dtype=np.int64)\n            )\n            valuelayout = ak.contents.ListOffsetArray(offsets, valuelayout)\n        else:\n            valuelayout = ak.contents.RegularArray(valuelayout, len(valuelayout), 1)\n    else:\n        valuelayout = ak.operations.to_layout(\n            [value], allow_record=False, allow_other=False\n        )\n\n    if axis is None:\n\n        def action(layout, continuation, **kwargs):\n            if layout.is_option:\n                return ak._do.fill_none(continuation(), valuelayout)\n\n    else:\n\n        def action(layout, depth, **kwargs):\n            posaxis = ak._util.maybe_posaxis(layout, axis, depth)\n            if posaxis is not None and posaxis + 1 == depth:\n                if layout.is_union or layout.is_record:\n                    return None\n                elif layout.is_option:\n                    return ak._do.fill_none(layout, valuelayout)\n                else:\n                    return layout\n\n            elif layout.is_leaf:\n                raise ak._errors.wrap_error(\n                    np.AxisError(\n                        f\"axis={axis} exceeds the depth of this array ({depth})\"\n                    )\n                )\n\n    out = ak._do.recursively_apply(arraylayout, action, behavior)\n    return ak._util.wrap(out, behavior, highlevel)\n", "path": "src/awkward/operations/ak_fill_none.py"}], "after_files": [{"content": "# BSD 3-Clause License; see https://github.com/scikit-hep/awkward-1.0/blob/main/LICENSE\n\nimport numbers\n\nimport awkward as ak\n\nnp = ak._nplikes.NumpyMetadata.instance()\ncpu = ak._backends.NumpyBackend.instance()\n\n\ndef fill_none(array, value, axis=-1, *, highlevel=True, behavior=None):\n    \"\"\"\n    Args:\n        array: Array-like data (anything #ak.to_layout recognizes).\n        value: Data with which to replace None.\n        axis (None or int): If None, replace all None values in the array\n            with the given value; if an int, The dimension at which this\n            operation is applied. The outermost dimension is `0`, followed\n            by `1`, etc., and negative values count backward from the\n            innermost: `-1` is the innermost  dimension, `-2` is the next\n            level up, etc.\n        highlevel (bool): If True, return an #ak.Array; otherwise, return\n            a low-level #ak.contents.Content subclass.\n        behavior (None or dict): Custom #ak.behavior for the output array, if\n            high-level.\n\n    Replaces missing values (None) with a given `value`.\n\n    For example, in the following\n\n        >>> array = ak.Array([[1.1, None, 2.2], [], [None, 3.3, 4.4]])\n\n    The None values could be replaced with `0` by\n\n        >>> ak.fill_none(array, 0)\n        <Array [[1.1, 0, 2.2], [], [0, 3.3, 4.4]] type='3 * var * float64'>\n\n    The replacement value doesn't strictly need the same type as the\n    surrounding data. For example, the None values could also be replaced\n    by a string.\n\n        >>> ak.fill_none(array, \"hi\")\n        <Array [[1.1, 'hi', 2.2], [], ['hi', ...]] type='3 * var * union[float64, s...'>\n\n    The list content now has a union type:\n\n        >>> ak.fill_none(array, \"hi\").type.show()\n        3 * var * union[\n            float64,\n            string\n        ]\n\n    The values could be floating-point numbers or strings.\n    \"\"\"\n    with ak._errors.OperationErrorContext(\n        \"ak.fill_none\",\n        dict(\n            array=array, value=value, axis=axis, highlevel=highlevel, behavior=behavior\n        ),\n    ):\n        return _impl(array, value, axis, highlevel, behavior)\n\n\ndef _impl(array, value, axis, highlevel, behavior):\n    arraylayout = ak.operations.to_layout(array, allow_record=True, allow_other=False)\n    behavior = ak._util.behavior_of(array, value, behavior=behavior)\n    backend = ak._backends.backend_of(arraylayout, default=cpu)\n\n    # Convert value type to appropriate layout\n    if (\n        isinstance(value, np.ndarray)\n        and issubclass(value.dtype.type, (np.bool_, np.number))\n        and len(value.shape) != 0\n    ):\n        valuelayout = ak.operations.to_layout(\n            backend.nplike.asarray(value)[np.newaxis],\n            allow_record=False,\n            allow_other=False,\n        )\n    elif isinstance(value, (bool, numbers.Number, np.bool_, np.number)) or (\n        isinstance(value, np.ndarray)\n        and issubclass(value.dtype.type, (np.bool_, np.number))\n    ):\n        valuelayout = ak.operations.to_layout(\n            backend.nplike.asarray(value), allow_record=False, allow_other=False\n        )\n    elif (\n        ak._util.is_sized_iterable(value)\n        and not (isinstance(value, (str, bytes)))\n        or isinstance(value, (ak.highlevel.Record, ak.record.Record))\n    ):\n        valuelayout = ak.operations.to_layout(\n            value, allow_record=True, allow_other=False\n        )\n        if isinstance(valuelayout, ak.record.Record):\n            valuelayout = valuelayout.array[valuelayout.at : valuelayout.at + 1]\n        elif len(valuelayout) == 0:\n            offsets = ak.index.Index64(\n                backend.index_nplike.array([0, 0], dtype=np.int64)\n            )\n            valuelayout = ak.contents.ListOffsetArray(offsets, valuelayout)\n        else:\n            valuelayout = ak.contents.RegularArray(valuelayout, len(valuelayout), 1)\n    else:\n        valuelayout = ak.operations.to_layout(\n            [value], allow_record=False, allow_other=False\n        )\n\n    if axis is None:\n\n        def action(layout, continuation, **kwargs):\n            if layout.is_option:\n                return ak._do.fill_none(continuation(), valuelayout)\n\n    else:\n\n        def action(layout, depth, **kwargs):\n            posaxis = ak._util.maybe_posaxis(layout, axis, depth)\n            if posaxis is not None and posaxis + 1 == depth:\n                if layout.is_option:\n                    return ak._do.fill_none(layout, valuelayout)\n                elif layout.is_union or layout.is_record or layout.is_indexed:\n                    return None\n                else:\n                    return layout\n\n            elif layout.is_leaf:\n                raise ak._errors.wrap_error(\n                    np.AxisError(\n                        f\"axis={axis} exceeds the depth of this array ({depth})\"\n                    )\n                )\n\n    out = ak._do.recursively_apply(arraylayout, action, behavior)\n    return ak._util.wrap(out, behavior, highlevel)\n", "path": "src/awkward/operations/ak_fill_none.py"}]}