Skip to content

Conversation

@A5rocks
Copy link
Collaborator

@A5rocks A5rocks commented Nov 23, 2025

Fixes #20283

This is a bit gross, but I'm not sure how to better do this. The problem is that we look up class attributes before looking at locals, but then put the type vars in a new locals scope. I guess one idea would be to define the typevars at usage time? But this is less of a change.

@github-actions
Copy link
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

Copy link
Collaborator

@sterliakov sterliakov left a comment

Choose a reason for hiding this comment

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

Nice one! This part definitely should not use lookup, we are only interested in locals, and (except for one bad corner case) only in the most recent locals entry. Traversing further is only needed when we have

class Foo[T]:
    class Bar[T]:  # Error here, but typevar is still needed
        ...


def is_defined_type_param(self, name: str) -> bool:
def get_defined_type_param(self, name: str) -> TypeVarLikeExpr | None:
for names in self.locals:
Copy link
Collaborator

@sterliakov sterliakov Nov 26, 2025

Choose a reason for hiding this comment

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

Ough, I spelled that out but didn't realize that this goes in the wrong direction (?). We are typically interested in the most recent locals frame, so shouldn't this be

Suggested change
for names in self.locals:
for names in reversed(self.locals):

? It didn't matter when we only requested a boolean "is defined" result, but now could potentially resolve to a wrong symbol. I don't have a testcase for that, but anyway the variable will normally be found in the most recent local frame, so checking it first makes more sense? Upd: no, it cannot resolve to the wrong symbol, we only accept type variables, and type param redefinitions are never added to symtable, but maybe it's still better to avoid the unnecessary work? reversed is fast

Comment on lines 1856 to 1858
if names is None:
continue
if name in names:
Copy link
Collaborator

Choose a reason for hiding this comment

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

And just to save a bit on branching,

Suggested change
if names is None:
continue
if name in names:
if names is not None and name in names:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Assertion failure crash: assert isinstance(node.node, TypeVarLikeExpr)

2 participants