From 80b3e2b0d9a0e5ccb1dfc6d3de8ae84050ca937e Mon Sep 17 00:00:00 2001 From: David Peter Date: Wed, 9 Apr 2025 12:33:11 +0200 Subject: [PATCH] [red-knot] Completely hide unreachable symbols --- .../resources/mdtest/terminal_statements.md | 2 +- .../resources/mdtest/unreachable.md | 6 +-- crates/red_knot_python_semantic/src/symbol.rs | 47 ------------------- 3 files changed, 3 insertions(+), 52 deletions(-) diff --git a/crates/red_knot_python_semantic/resources/mdtest/terminal_statements.md b/crates/red_knot_python_semantic/resources/mdtest/terminal_statements.md index 016ab3d655..ba04ec4388 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/terminal_statements.md +++ b/crates/red_knot_python_semantic/resources/mdtest/terminal_statements.md @@ -654,7 +654,7 @@ def f(cond: bool) -> str: reveal_type(x) # revealed: Literal["before"] return "a" x = "after-return" - reveal_type(x) # revealed: Never + reveal_type(x) # revealed: Unknown else: x = "else" return reveal_type(x) # revealed: Literal["else"] diff --git a/crates/red_knot_python_semantic/resources/mdtest/unreachable.md b/crates/red_knot_python_semantic/resources/mdtest/unreachable.md index 9b185aee7a..644e51a242 100644 --- a/crates/red_knot_python_semantic/resources/mdtest/unreachable.md +++ b/crates/red_knot_python_semantic/resources/mdtest/unreachable.md @@ -244,6 +244,8 @@ def outer(): x = 1 def inner(): + # TODO + # error: [unresolved-reference] reveal_type(x) # revealed: Unknown while True: pass @@ -443,12 +445,8 @@ def _(): class C: ... return - # TODO - # error: [invalid-type-form] "Variable of type `Never` is not allowed in a type expression" c: C = C() - # TODO - # error: [invalid-base] "Invalid class base with type `Never` (all bases must be a class, `Any`, `Unknown` or `Todo`)" class Sub(C): ... ``` diff --git a/crates/red_knot_python_semantic/src/symbol.rs b/crates/red_knot_python_semantic/src/symbol.rs index 08c100486e..518470a771 100644 --- a/crates/red_knot_python_semantic/src/symbol.rs +++ b/crates/red_knot_python_semantic/src/symbol.rs @@ -679,53 +679,6 @@ fn symbol_from_bindings_impl<'db>( visibility_constraints.evaluate(db, predicates, visibility_constraint); if static_visibility.is_always_false() { - // We found a binding that we have statically determined to not be visible from - // the use of the symbol that we are investigating. There are three interesting - // cases to consider: - // - // ```py - // def f1(): - // if False: - // x = 1 - // use(x) - // - // def f2(): - // y = 1 - // return - // use(y) - // - // def f3(flag: bool): - // z = 1 - // if flag: - // z = 2 - // return - // use(z) - // ``` - // - // In the first case, there is a single binding for `x`, and due to the statically - // known `False` condition, it is not visible at the use of `x`. However, we *can* - // see/reach the start of the scope from `use(x)`. This means that `x` is unbound - // and we should return `None`. - // - // In the second case, `y` is also not visible at the use of `y`, but here, we can - // not see/reach the start of the scope. There is only one path of control flow, - // and it passes through that binding of `y` (which we can not see). This implies - // that we are in an unreachable section of code. We return `Never` in order to - // silence the `unresolve-reference` diagnostic that would otherwise be emitted at - // the use of `y`. - // - // In the third case, we have two bindings for `z`. The first one is visible, so we - // consider the case that we now encounter the second binding `z = 2`, which is not - // visible due to the early return. We *also* can not see the start of the scope - // from `use(z)` because both paths of control flow pass through a binding of `z`. - // The `z = 1` binding is visible, and so we are *not* in an unreachable section of - // code. However, it is still okay to return `Never` in this case, because we will - // union the types of all bindings, and `Never` will be eliminated automatically. - - if unbound_visibility.is_always_false() { - // The scope-start is not visible - return Some(Type::Never); - } return None; }