mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-03 19:37:39 +03:00
Fixed bug that results in the incorrect default value of a variadic type variable when the type argument is not provided. It should default to *tuple[Any, ...]
, not *tuple[Any]
. This addresses #8285.
This commit is contained in:
parent
74846de568
commit
21efa0ecf8
@ -290,7 +290,7 @@ function validateNewAndInitMethods(
|
||||
newMethodReturnType = applySolvedTypeVars(
|
||||
ClassType.cloneAsInstance(type),
|
||||
new TypeVarContext(getTypeVarScopeId(type)),
|
||||
{ unknownIfNotFound: true }
|
||||
{ unknownIfNotFound: true, tupleClassType: evaluator.getTupleClassType() }
|
||||
) as ClassType;
|
||||
}
|
||||
|
||||
@ -824,6 +824,7 @@ function applyExpectedTypeForConstructor(
|
||||
|
||||
const specializedType = applySolvedTypeVars(type, typeVarContext, {
|
||||
unknownIfNotFound: unsolvedTypeVarsAreUnknown,
|
||||
tupleClassType: evaluator.getTupleClassType(),
|
||||
}) as ClassType;
|
||||
return ClassType.cloneAsInstance(specializedType);
|
||||
}
|
||||
@ -1118,7 +1119,10 @@ function createFunctionFromInitMethod(
|
||||
}
|
||||
});
|
||||
|
||||
returnType = applySolvedTypeVars(objectType, typeVarContext, { unknownIfNotFound: true }) as ClassType;
|
||||
returnType = applySolvedTypeVars(objectType, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: evaluator.getTupleClassType(),
|
||||
}) as ClassType;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -821,7 +821,10 @@ function getConverterInputType(
|
||||
const inputTypeVarContext = new TypeVarContext(typeVar.scopeId);
|
||||
|
||||
if (evaluator.assignType(targetFunction, signature, diagAddendum, inputTypeVarContext)) {
|
||||
const overloadSolution = applySolvedTypeVars(typeVar, inputTypeVarContext, { unknownIfNotFound: true });
|
||||
const overloadSolution = applySolvedTypeVars(typeVar, inputTypeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: evaluator.getTupleClassType(),
|
||||
});
|
||||
acceptedTypes.push(overloadSolution);
|
||||
}
|
||||
});
|
||||
|
@ -685,7 +685,7 @@ function narrowTypeBasedOnClassPattern(
|
||||
// specialize it with Unknown type arguments.
|
||||
if (isClass(exprType) && !exprType.typeAliasInfo) {
|
||||
exprType = ClassType.cloneRemoveTypePromotions(exprType);
|
||||
exprType = specializeWithUnknownTypeArgs(exprType);
|
||||
exprType = specializeWithUnknownTypeArgs(exprType, evaluator.getTupleClassType());
|
||||
}
|
||||
|
||||
// Are there any positional arguments? If so, try to get the mappings for
|
||||
@ -932,6 +932,7 @@ function narrowTypeBasedOnClassPattern(
|
||||
) {
|
||||
resultType = applySolvedTypeVars(matchTypeInstance, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: evaluator.getTupleClassType(),
|
||||
}) as ClassType;
|
||||
}
|
||||
}
|
||||
|
@ -4926,7 +4926,10 @@ export function createTypeEvaluator(
|
||||
|
||||
let defaultType: Type;
|
||||
if (param.details.isDefaultExplicit || param.details.isParamSpec) {
|
||||
defaultType = applySolvedTypeVars(param, typeVarContext, { unknownIfNotFound: true });
|
||||
defaultType = applySolvedTypeVars(param, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
});
|
||||
} else if (param.details.isVariadic && tupleClass && isInstantiableClass(tupleClass)) {
|
||||
defaultType = makeTupleObject(
|
||||
[{ type: UnknownType.create(), isUnbounded: true }],
|
||||
@ -4951,7 +4954,10 @@ export function createTypeEvaluator(
|
||||
}
|
||||
|
||||
type = TypeBase.cloneForTypeAlias(
|
||||
applySolvedTypeVars(type, typeVarContext, { unknownIfNotFound: true }),
|
||||
applySolvedTypeVars(type, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
}),
|
||||
type.typeAliasInfo.name,
|
||||
type.typeAliasInfo.fullName,
|
||||
type.typeAliasInfo.moduleName,
|
||||
@ -6855,7 +6861,10 @@ export function createTypeEvaluator(
|
||||
if (index < typeArgs.length) {
|
||||
typeArgType = convertToInstance(typeArgs[index].type);
|
||||
} else if (param.details.isDefaultExplicit) {
|
||||
typeArgType = applySolvedTypeVars(param, typeVarContext, { unknownIfNotFound: true });
|
||||
typeArgType = applySolvedTypeVars(param, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
});
|
||||
} else {
|
||||
typeArgType = UnknownType.create();
|
||||
}
|
||||
@ -11333,6 +11342,7 @@ export function createTypeEvaluator(
|
||||
|
||||
effectiveExpectedType = applySolvedTypeVars(genericReturnType, tempTypeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
});
|
||||
|
||||
effectiveFlags |= AssignTypeFlags.SkipPopulateUnknownExpectedType;
|
||||
@ -11633,6 +11643,7 @@ export function createTypeEvaluator(
|
||||
|
||||
let specializedReturnType = applySolvedTypeVars(returnType, typeVarContext, {
|
||||
unknownIfNotFound,
|
||||
tupleClassType: getTupleClassType(),
|
||||
unknownExemptTypeVars: getUnknownExemptTypeVarsForReturnType(type, returnType),
|
||||
eliminateUnsolvedInUnions,
|
||||
applyInScopePlaceholders: true,
|
||||
@ -12516,6 +12527,7 @@ export function createTypeEvaluator(
|
||||
const concreteDefaultType = makeTopLevelTypeVarsConcrete(
|
||||
applySolvedTypeVars(typeVar.details.defaultType, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
})
|
||||
);
|
||||
|
||||
@ -18334,6 +18346,7 @@ export function createTypeEvaluator(
|
||||
// Replace any unsolved TypeVars with Unknown (including all function-scoped TypeVars).
|
||||
inferredParamType = applySolvedTypeVars(inferredParamType, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
});
|
||||
}
|
||||
|
||||
@ -20388,7 +20401,10 @@ export function createTypeEvaluator(
|
||||
return;
|
||||
}
|
||||
|
||||
const solvedDefaultType = applySolvedTypeVars(typeParam, typeVarContext, { unknownIfNotFound: true });
|
||||
const solvedDefaultType = applySolvedTypeVars(typeParam, typeVarContext, {
|
||||
unknownIfNotFound: true,
|
||||
tupleClassType: getTupleClassType(),
|
||||
});
|
||||
typeArgTypes.push(solvedDefaultType);
|
||||
if (isParamSpec(typeParam)) {
|
||||
typeVarContext.setTypeVarType(typeParam, convertTypeToParamSpecValue(solvedDefaultType));
|
||||
@ -22360,7 +22376,7 @@ export function createTypeEvaluator(
|
||||
getEffectiveTypeOfSymbol(member.symbol),
|
||||
member.classType,
|
||||
/* selfClass */ undefined,
|
||||
typeClass ?? UnknownType.create()
|
||||
typeClass && isInstantiableClass(typeClass) ? typeClass : undefined
|
||||
);
|
||||
}
|
||||
return UnknownType.create();
|
||||
|
@ -638,7 +638,7 @@ export function getTypeNarrowingCallback(
|
||||
);
|
||||
const arg1Type = arg1TypeResult.type;
|
||||
|
||||
const classTypeList = getIsInstanceClassTypes(arg1Type);
|
||||
const classTypeList = getIsInstanceClassTypes(evaluator, arg1Type);
|
||||
const isIncomplete = !!callTypeResult.isIncomplete || !!arg1TypeResult.isIncomplete;
|
||||
|
||||
if (classTypeList) {
|
||||
@ -1146,7 +1146,10 @@ function narrowTypeForIsEllipsis(evaluator: TypeEvaluator, type: Type, isPositiv
|
||||
// that accepts a single class, and a more complex form that accepts a tuple
|
||||
// of classes (including arbitrarily-nested tuples). This method determines
|
||||
// which form and returns a list of classes or undefined.
|
||||
function getIsInstanceClassTypes(argType: Type): (ClassType | TypeVarType | FunctionType)[] | undefined {
|
||||
function getIsInstanceClassTypes(
|
||||
evaluator: TypeEvaluator,
|
||||
argType: Type
|
||||
): (ClassType | TypeVarType | FunctionType)[] | undefined {
|
||||
let foundNonClassType = false;
|
||||
const classTypeList: (ClassType | TypeVarType | FunctionType)[] = [];
|
||||
|
||||
@ -1155,7 +1158,7 @@ function getIsInstanceClassTypes(argType: Type): (ClassType | TypeVarType | Func
|
||||
const addClassTypesToList = (types: Type[]) => {
|
||||
types.forEach((subtype) => {
|
||||
if (isClass(subtype)) {
|
||||
subtype = specializeWithUnknownTypeArgs(subtype);
|
||||
subtype = specializeWithUnknownTypeArgs(subtype, evaluator.getTupleClassType());
|
||||
|
||||
if (isInstantiableClass(subtype) && ClassType.isBuiltIn(subtype, 'Callable')) {
|
||||
subtype = convertToInstantiable(getUnknownTypeForCallable());
|
||||
@ -1359,7 +1362,8 @@ function narrowTypeForIsInstanceInternal(
|
||||
concreteFilterType,
|
||||
/* typeArguments */ undefined,
|
||||
/* isTypeArgumentExplicit */ false
|
||||
)
|
||||
),
|
||||
evaluator.getTupleClassType()
|
||||
);
|
||||
}
|
||||
|
||||
@ -1463,7 +1467,11 @@ function narrowTypeForIsInstanceInternal(
|
||||
specializedFilterType = applySolvedTypeVars(
|
||||
unspecializedFilterType,
|
||||
typeVarContext,
|
||||
{ unknownIfNotFound: true, useUnknownOverDefault: true }
|
||||
{
|
||||
unknownIfNotFound: true,
|
||||
useUnknownOverDefault: true,
|
||||
tupleClassType: evaluator.getTupleClassType(),
|
||||
}
|
||||
) as ClassType;
|
||||
}
|
||||
}
|
||||
|
@ -245,12 +245,13 @@ export const enum AssignTypeFlags {
|
||||
}
|
||||
|
||||
export interface ApplyTypeVarOptions {
|
||||
typeClassType?: ClassType;
|
||||
tupleClassType?: ClassType;
|
||||
unknownIfNotFound?: boolean;
|
||||
useUnknownOverDefault?: boolean;
|
||||
unknownExemptTypeVars?: TypeVarType[];
|
||||
useNarrowBoundOnly?: boolean;
|
||||
eliminateUnsolvedInUnions?: boolean;
|
||||
typeClassType?: Type;
|
||||
applyInScopePlaceholders?: boolean;
|
||||
}
|
||||
|
||||
@ -1073,7 +1074,7 @@ export function specializeWithDefaultTypeArgs(type: ClassType): ClassType {
|
||||
|
||||
// Specializes the class with "Unknown" type args (or the equivalent for ParamSpecs
|
||||
// or TypeVarTuples).
|
||||
export function specializeWithUnknownTypeArgs(type: ClassType): ClassType {
|
||||
export function specializeWithUnknownTypeArgs(type: ClassType, tupleClassType?: ClassType): ClassType {
|
||||
if (type.details.typeParameters.length === 0) {
|
||||
return type;
|
||||
}
|
||||
@ -1091,18 +1092,22 @@ export function specializeWithUnknownTypeArgs(type: ClassType): ClassType {
|
||||
|
||||
return ClassType.cloneForSpecialization(
|
||||
type,
|
||||
type.details.typeParameters.map((param) => getUnknownTypeForTypeVar(param)),
|
||||
type.details.typeParameters.map((param) => getUnknownTypeForTypeVar(param, tupleClassType)),
|
||||
/* isTypeArgumentExplicit */ false,
|
||||
/* includeSubclasses */ type.includeSubclasses
|
||||
);
|
||||
}
|
||||
|
||||
// Returns "Unknown" for simple TypeVars or the equivalent for a ParamSpec.
|
||||
export function getUnknownTypeForTypeVar(typeVar: TypeVarType): Type {
|
||||
export function getUnknownTypeForTypeVar(typeVar: TypeVarType, tupleClassType?: ClassType): Type {
|
||||
if (typeVar.details.isParamSpec) {
|
||||
return getUnknownTypeForParamSpec();
|
||||
}
|
||||
|
||||
if (typeVar.details.isVariadic && tupleClassType) {
|
||||
return getUnknownTypeForVariadicTypeVar(tupleClassType);
|
||||
}
|
||||
|
||||
return UnknownType.create();
|
||||
}
|
||||
|
||||
@ -1118,6 +1123,19 @@ export function getUnknownTypeForParamSpec(): FunctionType {
|
||||
return newFunction;
|
||||
}
|
||||
|
||||
export function getUnknownTypeForVariadicTypeVar(tupleClassType: ClassType): Type {
|
||||
assert(isInstantiableClass(tupleClassType) && ClassType.isBuiltIn(tupleClassType, 'tuple'));
|
||||
|
||||
return ClassType.cloneAsInstance(
|
||||
specializeTupleClass(
|
||||
tupleClassType,
|
||||
[{ type: UnknownType.create(), isUnbounded: true }],
|
||||
/* isTypeArgumentExplicit */ true,
|
||||
/* isUnpackedTuple */ true
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
// Returns the equivalent of "Callable[..., Unknown]".
|
||||
export function getUnknownTypeForCallable(): FunctionType {
|
||||
const newFunction = FunctionType.createSynthesizedInstance('', FunctionTypeFlags.GradualCallableForm);
|
||||
@ -1374,7 +1392,7 @@ export function partiallySpecializeType(
|
||||
type: Type,
|
||||
contextClassType: ClassType,
|
||||
selfClass?: ClassType | TypeVarType,
|
||||
typeClassType?: Type
|
||||
typeClassType?: ClassType
|
||||
): Type {
|
||||
// If the context class is not specialized (or doesn't need specialization),
|
||||
// then there's no need to do any more work.
|
||||
@ -4133,7 +4151,7 @@ class ApplySolvedTypeVarsTransformer extends TypeVarTransformer {
|
||||
|
||||
if (this._options.unknownIfNotFound) {
|
||||
return this._options.useUnknownOverDefault
|
||||
? specializeWithUnknownTypeArgs(subtype)
|
||||
? specializeWithUnknownTypeArgs(subtype, this._options.tupleClassType)
|
||||
: specializeWithDefaultTypeArgs(subtype);
|
||||
}
|
||||
}
|
||||
@ -4171,7 +4189,7 @@ class ApplySolvedTypeVarsTransformer extends TypeVarTransformer {
|
||||
return this._solveDefaultType(typeVar.details.defaultType, recursionCount);
|
||||
}
|
||||
|
||||
return UnknownType.create();
|
||||
return getUnknownTypeForTypeVar(typeVar, this._options.tupleClassType);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -18,13 +18,16 @@ class Array(Generic[Unpack[_Xs]]):
|
||||
reveal_type(args, expected_text="tuple[*_Xs@Array]")
|
||||
|
||||
# This should generate an error because _Xs is not unpacked.
|
||||
def foo(self, *args: _Xs) -> None: ...
|
||||
def foo(self, *args: _Xs) -> None:
|
||||
...
|
||||
|
||||
|
||||
def linearize(value: Array[Unpack[_Xs]]) -> tuple[Unpack[_Xs]]: ...
|
||||
def linearize(value: Array[Unpack[_Xs]]) -> tuple[Unpack[_Xs]]:
|
||||
...
|
||||
|
||||
|
||||
def array_to_tuple(value: Array[Unpack[_Xs]]) -> tuple[complex, Unpack[_Xs]]: ...
|
||||
def array_to_tuple(value: Array[Unpack[_Xs]]) -> tuple[complex, Unpack[_Xs]]:
|
||||
...
|
||||
|
||||
|
||||
def func1(x: Array[int, str, str, float], y: Array[()]):
|
||||
@ -88,12 +91,23 @@ def func3(x: Array[Unpack[_Xs]]) -> Array[Unpack[_Xs]]:
|
||||
|
||||
|
||||
@overload
|
||||
def func4(signal: Array[*_Xs], *args: *_Xs) -> None: ...
|
||||
def func4(signal: Array[*_Xs], *args: *_Xs) -> None:
|
||||
...
|
||||
|
||||
|
||||
@overload
|
||||
def func4(signal: str, *args: Any) -> None: ...
|
||||
def func4(signal: Array[*_Xs] | str, *args: *_Xs) -> None: ...
|
||||
def func4(signal: str, *args: Any) -> None:
|
||||
...
|
||||
|
||||
|
||||
def func4(signal: Array[*_Xs] | str, *args: *_Xs) -> None:
|
||||
...
|
||||
|
||||
|
||||
def func5(a1: Array[Literal["a", "b"]], a2: Array[Literal["a"], Literal["b"]]):
|
||||
func4(a1, "a")
|
||||
func4(a2, "a", "b")
|
||||
|
||||
|
||||
def func6(a: Array):
|
||||
reveal_type(a, expected_text="Array[*tuple[Unknown, ...]]")
|
||||
|
Loading…
Reference in New Issue
Block a user