We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
BUG np.broadcast_arrays does not work on void arrays with object fields
In the process of working on #4622, it was realised that `np.broadcas_arrays` do not work for void arrays with object fields, because in the process of changing new strides and shapes in `as_strided`, the `dtype` gets lost, and this cannot just be reset when object fields are present. While obviously this is somewhat of a corner case, it might still be good to see if it can be fixed easily, perhaps by doing something that preserves the dtype, or by bypassing the test for object fields.

```
import numpy as np
dt = np.dtype([('x', 'i8'), ('y', '?'), ('z', 'O')])
b = np.array([(1, True, None), (2, False, [3, 4, 5])], dtype=dt)
c = np.array([[-1], [-2]])
b_strided, c_strided = np.broadcast_arrays(b, c)
TypeError                                 Traceback (most recent call last)
...
/usr/lib/python3/dist-packages/numpy/lib/stride_tricks.py in as_strided(x, shape, strides)
     31     # Make sure dtype is correct in case of custom dtype
     32     if array.dtype.kind == 'V':
---> 33         array.dtype = x.dtype
     34     return array
     35 

TypeError: Cannot change data-type for object array.
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `numpy/lib/stride_tricks.py`
Content:
```
1 """
2 Utilities that manipulate strides to achieve desirable effects.
3 
4 An explanation of strides can be found in the "ndarray.rst" file in the
5 NumPy reference guide.
6 
7 """
8 from __future__ import division, absolute_import, print_function
9 
10 import numpy as np
11 
12 __all__ = ['broadcast_to', 'broadcast_arrays']
13 
14 
15 class DummyArray(object):
16     """Dummy object that just exists to hang __array_interface__ dictionaries
17     and possibly keep alive a reference to a base array.
18     """
19 
20     def __init__(self, interface, base=None):
21         self.__array_interface__ = interface
22         self.base = base
23 
24 
25 def _maybe_view_as_subclass(original_array, new_array):
26     if type(original_array) is not type(new_array):
27         # if input was an ndarray subclass and subclasses were OK,
28         # then view the result as that subclass.
29         new_array = new_array.view(type=type(original_array))
30         # Since we have done something akin to a view from original_array, we
31         # should let the subclass finalize (if it has it implemented, i.e., is
32         # not None).
33         if new_array.__array_finalize__:
34             new_array.__array_finalize__(original_array)
35     return new_array
36 
37 
38 def as_strided(x, shape=None, strides=None, subok=False):
39     """ Make an ndarray from the given array with the given shape and strides.
40     """
41     # first convert input to array, possibly keeping subclass
42     x = np.array(x, copy=False, subok=subok)
43     interface = dict(x.__array_interface__)
44     if shape is not None:
45         interface['shape'] = tuple(shape)
46     if strides is not None:
47         interface['strides'] = tuple(strides)
48     array = np.asarray(DummyArray(interface, base=x))
49     # Make sure dtype is correct in case of custom dtype
50     if array.dtype.kind == 'V':
51         array.dtype = x.dtype
52     return _maybe_view_as_subclass(x, array)
53 
54 
55 def _broadcast_to(array, shape, subok, readonly):
56     shape = tuple(shape) if np.iterable(shape) else (shape,)
57     array = np.array(array, copy=False, subok=subok)
58     if not shape and array.shape:
59         raise ValueError('cannot broadcast a non-scalar to a scalar array')
60     if any(size < 0 for size in shape):
61         raise ValueError('all elements of broadcast shape must be non-'
62                          'negative')
63     broadcast = np.nditer(
64         (array,), flags=['multi_index', 'refs_ok', 'zerosize_ok'],
65         op_flags=['readonly'], itershape=shape, order='C').itviews[0]
66     result = _maybe_view_as_subclass(array, broadcast)
67     if not readonly and array.flags.writeable:
68         result.flags.writeable = True
69     return result
70 
71 
72 def broadcast_to(array, shape, subok=False):
73     """Broadcast an array to a new shape.
74 
75     Parameters
76     ----------
77     array : array_like
78         The array to broadcast.
79     shape : tuple
80         The shape of the desired array.
81     subok : bool, optional
82         If True, then sub-classes will be passed-through, otherwise
83         the returned array will be forced to be a base-class array (default).
84 
85     Returns
86     -------
87     broadcast : array
88         A readonly view on the original array with the given shape. It is
89         typically not contiguous. Furthermore, more than one element of a
90         broadcasted array may refer to a single memory location.
91 
92     Raises
93     ------
94     ValueError
95         If the array is not compatible with the new shape according to NumPy's
96         broadcasting rules.
97 
98     Examples
99     --------
100     >>> x = np.array([1, 2, 3])
101     >>> np.broadcast_to(x, (3, 3))
102     array([[1, 2, 3],
103            [1, 2, 3],
104            [1, 2, 3]])
105     """
106     return _broadcast_to(array, shape, subok=subok, readonly=True)
107 
108 
109 def _broadcast_shape(*args):
110     """Returns the shape of the ararys that would result from broadcasting the
111     supplied arrays against each other.
112     """
113     if not args:
114         raise ValueError('must provide at least one argument')
115     if len(args) == 1:
116         # a single argument does not work with np.broadcast
117         return np.asarray(args[0]).shape
118     # use the old-iterator because np.nditer does not handle size 0 arrays
119     # consistently
120     b = np.broadcast(*args[:32])
121     # unfortunately, it cannot handle 32 or more arguments directly
122     for pos in range(32, len(args), 31):
123         b = np.broadcast(b, *args[pos:(pos + 31)])
124     return b.shape
125 
126 
127 def broadcast_arrays(*args, **kwargs):
128     """
129     Broadcast any number of arrays against each other.
130 
131     Parameters
132     ----------
133     `*args` : array_likes
134         The arrays to broadcast.
135 
136     subok : bool, optional
137         If True, then sub-classes will be passed-through, otherwise
138         the returned arrays will be forced to be a base-class array (default).
139 
140     Returns
141     -------
142     broadcasted : list of arrays
143         These arrays are views on the original arrays.  They are typically
144         not contiguous.  Furthermore, more than one element of a
145         broadcasted array may refer to a single memory location.  If you
146         need to write to the arrays, make copies first.
147 
148     Examples
149     --------
150     >>> x = np.array([[1,2,3]])
151     >>> y = np.array([[1],[2],[3]])
152     >>> np.broadcast_arrays(x, y)
153     [array([[1, 2, 3],
154            [1, 2, 3],
155            [1, 2, 3]]), array([[1, 1, 1],
156            [2, 2, 2],
157            [3, 3, 3]])]
158 
159     Here is a useful idiom for getting contiguous copies instead of
160     non-contiguous views.
161 
162     >>> [np.array(a) for a in np.broadcast_arrays(x, y)]
163     [array([[1, 2, 3],
164            [1, 2, 3],
165            [1, 2, 3]]), array([[1, 1, 1],
166            [2, 2, 2],
167            [3, 3, 3]])]
168 
169     """
170     # nditer is not used here to avoid the limit of 32 arrays.
171     # Otherwise, something like the following one-liner would suffice:
172     # return np.nditer(args, flags=['multi_index', 'zerosize_ok'],
173     #                  order='C').itviews
174 
175     subok = kwargs.pop('subok', False)
176     if kwargs:
177         raise TypeError('broadcast_arrays() got an unexpected keyword '
178                         'argument {}'.format(kwargs.pop()))
179     args = [np.array(_m, copy=False, subok=subok) for _m in args]
180 
181     shape = _broadcast_shape(*args)
182 
183     if all(array.shape == shape for array in args):
184         # Common case where nothing needs to be broadcasted.
185         return args
186 
187     # TODO: consider making the results of broadcast_arrays readonly to match
188     # broadcast_to. This will require a deprecation cycle.
189     return [_broadcast_to(array, shape, subok=subok, readonly=False)
190             for array in args]
191
```
--- 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/numpy/lib/stride_tricks.py b/numpy/lib/stride_tricks.py
--- a/numpy/lib/stride_tricks.py
+++ b/numpy/lib/stride_tricks.py
@@ -46,9 +46,11 @@
     if strides is not None:
         interface['strides'] = tuple(strides)
     array = np.asarray(DummyArray(interface, base=x))
-    # Make sure dtype is correct in case of custom dtype
-    if array.dtype.kind == 'V':
+
+    if array.dtype.fields is None and x.dtype.fields is not None:
+        # This should only happen if x.dtype is [('', 'Vx')]
         array.dtype = x.dtype
+
     return _maybe_view_as_subclass(x, array)

{"golden_diff": "diff --git a/numpy/lib/stride_tricks.py b/numpy/lib/stride_tricks.py\n--- a/numpy/lib/stride_tricks.py\n+++ b/numpy/lib/stride_tricks.py\n@@ -46,9 +46,11 @@\n     if strides is not None:\n         interface['strides'] = tuple(strides)\n     array = np.asarray(DummyArray(interface, base=x))\n-    # Make sure dtype is correct in case of custom dtype\n-    if array.dtype.kind == 'V':\n+\n+    if array.dtype.fields is None and x.dtype.fields is not None:\n+        # This should only happen if x.dtype is [('', 'Vx')]\n         array.dtype = x.dtype\n+\n     return _maybe_view_as_subclass(x, array)\n", "issue": "BUG np.broadcast_arrays does not work on void arrays with object fields\nIn the process of working on #4622, it was realised that `np.broadcas_arrays` do not work for void arrays with object fields, because in the process of changing new strides and shapes in `as_strided`, the `dtype` gets lost, and this cannot just be reset when object fields are present. While obviously this is somewhat of a corner case, it might still be good to see if it can be fixed easily, perhaps by doing something that preserves the dtype, or by bypassing the test for object fields.\n\n```\nimport numpy as np\ndt = np.dtype([('x', 'i8'), ('y', '?'), ('z', 'O')])\nb = np.array([(1, True, None), (2, False, [3, 4, 5])], dtype=dt)\nc = np.array([[-1], [-2]])\nb_strided, c_strided = np.broadcast_arrays(b, c)\nTypeError                                 Traceback (most recent call last)\n...\n/usr/lib/python3/dist-packages/numpy/lib/stride_tricks.py in as_strided(x, shape, strides)\n     31     # Make sure dtype is correct in case of custom dtype\n     32     if array.dtype.kind == 'V':\n---> 33         array.dtype = x.dtype\n     34     return array\n     35 \n\nTypeError: Cannot change data-type for object array.\n```\n\n", "before_files": [{"content": "\"\"\"\nUtilities that manipulate strides to achieve desirable effects.\n\nAn explanation of strides can be found in the \"ndarray.rst\" file in the\nNumPy reference guide.\n\n\"\"\"\nfrom __future__ import division, absolute_import, print_function\n\nimport numpy as np\n\n__all__ = ['broadcast_to', 'broadcast_arrays']\n\n\nclass DummyArray(object):\n    \"\"\"Dummy object that just exists to hang __array_interface__ dictionaries\n    and possibly keep alive a reference to a base array.\n    \"\"\"\n\n    def __init__(self, interface, base=None):\n        self.__array_interface__ = interface\n        self.base = base\n\n\ndef _maybe_view_as_subclass(original_array, new_array):\n    if type(original_array) is not type(new_array):\n        # if input was an ndarray subclass and subclasses were OK,\n        # then view the result as that subclass.\n        new_array = new_array.view(type=type(original_array))\n        # Since we have done something akin to a view from original_array, we\n        # should let the subclass finalize (if it has it implemented, i.e., is\n        # not None).\n        if new_array.__array_finalize__:\n            new_array.__array_finalize__(original_array)\n    return new_array\n\n\ndef as_strided(x, shape=None, strides=None, subok=False):\n    \"\"\" Make an ndarray from the given array with the given shape and strides.\n    \"\"\"\n    # first convert input to array, possibly keeping subclass\n    x = np.array(x, copy=False, subok=subok)\n    interface = dict(x.__array_interface__)\n    if shape is not None:\n        interface['shape'] = tuple(shape)\n    if strides is not None:\n        interface['strides'] = tuple(strides)\n    array = np.asarray(DummyArray(interface, base=x))\n    # Make sure dtype is correct in case of custom dtype\n    if array.dtype.kind == 'V':\n        array.dtype = x.dtype\n    return _maybe_view_as_subclass(x, array)\n\n\ndef _broadcast_to(array, shape, subok, readonly):\n    shape = tuple(shape) if np.iterable(shape) else (shape,)\n    array = np.array(array, copy=False, subok=subok)\n    if not shape and array.shape:\n        raise ValueError('cannot broadcast a non-scalar to a scalar array')\n    if any(size < 0 for size in shape):\n        raise ValueError('all elements of broadcast shape must be non-'\n                         'negative')\n    broadcast = np.nditer(\n        (array,), flags=['multi_index', 'refs_ok', 'zerosize_ok'],\n        op_flags=['readonly'], itershape=shape, order='C').itviews[0]\n    result = _maybe_view_as_subclass(array, broadcast)\n    if not readonly and array.flags.writeable:\n        result.flags.writeable = True\n    return result\n\n\ndef broadcast_to(array, shape, subok=False):\n    \"\"\"Broadcast an array to a new shape.\n\n    Parameters\n    ----------\n    array : array_like\n        The array to broadcast.\n    shape : tuple\n        The shape of the desired array.\n    subok : bool, optional\n        If True, then sub-classes will be passed-through, otherwise\n        the returned array will be forced to be a base-class array (default).\n\n    Returns\n    -------\n    broadcast : array\n        A readonly view on the original array with the given shape. It is\n        typically not contiguous. Furthermore, more than one element of a\n        broadcasted array may refer to a single memory location.\n\n    Raises\n    ------\n    ValueError\n        If the array is not compatible with the new shape according to NumPy's\n        broadcasting rules.\n\n    Examples\n    --------\n    >>> x = np.array([1, 2, 3])\n    >>> np.broadcast_to(x, (3, 3))\n    array([[1, 2, 3],\n           [1, 2, 3],\n           [1, 2, 3]])\n    \"\"\"\n    return _broadcast_to(array, shape, subok=subok, readonly=True)\n\n\ndef _broadcast_shape(*args):\n    \"\"\"Returns the shape of the ararys that would result from broadcasting the\n    supplied arrays against each other.\n    \"\"\"\n    if not args:\n        raise ValueError('must provide at least one argument')\n    if len(args) == 1:\n        # a single argument does not work with np.broadcast\n        return np.asarray(args[0]).shape\n    # use the old-iterator because np.nditer does not handle size 0 arrays\n    # consistently\n    b = np.broadcast(*args[:32])\n    # unfortunately, it cannot handle 32 or more arguments directly\n    for pos in range(32, len(args), 31):\n        b = np.broadcast(b, *args[pos:(pos + 31)])\n    return b.shape\n\n\ndef broadcast_arrays(*args, **kwargs):\n    \"\"\"\n    Broadcast any number of arrays against each other.\n\n    Parameters\n    ----------\n    `*args` : array_likes\n        The arrays to broadcast.\n\n    subok : bool, optional\n        If True, then sub-classes will be passed-through, otherwise\n        the returned arrays will be forced to be a base-class array (default).\n\n    Returns\n    -------\n    broadcasted : list of arrays\n        These arrays are views on the original arrays.  They are typically\n        not contiguous.  Furthermore, more than one element of a\n        broadcasted array may refer to a single memory location.  If you\n        need to write to the arrays, make copies first.\n\n    Examples\n    --------\n    >>> x = np.array([[1,2,3]])\n    >>> y = np.array([[1],[2],[3]])\n    >>> np.broadcast_arrays(x, y)\n    [array([[1, 2, 3],\n           [1, 2, 3],\n           [1, 2, 3]]), array([[1, 1, 1],\n           [2, 2, 2],\n           [3, 3, 3]])]\n\n    Here is a useful idiom for getting contiguous copies instead of\n    non-contiguous views.\n\n    >>> [np.array(a) for a in np.broadcast_arrays(x, y)]\n    [array([[1, 2, 3],\n           [1, 2, 3],\n           [1, 2, 3]]), array([[1, 1, 1],\n           [2, 2, 2],\n           [3, 3, 3]])]\n\n    \"\"\"\n    # nditer is not used here to avoid the limit of 32 arrays.\n    # Otherwise, something like the following one-liner would suffice:\n    # return np.nditer(args, flags=['multi_index', 'zerosize_ok'],\n    #                  order='C').itviews\n\n    subok = kwargs.pop('subok', False)\n    if kwargs:\n        raise TypeError('broadcast_arrays() got an unexpected keyword '\n                        'argument {}'.format(kwargs.pop()))\n    args = [np.array(_m, copy=False, subok=subok) for _m in args]\n\n    shape = _broadcast_shape(*args)\n\n    if all(array.shape == shape for array in args):\n        # Common case where nothing needs to be broadcasted.\n        return args\n\n    # TODO: consider making the results of broadcast_arrays readonly to match\n    # broadcast_to. This will require a deprecation cycle.\n    return [_broadcast_to(array, shape, subok=subok, readonly=False)\n            for array in args]\n", "path": "numpy/lib/stride_tricks.py"}], "after_files": [{"content": "\"\"\"\nUtilities that manipulate strides to achieve desirable effects.\n\nAn explanation of strides can be found in the \"ndarray.rst\" file in the\nNumPy reference guide.\n\n\"\"\"\nfrom __future__ import division, absolute_import, print_function\n\nimport numpy as np\n\n__all__ = ['broadcast_to', 'broadcast_arrays']\n\n\nclass DummyArray(object):\n    \"\"\"Dummy object that just exists to hang __array_interface__ dictionaries\n    and possibly keep alive a reference to a base array.\n    \"\"\"\n\n    def __init__(self, interface, base=None):\n        self.__array_interface__ = interface\n        self.base = base\n\n\ndef _maybe_view_as_subclass(original_array, new_array):\n    if type(original_array) is not type(new_array):\n        # if input was an ndarray subclass and subclasses were OK,\n        # then view the result as that subclass.\n        new_array = new_array.view(type=type(original_array))\n        # Since we have done something akin to a view from original_array, we\n        # should let the subclass finalize (if it has it implemented, i.e., is\n        # not None).\n        if new_array.__array_finalize__:\n            new_array.__array_finalize__(original_array)\n    return new_array\n\n\ndef as_strided(x, shape=None, strides=None, subok=False):\n    \"\"\" Make an ndarray from the given array with the given shape and strides.\n    \"\"\"\n    # first convert input to array, possibly keeping subclass\n    x = np.array(x, copy=False, subok=subok)\n    interface = dict(x.__array_interface__)\n    if shape is not None:\n        interface['shape'] = tuple(shape)\n    if strides is not None:\n        interface['strides'] = tuple(strides)\n    array = np.asarray(DummyArray(interface, base=x))\n\n    if array.dtype.fields is None and x.dtype.fields is not None:\n        # This should only happen if x.dtype is [('', 'Vx')]\n        array.dtype = x.dtype\n\n    return _maybe_view_as_subclass(x, array)\n\n\ndef _broadcast_to(array, shape, subok, readonly):\n    shape = tuple(shape) if np.iterable(shape) else (shape,)\n    array = np.array(array, copy=False, subok=subok)\n    if not shape and array.shape:\n        raise ValueError('cannot broadcast a non-scalar to a scalar array')\n    if any(size < 0 for size in shape):\n        raise ValueError('all elements of broadcast shape must be non-'\n                         'negative')\n    broadcast = np.nditer((array,), flags=['multi_index', 'zerosize_ok'],\n                          op_flags=['readonly'], itershape=shape, order='C'\n                          ).itviews[0]\n    result = _maybe_view_as_subclass(array, broadcast)\n    if not readonly and array.flags.writeable:\n        result.flags.writeable = True\n    return result\n\n\ndef broadcast_to(array, shape, subok=False):\n    \"\"\"Broadcast an array to a new shape.\n\n    Parameters\n    ----------\n    array : array_like\n        The array to broadcast.\n    shape : tuple\n        The shape of the desired array.\n    subok : bool, optional\n        If True, then sub-classes will be passed-through, otherwise\n        the returned array will be forced to be a base-class array (default).\n\n    Returns\n    -------\n    broadcast : array\n        A readonly view on the original array with the given shape. It is\n        typically not contiguous. Furthermore, more than one element of a\n        broadcasted array may refer to a single memory location.\n\n    Raises\n    ------\n    ValueError\n        If the array is not compatible with the new shape according to NumPy's\n        broadcasting rules.\n\n    Examples\n    --------\n    >>> x = np.array([1, 2, 3])\n    >>> np.broadcast_to(x, (3, 3))\n    array([[1, 2, 3],\n           [1, 2, 3],\n           [1, 2, 3]])\n    \"\"\"\n    return _broadcast_to(array, shape, subok=subok, readonly=True)\n\n\ndef _broadcast_shape(*args):\n    \"\"\"Returns the shape of the ararys that would result from broadcasting the\n    supplied arrays against each other.\n    \"\"\"\n    if not args:\n        raise ValueError('must provide at least one argument')\n    if len(args) == 1:\n        # a single argument does not work with np.broadcast\n        return np.asarray(args[0]).shape\n    # use the old-iterator because np.nditer does not handle size 0 arrays\n    # consistently\n    b = np.broadcast(*args[:32])\n    # unfortunately, it cannot handle 32 or more arguments directly\n    for pos in range(32, len(args), 31):\n        b = np.broadcast(b, *args[pos:(pos + 31)])\n    return b.shape\n\n\ndef broadcast_arrays(*args, **kwargs):\n    \"\"\"\n    Broadcast any number of arrays against each other.\n\n    Parameters\n    ----------\n    `*args` : array_likes\n        The arrays to broadcast.\n\n    subok : bool, optional\n        If True, then sub-classes will be passed-through, otherwise\n        the returned arrays will be forced to be a base-class array (default).\n\n    Returns\n    -------\n    broadcasted : list of arrays\n        These arrays are views on the original arrays.  They are typically\n        not contiguous.  Furthermore, more than one element of a\n        broadcasted array may refer to a single memory location.  If you\n        need to write to the arrays, make copies first.\n\n    Examples\n    --------\n    >>> x = np.array([[1,2,3]])\n    >>> y = np.array([[1],[2],[3]])\n    >>> np.broadcast_arrays(x, y)\n    [array([[1, 2, 3],\n           [1, 2, 3],\n           [1, 2, 3]]), array([[1, 1, 1],\n           [2, 2, 2],\n           [3, 3, 3]])]\n\n    Here is a useful idiom for getting contiguous copies instead of\n    non-contiguous views.\n\n    >>> [np.array(a) for a in np.broadcast_arrays(x, y)]\n    [array([[1, 2, 3],\n           [1, 2, 3],\n           [1, 2, 3]]), array([[1, 1, 1],\n           [2, 2, 2],\n           [3, 3, 3]])]\n\n    \"\"\"\n    # nditer is not used here to avoid the limit of 32 arrays.\n    # Otherwise, something like the following one-liner would suffice:\n    # return np.nditer(args, flags=['multi_index', 'zerosize_ok'],\n    #                  order='C').itviews\n\n    subok = kwargs.pop('subok', False)\n    if kwargs:\n        raise TypeError('broadcast_arrays() got an unexpected keyword '\n                        'argument {}'.format(kwargs.pop()))\n    args = [np.array(_m, copy=False, subok=subok) for _m in args]\n\n    shape = _broadcast_shape(*args)\n\n    if all(array.shape == shape for array in args):\n        # Common case where nothing needs to be broadcasted.\n        return args\n\n    # TODO: consider making the results of broadcast_arrays readonly to match\n    # broadcast_to. This will require a deprecation cycle.\n    return [_broadcast_to(array, shape, subok=subok, readonly=False)\n            for array in args]\n", "path": "numpy/lib/stride_tricks.py"}]}