Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added logic to expand promotion types for float and complex when … #8024

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/pyright-internal/src/analyzer/constructors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ export function validateConstructorArguments(
inferenceContext: InferenceContext | undefined,
signatureTracker: UniqueSignatureTracker | undefined
): CallResult {
// If this is a "float" or "complex" constructor call, do not include
// the associated promotions.
if (!type.includeSubclasses && type.includePromotions) {
type = ClassType.cloneRemoveTypePromotions(type);
}

const metaclassResult = validateMetaclassCall(
evaluator,
errorNode,
Expand Down
5 changes: 5 additions & 0 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5226,6 +5226,11 @@ export function createTypeEvaluator(
baseType = makeTopLevelTypeVarsConcrete(baseType);
}

// Do union expansion for promotion types. Exclude bytes here because
// this creates too much noise. Users who want stricter checks for bytes
// can use "disableBytesTypePromotions".
baseType = expandPromotionTypes(node, baseType, /* excludeBytes */ true);

switch (baseType.category) {
case TypeCategory.Any:
case TypeCategory.Unknown:
Expand Down
25 changes: 19 additions & 6 deletions packages/pyright-internal/src/analyzer/typeGuards.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1346,6 +1346,12 @@ function narrowTypeForIsInstanceInternal(
let filterIsSuperclass: boolean;
let filterIsSubclass: boolean;

// If the user has explicitly specified "float" or "complex" as a filter,
// eliminate the associated promotions.
if (!concreteFilterType.includeSubclasses && concreteFilterType.includePromotions) {
concreteFilterType = ClassType.cloneRemoveTypePromotions(concreteFilterType);
}

if (isTypeIsCheck) {
filterIsSuperclass = evaluator.assignType(filterType, concreteVarType);
filterIsSubclass = evaluator.assignType(concreteVarType, filterType);
Expand Down Expand Up @@ -1775,21 +1781,28 @@ function narrowTypeForIsInstanceInternal(
const isSubtypeMetaclass = isMetaclassInstance(subtype);

if (isPositiveTest && isAnyOrUnknown(subtype)) {
const filterTypeInstances = filterTypes.map((filterType) => {
if (
isInstantiableClass(filterType) &&
!filterType.includeSubclasses &&
filterType.includePromotions
) {
filterType = ClassType.cloneRemoveTypePromotions(filterType);
}
return convertToInstance(filterType);
});

// If this is a positive test and the effective type is Any or
// Unknown, we can assume that the type matches one of the
// specified types.
if (isInstanceCheck) {
anyOrUnknownSubstitutions.push(
combineTypes(filterTypes.map((classType) => convertToInstance(classType)))
);
anyOrUnknownSubstitutions.push(combineTypes(filterTypeInstances));
} else {
// We perform a double conversion from instance to instantiable
// here to make sure that the includeSubclasses flag is cleared
// if it's a class.
anyOrUnknownSubstitutions.push(
combineTypes(
filterTypes.map((classType) => convertToInstantiable(convertToInstance(classType)))
)
combineTypes(filterTypeInstances.map((classType) => convertToInstantiable(classType)))
);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
b2: float = b["x"]

c = dict(x=m, y=n)
reveal_type(c, expected_text="dict[str, float]")
reveal_type(c, expected_text="dict[str, int | float]")

# This should generate an error.
c1: int = c["x"]
Expand Down
Loading