Skip to content

Commit

Permalink
Fix a bug regarding nested scopes
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexWaygood committed Sep 12, 2024
1 parent ab58952 commit 8c9e02b
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 0 deletions.
5 changes: 5 additions & 0 deletions crates/red_knot_python_semantic/src/semantic_index/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,12 @@ impl<'db> SemanticIndexBuilder<'db> {
parent,
kind: node.scope_kind(),
descendents: children_start..children_start,
contained_inside_try_block: self.visiting_try_block,
};

// All scopes start off as not visiting a `try` block
self.visiting_try_block = false;

let file_scope_id = self.scopes.push(scope);
self.symbol_tables.push(SymbolTableBuilder::new());
self.use_def_maps.push(UseDefMapBuilder::new());
Expand Down Expand Up @@ -141,6 +145,7 @@ impl<'db> SemanticIndexBuilder<'db> {
let children_end = self.scopes.next_index();
let scope = &mut self.scopes[id];
scope.descendents = scope.descendents.start..children_end;
self.visiting_try_block = scope.contained_inside_try_block();
id
}

Expand Down
6 changes: 6 additions & 0 deletions crates/red_knot_python_semantic/src/semantic_index/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ pub struct Scope {
pub(super) parent: Option<FileScopeId>,
pub(super) kind: ScopeKind,
pub(super) descendents: Range<FileScopeId>,
pub(super) contained_inside_try_block: bool,
}

impl Scope {
Expand All @@ -174,6 +175,11 @@ impl Scope {
pub fn kind(&self) -> ScopeKind {
self.kind
}

/// Whether this scope is a top-level expression/statement inside a `try` block
pub const fn contained_inside_try_block(&self) -> bool {
self.contained_inside_try_block
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
Expand Down
58 changes: 58 additions & 0 deletions crates/red_knot_python_semantic/src/types/infer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4970,6 +4970,64 @@ mod tests {
Ok(())
}

#[test]
fn inner_try_blocks_inside_separate_scopes_not_tracked_by_outer_block() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_dedented(
"src/a.py",
"
try:
x = 1
def foo():
try:
x = 2
x = 3
except:
x = 4
except:
pass
",
)?;

assert_file_diagnostics(&db, "src/a.py", &[]);
assert_public_ty(&db, "src/a.py", "x", "Unbound | Literal[1]");
assert_scope_ty(&db, "src/a.py", &["foo"], "x", "Literal[3, 4]");

Ok(())
}

#[test]
fn inner_try_blocks_inside_class_scopes_not_tracked_by_outer_block() -> anyhow::Result<()> {
let mut db = setup_db();

db.write_dedented(
"src/a.py",
"
try:
x = 1
class Foo:
try:
x = 2
x = 3
except:
x = 4
except:
pass
",
)?;

assert_file_diagnostics(&db, "src/a.py", &[]);
assert_public_ty(&db, "src/a.py", "x", "Unbound | Literal[1]");
assert_scope_ty(&db, "src/a.py", &["Foo"], "x", "Literal[3, 4]");

Ok(())
}

#[test]
fn basic_comprehension() -> anyhow::Result<()> {
let mut db = setup_db();
Expand Down

0 comments on commit 8c9e02b

Please sign in to comment.