diff --git a/tests/parser/types/test_lists.py b/tests/parser/types/test_lists.py index a9e09a12eb..6ef40086ca 100644 --- a/tests/parser/types/test_lists.py +++ b/tests/parser/types/test_lists.py @@ -212,6 +212,23 @@ def test_array(x: int128, y: int128, z: int128, w: int128) -> int128: def test_array_negative_accessor(get_contract_with_gas_estimation, assert_compile_failed): + array_negative_accessor = """ +FOO: constant(int128) = -1 + +@external +def test_array(x: int128, y: int128, z: int128, w: int128) -> int128: + a: int128[4] = [0, 0, 0, 0] + a[0] = x + a[1] = y + a[2] = z + a[3] = w + return a[-4] * 1000 + a[-3] * 100 + a[-2] * 10 + a[FOO] + """ + + assert_compile_failed( + lambda: get_contract_with_gas_estimation(array_negative_accessor), ArrayIndexException + ) + array_negative_accessor = """ @external def test_array(x: int128, y: int128, z: int128, w: int128) -> int128: diff --git a/vyper/semantics/types/subscriptable.py b/vyper/semantics/types/subscriptable.py index 742fc5aeeb..3faaf54509 100644 --- a/vyper/semantics/types/subscriptable.py +++ b/vyper/semantics/types/subscriptable.py @@ -129,10 +129,11 @@ def validate_index_type(self, node): # TODO break this cycle from vyper.semantics.analysis.utils import validate_expected_type - if isinstance(node, vy_ast.Int): - if node.value < 0: + index_val = prefold(node) + if isinstance(index_val, int): + if index_val < 0: raise ArrayIndexException("Vyper does not support negative indexing", node) - if node.value >= self.length: + if index_val >= self.length: raise ArrayIndexException("Index out of range", node) validate_expected_type(node, IntegerT.any()) diff --git a/vyper/semantics/types/utils.py b/vyper/semantics/types/utils.py index eae5e1a0fc..5cde0530a7 100644 --- a/vyper/semantics/types/utils.py +++ b/vyper/semantics/types/utils.py @@ -1,12 +1,6 @@ from vyper import ast as vy_ast from vyper.ast.pre_typecheck import prefold -from vyper.exceptions import ( - ArrayIndexException, - InstantiationException, - InvalidType, - StructureException, - UnknownType, -) +from vyper.exceptions import ArrayIndexException, InstantiationException, InvalidType, UnknownType from vyper.semantics.analysis.levenshtein_utils import get_levenshtein_error_suggestions from vyper.semantics.data_locations import DataLocation from vyper.semantics.namespace import get_namespace @@ -146,22 +140,9 @@ def get_index_value(node: vy_ast.Index) -> int: int Literal integer value. """ - # this is imported to improve error messages - # TODO: revisit this! - from vyper.semantics.analysis.utils import get_possible_types_from_node - val = prefold(node.value) if not isinstance(val, int): - if hasattr(node, "value"): - # even though the subscript is an invalid type, first check if it's a valid _something_ - # this gives a more accurate error in case of e.g. a typo in a constant variable name - try: - get_possible_types_from_node(node.value) - except StructureException: - # StructureException is a very broad error, better to raise InvalidType in this case - pass - raise InvalidType("Subscript must be a literal integer", node) if val <= 0: