Skip to content

Commit

Permalink
fix[lang]: typecheck hashmap indexes with folding (#4007)
Browse files Browse the repository at this point in the history
this commit fixes a bug in typechecking of folded values for hashmap
indexes. there was previously a carveout for subscript typechecking for
arrays; however, it should not apply to hashmap indexes.

this was introduced as an edge case resulting from the semantic changes
in 56c4c9d. a related fix was applied in 75fb059, but it did not
handle hashmaps.
  • Loading branch information
DanielSchiavini authored May 9, 2024
1 parent 4c66c8c commit 54616d6
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 6 deletions.
35 changes: 35 additions & 0 deletions tests/functional/codegen/storage_variables/test_getters.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
import pytest

from vyper import compile_code
from vyper.exceptions import OverflowException, TypeMismatch


def test_state_accessor(get_contract):
state_accessor = """
y: HashMap[int128, int128]
Expand Down Expand Up @@ -98,3 +104,32 @@ def __init__():
if item["type"] == "constructor":
continue
assert item["stateMutability"] == "view"


@pytest.mark.parametrize(
"typ,index,expected_error",
[
("uint256", "-1", TypeMismatch),
("uint256", "0-1", TypeMismatch),
("uint256", "0-1+1", TypeMismatch),
("uint256", "2**256", OverflowException),
("uint256", "2**256 // 2", OverflowException),
("uint256", "2 * 2**255", OverflowException),
("int256", "-2**255", TypeMismatch),
("int256", "-2**256", OverflowException),
("int256", "2**255", TypeMismatch),
("int256", "2**256 - 5", OverflowException),
("int256", "2 * 2**254", TypeMismatch),
("int8", "*".join(["2"] * 7), TypeMismatch),
],
)
def test_hashmap_index_checks(typ, index, expected_error):
code = f"""
m: HashMap[{typ}, uint256]
@external
def foo():
self.m[{index}] = 2
"""
with pytest.raises(expected_error):
compile_code(code)
12 changes: 6 additions & 6 deletions vyper/semantics/analysis/local.py
Original file line number Diff line number Diff line change
Expand Up @@ -914,14 +914,14 @@ def visit_Subscript(self, node: vy_ast.Subscript, typ: VyperType) -> None:
else:
base_type = get_exact_type_from_node(node.value)

# get the correct type for the index, it might
# not be exactly base_type.key_type
# note: index_type is validated in types_from_Subscript
index_types = get_possible_types_from_node(node.slice)
index_type = index_types.pop()
if isinstance(base_type, HashMapT):
index_type = base_type.key_type
else:
# Arrays allow most int types as index: Take the least specific
index_type = get_possible_types_from_node(node.slice).pop()

self.visit(node.slice, index_type)
self.visit(node.value, base_type)
self.visit(node.slice, index_type)

def visit_Tuple(self, node: vy_ast.Tuple, typ: VyperType) -> None:
if isinstance(typ, TYPE_T):
Expand Down

0 comments on commit 54616d6

Please sign in to comment.