Code cleanup for prefetched types used in type evaluator.

This commit is contained in:
Eric Traut 2024-05-30 17:41:39 -07:00
parent 32fa85e3ed
commit ce229098e6

View File

@ -602,28 +602,28 @@ export function createTypeEvaluator(
let expectedTypeCache = new Map<number, Type>();
let deferredClassCompletions: DeferredClassCompletion[] = [];
let cancellationToken: CancellationToken | undefined;
let isBasicTypesInitialized = false;
let noneClassType: Type | undefined;
let noneType: Type | undefined;
let objectType: Type | undefined;
let typeClassType: Type | undefined;
let unionClassType: Type | undefined;
let awaitableProtocolType: Type | undefined;
let functionObj: Type | undefined;
let tupleClassType: Type | undefined;
let boolClassType: Type | undefined;
let intClassType: Type | undefined;
let strClassType: Type | undefined;
let dictClassType: Type | undefined;
let typedDictClassType: Type | undefined;
let typedDictPrivateClassType: Type | undefined;
let supportsKeysAndGetItemProtocolType: Type | undefined;
let mappingType: Type | undefined;
let printExpressionSpaceCount = 0;
let incompleteGenerationCount = 0;
const returnTypeInferenceContextStack: ReturnTypeInferenceContext[] = [];
let returnTypeInferenceTypeCache: Map<number, TypeCacheEntry> | undefined;
let isPrefetchedTypesInitialized = false;
// Various types prefetched from stdlib stubs
let noneTypeClass: Type | undefined;
let objectClass: Type | undefined;
let typeClass: Type | undefined;
let unionClass: Type | undefined;
let awaitableClass: Type | undefined;
let functionClass: Type | undefined;
let tupleClass: Type | undefined;
let boolClass: Type | undefined;
let intClass: Type | undefined;
let strClass: Type | undefined;
let dictClass: Type | undefined;
let typedDictClassType: Type | undefined;
let typedDictPrivateClass: Type | undefined;
let supportsKeysAndGetItemClass: Type | undefined;
let mappingClass: Type | undefined;
function runWithCancellationToken<T>(token: CancellationToken, callback: () => T): T {
try {
@ -847,7 +847,7 @@ export function createTypeEvaluator(
// context, logging any errors in the process. This may require the
// type of surrounding statements to be evaluated.
function getType(node: ExpressionNode): Type | undefined {
initializedBasicTypes(node);
initializePrefetchedTypes(node);
let type = evaluateTypeForSubnode(node, () => {
evaluateTypesForExpressionInContext(node);
@ -940,54 +940,44 @@ export function createTypeEvaluator(
return undefined;
}
function initializedBasicTypes(node: ParseNode) {
if (!isBasicTypesInitialized) {
function initializePrefetchedTypes(node: ParseNode) {
if (!isPrefetchedTypesInitialized) {
// Some of these types have cyclical dependencies on each other,
// so don't re-enter this block once we start executing it.
isBasicTypesInitialized = true;
isPrefetchedTypesInitialized = true;
objectType = getBuiltInObject(node, 'object');
typeClassType = getBuiltInType(node, 'type');
functionObj = getBuiltInObject(node, 'function');
objectClass = getBuiltInType(node, 'object');
typeClass = getBuiltInType(node, 'type');
functionClass = getBuiltInType(node, 'function');
unionClassType = getTypesType(node, 'UnionType');
if (unionClassType && isClass(unionClassType)) {
unionClassType.details.flags |= ClassTypeFlags.SpecialFormClass;
unionClass = getTypesType(node, 'UnionType');
if (unionClass && isClass(unionClass)) {
unionClass.details.flags |= ClassTypeFlags.SpecialFormClass;
}
// Initialize and cache "Collection" to break a cyclical dependency
// that occurs when resolving tuple below.
getTypingType(node, 'Collection');
noneClassType = getTypeshedType(node, 'NoneType') ?? UnknownType.create();
noneType = isInstantiableClass(noneClassType)
? ClassType.cloneAsInstance(noneClassType)
: UnknownType.create();
tupleClassType = getBuiltInType(node, 'tuple');
boolClassType = getBuiltInType(node, 'bool');
intClassType = getBuiltInType(node, 'int');
strClassType = getBuiltInType(node, 'str');
dictClassType = getBuiltInType(node, 'dict');
noneTypeClass = getTypeshedType(node, 'NoneType') ?? UnknownType.create();
tupleClass = getBuiltInType(node, 'tuple');
boolClass = getBuiltInType(node, 'bool');
intClass = getBuiltInType(node, 'int');
strClass = getBuiltInType(node, 'str');
dictClass = getBuiltInType(node, 'dict');
typedDictClassType = getTypingType(node, 'TypedDict');
typedDictPrivateClassType = getTypingType(node, '_TypedDict');
awaitableProtocolType = getTypingType(node, 'Awaitable');
mappingType = getTypingType(node, 'Mapping');
typedDictPrivateClass = getTypingType(node, '_TypedDict');
awaitableClass = getTypingType(node, 'Awaitable');
mappingClass = getTypingType(node, 'Mapping');
supportsKeysAndGetItemProtocolType = getTypeshedType(node, 'SupportsKeysAndGetItem');
if (!supportsKeysAndGetItemProtocolType) {
supportsKeysAndGetItemClass = getTypeshedType(node, 'SupportsKeysAndGetItem');
if (!supportsKeysAndGetItemClass) {
// Fall back on 'Mapping' if 'SupportsKeysAndGetItem' is not available.
supportsKeysAndGetItemProtocolType = mappingType;
supportsKeysAndGetItemClass = mappingClass;
}
// Wire up the `Any` class to the special-form version of our internal AnyType.
const objectClass = getBuiltInType(node, 'object');
if (
objectClass &&
isInstantiableClass(objectClass) &&
typeClassType &&
isInstantiableClass(typeClassType)
) {
if (objectClass && isInstantiableClass(objectClass) && typeClass && isInstantiableClass(typeClass)) {
const anyClass = ClassType.createInstantiable(
'Any',
'typing.Any',
@ -996,7 +986,7 @@ export function createTypeEvaluator(
ClassTypeFlags.BuiltInClass | ClassTypeFlags.SpecialFormClass,
/* typeSourceId */ -1,
/* declaredMetaclass */ undefined,
/* effectiveMetaclass */ typeClassType
/* effectiveMetaclass */ typeClass
);
anyClass.details.baseClasses.push(objectClass);
computeMroLinearization(anyClass);
@ -1070,7 +1060,7 @@ export function createTypeEvaluator(
// typeshed stubs, do so here. It would be better to fetch this when it's
// needed in assignType, but we don't have access to the parse tree
// at that point.
initializedBasicTypes(node);
initializePrefetchedTypes(node);
let typeResult = getTypeOfExpressionCore(node, flags, inferenceContext, signatureTracker);
@ -1699,8 +1689,8 @@ export function createTypeEvaluator(
if (ClassType.isBuiltIn(subtype, 'LiteralString')) {
// Handle "LiteralString" specially.
if (strClassType && isInstantiableClass(strClassType)) {
let strInstance = ClassType.cloneAsInstance(strClassType);
if (strClass && isInstantiableClass(strClass)) {
let strInstance = ClassType.cloneAsInstance(strClass);
if (subtype.condition) {
strInstance = TypeBase.cloneForCondition(strInstance, getTypeCondition(subtype));
@ -2695,14 +2685,14 @@ export function createTypeEvaluator(
// If errorNode is undefined, no errors are reported.
function getTypeOfAwaitable(type: Type, errorNode?: ExpressionNode): Type {
if (
!awaitableProtocolType ||
!isInstantiableClass(awaitableProtocolType) ||
awaitableProtocolType.details.typeParameters.length !== 1
!awaitableClass ||
!isInstantiableClass(awaitableClass) ||
awaitableClass.details.typeParameters.length !== 1
) {
return UnknownType.create();
}
const awaitableProtocolObj = ClassType.cloneAsInstance(awaitableProtocolType);
const awaitableProtocolObj = ClassType.cloneAsInstance(awaitableClass);
return mapSubtypes(type, (subtype) => {
subtype = makeTopLevelTypeVarsConcrete(subtype);
@ -2797,8 +2787,8 @@ export function createTypeEvaluator(
[
{
type:
intClassType && isInstantiableClass(intClassType)
? ClassType.cloneAsInstance(intClassType)
intClass && isInstantiableClass(intClass)
? ClassType.cloneAsInstance(intClass)
: UnknownType.create(),
},
],
@ -2833,7 +2823,7 @@ export function createTypeEvaluator(
// know anything more about them.
nextReturnType = mapSubtypes(nextReturnType, (returnSubtype) => {
if (isTypeVar(returnSubtype) && isUnpackedVariadicTypeVar(returnSubtype)) {
return objectType ?? UnknownType.create();
return getObjectType();
}
return returnSubtype;
@ -2973,25 +2963,23 @@ export function createTypeEvaluator(
}
function getTypedDictClassType(): ClassType | undefined {
return typedDictPrivateClassType && isInstantiableClass(typedDictPrivateClassType)
? typedDictPrivateClassType
: undefined;
return typedDictPrivateClass && isInstantiableClass(typedDictPrivateClass) ? typedDictPrivateClass : undefined;
}
function getTupleClassType(): ClassType | undefined {
return tupleClassType && isInstantiableClass(tupleClassType) ? tupleClassType : undefined;
return tupleClass && isInstantiableClass(tupleClass) ? tupleClass : undefined;
}
function getObjectType(): Type {
return objectType ?? UnknownType.create();
return objectClass ? convertToInstance(objectClass) : UnknownType.create();
}
function getNoneType(): Type {
return noneType ?? UnknownType.create();
return noneTypeClass ? convertToInstance(noneTypeClass) : UnknownType.create();
}
function getUnionClassType(): Type {
return unionClassType ?? UnknownType.create();
return unionClass ?? UnknownType.create();
}
function getTypingType(node: ParseNode, symbolName: string): Type | undefined {
@ -3790,24 +3778,13 @@ export function createTypeEvaluator(
return mapSubtypes(type, (subtype) => {
if (isParamSpec(subtype)) {
if (subtype.paramSpecAccess === 'args') {
if (objectType && isClassInstance(objectType)) {
return makeTupleObject([{ type: objectType, isUnbounded: true }]);
}
return UnknownType.create();
return makeTupleObject([{ type: getObjectType(), isUnbounded: true }]);
} else if (subtype.paramSpecAccess === 'kwargs') {
if (
dictClassType &&
isInstantiableClass(dictClassType) &&
strClassType &&
isInstantiableClass(strClassType) &&
objectType &&
isClassInstance(objectType)
) {
if (dictClass && isInstantiableClass(dictClass) && strClass && isInstantiableClass(strClass)) {
return ClassType.cloneAsInstance(
ClassType.cloneForSpecialization(
dictClassType,
[convertToInstance(strClassType), objectType],
dictClass,
[convertToInstance(strClass), getObjectType()],
/* isTypeArgumentExplicit */ true
)
);
@ -3832,21 +3809,18 @@ export function createTypeEvaluator(
// If it's in a union, convert to type or object.
if (subtype.isVariadicInUnion) {
if (TypeBase.isInstantiable(subtype)) {
if (typeClassType && isInstantiableClass(typeClassType)) {
return typeClassType;
if (typeClass && isInstantiableClass(typeClass)) {
return typeClass;
}
} else if (objectType) {
return objectType;
} else {
return getObjectType();
}
return AnyType.create();
}
// Fall back to "*tuple[object, ...]".
return makeTupleObject(
[{ type: objectType ?? UnknownType.create(), isUnbounded: true }],
/* isUnpacked */ true
);
return makeTupleObject([{ type: getObjectType(), isUnbounded: true }], /* isUnpacked */ true);
}
if (isTypeVar(subtype)) {
@ -3892,7 +3866,7 @@ export function createTypeEvaluator(
}
// Fall back to a bound of "object" if no bound is provided.
let boundType = subtype.details.boundType ?? objectType ?? UnknownType.create();
let boundType = subtype.details.boundType ?? getObjectType();
boundType = TypeBase.isInstantiable(subtype) ? convertToInstantiable(boundType) : boundType;
return addConditionToType(boundType, [{ typeVar: subtype, constraintIndex: 0 }]);
@ -4911,7 +4885,7 @@ export function createTypeEvaluator(
let defaultType: Type;
if (param.details.isDefaultExplicit || param.details.isParamSpec) {
defaultType = applySolvedTypeVars(param, typeVarContext, { unknownIfNotFound: true });
} else if (param.details.isVariadic && tupleClassType && isInstantiableClass(tupleClassType)) {
} else if (param.details.isVariadic && tupleClass && isInstantiableClass(tupleClass)) {
defaultType = makeTupleObject(
[{ type: UnknownType.create(), isUnbounded: true }],
/* isUnpackedTuple */ true
@ -5486,8 +5460,9 @@ export function createTypeEvaluator(
return undefined;
}
if (isNoneInstance(subtype) && noneType && isClassInstance(noneType)) {
const typeResult = getTypeOfBoundMember(node.memberName, noneType, memberName, usage, diag);
if (isNoneInstance(subtype)) {
assert(isClassInstance(subtype));
const typeResult = getTypeOfBoundMember(node.memberName, subtype, memberName, usage, diag);
if (typeResult && !typeResult.typeErrors) {
type = addConditionToType(typeResult.type, getTypeCondition(baseType));
@ -5551,7 +5526,7 @@ export function createTypeEvaluator(
} else {
type = getTypeOfMemberAccessWithBaseType(
node,
{ type: functionObj ?? AnyType.create() },
{ type: functionClass ? convertToInstance(functionClass) : UnknownType.create() },
usage,
flags
).type;
@ -6387,8 +6362,8 @@ export function createTypeEvaluator(
argumentCategory: ArgumentCategory.Simple,
typeResult: {
type:
strClassType && isInstantiableClass(strClassType)
? ClassType.cloneWithLiteral(ClassType.cloneAsInstance(strClassType), memberName)
strClass && isInstantiableClass(strClass)
? ClassType.cloneWithLiteral(ClassType.cloneAsInstance(strClass), memberName)
: AnyType.create(),
},
});
@ -7307,9 +7282,9 @@ export function createTypeEvaluator(
}
function makeTupleObject(typeArgs: TupleTypeArgument[], isUnpackedTuple = false) {
if (tupleClassType && isInstantiableClass(tupleClassType)) {
if (tupleClass && isInstantiableClass(tupleClass)) {
return convertToInstance(
specializeTupleClass(tupleClassType, typeArgs, /* isTypeArgumentExplicit */ true, isUnpackedTuple)
specializeTupleClass(tupleClass, typeArgs, /* isTypeArgumentExplicit */ true, isUnpackedTuple)
);
}
@ -7785,8 +7760,7 @@ export function createTypeEvaluator(
typedDictClassType && isInstantiableClass(typedDictClassType)
? createTypedDictTypeInlined(evaluatorInterface, node, typedDictClassType)
: undefined;
const keyTypeFallback =
strClassType && isInstantiableClass(strClassType) ? strClassType : UnknownType.create();
const keyTypeFallback = strClass && isInstantiableClass(strClass) ? strClass : UnknownType.create();
typeResult = {
type: keyTypeFallback,
@ -7923,7 +7897,7 @@ export function createTypeEvaluator(
return undefined;
}
if (!tupleClassType || !isInstantiableClass(tupleClassType)) {
if (!tupleClass || !isInstantiableClass(tupleClass)) {
return undefined;
}
@ -7945,11 +7919,11 @@ export function createTypeEvaluator(
}
}
} else {
const tupleTypeVarContext = new TypeVarContext(getTypeVarScopeId(tupleClassType));
const tupleTypeVarContext = new TypeVarContext(getTypeVarScopeId(tupleClass));
if (
!populateTypeVarContextBasedOnExpectedType(
evaluatorInterface,
ClassType.cloneAsInstance(tupleClassType),
ClassType.cloneAsInstance(tupleClass),
inferenceContext.expectedType,
tupleTypeVarContext,
ParseTreeUtils.getTypeVarScopesForNode(node),
@ -7959,7 +7933,7 @@ export function createTypeEvaluator(
return undefined;
}
const specializedTuple = applySolvedTypeVars(tupleClassType, tupleTypeVarContext) as ClassType;
const specializedTuple = applySolvedTypeVars(tupleClass, tupleTypeVarContext) as ClassType;
if (!specializedTuple.typeArguments || specializedTuple.typeArguments.length !== 1) {
return undefined;
}
@ -8636,11 +8610,9 @@ export function createTypeEvaluator(
} else if (
effectiveTargetClass &&
!isAnyOrUnknown(effectiveTargetClass) &&
!derivesFromAnyOrUnknown(effectiveTargetClass) &&
objectType &&
isClassInstance(objectType)
!derivesFromAnyOrUnknown(effectiveTargetClass)
) {
resultType = ClassType.cloneAsInstantiable(objectType);
resultType = objectClass ?? UnknownType.create();
} else {
resultType = UnknownType.create();
}
@ -8693,9 +8665,9 @@ export function createTypeEvaluator(
}
// There's not much we can say about the type. Simply return object or type.
if (objectType && isClassInstance(objectType) && typeClassType && isInstantiableClass(typeClassType)) {
if (typeClass && isInstantiableClass(typeClass)) {
return {
type: resultIsInstance ? objectType : convertToInstance(typeClassType),
type: resultIsInstance ? getObjectType() : convertToInstance(typeClass),
};
}
} else {
@ -10190,7 +10162,7 @@ export function createTypeEvaluator(
// If this is a tuple with specified element types, use those
// specified types rather than using the more generic iterator
// type which will be a union of all element types.
const combinedArgType = combineSameSizedTuples(makeTopLevelTypeVarsConcrete(argType), tupleClassType);
const combinedArgType = combineSameSizedTuples(makeTopLevelTypeVarsConcrete(argType), tupleClass);
if (isClassInstance(combinedArgType) && isTupleClass(combinedArgType)) {
const tupleTypeArgs = combinedArgType.tupleTypeArguments ?? [];
@ -10848,13 +10820,13 @@ export function createTypeEvaluator(
const strObjType = getBuiltInObject(errorNode, 'str');
if (
supportsKeysAndGetItemProtocolType &&
isInstantiableClass(supportsKeysAndGetItemProtocolType) &&
supportsKeysAndGetItemClass &&
isInstantiableClass(supportsKeysAndGetItemClass) &&
strObjType &&
isClassInstance(strObjType)
) {
const mappingTypeVarContext = new TypeVarContext(
getTypeVarScopeId(supportsKeysAndGetItemProtocolType)
getTypeVarScopeId(supportsKeysAndGetItemClass)
);
let isValidMappingType = false;
@ -10864,14 +10836,14 @@ export function createTypeEvaluator(
isValidMappingType = true;
} else if (
assignType(
ClassType.cloneAsInstance(supportsKeysAndGetItemProtocolType),
ClassType.cloneAsInstance(supportsKeysAndGetItemClass),
argType,
/* diag */ undefined,
mappingTypeVarContext
)
) {
const specializedMapping = applySolvedTypeVars(
supportsKeysAndGetItemProtocolType,
supportsKeysAndGetItemClass,
mappingTypeVarContext
) as ClassType;
const typeArgs = specializedMapping.typeArguments;
@ -11740,7 +11712,7 @@ export function createTypeEvaluator(
specializedReturnType.typeArguments &&
specializedReturnType.typeArguments.length > 0
) {
if (boolClassType && isInstantiableClass(boolClassType)) {
if (boolClass && isInstantiableClass(boolClass)) {
let typeGuardType = specializedReturnType.typeArguments[0];
// If the first argument is a simple (non-constrained) TypeVar,
@ -11760,7 +11732,7 @@ export function createTypeEvaluator(
const useTypeIsSemantics = ClassType.isBuiltIn(specializedReturnType, 'TypeIs');
specializedReturnType = ClassType.cloneAsInstance(
ClassType.cloneForTypeGuard(boolClassType, typeGuardType, useTypeIsSemantics)
ClassType.cloneForTypeGuard(boolClass, typeGuardType, useTypeIsSemantics)
);
}
}
@ -13030,9 +13002,7 @@ export function createTypeEvaluator(
let isBaseClassAny = false;
if (isAnyOrUnknown(baseClass)) {
if (objectType && isClassInstance(objectType)) {
baseClass = ClassType.cloneAsInstantiable(objectType);
}
baseClass = objectClass ?? UnknownType.create();
addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
@ -13192,7 +13162,12 @@ export function createTypeEvaluator(
let type: Type | undefined;
if (node.constType === KeywordType.None) {
type = (flags & EvaluatorFlags.ExpectingInstantiableType) !== 0 ? noneClassType : noneType;
if (noneTypeClass) {
type =
(flags & EvaluatorFlags.ExpectingInstantiableType) !== 0
? noneTypeClass
: convertToInstance(noneTypeClass);
}
} else if (
node.constType === KeywordType.True ||
node.constType === KeywordType.False ||
@ -13294,16 +13269,16 @@ export function createTypeEvaluator(
}
if (isNoneInstance(subtype)) {
if (objectType && isClassInstance(objectType)) {
if (objectClass && isInstantiableClass(objectClass)) {
// Use 'object' for 'None'.
return handleSubtype(objectType);
return handleSubtype(convertToInstance(objectClass));
}
}
if (isNoneTypeClass(subtype)) {
if (typeClassType && isInstantiableClass(typeClassType)) {
if (typeClass && isInstantiableClass(typeClass)) {
// Use 'type' for 'type[None]'.
return handleSubtype(ClassType.cloneAsInstance(typeClassType));
return handleSubtype(ClassType.cloneAsInstance(typeClass));
}
}
@ -13754,10 +13729,10 @@ export function createTypeEvaluator(
} else if (entryNode.nodeType === ParseNodeType.DictionaryExpandEntry) {
let expectedType: Type | undefined;
if (expectedKeyType && expectedValueType) {
if (supportsKeysAndGetItemProtocolType && isInstantiableClass(supportsKeysAndGetItemProtocolType)) {
if (supportsKeysAndGetItemClass && isInstantiableClass(supportsKeysAndGetItemClass)) {
expectedType = ClassType.cloneAsInstance(
ClassType.cloneForSpecialization(
supportsKeysAndGetItemProtocolType,
supportsKeysAndGetItemClass,
[expectedKeyType, expectedValueType],
/* isTypeArgumentExplicit */ true
)
@ -13797,8 +13772,8 @@ export function createTypeEvaluator(
addUnknown = false;
} else if (isClassInstance(unexpandedType) && ClassType.isTypedDictClass(unexpandedType)) {
// Handle dictionary expansion for a TypedDict.
if (strClassType && isInstantiableClass(strClassType)) {
const strObject = ClassType.cloneAsInstance(strClassType);
if (strClass && isInstantiableClass(strClass)) {
const strObject = ClassType.cloneAsInstance(strClass);
const tdEntries = getTypedDictMembersForClass(
evaluatorInterface,
unexpandedType,
@ -13819,25 +13794,20 @@ export function createTypeEvaluator(
keyTypes.push({ node: entryNode, type: ClassType.cloneAsInstance(strObject) });
valueTypes.push({
node: entryNode,
type: tdEntries.extraItems?.valueType ?? objectType ?? UnknownType.create(),
type: tdEntries.extraItems?.valueType ?? getObjectType(),
});
}
addUnknown = false;
}
} else if (
supportsKeysAndGetItemProtocolType &&
isInstantiableClass(supportsKeysAndGetItemProtocolType)
) {
const mappingTypeVarContext = new TypeVarContext(
getTypeVarScopeId(supportsKeysAndGetItemProtocolType)
);
} else if (supportsKeysAndGetItemClass && isInstantiableClass(supportsKeysAndGetItemClass)) {
const mappingTypeVarContext = new TypeVarContext(getTypeVarScopeId(supportsKeysAndGetItemClass));
supportsKeysAndGetItemProtocolType = selfSpecializeClass(supportsKeysAndGetItemProtocolType);
supportsKeysAndGetItemClass = selfSpecializeClass(supportsKeysAndGetItemClass);
if (
assignType(
ClassType.cloneAsInstance(supportsKeysAndGetItemProtocolType),
ClassType.cloneAsInstance(supportsKeysAndGetItemClass),
unexpandedType,
/* diag */ undefined,
mappingTypeVarContext,
@ -13846,7 +13816,7 @@ export function createTypeEvaluator(
)
) {
const specializedMapping = applySolvedTypeVars(
supportsKeysAndGetItemProtocolType,
supportsKeysAndGetItemClass,
mappingTypeVarContext
) as ClassType;
const typeArgs = specializedMapping.typeArguments;
@ -14994,9 +14964,9 @@ export function createTypeEvaluator(
typeArg0Type = UnknownType.create();
}
let optionalType = combineTypes([typeArg0Type, noneClassType ?? UnknownType.create()]);
if (unionClassType && isInstantiableClass(unionClassType)) {
optionalType = TypeBase.cloneAsSpecialForm(optionalType, ClassType.cloneAsInstance(unionClassType));
let optionalType = combineTypes([typeArg0Type, noneTypeClass ?? UnknownType.create()]);
if (unionClass && isInstantiableClass(unionClass)) {
optionalType = TypeBase.cloneAsSpecialForm(optionalType, ClassType.cloneAsInstance(unionClass));
}
return optionalType;
@ -15076,7 +15046,7 @@ export function createTypeEvaluator(
} else if (itemExpr.constType === KeywordType.False) {
type = cloneBuiltinClassWithLiteral(node, classType, 'bool', false);
} else if (itemExpr.constType === KeywordType.None) {
type = noneClassType ?? UnknownType.create();
type = noneTypeClass ?? UnknownType.create();
}
} else if (itemExpr.nodeType === ParseNodeType.UnaryOperation) {
if (itemExpr.operator === OperatorType.Subtract || itemExpr.operator === OperatorType.Add) {
@ -15133,8 +15103,8 @@ export function createTypeEvaluator(
let result = combineTypes(literalTypes);
if (isUnion(result) && unionClassType && isInstantiableClass(unionClassType)) {
result = TypeBase.cloneAsSpecialForm(result, ClassType.cloneAsInstance(unionClassType));
if (isUnion(result) && unionClass && isInstantiableClass(unionClass)) {
result = TypeBase.cloneAsSpecialForm(result, ClassType.cloneAsInstance(unionClass));
}
return result;
@ -15708,8 +15678,8 @@ export function createTypeEvaluator(
}
let unionType = combineTypes(types);
if (unionClassType && isInstantiableClass(unionClassType)) {
unionType = TypeBase.cloneAsSpecialForm(unionType, ClassType.cloneAsInstance(unionClassType));
if (unionClass && isInstantiableClass(unionClass)) {
unionType = TypeBase.cloneAsSpecialForm(unionType, ClassType.cloneAsInstance(unionClass));
}
return unionType;
@ -16024,7 +15994,7 @@ export function createTypeEvaluator(
// Handle 'LiteralString' specially because we want it to act as
// though it derives from 'str'.
if (assignedName === 'LiteralString') {
specialType.details.baseClasses.push(strClassType ?? AnyType.create());
specialType.details.baseClasses.push(strClass ?? AnyType.create());
computeMroLinearization(specialType);
}
@ -16415,7 +16385,7 @@ export function createTypeEvaluator(
}
function getTypeOfClass(node: ClassNode): ClassTypeResult | undefined {
initializedBasicTypes(node);
initializePrefetchedTypes(node);
// Is this type already cached?
const cachedClassType = readTypeCache(node.name, EvaluatorFlags.None);
@ -17266,10 +17236,6 @@ export function createTypeEvaluator(
return;
}
if (!objectType || !isClassInstance(objectType)) {
return;
}
// Presumptively mark the variance inference as complete. This
// prevents potential recursion.
classType.details.requiresVarianceInference = false;
@ -17310,8 +17276,7 @@ export function createTypeEvaluator(
if (p.details.isVariadic) {
return p;
}
assert(objectType !== undefined);
return i === paramIndex ? objectType : dummyTypeObject;
return i === paramIndex ? getObjectType() : dummyTypeObject;
});
// Replace all type arguments with a dummy type except for the
@ -17388,7 +17353,7 @@ export function createTypeEvaluator(
if (!effectiveMetaclass || isInstantiableClass(effectiveMetaclass)) {
for (const baseClass of classType.details.baseClasses) {
if (isInstantiableClass(baseClass)) {
const baseClassMeta = baseClass.details.effectiveMetaclass || typeClassType;
const baseClassMeta = baseClass.details.effectiveMetaclass || typeClass;
if (baseClassMeta && isInstantiableClass(baseClassMeta)) {
// Make sure there is no metaclass conflict.
if (!effectiveMetaclass) {
@ -17704,7 +17669,7 @@ export function createTypeEvaluator(
}
function getTypeOfFunction(node: FunctionNode): FunctionTypeResult | undefined {
initializedBasicTypes(node);
initializePrefetchedTypes(node);
// Is this predecorated function type cached?
let functionType = readTypeCache(node.name, EvaluatorFlags.None);
@ -19740,7 +19705,7 @@ export function createTypeEvaluator(
// be evaluated to provide sufficient context for the type. Evaluated types
// are written back to the type cache for later retrieval.
function evaluateTypesForStatement(node: ParseNode): void {
initializedBasicTypes(node);
initializePrefetchedTypes(node);
let curNode: ParseNode | undefined = node;
@ -20139,9 +20104,9 @@ export function createTypeEvaluator(
}
}
if (typeClassType && isInstantiableClass(typeClassType)) {
if (typeClass && isInstantiableClass(typeClass)) {
let typeType = createSpecialType(
typeClassType,
typeClass,
typeArgs,
1,
/* allowParamSpec */ undefined,
@ -22344,7 +22309,7 @@ export function createTypeEvaluator(
getEffectiveTypeOfSymbol(member.symbol),
member.classType,
/* selfClass */ undefined,
typeClassType ?? UnknownType.create()
typeClass ?? UnknownType.create()
);
}
return UnknownType.create();
@ -22476,14 +22441,14 @@ export function createTypeEvaluator(
if (
mappingValueType &&
mappingType &&
isInstantiableClass(mappingType) &&
strClassType &&
isInstantiableClass(strClassType)
mappingClass &&
isInstantiableClass(mappingClass) &&
strClass &&
isInstantiableClass(strClass)
) {
srcType = ClassType.cloneForSpecialization(
mappingType,
[ClassType.cloneAsInstance(strClassType), mappingValueType],
mappingClass,
[ClassType.cloneAsInstance(strClass), mappingValueType],
/* isTypeArgumentExplicit */ true
);
}
@ -22492,14 +22457,14 @@ export function createTypeEvaluator(
if (
dictValueType &&
dictClassType &&
isInstantiableClass(dictClassType) &&
strClassType &&
isInstantiableClass(strClassType)
dictClass &&
isInstantiableClass(dictClass) &&
strClass &&
isInstantiableClass(strClass)
) {
srcType = ClassType.cloneForSpecialization(
dictClassType,
[ClassType.cloneAsInstance(strClassType), dictValueType],
dictClass,
[ClassType.cloneAsInstance(strClass), dictValueType],
/* isTypeArgumentExplicit */ true
);
}
@ -22840,7 +22805,7 @@ export function createTypeEvaluator(
const skipAdjustment =
destArgsToCapture === 1 && isVariadicTypeVar(destTypeArgs[srcVariadicIndex].type);
if (!skipAdjustment && tupleClassType && isInstantiableClass(tupleClassType)) {
if (!skipAdjustment && tupleClass && isInstantiableClass(tupleClass)) {
const removedArgs = destTypeArgs.splice(srcVariadicIndex, destArgsToCapture);
// Package up the remaining type arguments into a tuple object.
@ -22868,7 +22833,7 @@ export function createTypeEvaluator(
// If the dest contains a variadic element, determine which source
// args map to this element and package them up into an unpacked tuple.
if (isVariadicTypeVar(destTypeArgs[destUnboundedOrVariadicIndex].type)) {
if (tupleClassType && isInstantiableClass(tupleClassType)) {
if (tupleClass && isInstantiableClass(tupleClass)) {
const removedArgs = srcTypeArgs.splice(destUnboundedOrVariadicIndex, srcArgsToCapture);
let variadicTuple: Type;
@ -23929,11 +23894,11 @@ export function createTypeEvaluator(
}
} else if (
ClassType.isBuiltIn(concreteSrcType, 'LiteralString') &&
strClassType &&
isInstantiableClass(strClassType) &&
strClass &&
isInstantiableClass(strClass) &&
(flags & AssignTypeFlags.EnforceInvariance) === 0
) {
concreteSrcType = ClassType.cloneAsInstance(strClassType);
concreteSrcType = ClassType.cloneAsInstance(strClass);
}
if (
@ -23968,10 +23933,10 @@ export function createTypeEvaluator(
}
// All functions are considered instances of "builtins.function".
if (functionObj && isClassInstance(functionObj)) {
if (functionClass) {
return assignType(
destType,
functionObj,
convertToInstance(functionClass),
diag,
destTypeVarContext,
srcTypeVarContext,
@ -24248,11 +24213,11 @@ export function createTypeEvaluator(
// Are we trying to assign None to a protocol?
if (isNoneInstance(srcType) && isClassInstance(destType) && ClassType.isProtocolClass(destType)) {
if (noneClassType && isInstantiableClass(noneClassType)) {
if (noneTypeClass && isInstantiableClass(noneTypeClass)) {
return assignClassToProtocol(
evaluatorInterface,
ClassType.cloneAsInstantiable(destType),
ClassType.cloneAsInstance(noneClassType),
ClassType.cloneAsInstance(noneTypeClass),
diag,
destTypeVarContext,
srcTypeVarContext,
@ -24930,8 +24895,8 @@ export function createTypeEvaluator(
if (field[0] !== '__call__' && !field[1].isIgnoredForProtocolMatch()) {
let fieldIsPartOfFunction = false;
if (functionObj && isClass(functionObj)) {
if (ClassType.getSymbolTable(functionObj).has(field[0])) {
if (functionClass && isClass(functionClass)) {
if (ClassType.getSymbolTable(functionClass).has(field[0])) {
fieldIsPartOfFunction = true;
}
}
@ -25873,13 +25838,13 @@ export function createTypeEvaluator(
if (
isClassInstance(srcReturnType) &&
ClassType.isBuiltIn(srcReturnType, ['TypeGuard', 'TypeIs']) &&
boolClassType &&
isInstantiableClass(boolClassType)
boolClass &&
isInstantiableClass(boolClass)
) {
if (
assignType(
destReturnType,
ClassType.cloneAsInstance(boolClassType),
ClassType.cloneAsInstance(boolClass),
returnDiag?.createAddendum(),
destTypeVarContext,
srcTypeVarContext,