Skip to content

Commit

Permalink
fix: improve error message with invalid String() comparisons
Browse files Browse the repository at this point in the history
  • Loading branch information
achidlow committed Apr 15, 2024
1 parent 255c051 commit f340c86
Show file tree
Hide file tree
Showing 3 changed files with 17 additions and 10 deletions.
9 changes: 6 additions & 3 deletions src/puya/awst_build/eb/string.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
)
from puya.awst_build.eb.bytes_backed import BytesBackedClassExpressionBuilder
from puya.awst_build.eb.var_factory import var_expression
from puya.awst_build.utils import expect_operand_wtype
from puya.awst_build.utils import convert_literal_to_expr, expect_operand_wtype
from puya.errors import CodeError

if typing.TYPE_CHECKING:
Expand Down Expand Up @@ -132,8 +132,11 @@ def binary_op(
def compare(
self, other: ExpressionBuilder | Literal, op: BuilderComparisonOp, location: SourceLocation
) -> ExpressionBuilder:
other_expr = expect_operand_wtype(other, self.wtype)

other_expr = convert_literal_to_expr(other, self.wtype)
if other_expr.wtype == self.wtype:
pass
else:
return NotImplemented
cmp = BytesComparisonExpression(
source_location=location,
lhs=self.expr,
Expand Down
6 changes: 1 addition & 5 deletions src/puya/awst_build/subroutine.py
Original file line number Diff line number Diff line change
Expand Up @@ -1079,10 +1079,6 @@ def visit_comparison_expr(self, expr: mypy.nodes.ComparisonExpr) -> ExpressionBu
# type signatures that should be possible, and we can always know it's value at
# compile time, but it would always result in a constant ...

expr_wtype = self.context.mypy_expr_node_type(expr)
if expr_wtype is not wtypes.bool_wtype:
raise CodeError("Result of comparison must be a boolean type", expr_loc)

operands = [o.accept(self) for o in expr.operands]
operands[1:-1] = [temporary_assignment_if_required(operand) for operand in operands[1:-1]]

Expand Down Expand Up @@ -1132,7 +1128,7 @@ def _build_compare(
op = BuilderComparisonOp(invert_ordered_binary_op(operator))
result = rhs.compare(other=lhs, op=op, location=cmp_loc)
if result is NotImplemented:
raise CodeError(f"Unsupported comparison {operator} between types", cmp_loc)
raise CodeError(f"Unsupported comparison {operator!r} between types", cmp_loc)
return result.rvalue()

def visit_int_expr(self, expr: mypy.nodes.IntExpr) -> Literal:
Expand Down
12 changes: 10 additions & 2 deletions tests/test_expected_output/expected_errors.test
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ def typing_interactions() -> None:
typing.assert_type(UInt64(1), UInt64) ## W: use of typing.assert_type has no effect on compilation \
## W: expression result is ignored

assert typing.cast(Bytes, Account(SOME_ADDRESS)) == Bytes.from_base64(SOME_ADDRESS_PADDED) ## E: Unsupported comparison == between types \
## W: use of typing.cast, output may be invalid or insecure TEAL
assert typing.cast(Bytes, Account(SOME_ADDRESS)) == Bytes.from_base64(SOME_ADDRESS_PADDED) ## W: use of typing.cast, output may be invalid or insecure TEAL \
## E: Unsupported comparison '==' between types

## case: test_unreachable

Expand Down Expand Up @@ -225,3 +225,11 @@ def invalid_constructor_args() -> None:
# the next check is just to make sure we didn't throw on the line above

h = 1 ## E: A Python literal is not valid at this location


## case: unsupported_type_comparisons
from algopy import *

@subroutine
def compare_biguint_string() -> None:
assert BigUInt() != String() # type: ignore[operator,misc] ## E: Unsupported comparison '!=' between types

0 comments on commit f340c86

Please sign in to comment.