We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
can't declare variable `public` but can define custom getter
### Version Information

* vyper Version:  0.3.4+commit.f31f0ec
* OS: osx
* Python Version: 3.8.9

### What's your issue about?

This code fails to compile:

```
slates : public(HashMap[bytes32, DynArray[address, 15]])
```

but I can define my own getter for that type just fine:

```
slates : HashMap[bytes32, DynArray[address, 15]]

@external
def slate(sid :bytes32) -> DynArray[address, 15]:
   return self.slates[sid]
```


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `vyper/ast/expansion.py`
Content:
```
1 import copy
2 
3 from vyper import ast as vy_ast
4 from vyper.exceptions import CompilerPanic
5 
6 
7 def expand_annotated_ast(vyper_module: vy_ast.Module) -> None:
8     """
9     Perform expansion / simplification operations on an annotated Vyper AST.
10 
11     This pass uses annotated type information to modify the AST, simplifying
12     logic and expanding subtrees to reduce the compexity during codegen.
13 
14     Arguments
15     ---------
16     vyper_module : Module
17         Top-level Vyper AST node that has been type-checked and annotated.
18     """
19     generate_public_variable_getters(vyper_module)
20     remove_unused_statements(vyper_module)
21 
22 
23 def generate_public_variable_getters(vyper_module: vy_ast.Module) -> None:
24     """
25     Create getter functions for public variables.
26 
27     Arguments
28     ---------
29     vyper_module : Module
30         Top-level Vyper AST node.
31     """
32 
33     for node in vyper_module.get_children(vy_ast.VariableDecl, {"annotation.func.id": "public"}):
34         func_type = node._metadata["func_type"]
35         input_types, return_type = func_type.get_signature()
36         input_nodes = []
37 
38         # use the annotation node as a base to build the input args and return type
39         # starting with `args[0]` to remove the surrounding `public()` call`
40         annotation = copy.copy(node.annotation.args[0])
41 
42         # the base return statement is an `Attribute` node, e.g. `self.<var_name>`
43         # for each input type we wrap it in a `Subscript` to access a specific member
44         return_stmt: vy_ast.VyperNode = vy_ast.Attribute(
45             value=vy_ast.Name(id="self"), attr=func_type.name
46         )
47         return_stmt._metadata["type"] = node._metadata["type"]
48 
49         for i, type_ in enumerate(input_types):
50             if not isinstance(annotation, vy_ast.Subscript):
51                 # if we get here something has failed in type checking
52                 raise CompilerPanic("Mismatch between node and input type while building getter")
53             if annotation.value.get("id") == "HashMap":  # type: ignore
54                 # for a HashMap, split the key/value types and use the key type as the next arg
55                 arg, annotation = annotation.slice.value.elements  # type: ignore
56             else:
57                 # for other types, build an input arg node from the expected type
58                 # and remove the outer `Subscript` from the annotation
59                 arg = vy_ast.Name(id=type_._id)
60                 annotation = annotation.value
61             input_nodes.append(vy_ast.arg(arg=f"arg{i}", annotation=arg))
62 
63             # wrap the return statement in a `Subscript`
64             return_stmt = vy_ast.Subscript(
65                 value=return_stmt, slice=vy_ast.Index(value=vy_ast.Name(id=f"arg{i}"))
66             )
67 
68         # after iterating the input types, the remaining annotation node is our return type
69         return_node = annotation
70 
71         # join everything together as a new `FunctionDef` node, annotate it
72         # with the type, and append it to the existing `Module` node
73         expanded = vy_ast.FunctionDef.from_node(
74             node.annotation,
75             name=func_type.name,
76             args=vy_ast.arguments(args=input_nodes, defaults=[]),
77             body=[vy_ast.Return(value=return_stmt)],
78             decorator_list=[vy_ast.Name(id="external"), vy_ast.Name(id="view")],
79             returns=return_node,
80         )
81         expanded._metadata["type"] = func_type
82         return_node.set_parent(expanded)
83         vyper_module.add_to_body(expanded)
84 
85 
86 def remove_unused_statements(vyper_module: vy_ast.Module) -> None:
87     """
88     Remove statement nodes that are unused after type checking.
89 
90     Once type checking is complete, we can remove now-meaningless statements to
91     simplify the AST prior to IR generation.
92 
93     Arguments
94     ---------
95     vyper_module : Module
96         Top-level Vyper AST node.
97     """
98 
99     # constant declarations - values were substituted within the AST during folding
100     for node in vyper_module.get_children(vy_ast.VariableDecl, {"annotation.func.id": "constant"}):
101         vyper_module.remove_from_body(node)
102 
103     # `implements: interface` statements - validated during type checking
104     for node in vyper_module.get_children(vy_ast.AnnAssign, {"target.id": "implements"}):
105         vyper_module.remove_from_body(node)
106
```
--- 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/vyper/ast/expansion.py b/vyper/ast/expansion.py
--- a/vyper/ast/expansion.py
+++ b/vyper/ast/expansion.py
@@ -53,6 +53,9 @@
             if annotation.value.get("id") == "HashMap":  # type: ignore
                 # for a HashMap, split the key/value types and use the key type as the next arg
                 arg, annotation = annotation.slice.value.elements  # type: ignore
+            elif annotation.value.get("id") == "DynArray":
+                arg = vy_ast.Name(id=type_._id)
+                annotation = annotation.slice.value.elements[0]  # type: ignore
             else:
                 # for other types, build an input arg node from the expected type
                 # and remove the outer `Subscript` from the annotation
@@ -66,7 +69,7 @@
             )
 
         # after iterating the input types, the remaining annotation node is our return type
-        return_node = annotation
+        return_node = copy.copy(annotation)
 
         # join everything together as a new `FunctionDef` node, annotate it
         # with the type, and append it to the existing `Module` node

{"golden_diff": "diff --git a/vyper/ast/expansion.py b/vyper/ast/expansion.py\n--- a/vyper/ast/expansion.py\n+++ b/vyper/ast/expansion.py\n@@ -53,6 +53,9 @@\n             if annotation.value.get(\"id\") == \"HashMap\":  # type: ignore\n                 # for a HashMap, split the key/value types and use the key type as the next arg\n                 arg, annotation = annotation.slice.value.elements  # type: ignore\n+            elif annotation.value.get(\"id\") == \"DynArray\":\n+                arg = vy_ast.Name(id=type_._id)\n+                annotation = annotation.slice.value.elements[0]  # type: ignore\n             else:\n                 # for other types, build an input arg node from the expected type\n                 # and remove the outer `Subscript` from the annotation\n@@ -66,7 +69,7 @@\n             )\n \n         # after iterating the input types, the remaining annotation node is our return type\n-        return_node = annotation\n+        return_node = copy.copy(annotation)\n \n         # join everything together as a new `FunctionDef` node, annotate it\n         # with the type, and append it to the existing `Module` node\n", "issue": "can't declare variable `public` but can define custom getter\n### Version Information\r\n\r\n* vyper Version:  0.3.4+commit.f31f0ec\r\n* OS: osx\r\n* Python Version: 3.8.9\r\n\r\n### What's your issue about?\r\n\r\nThis code fails to compile:\r\n\r\n```\r\nslates : public(HashMap[bytes32, DynArray[address, 15]])\r\n```\r\n\r\nbut I can define my own getter for that type just fine:\r\n\r\n```\r\nslates : HashMap[bytes32, DynArray[address, 15]]\r\n\r\n@external\r\ndef slate(sid :bytes32) -> DynArray[address, 15]:\r\n   return self.slates[sid]\r\n```\r\n\n", "before_files": [{"content": "import copy\n\nfrom vyper import ast as vy_ast\nfrom vyper.exceptions import CompilerPanic\n\n\ndef expand_annotated_ast(vyper_module: vy_ast.Module) -> None:\n    \"\"\"\n    Perform expansion / simplification operations on an annotated Vyper AST.\n\n    This pass uses annotated type information to modify the AST, simplifying\n    logic and expanding subtrees to reduce the compexity during codegen.\n\n    Arguments\n    ---------\n    vyper_module : Module\n        Top-level Vyper AST node that has been type-checked and annotated.\n    \"\"\"\n    generate_public_variable_getters(vyper_module)\n    remove_unused_statements(vyper_module)\n\n\ndef generate_public_variable_getters(vyper_module: vy_ast.Module) -> None:\n    \"\"\"\n    Create getter functions for public variables.\n\n    Arguments\n    ---------\n    vyper_module : Module\n        Top-level Vyper AST node.\n    \"\"\"\n\n    for node in vyper_module.get_children(vy_ast.VariableDecl, {\"annotation.func.id\": \"public\"}):\n        func_type = node._metadata[\"func_type\"]\n        input_types, return_type = func_type.get_signature()\n        input_nodes = []\n\n        # use the annotation node as a base to build the input args and return type\n        # starting with `args[0]` to remove the surrounding `public()` call`\n        annotation = copy.copy(node.annotation.args[0])\n\n        # the base return statement is an `Attribute` node, e.g. `self.<var_name>`\n        # for each input type we wrap it in a `Subscript` to access a specific member\n        return_stmt: vy_ast.VyperNode = vy_ast.Attribute(\n            value=vy_ast.Name(id=\"self\"), attr=func_type.name\n        )\n        return_stmt._metadata[\"type\"] = node._metadata[\"type\"]\n\n        for i, type_ in enumerate(input_types):\n            if not isinstance(annotation, vy_ast.Subscript):\n                # if we get here something has failed in type checking\n                raise CompilerPanic(\"Mismatch between node and input type while building getter\")\n            if annotation.value.get(\"id\") == \"HashMap\":  # type: ignore\n                # for a HashMap, split the key/value types and use the key type as the next arg\n                arg, annotation = annotation.slice.value.elements  # type: ignore\n            else:\n                # for other types, build an input arg node from the expected type\n                # and remove the outer `Subscript` from the annotation\n                arg = vy_ast.Name(id=type_._id)\n                annotation = annotation.value\n            input_nodes.append(vy_ast.arg(arg=f\"arg{i}\", annotation=arg))\n\n            # wrap the return statement in a `Subscript`\n            return_stmt = vy_ast.Subscript(\n                value=return_stmt, slice=vy_ast.Index(value=vy_ast.Name(id=f\"arg{i}\"))\n            )\n\n        # after iterating the input types, the remaining annotation node is our return type\n        return_node = annotation\n\n        # join everything together as a new `FunctionDef` node, annotate it\n        # with the type, and append it to the existing `Module` node\n        expanded = vy_ast.FunctionDef.from_node(\n            node.annotation,\n            name=func_type.name,\n            args=vy_ast.arguments(args=input_nodes, defaults=[]),\n            body=[vy_ast.Return(value=return_stmt)],\n            decorator_list=[vy_ast.Name(id=\"external\"), vy_ast.Name(id=\"view\")],\n            returns=return_node,\n        )\n        expanded._metadata[\"type\"] = func_type\n        return_node.set_parent(expanded)\n        vyper_module.add_to_body(expanded)\n\n\ndef remove_unused_statements(vyper_module: vy_ast.Module) -> None:\n    \"\"\"\n    Remove statement nodes that are unused after type checking.\n\n    Once type checking is complete, we can remove now-meaningless statements to\n    simplify the AST prior to IR generation.\n\n    Arguments\n    ---------\n    vyper_module : Module\n        Top-level Vyper AST node.\n    \"\"\"\n\n    # constant declarations - values were substituted within the AST during folding\n    for node in vyper_module.get_children(vy_ast.VariableDecl, {\"annotation.func.id\": \"constant\"}):\n        vyper_module.remove_from_body(node)\n\n    # `implements: interface` statements - validated during type checking\n    for node in vyper_module.get_children(vy_ast.AnnAssign, {\"target.id\": \"implements\"}):\n        vyper_module.remove_from_body(node)\n", "path": "vyper/ast/expansion.py"}], "after_files": [{"content": "import copy\n\nfrom vyper import ast as vy_ast\nfrom vyper.exceptions import CompilerPanic\n\n\ndef expand_annotated_ast(vyper_module: vy_ast.Module) -> None:\n    \"\"\"\n    Perform expansion / simplification operations on an annotated Vyper AST.\n\n    This pass uses annotated type information to modify the AST, simplifying\n    logic and expanding subtrees to reduce the compexity during codegen.\n\n    Arguments\n    ---------\n    vyper_module : Module\n        Top-level Vyper AST node that has been type-checked and annotated.\n    \"\"\"\n    generate_public_variable_getters(vyper_module)\n    remove_unused_statements(vyper_module)\n\n\ndef generate_public_variable_getters(vyper_module: vy_ast.Module) -> None:\n    \"\"\"\n    Create getter functions for public variables.\n\n    Arguments\n    ---------\n    vyper_module : Module\n        Top-level Vyper AST node.\n    \"\"\"\n\n    for node in vyper_module.get_children(vy_ast.VariableDecl, {\"annotation.func.id\": \"public\"}):\n        func_type = node._metadata[\"func_type\"]\n        input_types, return_type = func_type.get_signature()\n        input_nodes = []\n\n        # use the annotation node as a base to build the input args and return type\n        # starting with `args[0]` to remove the surrounding `public()` call`\n        annotation = copy.copy(node.annotation.args[0])\n\n        # the base return statement is an `Attribute` node, e.g. `self.<var_name>`\n        # for each input type we wrap it in a `Subscript` to access a specific member\n        return_stmt: vy_ast.VyperNode = vy_ast.Attribute(\n            value=vy_ast.Name(id=\"self\"), attr=func_type.name\n        )\n        return_stmt._metadata[\"type\"] = node._metadata[\"type\"]\n\n        for i, type_ in enumerate(input_types):\n            if not isinstance(annotation, vy_ast.Subscript):\n                # if we get here something has failed in type checking\n                raise CompilerPanic(\"Mismatch between node and input type while building getter\")\n            if annotation.value.get(\"id\") == \"HashMap\":  # type: ignore\n                # for a HashMap, split the key/value types and use the key type as the next arg\n                arg, annotation = annotation.slice.value.elements  # type: ignore\n            elif annotation.value.get(\"id\") == \"DynArray\":\n                arg = vy_ast.Name(id=type_._id)\n                annotation = annotation.slice.value.elements[0]  # type: ignore\n            else:\n                # for other types, build an input arg node from the expected type\n                # and remove the outer `Subscript` from the annotation\n                arg = vy_ast.Name(id=type_._id)\n                annotation = annotation.value\n            input_nodes.append(vy_ast.arg(arg=f\"arg{i}\", annotation=arg))\n\n            # wrap the return statement in a `Subscript`\n            return_stmt = vy_ast.Subscript(\n                value=return_stmt, slice=vy_ast.Index(value=vy_ast.Name(id=f\"arg{i}\"))\n            )\n\n        # after iterating the input types, the remaining annotation node is our return type\n        return_node = copy.copy(annotation)\n\n        # join everything together as a new `FunctionDef` node, annotate it\n        # with the type, and append it to the existing `Module` node\n        expanded = vy_ast.FunctionDef.from_node(\n            node.annotation,\n            name=func_type.name,\n            args=vy_ast.arguments(args=input_nodes, defaults=[]),\n            body=[vy_ast.Return(value=return_stmt)],\n            decorator_list=[vy_ast.Name(id=\"external\"), vy_ast.Name(id=\"view\")],\n            returns=return_node,\n        )\n        expanded._metadata[\"type\"] = func_type\n        return_node.set_parent(expanded)\n        vyper_module.add_to_body(expanded)\n\n\ndef remove_unused_statements(vyper_module: vy_ast.Module) -> None:\n    \"\"\"\n    Remove statement nodes that are unused after type checking.\n\n    Once type checking is complete, we can remove now-meaningless statements to\n    simplify the AST prior to IR generation.\n\n    Arguments\n    ---------\n    vyper_module : Module\n        Top-level Vyper AST node.\n    \"\"\"\n\n    # constant declarations - values were substituted within the AST during folding\n    for node in vyper_module.get_children(vy_ast.VariableDecl, {\"annotation.func.id\": \"constant\"}):\n        vyper_module.remove_from_body(node)\n\n    # `implements: interface` statements - validated during type checking\n    for node in vyper_module.get_children(vy_ast.AnnAssign, {\"target.id\": \"implements\"}):\n        vyper_module.remove_from_body(node)\n", "path": "vyper/ast/expansion.py"}]}