Skip to content

Commit

Permalink
Fixed a bug that led to incorrect type evaluation when passing a gene…
Browse files Browse the repository at this point in the history
…ric class (with a constructor that includes class-scoped TypeVars) as an argument for a callable parameter. The class was being specialized prematurely (with type arguments set to `Unknown`) before the constraint solver was able to solve the higher-order function's type variables. This addresses microsoft#5324. (microsoft#5328)

Co-authored-by: Eric Traut <[email protected]>
  • Loading branch information
erictraut and msfterictraut authored Jun 18, 2023
1 parent 47cd514 commit 9bf8231
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 2 deletions.
4 changes: 2 additions & 2 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11214,7 +11214,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.DisallowParamSpec |
EvaluatorFlags.DisallowTypeVarTuple
: EvaluatorFlags.None;
: EvaluatorFlags.DoNotSpecialize;
const exprTypeResult = getTypeOfExpression(
argParam.argument.valueExpression,
flags,
Expand Down Expand Up @@ -22542,7 +22542,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
concreteSrcType,
diag?.createAddendum(),
destTypeVarContext ?? new TypeVarContext(getTypeVarScopeId(destType)),
srcTypeVarContext ?? new TypeVarContext(getTypeVarScopeId(concreteSrcType)),
srcTypeVarContext ?? new TypeVarContext(getTypeVarScopeIds(concreteSrcType)),
flags,
recursionCount
)
Expand Down
12 changes: 12 additions & 0 deletions packages/pyright-internal/src/tests/samples/genericTypes118.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# This sample tests the case where a generic class is passed as an
# argument to a function that accepts a generic callable parameter.
# The class-scoped TypeVars for the class must be preserved when
# solving the higher-order TypeVars.

from itertools import compress
from typing import Any, Iterable


def func1(a: Iterable[Iterable[tuple[str, int]]], b: Any) -> None:
c = map(compress, a, b)
reveal_type(c, expected_text="map[compress[tuple[str, int]]]")
6 changes: 6 additions & 0 deletions packages/pyright-internal/src/tests/typeEvaluator2.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1127,6 +1127,12 @@ test('GenericTypes117', () => {
TestUtils.validateResults(analysisResults, 1);
});

test('GenericTypes118', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['genericTypes118.py']);

TestUtils.validateResults(analysisResults, 0);
});

test('Protocol1', () => {
const analysisResults = TestUtils.typeAnalyzeSampleFiles(['protocol1.py']);

Expand Down

0 comments on commit 9bf8231

Please sign in to comment.