Simplified handling of TypeVars used in bound objects for constructor methods. (#8119)

This commit is contained in:
Eric Traut 2024-06-11 12:50:12 -07:00 committed by GitHub
parent 0edcd2eecf
commit 0df185ebd4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 30 additions and 36 deletions

View File

@ -11411,41 +11411,27 @@ export function createTypeEvaluator(
}
}
if (type.boundTypeVarScopeId) {
// If the function was bound to a class or object and was a constructor, a
// static method or a class method, it's possible that some of that class's
// type variables have not yet been solved. Add that class's TypeVar scope ID.
if (type.preBoundFlags !== undefined && type.boundToType && requiresSpecialization(type.boundToType)) {
if (
type.preBoundFlags &
(FunctionTypeFlags.StaticMethod | FunctionTypeFlags.ClassMethod | FunctionTypeFlags.StaticMethod)
) {
typeVarContext.addSolveForScope(type.boundTypeVarScopeId);
}
}
// The type annotation for the "self" parameter in an __init__ method to
// can influence the type being constructed.
if (
type.details.name === '__init__' &&
type.strippedFirstParamType &&
type.boundToType &&
isClassInstance(type.strippedFirstParamType) &&
isClassInstance(type.boundToType) &&
ClassType.isSameGenericClass(type.strippedFirstParamType, type.boundToType) &&
type.strippedFirstParamType.typeArguments
) {
const typeParams = type.strippedFirstParamType.details.typeParameters;
specializedInitSelfType = type.strippedFirstParamType;
type.strippedFirstParamType.typeArguments.forEach((typeArg, index) => {
if (index < typeParams.length) {
const typeParam = typeParams[index];
if (!isTypeSame(typeParam, typeArg, { ignorePseudoGeneric: true })) {
typeVarContext.setTypeVarType(typeParams[index], typeArg);
}
// The type annotation for the "self" parameter in an __init__ method to
// can influence the type being constructed.
if (
type.details.name === '__init__' &&
type.strippedFirstParamType &&
type.boundToType &&
isClassInstance(type.strippedFirstParamType) &&
isClassInstance(type.boundToType) &&
ClassType.isSameGenericClass(type.strippedFirstParamType, type.boundToType) &&
type.strippedFirstParamType.typeArguments
) {
const typeParams = type.strippedFirstParamType.details.typeParameters;
specializedInitSelfType = type.strippedFirstParamType;
type.strippedFirstParamType.typeArguments.forEach((typeArg, index) => {
if (index < typeParams.length) {
const typeParam = typeParams[index];
if (!isTypeSame(typeParam, typeArg, { ignorePseudoGeneric: true })) {
typeVarContext.setTypeVarType(typeParams[index], typeArg);
}
});
}
}
});
}
// Special-case a few built-in calls that are often used for

View File

@ -1065,6 +1065,10 @@ export function getTypeVarScopeIds(type: Type): TypeVarScopeId[] | undefined {
if (type.details.higherOrderTypeVarScopeIds) {
scopeIds.push(...type.details.higherOrderTypeVarScopeIds);
}
if (type.boundTypeVarScopeId) {
scopeIds.push(type.boundTypeVarScopeId);
}
}
return scopeIds;

View File

@ -1537,7 +1537,8 @@ export interface FunctionType extends TypeBase {
// The flags for the function prior to binding
preBoundFlags?: FunctionTypeFlags;
// The type var scope for the class that the function was bound to
// The type var scope for the class that the function was bound to.
// This applies only to constructor methods.
boundTypeVarScopeId?: TypeVarScopeId | undefined;
// If this function is part of an overloaded function, this
@ -1657,7 +1658,10 @@ export namespace FunctionType {
}
newFunction.inferredReturnType = type.inferredReturnType;
newFunction.boundTypeVarScopeId = boundTypeVarScopeId ?? type.boundTypeVarScopeId;
if (newFunction.preBoundFlags & FunctionTypeFlags.ConstructorMethod) {
newFunction.boundTypeVarScopeId = boundTypeVarScopeId ?? type.boundTypeVarScopeId;
}
return newFunction;
}