Skip to content

Commit

Permalink
Fixed a bug that results in a false negative when a class is used in …
Browse files Browse the repository at this point in the history
…a type annotation for a method parameter and both the class and the method are generic and use PEP 695 syntax. This addresses #9382.
  • Loading branch information
erictraut committed Nov 10, 2024
1 parent 6be5f8c commit f25ad47
Show file tree
Hide file tree
Showing 4 changed files with 14 additions and 6 deletions.
7 changes: 5 additions & 2 deletions packages/pyright-internal/src/analyzer/parseTreeUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1092,9 +1092,12 @@ export function getExecutionScopeNode(node: ParseNode): ExecutionScopeNode {
let evaluationScope = getEvaluationScopeNode(node).node;

// Classes are not considered execution scope because they are executed
// within the context of their containing module or function. Likewise, list
// comprehensions are executed within their container.
// within the context of their containing module or function. Likewise,
// list comprehensions are executed within their container. Type parameter
// scopes are special because they act as proxies for their containing
// function or class scope.
while (
evaluationScope.nodeType === ParseNodeType.TypeParameterList ||
evaluationScope.nodeType === ParseNodeType.Class ||
evaluationScope.nodeType === ParseNodeType.Comprehension
) {
Expand Down
5 changes: 2 additions & 3 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21321,9 +21321,8 @@ export function createTypeEvaluator(
// within the local scope.
let scopeTypeHonorsCodeFlow = scopeType !== ScopeType.Function && scopeType !== ScopeType.Comprehension;

// Type parameter scopes don't honor code flow, but if the symbol is resolved
// using the proxy scope for the type parameter scope, we should use code flow.
if (scopeType === ScopeType.TypeParameter && symbolWithScope && symbolWithScope.scope === scope) {
// Type parameter scopes don't honor code flow.
if (symbolWithScope?.scope.type === ScopeType.TypeParameter) {
scopeTypeHonorsCodeFlow = false;
}

Expand Down
6 changes: 6 additions & 0 deletions packages/pyright-internal/src/tests/samples/typeParams3.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,3 +101,9 @@ def outer_method(self):

def inner_func():
reveal_type(T, expected_text="complex")


class Outer3[T]:
# This should generate an error because Outer3 is
# not bound at this point.
def inner_func1[S](self: Outer3[S]): ...
2 changes: 1 addition & 1 deletion packages/pyright-internal/src/tests/typeEvaluator5.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ test('TypeParams3', () => {
configOptions.defaultPythonVersion = pythonVersion3_12;

const analysisResults = TestUtils.typeAnalyzeSampleFiles(['typeParams3.py'], configOptions);
TestUtils.validateResults(analysisResults, 7);
TestUtils.validateResults(analysisResults, 8);
});

test('TypeParams4', () => {
Expand Down

0 comments on commit f25ad47

Please sign in to comment.