From 96a96ae8e3f456f45b65ba052086c72ac7897172 Mon Sep 17 00:00:00 2001 From: 11happy Date: Fri, 7 Nov 2025 11:32:44 +0530 Subject: [PATCH 1/6] ty: name is parameter and global Signed-off-by: 11happy --- .../diagnostics/semantic_syntax_errors.md | 36 +++ ...er_an\342\200\246_(99bae53daf67ae6e).snap" | 296 ++++++++++++++++++ .../src/semantic_index/builder.rs | 18 +- 3 files changed, 349 insertions(+), 1 deletion(-) create mode 100644 "crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" diff --git a/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md b/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md index e3c830a1e871f..15805503522d2 100644 --- a/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md +++ b/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md @@ -376,3 +376,39 @@ for x in range(42): break # error: [invalid-syntax] continue # error: [invalid-syntax] ``` + +## name is parameter and global + + + +```py +def f1(a): + global a # error: [invalid-syntax] + +def f2(a): + if True: + global a # error: [invalid-syntax] + +def f3(a): + def inner(): + global a # error: [invalid-syntax] + +def f4(a): + try: + global a # error: [invalid-syntax] + except Exception: + pass + +def f5(a): + a = 1 + global a # error: [invalid-syntax] + +def f6(a): + a = 1 + a = 2 + global a # error: [invalid-syntax] + +def f7(a): + class Inner: + global a # fine +``` diff --git "a/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" new file mode 100644 index 0000000000000..8d70e177a408b --- /dev/null +++ "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" @@ -0,0 +1,296 @@ +--- +source: crates/ty_test/src/lib.rs +expression: snapshot +--- +--- +mdtest name: semantic_syntax_errors.md - Semantic syntax error diagnostics - name is parameter and global +mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md +--- + +# Python source files + +## mdtest_snippet.py + +``` + 1 | def f1(a): + 2 | global a # error: [invalid-syntax] + 3 | def f2(a): + 4 | if True: + 5 | global a # error: [invalid-syntax] + 6 | def f3(a): + 7 | def inner(): + 8 | global a # error: [invalid-syntax] + 9 | def f4(a): +10 | try: +11 | global a # error: [invalid-syntax] +12 | except Exception: +13 | pass +14 | def f5(a): +15 | a = 1 +16 | global a # error: [invalid-syntax] +17 | +18 | def f6(a): +19 | a = 1 +20 | a = 2 +21 | global a # error: [invalid-syntax] +22 | +23 | def f7(a): +24 | class Inner: +25 | global a # fine +``` + +# Diagnostics + +``` +error[invalid-syntax]: name `a` is parameter and global + --> src/mdtest_snippet.py:2:12 + | +1 | def f1(a): +2 | global a # error: [invalid-syntax] + | ^ +3 | def f2(a): +4 | if True: + | + +``` + +``` +error[invalid-syntax]: name `a` is used prior to global declaration + --> src/mdtest_snippet.py:2:12 + | +1 | def f1(a): +2 | global a # error: [invalid-syntax] + | ^ +3 | def f2(a): +4 | if True: + | + +``` + +``` +warning[unresolved-global]: Invalid global declaration of `a` + --> src/mdtest_snippet.py:2:12 + | +1 | def f1(a): +2 | global a # error: [invalid-syntax] + | ^ `a` has no declarations or bindings in the global scope +3 | def f2(a): +4 | if True: + | +info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols +info: Consider adding a declaration to the global scope, e.g. `a: int` +info: rule `unresolved-global` is enabled by default + +``` + +``` +error[invalid-syntax]: name `a` is parameter and global + --> src/mdtest_snippet.py:5:16 + | +3 | def f2(a): +4 | if True: +5 | global a # error: [invalid-syntax] + | ^ +6 | def f3(a): +7 | def inner(): + | + +``` + +``` +error[invalid-syntax]: name `a` is used prior to global declaration + --> src/mdtest_snippet.py:5:16 + | +3 | def f2(a): +4 | if True: +5 | global a # error: [invalid-syntax] + | ^ +6 | def f3(a): +7 | def inner(): + | + +``` + +``` +warning[unresolved-global]: Invalid global declaration of `a` + --> src/mdtest_snippet.py:5:16 + | +3 | def f2(a): +4 | if True: +5 | global a # error: [invalid-syntax] + | ^ `a` has no declarations or bindings in the global scope +6 | def f3(a): +7 | def inner(): + | +info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols +info: Consider adding a declaration to the global scope, e.g. `a: int` +info: rule `unresolved-global` is enabled by default + +``` + +``` +warning[unresolved-global]: Invalid global declaration of `a` + --> src/mdtest_snippet.py:8:16 + | + 6 | def f3(a): + 7 | def inner(): + 8 | global a # error: [invalid-syntax] + | ^ `a` has no declarations or bindings in the global scope + 9 | def f4(a): +10 | try: + | +info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols +info: Consider adding a declaration to the global scope, e.g. `a: int` +info: rule `unresolved-global` is enabled by default + +``` + +``` +error[invalid-syntax]: name `a` is parameter and global + --> src/mdtest_snippet.py:11:16 + | + 9 | def f4(a): +10 | try: +11 | global a # error: [invalid-syntax] + | ^ +12 | except Exception: +13 | pass + | + +``` + +``` +error[invalid-syntax]: name `a` is used prior to global declaration + --> src/mdtest_snippet.py:11:16 + | + 9 | def f4(a): +10 | try: +11 | global a # error: [invalid-syntax] + | ^ +12 | except Exception: +13 | pass + | + +``` + +``` +warning[unresolved-global]: Invalid global declaration of `a` + --> src/mdtest_snippet.py:11:16 + | + 9 | def f4(a): +10 | try: +11 | global a # error: [invalid-syntax] + | ^ `a` has no declarations or bindings in the global scope +12 | except Exception: +13 | pass + | +info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols +info: Consider adding a declaration to the global scope, e.g. `a: int` +info: rule `unresolved-global` is enabled by default + +``` + +``` +error[invalid-syntax]: name `a` is parameter and global + --> src/mdtest_snippet.py:16:12 + | +14 | def f5(a): +15 | a = 1 +16 | global a # error: [invalid-syntax] + | ^ +17 | +18 | def f6(a): + | + +``` + +``` +error[invalid-syntax]: name `a` is used prior to global declaration + --> src/mdtest_snippet.py:16:12 + | +14 | def f5(a): +15 | a = 1 +16 | global a # error: [invalid-syntax] + | ^ +17 | +18 | def f6(a): + | + +``` + +``` +warning[unresolved-global]: Invalid global declaration of `a` + --> src/mdtest_snippet.py:16:12 + | +14 | def f5(a): +15 | a = 1 +16 | global a # error: [invalid-syntax] + | ^ `a` has no declarations or bindings in the global scope +17 | +18 | def f6(a): + | +info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols +info: Consider adding a declaration to the global scope, e.g. `a: int` +info: rule `unresolved-global` is enabled by default + +``` + +``` +error[invalid-syntax]: name `a` is parameter and global + --> src/mdtest_snippet.py:21:12 + | +19 | a = 1 +20 | a = 2 +21 | global a # error: [invalid-syntax] + | ^ +22 | +23 | def f7(a): + | + +``` + +``` +error[invalid-syntax]: name `a` is used prior to global declaration + --> src/mdtest_snippet.py:21:12 + | +19 | a = 1 +20 | a = 2 +21 | global a # error: [invalid-syntax] + | ^ +22 | +23 | def f7(a): + | + +``` + +``` +warning[unresolved-global]: Invalid global declaration of `a` + --> src/mdtest_snippet.py:21:12 + | +19 | a = 1 +20 | a = 2 +21 | global a # error: [invalid-syntax] + | ^ `a` has no declarations or bindings in the global scope +22 | +23 | def f7(a): + | +info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols +info: Consider adding a declaration to the global scope, e.g. `a: int` +info: rule `unresolved-global` is enabled by default + +``` + +``` +warning[unresolved-global]: Invalid global declaration of `a` + --> src/mdtest_snippet.py:25:16 + | +23 | def f7(a): +24 | class Inner: +25 | global a # fine + | ^ `a` has no declarations or bindings in the global scope + | +info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols +info: Consider adding a declaration to the global scope, e.g. `a: int` +info: rule `unresolved-global` is enabled by default + +``` diff --git a/crates/ty_python_semantic/src/semantic_index/builder.rs b/crates/ty_python_semantic/src/semantic_index/builder.rs index 6affc11424819..7ae805098e150 100644 --- a/crates/ty_python_semantic/src/semantic_index/builder.rs +++ b/crates/ty_python_semantic/src/semantic_index/builder.rs @@ -2810,7 +2810,23 @@ impl SemanticSyntaxContext for SemanticIndexBuilder<'_, '_> { fn in_loop_context(&self) -> bool { self.current_scope_info().current_loop.is_some() } - fn is_bound_parameter(&self, _name: &str) -> bool { + fn is_bound_parameter(&self, name: &str) -> bool { + for scope_info in self.scope_stack.iter().rev() { + let scope = &self.scopes[scope_info.file_scope_id]; + match scope.node() { + NodeWithScopeKind::Function(func) => { + let parameters = &func.node(self.module).parameters; + return parameters.includes(name); + } + NodeWithScopeKind::Lambda(lambda) => { + if let Some(parameters) = lambda.node(self.module).parameters.as_ref() { + return parameters.includes(name); + } + } + NodeWithScopeKind::Class(_) => return false, + _ => {} + } + } false } } From 3c991d2d1b1d9ade2bc398de1740f87d0d674f89 Mon Sep 17 00:00:00 2001 From: 11happy Date: Fri, 7 Nov 2025 11:46:05 +0530 Subject: [PATCH 2/6] update snapshot Signed-off-by: 11happy --- ...er_an\342\200\246_(99bae53daf67ae6e).snap" | 230 +++++++++--------- 1 file changed, 117 insertions(+), 113 deletions(-) diff --git "a/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" index 8d70e177a408b..296c3e4dc8dec 100644 --- "a/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" +++ "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" @@ -13,30 +13,34 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syn ``` 1 | def f1(a): - 2 | global a # error: [invalid-syntax] - 3 | def f2(a): - 4 | if True: - 5 | global a # error: [invalid-syntax] - 6 | def f3(a): - 7 | def inner(): - 8 | global a # error: [invalid-syntax] - 9 | def f4(a): -10 | try: -11 | global a # error: [invalid-syntax] -12 | except Exception: -13 | pass -14 | def f5(a): -15 | a = 1 -16 | global a # error: [invalid-syntax] + 2 | global a # error: [invalid-syntax] + 3 | + 4 | def f2(a): + 5 | if True: + 6 | global a # error: [invalid-syntax] + 7 | + 8 | def f3(a): + 9 | def inner(): +10 | global a # error: [invalid-syntax] +11 | +12 | def f4(a): +13 | try: +14 | global a # error: [invalid-syntax] +15 | except Exception: +16 | pass 17 | -18 | def f6(a): +18 | def f5(a): 19 | a = 1 -20 | a = 2 -21 | global a # error: [invalid-syntax] -22 | -23 | def f7(a): -24 | class Inner: -25 | global a # fine +20 | global a # error: [invalid-syntax] +21 | +22 | def f6(a): +23 | a = 1 +24 | a = 2 +25 | global a # error: [invalid-syntax] +26 | +27 | def f7(a): +28 | class Inner: +29 | global a # fine ``` # Diagnostics @@ -46,10 +50,10 @@ error[invalid-syntax]: name `a` is parameter and global --> src/mdtest_snippet.py:2:12 | 1 | def f1(a): -2 | global a # error: [invalid-syntax] +2 | global a # error: [invalid-syntax] | ^ -3 | def f2(a): -4 | if True: +3 | +4 | def f2(a): | ``` @@ -59,10 +63,10 @@ error[invalid-syntax]: name `a` is used prior to global declaration --> src/mdtest_snippet.py:2:12 | 1 | def f1(a): -2 | global a # error: [invalid-syntax] +2 | global a # error: [invalid-syntax] | ^ -3 | def f2(a): -4 | if True: +3 | +4 | def f2(a): | ``` @@ -72,10 +76,10 @@ warning[unresolved-global]: Invalid global declaration of `a` --> src/mdtest_snippet.py:2:12 | 1 | def f1(a): -2 | global a # error: [invalid-syntax] +2 | global a # error: [invalid-syntax] | ^ `a` has no declarations or bindings in the global scope -3 | def f2(a): -4 | if True: +3 | +4 | def f2(a): | info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols info: Consider adding a declaration to the global scope, e.g. `a: int` @@ -85,42 +89,42 @@ info: rule `unresolved-global` is enabled by default ``` error[invalid-syntax]: name `a` is parameter and global - --> src/mdtest_snippet.py:5:16 + --> src/mdtest_snippet.py:6:16 | -3 | def f2(a): -4 | if True: -5 | global a # error: [invalid-syntax] +4 | def f2(a): +5 | if True: +6 | global a # error: [invalid-syntax] | ^ -6 | def f3(a): -7 | def inner(): +7 | +8 | def f3(a): | ``` ``` error[invalid-syntax]: name `a` is used prior to global declaration - --> src/mdtest_snippet.py:5:16 + --> src/mdtest_snippet.py:6:16 | -3 | def f2(a): -4 | if True: -5 | global a # error: [invalid-syntax] +4 | def f2(a): +5 | if True: +6 | global a # error: [invalid-syntax] | ^ -6 | def f3(a): -7 | def inner(): +7 | +8 | def f3(a): | ``` ``` warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:5:16 + --> src/mdtest_snippet.py:6:16 | -3 | def f2(a): -4 | if True: -5 | global a # error: [invalid-syntax] +4 | def f2(a): +5 | if True: +6 | global a # error: [invalid-syntax] | ^ `a` has no declarations or bindings in the global scope -6 | def f3(a): -7 | def inner(): +7 | +8 | def f3(a): | info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols info: Consider adding a declaration to the global scope, e.g. `a: int` @@ -130,14 +134,14 @@ info: rule `unresolved-global` is enabled by default ``` warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:8:16 + --> src/mdtest_snippet.py:10:16 | - 6 | def f3(a): - 7 | def inner(): - 8 | global a # error: [invalid-syntax] + 8 | def f3(a): + 9 | def inner(): +10 | global a # error: [invalid-syntax] | ^ `a` has no declarations or bindings in the global scope - 9 | def f4(a): -10 | try: +11 | +12 | def f4(a): | info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols info: Consider adding a declaration to the global scope, e.g. `a: int` @@ -147,42 +151,42 @@ info: rule `unresolved-global` is enabled by default ``` error[invalid-syntax]: name `a` is parameter and global - --> src/mdtest_snippet.py:11:16 + --> src/mdtest_snippet.py:14:16 | - 9 | def f4(a): -10 | try: -11 | global a # error: [invalid-syntax] +12 | def f4(a): +13 | try: +14 | global a # error: [invalid-syntax] | ^ -12 | except Exception: -13 | pass +15 | except Exception: +16 | pass | ``` ``` error[invalid-syntax]: name `a` is used prior to global declaration - --> src/mdtest_snippet.py:11:16 + --> src/mdtest_snippet.py:14:16 | - 9 | def f4(a): -10 | try: -11 | global a # error: [invalid-syntax] +12 | def f4(a): +13 | try: +14 | global a # error: [invalid-syntax] | ^ -12 | except Exception: -13 | pass +15 | except Exception: +16 | pass | ``` ``` warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:11:16 + --> src/mdtest_snippet.py:14:16 | - 9 | def f4(a): -10 | try: -11 | global a # error: [invalid-syntax] +12 | def f4(a): +13 | try: +14 | global a # error: [invalid-syntax] | ^ `a` has no declarations or bindings in the global scope -12 | except Exception: -13 | pass +15 | except Exception: +16 | pass | info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols info: Consider adding a declaration to the global scope, e.g. `a: int` @@ -192,42 +196,42 @@ info: rule `unresolved-global` is enabled by default ``` error[invalid-syntax]: name `a` is parameter and global - --> src/mdtest_snippet.py:16:12 + --> src/mdtest_snippet.py:20:12 | -14 | def f5(a): -15 | a = 1 -16 | global a # error: [invalid-syntax] +18 | def f5(a): +19 | a = 1 +20 | global a # error: [invalid-syntax] | ^ -17 | -18 | def f6(a): +21 | +22 | def f6(a): | ``` ``` error[invalid-syntax]: name `a` is used prior to global declaration - --> src/mdtest_snippet.py:16:12 + --> src/mdtest_snippet.py:20:12 | -14 | def f5(a): -15 | a = 1 -16 | global a # error: [invalid-syntax] +18 | def f5(a): +19 | a = 1 +20 | global a # error: [invalid-syntax] | ^ -17 | -18 | def f6(a): +21 | +22 | def f6(a): | ``` ``` warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:16:12 + --> src/mdtest_snippet.py:20:12 | -14 | def f5(a): -15 | a = 1 -16 | global a # error: [invalid-syntax] +18 | def f5(a): +19 | a = 1 +20 | global a # error: [invalid-syntax] | ^ `a` has no declarations or bindings in the global scope -17 | -18 | def f6(a): +21 | +22 | def f6(a): | info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols info: Consider adding a declaration to the global scope, e.g. `a: int` @@ -237,42 +241,42 @@ info: rule `unresolved-global` is enabled by default ``` error[invalid-syntax]: name `a` is parameter and global - --> src/mdtest_snippet.py:21:12 + --> src/mdtest_snippet.py:25:12 | -19 | a = 1 -20 | a = 2 -21 | global a # error: [invalid-syntax] +23 | a = 1 +24 | a = 2 +25 | global a # error: [invalid-syntax] | ^ -22 | -23 | def f7(a): +26 | +27 | def f7(a): | ``` ``` error[invalid-syntax]: name `a` is used prior to global declaration - --> src/mdtest_snippet.py:21:12 + --> src/mdtest_snippet.py:25:12 | -19 | a = 1 -20 | a = 2 -21 | global a # error: [invalid-syntax] +23 | a = 1 +24 | a = 2 +25 | global a # error: [invalid-syntax] | ^ -22 | -23 | def f7(a): +26 | +27 | def f7(a): | ``` ``` warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:21:12 + --> src/mdtest_snippet.py:25:12 | -19 | a = 1 -20 | a = 2 -21 | global a # error: [invalid-syntax] +23 | a = 1 +24 | a = 2 +25 | global a # error: [invalid-syntax] | ^ `a` has no declarations or bindings in the global scope -22 | -23 | def f7(a): +26 | +27 | def f7(a): | info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols info: Consider adding a declaration to the global scope, e.g. `a: int` @@ -282,11 +286,11 @@ info: rule `unresolved-global` is enabled by default ``` warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:25:16 + --> src/mdtest_snippet.py:29:16 | -23 | def f7(a): -24 | class Inner: -25 | global a # fine +27 | def f7(a): +28 | class Inner: +29 | global a # fine | ^ `a` has no declarations or bindings in the global scope | info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols From 127425cc1988f8d143a2e07a6a32a0c095de08ba Mon Sep 17 00:00:00 2001 From: 11happy Date: Fri, 7 Nov 2025 11:56:54 +0530 Subject: [PATCH 3/6] test: update snapshot Signed-off-by: 11happy --- .../diagnostics/semantic_syntax_errors.md | 29 +- ...er_an\342\200\246_(99bae53daf67ae6e).snap" | 255 +----------------- 2 files changed, 6 insertions(+), 278 deletions(-) diff --git a/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md b/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md index 15805503522d2..5321bbdfbf819 100644 --- a/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md +++ b/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md @@ -382,33 +382,6 @@ for x in range(42): ```py -def f1(a): +def f(a): global a # error: [invalid-syntax] - -def f2(a): - if True: - global a # error: [invalid-syntax] - -def f3(a): - def inner(): - global a # error: [invalid-syntax] - -def f4(a): - try: - global a # error: [invalid-syntax] - except Exception: - pass - -def f5(a): - a = 1 - global a # error: [invalid-syntax] - -def f6(a): - a = 1 - a = 2 - global a # error: [invalid-syntax] - -def f7(a): - class Inner: - global a # fine ``` diff --git "a/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" index 296c3e4dc8dec..292c5597d529c 100644 --- "a/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" +++ "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" @@ -12,35 +12,8 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syn ## mdtest_snippet.py ``` - 1 | def f1(a): - 2 | global a # error: [invalid-syntax] - 3 | - 4 | def f2(a): - 5 | if True: - 6 | global a # error: [invalid-syntax] - 7 | - 8 | def f3(a): - 9 | def inner(): -10 | global a # error: [invalid-syntax] -11 | -12 | def f4(a): -13 | try: -14 | global a # error: [invalid-syntax] -15 | except Exception: -16 | pass -17 | -18 | def f5(a): -19 | a = 1 -20 | global a # error: [invalid-syntax] -21 | -22 | def f6(a): -23 | a = 1 -24 | a = 2 -25 | global a # error: [invalid-syntax] -26 | -27 | def f7(a): -28 | class Inner: -29 | global a # fine +1 | def f(a): +2 | global a # error: [invalid-syntax] ``` # Diagnostics @@ -49,11 +22,9 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syn error[invalid-syntax]: name `a` is parameter and global --> src/mdtest_snippet.py:2:12 | -1 | def f1(a): +1 | def f(a): 2 | global a # error: [invalid-syntax] | ^ -3 | -4 | def f2(a): | ``` @@ -62,11 +33,9 @@ error[invalid-syntax]: name `a` is parameter and global error[invalid-syntax]: name `a` is used prior to global declaration --> src/mdtest_snippet.py:2:12 | -1 | def f1(a): +1 | def f(a): 2 | global a # error: [invalid-syntax] | ^ -3 | -4 | def f2(a): | ``` @@ -75,224 +44,10 @@ error[invalid-syntax]: name `a` is used prior to global declaration warning[unresolved-global]: Invalid global declaration of `a` --> src/mdtest_snippet.py:2:12 | -1 | def f1(a): +1 | def f(a): 2 | global a # error: [invalid-syntax] | ^ `a` has no declarations or bindings in the global scope -3 | -4 | def f2(a): - | -info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols -info: Consider adding a declaration to the global scope, e.g. `a: int` -info: rule `unresolved-global` is enabled by default - -``` - -``` -error[invalid-syntax]: name `a` is parameter and global - --> src/mdtest_snippet.py:6:16 - | -4 | def f2(a): -5 | if True: -6 | global a # error: [invalid-syntax] - | ^ -7 | -8 | def f3(a): - | - -``` - -``` -error[invalid-syntax]: name `a` is used prior to global declaration - --> src/mdtest_snippet.py:6:16 - | -4 | def f2(a): -5 | if True: -6 | global a # error: [invalid-syntax] - | ^ -7 | -8 | def f3(a): - | - -``` - -``` -warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:6:16 | -4 | def f2(a): -5 | if True: -6 | global a # error: [invalid-syntax] - | ^ `a` has no declarations or bindings in the global scope -7 | -8 | def f3(a): - | -info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols -info: Consider adding a declaration to the global scope, e.g. `a: int` -info: rule `unresolved-global` is enabled by default - -``` - -``` -warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:10:16 - | - 8 | def f3(a): - 9 | def inner(): -10 | global a # error: [invalid-syntax] - | ^ `a` has no declarations or bindings in the global scope -11 | -12 | def f4(a): - | -info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols -info: Consider adding a declaration to the global scope, e.g. `a: int` -info: rule `unresolved-global` is enabled by default - -``` - -``` -error[invalid-syntax]: name `a` is parameter and global - --> src/mdtest_snippet.py:14:16 - | -12 | def f4(a): -13 | try: -14 | global a # error: [invalid-syntax] - | ^ -15 | except Exception: -16 | pass - | - -``` - -``` -error[invalid-syntax]: name `a` is used prior to global declaration - --> src/mdtest_snippet.py:14:16 - | -12 | def f4(a): -13 | try: -14 | global a # error: [invalid-syntax] - | ^ -15 | except Exception: -16 | pass - | - -``` - -``` -warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:14:16 - | -12 | def f4(a): -13 | try: -14 | global a # error: [invalid-syntax] - | ^ `a` has no declarations or bindings in the global scope -15 | except Exception: -16 | pass - | -info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols -info: Consider adding a declaration to the global scope, e.g. `a: int` -info: rule `unresolved-global` is enabled by default - -``` - -``` -error[invalid-syntax]: name `a` is parameter and global - --> src/mdtest_snippet.py:20:12 - | -18 | def f5(a): -19 | a = 1 -20 | global a # error: [invalid-syntax] - | ^ -21 | -22 | def f6(a): - | - -``` - -``` -error[invalid-syntax]: name `a` is used prior to global declaration - --> src/mdtest_snippet.py:20:12 - | -18 | def f5(a): -19 | a = 1 -20 | global a # error: [invalid-syntax] - | ^ -21 | -22 | def f6(a): - | - -``` - -``` -warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:20:12 - | -18 | def f5(a): -19 | a = 1 -20 | global a # error: [invalid-syntax] - | ^ `a` has no declarations or bindings in the global scope -21 | -22 | def f6(a): - | -info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols -info: Consider adding a declaration to the global scope, e.g. `a: int` -info: rule `unresolved-global` is enabled by default - -``` - -``` -error[invalid-syntax]: name `a` is parameter and global - --> src/mdtest_snippet.py:25:12 - | -23 | a = 1 -24 | a = 2 -25 | global a # error: [invalid-syntax] - | ^ -26 | -27 | def f7(a): - | - -``` - -``` -error[invalid-syntax]: name `a` is used prior to global declaration - --> src/mdtest_snippet.py:25:12 - | -23 | a = 1 -24 | a = 2 -25 | global a # error: [invalid-syntax] - | ^ -26 | -27 | def f7(a): - | - -``` - -``` -warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:25:12 - | -23 | a = 1 -24 | a = 2 -25 | global a # error: [invalid-syntax] - | ^ `a` has no declarations or bindings in the global scope -26 | -27 | def f7(a): - | -info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols -info: Consider adding a declaration to the global scope, e.g. `a: int` -info: rule `unresolved-global` is enabled by default - -``` - -``` -warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:29:16 - | -27 | def f7(a): -28 | class Inner: -29 | global a # fine - | ^ `a` has no declarations or bindings in the global scope - | info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols info: Consider adding a declaration to the global scope, e.g. `a: int` info: rule `unresolved-global` is enabled by default From 89dc04f4b81eb737e1636d281f0948dac45ac4eb Mon Sep 17 00:00:00 2001 From: 11happy Date: Wed, 12 Nov 2025 07:12:53 +0530 Subject: [PATCH 4/6] feat: add new method is_parameter for symbol Signed-off-by: 11happy --- .../diagnostics/semantic_syntax_errors.md | 2 + ...er_an\342\200\246_(99bae53daf67ae6e).snap" | 37 ++++--------------- .../src/semantic_index/builder.rs | 14 ++++++- .../src/semantic_index/symbol.rs | 9 +++++ 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md b/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md index 5321bbdfbf819..e090ab54cfa1d 100644 --- a/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md +++ b/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md @@ -382,6 +382,8 @@ for x in range(42): ```py +a = None + def f(a): global a # error: [invalid-syntax] ``` diff --git "a/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" index 292c5597d529c..bf640d5f6aea1 100644 --- "a/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" +++ "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" @@ -12,44 +12,21 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syn ## mdtest_snippet.py ``` -1 | def f(a): -2 | global a # error: [invalid-syntax] +1 | a = None +2 | def f(a): +3 | global a # error: [invalid-syntax] ``` # Diagnostics ``` error[invalid-syntax]: name `a` is parameter and global - --> src/mdtest_snippet.py:2:12 + --> src/mdtest_snippet.py:3:12 | -1 | def f(a): -2 | global a # error: [invalid-syntax] +1 | a = None +2 | def f(a): +3 | global a # error: [invalid-syntax] | ^ | ``` - -``` -error[invalid-syntax]: name `a` is used prior to global declaration - --> src/mdtest_snippet.py:2:12 - | -1 | def f(a): -2 | global a # error: [invalid-syntax] - | ^ - | - -``` - -``` -warning[unresolved-global]: Invalid global declaration of `a` - --> src/mdtest_snippet.py:2:12 - | -1 | def f(a): -2 | global a # error: [invalid-syntax] - | ^ `a` has no declarations or bindings in the global scope - | -info: This limits ty's ability to make accurate inferences about the boundness and types of global-scope symbols -info: Consider adding a declaration to the global scope, e.g. `a: int` -info: rule `unresolved-global` is enabled by default - -``` diff --git a/crates/ty_python_semantic/src/semantic_index/builder.rs b/crates/ty_python_semantic/src/semantic_index/builder.rs index 7ae805098e150..165f7fef8a4a2 100644 --- a/crates/ty_python_semantic/src/semantic_index/builder.rs +++ b/crates/ty_python_semantic/src/semantic_index/builder.rs @@ -1130,6 +1130,9 @@ impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> { } if let Some(vararg) = parameters.vararg.as_ref() { let symbol = self.add_symbol(vararg.name.id().clone()); + self.current_place_table_mut() + .symbol_mut(symbol) + .mark_parameter(); self.add_definition( symbol.into(), DefinitionNodeRef::VariadicPositionalParameter(vararg), @@ -1137,6 +1140,9 @@ impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> { } if let Some(kwarg) = parameters.kwarg.as_ref() { let symbol = self.add_symbol(kwarg.name.id().clone()); + self.current_place_table_mut() + .symbol_mut(symbol) + .mark_parameter(); self.add_definition( symbol.into(), DefinitionNodeRef::VariadicKeywordParameter(kwarg), @@ -1149,6 +1155,10 @@ impl<'db, 'ast> SemanticIndexBuilder<'db, 'ast> { let definition = self.add_definition(symbol.into(), parameter); + self.current_place_table_mut() + .symbol_mut(symbol) + .mark_parameter(); + // Insert a mapping from the inner Parameter node to the same definition. This // ensures that calling `HasType::inferred_type` on the inner parameter returns // a valid type (and doesn't panic) @@ -2173,7 +2183,9 @@ impl<'ast> Visitor<'ast> for SemanticIndexBuilder<'_, 'ast> { let symbol_id = self.add_symbol(name.id.clone()); let symbol = self.current_place_table().symbol(symbol_id); // Check whether the variable has already been accessed in this scope. - if symbol.is_bound() || symbol.is_declared() || symbol.is_used() { + if (symbol.is_bound() || symbol.is_declared() || symbol.is_used()) + && !symbol.is_parameter() + { self.report_semantic_error(SemanticSyntaxError { kind: SemanticSyntaxErrorKind::LoadBeforeGlobalDeclaration { name: name.to_string(), diff --git a/crates/ty_python_semantic/src/semantic_index/symbol.rs b/crates/ty_python_semantic/src/semantic_index/symbol.rs index 400165485ed46..8aea606f597bf 100644 --- a/crates/ty_python_semantic/src/semantic_index/symbol.rs +++ b/crates/ty_python_semantic/src/semantic_index/symbol.rs @@ -38,6 +38,7 @@ bitflags! { 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; + const IS_PARAMETER = 1 << 6; } } @@ -116,6 +117,10 @@ impl Symbol { self.flags.contains(SymbolFlags::IS_REASSIGNED) } + pub(crate) fn is_parameter(&self) -> bool { + self.flags.contains(SymbolFlags::IS_PARAMETER) + } + pub(super) fn mark_global(&mut self) { self.insert_flags(SymbolFlags::MARKED_GLOBAL); } @@ -140,6 +145,10 @@ impl Symbol { self.insert_flags(SymbolFlags::IS_DECLARED); } + pub(super) fn mark_parameter(&mut self) { + self.insert_flags(SymbolFlags::IS_PARAMETER); + } + fn insert_flags(&mut self, flags: SymbolFlags) { self.flags.insert(flags); } From ddcff387084570ca2c3367eeb1d945448b3705a8 Mon Sep 17 00:00:00 2001 From: 11happy Date: Wed, 12 Nov 2025 07:19:40 +0530 Subject: [PATCH 5/6] test: update snapshot Signed-off-by: 11happy --- ...parameter_an\342\200\246_(99bae53daf67ae6e).snap" | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git "a/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" index bf640d5f6aea1..c50518ee124dd 100644 --- "a/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" +++ "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" @@ -13,19 +13,19 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syn ``` 1 | a = None -2 | def f(a): -3 | global a # error: [invalid-syntax] +2 | +3 | def f(a): +4 | global a # error: [invalid-syntax] ``` # Diagnostics ``` error[invalid-syntax]: name `a` is parameter and global - --> src/mdtest_snippet.py:3:12 + --> src/mdtest_snippet.py:4:12 | -1 | a = None -2 | def f(a): -3 | global a # error: [invalid-syntax] +3 | def f(a): +4 | global a # error: [invalid-syntax] | ^ | From 43e459832ce99d075ddeac58fcc96d40aa0dbc37 Mon Sep 17 00:00:00 2001 From: Alex Waygood Date: Fri, 14 Nov 2025 17:46:10 +0000 Subject: [PATCH 6/6] simplify --- crates/ruff_linter/src/checkers/ast/mod.rs | 24 ++--- .../ruff_python_parser/src/semantic_errors.rs | 2 + .../diagnostics/semantic_syntax_errors.md | 27 ++++++ ...er_an\342\200\246_(99bae53daf67ae6e).snap" | 93 ++++++++++++++++++- .../src/semantic_index/builder.rs | 22 +---- 5 files changed, 132 insertions(+), 36 deletions(-) diff --git a/crates/ruff_linter/src/checkers/ast/mod.rs b/crates/ruff_linter/src/checkers/ast/mod.rs index f3315b3b47aea..5f7f459ba98c6 100644 --- a/crates/ruff_linter/src/checkers/ast/mod.rs +++ b/crates/ruff_linter/src/checkers/ast/mod.rs @@ -860,23 +860,17 @@ impl SemanticSyntaxContext for Checker<'_> { } fn is_bound_parameter(&self, name: &str) -> bool { - for scope in self.semantic.current_scopes() { - match scope.kind { - ScopeKind::Class(_) => return false, - ScopeKind::Function(ast::StmtFunctionDef { parameters, .. }) - | ScopeKind::Lambda(ast::ExprLambda { - parameters: Some(parameters), - .. - }) => return parameters.includes(name), - ScopeKind::Lambda(_) - | ScopeKind::Generator { .. } - | ScopeKind::Module - | ScopeKind::Type - | ScopeKind::DunderClassCell => {} + match self.semantic.current_scope().kind { + ScopeKind::Function(ast::StmtFunctionDef { parameters, .. }) => { + parameters.includes(name) } + ScopeKind::Class(_) + | ScopeKind::Lambda(_) + | ScopeKind::Generator { .. } + | ScopeKind::Module + | ScopeKind::Type + | ScopeKind::DunderClassCell => false, } - - false } } diff --git a/crates/ruff_python_parser/src/semantic_errors.rs b/crates/ruff_python_parser/src/semantic_errors.rs index 2775aa9065b78..f8e88925df552 100644 --- a/crates/ruff_python_parser/src/semantic_errors.rs +++ b/crates/ruff_python_parser/src/semantic_errors.rs @@ -2105,8 +2105,10 @@ pub trait SemanticSyntaxContext { fn report_semantic_error(&self, error: SemanticSyntaxError); + /// Returns `true` if the visitor is inside a `for` or `while` loop. fn in_loop_context(&self) -> bool; + /// Returns `true` if `name` is a bound parameter in the current function or lambda scope. fn is_bound_parameter(&self, name: &str) -> bool; } diff --git a/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md b/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md index e090ab54cfa1d..f1c043478bc1b 100644 --- a/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md +++ b/crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syntax_errors.md @@ -386,4 +386,31 @@ a = None def f(a): global a # error: [invalid-syntax] + +def g(a): + if True: + global a # error: [invalid-syntax] + +def h(a): + def inner(): + global a + +def i(a): + try: + global a # error: [invalid-syntax] + except Exception: + pass + +def f(a): + a = 1 + global a # error: [invalid-syntax] + +def f(a): + a = 1 + a = 2 + global a # error: [invalid-syntax] + +def f(a): + class Inner: + global a # ok ``` diff --git "a/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" index c50518ee124dd..21c00c8b7e2aa 100644 --- "a/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" +++ "b/crates/ty_python_semantic/resources/mdtest/snapshots/semantic_syntax_erro\342\200\246_-_Semantic_syntax_erro\342\200\246_-_name_is_parameter_an\342\200\246_(99bae53daf67ae6e).snap" @@ -12,10 +12,37 @@ mdtest path: crates/ty_python_semantic/resources/mdtest/diagnostics/semantic_syn ## mdtest_snippet.py ``` -1 | a = None -2 | -3 | def f(a): -4 | global a # error: [invalid-syntax] + 1 | a = None + 2 | + 3 | def f(a): + 4 | global a # error: [invalid-syntax] + 5 | + 6 | def g(a): + 7 | if True: + 8 | global a # error: [invalid-syntax] + 9 | +10 | def h(a): +11 | def inner(): +12 | global a +13 | +14 | def i(a): +15 | try: +16 | global a # error: [invalid-syntax] +17 | except Exception: +18 | pass +19 | +20 | def f(a): +21 | a = 1 +22 | global a # error: [invalid-syntax] +23 | +24 | def f(a): +25 | a = 1 +26 | a = 2 +27 | global a # error: [invalid-syntax] +28 | +29 | def f(a): +30 | class Inner: +31 | global a # ok ``` # Diagnostics @@ -27,6 +54,64 @@ error[invalid-syntax]: name `a` is parameter and global 3 | def f(a): 4 | global a # error: [invalid-syntax] | ^ +5 | +6 | def g(a): | ``` + +``` +error[invalid-syntax]: name `a` is parameter and global + --> src/mdtest_snippet.py:8:16 + | + 6 | def g(a): + 7 | if True: + 8 | global a # error: [invalid-syntax] + | ^ + 9 | +10 | def h(a): + | + +``` + +``` +error[invalid-syntax]: name `a` is parameter and global + --> src/mdtest_snippet.py:16:16 + | +14 | def i(a): +15 | try: +16 | global a # error: [invalid-syntax] + | ^ +17 | except Exception: +18 | pass + | + +``` + +``` +error[invalid-syntax]: name `a` is parameter and global + --> src/mdtest_snippet.py:22:12 + | +20 | def f(a): +21 | a = 1 +22 | global a # error: [invalid-syntax] + | ^ +23 | +24 | def f(a): + | + +``` + +``` +error[invalid-syntax]: name `a` is parameter and global + --> src/mdtest_snippet.py:27:12 + | +25 | a = 1 +26 | a = 2 +27 | global a # error: [invalid-syntax] + | ^ +28 | +29 | def f(a): + | + +``` diff --git a/crates/ty_python_semantic/src/semantic_index/builder.rs b/crates/ty_python_semantic/src/semantic_index/builder.rs index 165f7fef8a4a2..2bcf92a48c79f 100644 --- a/crates/ty_python_semantic/src/semantic_index/builder.rs +++ b/crates/ty_python_semantic/src/semantic_index/builder.rs @@ -2822,24 +2822,12 @@ impl SemanticSyntaxContext for SemanticIndexBuilder<'_, '_> { fn in_loop_context(&self) -> bool { self.current_scope_info().current_loop.is_some() } + fn is_bound_parameter(&self, name: &str) -> bool { - for scope_info in self.scope_stack.iter().rev() { - let scope = &self.scopes[scope_info.file_scope_id]; - match scope.node() { - NodeWithScopeKind::Function(func) => { - let parameters = &func.node(self.module).parameters; - return parameters.includes(name); - } - NodeWithScopeKind::Lambda(lambda) => { - if let Some(parameters) = lambda.node(self.module).parameters.as_ref() { - return parameters.includes(name); - } - } - NodeWithScopeKind::Class(_) => return false, - _ => {} - } - } - false + self.scopes[self.current_scope()] + .node() + .as_function() + .is_some_and(|func| func.node(self.module).parameters.includes(name)) } }