We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Can't import interface using structs
### Version Information

* vyper Version (output of `vyper --version`): 0.2.12+commit.2c6842c
* OS: linux
* Python Version (output of `python --version`): 3.8.5
* Environment (output of `pip freeze`):
```
asttokens==2.0.4
pycryptodome==3.10.1
semantic-version==2.8.5
six==1.15.0
vyper==0.2.12
```

### What's your issue about?

Can't import an interface if it uses structs. Simple example:

foo.vy:
```
struct Widget:
        name: String[8]
        count: uint256

widget: Widget

@external
def show() -> (String[8], uint256):
        return (self.widget.name, self.widget.count)

@external
def __init__():
        self.widget = Widget({
                name: "thing",
                count: 1
        })
```
bar.vy
```
import foo as Foo

@external
def __init__():
        pass
```

Throw both in the same dir.

`vyper foo.vy` results in a successful compilation

`vyper bar.vy` results in:
```
Error compiling: bar.vy
vyper.exceptions.InvalidType: Invalid base type: Widget
  contract "Foo", line 5:8 
       4
  ---> 5 widget: Widget
  ---------------^
       6
```

### How can it be fixed?

Haven't spent time fixing yet

--- 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/signatures/interface.py`
Content:
```
1 # TODO does this module not get imported?
2 
3 import importlib
4 import pkgutil
5 
6 import vyper.builtin_interfaces
7 from vyper import ast as vy_ast
8 from vyper.ast.signatures import sig_utils
9 from vyper.ast.signatures.function_signature import FunctionSignature
10 from vyper.exceptions import StructureException
11 from vyper.old_codegen.global_context import GlobalContext
12 
13 
14 # Populate built-in interfaces.
15 def get_builtin_interfaces():
16     interface_names = [x.name for x in pkgutil.iter_modules(vyper.builtin_interfaces.__path__)]
17     return {
18         name: extract_sigs(
19             {
20                 "type": "vyper",
21                 "code": importlib.import_module(f"vyper.builtin_interfaces.{name}",).interface_code,
22             },
23             name,
24         )
25         for name in interface_names
26     }
27 
28 
29 def abi_type_to_ast(atype, expected_size):
30     if atype in ("int128", "uint256", "bool", "address", "bytes32"):
31         return vy_ast.Name(id=atype)
32     elif atype == "fixed168x10":
33         return vy_ast.Name(id="decimal")
34     elif atype in ("bytes", "string"):
35         # expected_size is the maximum length for inputs, minimum length for outputs
36         return vy_ast.Subscript(
37             value=vy_ast.Name(id=atype.capitalize()),
38             slice=vy_ast.Index(value=vy_ast.Int(value=expected_size)),
39         )
40     else:
41         raise StructureException(f"Type {atype} not supported by vyper.")
42 
43 
44 # Vyper defines a maximum length for bytes and string types, but Solidity does not.
45 # To maximize interoperability, we internally considers these types to have a
46 # a length of 1Mb (1024 * 1024 * 1 byte) for inputs, and 1 for outputs.
47 # Ths approach solves the issue because Vyper allows for an implicit casting
48 # from a lower length into a higher one.  (@iamdefinitelyahuman)
49 def mk_full_signature_from_json(abi):
50     funcs = [func for func in abi if func["type"] == "function"]
51     sigs = []
52 
53     for func in funcs:
54         args = []
55         returns = None
56         for a in func["inputs"]:
57             arg = vy_ast.arg(
58                 arg=a["name"],
59                 annotation=abi_type_to_ast(a["type"], 1048576),
60                 lineno=0,
61                 col_offset=0,
62             )
63             args.append(arg)
64 
65         if len(func["outputs"]) == 1:
66             returns = abi_type_to_ast(func["outputs"][0]["type"], 1)
67         elif len(func["outputs"]) > 1:
68             returns = vy_ast.Tuple(
69                 elements=[abi_type_to_ast(a["type"], 1) for a in func["outputs"]]
70             )
71 
72         decorator_list = [vy_ast.Name(id="external")]
73         # Handle either constant/payable or stateMutability field
74         if ("constant" in func and func["constant"]) or (
75             "stateMutability" in func and func["stateMutability"] == "view"
76         ):
77             decorator_list.append(vy_ast.Name(id="view"))
78         if ("payable" in func and func["payable"]) or (
79             "stateMutability" in func and func["stateMutability"] == "payable"
80         ):
81             decorator_list.append(vy_ast.Name(id="payable"))
82 
83         sig = FunctionSignature.from_definition(
84             code=vy_ast.FunctionDef(
85                 name=func["name"],
86                 args=vy_ast.arguments(args=args),
87                 decorator_list=decorator_list,
88                 returns=returns,
89             ),
90             custom_structs=dict(),
91             is_from_json=True,
92         )
93         sigs.append(sig)
94     return sigs
95 
96 
97 def extract_sigs(sig_code, interface_name=None):
98     if sig_code["type"] == "vyper":
99         interface_ast = [
100             i
101             for i in vy_ast.parse_to_ast(sig_code["code"], contract_name=interface_name)
102             if isinstance(i, vy_ast.FunctionDef)
103             or isinstance(i, vy_ast.EventDef)
104             or (isinstance(i, vy_ast.AnnAssign) and i.target.id != "implements")
105         ]
106         global_ctx = GlobalContext.get_global_context(interface_ast)
107         return sig_utils.mk_full_signature(global_ctx, sig_formatter=lambda x: x)
108     elif sig_code["type"] == "json":
109         return mk_full_signature_from_json(sig_code["code"])
110     else:
111         raise Exception(
112             (
113                 f"Unknown interface signature type '{sig_code['type']}' supplied. "
114                 "'vyper' & 'json' are supported"
115             )
116         )
117
```
--- 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/signatures/interface.py b/vyper/ast/signatures/interface.py
--- a/vyper/ast/signatures/interface.py
+++ b/vyper/ast/signatures/interface.py
@@ -99,8 +99,20 @@
         interface_ast = [
             i
             for i in vy_ast.parse_to_ast(sig_code["code"], contract_name=interface_name)
-            if isinstance(i, vy_ast.FunctionDef)
-            or isinstance(i, vy_ast.EventDef)
+            # all the nodes visited by ModuleNodeVisitor.
+            if isinstance(
+                i,
+                (
+                    vy_ast.FunctionDef,
+                    vy_ast.EventDef,
+                    vy_ast.StructDef,
+                    vy_ast.InterfaceDef,
+                    # parsing import statements at this stage
+                    # causes issues with recursive imports
+                    # vy_ast.Import,
+                    # vy_ast.ImportFrom,
+                ),
+            )
             or (isinstance(i, vy_ast.AnnAssign) and i.target.id != "implements")
         ]
         global_ctx = GlobalContext.get_global_context(interface_ast)

{"golden_diff": "diff --git a/vyper/ast/signatures/interface.py b/vyper/ast/signatures/interface.py\n--- a/vyper/ast/signatures/interface.py\n+++ b/vyper/ast/signatures/interface.py\n@@ -99,8 +99,20 @@\n         interface_ast = [\n             i\n             for i in vy_ast.parse_to_ast(sig_code[\"code\"], contract_name=interface_name)\n-            if isinstance(i, vy_ast.FunctionDef)\n-            or isinstance(i, vy_ast.EventDef)\n+            # all the nodes visited by ModuleNodeVisitor.\n+            if isinstance(\n+                i,\n+                (\n+                    vy_ast.FunctionDef,\n+                    vy_ast.EventDef,\n+                    vy_ast.StructDef,\n+                    vy_ast.InterfaceDef,\n+                    # parsing import statements at this stage\n+                    # causes issues with recursive imports\n+                    # vy_ast.Import,\n+                    # vy_ast.ImportFrom,\n+                ),\n+            )\n             or (isinstance(i, vy_ast.AnnAssign) and i.target.id != \"implements\")\n         ]\n         global_ctx = GlobalContext.get_global_context(interface_ast)\n", "issue": "Can't import interface using structs\n### Version Information\r\n\r\n* vyper Version (output of `vyper --version`): 0.2.12+commit.2c6842c\r\n* OS: linux\r\n* Python Version (output of `python --version`): 3.8.5\r\n* Environment (output of `pip freeze`):\r\n```\r\nasttokens==2.0.4\r\npycryptodome==3.10.1\r\nsemantic-version==2.8.5\r\nsix==1.15.0\r\nvyper==0.2.12\r\n```\r\n\r\n### What's your issue about?\r\n\r\nCan't import an interface if it uses structs. Simple example:\r\n\r\nfoo.vy:\r\n```\r\nstruct Widget:\r\n        name: String[8]\r\n        count: uint256\r\n\r\nwidget: Widget\r\n\r\n@external\r\ndef show() -> (String[8], uint256):\r\n        return (self.widget.name, self.widget.count)\r\n\r\n@external\r\ndef __init__():\r\n        self.widget = Widget({\r\n                name: \"thing\",\r\n                count: 1\r\n        })\r\n```\r\nbar.vy\r\n```\r\nimport foo as Foo\r\n\r\n@external\r\ndef __init__():\r\n        pass\r\n```\r\n\r\nThrow both in the same dir.\r\n\r\n`vyper foo.vy` results in a successful compilation\r\n\r\n`vyper bar.vy` results in:\r\n```\r\nError compiling: bar.vy\r\nvyper.exceptions.InvalidType: Invalid base type: Widget\r\n  contract \"Foo\", line 5:8 \r\n       4\r\n  ---> 5 widget: Widget\r\n  ---------------^\r\n       6\r\n```\r\n\r\n### How can it be fixed?\r\n\r\nHaven't spent time fixing yet\n", "before_files": [{"content": "# TODO does this module not get imported?\n\nimport importlib\nimport pkgutil\n\nimport vyper.builtin_interfaces\nfrom vyper import ast as vy_ast\nfrom vyper.ast.signatures import sig_utils\nfrom vyper.ast.signatures.function_signature import FunctionSignature\nfrom vyper.exceptions import StructureException\nfrom vyper.old_codegen.global_context import GlobalContext\n\n\n# Populate built-in interfaces.\ndef get_builtin_interfaces():\n    interface_names = [x.name for x in pkgutil.iter_modules(vyper.builtin_interfaces.__path__)]\n    return {\n        name: extract_sigs(\n            {\n                \"type\": \"vyper\",\n                \"code\": importlib.import_module(f\"vyper.builtin_interfaces.{name}\",).interface_code,\n            },\n            name,\n        )\n        for name in interface_names\n    }\n\n\ndef abi_type_to_ast(atype, expected_size):\n    if atype in (\"int128\", \"uint256\", \"bool\", \"address\", \"bytes32\"):\n        return vy_ast.Name(id=atype)\n    elif atype == \"fixed168x10\":\n        return vy_ast.Name(id=\"decimal\")\n    elif atype in (\"bytes\", \"string\"):\n        # expected_size is the maximum length for inputs, minimum length for outputs\n        return vy_ast.Subscript(\n            value=vy_ast.Name(id=atype.capitalize()),\n            slice=vy_ast.Index(value=vy_ast.Int(value=expected_size)),\n        )\n    else:\n        raise StructureException(f\"Type {atype} not supported by vyper.\")\n\n\n# Vyper defines a maximum length for bytes and string types, but Solidity does not.\n# To maximize interoperability, we internally considers these types to have a\n# a length of 1Mb (1024 * 1024 * 1 byte) for inputs, and 1 for outputs.\n# Ths approach solves the issue because Vyper allows for an implicit casting\n# from a lower length into a higher one.  (@iamdefinitelyahuman)\ndef mk_full_signature_from_json(abi):\n    funcs = [func for func in abi if func[\"type\"] == \"function\"]\n    sigs = []\n\n    for func in funcs:\n        args = []\n        returns = None\n        for a in func[\"inputs\"]:\n            arg = vy_ast.arg(\n                arg=a[\"name\"],\n                annotation=abi_type_to_ast(a[\"type\"], 1048576),\n                lineno=0,\n                col_offset=0,\n            )\n            args.append(arg)\n\n        if len(func[\"outputs\"]) == 1:\n            returns = abi_type_to_ast(func[\"outputs\"][0][\"type\"], 1)\n        elif len(func[\"outputs\"]) > 1:\n            returns = vy_ast.Tuple(\n                elements=[abi_type_to_ast(a[\"type\"], 1) for a in func[\"outputs\"]]\n            )\n\n        decorator_list = [vy_ast.Name(id=\"external\")]\n        # Handle either constant/payable or stateMutability field\n        if (\"constant\" in func and func[\"constant\"]) or (\n            \"stateMutability\" in func and func[\"stateMutability\"] == \"view\"\n        ):\n            decorator_list.append(vy_ast.Name(id=\"view\"))\n        if (\"payable\" in func and func[\"payable\"]) or (\n            \"stateMutability\" in func and func[\"stateMutability\"] == \"payable\"\n        ):\n            decorator_list.append(vy_ast.Name(id=\"payable\"))\n\n        sig = FunctionSignature.from_definition(\n            code=vy_ast.FunctionDef(\n                name=func[\"name\"],\n                args=vy_ast.arguments(args=args),\n                decorator_list=decorator_list,\n                returns=returns,\n            ),\n            custom_structs=dict(),\n            is_from_json=True,\n        )\n        sigs.append(sig)\n    return sigs\n\n\ndef extract_sigs(sig_code, interface_name=None):\n    if sig_code[\"type\"] == \"vyper\":\n        interface_ast = [\n            i\n            for i in vy_ast.parse_to_ast(sig_code[\"code\"], contract_name=interface_name)\n            if isinstance(i, vy_ast.FunctionDef)\n            or isinstance(i, vy_ast.EventDef)\n            or (isinstance(i, vy_ast.AnnAssign) and i.target.id != \"implements\")\n        ]\n        global_ctx = GlobalContext.get_global_context(interface_ast)\n        return sig_utils.mk_full_signature(global_ctx, sig_formatter=lambda x: x)\n    elif sig_code[\"type\"] == \"json\":\n        return mk_full_signature_from_json(sig_code[\"code\"])\n    else:\n        raise Exception(\n            (\n                f\"Unknown interface signature type '{sig_code['type']}' supplied. \"\n                \"'vyper' & 'json' are supported\"\n            )\n        )\n", "path": "vyper/ast/signatures/interface.py"}], "after_files": [{"content": "# TODO does this module not get imported?\n\nimport importlib\nimport pkgutil\n\nimport vyper.builtin_interfaces\nfrom vyper import ast as vy_ast\nfrom vyper.ast.signatures import sig_utils\nfrom vyper.ast.signatures.function_signature import FunctionSignature\nfrom vyper.exceptions import StructureException\nfrom vyper.old_codegen.global_context import GlobalContext\n\n\n# Populate built-in interfaces.\ndef get_builtin_interfaces():\n    interface_names = [x.name for x in pkgutil.iter_modules(vyper.builtin_interfaces.__path__)]\n    return {\n        name: extract_sigs(\n            {\n                \"type\": \"vyper\",\n                \"code\": importlib.import_module(f\"vyper.builtin_interfaces.{name}\",).interface_code,\n            },\n            name,\n        )\n        for name in interface_names\n    }\n\n\ndef abi_type_to_ast(atype, expected_size):\n    if atype in (\"int128\", \"uint256\", \"bool\", \"address\", \"bytes32\"):\n        return vy_ast.Name(id=atype)\n    elif atype == \"fixed168x10\":\n        return vy_ast.Name(id=\"decimal\")\n    elif atype in (\"bytes\", \"string\"):\n        # expected_size is the maximum length for inputs, minimum length for outputs\n        return vy_ast.Subscript(\n            value=vy_ast.Name(id=atype.capitalize()),\n            slice=vy_ast.Index(value=vy_ast.Int(value=expected_size)),\n        )\n    else:\n        raise StructureException(f\"Type {atype} not supported by vyper.\")\n\n\n# Vyper defines a maximum length for bytes and string types, but Solidity does not.\n# To maximize interoperability, we internally considers these types to have a\n# a length of 1Mb (1024 * 1024 * 1 byte) for inputs, and 1 for outputs.\n# Ths approach solves the issue because Vyper allows for an implicit casting\n# from a lower length into a higher one.  (@iamdefinitelyahuman)\ndef mk_full_signature_from_json(abi):\n    funcs = [func for func in abi if func[\"type\"] == \"function\"]\n    sigs = []\n\n    for func in funcs:\n        args = []\n        returns = None\n        for a in func[\"inputs\"]:\n            arg = vy_ast.arg(\n                arg=a[\"name\"],\n                annotation=abi_type_to_ast(a[\"type\"], 1048576),\n                lineno=0,\n                col_offset=0,\n            )\n            args.append(arg)\n\n        if len(func[\"outputs\"]) == 1:\n            returns = abi_type_to_ast(func[\"outputs\"][0][\"type\"], 1)\n        elif len(func[\"outputs\"]) > 1:\n            returns = vy_ast.Tuple(\n                elements=[abi_type_to_ast(a[\"type\"], 1) for a in func[\"outputs\"]]\n            )\n\n        decorator_list = [vy_ast.Name(id=\"external\")]\n        # Handle either constant/payable or stateMutability field\n        if (\"constant\" in func and func[\"constant\"]) or (\n            \"stateMutability\" in func and func[\"stateMutability\"] == \"view\"\n        ):\n            decorator_list.append(vy_ast.Name(id=\"view\"))\n        if (\"payable\" in func and func[\"payable\"]) or (\n            \"stateMutability\" in func and func[\"stateMutability\"] == \"payable\"\n        ):\n            decorator_list.append(vy_ast.Name(id=\"payable\"))\n\n        sig = FunctionSignature.from_definition(\n            code=vy_ast.FunctionDef(\n                name=func[\"name\"],\n                args=vy_ast.arguments(args=args),\n                decorator_list=decorator_list,\n                returns=returns,\n            ),\n            custom_structs=dict(),\n            is_from_json=True,\n        )\n        sigs.append(sig)\n    return sigs\n\n\ndef extract_sigs(sig_code, interface_name=None):\n    if sig_code[\"type\"] == \"vyper\":\n        interface_ast = [\n            i\n            for i in vy_ast.parse_to_ast(sig_code[\"code\"], contract_name=interface_name)\n            # all the nodes visited by ModuleNodeVisitor.\n            if isinstance(\n                i,\n                (\n                    vy_ast.FunctionDef,\n                    vy_ast.EventDef,\n                    vy_ast.StructDef,\n                    vy_ast.InterfaceDef,\n                    # parsing import statements at this stage\n                    # causes issues with recursive imports\n                    # vy_ast.Import,\n                    # vy_ast.ImportFrom,\n                ),\n            )\n            or (isinstance(i, vy_ast.AnnAssign) and i.target.id != \"implements\")\n        ]\n        global_ctx = GlobalContext.get_global_context(interface_ast)\n        return sig_utils.mk_full_signature(global_ctx, sig_formatter=lambda x: x)\n    elif sig_code[\"type\"] == \"json\":\n        return mk_full_signature_from_json(sig_code[\"code\"])\n    else:\n        raise Exception(\n            (\n                f\"Unknown interface signature type '{sig_code['type']}' supplied. \"\n                \"'vyper' & 'json' are supported\"\n            )\n        )\n", "path": "vyper/ast/signatures/interface.py"}]}