Skip to content

Commit

Permalink
Fixed bug that results in false positive error when a dataclass field…
Browse files Browse the repository at this point in the history
… is annotated with a class-scoped type variable and includes a default value whose type require bidirectional type inference. This addresses #9222. (#9223)
  • Loading branch information
erictraut authored Oct 15, 2024
1 parent fb54490 commit 8b5d9a3
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 3 deletions.
16 changes: 14 additions & 2 deletions packages/pyright-internal/src/analyzer/dataClasses.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,13 @@ import { ConstraintTracker } from './constraintTracker';
import { createFunctionFromConstructor, getBoundInitMethod } from './constructors';
import { DeclarationType, VariableDeclaration } from './declaration';
import { updateNamedTupleBaseClass } from './namedTuples';
import { getClassFullName, getEnclosingClassOrFunction, getScopeIdForNode, getTypeSourceId } from './parseTreeUtils';
import {
getClassFullName,
getEnclosingClassOrFunction,
getScopeIdForNode,
getTypeSourceId,
getTypeVarScopesForNode,
} from './parseTreeUtils';
import { evaluateStaticBoolExpression } from './staticExpressions';
import { Symbol, SymbolFlags } from './symbol';
import { isPrivateName } from './symbolNameUtils';
Expand Down Expand Up @@ -75,6 +81,8 @@ import {
isLiteralType,
isMetaclassInstance,
makeInferenceContext,
makeTypeVarsBound,
makeTypeVarsFree,
requiresSpecialization,
specializeTupleClass,
synthesizeTypeVarForSelfCls,
Expand Down Expand Up @@ -584,6 +592,8 @@ export function synthesizeDataClassMethods(
const defaultExpr = entry.defaultExpr;
const fileInfo = AnalyzerNodeInfo.getFileInfo(node);
const flags = fileInfo.isStubFile ? EvalFlags.ConvertEllipsisToAny : EvalFlags.None;
const liveTypeVars = getTypeVarScopesForNode(entry.defaultExpr);
const boundEffectiveType = makeTypeVarsBound(effectiveType, liveTypeVars);

// Use speculative mode here so we don't cache the results.
// We'll want to re-evaluate this expression later, potentially
Expand All @@ -592,9 +602,11 @@ export function synthesizeDataClassMethods(
return evaluator.getTypeOfExpression(
defaultExpr,
flags,
makeInferenceContext(entry.type)
makeInferenceContext(boundEffectiveType)
).type;
});

defaultType = makeTypeVarsFree(defaultType, liveTypeVars);
}
}
}
Expand Down
11 changes: 10 additions & 1 deletion packages/pyright-internal/src/tests/samples/dataclass1.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# This sample tests the handling of the @dataclass decorator.

from dataclasses import dataclass, InitVar, field
from typing import Generic, Literal, Sequence, TypeVar
from typing import Callable, Generic, Literal, Sequence, TypeVar


@dataclass
Expand Down Expand Up @@ -117,3 +117,12 @@ class DC8(Generic[T1]):
@dataclass
class DC9(Generic[T1]):
x: Sequence[Literal["a", "b"]] = ["a"]


@dataclass
class DC10[T]:
a: type[T]
b: Callable[[T], bool] = lambda _: True


DC10(a=int)

0 comments on commit 8b5d9a3

Please sign in to comment.