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

View File

@ -1537,7 +1537,8 @@ export interface FunctionType extends TypeBase {
// The flags for the function prior to binding // The flags for the function prior to binding
preBoundFlags?: FunctionTypeFlags; 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; boundTypeVarScopeId?: TypeVarScopeId | undefined;
// If this function is part of an overloaded function, this // If this function is part of an overloaded function, this
@ -1657,7 +1658,10 @@ export namespace FunctionType {
} }
newFunction.inferredReturnType = type.inferredReturnType; newFunction.inferredReturnType = type.inferredReturnType;
newFunction.boundTypeVarScopeId = boundTypeVarScopeId ?? type.boundTypeVarScopeId;
if (newFunction.preBoundFlags & FunctionTypeFlags.ConstructorMethod) {
newFunction.boundTypeVarScopeId = boundTypeVarScopeId ?? type.boundTypeVarScopeId;
}
return newFunction; return newFunction;
} }