Skip to content

Commit

Permalink
fix[lang]: fix .vyi function body check (#4177)
Browse files Browse the repository at this point in the history
previously the validation for function bodies in interfaces incorrectly
allowed other types of expressions with the `.value` member, e.g.

```vyper
@external
def some_interface_function():
    return ...
```
although the body should only be allowed to be an ellipsis expr (`...`).

this commit correctly rejects the above source code
  • Loading branch information
cyberthirst committed Jul 29, 2024
1 parent 9e51684 commit 99304da
Show file tree
Hide file tree
Showing 2 changed files with 68 additions and 1 deletion.
63 changes: 63 additions & 0 deletions tests/functional/syntax/test_interfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from vyper import compiler
from vyper.exceptions import (
ArgumentException,
FunctionDeclarationException,
InterfaceViolation,
InvalidReference,
InvalidType,
Expand Down Expand Up @@ -421,3 +422,65 @@ def test_builtins_not_found2(erc):
compiler.compile_code(code)
assert e.value._message == f"ethereum.ercs.{erc}"
assert e.value._hint == f"try renaming `{erc}` to `I{erc}`"


def test_interface_body_check(make_input_bundle):
interface_code = """
@external
def foobar():
return ...
"""

input_bundle = make_input_bundle({"foo.vyi": interface_code})

code = """
import foo as Foo
implements: Foo
@external
def foobar():
pass
"""
with pytest.raises(FunctionDeclarationException) as e:
compiler.compile_code(code, input_bundle=input_bundle)

assert e.value._message == "function body in an interface can only be `...`!"


def test_interface_body_check2(make_input_bundle):
interface_code = """
@external
def foobar():
...
@external
def bar():
...
@external
def baz():
...
"""

input_bundle = make_input_bundle({"foo.vyi": interface_code})

code = """
import foo
implements: foo
@external
def foobar():
pass
@external
def bar():
pass
@external
def baz():
pass
"""

assert compiler.compile_code(code, input_bundle=input_bundle) is not None
6 changes: 5 additions & 1 deletion vyper/semantics/types/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,11 @@ def from_vyi(cls, funcdef: vy_ast.FunctionDef) -> "ContractFunctionT":

return_type = _parse_return_type(funcdef)

if len(funcdef.body) != 1 or not isinstance(funcdef.body[0].get("value"), vy_ast.Ellipsis):
body = funcdef.body

if len(body) != 1 or not (
isinstance(body[0], vy_ast.Expr) and isinstance(body[0].value, vy_ast.Ellipsis)
):
raise FunctionDeclarationException(
"function body in an interface can only be `...`!", funcdef
)
Expand Down

0 comments on commit 99304da

Please sign in to comment.