-
-
Notifications
You must be signed in to change notification settings - Fork 821
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix[lang]: stateless modules should not be initialized #4347
base: master
Are you sure you want to change the base?
Changes from 11 commits
1b1ac45
3a9e29d
5527244
3c695da
5000efc
e3d7582
c92e1ad
cf91784
1ab6433
28c9be7
0c5f645
47efc8e
5fe6c84
fececb7
4cc01bb
ba19783
b668f41
6c7a30f
948d047
3dbbeb6
1f4a2d6
be5aa0b
7b2f38b
bb4944f
b41bc28
2bcba89
7f2f452
f64109f
bf7307c
a075979
b67ab3f
ef0c49d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
def test_export_nonreentrant(make_input_bundle, get_contract, tx_failed): | ||
lib1 = """ | ||
phony: uint32 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this feels off, see my comment at |
||
|
||
interface Foo: | ||
def foo() -> uint256: nonpayable | ||
|
||
|
@@ -38,6 +40,8 @@ def __default__(): | |
|
||
def test_internal_nonreentrant(make_input_bundle, get_contract, tx_failed): | ||
lib1 = """ | ||
phony: uint32 | ||
|
||
interface Foo: | ||
def foo() -> uint256: nonpayable | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -218,6 +218,8 @@ def bar(x: {type}): | |
|
||
def test_exports_abi(make_input_bundle): | ||
lib1 = """ | ||
phony: uint32 | ||
|
||
@external | ||
def foo(): | ||
pass | ||
|
@@ -330,6 +332,8 @@ def __init__(): | |
def test_event_export_from_init(make_input_bundle): | ||
# test that events get exported when used in init functions | ||
lib1 = """ | ||
phony: uint32 | ||
|
||
event MyEvent: | ||
pass | ||
|
||
|
@@ -361,6 +365,8 @@ def __init__(): | |
def test_event_export_from_function_export(make_input_bundle): | ||
# test events used in exported functions are exported | ||
lib1 = """ | ||
phony: uint32 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe we shouldn't add phony here -- the code change is telling us to remove |
||
|
||
event MyEvent: | ||
pass | ||
|
||
|
@@ -396,6 +402,8 @@ def foo(): | |
def test_event_export_unused_function(make_input_bundle): | ||
# test events in unused functions are not exported | ||
lib1 = """ | ||
phony: uint32 | ||
|
||
event MyEvent: | ||
pass | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -37,6 +37,7 @@ | |
check_modifiability, | ||
get_exact_type_from_node, | ||
get_expr_info, | ||
is_stateless, | ||
) | ||
from vyper.semantics.data_locations import DataLocation | ||
from vyper.semantics.namespace import Namespace, get_namespace, override_global_namespace | ||
|
@@ -409,6 +410,10 @@ def visit_InitializesDecl(self, node): | |
module_info = get_expr_info(module_ref).module_info | ||
if module_info is None: | ||
raise StructureException("Not a module!", module_ref) | ||
if is_stateless(module_info.module_node): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe should we also have this restriction on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry, missed the ping i think that makes sense - |
||
raise StructureException( | ||
f"Cannot initialize a stateless module {module_info.alias}!", module_ref | ||
) | ||
|
||
used_modules = {i.module_t: i for i in module_info.module_t.used_modules} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -736,3 +736,19 @@ def validate_kwargs(node: vy_ast.Call, members: dict[str, VyperType], typeclass: | |
msg = f"{typeclass} instantiation missing fields:" | ||
msg += f" {', '.join(list(missing))}" | ||
raise InstantiationException(msg, node) | ||
|
||
|
||
def is_stateless(module: vy_ast.Module): | ||
""" | ||
Determine whether a module is stateless by examining its top-level declarations. | ||
A module has state if it contains storage variables, transient variables, or | ||
immutables, or if it includes a "uses" or "initializes" declaration. | ||
""" | ||
for i in module.body: | ||
if isinstance(i, (vy_ast.InitializesDecl, vy_ast.UsesDecl)): | ||
return False | ||
if isinstance(i, vy_ast.VariableDecl) and not i.is_constant: | ||
return False | ||
if isinstance(i, vy_ast.FunctionDef) and i.name == "__init__": | ||
return False | ||
return True | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. i think this belongs better on There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, moved it. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let's please add a comment here that we're testing the initialization and how it relates to state