We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Sweepable is actually a recursive type
The current type signature of Sweepable is
```
Sweepable = Union[Dict[str, float], ParamResolver, Sweep, Iterable[
    Union[Dict[str, float], ParamResolver, Sweep]], None]
```
But there is no logical reason to only allow one level of iteration over Sweep. And in fact, `cirq.to_sweeps` is a recursive function, so it already assumes that Sweepable is a recursive type. So as it stands, Sweepable should be defined as a recursive type.

But I would like to ask whether Sweepable really needs to be this recursive type, rather than just something that can be converted to a single Sweep. Do people actually use lists of sweeps, rather than just plain sweeps? It seems like a rather confusing thing to attempt, given that one would need to keep track of how results correspond to the individual parameter resolvers.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cirq/study/sweepable.py`
Content:
```
1 # Copyright 2018 The Cirq Developers
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     https://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 """Defines which types are Sweepable."""
16 
17 from typing import Dict, Iterable, Iterator, List, Sequence, Union, cast
18 import warnings
19 
20 from cirq._doc import document
21 from cirq.study.resolver import ParamResolver, ParamResolverOrSimilarType
22 from cirq.study.sweeps import ListSweep, Points, Sweep, UnitSweep, Zip, dict_to_product_sweep
23 
24 SweepLike = Union[ParamResolverOrSimilarType, Sweep]
25 document(SweepLike, """An object similar to an iterable of parameter resolvers.""")  # type: ignore
26 
27 Sweepable = Union[SweepLike, Iterable[SweepLike]]
28 document(
29     Sweepable,  # type: ignore
30     """An object or collection of objects representing a parameter sweep.""",
31 )
32 
33 
34 def to_resolvers(sweepable: Sweepable) -> Iterator[ParamResolver]:
35     """Convert a Sweepable to a list of ParamResolvers."""
36     for sweep in to_sweeps(sweepable):
37         yield from sweep
38 
39 
40 def to_sweeps(sweepable: Sweepable) -> List[Sweep]:
41     """Converts a Sweepable to a list of Sweeps."""
42     if sweepable is None:
43         return [UnitSweep]
44     if isinstance(sweepable, ParamResolver):
45         return [_resolver_to_sweep(sweepable)]
46     if isinstance(sweepable, Sweep):
47         return [sweepable]
48     if isinstance(sweepable, dict):
49         if any(isinstance(val, Sequence) for val in sweepable.values()):
50             warnings.warn(
51                 'Implicit expansion of a dictionary into a Cartesian product '
52                 'of sweeps is deprecated and will be removed in cirq 0.10. '
53                 'Instead, expand the sweep explicitly using '
54                 '`cirq.dict_to_product_sweep`.',
55                 DeprecationWarning,
56                 stacklevel=2,
57             )
58         product_sweep = dict_to_product_sweep(sweepable)
59         return [_resolver_to_sweep(resolver) for resolver in product_sweep]
60     if isinstance(sweepable, Iterable) and not isinstance(sweepable, str):
61         return [
62             sweep
63             for item in sweepable
64             for sweep in to_sweeps(cast(Union[Dict[str, float], ParamResolver, Sweep], item))
65         ]
66     raise TypeError(f'Unrecognized sweepable type: {type(sweepable)}.\nsweepable: {sweepable}')
67 
68 
69 def to_sweep(
70     sweep_or_resolver_list: Union[
71         'Sweep', ParamResolverOrSimilarType, Iterable[ParamResolverOrSimilarType]
72     ]
73 ) -> 'Sweep':
74     """Converts the argument into a ``cirq.Sweep``.
75 
76     Args:
77         sweep_or_resolver_list: The object to try to turn into a
78             ``cirq.Sweep`` . A ``cirq.Sweep``, a single ``cirq.ParamResolver``,
79             or a list of ``cirq.ParamResolver`` s.
80 
81     Returns:
82         A sweep equal to or containing the argument.
83     """
84     if isinstance(sweep_or_resolver_list, Sweep):
85         return sweep_or_resolver_list
86     if isinstance(sweep_or_resolver_list, (ParamResolver, dict)):
87         resolver = cast(ParamResolverOrSimilarType, sweep_or_resolver_list)
88         return ListSweep([resolver])
89     if isinstance(sweep_or_resolver_list, Iterable):
90         resolver_iter = cast(Iterable[ParamResolverOrSimilarType], sweep_or_resolver_list)
91         return ListSweep(resolver_iter)
92     raise TypeError('Unexpected sweep-like value: {}'.format(sweep_or_resolver_list))
93 
94 
95 def _resolver_to_sweep(resolver: ParamResolver) -> Sweep:
96     params = resolver.param_dict
97     if not params:
98         return UnitSweep
99     return Zip(*[Points(key, [cast(float, value)]) for key, value in params.items()])
100
```
--- 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/cirq/study/sweepable.py b/cirq/study/sweepable.py
--- a/cirq/study/sweepable.py
+++ b/cirq/study/sweepable.py
@@ -16,17 +16,27 @@
 
 from typing import Dict, Iterable, Iterator, List, Sequence, Union, cast
 import warnings
+from typing_extensions import Protocol
 
 from cirq._doc import document
 from cirq.study.resolver import ParamResolver, ParamResolverOrSimilarType
 from cirq.study.sweeps import ListSweep, Points, Sweep, UnitSweep, Zip, dict_to_product_sweep
 
 SweepLike = Union[ParamResolverOrSimilarType, Sweep]
-document(SweepLike, """An object similar to an iterable of parameter resolvers.""")  # type: ignore
+document(SweepLike, """An object similar to an iterable of parameter resolvers.""")
 
-Sweepable = Union[SweepLike, Iterable[SweepLike]]
+
+class _Sweepable(Protocol):
+    """An intermediate class allowing for recursive definition of Sweepable,
+    since recursive union definitions are not yet supported in mypy."""
+
+    def __iter__(self) -> Iterator[Union[SweepLike, '_Sweepable']]:
+        pass
+
+
+Sweepable = Union[SweepLike, _Sweepable]
 document(
-    Sweepable,  # type: ignore
+    Sweepable,
     """An object or collection of objects representing a parameter sweep.""",
 )
 
@@ -58,11 +68,7 @@
         product_sweep = dict_to_product_sweep(sweepable)
         return [_resolver_to_sweep(resolver) for resolver in product_sweep]
     if isinstance(sweepable, Iterable) and not isinstance(sweepable, str):
-        return [
-            sweep
-            for item in sweepable
-            for sweep in to_sweeps(cast(Union[Dict[str, float], ParamResolver, Sweep], item))
-        ]
+        return [sweep for item in sweepable for sweep in to_sweeps(item)]
     raise TypeError(f'Unrecognized sweepable type: {type(sweepable)}.\nsweepable: {sweepable}')

{"golden_diff": "diff --git a/cirq/study/sweepable.py b/cirq/study/sweepable.py\n--- a/cirq/study/sweepable.py\n+++ b/cirq/study/sweepable.py\n@@ -16,17 +16,27 @@\n \n from typing import Dict, Iterable, Iterator, List, Sequence, Union, cast\n import warnings\n+from typing_extensions import Protocol\n \n from cirq._doc import document\n from cirq.study.resolver import ParamResolver, ParamResolverOrSimilarType\n from cirq.study.sweeps import ListSweep, Points, Sweep, UnitSweep, Zip, dict_to_product_sweep\n \n SweepLike = Union[ParamResolverOrSimilarType, Sweep]\n-document(SweepLike, \"\"\"An object similar to an iterable of parameter resolvers.\"\"\")  # type: ignore\n+document(SweepLike, \"\"\"An object similar to an iterable of parameter resolvers.\"\"\")\n \n-Sweepable = Union[SweepLike, Iterable[SweepLike]]\n+\n+class _Sweepable(Protocol):\n+    \"\"\"An intermediate class allowing for recursive definition of Sweepable,\n+    since recursive union definitions are not yet supported in mypy.\"\"\"\n+\n+    def __iter__(self) -> Iterator[Union[SweepLike, '_Sweepable']]:\n+        pass\n+\n+\n+Sweepable = Union[SweepLike, _Sweepable]\n document(\n-    Sweepable,  # type: ignore\n+    Sweepable,\n     \"\"\"An object or collection of objects representing a parameter sweep.\"\"\",\n )\n \n@@ -58,11 +68,7 @@\n         product_sweep = dict_to_product_sweep(sweepable)\n         return [_resolver_to_sweep(resolver) for resolver in product_sweep]\n     if isinstance(sweepable, Iterable) and not isinstance(sweepable, str):\n-        return [\n-            sweep\n-            for item in sweepable\n-            for sweep in to_sweeps(cast(Union[Dict[str, float], ParamResolver, Sweep], item))\n-        ]\n+        return [sweep for item in sweepable for sweep in to_sweeps(item)]\n     raise TypeError(f'Unrecognized sweepable type: {type(sweepable)}.\\nsweepable: {sweepable}')\n", "issue": "Sweepable is actually a recursive type\nThe current type signature of Sweepable is\r\n```\r\nSweepable = Union[Dict[str, float], ParamResolver, Sweep, Iterable[\r\n    Union[Dict[str, float], ParamResolver, Sweep]], None]\r\n```\r\nBut there is no logical reason to only allow one level of iteration over Sweep. And in fact, `cirq.to_sweeps` is a recursive function, so it already assumes that Sweepable is a recursive type. So as it stands, Sweepable should be defined as a recursive type.\r\n\r\nBut I would like to ask whether Sweepable really needs to be this recursive type, rather than just something that can be converted to a single Sweep. Do people actually use lists of sweeps, rather than just plain sweeps? It seems like a rather confusing thing to attempt, given that one would need to keep track of how results correspond to the individual parameter resolvers.\n", "before_files": [{"content": "# Copyright 2018 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Defines which types are Sweepable.\"\"\"\n\nfrom typing import Dict, Iterable, Iterator, List, Sequence, Union, cast\nimport warnings\n\nfrom cirq._doc import document\nfrom cirq.study.resolver import ParamResolver, ParamResolverOrSimilarType\nfrom cirq.study.sweeps import ListSweep, Points, Sweep, UnitSweep, Zip, dict_to_product_sweep\n\nSweepLike = Union[ParamResolverOrSimilarType, Sweep]\ndocument(SweepLike, \"\"\"An object similar to an iterable of parameter resolvers.\"\"\")  # type: ignore\n\nSweepable = Union[SweepLike, Iterable[SweepLike]]\ndocument(\n    Sweepable,  # type: ignore\n    \"\"\"An object or collection of objects representing a parameter sweep.\"\"\",\n)\n\n\ndef to_resolvers(sweepable: Sweepable) -> Iterator[ParamResolver]:\n    \"\"\"Convert a Sweepable to a list of ParamResolvers.\"\"\"\n    for sweep in to_sweeps(sweepable):\n        yield from sweep\n\n\ndef to_sweeps(sweepable: Sweepable) -> List[Sweep]:\n    \"\"\"Converts a Sweepable to a list of Sweeps.\"\"\"\n    if sweepable is None:\n        return [UnitSweep]\n    if isinstance(sweepable, ParamResolver):\n        return [_resolver_to_sweep(sweepable)]\n    if isinstance(sweepable, Sweep):\n        return [sweepable]\n    if isinstance(sweepable, dict):\n        if any(isinstance(val, Sequence) for val in sweepable.values()):\n            warnings.warn(\n                'Implicit expansion of a dictionary into a Cartesian product '\n                'of sweeps is deprecated and will be removed in cirq 0.10. '\n                'Instead, expand the sweep explicitly using '\n                '`cirq.dict_to_product_sweep`.',\n                DeprecationWarning,\n                stacklevel=2,\n            )\n        product_sweep = dict_to_product_sweep(sweepable)\n        return [_resolver_to_sweep(resolver) for resolver in product_sweep]\n    if isinstance(sweepable, Iterable) and not isinstance(sweepable, str):\n        return [\n            sweep\n            for item in sweepable\n            for sweep in to_sweeps(cast(Union[Dict[str, float], ParamResolver, Sweep], item))\n        ]\n    raise TypeError(f'Unrecognized sweepable type: {type(sweepable)}.\\nsweepable: {sweepable}')\n\n\ndef to_sweep(\n    sweep_or_resolver_list: Union[\n        'Sweep', ParamResolverOrSimilarType, Iterable[ParamResolverOrSimilarType]\n    ]\n) -> 'Sweep':\n    \"\"\"Converts the argument into a ``cirq.Sweep``.\n\n    Args:\n        sweep_or_resolver_list: The object to try to turn into a\n            ``cirq.Sweep`` . A ``cirq.Sweep``, a single ``cirq.ParamResolver``,\n            or a list of ``cirq.ParamResolver`` s.\n\n    Returns:\n        A sweep equal to or containing the argument.\n    \"\"\"\n    if isinstance(sweep_or_resolver_list, Sweep):\n        return sweep_or_resolver_list\n    if isinstance(sweep_or_resolver_list, (ParamResolver, dict)):\n        resolver = cast(ParamResolverOrSimilarType, sweep_or_resolver_list)\n        return ListSweep([resolver])\n    if isinstance(sweep_or_resolver_list, Iterable):\n        resolver_iter = cast(Iterable[ParamResolverOrSimilarType], sweep_or_resolver_list)\n        return ListSweep(resolver_iter)\n    raise TypeError('Unexpected sweep-like value: {}'.format(sweep_or_resolver_list))\n\n\ndef _resolver_to_sweep(resolver: ParamResolver) -> Sweep:\n    params = resolver.param_dict\n    if not params:\n        return UnitSweep\n    return Zip(*[Points(key, [cast(float, value)]) for key, value in params.items()])\n", "path": "cirq/study/sweepable.py"}], "after_files": [{"content": "# Copyright 2018 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\n\"\"\"Defines which types are Sweepable.\"\"\"\n\nfrom typing import Dict, Iterable, Iterator, List, Sequence, Union, cast\nimport warnings\nfrom typing_extensions import Protocol\n\nfrom cirq._doc import document\nfrom cirq.study.resolver import ParamResolver, ParamResolverOrSimilarType\nfrom cirq.study.sweeps import ListSweep, Points, Sweep, UnitSweep, Zip, dict_to_product_sweep\n\nSweepLike = Union[ParamResolverOrSimilarType, Sweep]\ndocument(SweepLike, \"\"\"An object similar to an iterable of parameter resolvers.\"\"\")\n\n\nclass _Sweepable(Protocol):\n    \"\"\"An intermediate class allowing for recursive definition of Sweepable,\n    since recursive union definitions are not yet supported in mypy.\"\"\"\n\n    def __iter__(self) -> Iterator[Union[SweepLike, '_Sweepable']]:\n        pass\n\n\nSweepable = Union[SweepLike, _Sweepable]\ndocument(\n    Sweepable,\n    \"\"\"An object or collection of objects representing a parameter sweep.\"\"\",\n)\n\n\ndef to_resolvers(sweepable: Sweepable) -> Iterator[ParamResolver]:\n    \"\"\"Convert a Sweepable to a list of ParamResolvers.\"\"\"\n    for sweep in to_sweeps(sweepable):\n        yield from sweep\n\n\ndef to_sweeps(sweepable: Sweepable) -> List[Sweep]:\n    \"\"\"Converts a Sweepable to a list of Sweeps.\"\"\"\n    if sweepable is None:\n        return [UnitSweep]\n    if isinstance(sweepable, ParamResolver):\n        return [_resolver_to_sweep(sweepable)]\n    if isinstance(sweepable, Sweep):\n        return [sweepable]\n    if isinstance(sweepable, dict):\n        if any(isinstance(val, Sequence) for val in sweepable.values()):\n            warnings.warn(\n                'Implicit expansion of a dictionary into a Cartesian product '\n                'of sweeps is deprecated and will be removed in cirq 0.10. '\n                'Instead, expand the sweep explicitly using '\n                '`cirq.dict_to_product_sweep`.',\n                DeprecationWarning,\n                stacklevel=2,\n            )\n        product_sweep = dict_to_product_sweep(sweepable)\n        return [_resolver_to_sweep(resolver) for resolver in product_sweep]\n    if isinstance(sweepable, Iterable) and not isinstance(sweepable, str):\n        return [sweep for item in sweepable for sweep in to_sweeps(item)]\n    raise TypeError(f'Unrecognized sweepable type: {type(sweepable)}.\\nsweepable: {sweepable}')\n\n\ndef to_sweep(\n    sweep_or_resolver_list: Union[\n        'Sweep', ParamResolverOrSimilarType, Iterable[ParamResolverOrSimilarType]\n    ]\n) -> 'Sweep':\n    \"\"\"Converts the argument into a ``cirq.Sweep``.\n\n    Args:\n        sweep_or_resolver_list: The object to try to turn into a\n            ``cirq.Sweep`` . A ``cirq.Sweep``, a single ``cirq.ParamResolver``,\n            or a list of ``cirq.ParamResolver`` s.\n\n    Returns:\n        A sweep equal to or containing the argument.\n    \"\"\"\n    if isinstance(sweep_or_resolver_list, Sweep):\n        return sweep_or_resolver_list\n    if isinstance(sweep_or_resolver_list, (ParamResolver, dict)):\n        resolver = cast(ParamResolverOrSimilarType, sweep_or_resolver_list)\n        return ListSweep([resolver])\n    if isinstance(sweep_or_resolver_list, Iterable):\n        resolver_iter = cast(Iterable[ParamResolverOrSimilarType], sweep_or_resolver_list)\n        return ListSweep(resolver_iter)\n    raise TypeError('Unexpected sweep-like value: {}'.format(sweep_or_resolver_list))\n\n\ndef _resolver_to_sweep(resolver: ParamResolver) -> Sweep:\n    params = resolver.param_dict\n    if not params:\n        return UnitSweep\n    return Zip(*[Points(key, [cast(float, value)]) for key, value in params.items()])\n", "path": "cirq/study/sweepable.py"}]}