-
Notifications
You must be signed in to change notification settings - Fork 1.6k
[ty] fix global symbol lookup from eager scopes #21317
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
Diagnostic diff on typing conformance testsNo changes detected when running ty on typing conformance tests ✅ |
|
7cc7ce1 to
fb1bc92
Compare
fb1bc92 to
9f904d1
Compare
|
https://github.com/astral-sh/ruff/actions/runs/19173434027/job/54811898939?pr=21317 |
| )); | ||
| // Reaching here means that no bindings are found in any scope. | ||
| // Since `explicit_global_symbol` may return a cycle initial value, we return `Place::Undefined` here. | ||
| return Place::Undefined.into(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If returning here is correct, then pushing the constraint into constraint_keys immediately above this cannot have any effect, so should we remove that as well? (Removing it doesn't seem to fail any test.)
Why do we hit the FoundConstraint case in this situation in the first place? It's not clear to me where the "constraint" comes from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since place includes member as well as symbol, narrowing constraints must still be tracked even if there are no bindings, for example:
from typing import Literal
class Foo:
bar: Literal[1, 2]
foo = Foo()
if foo.bar == 1:
# `foo.bar` has no explicit binding, but the constraint is `foo.bar == 1`
[reveal_type(foo.bar) for _ in ()] # Literal[1]But as you pointed out, there was no need to add the constraint to constraint_keys here, because we already added it when iterating over ancestor_scopes above. Fixed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A more fundamental issue is that the global scope should be excluded from the scopes of enclosing scope lookup.
See the comments below.
|
I found another example of a too-many-cycle-iteration panic. if C:
class C[_T](C): ...The panic occurred because |
|
I don't have time right now (I originally found this bug while working on #20566), but I think the logic in |
| @@ -1,13 +1,7 @@ | |||
| # Documentation of two fuzzer panics involving comprehensions | |||
| # Regression test for https://github.com/astral-sh/ruff/pull/20962 | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you say more about why you converted this file to a corpus test? It's not clear to me why that would be preferred or required.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The previous test asserted that we panicked; the new test asserts that the snippet does not cause us to panic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess it could have stayed as an mdtest, but corpus tests are what we usually use when all we care about is checking that we didn't panic; it makes sense to me
| for (enclosing_scope_file_id, _) in self.index.ancestor_scopes(file_scope_id).skip(1) { | ||
| // If the current enclosing scope is global, no place lookup is performed here, | ||
| // instead falling back to the module's explicit global lookup below. | ||
| if enclosing_scope_file_id == FileScopeId::global() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit
| if enclosing_scope_file_id == FileScopeId::global() { | |
| if enclosing_scope_file_id.is_global() { |
Summary
cf. #20962
In the following code,
fooin the comprehension was not reported as unresolved:In fact, this is a more serious bug than it looks: for
foo,explicit_global_symbolis called, causing a symbol that should actually beUndefinedto be reported as being of typeDivergent.This PR fixes this bug. As a result, the code in
mdtest/regression/pr_20962_comprehension_panics.mdno longer panics.Test Plan
corpus\cyclic_symbol_in_comprehension.pyis added.New tests are added in
mdtest/comprehensions/basic.md.