diff --git a/crates/ty_python_semantic/resources/mdtest/narrow/conditionals/nested.md b/crates/ty_python_semantic/resources/mdtest/narrow/conditionals/nested.md index 77307c5110..74c1d42a49 100644 --- a/crates/ty_python_semantic/resources/mdtest/narrow/conditionals/nested.md +++ b/crates/ty_python_semantic/resources/mdtest/narrow/conditionals/nested.md @@ -363,11 +363,12 @@ def f(x: str | Literal[1] | None): x = None def _(): + # No narrowing is performed on unresolved references. # error: [unresolved-reference] if x is not None: def _(): if x != 1: - reveal_type(x) # revealed: Never + reveal_type(x) # revealed: None x = None def f(const: str | Literal[1] | None): @@ -375,8 +376,7 @@ def f(const: str | Literal[1] | None): if const is not None: def _(): if const != 1: - # TODO: should be `str` - reveal_type(const) # revealed: str | None + reveal_type(const) # revealed: str class D: if const != 1: diff --git a/crates/ty_python_semantic/src/semantic_index/builder.rs b/crates/ty_python_semantic/src/semantic_index/builder.rs index 9783236902..c545d9868f 100644 --- a/crates/ty_python_semantic/src/semantic_index/builder.rs +++ b/crates/ty_python_semantic/src/semantic_index/builder.rs @@ -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; } diff --git a/crates/ty_python_semantic/src/semantic_index/scope.rs b/crates/ty_python_semantic/src/semantic_index/scope.rs index 89581d9194..29c262ef4c 100644 --- a/crates/ty_python_semantic/src/semantic_index/scope.rs +++ b/crates/ty_python_semantic/src/semantic_index/scope.rs @@ -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) } diff --git a/crates/ty_python_semantic/src/semantic_index/symbol.rs b/crates/ty_python_semantic/src/semantic_index/symbol.rs index a8564ea950..7bf0939bbb 100644 --- a/crates/ty_python_semantic/src/semantic_index/symbol.rs +++ b/crates/ty_python_semantic/src/semantic_index/symbol.rs @@ -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); }