Skip to content
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

Fixes issue #336 #371

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions examples/smart_contracts/assert_foo_none.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!opshin
from opshin.prelude import *


def foo() -> None:
return None


def validator(datum: int, redeemer: int, context: ScriptContext) -> None:
assert foo(), f"Always fails!"
6 changes: 6 additions & 0 deletions examples/smart_contracts/assert_none.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#!opshin
from opshin.prelude import *


def validator(datum: int, redeemer: int, context: ScriptContext) -> None:
assert None, f"Always fails!"
18 changes: 18 additions & 0 deletions opshin/type_inference.py
Original file line number Diff line number Diff line change
Expand Up @@ -838,6 +838,24 @@ def visit_Attribute(self, node: Attribute) -> TypedAttribute:
def visit_Assert(self, node: Assert) -> TypedAssert:
ta = copy(node)
ta.test = self.visit(node.test)
try:
warn_assert_msg = f" (see assert with message '{node.msg.values[0].value}')"
except AttributeError as err:
warn_assert_msg = ""
nielstron marked this conversation as resolved.
Show resolved Hide resolved
if isinstance(ta.test.args[0], Constant) and ta.test.args[0].value is None:
Copy link
Contributor

@nielstron nielstron Apr 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I understand correctly you are trying to cover two cases here: either the line is assert None or the line is assert foo() where foo returns None.

I think it is good to explicitly cover the foo case and provide a more specific error message for it. However the handling would be more generic if after that check we check for the type of the whole expression (I.e. ta.test.args[0].typ or ta.test.typ)

OPSHIN_LOGGER.warning(
"Asserting `None'"
+ warn_assert_msg
+ " is equivalent to asserting False, which always fails."
)
nielstron marked this conversation as resolved.
Show resolved Hide resolved
if isinstance(ta.test.args[0], Call) and isinstance(
ta.test.args[0].typ.typ, UnitType
):
OPSHIN_LOGGER.warning(
"Asserting `None'"
+ warn_assert_msg
+ " is likely to stem from a procedure already doing internal assertions and returning `None'. Asserting this is equivalent to asserting False, which always fails (likely unintended)."
)
assert (
ta.test.typ == BoolInstanceType
nielstron marked this conversation as resolved.
Show resolved Hide resolved
), "Assertions must result in a boolean type"
nielstron marked this conversation as resolved.
Show resolved Hide resolved
Expand Down