[ty] fix incorrect lazy scope narrowing (#19744)

## Summary

This is a follow-up to #19321.

Narrowing constraints introduced in a class scope were not applied even
when they can be applied in lazy nested scopes. This PR fixes so that
they are now applied.
Conversely, there were cases where narrowing constraints were being
applied in places where they should not, so it is also fixed.

## Test Plan

Some TODOs in `narrow/conditionals/nested.md` are now work correctly.
This commit is contained in:
Shunsuke Shibayama 2025-08-05 12:32:08 +09:00 committed by GitHub
parent 64bcc8db2f
commit 351121c5c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 12 additions and 5 deletions

View file

@ -356,7 +356,9 @@ impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> {
for nested_symbol in self.place_tables[popped_scope_id].symbols() {
// For the same reason, symbols declared as nonlocal or global are not recorded.
// Also, if the enclosing scope allows its members to be modified from elsewhere, the snapshot will not be recorded.
if self.scopes[enclosing_scope_id].visibility().is_public() {
// (In the case of class scopes, class variables can be modified from elsewhere, but this has no effect in nested scopes,
// as class variables are not visible to them)
if self.scopes[enclosing_scope_id].kind().is_module() {
continue;
}

View file

@ -251,6 +251,10 @@ impl ScopeKind {
matches!(self, ScopeKind::Class)
}
pub(crate) const fn is_module(self) -> bool {
matches!(self, ScopeKind::Module)
}
pub(crate) const fn is_type_parameter(self) -> bool {
matches!(self, ScopeKind::Annotation | ScopeKind::TypeAlias)
}

View file

@ -36,6 +36,7 @@ bitflags! {
const IS_DECLARED = 1 << 2;
const MARKED_GLOBAL = 1 << 3;
const MARKED_NONLOCAL = 1 << 4;
/// true if the symbol is assigned more than once, or if it is assigned even though it is already in use
const IS_REASSIGNED = 1 << 5;
}
}
@ -92,7 +93,7 @@ impl Symbol {
}
pub(super) fn mark_bound(&mut self) {
if self.is_bound() {
if self.is_bound() || self.is_used() {
self.insert_flags(SymbolFlags::IS_REASSIGNED);
}