Skip to content

Commit

Permalink
chore: fix loop variable typing (#3571)
Browse files Browse the repository at this point in the history
there is an inconsistency between codegen and typechecking types when a
loop iterates over a literal list.

in this code, although it compiles, during typechecking, `i` is typed as
a `uint8` while `[1,2,3]` is annotated with `int8[3]`

```
@external
def foo():
for i in [1,2,3]:
    a: uint8 = i
```

since the iterator type is always correct, this commit is a chore since
it fixes the discrepancy, but there is no known way to "abuse" the
behavior to get a wrong codegen type.

chainsec june 2023 review 5.15
  • Loading branch information
charles-cooper authored Aug 31, 2023
1 parent 158099b commit c28f14f
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 7 deletions.
4 changes: 1 addition & 3 deletions vyper/codegen/stmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,10 +316,8 @@ def _parse_For_list(self):
with self.context.range_scope():
iter_list = Expr(self.stmt.iter, self.context).ir_node

# override with type inferred at typechecking time
# TODO investigate why stmt.target.type != stmt.iter.type.value_type
target_type = self.stmt.target._metadata["type"]
iter_list.typ.value_type = target_type
assert target_type == iter_list.typ.value_type

# user-supplied name for loop variable
varname = self.stmt.target.id
Expand Down
8 changes: 4 additions & 4 deletions vyper/semantics/analysis/annotation.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,14 +85,14 @@ def visit_Return(self, node):
def visit_For(self, node):
if isinstance(node.iter, (vy_ast.Name, vy_ast.Attribute)):
self.expr_visitor.visit(node.iter)
# typecheck list literal as static array

iter_type = node.target._metadata["type"]
if isinstance(node.iter, vy_ast.List):
value_type = get_common_types(*node.iter.elements).pop()
# typecheck list literal as static array
len_ = len(node.iter.elements)
self.expr_visitor.visit(node.iter, SArrayT(value_type, len_))
self.expr_visitor.visit(node.iter, SArrayT(iter_type, len_))

if isinstance(node.iter, vy_ast.Call) and node.iter.func.id == "range":
iter_type = node.target._metadata["type"]
for a in node.iter.args:
self.expr_visitor.visit(a, iter_type)
for a in node.iter.keywords:
Expand Down

0 comments on commit c28f14f

Please sign in to comment.