We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`backprop_step` only partially documented
The `backprop_step` function in `chainer/_backprop_utils.py` is documented but misses an explanation for the `func` argument. https://github.com/chainer/chainer/blob/master/chainer/_backprop_utils.py#L73-L89

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `chainer/_backprop_utils.py`
Content:
```
1 import six
2 
3 import chainer
4 
5 
6 def _reduce(grad_list):
7     if not grad_list:
8         return None
9     if len(grad_list) >= 2:
10         grad_list[:] = [chainer.functions.add(*grad_list)]
11     return grad_list[0]
12 
13 
14 def _pure(grad):
15     return [] if grad is None else [grad]
16 
17 
18 def _pop_or_none(grad_list):
19     return grad_list.pop() if grad_list else None
20 
21 
22 class GradTable(object):
23 
24     """Dict of nodes to references of gradients
25 
26     The gradients are stored as references to them in the backprop process. The
27     current implementation uses lists. Keep the lengths of lists <= 1 for the
28     strict accumulation of gradients. Leave them to accumulate gradients
29     lazily.
30 
31     Args:
32         load_if_new (bool): read ``grad_var`` of node when the node has not
33             been added.
34 
35     """
36 
37     def __init__(self, load_if_new=False):
38         self.grads = {}
39         self._load_if_new = load_if_new
40 
41     def __setitem__(self, node, grad):
42         assert node is not None
43         self.grads[node] = _pure(grad)
44 
45     def get_as_list(self, node):
46         assert node is not None
47         grads = self.grads
48         if node not in grads:
49             if self._load_if_new and node.creator_node is None:
50                 node._check_old_style_gradient()
51                 # accumulate the gradient only if the node is a leaf
52                 grads[node] = _pure(node.grad_var)
53             else:
54                 grads[node] = []
55         return grads[node]
56 
57     def pop(self, node):
58         if node is None:
59             return None
60         grads = self.grads
61         if node in grads:
62             return _reduce(grads.pop(node))
63         if self._load_if_new:
64             return node.grad_var
65         else:
66             return None
67 
68     def assert_no_grads(self):
69         for gx in self.grads.values():
70             assert gx == []
71 
72 
73 def backprop_step(
74         func, target_input_indexes, grad_outputs, grad_inputs):
75     """Accumulates gradients of a FunctionNode
76 
77     This routine is used by :meth:`chainer.Variable.backward` and
78     :func:`chainer.grad`.
79 
80     Args:
81         target_input_indexes (tuple of int): Sorted indices of the input
82             variables w.r.t. which the gradients are required. It is
83             guaranteed that this tuple contains at least one element.
84         grad_outputs (tuple of Variable): Gradients w.r.t. the output
85             variables. If the gradient w.r.t. an output variable is not
86             given, the corresponding element is ``None``.
87         grad_inputs (dict): References of radients w.r.t. the input variables.
88 
89     """
90     is_debug = chainer.is_debug()
91     if is_debug:
92         assert isinstance(target_input_indexes, tuple)
93         assert target_input_indexes == tuple(sorted(target_input_indexes))
94         assert isinstance(grad_outputs, tuple)
95     if func.backward_accumulate.__code__ \
96             is not chainer.FunctionNode.backward_accumulate.__code__:
97         # backward_accumulate is overridden
98         grad_inputs_tuple = tuple([
99             _pop_or_none(grad_inputs[func.inputs[i]])
100             for i in target_input_indexes
101         ])
102         gxs = func.backward_accumulate(
103             target_input_indexes, grad_outputs, grad_inputs_tuple)
104     else:  # otherwise, backward should be overridden
105         gxs = func.backward(
106             target_input_indexes, grad_outputs)
107 
108         if is_debug:
109             for gx in gxs:
110                 if not (gx is None or isinstance(gx, chainer.Variable)):
111                     raise ValueError(func._get_error_message(
112                         'type of gradients returned from backward is '
113                         'incorrect: '
114                         '{} != expected {}'.format(
115                             type(gx), chainer.Variable)))
116 
117         len_gxs = len(gxs)
118         if len_gxs == len(func.inputs):
119             gxs = tuple([gxs[i] for i in target_input_indexes])
120         elif len_gxs != len(target_input_indexes):
121             msg = 'number of gradients returned from backward is incorrect: '
122             if len(func.inputs) == len(target_input_indexes):
123                 msg += (
124                     '%s != expected %s' % (len_gxs, len(func.inputs)))
125             else:
126                 msg += (
127                     '%s != expected %s or %s'
128                     % (len_gxs, len(func.inputs), len(target_input_indexes)))
129             raise ValueError(func._get_error_message(msg))
130 
131     for i, gx in six.moves.zip(target_input_indexes, gxs):
132         if gx is not None:
133             grad_inputs[func.inputs[i]].append(gx)
134 
135             if is_debug:
136                 node_x = func.inputs[i]
137                 g_input_list = grad_inputs[node_x]
138                 if gx.shape != node_x.shape:
139                     raise ValueError(func._get_error_message(
140                         'shape of gradients returned from backward is '
141                         'incorrect: '
142                         'input-index={}, actual {} != expected {}'.format(
143                             i, gx.shape, node_x.shape)))
144                 if gx is not None and g_input_list:
145                     g_input = g_input_list[0]
146                     if gx.shape != g_input.shape:
147                         raise ValueError(func._get_error_message(
148                             'shape of gradients returned from backward is '
149                             'incorrect: '
150                             'input-index={}, actual {} != expected {}'.format(
151                                 i, gx.shape, g_input.shape)))
152                     if gx.dtype != g_input.dtype:
153                         raise ValueError(func._get_error_message(
154                             'dtype of gradients returned from backward is '
155                             'incorrect: '
156                             'input-index={}, actual {} != expected {}'.format(
157                                 i, gx.dtype, g_input.dtype)))
158     del gxs
159 
160     if is_debug:
161         # each grad is a list of variables
162         # iter_gxs expands it as a sequence of variables.
163         def iter_gxs(gxs):
164             for gx in gxs:
165                 for gx_elem in gx:
166                     yield gx_elem
167 
168         for gx in iter_gxs(grad_inputs.values()):
169             if chainer.backend._contains_nan(gx.data):
170                 raise RuntimeError(
171                     'NaN is detected on backward computation of {}'
172                     .format(func.label))
173 
174     if not func.lazy_grad_sum:
175         for gx in grad_inputs.values():
176             _reduce(gx)
177
```
--- 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/chainer/_backprop_utils.py b/chainer/_backprop_utils.py
--- a/chainer/_backprop_utils.py
+++ b/chainer/_backprop_utils.py
@@ -78,13 +78,16 @@
     :func:`chainer.grad`.
 
     Args:
-        target_input_indexes (tuple of int): Sorted indices of the input
-            variables w.r.t. which the gradients are required. It is
-            guaranteed that this tuple contains at least one element.
+        func (~chainer.FunctionNode): The function for which gradients are
+            accumulated.
+        target_input_indexes (tuple of int): Sorted indices of the inputs
+            that require gradients. It is guaranteed that this tuple contains
+            at least one element.
         grad_outputs (tuple of Variable): Gradients w.r.t. the output
             variables. If the gradient w.r.t. an output variable is not
             given, the corresponding element is ``None``.
-        grad_inputs (dict): References of radients w.r.t. the input variables.
+        grad_inputs (dict): References of the gradients w.r.t. the input
+            variables.
 
     """
     is_debug = chainer.is_debug()

{"golden_diff": "diff --git a/chainer/_backprop_utils.py b/chainer/_backprop_utils.py\n--- a/chainer/_backprop_utils.py\n+++ b/chainer/_backprop_utils.py\n@@ -78,13 +78,16 @@\n     :func:`chainer.grad`.\n \n     Args:\n-        target_input_indexes (tuple of int): Sorted indices of the input\n-            variables w.r.t. which the gradients are required. It is\n-            guaranteed that this tuple contains at least one element.\n+        func (~chainer.FunctionNode): The function for which gradients are\n+            accumulated.\n+        target_input_indexes (tuple of int): Sorted indices of the inputs\n+            that require gradients. It is guaranteed that this tuple contains\n+            at least one element.\n         grad_outputs (tuple of Variable): Gradients w.r.t. the output\n             variables. If the gradient w.r.t. an output variable is not\n             given, the corresponding element is ``None``.\n-        grad_inputs (dict): References of radients w.r.t. the input variables.\n+        grad_inputs (dict): References of the gradients w.r.t. the input\n+            variables.\n \n     \"\"\"\n     is_debug = chainer.is_debug()\n", "issue": "`backprop_step` only partially documented\nThe `backprop_step` function in `chainer/_backprop_utils.py` is documented but misses an explanation for the `func` argument. https://github.com/chainer/chainer/blob/master/chainer/_backprop_utils.py#L73-L89\n", "before_files": [{"content": "import six\n\nimport chainer\n\n\ndef _reduce(grad_list):\n    if not grad_list:\n        return None\n    if len(grad_list) >= 2:\n        grad_list[:] = [chainer.functions.add(*grad_list)]\n    return grad_list[0]\n\n\ndef _pure(grad):\n    return [] if grad is None else [grad]\n\n\ndef _pop_or_none(grad_list):\n    return grad_list.pop() if grad_list else None\n\n\nclass GradTable(object):\n\n    \"\"\"Dict of nodes to references of gradients\n\n    The gradients are stored as references to them in the backprop process. The\n    current implementation uses lists. Keep the lengths of lists <= 1 for the\n    strict accumulation of gradients. Leave them to accumulate gradients\n    lazily.\n\n    Args:\n        load_if_new (bool): read ``grad_var`` of node when the node has not\n            been added.\n\n    \"\"\"\n\n    def __init__(self, load_if_new=False):\n        self.grads = {}\n        self._load_if_new = load_if_new\n\n    def __setitem__(self, node, grad):\n        assert node is not None\n        self.grads[node] = _pure(grad)\n\n    def get_as_list(self, node):\n        assert node is not None\n        grads = self.grads\n        if node not in grads:\n            if self._load_if_new and node.creator_node is None:\n                node._check_old_style_gradient()\n                # accumulate the gradient only if the node is a leaf\n                grads[node] = _pure(node.grad_var)\n            else:\n                grads[node] = []\n        return grads[node]\n\n    def pop(self, node):\n        if node is None:\n            return None\n        grads = self.grads\n        if node in grads:\n            return _reduce(grads.pop(node))\n        if self._load_if_new:\n            return node.grad_var\n        else:\n            return None\n\n    def assert_no_grads(self):\n        for gx in self.grads.values():\n            assert gx == []\n\n\ndef backprop_step(\n        func, target_input_indexes, grad_outputs, grad_inputs):\n    \"\"\"Accumulates gradients of a FunctionNode\n\n    This routine is used by :meth:`chainer.Variable.backward` and\n    :func:`chainer.grad`.\n\n    Args:\n        target_input_indexes (tuple of int): Sorted indices of the input\n            variables w.r.t. which the gradients are required. It is\n            guaranteed that this tuple contains at least one element.\n        grad_outputs (tuple of Variable): Gradients w.r.t. the output\n            variables. If the gradient w.r.t. an output variable is not\n            given, the corresponding element is ``None``.\n        grad_inputs (dict): References of radients w.r.t. the input variables.\n\n    \"\"\"\n    is_debug = chainer.is_debug()\n    if is_debug:\n        assert isinstance(target_input_indexes, tuple)\n        assert target_input_indexes == tuple(sorted(target_input_indexes))\n        assert isinstance(grad_outputs, tuple)\n    if func.backward_accumulate.__code__ \\\n            is not chainer.FunctionNode.backward_accumulate.__code__:\n        # backward_accumulate is overridden\n        grad_inputs_tuple = tuple([\n            _pop_or_none(grad_inputs[func.inputs[i]])\n            for i in target_input_indexes\n        ])\n        gxs = func.backward_accumulate(\n            target_input_indexes, grad_outputs, grad_inputs_tuple)\n    else:  # otherwise, backward should be overridden\n        gxs = func.backward(\n            target_input_indexes, grad_outputs)\n\n        if is_debug:\n            for gx in gxs:\n                if not (gx is None or isinstance(gx, chainer.Variable)):\n                    raise ValueError(func._get_error_message(\n                        'type of gradients returned from backward is '\n                        'incorrect: '\n                        '{} != expected {}'.format(\n                            type(gx), chainer.Variable)))\n\n        len_gxs = len(gxs)\n        if len_gxs == len(func.inputs):\n            gxs = tuple([gxs[i] for i in target_input_indexes])\n        elif len_gxs != len(target_input_indexes):\n            msg = 'number of gradients returned from backward is incorrect: '\n            if len(func.inputs) == len(target_input_indexes):\n                msg += (\n                    '%s != expected %s' % (len_gxs, len(func.inputs)))\n            else:\n                msg += (\n                    '%s != expected %s or %s'\n                    % (len_gxs, len(func.inputs), len(target_input_indexes)))\n            raise ValueError(func._get_error_message(msg))\n\n    for i, gx in six.moves.zip(target_input_indexes, gxs):\n        if gx is not None:\n            grad_inputs[func.inputs[i]].append(gx)\n\n            if is_debug:\n                node_x = func.inputs[i]\n                g_input_list = grad_inputs[node_x]\n                if gx.shape != node_x.shape:\n                    raise ValueError(func._get_error_message(\n                        'shape of gradients returned from backward is '\n                        'incorrect: '\n                        'input-index={}, actual {} != expected {}'.format(\n                            i, gx.shape, node_x.shape)))\n                if gx is not None and g_input_list:\n                    g_input = g_input_list[0]\n                    if gx.shape != g_input.shape:\n                        raise ValueError(func._get_error_message(\n                            'shape of gradients returned from backward is '\n                            'incorrect: '\n                            'input-index={}, actual {} != expected {}'.format(\n                                i, gx.shape, g_input.shape)))\n                    if gx.dtype != g_input.dtype:\n                        raise ValueError(func._get_error_message(\n                            'dtype of gradients returned from backward is '\n                            'incorrect: '\n                            'input-index={}, actual {} != expected {}'.format(\n                                i, gx.dtype, g_input.dtype)))\n    del gxs\n\n    if is_debug:\n        # each grad is a list of variables\n        # iter_gxs expands it as a sequence of variables.\n        def iter_gxs(gxs):\n            for gx in gxs:\n                for gx_elem in gx:\n                    yield gx_elem\n\n        for gx in iter_gxs(grad_inputs.values()):\n            if chainer.backend._contains_nan(gx.data):\n                raise RuntimeError(\n                    'NaN is detected on backward computation of {}'\n                    .format(func.label))\n\n    if not func.lazy_grad_sum:\n        for gx in grad_inputs.values():\n            _reduce(gx)\n", "path": "chainer/_backprop_utils.py"}], "after_files": [{"content": "import six\n\nimport chainer\n\n\ndef _reduce(grad_list):\n    if not grad_list:\n        return None\n    if len(grad_list) >= 2:\n        grad_list[:] = [chainer.functions.add(*grad_list)]\n    return grad_list[0]\n\n\ndef _pure(grad):\n    return [] if grad is None else [grad]\n\n\ndef _pop_or_none(grad_list):\n    return grad_list.pop() if grad_list else None\n\n\nclass GradTable(object):\n\n    \"\"\"Dict of nodes to references of gradients\n\n    The gradients are stored as references to them in the backprop process. The\n    current implementation uses lists. Keep the lengths of lists <= 1 for the\n    strict accumulation of gradients. Leave them to accumulate gradients\n    lazily.\n\n    Args:\n        load_if_new (bool): read ``grad_var`` of node when the node has not\n            been added.\n\n    \"\"\"\n\n    def __init__(self, load_if_new=False):\n        self.grads = {}\n        self._load_if_new = load_if_new\n\n    def __setitem__(self, node, grad):\n        assert node is not None\n        self.grads[node] = _pure(grad)\n\n    def get_as_list(self, node):\n        assert node is not None\n        grads = self.grads\n        if node not in grads:\n            if self._load_if_new and node.creator_node is None:\n                node._check_old_style_gradient()\n                # accumulate the gradient only if the node is a leaf\n                grads[node] = _pure(node.grad_var)\n            else:\n                grads[node] = []\n        return grads[node]\n\n    def pop(self, node):\n        if node is None:\n            return None\n        grads = self.grads\n        if node in grads:\n            return _reduce(grads.pop(node))\n        if self._load_if_new:\n            return node.grad_var\n        else:\n            return None\n\n    def assert_no_grads(self):\n        for gx in self.grads.values():\n            assert gx == []\n\n\ndef backprop_step(\n        func, target_input_indexes, grad_outputs, grad_inputs):\n    \"\"\"Accumulates gradients of a FunctionNode\n\n    This routine is used by :meth:`chainer.Variable.backward` and\n    :func:`chainer.grad`.\n\n    Args:\n        func (~chainer.FunctionNode): The function for which gradients are\n            accumulated.\n        target_input_indexes (tuple of int): Sorted indices of the inputs\n            that require gradients. It is guaranteed that this tuple contains\n            at least one element.\n        grad_outputs (tuple of Variable): Gradients w.r.t. the output\n            variables. If the gradient w.r.t. an output variable is not\n            given, the corresponding element is ``None``.\n        grad_inputs (dict): References of the gradients w.r.t. the input\n            variables.\n\n    \"\"\"\n    is_debug = chainer.is_debug()\n    if is_debug:\n        assert isinstance(target_input_indexes, tuple)\n        assert target_input_indexes == tuple(sorted(target_input_indexes))\n        assert isinstance(grad_outputs, tuple)\n    if func.backward_accumulate.__code__ \\\n            is not chainer.FunctionNode.backward_accumulate.__code__:\n        # backward_accumulate is overridden\n        grad_inputs_tuple = tuple([\n            _pop_or_none(grad_inputs[func.inputs[i]])\n            for i in target_input_indexes\n        ])\n        gxs = func.backward_accumulate(\n            target_input_indexes, grad_outputs, grad_inputs_tuple)\n    else:  # otherwise, backward should be overridden\n        gxs = func.backward(\n            target_input_indexes, grad_outputs)\n\n        if is_debug:\n            for gx in gxs:\n                if not (gx is None or isinstance(gx, chainer.Variable)):\n                    raise ValueError(func._get_error_message(\n                        'type of gradients returned from backward is '\n                        'incorrect: '\n                        '{} != expected {}'.format(\n                            type(gx), chainer.Variable)))\n\n        len_gxs = len(gxs)\n        if len_gxs == len(func.inputs):\n            gxs = tuple([gxs[i] for i in target_input_indexes])\n        elif len_gxs != len(target_input_indexes):\n            msg = 'number of gradients returned from backward is incorrect: '\n            if len(func.inputs) == len(target_input_indexes):\n                msg += (\n                    '%s != expected %s' % (len_gxs, len(func.inputs)))\n            else:\n                msg += (\n                    '%s != expected %s or %s'\n                    % (len_gxs, len(func.inputs), len(target_input_indexes)))\n            raise ValueError(func._get_error_message(msg))\n\n    for i, gx in six.moves.zip(target_input_indexes, gxs):\n        if gx is not None:\n            grad_inputs[func.inputs[i]].append(gx)\n\n            if is_debug:\n                node_x = func.inputs[i]\n                g_input_list = grad_inputs[node_x]\n                if gx.shape != node_x.shape:\n                    raise ValueError(func._get_error_message(\n                        'shape of gradients returned from backward is '\n                        'incorrect: '\n                        'input-index={}, actual {} != expected {}'.format(\n                            i, gx.shape, node_x.shape)))\n                if gx is not None and g_input_list:\n                    g_input = g_input_list[0]\n                    if gx.shape != g_input.shape:\n                        raise ValueError(func._get_error_message(\n                            'shape of gradients returned from backward is '\n                            'incorrect: '\n                            'input-index={}, actual {} != expected {}'.format(\n                                i, gx.shape, g_input.shape)))\n                    if gx.dtype != g_input.dtype:\n                        raise ValueError(func._get_error_message(\n                            'dtype of gradients returned from backward is '\n                            'incorrect: '\n                            'input-index={}, actual {} != expected {}'.format(\n                                i, gx.dtype, g_input.dtype)))\n    del gxs\n\n    if is_debug:\n        # each grad is a list of variables\n        # iter_gxs expands it as a sequence of variables.\n        def iter_gxs(gxs):\n            for gx in gxs:\n                for gx_elem in gx:\n                    yield gx_elem\n\n        for gx in iter_gxs(grad_inputs.values()):\n            if chainer.backend._contains_nan(gx.data):\n                raise RuntimeError(\n                    'NaN is detected on backward computation of {}'\n                    .format(func.label))\n\n    if not func.lazy_grad_sum:\n        for gx in grad_inputs.values():\n            _reduce(gx)\n", "path": "chainer/_backprop_utils.py"}]}