Skip to content

fix[ux]: typechecking for loop annotation of list variable#4550

Merged
charles-cooper merged 5 commits intovyperlang:masterfrom
tserg:fix/for_typecheck
Apr 7, 2025
Merged

fix[ux]: typechecking for loop annotation of list variable#4550
charles-cooper merged 5 commits intovyperlang:masterfrom
tserg:fix/for_typecheck

Conversation

@tserg
Copy link
Copy Markdown
Contributor

@tserg tserg commented Mar 31, 2025

What I did

Fix #4549

How I did it

Add a check that the type derived for a variable list matches the iterator type specified in the for loop annotation.

How to verify it

See new tests.

Commit message

This commit fixes a compiler panic for `for` loops by properly catching
type mismatch between the iterator and target during semantic analysis

Description for the changelog

Typechecking for loop annotation of variable list

Cute Animal Picture

Put a link to a cute animal picture inside the parenthesis-->

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 92.57%. Comparing base (cef84e8) to head (579362a).
Report is 94 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #4550      +/-   ##
==========================================
+ Coverage   92.35%   92.57%   +0.22%     
==========================================
  Files         123      123              
  Lines       17543    17471      -72     
  Branches     2961     2951      -10     
==========================================
- Hits        16201    16173      -28     
+ Misses        938      894      -44     
  Partials      404      404              

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@tserg tserg requested a review from charles-cooper March 31, 2025 13:59
if not isinstance(iter_type, (DArrayT, SArrayT)):
raise InvalidType("Not an iterable type", iter_node)

if not target_type.compare_type(iter_type.value_type):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what happens if we don't move this into the try/except block?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would still work, just that it is a redundant check in the case of a literal list - but I think this is acceptable because your suggestion makes the code more readable.

Copy link
Copy Markdown
Member

@charles-cooper charles-cooper left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks reasonable. @cyberthirst please take a look

@cyberthirst
Copy link
Copy Markdown
Collaborator

possibly another for related bug:

def foo():
    a: DynArray[DynArray[uint256, 10], 10] = []
    for i: DynArray[uint256, 10] in a:
        for j: i in i:
            pass
vyper.exceptions.CompilerPanic: Not a type: VarInfo(typ=DynArray[uint256, 10], location=<DataLocation.UNSET: 'unset'>, modifiability=<Modifiability.RUNTIME_CONSTANT: 'runtime_constant'>, is_public=False, decl_node=vyper.ast.nodes.AnnAssign:
---> 1 def foo():
-------^
     2     a: DynArray[DynArray[uint256, 10], 10] = [])

  contract "tests/custom/test.vy:4", function "foo", line 4:15 
       3     for i: DynArray[uint256, 10] in a:
  ---> 4         for j: i in i:
  ----------------------^
       5             pass


This is an unhandled internal compiler error. Please create an issue on Github to notify the developers!
https://github.com/vyperlang/vyper/issues/new?template=bug.md

@cyberthirst
Copy link
Copy Markdown
Collaborator

maybe we could improve the suggestion here?

def foo():
    for i: DynArray[uint256, 10] in [[[]]][0]:
        for j: uint256 in i:
            pass
vyper.exceptions.TypeMismatch: Expected DynArray[uint256, 10][1] but literal can only be cast as DynArray[DynArray[GenericTypeAcceptor(<class 'vyper.semantics.types.bytestrings.BytesT'>), 1], 1] or DynArray[DynArray[uint96, 1], 1].

  contract "tests/custom/test.vy:2", function "foo", line 2:36 
       1 def foo():
  ---> 2     for i: DynArray[uint256, 10] in [[[]]][0]:
  -------------------------------------------^
       3         for j: uint256 in i:

@cyberthirst
Copy link
Copy Markdown
Collaborator

this fails on an assertion error:

def foo():
    a: DynArray[DynArray[uint256, 10], 10] = []
    for i: DynArray[uint256, 10] in [k for k in a]:
        for j: uint256 in i:
            pass
AssertionError

@charles-cooper
Copy link
Copy Markdown
Member

@cyberthirst these seem out of scope, right? like they were pre-existing errors prior to this PR?

@cyberthirst
Copy link
Copy Markdown
Collaborator

@cyberthirst these seem out of scope, right? like they were pre-existing errors prior to this PR?

yeah, I think we should lift those to a separate issue/PR


if not target_type.compare_type(iter_type.value_type):
raise TypeMismatch(
f"Iterator has a type of {target_type} but iterable has a type of {iter_type}",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe it would be better to refer to the value type inside the iterable?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also, I think it would be better to point to the iterator instead of the iterable

because most likely the iterable is the correct thing, but the iterator is incorrectly annotated

so like - "TypeMismatch(Expected type of {iter_type.value_type}..." and then instead of using iter_node use the iterator node?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! I had to pass target_node to _analyse_list_iter in order to raise the iterator node in the exception, which makes the function signature for _analyse_list_iter different from _analyse_range_iter (shouldn't be an issue?).

@cyberthirst
Copy link
Copy Markdown
Collaborator

this should also close #3988 which should be the original issue where this bug was described

@cyberthirst
Copy link
Copy Markdown
Collaborator

this fails on an assertion error:

def foo():
    a: DynArray[DynArray[uint256, 10], 10] = []
    for i: DynArray[uint256, 10] in [k for k in a]:
        for j: uint256 in i:
            pass
AssertionError

opened a new issue: #4557

@cyberthirst
Copy link
Copy Markdown
Collaborator

maybe we could improve the suggestion here?

def foo():
    for i: DynArray[uint256, 10] in [[[]]][0]:
        for j: uint256 in i:
            pass
vyper.exceptions.TypeMismatch: Expected DynArray[uint256, 10][1] but literal can only be cast as DynArray[DynArray[GenericTypeAcceptor(<class 'vyper.semantics.types.bytestrings.BytesT'>), 1], 1] or DynArray[DynArray[uint96, 1], 1].

 contract "tests/custom/test.vy:2", function "foo", line 2:36 
      1 def foo():
 ---> 2     for i: DynArray[uint256, 10] in [[[]]][0]:
 -------------------------------------------^
      3         for j: uint256 in i:

opened a new issue: #4558

@cyberthirst
Copy link
Copy Markdown
Collaborator

vyper.exceptions.CompilerPanic: Not a type:

opened a new issue: #4559

@charles-cooper charles-cooper changed the title fix[ux]: typechecking for loop annotation of variable list fix[ux]: typechecking for loop annotation of list variable Apr 6, 2025
@charles-cooper charles-cooper merged commit ded0394 into vyperlang:master Apr 7, 2025
163 checks passed
@tserg tserg deleted the fix/for_typecheck branch April 8, 2025 04:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

compiler panic when type checking struct iterator

3 participants