Skip to content

Commit

Permalink
fix: indexing into literal list (#3378)
Browse files Browse the repository at this point in the history
a regression was introduced in 046ea16 whereby the following contract
used to compile but now panics:
```
@external
def foo():
    f: uint256 = 1
    a:bool = 1 == [1,2,4][f] + -1
```
```
AssertionError: unreachable, uint256 != int8
```

the issue was that, previously, different integer types in vyper were
represented by different types in python. however, now all integer types
inherit from `IntegerT`. this commit fixes the issue by using the
correct (and hygienically appropriate) `type.compare_type(other)`,
instead of checking python-level type equality.

the lark grammar also needed to be changed to enable accessing a literal
list directly.

---------

Co-authored-by: Charles Cooper <cooper.charles.m@gmail.com>
  • Loading branch information
tserg and charles-cooper authored May 13, 2023
1 parent 8c8124b commit 97ff017
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 3 deletions.
12 changes: 12 additions & 0 deletions tests/parser/types/test_lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -676,6 +676,18 @@ def ix(i: uint256) -> {type}:
assert_tx_failed(lambda: c.ix(len(value) + 1))


def test_nested_constant_list_accessor(get_contract):
code = """
@external
def foo() -> bool:
f: uint256 = 1
a: bool = 1 == [1,2,4][f] + -1
return a
"""
c = get_contract(code)
assert c.foo() is True


# Would be nice to put this somewhere accessible, like in vyper.types or something
integer_types = ["uint8", "int128", "int256", "uint256"]

Expand Down
2 changes: 1 addition & 1 deletion vyper/ast/grammar.lark
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ _expr: operation
| dict
| ternary

get_item: variable_access "[" _expr "]"
get_item: (variable_access | list) "[" _expr "]"
get_attr: variable_access "." NAME
call: variable_access "(" [arguments] ")"
?variable_access: NAME -> get_var
Expand Down
8 changes: 6 additions & 2 deletions vyper/semantics/analysis/annotation.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from vyper import ast as vy_ast
from vyper.exceptions import StructureException
from vyper.exceptions import StructureException, TypeCheckFailure
from vyper.semantics.analysis.utils import (
get_common_types,
get_exact_type_from_node,
Expand Down Expand Up @@ -231,9 +231,13 @@ def visit_Subscript(self, node, type_):

elif type_ is not None and len(possible_base_types) > 1:
for possible_type in possible_base_types:
if isinstance(possible_type.value_type, type(type_)):
if type_.compare_type(possible_type.value_type):
base_type = possible_type
break
else:
# this should have been caught in
# `get_possible_types_from_node` but wasn't.
raise TypeCheckFailure(f"Expected {type_} but it is not a possible type", node)

else:
base_type = get_exact_type_from_node(node.value)
Expand Down

0 comments on commit 97ff017

Please sign in to comment.