Merge branch 'main' into add-azure-devops-release

This commit is contained in:
Bill Schnurr 2024-07-02 11:56:06 -07:00 committed by GitHub
commit ba50f35bb1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
572 changed files with 4067 additions and 4145 deletions

View File

@ -35,7 +35,7 @@ jobs:
contents: read contents: read
strategy: strategy:
matrix: matrix:
shard-index: [0, 1] shard-index: [0, 1, 2, 3, 4, 5, 6, 7]
fail-fast: false fail-fast: false
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@ -69,7 +69,7 @@ jobs:
--repo pyright_to_test \ --repo pyright_to_test \
--type-checker pyright \ --type-checker pyright \
--new $GITHUB_SHA --old base_commit \ --new $GITHUB_SHA --old base_commit \
--num-shards 2 --shard-index ${{ matrix.shard-index }} \ --num-shards 8 --shard-index ${{ matrix.shard-index }} \
--debug \ --debug \
--output concise \ --output concise \
| tee diff_${{ matrix.shard-index }}.txt | tee diff_${{ matrix.shard-index }}.txt

View File

@ -3092,106 +3092,123 @@ export class Checker extends ParseTreeWalker {
private _reportInvalidOverload(name: string, symbol: Symbol) { private _reportInvalidOverload(name: string, symbol: Symbol) {
const typedDecls = symbol.getTypedDeclarations(); const typedDecls = symbol.getTypedDeclarations();
if (typedDecls.length >= 1) { if (typedDecls.length === 0) {
const primaryDecl = typedDecls[0]; return;
}
if (primaryDecl.type === DeclarationType.Function) { const primaryDecl = typedDecls[0];
const type = this._evaluator.getEffectiveTypeOfSymbol(symbol);
const overloadedFunctions = isOverloadedFunction(type)
? OverloadedFunctionType.getOverloads(type)
: isFunction(type) && FunctionType.isOverloaded(type)
? [type]
: [];
if (overloadedFunctions.length === 1) { if (primaryDecl.type !== DeclarationType.Function) {
// There should never be a single overload. return;
this._evaluator.addDiagnostic( }
DiagnosticRule.reportInconsistentOverload,
LocMessage.singleOverload().format({ name }),
primaryDecl.node.name
);
}
// If the file is not a stub and this is the first overload, const type = this._evaluator.getEffectiveTypeOfSymbol(symbol);
// verify that there is an implementation. const overloadedFunctions = isOverloadedFunction(type)
if (!this._fileInfo.isStubFile && overloadedFunctions.length > 0) { ? OverloadedFunctionType.getOverloads(type)
let implementationFunction: FunctionType | undefined; : isFunction(type) && FunctionType.isOverloaded(type)
let exemptMissingImplementation = false; ? [type]
: [];
if (isOverloadedFunction(type)) { // If the implementation has no name, it was synthesized probably by a
implementationFunction = OverloadedFunctionType.getImplementation(type); // decorator that used a callable with a ParamSpec that captured the
// overloaded signature. We'll exempt it from this check.
if (isOverloadedFunction(type)) {
const overloads = OverloadedFunctionType.getOverloads(type);
if (overloads.length > 0 && overloads[0].details.name === '') {
return;
}
} else if (isFunction(type)) {
if (type.details.name === '') {
return;
}
}
// If the implementation has no name, it was synthesized probably by a if (overloadedFunctions.length === 1) {
// decorator that used a callable with a ParamSpec that captured the // There should never be a single overload.
// overloaded signature. We'll exempt it from this check. this._evaluator.addDiagnostic(
const overloads = OverloadedFunctionType.getOverloads(type); DiagnosticRule.reportInconsistentOverload,
if (overloads.length > 0 && overloads[0].details.name === '') { LocMessage.singleOverload().format({ name }),
exemptMissingImplementation = true; primaryDecl.node.name
} );
} else if (isFunction(type) && !FunctionType.isOverloaded(type)) { }
implementationFunction = type;
// If the file is not a stub and this is the first overload,
// verify that there is an implementation.
if (this._fileInfo.isStubFile || overloadedFunctions.length === 0) {
return;
}
let implementationFunction: FunctionType | undefined;
if (isOverloadedFunction(type)) {
implementationFunction = OverloadedFunctionType.getImplementation(type);
} else if (isFunction(type) && !FunctionType.isOverloaded(type)) {
implementationFunction = type;
}
if (!implementationFunction) {
const containingClassNode = ParseTreeUtils.getEnclosingClassOrFunction(primaryDecl.node);
if (containingClassNode && containingClassNode.nodeType === ParseNodeType.Class) {
const classType = this._evaluator.getTypeOfClass(containingClassNode);
if (classType) {
if (ClassType.isProtocolClass(classType.classType)) {
return;
} }
if (!implementationFunction) { if (ClassType.supportsAbstractMethods(classType.classType)) {
const containingClassNode = ParseTreeUtils.getEnclosingClassOrFunction(primaryDecl.node); if (
if (containingClassNode && containingClassNode.nodeType === ParseNodeType.Class) { isOverloadedFunction(type) &&
const classType = this._evaluator.getTypeOfClass(containingClassNode); OverloadedFunctionType.getOverloads(type).every((overload) =>
if (classType) { FunctionType.isAbstractMethod(overload)
if (ClassType.isProtocolClass(classType.classType)) { )
exemptMissingImplementation = true; ) {
} else if (ClassType.supportsAbstractMethods(classType.classType)) { return;
if (
isOverloadedFunction(type) &&
OverloadedFunctionType.getOverloads(type).every((overload) =>
FunctionType.isAbstractMethod(overload)
)
) {
exemptMissingImplementation = true;
}
}
}
} }
// If this is a method within a protocol class, don't require that
// there is an implementation.
if (!exemptMissingImplementation) {
this._evaluator.addDiagnostic(
DiagnosticRule.reportNoOverloadImplementation,
LocMessage.overloadWithoutImplementation().format({
name: primaryDecl.node.name.value,
}),
primaryDecl.node.name
);
}
} else if (isOverloadedFunction(type)) {
// Verify that all overload signatures are assignable to implementation signature.
OverloadedFunctionType.getOverloads(type).forEach((overload, index) => {
const diag = new DiagnosticAddendum();
if (!this._isLegalOverloadImplementation(overload, implementationFunction!, diag)) {
if (implementationFunction!.details.declaration) {
const diagnostic = this._evaluator.addDiagnostic(
DiagnosticRule.reportInconsistentOverload,
LocMessage.overloadImplementationMismatch().format({
name,
index: index + 1,
}) + diag.getString(),
implementationFunction!.details.declaration.node.name
);
if (diagnostic && overload.details.declaration) {
diagnostic.addRelatedInfo(
LocAddendum.overloadSignature(),
overload.details.declaration?.uri ?? primaryDecl.uri,
overload.details.declaration?.range ?? primaryDecl.range
);
}
}
}
});
} }
} }
} }
// If this is a method within a protocol class, don't require that
// there is an implementation.
this._evaluator.addDiagnostic(
DiagnosticRule.reportNoOverloadImplementation,
LocMessage.overloadWithoutImplementation().format({
name: primaryDecl.node.name.value,
}),
primaryDecl.node.name
);
return;
} }
if (!isOverloadedFunction(type)) {
return;
}
// Verify that all overload signatures are assignable to implementation signature.
OverloadedFunctionType.getOverloads(type).forEach((overload, index) => {
const diag = new DiagnosticAddendum();
if (!this._isLegalOverloadImplementation(overload, implementationFunction!, diag)) {
if (implementationFunction!.details.declaration) {
const diagnostic = this._evaluator.addDiagnostic(
DiagnosticRule.reportInconsistentOverload,
LocMessage.overloadImplementationMismatch().format({
name,
index: index + 1,
}) + diag.getString(),
implementationFunction!.details.declaration.node.name
);
if (diagnostic && overload.details.declaration) {
diagnostic.addRelatedInfo(
LocAddendum.overloadSignature(),
overload.details.declaration?.uri ?? primaryDecl.uri,
overload.details.declaration?.range ?? primaryDecl.range
);
}
}
}
});
} }
private _reportMultipleFinalDeclarations(name: string, symbol: Symbol, scopeType: ScopeType) { private _reportMultipleFinalDeclarations(name: string, symbol: Symbol, scopeType: ScopeType) {

View File

@ -134,6 +134,11 @@ export interface IncompleteType {
isRecursionSentinel?: boolean; isRecursionSentinel?: boolean;
} }
interface ReachabilityCacheEntry {
isReachable: boolean | undefined;
isReachableFrom: Map<number, boolean>;
}
// Define a user type guard function for IncompleteType. // Define a user type guard function for IncompleteType.
export function isIncompleteType(cachedType: CachedType): cachedType is IncompleteType { export function isIncompleteType(cachedType: CachedType): cachedType is IncompleteType {
return !!(cachedType as IncompleteType).isIncompleteType; return !!(cachedType as IncompleteType).isIncompleteType;
@ -164,6 +169,7 @@ export function getCodeFlowEngine(
speculativeTypeTracker: SpeculativeTypeTracker speculativeTypeTracker: SpeculativeTypeTracker
): CodeFlowEngine { ): CodeFlowEngine {
const isReachableRecursionSet = new Set<number>(); const isReachableRecursionSet = new Set<number>();
const reachabilityCache = new Map<number, ReachabilityCacheEntry>();
const callIsNoReturnCache = new Map<number, boolean>(); const callIsNoReturnCache = new Map<number, boolean>();
const isExceptionContextManagerCache = new Map<number, boolean>(); const isExceptionContextManagerCache = new Map<number, boolean>();
let flowIncompleteGeneration = 1; let flowIncompleteGeneration = 1;
@ -1182,11 +1188,29 @@ export function getCodeFlowEngine(
printControlFlowGraph(flowNode, /* reference */ undefined, 'isFlowNodeReachable'); printControlFlowGraph(flowNode, /* reference */ undefined, 'isFlowNodeReachable');
} }
function isFlowNodeReachableRecursive( function cacheReachabilityResult(isReachable: boolean): boolean {
flowNode: FlowNode, // If there is a finally gate set, we will not cache the results
sourceFlowNode: FlowNode | undefined, // because this can affect the reachability.
recursionCount = 0 if (closedFinallyGateSet.size > 0) {
): boolean { return isReachable;
}
let cacheEntry = reachabilityCache.get(flowNode.id);
if (!cacheEntry) {
cacheEntry = { isReachable: undefined, isReachableFrom: new Map<number, boolean>() };
reachabilityCache.set(flowNode.id, cacheEntry);
}
if (!sourceFlowNode) {
cacheEntry.isReachable = isReachable;
} else {
cacheEntry.isReachableFrom.set(sourceFlowNode.id, isReachable);
}
return isReachable;
}
function isFlowNodeReachableRecursive(flowNode: FlowNode, recursionCount = 0): boolean {
// Cut off the recursion at some point to prevent a stack overflow. // Cut off the recursion at some point to prevent a stack overflow.
const maxFlowNodeReachableRecursionCount = 64; const maxFlowNodeReachableRecursionCount = 64;
if (recursionCount > maxFlowNodeReachableRecursionCount) { if (recursionCount > maxFlowNodeReachableRecursionCount) {
@ -1197,21 +1221,36 @@ export function getCodeFlowEngine(
let curFlowNode = flowNode; let curFlowNode = flowNode;
while (true) { while (true) {
// See if we've already cached this result.
const cacheEntry = reachabilityCache.get(flowNode.id);
if (cacheEntry !== undefined && closedFinallyGateSet.size === 0) {
if (!sourceFlowNode) {
if (cacheEntry.isReachable !== undefined) {
return cacheEntry.isReachable;
}
} else {
const isReachableFrom = cacheEntry.isReachableFrom.get(sourceFlowNode.id);
if (isReachableFrom !== undefined) {
return isReachableFrom;
}
}
}
// If we've already visited this node, we can assume // If we've already visited this node, we can assume
// it wasn't reachable. // it wasn't reachable.
if (visitedFlowNodeSet.has(curFlowNode.id)) { if (visitedFlowNodeSet.has(curFlowNode.id)) {
return false; return cacheReachabilityResult(false);
} }
// Note that we've been here before. // Note that we've been here before.
visitedFlowNodeSet.add(curFlowNode.id); visitedFlowNodeSet.add(curFlowNode.id);
if (curFlowNode.flags & FlowFlags.Unreachable) { if (curFlowNode.flags & FlowFlags.Unreachable) {
return false; return cacheReachabilityResult(false);
} }
if (curFlowNode === sourceFlowNode) { if (curFlowNode === sourceFlowNode) {
return true; return cacheReachabilityResult(true);
} }
if ( if (
@ -1271,7 +1310,7 @@ export function getCodeFlowEngine(
} }
if (isUnreachable) { if (isUnreachable) {
return false; return cacheReachabilityResult(false);
} }
} }
} }
@ -1287,7 +1326,7 @@ export function getCodeFlowEngine(
// it always raises an exception or otherwise doesn't return, // it always raises an exception or otherwise doesn't return,
// so we can assume that the code before this is unreachable. // so we can assume that the code before this is unreachable.
if (!ignoreNoReturn && isCallNoReturn(evaluator, callFlowNode)) { if (!ignoreNoReturn && isCallNoReturn(evaluator, callFlowNode)) {
return false; return cacheReachabilityResult(false);
} }
curFlowNode = callFlowNode.antecedent; curFlowNode = callFlowNode.antecedent;
@ -1304,29 +1343,29 @@ export function getCodeFlowEngine(
isExceptionContextManager(evaluator, expr, contextMgrNode.isAsync) isExceptionContextManager(evaluator, expr, contextMgrNode.isAsync)
) )
) { ) {
return false; return cacheReachabilityResult(false);
} }
} }
const labelNode = curFlowNode as FlowLabel; const labelNode = curFlowNode as FlowLabel;
for (const antecedent of labelNode.antecedents) { for (const antecedent of labelNode.antecedents) {
if (isFlowNodeReachableRecursive(antecedent, sourceFlowNode, recursionCount)) { if (isFlowNodeReachableRecursive(antecedent, recursionCount)) {
return true; return cacheReachabilityResult(true);
} }
} }
return false; return cacheReachabilityResult(false);
} }
if (curFlowNode.flags & FlowFlags.Start) { if (curFlowNode.flags & FlowFlags.Start) {
// If we hit the start but were looking for a particular source flow // If we hit the start but were looking for a particular source flow
// node, return false. Otherwise, the start is what we're looking for. // node, return false. Otherwise, the start is what we're looking for.
return sourceFlowNode ? false : true; return cacheReachabilityResult(sourceFlowNode ? false : true);
} }
if (curFlowNode.flags & FlowFlags.PreFinallyGate) { if (curFlowNode.flags & FlowFlags.PreFinallyGate) {
const preFinallyFlowNode = curFlowNode as FlowPreFinallyGate; const preFinallyFlowNode = curFlowNode as FlowPreFinallyGate;
if (closedFinallyGateSet.has(preFinallyFlowNode.id)) { if (closedFinallyGateSet.has(preFinallyFlowNode.id)) {
return false; return cacheReachabilityResult(false);
} }
curFlowNode = preFinallyFlowNode.antecedent; curFlowNode = preFinallyFlowNode.antecedent;
@ -1339,10 +1378,8 @@ export function getCodeFlowEngine(
try { try {
closedFinallyGateSet.add(postFinallyFlowNode.preFinallyGate.id); closedFinallyGateSet.add(postFinallyFlowNode.preFinallyGate.id);
return isFlowNodeReachableRecursive( return cacheReachabilityResult(
postFinallyFlowNode.antecedent, isFlowNodeReachableRecursive(postFinallyFlowNode.antecedent, recursionCount)
sourceFlowNode,
recursionCount
); );
} finally { } finally {
if (!wasGateClosed) { if (!wasGateClosed) {
@ -1353,7 +1390,7 @@ export function getCodeFlowEngine(
// We shouldn't get here. // We shouldn't get here.
fail('Unexpected flow node flags'); fail('Unexpected flow node flags');
return false; return cacheReachabilityResult(false);
} }
} }
@ -1364,7 +1401,7 @@ export function getCodeFlowEngine(
isReachableRecursionSet.add(flowNode.id); isReachableRecursionSet.add(flowNode.id);
try { try {
return isFlowNodeReachableRecursive(flowNode, sourceFlowNode); return isFlowNodeReachableRecursive(flowNode);
} finally { } finally {
isReachableRecursionSet.delete(flowNode.id); isReachableRecursionSet.delete(flowNode.id);
} }

View File

@ -1020,7 +1020,7 @@ function assignTypeToParamSpec(
// performs this reverse mapping of type arguments and populates the type var // performs this reverse mapping of type arguments and populates the type var
// map for the target type. If the type is not assignable to the expected type, // map for the target type. If the type is not assignable to the expected type,
// it returns false. // it returns false.
export function populateTypeVarContextBasedOnExpectedType( export function addConstraintsForExpectedType(
evaluator: TypeEvaluator, evaluator: TypeEvaluator,
type: ClassType, type: ClassType,
expectedType: Type, expectedType: Type,

View File

@ -17,7 +17,7 @@ import { DiagnosticAddendum } from '../common/diagnostic';
import { DiagnosticRule } from '../common/diagnosticRules'; import { DiagnosticRule } from '../common/diagnosticRules';
import { LocMessage } from '../localization/localize'; import { LocMessage } from '../localization/localize';
import { ArgumentCategory, ExpressionNode, ParameterCategory } from '../parser/parseNodes'; import { ArgumentCategory, ExpressionNode, ParameterCategory } from '../parser/parseNodes';
import { populateTypeVarContextBasedOnExpectedType } from './constraintSolver'; import { addConstraintsForExpectedType } from './constraintSolver';
import { applyConstructorTransform, hasConstructorTransform } from './constructorTransform'; import { applyConstructorTransform, hasConstructorTransform } from './constructorTransform';
import { getTypeVarScopesForNode } from './parseTreeUtils'; import { getTypeVarScopesForNode } from './parseTreeUtils';
import { CallResult, FunctionArgument, TypeEvaluator, TypeResult } from './typeEvaluatorTypes'; import { CallResult, FunctionArgument, TypeEvaluator, TypeResult } from './typeEvaluatorTypes';
@ -25,14 +25,17 @@ import {
InferenceContext, InferenceContext,
MemberAccessFlags, MemberAccessFlags,
UniqueSignatureTracker, UniqueSignatureTracker,
addTypeVarsToListIfUnique,
applySolvedTypeVars, applySolvedTypeVars,
buildTypeVarContextFromSpecializedClass, buildTypeVarContextFromSpecializedClass,
convertToInstance, convertToInstance,
convertTypeToParamSpecValue,
doForEachSignature, doForEachSignature,
doForEachSubtype, doForEachSubtype,
ensureFunctionSignaturesAreUnique, ensureFunctionSignaturesAreUnique,
getTypeVarArgumentsRecursive, getTypeVarArgumentsRecursive,
getTypeVarScopeId, getTypeVarScopeId,
getTypeVarScopeIds,
isTupleClass, isTupleClass,
lookUpClassMember, lookUpClassMember,
mapSubtypes, mapSubtypes,
@ -60,6 +63,7 @@ import {
isInstantiableClass, isInstantiableClass,
isNever, isNever,
isOverloadedFunction, isOverloadedFunction,
isParamSpec,
isTypeVar, isTypeVar,
isUnion, isUnion,
isUnknown, isUnknown,
@ -286,7 +290,7 @@ function validateNewAndInitMethods(
newMethodReturnType = applySolvedTypeVars( newMethodReturnType = applySolvedTypeVars(
ClassType.cloneAsInstance(type), ClassType.cloneAsInstance(type),
new TypeVarContext(getTypeVarScopeId(type)), new TypeVarContext(getTypeVarScopeId(type)),
{ unknownIfNotFound: true } { unknownIfNotFound: true, tupleClassType: evaluator.getTupleClassType() }
) as ClassType; ) as ClassType;
} }
@ -539,7 +543,7 @@ function validateInitMethod(
typeVarContext.addSolveForScope(getTypeVarScopeId(initMethodType)); typeVarContext.addSolveForScope(getTypeVarScopeId(initMethodType));
if ( if (
populateTypeVarContextBasedOnExpectedType( !addConstraintsForExpectedType(
evaluator, evaluator,
ClassType.cloneAsInstance(type), ClassType.cloneAsInstance(type),
expectedSubType, expectedSubType,
@ -548,54 +552,56 @@ function validateInitMethod(
errorNode.start errorNode.start
) )
) { ) {
const specializedConstructor = applySolvedTypeVars(initMethodType, typeVarContext); return undefined;
let callResult: CallResult | undefined;
callResult = evaluator.useSpeculativeMode(errorNode, () => {
return evaluator.validateCallArguments(
errorNode,
argList,
{ type: specializedConstructor },
typeVarContext.clone(),
skipUnknownArgCheck,
/* inferenceContext */ undefined,
signatureTracker
);
});
if (!callResult.argumentErrors) {
// Call validateCallArguments again, this time without speculative
// mode, so any errors are reported.
callResult = evaluator.validateCallArguments(
errorNode,
argList,
{ type: specializedConstructor },
typeVarContext,
skipUnknownArgCheck,
/* inferenceContext */ undefined,
signatureTracker
);
if (callResult.isTypeIncomplete) {
isTypeIncomplete = true;
}
if (callResult.argumentErrors) {
argumentErrors = true;
}
if (callResult.overloadsUsedForCall) {
appendArray(overloadsUsedForCall, callResult.overloadsUsedForCall);
}
// Note that we've found an expected type that works.
foundWorkingExpectedType = true;
return applyExpectedSubtypeForConstructor(evaluator, type, expectedSubType, typeVarContext);
}
} }
return undefined; const specializedConstructor = applySolvedTypeVars(initMethodType, typeVarContext);
let callResult: CallResult | undefined;
callResult = evaluator.useSpeculativeMode(errorNode, () => {
return evaluator.validateCallArguments(
errorNode,
argList,
{ type: specializedConstructor },
typeVarContext.clone(),
skipUnknownArgCheck,
/* inferenceContext */ undefined,
signatureTracker
);
});
if (callResult.argumentErrors) {
return undefined;
}
// Call validateCallArguments again, this time without speculative
// mode, so any errors are reported.
callResult = evaluator.validateCallArguments(
errorNode,
argList,
{ type: specializedConstructor },
typeVarContext,
skipUnknownArgCheck,
/* inferenceContext */ undefined,
signatureTracker
);
if (callResult.isTypeIncomplete) {
isTypeIncomplete = true;
}
if (callResult.argumentErrors) {
argumentErrors = true;
}
if (callResult.overloadsUsedForCall) {
appendArray(overloadsUsedForCall, callResult.overloadsUsedForCall);
}
// Note that we've found an expected type that works.
foundWorkingExpectedType = true;
return applyExpectedSubtypeForConstructor(evaluator, type, expectedSubType, typeVarContext);
}, },
/* sortSubtypes */ true /* sortSubtypes */ true
); );
@ -704,7 +710,7 @@ function validateFallbackConstructorCall(
} }
if (expectedType) { if (expectedType) {
populateTypeVarContextBasedOnExpectedType( addConstraintsForExpectedType(
evaluator, evaluator,
ClassType.cloneAsInstance(type), ClassType.cloneAsInstance(type),
expectedType, expectedType,
@ -818,6 +824,7 @@ function applyExpectedTypeForConstructor(
const specializedType = applySolvedTypeVars(type, typeVarContext, { const specializedType = applySolvedTypeVars(type, typeVarContext, {
unknownIfNotFound: unsolvedTypeVarsAreUnknown, unknownIfNotFound: unsolvedTypeVarsAreUnknown,
tupleClassType: evaluator.getTupleClassType(),
}) as ClassType; }) as ClassType;
return ClassType.cloneAsInstance(specializedType); return ClassType.cloneAsInstance(specializedType);
} }
@ -1086,10 +1093,43 @@ function createFunctionFromInitMethod(
} }
const convertedInit = FunctionType.clone(boundInit); const convertedInit = FunctionType.clone(boundInit);
convertedInit.details.declaredReturnType = boundInit.strippedFirstParamType ?? selfType ?? objectType; let returnType = selfType;
if (!returnType) {
returnType = objectType;
// If this is a generic type, self-specialize the class (i.e. fill in
// its own type parameters as type arguments).
if (objectType.details.typeParameters.length > 0 && !objectType.typeArguments) {
const typeVarContext = new TypeVarContext(getTypeVarScopeIds(objectType));
// If a TypeVar is not used in any of the parameter types, it should take
// on its default value (typically Unknown) in the resulting specialized type.
const typeVarsInParams: TypeVarType[] = [];
convertedInit.details.parameters.forEach((param, index) => {
const paramType = FunctionType.getEffectiveParameterType(convertedInit, index);
addTypeVarsToListIfUnique(typeVarsInParams, getTypeVarArgumentsRecursive(paramType));
});
typeVarsInParams.forEach((typeVar) => {
if (isParamSpec(typeVar)) {
typeVarContext.setTypeVarType(typeVar, convertTypeToParamSpecValue(typeVar));
} else {
typeVarContext.setTypeVarType(typeVar, typeVar);
}
});
returnType = applySolvedTypeVars(objectType, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: evaluator.getTupleClassType(),
}) as ClassType;
}
}
convertedInit.details.declaredReturnType = boundInit.strippedFirstParamType ?? returnType;
if (convertedInit.specializedTypes) { if (convertedInit.specializedTypes) {
convertedInit.specializedTypes.returnType = selfType ?? objectType; convertedInit.specializedTypes.returnType = returnType;
} }
if (!convertedInit.details.docString && classType.details.docString) { if (!convertedInit.details.docString && classType.details.docString) {

View File

@ -821,7 +821,10 @@ function getConverterInputType(
const inputTypeVarContext = new TypeVarContext(typeVar.scopeId); const inputTypeVarContext = new TypeVarContext(typeVar.scopeId);
if (evaluator.assignType(targetFunction, signature, diagAddendum, inputTypeVarContext)) { 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); acceptedTypes.push(overloadSolution);
} }
}); });

View File

@ -109,7 +109,8 @@ export class ImportResolver {
private _cachedFilesForPath = new Map<string, Uri[]>(); private _cachedFilesForPath = new Map<string, Uri[]>();
private _cachedDirExistenceForRoot = new Map<string, boolean>(); private _cachedDirExistenceForRoot = new Map<string, boolean>();
private _stdlibModules: Set<string> | undefined; private _stdlibModules: Set<string> | undefined;
protected cachedParentImportResults: ParentDirectoryCache;
protected readonly cachedParentImportResults: ParentDirectoryCache;
constructor(readonly serviceProvider: ServiceProvider, private _configOptions: ConfigOptions, readonly host: Host) { constructor(readonly serviceProvider: ServiceProvider, private _configOptions: ConfigOptions, readonly host: Host) {
this.cachedParentImportResults = new ParentDirectoryCache(() => this.getPythonSearchPaths([])); this.cachedParentImportResults = new ParentDirectoryCache(() => this.getPythonSearchPaths([]));
@ -172,7 +173,7 @@ export class ImportResolver {
return suggestions; return suggestions;
} }
const root = this.getParentImportResolutionRoot(sourceFileUri, execEnv.root); const root = getParentImportResolutionRoot(sourceFileUri, execEnv.root);
const origin = sourceFileUri.getDirectory(); const origin = sourceFileUri.getDirectory();
let current: Uri | undefined = origin; let current: Uri | undefined = origin;
@ -533,7 +534,7 @@ export class ImportResolver {
execEnv: ExecutionEnvironment, execEnv: ExecutionEnvironment,
moduleDescriptor: ImportedModuleDescriptor moduleDescriptor: ImportedModuleDescriptor
): ImportResult { ): ImportResult {
const importName = this.formatImportName(moduleDescriptor); const importName = formatImportName(moduleDescriptor);
const importFailureInfo: string[] = []; const importFailureInfo: string[] = [];
const importResult = this._resolveImportStrict( const importResult = this._resolveImportStrict(
importName, importName,
@ -559,7 +560,7 @@ export class ImportResolver {
} }
// Check whether the given file is in the parent directory import resolution cache. // Check whether the given file is in the parent directory import resolution cache.
const root = this.getParentImportResolutionRoot(sourceFileUri, execEnv.root); const root = getParentImportResolutionRoot(sourceFileUri, execEnv.root);
if (!this.cachedParentImportResults.checkValidPath(this.fileSystem, sourceFileUri, root)) { if (!this.cachedParentImportResults.checkValidPath(this.fileSystem, sourceFileUri, root)) {
return importResult; return importResult;
} }
@ -776,74 +777,12 @@ export class ImportResolver {
protected getNativeModuleName(uri: Uri): string | undefined { protected getNativeModuleName(uri: Uri): string | undefined {
const fileExtension = uri.lastExtension.toLowerCase(); const fileExtension = uri.lastExtension.toLowerCase();
if (this._isNativeModuleFileExtension(fileExtension)) { if (_isNativeModuleFileExtension(fileExtension)) {
return stripFileExtension(uri.fileName, /* multiDotExtension */ true); return stripFileExtension(uri.fileName, /* multiDotExtension */ true);
} }
return undefined; return undefined;
} }
protected getModuleNameFromPath(
containerPath: Uri,
fileUri: Uri,
stripTopContainerDir = false
): string | undefined {
const moduleNameInfo = this.getModuleNameInfoFromPath(containerPath, fileUri, stripTopContainerDir);
if (!moduleNameInfo || moduleNameInfo.containsInvalidCharacters) {
return undefined;
}
return moduleNameInfo.moduleName;
}
protected getModuleNameInfoFromPath(
containerPath: Uri,
fileUri: Uri,
stripTopContainerDir = false
): ModuleNameInfoFromPath | undefined {
let fileUriWithoutExtension = fileUri.stripExtension();
// If module is native, strip platform part, such as 'cp36-win_amd64' in 'mtrand.cp36-win_amd64'.
if (this._isNativeModuleFileExtension(fileUri.lastExtension)) {
fileUriWithoutExtension = fileUriWithoutExtension.stripExtension();
}
if (!fileUriWithoutExtension.startsWith(containerPath)) {
return undefined;
}
// Strip off the '/__init__' if it's present.
if (fileUriWithoutExtension.pathEndsWith('__init__')) {
fileUriWithoutExtension = fileUriWithoutExtension.getDirectory();
}
const parts = Array.from(containerPath.getRelativePathComponents(fileUriWithoutExtension));
if (stripTopContainerDir) {
if (parts.length === 0) {
return undefined;
}
parts.shift();
}
if (parts.length === 0) {
return undefined;
}
// Handle the case where the symbol was resolved to a stubs package
// rather than the real package. We'll strip off the "-stubs" suffix
// in this case.
if (parts[0].endsWith(stubsSuffix)) {
parts[0] = parts[0].substr(0, parts[0].length - stubsSuffix.length);
}
// Check whether parts contains invalid characters.
const containsInvalidCharacters = parts.some((p) => !this._isIdentifier(p));
return {
moduleName: parts.join('.'),
containsInvalidCharacters,
};
}
// Potentially modifies the ImportResult by removing some or all of the // Potentially modifies the ImportResult by removing some or all of the
// implicit import entries. Only the imported symbols should be included. // implicit import entries. Only the imported symbols should be included.
protected filterImplicitImports( protected filterImplicitImports(
@ -880,22 +819,6 @@ export class ImportResolver {
return newImportResult; return newImportResult;
} }
protected formatImportName(moduleDescriptor: ImportedModuleDescriptor) {
return '.'.repeat(moduleDescriptor.leadingDots) + moduleDescriptor.nameParts.join('.');
}
protected getParentImportResolutionRoot(sourceFileUri: Uri, executionRoot: Uri | undefined): Uri {
if (!this._isDefaultWorkspace(executionRoot)) {
return executionRoot!;
}
return sourceFileUri.getDirectory();
}
private _isDefaultWorkspace(uri: Uri | undefined) {
return !uri || uri.isEmpty() || Uri.isDefaultWorkspace(uri);
}
private _resolveImportStrict( private _resolveImportStrict(
importName: string, importName: string,
sourceFileUri: Uri, sourceFileUri: Uri,
@ -1119,7 +1042,7 @@ export class ImportResolver {
); );
if (stdLibTypeshedPath) { if (stdLibTypeshedPath) {
moduleName = this.getModuleNameFromPath(stdLibTypeshedPath, fileUri); moduleName = getModuleNameFromPath(stdLibTypeshedPath, fileUri);
if (moduleName) { if (moduleName) {
const moduleDescriptor: ImportedModuleDescriptor = { const moduleDescriptor: ImportedModuleDescriptor = {
leadingDots: 0, leadingDots: 0,
@ -1149,7 +1072,7 @@ export class ImportResolver {
// Look for it in the root directory of the execution environment. // Look for it in the root directory of the execution environment.
if (execEnv.root) { if (execEnv.root) {
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(execEnv.root, fileUri); const candidateModuleNameInfo = _getModuleNameInfoFromPath(execEnv.root, fileUri);
if (candidateModuleNameInfo) { if (candidateModuleNameInfo) {
if (candidateModuleNameInfo.containsInvalidCharacters) { if (candidateModuleNameInfo.containsInvalidCharacters) {
@ -1163,7 +1086,7 @@ export class ImportResolver {
} }
for (const extraPath of execEnv.extraPaths) { for (const extraPath of execEnv.extraPaths) {
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(extraPath, fileUri); const candidateModuleNameInfo = _getModuleNameInfoFromPath(extraPath, fileUri);
if (candidateModuleNameInfo) { if (candidateModuleNameInfo) {
if (candidateModuleNameInfo.containsInvalidCharacters) { if (candidateModuleNameInfo.containsInvalidCharacters) {
@ -1182,7 +1105,7 @@ export class ImportResolver {
// Check for a typings file. // Check for a typings file.
if (this._configOptions.stubPath) { if (this._configOptions.stubPath) {
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(this._configOptions.stubPath, fileUri); const candidateModuleNameInfo = _getModuleNameInfoFromPath(this._configOptions.stubPath, fileUri);
if (candidateModuleNameInfo) { if (candidateModuleNameInfo) {
if (candidateModuleNameInfo.containsInvalidCharacters) { if (candidateModuleNameInfo.containsInvalidCharacters) {
@ -1209,7 +1132,7 @@ export class ImportResolver {
); );
if (thirdPartyTypeshedPath) { if (thirdPartyTypeshedPath) {
const candidateModuleName = this.getModuleNameFromPath( const candidateModuleName = getModuleNameFromPath(
thirdPartyTypeshedPath, thirdPartyTypeshedPath,
fileUri, fileUri,
/* stripTopContainerDir */ true /* stripTopContainerDir */ true
@ -1226,7 +1149,7 @@ export class ImportResolver {
const thirdPartyTypeshedPathEx = this.getTypeshedPathEx(execEnv, importFailureInfo); const thirdPartyTypeshedPathEx = this.getTypeshedPathEx(execEnv, importFailureInfo);
if (thirdPartyTypeshedPathEx) { if (thirdPartyTypeshedPathEx) {
const candidateModuleName = this.getModuleNameFromPath(thirdPartyTypeshedPathEx, fileUri); const candidateModuleName = getModuleNameFromPath(thirdPartyTypeshedPathEx, fileUri);
// Does this candidate look better than the previous best module name? // Does this candidate look better than the previous best module name?
// We'll always try to use the shortest version. // We'll always try to use the shortest version.
@ -1241,7 +1164,7 @@ export class ImportResolver {
const pythonSearchPaths = this.getPythonSearchPaths(importFailureInfo); const pythonSearchPaths = this.getPythonSearchPaths(importFailureInfo);
for (const searchPath of pythonSearchPaths) { for (const searchPath of pythonSearchPaths) {
const candidateModuleNameInfo = this.getModuleNameInfoFromPath(searchPath, fileUri); const candidateModuleNameInfo = _getModuleNameInfoFromPath(searchPath, fileUri);
if (candidateModuleNameInfo) { if (candidateModuleNameInfo) {
if (candidateModuleNameInfo.containsInvalidCharacters) { if (candidateModuleNameInfo.containsInvalidCharacters) {
@ -1260,7 +1183,7 @@ export class ImportResolver {
} }
if (detectPyTyped && importType === ImportType.ThirdParty) { if (detectPyTyped && importType === ImportType.ThirdParty) {
const root = this.getParentImportResolutionRoot(fileUri, execEnv.root); const root = getParentImportResolutionRoot(fileUri, execEnv.root);
// Go up directories one by one looking for a py.typed file. // Go up directories one by one looking for a py.typed file.
let current: Uri | undefined = fileUri.getDirectory(); let current: Uri | undefined = fileUri.getDirectory();
@ -1552,7 +1475,7 @@ export class ImportResolver {
moduleDescriptor: ImportedModuleDescriptor, moduleDescriptor: ImportedModuleDescriptor,
allowPyi: boolean allowPyi: boolean
): ImportResult | undefined { ): ImportResult | undefined {
const importName = this.formatImportName(moduleDescriptor); const importName = formatImportName(moduleDescriptor);
const importFailureInfo: string[] = []; const importFailureInfo: string[] = [];
// Check for a local stub file using stubPath. // Check for a local stub file using stubPath.
@ -1828,16 +1751,6 @@ export class ImportResolver {
return bestImportSoFar; return bestImportSoFar;
} }
private _isIdentifier(value: string) {
for (let i = 0; i < value.length; i++) {
if (i === 0 ? !isIdentifierStartChar(value.charCodeAt(i)) : !isIdentifierChar(value.charCodeAt(i))) {
return false;
}
}
return true;
}
private _findTypeshedPath( private _findTypeshedPath(
execEnv: ExecutionEnvironment, execEnv: ExecutionEnvironment,
moduleDescriptor: ImportedModuleDescriptor, moduleDescriptor: ImportedModuleDescriptor,
@ -2588,7 +2501,7 @@ export class ImportResolver {
// Make sure we don't use parent folder resolution when checking whether the given name is resolvable. // Make sure we don't use parent folder resolution when checking whether the given name is resolvable.
let importResult: ImportResult | undefined; let importResult: ImportResult | undefined;
if (strictOnly) { if (strictOnly) {
const importName = this.formatImportName(moduleDescriptor); const importName = formatImportName(moduleDescriptor);
const importFailureInfo: string[] = []; const importFailureInfo: string[] = [];
importResult = this._resolveImportStrict( importResult = this._resolveImportStrict(
@ -2653,7 +2566,7 @@ export class ImportResolver {
if (fileExt === '.py' || fileExt === '.pyi') { if (fileExt === '.py' || fileExt === '.pyi') {
strippedFileName = stripFileExtension(filePath.fileName); strippedFileName = stripFileExtension(filePath.fileName);
} else if ( } else if (
this._isNativeModuleFileExtension(fileExt) && _isNativeModuleFileExtension(fileExt) &&
!this.fileExistsCached(filePath.packageUri) && !this.fileExistsCached(filePath.packageUri) &&
!this.fileExistsCached(filePath.packageStubUri) !this.fileExistsCached(filePath.packageStubUri)
) { ) {
@ -2770,15 +2683,10 @@ export class ImportResolver {
const fileExtension = fileUri.lastExtension.toLowerCase(); const fileExtension = fileUri.lastExtension.toLowerCase();
const withoutExtension = stripFileExtension(fileUri.fileName, /* multiDotExtension */ true); const withoutExtension = stripFileExtension(fileUri.fileName, /* multiDotExtension */ true);
return ( return (
this._isNativeModuleFileExtension(fileExtension) && _isNativeModuleFileExtension(fileExtension) && equateStringsCaseInsensitive(moduleName, withoutExtension)
equateStringsCaseInsensitive(moduleName, withoutExtension)
); );
} }
private _isNativeModuleFileExtension(fileExtension: string): boolean {
return supportedNativeLibExtensions.some((ext) => ext === fileExtension);
}
private _tryWalkUp(current: Uri | undefined): Uri | undefined { private _tryWalkUp(current: Uri | undefined): Uri | undefined {
if (!current || current.isEmpty() || current.isRoot()) { if (!current || current.isEmpty() || current.isRoot()) {
return undefined; return undefined;
@ -2796,7 +2704,7 @@ export class ImportResolver {
return ( return (
current && current &&
!current.isEmpty() && !current.isEmpty() &&
(current.isChild(root) || (current.equals(root) && this._isDefaultWorkspace(execEnv.root))) (current.isChild(root) || (current.equals(root) && _isDefaultWorkspace(execEnv.root)))
); );
} }
} }
@ -2806,3 +2714,95 @@ export type ImportResolverFactory = (
options: ConfigOptions, options: ConfigOptions,
host: Host host: Host
) => ImportResolver; ) => ImportResolver;
export function formatImportName(moduleDescriptor: ImportedModuleDescriptor) {
return '.'.repeat(moduleDescriptor.leadingDots) + moduleDescriptor.nameParts.join('.');
}
export function getParentImportResolutionRoot(sourceFileUri: Uri, executionRoot: Uri | undefined): Uri {
if (!_isDefaultWorkspace(executionRoot)) {
return executionRoot!;
}
return sourceFileUri.getDirectory();
}
export function getModuleNameFromPath(
containerPath: Uri,
fileUri: Uri,
stripTopContainerDir = false
): string | undefined {
const moduleNameInfo = _getModuleNameInfoFromPath(containerPath, fileUri, stripTopContainerDir);
if (!moduleNameInfo || moduleNameInfo.containsInvalidCharacters) {
return undefined;
}
return moduleNameInfo.moduleName;
}
function _getModuleNameInfoFromPath(
containerPath: Uri,
fileUri: Uri,
stripTopContainerDir = false
): ModuleNameInfoFromPath | undefined {
let fileUriWithoutExtension = fileUri.stripExtension();
// If module is native, strip platform part, such as 'cp36-win_amd64' in 'mtrand.cp36-win_amd64'.
if (_isNativeModuleFileExtension(fileUri.lastExtension)) {
fileUriWithoutExtension = fileUriWithoutExtension.stripExtension();
}
if (!fileUriWithoutExtension.startsWith(containerPath)) {
return undefined;
}
// Strip off the '/__init__' if it's present.
if (fileUriWithoutExtension.pathEndsWith('__init__')) {
fileUriWithoutExtension = fileUriWithoutExtension.getDirectory();
}
const parts = Array.from(containerPath.getRelativePathComponents(fileUriWithoutExtension));
if (stripTopContainerDir) {
if (parts.length === 0) {
return undefined;
}
parts.shift();
}
if (parts.length === 0) {
return undefined;
}
// Handle the case where the symbol was resolved to a stubs package
// rather than the real package. We'll strip off the "-stubs" suffix
// in this case.
if (parts[0].endsWith(stubsSuffix)) {
parts[0] = parts[0].substr(0, parts[0].length - stubsSuffix.length);
}
// Check whether parts contains invalid characters.
const containsInvalidCharacters = parts.some((p) => !_isIdentifier(p));
return {
moduleName: parts.join('.'),
containsInvalidCharacters,
};
}
function _isNativeModuleFileExtension(fileExtension: string): boolean {
return supportedNativeLibExtensions.some((ext) => ext === fileExtension);
}
function _isDefaultWorkspace(uri: Uri | undefined) {
return !uri || uri.isEmpty() || Uri.isDefaultWorkspace(uri);
}
function _isIdentifier(value: string) {
for (let i = 0; i < value.length; i++) {
if (i === 0 ? !isIdentifierStartChar(value.charCodeAt(i)) : !isIdentifierChar(value.charCodeAt(i))) {
return false;
}
}
return true;
}

View File

@ -703,7 +703,7 @@ export function getTypeOfBinaryOperation(
} }
} }
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
// Exempt "|" because it might be a union operation involving unknowns. // Exempt "|" because it might be a union operation involving unknowns.
if (node.operator !== OperatorType.BitwiseOr) { if (node.operator !== OperatorType.BitwiseOr) {
evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.binaryOperationNotAllowed(), node); evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.binaryOperationNotAllowed(), node);
@ -950,7 +950,7 @@ export function getTypeOfUnaryOperation(
flags: EvaluatorFlags, flags: EvaluatorFlags,
inferenceContext: InferenceContext | undefined inferenceContext: InferenceContext | undefined
): TypeResult { ): TypeResult {
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.unaryOperationNotAllowed(), node); evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.unaryOperationNotAllowed(), node);
return { type: UnknownType.create() }; return { type: UnknownType.create() };
} }
@ -1087,7 +1087,7 @@ export function getTypeOfTernaryOperation(
): TypeResult { ): TypeResult {
const fileInfo = getFileInfo(node); const fileInfo = getFileInfo(node);
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.ternaryNotAllowed(), node); evaluator.addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.ternaryNotAllowed(), node);
return { type: UnknownType.create() }; return { type: UnknownType.create() };
} }

View File

@ -29,7 +29,7 @@ import {
PatternValueNode, PatternValueNode,
} from '../parser/parseNodes'; } from '../parser/parseNodes';
import { CodeFlowReferenceExpressionNode } from './codeFlowTypes'; import { CodeFlowReferenceExpressionNode } from './codeFlowTypes';
import { populateTypeVarContextBasedOnExpectedType } from './constraintSolver'; import { addConstraintsForExpectedType } from './constraintSolver';
import { getTypeVarScopesForNode, isMatchingExpression } from './parseTreeUtils'; import { getTypeVarScopesForNode, isMatchingExpression } from './parseTreeUtils';
import { EvaluatorFlags, TypeEvaluator, TypeResult } from './typeEvaluatorTypes'; import { EvaluatorFlags, TypeEvaluator, TypeResult } from './typeEvaluatorTypes';
import { import {
@ -685,7 +685,7 @@ function narrowTypeBasedOnClassPattern(
// specialize it with Unknown type arguments. // specialize it with Unknown type arguments.
if (isClass(exprType) && !exprType.typeAliasInfo) { if (isClass(exprType) && !exprType.typeAliasInfo) {
exprType = ClassType.cloneRemoveTypePromotions(exprType); 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 // Are there any positional arguments? If so, try to get the mappings for
@ -921,7 +921,7 @@ function narrowTypeBasedOnClassPattern(
const matchTypeInstance = ClassType.cloneAsInstance(unspecializedMatchType); const matchTypeInstance = ClassType.cloneAsInstance(unspecializedMatchType);
if ( if (
populateTypeVarContextBasedOnExpectedType( addConstraintsForExpectedType(
evaluator, evaluator,
matchTypeInstance, matchTypeInstance,
subjectSubtypeExpanded, subjectSubtypeExpanded,
@ -932,6 +932,7 @@ function narrowTypeBasedOnClassPattern(
) { ) {
resultType = applySolvedTypeVars(matchTypeInstance, typeVarContext, { resultType = applySolvedTypeVars(matchTypeInstance, typeVarContext, {
unknownIfNotFound: true, unknownIfNotFound: true,
tupleClassType: evaluator.getTupleClassType(),
}) as ClassType; }) as ClassType;
} }
} }
@ -1454,7 +1455,7 @@ function getSequencePatternInfo(
if (sequenceType && isInstantiableClass(sequenceType)) { if (sequenceType && isInstantiableClass(sequenceType)) {
const sequenceTypeVarContext = new TypeVarContext(getTypeVarScopeId(sequenceType)); const sequenceTypeVarContext = new TypeVarContext(getTypeVarScopeId(sequenceType));
if ( if (
populateTypeVarContextBasedOnExpectedType( addConstraintsForExpectedType(
evaluator, evaluator,
ClassType.cloneAsInstance(sequenceType), ClassType.cloneAsInstance(sequenceType),
subtype, subtype,

View File

@ -102,7 +102,7 @@ export function assignClassToProtocol(
// If the caller has provided a destination type var context, // If the caller has provided a destination type var context,
// we can't use the cached value unless the dest has no type // we can't use the cached value unless the dest has no type
// parameters to solve. // parameters to solve.
if (!destTypeVarContext || destType.details.typeParameters.length === 0) { if (!destTypeVarContext || !requiresSpecialization(destType)) {
return true; return true;
} }
} }

View File

@ -643,7 +643,7 @@ export class AnalyzerService {
const configs = this._getExtendedConfigurations(configFilePath ?? pyprojectFilePath); const configs = this._getExtendedConfigurations(configFilePath ?? pyprojectFilePath);
if (configs) { if (configs && configs.length > 0) {
for (const config of configs) { for (const config of configs) {
configOptions.initializeFromJson( configOptions.initializeFromJson(
config.configFileJsonObj, config.configFileJsonObj,

View File

@ -97,7 +97,7 @@ import {
isCodeFlowSupportedForReference, isCodeFlowSupportedForReference,
wildcardImportReferenceKey, wildcardImportReferenceKey,
} from './codeFlowTypes'; } from './codeFlowTypes';
import { assignTypeToTypeVar, populateTypeVarContextBasedOnExpectedType, updateTypeVarType } from './constraintSolver'; import { addConstraintsForExpectedType, assignTypeToTypeVar, updateTypeVarType } from './constraintSolver';
import { import {
createFunctionFromConstructor, createFunctionFromConstructor,
getBoundInitMethod, getBoundInitMethod,
@ -1266,7 +1266,7 @@ export function createTypeEvaluator(
} }
case ParseNodeType.AssignmentExpression: { case ParseNodeType.AssignmentExpression: {
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.walrusNotAllowed(), node); addError(LocMessage.walrusNotAllowed(), node);
} }
@ -1294,7 +1294,7 @@ export function createTypeEvaluator(
typeResult = getTypeOfExpression( typeResult = getTypeOfExpression(
node.typeAnnotation, node.typeAnnotation,
EvaluatorFlags.ExpectingInstantiableType | EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ExpectingTypeAnnotation | EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.EvaluateStringLiteralAsType | EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.DisallowParamSpec | EvaluatorFlags.DisallowParamSpec |
EvaluatorFlags.DisallowTypeVarTuple | EvaluatorFlags.DisallowTypeVarTuple |
@ -1337,7 +1337,7 @@ export function createTypeEvaluator(
// If this is a PEP 695 type alias, remove the special form so the type // If this is a PEP 695 type alias, remove the special form so the type
// printer prints it as its aliased type rather than TypeAliasType. // printer prints it as its aliased type rather than TypeAliasType.
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
if (typeResult.type.specialForm && ClassType.isBuiltIn(typeResult.type.specialForm, 'TypeAliasType')) { if (typeResult.type.specialForm && ClassType.isBuiltIn(typeResult.type.specialForm, 'TypeAliasType')) {
typeResult.type = TypeBase.cloneAsSpecialForm(typeResult.type, undefined); typeResult.type = TypeBase.cloneAsSpecialForm(typeResult.type, undefined);
} }
@ -1404,7 +1404,7 @@ export function createTypeEvaluator(
} }
function getTypeOfAwaitOperator(node: AwaitNode, flags: EvaluatorFlags, inferenceContext?: InferenceContext) { function getTypeOfAwaitOperator(node: AwaitNode, flags: EvaluatorFlags, inferenceContext?: InferenceContext) {
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.awaitNotAllowed(), node); addError(LocMessage.awaitNotAllowed(), node);
return { type: UnknownType.create() }; return { type: UnknownType.create() };
} }
@ -1484,7 +1484,7 @@ export function createTypeEvaluator(
ClassType.isBuiltIn(iterType, 'tuple') ClassType.isBuiltIn(iterType, 'tuple')
) { ) {
typeResult = { type: ClassType.cloneForUnpacked(iterType) }; typeResult = { type: ClassType.cloneForUnpacked(iterType) };
} else if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { } else if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.unpackInAnnotation(), node, node.starToken); addError(LocMessage.unpackInAnnotation(), node, node.starToken);
typeResult = { type: UnknownType.create() }; typeResult = { type: UnknownType.create() };
} else { } else {
@ -1726,7 +1726,7 @@ export function createTypeEvaluator(
let evaluatorFlags = let evaluatorFlags =
EvaluatorFlags.ExpectingInstantiableType | EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ExpectingTypeAnnotation | EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.ConvertEllipsisToAny | EvaluatorFlags.ConvertEllipsisToAny |
EvaluatorFlags.EvaluateStringLiteralAsType; EvaluatorFlags.EvaluateStringLiteralAsType;
@ -4411,7 +4411,7 @@ export function createTypeEvaluator(
node, node,
name, name,
!allowForwardReferences, !allowForwardReferences,
allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0
); );
if (!symbolWithScope) { if (!symbolWithScope) {
@ -4424,7 +4424,7 @@ export function createTypeEvaluator(
alias, alias,
alias.value, alias.value,
!allowForwardReferences, !allowForwardReferences,
allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 allowForwardReferences && (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0
); );
} }
} }
@ -4517,7 +4517,7 @@ export function createTypeEvaluator(
const codeFlowTypeResult = getFlowTypeOfReference(node, /* startNode */ undefined, { const codeFlowTypeResult = getFlowTypeOfReference(node, /* startNode */ undefined, {
targetSymbolId: symbol.id, targetSymbolId: symbol.id,
typeAtStart: { type: typeAtStart, isIncomplete: isTypeAtStartIncomplete }, typeAtStart: { type: typeAtStart, isIncomplete: isTypeAtStartIncomplete },
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0, skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0,
}); });
if (codeFlowTypeResult.type) { if (codeFlowTypeResult.type) {
@ -4532,7 +4532,7 @@ export function createTypeEvaluator(
// Detect, report, and fill in missing type arguments if appropriate. // Detect, report, and fill in missing type arguments if appropriate.
type = reportMissingTypeArguments(node, type, flags); type = reportMissingTypeArguments(node, type, flags);
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
// Verify that the name does not refer to a (non type alias) variable. // Verify that the name does not refer to a (non type alias) variable.
if (effectiveTypeInfo.includesVariableDecl && !type.typeAliasInfo) { if (effectiveTypeInfo.includesVariableDecl && !type.typeAliasInfo) {
let isAllowedTypeForVariable = isTypeVar(type) || isTypeAliasPlaceholder(type); let isAllowedTypeForVariable = isTypeVar(type) || isTypeAliasPlaceholder(type);
@ -4593,7 +4593,7 @@ export function createTypeEvaluator(
type = convertTypeVarToRuntimeInstance(node, type, flags); type = convertTypeVarToRuntimeInstance(node, type, flags);
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
reportUseOfTypeCheckOnly(type, node); reportUseOfTypeCheckOnly(type, node);
} }
@ -4926,7 +4926,10 @@ export function createTypeEvaluator(
let defaultType: Type; let defaultType: Type;
if (param.details.isDefaultExplicit || param.details.isParamSpec) { 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)) { } else if (param.details.isVariadic && tupleClass && isInstantiableClass(tupleClass)) {
defaultType = makeTupleObject( defaultType = makeTupleObject(
[{ type: UnknownType.create(), isUnbounded: true }], [{ type: UnknownType.create(), isUnbounded: true }],
@ -4951,7 +4954,10 @@ export function createTypeEvaluator(
} }
type = TypeBase.cloneForTypeAlias( type = TypeBase.cloneForTypeAlias(
applySolvedTypeVars(type, typeVarContext, { unknownIfNotFound: true }), applySolvedTypeVars(type, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
}),
type.typeAliasInfo.name, type.typeAliasInfo.name,
type.typeAliasInfo.fullName, type.typeAliasInfo.fullName,
type.typeAliasInfo.moduleName, type.typeAliasInfo.moduleName,
@ -5088,7 +5094,7 @@ export function createTypeEvaluator(
let leftExprFlags = EvaluatorFlags.MemberAccessBaseDefaults; let leftExprFlags = EvaluatorFlags.MemberAccessBaseDefaults;
leftExprFlags |= leftExprFlags |=
flags & flags &
(EvaluatorFlags.ExpectingTypeAnnotation | (EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.VariableTypeAnnotation | EvaluatorFlags.VariableTypeAnnotation |
EvaluatorFlags.AllowForwardReferences | EvaluatorFlags.AllowForwardReferences |
EvaluatorFlags.NotParsedByInterpreter | EvaluatorFlags.NotParsedByInterpreter |
@ -5155,7 +5161,7 @@ export function createTypeEvaluator(
const codeFlowTypeResult = getFlowTypeOfReference(node, /* startNode */ undefined, { const codeFlowTypeResult = getFlowTypeOfReference(node, /* startNode */ undefined, {
targetSymbolId: indeterminateSymbolId, targetSymbolId: indeterminateSymbolId,
typeAtStart: { type: typeAtStart, isIncomplete: isTypeAtStartIncomplete }, typeAtStart: { type: typeAtStart, isIncomplete: isTypeAtStartIncomplete },
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0, skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0,
}); });
if (codeFlowTypeResult.type) { if (codeFlowTypeResult.type) {
@ -5288,7 +5294,7 @@ export function createTypeEvaluator(
} }
// It's illegal to reference a member from a type variable. // It's illegal to reference a member from a type variable.
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
if (!isIncomplete) { if (!isIncomplete) {
addDiagnostic( addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues, DiagnosticRule.reportGeneralTypeIssues,
@ -5632,7 +5638,7 @@ export function createTypeEvaluator(
type = isFunctionRule ? AnyType.create() : UnknownType.create(); type = isFunctionRule ? AnyType.create() : UnknownType.create();
} }
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
reportUseOfTypeCheckOnly(type, node.memberName); reportUseOfTypeCheckOnly(type, node.memberName);
} }
@ -6515,7 +6521,7 @@ export function createTypeEvaluator(
type: indexTypeResult.type, type: indexTypeResult.type,
isIncomplete: !!baseTypeResult.isIncomplete || !!indexTypeResult.isIncomplete, isIncomplete: !!baseTypeResult.isIncomplete || !!indexTypeResult.isIncomplete,
}, },
skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0, skipConditionalNarrowing: (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0,
}); });
if (codeFlowTypeResult.type) { if (codeFlowTypeResult.type) {
@ -6855,7 +6861,10 @@ export function createTypeEvaluator(
if (index < typeArgs.length) { if (index < typeArgs.length) {
typeArgType = convertToInstance(typeArgs[index].type); typeArgType = convertToInstance(typeArgs[index].type);
} else if (param.details.isDefaultExplicit) { } else if (param.details.isDefaultExplicit) {
typeArgType = applySolvedTypeVars(param, typeVarContext, { unknownIfNotFound: true }); typeArgType = applySolvedTypeVars(param, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
});
} else { } else {
typeArgType = UnknownType.create(); typeArgType = UnknownType.create();
} }
@ -7018,7 +7027,7 @@ export function createTypeEvaluator(
getIndexAccessMagicMethodName(usage) getIndexAccessMagicMethodName(usage)
); );
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
// If the class doesn't derive from Generic, a type argument should not be allowed. // If the class doesn't derive from Generic, a type argument should not be allowed.
addDiagnostic( addDiagnostic(
DiagnosticRule.reportInvalidTypeArguments, DiagnosticRule.reportInvalidTypeArguments,
@ -7059,7 +7068,7 @@ export function createTypeEvaluator(
// Special-case InitVar, used in dataclasses. // Special-case InitVar, used in dataclasses.
const typeArgs = getTypeArgs(node, flags); const typeArgs = getTypeArgs(node, flags);
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
if ((flags & EvaluatorFlags.VariableTypeAnnotation) === 0) { if ((flags & EvaluatorFlags.VariableTypeAnnotation) === 0) {
addError(LocMessage.initVarNotAllowed(), node.baseExpression); addError(LocMessage.initVarNotAllowed(), node.baseExpression);
} }
@ -7743,7 +7752,7 @@ export function createTypeEvaluator(
signatureTracker: UniqueSignatureTracker | undefined signatureTracker: UniqueSignatureTracker | undefined
): TypeResult { ): TypeResult {
if ( if (
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 && (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
node.parent?.nodeType !== ParseNodeType.Argument node.parent?.nodeType !== ParseNodeType.Argument
) { ) {
// This is allowed inside of an index trailer, specifically // This is allowed inside of an index trailer, specifically
@ -7769,7 +7778,7 @@ export function createTypeEvaluator(
} }
flags &= ~( flags &= ~(
EvaluatorFlags.ExpectingTypeAnnotation | EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.EvaluateStringLiteralAsType | EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.ExpectingInstantiableType EvaluatorFlags.ExpectingInstantiableType
); );
@ -7872,7 +7881,7 @@ export function createTypeEvaluator(
} else { } else {
const tupleTypeVarContext = new TypeVarContext(getTypeVarScopeId(tupleClass)); const tupleTypeVarContext = new TypeVarContext(getTypeVarScopeId(tupleClass));
if ( if (
!populateTypeVarContextBasedOnExpectedType( !addConstraintsForExpectedType(
evaluatorInterface, evaluatorInterface,
ClassType.cloneAsInstance(tupleClass), ClassType.cloneAsInstance(tupleClass),
inferenceContext.expectedType, inferenceContext.expectedType,
@ -8001,7 +8010,7 @@ export function createTypeEvaluator(
// allowed, and it's a common mistake, so we want to emit a diagnostic // allowed, and it's a common mistake, so we want to emit a diagnostic
// that guides the user to the right solution. // that guides the user to the right solution.
if ( if (
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 && (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
node.leftExpression.nodeType === ParseNodeType.Name && node.leftExpression.nodeType === ParseNodeType.Name &&
node.leftExpression.value === 'type' node.leftExpression.value === 'type'
) { ) {
@ -8129,7 +8138,7 @@ export function createTypeEvaluator(
} }
} }
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.typeAnnotationCall(), node); addDiagnostic(DiagnosticRule.reportInvalidTypeForm, LocMessage.typeAnnotationCall(), node);
typeResult = { type: UnknownType.create() }; typeResult = { type: UnknownType.create() };
@ -11316,7 +11325,7 @@ export function createTypeEvaluator(
if (isClassInstance(effectiveExpectedType) && !isTypeSame(effectiveReturnType, effectiveExpectedType)) { if (isClassInstance(effectiveExpectedType) && !isTypeSame(effectiveReturnType, effectiveExpectedType)) {
const tempTypeVarContext = new TypeVarContext(getTypeVarScopeId(effectiveReturnType)); const tempTypeVarContext = new TypeVarContext(getTypeVarScopeId(effectiveReturnType));
if ( if (
populateTypeVarContextBasedOnExpectedType( addConstraintsForExpectedType(
evaluatorInterface, evaluatorInterface,
effectiveReturnType, effectiveReturnType,
effectiveExpectedType, effectiveExpectedType,
@ -11333,6 +11342,7 @@ export function createTypeEvaluator(
effectiveExpectedType = applySolvedTypeVars(genericReturnType, tempTypeVarContext, { effectiveExpectedType = applySolvedTypeVars(genericReturnType, tempTypeVarContext, {
unknownIfNotFound: true, unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
}); });
effectiveFlags |= AssignTypeFlags.SkipPopulateUnknownExpectedType; effectiveFlags |= AssignTypeFlags.SkipPopulateUnknownExpectedType;
@ -11633,6 +11643,7 @@ export function createTypeEvaluator(
let specializedReturnType = applySolvedTypeVars(returnType, typeVarContext, { let specializedReturnType = applySolvedTypeVars(returnType, typeVarContext, {
unknownIfNotFound, unknownIfNotFound,
tupleClassType: getTupleClassType(),
unknownExemptTypeVars: getUnknownExemptTypeVarsForReturnType(type, returnType), unknownExemptTypeVars: getUnknownExemptTypeVarsForReturnType(type, returnType),
eliminateUnsolvedInUnions, eliminateUnsolvedInUnions,
applyInScopePlaceholders: true, applyInScopePlaceholders: true,
@ -12067,7 +12078,7 @@ export function createTypeEvaluator(
EvaluatorFlags.DisallowTypeVarTuple | EvaluatorFlags.DisallowTypeVarTuple |
EvaluatorFlags.DisallowFinal | EvaluatorFlags.DisallowFinal |
EvaluatorFlags.DoNotSpecialize EvaluatorFlags.DoNotSpecialize
: EvaluatorFlags.DoNotSpecialize | EvaluatorFlags.DisallowFinal; : EvaluatorFlags.DisallowFinal | EvaluatorFlags.DoNotSpecialize;
const exprTypeResult = getTypeOfExpression( const exprTypeResult = getTypeOfExpression(
argParam.argument.valueExpression, argParam.argument.valueExpression,
flags, flags,
@ -12516,6 +12527,7 @@ export function createTypeEvaluator(
const concreteDefaultType = makeTopLevelTypeVarsConcrete( const concreteDefaultType = makeTopLevelTypeVarsConcrete(
applySolvedTypeVars(typeVar.details.defaultType, typeVarContext, { applySolvedTypeVars(typeVar.details.defaultType, typeVarContext, {
unknownIfNotFound: true, unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
}) })
); );
@ -13006,14 +13018,12 @@ export function createTypeEvaluator(
); );
} }
let classFlags = baseClass.details.flags & ~(ClassTypeFlags.BuiltInClass | ClassTypeFlags.SpecialBuiltIn);
classFlags |= ClassTypeFlags.Final | ClassTypeFlags.NewTypeClass | ClassTypeFlags.ValidTypeAliasClass;
const classType = ClassType.createInstantiable( const classType = ClassType.createInstantiable(
className, className,
ParseTreeUtils.getClassFullName(errorNode, fileInfo.moduleName, className), ParseTreeUtils.getClassFullName(errorNode, fileInfo.moduleName, className),
fileInfo.moduleName, fileInfo.moduleName,
fileInfo.fileUri, fileInfo.fileUri,
classFlags, ClassTypeFlags.Final | ClassTypeFlags.NewTypeClass | ClassTypeFlags.ValidTypeAliasClass,
ParseTreeUtils.getTypeSourceId(errorNode), ParseTreeUtils.getTypeSourceId(errorNode),
/* declaredMetaclass */ undefined, /* declaredMetaclass */ undefined,
baseClass.details.effectiveMetaclass baseClass.details.effectiveMetaclass
@ -13255,7 +13265,7 @@ export function createTypeEvaluator(
inferenceContext: InferenceContext | undefined inferenceContext: InferenceContext | undefined
): TypeResult { ): TypeResult {
if ( if (
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 && (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
node.parent?.nodeType !== ParseNodeType.Argument node.parent?.nodeType !== ParseNodeType.Argument
) { ) {
const diag = new DiagnosticAddendum(); const diag = new DiagnosticAddendum();
@ -13397,7 +13407,7 @@ export function createTypeEvaluator(
const dictTypeVarContext = new TypeVarContext(getTypeVarScopeId(builtInDict)); const dictTypeVarContext = new TypeVarContext(getTypeVarScopeId(builtInDict));
if ( if (
!populateTypeVarContextBasedOnExpectedType( !addConstraintsForExpectedType(
evaluatorInterface, evaluatorInterface,
builtInDict, builtInDict,
inferenceContext.expectedType, inferenceContext.expectedType,
@ -13575,7 +13585,7 @@ export function createTypeEvaluator(
const keyFlags = const keyFlags =
flags & flags &
~( ~(
EvaluatorFlags.ExpectingTypeAnnotation | EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.EvaluateStringLiteralAsType | EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.ExpectingInstantiableType EvaluatorFlags.ExpectingInstantiableType
); );
@ -13837,7 +13847,7 @@ export function createTypeEvaluator(
inferenceContext: InferenceContext | undefined inferenceContext: InferenceContext | undefined
): TypeResult { ): TypeResult {
if ( if (
(flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0 && (flags & EvaluatorFlags.ExpectingTypeExpression) !== 0 &&
node.nodeType === ParseNodeType.List && node.nodeType === ParseNodeType.List &&
node.parent?.nodeType !== ParseNodeType.Argument node.parent?.nodeType !== ParseNodeType.Argument
) { ) {
@ -13847,7 +13857,7 @@ export function createTypeEvaluator(
} }
flags &= ~( flags &= ~(
EvaluatorFlags.ExpectingTypeAnnotation | EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.EvaluateStringLiteralAsType | EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.ExpectingInstantiableType EvaluatorFlags.ExpectingInstantiableType
); );
@ -14016,7 +14026,7 @@ export function createTypeEvaluator(
const typeVarContext = new TypeVarContext(getTypeVarScopeId(expectedClassType)); const typeVarContext = new TypeVarContext(getTypeVarScopeId(expectedClassType));
if ( if (
!populateTypeVarContextBasedOnExpectedType( !addConstraintsForExpectedType(
evaluatorInterface, evaluatorInterface,
ClassType.cloneAsInstance(expectedClassType), ClassType.cloneAsInstance(expectedClassType),
inferenceContext.expectedType, inferenceContext.expectedType,
@ -14921,7 +14931,7 @@ export function createTypeEvaluator(
// If no type arguments are provided, the resulting type // If no type arguments are provided, the resulting type
// depends on whether we're evaluating a type annotation or // depends on whether we're evaluating a type annotation or
// we're in some other context. // we're in some other context.
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.optionalExtraArgs(), errorNode); addError(LocMessage.optionalExtraArgs(), errorNode);
return UnknownType.create(); return UnknownType.create();
} }
@ -15139,7 +15149,7 @@ export function createTypeEvaluator(
// depends on whether we're evaluating a type annotation or // depends on whether we're evaluating a type annotation or
// we're in some other context. // we're in some other context.
if (!typeArgs) { if (!typeArgs) {
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.typeGuardArgCount(), errorNode); addError(LocMessage.typeGuardArgCount(), errorNode);
} }
@ -15184,7 +15194,7 @@ export function createTypeEvaluator(
const enclosingClassTypeResult = enclosingClass ? getTypeOfClass(enclosingClass) : undefined; const enclosingClassTypeResult = enclosingClass ? getTypeOfClass(enclosingClass) : undefined;
if (!enclosingClassTypeResult) { if (!enclosingClassTypeResult) {
if ((flags & (EvaluatorFlags.ExpectingTypeAnnotation | EvaluatorFlags.ExpectingInstantiableType)) !== 0) { if ((flags & (EvaluatorFlags.ExpectingTypeExpression | EvaluatorFlags.ExpectingInstantiableType)) !== 0) {
addDiagnostic(DiagnosticRule.reportGeneralTypeIssues, LocMessage.selfTypeContext(), errorNode); addDiagnostic(DiagnosticRule.reportGeneralTypeIssues, LocMessage.selfTypeContext(), errorNode);
} }
@ -15246,7 +15256,7 @@ export function createTypeEvaluator(
// If no type arguments are provided, the resulting type // If no type arguments are provided, the resulting type
// depends on whether we're evaluating a type annotation or // depends on whether we're evaluating a type annotation or
// we're in some other context. // we're in some other context.
if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) { if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
return { type: classType }; return { type: classType };
} }
@ -15330,7 +15340,7 @@ export function createTypeEvaluator(
// If no type arguments are provided, the resulting type // If no type arguments are provided, the resulting type
// depends on whether we're evaluating a type annotation or // depends on whether we're evaluating a type annotation or
// we're in some other context. // we're in some other context.
if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeAnnotation) === 0) { if (!typeArgs && (flags & EvaluatorFlags.ExpectingTypeExpression) === 0) {
return classType; return classType;
} }
@ -15654,7 +15664,7 @@ export function createTypeEvaluator(
// If no type arguments are provided, the resulting type // If no type arguments are provided, the resulting type
// depends on whether we're evaluating a type annotation or // depends on whether we're evaluating a type annotation or
// we're in some other context. // we're in some other context.
if ((flags & EvaluatorFlags.ExpectingTypeAnnotation) !== 0) { if ((flags & EvaluatorFlags.ExpectingTypeExpression) !== 0) {
addError(LocMessage.unionTypeArgCount(), errorNode); addError(LocMessage.unionTypeArgCount(), errorNode);
return NeverType.createNever(); return NeverType.createNever();
} }
@ -15741,7 +15751,7 @@ export function createTypeEvaluator(
// If no type arguments are provided, the resulting type // If no type arguments are provided, the resulting type
// depends on whether we're evaluating a type annotation or // depends on whether we're evaluating a type annotation or
// we're in some other context. // we're in some other context.
if ((flags & (EvaluatorFlags.ExpectingTypeAnnotation | EvaluatorFlags.DisallowNakedGeneric)) !== 0) { if ((flags & (EvaluatorFlags.ExpectingTypeExpression | EvaluatorFlags.DisallowNakedGeneric)) !== 0) {
addError(LocMessage.genericTypeArgMissing(), errorNode); addError(LocMessage.genericTypeArgMissing(), errorNode);
} }
@ -16113,19 +16123,8 @@ export function createTypeEvaluator(
flags |= EvaluatorFlags.DoNotSpecialize; flags |= EvaluatorFlags.DoNotSpecialize;
} }
if (isDeclaredTypeAlias(node.leftExpression)) {
flags |=
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ExpectingTypeAnnotation |
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.DisallowParamSpec |
EvaluatorFlags.DisallowTypeVarTuple |
EvaluatorFlags.DisallowClassVar;
flags &= ~EvaluatorFlags.DoNotSpecialize;
}
// Is this type already cached? // Is this type already cached?
let rightHandType = readTypeCache(node.rightExpression, flags); let rightHandType = readTypeCache(node.rightExpression, /* flags */ undefined);
let isIncomplete = false; let isIncomplete = false;
let expectedTypeDiagAddendum: DiagnosticAddendum | undefined; let expectedTypeDiagAddendum: DiagnosticAddendum | undefined;
@ -16138,76 +16137,118 @@ export function createTypeEvaluator(
writeTypeCache(node.rightExpression, { type: rightHandType }, EvaluatorFlags.None); writeTypeCache(node.rightExpression, { type: rightHandType }, EvaluatorFlags.None);
} }
} }
}
if (!rightHandType) { if (!rightHandType) {
// Determine whether there is a declared type. // Determine whether there is a declared type.
const declaredType = getDeclaredTypeForExpression(node.leftExpression, { const declaredType = getDeclaredTypeForExpression(node.leftExpression, { method: 'set' });
method: 'set',
});
let typeAliasNameNode: NameNode | undefined; let typeAliasNameNode: NameNode | undefined;
let isSpeculativeTypeAlias = false; let isSpeculativeTypeAlias = false;
let typeAliasPlaceholder: TypeVarType | undefined;
if (isDeclaredTypeAlias(node.leftExpression)) { if (isDeclaredTypeAlias(node.leftExpression)) {
typeAliasNameNode = (node.leftExpression as TypeAnnotationNode).valueExpression as NameNode; flags =
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ExpectingTypeExpression |
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.DisallowParamSpec |
EvaluatorFlags.DisallowTypeVarTuple |
EvaluatorFlags.DisallowClassVar;
if (!isLegalTypeAliasExpressionForm(node.rightExpression)) { typeAliasNameNode = (node.leftExpression as TypeAnnotationNode).valueExpression as NameNode;
addDiagnostic(
DiagnosticRule.reportInvalidTypeForm, if (!isLegalTypeAliasExpressionForm(node.rightExpression)) {
LocMessage.typeAliasIllegalExpressionForm(), addDiagnostic(
node.rightExpression DiagnosticRule.reportInvalidTypeForm,
); LocMessage.typeAliasIllegalExpressionForm(),
} node.rightExpression
} else if (node.leftExpression.nodeType === ParseNodeType.Name) {
const symbolWithScope = lookUpSymbolRecursive(
node.leftExpression,
node.leftExpression.value,
/* honorCodeFlow */ false
); );
if (symbolWithScope) { }
const decls = symbolWithScope.symbol.getDeclarations(); } else if (node.leftExpression.nodeType === ParseNodeType.Name) {
if (decls.length === 1 && isPossibleTypeAliasOrTypedDict(decls[0])) { const symbolWithScope = lookUpSymbolRecursive(
node.leftExpression,
node.leftExpression.value,
/* honorCodeFlow */ false
);
if (symbolWithScope) {
const decls = symbolWithScope.symbol.getDeclarations();
if (decls.length === 1) {
if (isPossibleTypeAliasDeclaration(decls[0])) {
typeAliasNameNode = node.leftExpression; typeAliasNameNode = node.leftExpression;
isSpeculativeTypeAlias = true; isSpeculativeTypeAlias = true;
} else if (isPossibleTypeDictFactoryCall(decls[0])) {
// Handle calls to TypedDict factory functions like type
// aliases to support recursive field type definitions.
typeAliasNameNode = node.leftExpression;
} }
} }
} }
}
// Synthesize a type variable that represents the type alias while we're if (typeAliasNameNode) {
// evaluating it. This allows us to handle recursive definitions. typeAliasPlaceholder = synthesizeTypeAliasPlaceholder(typeAliasNameNode);
let typeAliasTypeVar: TypeVarType | undefined;
if (typeAliasNameNode) {
typeAliasTypeVar = TypeVarType.createInstantiable(`__type_alias_${typeAliasNameNode.value}`);
typeAliasTypeVar.details.isSynthesized = true;
typeAliasTypeVar.details.recursiveTypeAliasName = typeAliasNameNode.value;
const scopeId = ParseTreeUtils.getScopeIdForNode(typeAliasNameNode);
typeAliasTypeVar.details.recursiveTypeAliasScopeId = scopeId;
typeAliasTypeVar.details.recursiveTypeAliasIsPep695Syntax = false;
typeAliasTypeVar.scopeId = scopeId;
// Write the type back to the type cache. It will be replaced below. writeTypeCache(node, { type: typeAliasPlaceholder }, /* flags */ undefined);
writeTypeCache(node, { type: typeAliasTypeVar }, /* flags */ undefined); writeTypeCache(node.leftExpression, { type: typeAliasPlaceholder }, /* flags */ undefined);
writeTypeCache(node.leftExpression, { type: typeAliasTypeVar }, /* flags */ undefined);
if (node.leftExpression.nodeType === ParseNodeType.TypeAnnotation) { if (node.leftExpression.nodeType === ParseNodeType.TypeAnnotation) {
writeTypeCache( writeTypeCache(
node.leftExpression.valueExpression, node.leftExpression.valueExpression,
{ type: typeAliasTypeVar }, { type: typeAliasPlaceholder },
/* flags */ undefined /* flags */ undefined
); );
}
} }
}
const srcTypeResult = getTypeOfExpression( const srcTypeResult = getTypeOfExpression(node.rightExpression, flags, makeInferenceContext(declaredType));
node.rightExpression,
flags, rightHandType = srcTypeResult.type;
makeInferenceContext(declaredType) expectedTypeDiagAddendum = srcTypeResult.expectedTypeDiagAddendum;
if (srcTypeResult.isIncomplete) {
isIncomplete = true;
}
// If this was a speculative type alias, it becomes a real type alias
// only if the evaluated type is an instantiable type.
if (isSpeculativeTypeAlias && !isLegalImplicitTypeAliasType(rightHandType)) {
typeAliasNameNode = undefined;
}
if (typeAliasNameNode) {
assert(typeAliasPlaceholder !== undefined);
// If this is a type alias, record its name based on the assignment target.
rightHandType = transformTypeForTypeAlias(
rightHandType,
typeAliasNameNode,
typeAliasNameNode,
/* isPep695Syntax */ false,
/* isPep695TypeVarType */ false
); );
let srcType = srcTypeResult.type;
expectedTypeDiagAddendum = srcTypeResult.expectedTypeDiagAddendum; if (isTypeAliasRecursive(typeAliasPlaceholder, rightHandType)) {
if (srcTypeResult.isIncomplete) { addDiagnostic(
isIncomplete = true; DiagnosticRule.reportGeneralTypeIssues,
LocMessage.typeAliasIsRecursiveDirect().format({
name: typeAliasNameNode.value,
}),
node.rightExpression
);
rightHandType = UnknownType.create();
} }
// Set the resulting type to the boundType of the original type alias
// to support recursive type aliases.
typeAliasPlaceholder.details.boundType = rightHandType;
// Record the type parameters within the recursive type alias so it
// can be specialized.
typeAliasPlaceholder.details.recursiveTypeParameters = rightHandType.typeAliasInfo?.typeParameters;
} else {
// If the RHS is a constant boolean expression, assign it a literal type. // If the RHS is a constant boolean expression, assign it a literal type.
const constExprValue = evaluateStaticBoolExpression( const constExprValue = evaluateStaticBoolExpression(
node.rightExpression, node.rightExpression,
@ -16218,46 +16259,7 @@ export function createTypeEvaluator(
if (constExprValue !== undefined) { if (constExprValue !== undefined) {
const boolType = getBuiltInObject(node, 'bool'); const boolType = getBuiltInObject(node, 'bool');
if (isClassInstance(boolType)) { if (isClassInstance(boolType)) {
srcType = ClassType.cloneWithLiteral(boolType, constExprValue); rightHandType = ClassType.cloneWithLiteral(boolType, constExprValue);
}
}
// If this is an enum, transform the type as required.
rightHandType = srcType;
if (typeAliasNameNode) {
// If this was a speculative type alias, it becomes a real type alias
// only if the evaluated type is an instantiable type.
if (!isSpeculativeTypeAlias || isLegalImplicitTypeAliasType(rightHandType)) {
// If this is a type alias, record its name based on the assignment target.
rightHandType = transformTypeForTypeAlias(
rightHandType,
typeAliasNameNode,
typeAliasNameNode,
/* isPep695Syntax */ false,
/* isPep695TypeVarType */ false
);
assert(typeAliasTypeVar !== undefined);
if (isTypeAliasRecursive(typeAliasTypeVar, rightHandType)) {
addDiagnostic(
DiagnosticRule.reportGeneralTypeIssues,
LocMessage.typeAliasIsRecursiveDirect().format({
name: typeAliasNameNode.value,
}),
node.rightExpression
);
rightHandType = UnknownType.create();
}
// Set the resulting type to the boundType of the original type alias
// to support recursive type aliases.
typeAliasTypeVar.details.boundType = rightHandType;
// Record the type parameters within the recursive type alias so it
// can be specialized.
typeAliasTypeVar.details.recursiveTypeParameters = rightHandType.typeAliasInfo?.typeParameters;
} }
} }
} }
@ -16275,39 +16277,18 @@ export function createTypeEvaluator(
writeTypeCache(node, { type: rightHandType, isIncomplete }, EvaluatorFlags.None); writeTypeCache(node, { type: rightHandType, isIncomplete }, EvaluatorFlags.None);
} }
function isPossibleTypeAliasOrTypedDict(decl: Declaration) { // Synthesize a TypeVar that acts as a placeholder for a type alias. This allows
if (isPossibleTypeAliasDeclaration(decl)) { // the type alias definition to refer to itself.
return true; function synthesizeTypeAliasPlaceholder(nameNode: NameNode): TypeVarType {
} const placeholder = TypeVarType.createInstantiable(`__type_alias_${nameNode.value}`);
placeholder.details.isSynthesized = true;
placeholder.details.recursiveTypeAliasName = nameNode.value;
const scopeId = ParseTreeUtils.getScopeIdForNode(nameNode);
placeholder.details.recursiveTypeAliasScopeId = scopeId;
placeholder.details.recursiveTypeAliasIsPep695Syntax = false;
placeholder.scopeId = scopeId;
if ( return placeholder;
decl.type === DeclarationType.Variable &&
decl.node.parent &&
decl.node.parent.nodeType === ParseNodeType.Assignment &&
decl.node.parent.rightExpression?.nodeType === ParseNodeType.Call
) {
const callLeftNode = decl.node.parent.rightExpression.leftExpression;
// Use a simple heuristic to determine whether this is potentially
// a call to the TypedDict call. This avoids the expensive (and potentially
// recursive) call to getTypeOfExpression in cases where it's not needed.
if (
(callLeftNode.nodeType === ParseNodeType.Name && callLeftNode.value) === 'TypedDict' ||
(callLeftNode.nodeType === ParseNodeType.MemberAccess &&
callLeftNode.memberName.value === 'TypedDict' &&
callLeftNode.leftExpression.nodeType === ParseNodeType.Name)
) {
// See if this is a call to TypedDict. We want to support
// recursive type references in a TypedDict call.
const callType = getTypeOfExpression(callLeftNode, EvaluatorFlags.CallBaseDefaults).type;
if (isInstantiableClass(callType) && ClassType.isBuiltIn(callType, 'TypedDict')) {
return true;
}
}
}
return false;
} }
// Evaluates the type of a type alias (i.e. "type") statement. This code // Evaluates the type of a type alias (i.e. "type") statement. This code
@ -16346,15 +16327,9 @@ export function createTypeEvaluator(
// Synthesize a type variable that represents the type alias while we're // Synthesize a type variable that represents the type alias while we're
// evaluating it. This allows us to handle recursive definitions. // evaluating it. This allows us to handle recursive definitions.
const typeAliasTypeVar = TypeVarType.createInstantiable(`__type_alias_${nameNode.value}`); const typeAliasTypeVar = synthesizeTypeAliasPlaceholder(nameNode);
typeAliasTypeVar.details.isSynthesized = true;
typeAliasTypeVar.details.recursiveTypeAliasName = nameNode.value;
const scopeId = ParseTreeUtils.getScopeIdForNode(nameNode);
typeAliasTypeVar.details.recursiveTypeAliasScopeId = scopeId;
typeAliasTypeVar.details.recursiveTypeAliasIsPep695Syntax = isPep695Syntax;
typeAliasTypeVar.scopeId = scopeId;
// Write the type to the type cache. It will be replaced below. // Write the type to the type cache to support recursive type alias definitions.
writeTypeCache(nameNode, { type: typeAliasTypeVar }, /* flags */ undefined); writeTypeCache(nameNode, { type: typeAliasTypeVar }, /* flags */ undefined);
// Set a partial type to handle recursive (self-referential) type aliases. // Set a partial type to handle recursive (self-referential) type aliases.
@ -18340,6 +18315,7 @@ export function createTypeEvaluator(
// Replace any unsolved TypeVars with Unknown (including all function-scoped TypeVars). // Replace any unsolved TypeVars with Unknown (including all function-scoped TypeVars).
inferredParamType = applySolvedTypeVars(inferredParamType, typeVarContext, { inferredParamType = applySolvedTypeVars(inferredParamType, typeVarContext, {
unknownIfNotFound: true, unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
}); });
} }
@ -18764,6 +18740,11 @@ export function createTypeEvaluator(
return false; return false;
} }
const statements = functionDecl.node.suite.statements;
if (statements.some((statement) => statement.nodeType !== ParseNodeType.StatementList)) {
return false;
}
for (const raiseStatement of functionDecl.raiseStatements) { for (const raiseStatement of functionDecl.raiseStatements) {
if (!raiseStatement.typeExpression || raiseStatement.valueExpression) { if (!raiseStatement.typeExpression || raiseStatement.valueExpression) {
return false; return false;
@ -19494,6 +19475,16 @@ export function createTypeEvaluator(
continue; continue;
} }
// Forward-declared type annotation expressions need to be be evaluated
// in context so they have the appropriate flags set. Most of these cases
// will have been detected above when calling getParentAnnotationNode,
// but TypeAlias expressions are not handled there.
const stringEnclosure = ParseTreeUtils.getParentNodeOfType(parent, ParseNodeType.StringList);
if (stringEnclosure) {
nodeToEvaluate = stringEnclosure as StringListNode;
continue;
}
// The left expression of a call or member access expression is not generally contextual. // The left expression of a call or member access expression is not generally contextual.
if (parent.nodeType === ParseNodeType.Call || parent.nodeType === ParseNodeType.MemberAccess) { if (parent.nodeType === ParseNodeType.Call || parent.nodeType === ParseNodeType.MemberAccess) {
if (nodeToEvaluate === parent.leftExpression) { if (nodeToEvaluate === parent.leftExpression) {
@ -19520,15 +19511,7 @@ export function createTypeEvaluator(
// The base expression of an index expression is not contextual. // The base expression of an index expression is not contextual.
if (nodeToEvaluate === parent.baseExpression) { if (nodeToEvaluate === parent.baseExpression) {
flags = EvaluatorFlags.IndexBaseDefaults; flags = EvaluatorFlags.IndexBaseDefaults;
break;
} }
} else if (parent.nodeType === ParseNodeType.StringList && nodeToEvaluate === parent.typeAnnotation) {
// Forward-declared type annotation expressions need to be be evaluated
// in context so they have the appropriate flags set. Most of these cases
// will have been detected above when calling getParentAnnotationNode,
// but TypeAlias expressions are not handled there.
nodeToEvaluate = parent;
continue;
} }
if (!isExpressionNode(parent)) { if (!isExpressionNode(parent)) {
@ -19873,7 +19856,19 @@ export function createTypeEvaluator(
// don't bother doing additional work. // don't bother doing additional work.
let cacheEntry = readTypeCacheEntry(subnode); let cacheEntry = readTypeCacheEntry(subnode);
if (cacheEntry && !cacheEntry.typeResult.isIncomplete) { if (cacheEntry && !cacheEntry.typeResult.isIncomplete) {
return cacheEntry.typeResult; const typeResult = cacheEntry.typeResult;
// Handle the special case where a function or class is partially evaluated.
// Indicate that these are not complete types.
if (isFunction(typeResult.type) && FunctionType.isPartiallyEvaluated(typeResult.type)) {
return { ...typeResult, isIncomplete: true };
}
if (isClass(typeResult.type) && ClassType.isPartiallyEvaluated(typeResult.type)) {
return { ...typeResult, isIncomplete: true };
}
return typeResult;
} }
callback(); callback();
@ -20024,7 +20019,7 @@ export function createTypeEvaluator(
case 'Protocol': { case 'Protocol': {
if ( if (
(flags & (flags &
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeAnnotation)) !== (EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeExpression)) !==
0 0
) { ) {
addError(LocMessage.protocolNotAllowed(), errorNode); addError(LocMessage.protocolNotAllowed(), errorNode);
@ -20049,7 +20044,7 @@ export function createTypeEvaluator(
case 'TypedDict': { case 'TypedDict': {
if ( if (
(flags & (flags &
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeAnnotation)) !== (EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeExpression)) !==
0 0
) { ) {
addError(LocMessage.typedDictNotAllowed(), errorNode); addError(LocMessage.typedDictNotAllowed(), errorNode);
@ -20060,7 +20055,7 @@ export function createTypeEvaluator(
case 'Literal': { case 'Literal': {
if ( if (
(flags & (flags &
(EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeAnnotation)) !== (EvaluatorFlags.DisallowNonTypeSpecialForms | EvaluatorFlags.ExpectingTypeExpression)) !==
0 0
) { ) {
addError(LocMessage.literalNotAllowed(), errorNode); addError(LocMessage.literalNotAllowed(), errorNode);
@ -20375,7 +20370,10 @@ export function createTypeEvaluator(
return; return;
} }
const solvedDefaultType = applySolvedTypeVars(typeParam, typeVarContext, { unknownIfNotFound: true }); const solvedDefaultType = applySolvedTypeVars(typeParam, typeVarContext, {
unknownIfNotFound: true,
tupleClassType: getTupleClassType(),
});
typeArgTypes.push(solvedDefaultType); typeArgTypes.push(solvedDefaultType);
if (isParamSpec(typeParam)) { if (isParamSpec(typeParam)) {
typeVarContext.setTypeVarType(typeParam, convertTypeToParamSpecValue(solvedDefaultType)); typeVarContext.setTypeVarType(typeParam, convertTypeToParamSpecValue(solvedDefaultType));
@ -20510,7 +20508,7 @@ export function createTypeEvaluator(
} }
if (options?.allowRequired) { if (options?.allowRequired) {
flags |= EvaluatorFlags.AllowRequired | EvaluatorFlags.ExpectingTypeAnnotation; flags |= EvaluatorFlags.AllowRequired | EvaluatorFlags.ExpectingTypeExpression;
} }
if (options?.allowUnpackedTuple) { if (options?.allowUnpackedTuple) {
@ -20524,7 +20522,7 @@ export function createTypeEvaluator(
} }
if (options?.enforceTypeAnnotationRules) { if (options?.enforceTypeAnnotationRules) {
flags |= EvaluatorFlags.ExpectingTypeAnnotation; flags |= EvaluatorFlags.ExpectingTypeExpression;
} }
if (options?.disallowProtocolAndTypedDict) { if (options?.disallowProtocolAndTypedDict) {
@ -22347,7 +22345,7 @@ export function createTypeEvaluator(
getEffectiveTypeOfSymbol(member.symbol), getEffectiveTypeOfSymbol(member.symbol),
member.classType, member.classType,
/* selfClass */ undefined, /* selfClass */ undefined,
typeClass ?? UnknownType.create() typeClass && isInstantiableClass(typeClass) ? typeClass : undefined
); );
} }
return UnknownType.create(); return UnknownType.create();
@ -25944,7 +25942,7 @@ export function createTypeEvaluator(
!assignedType.tupleTypeArguments !assignedType.tupleTypeArguments
) { ) {
const typeVarContext = new TypeVarContext(getTypeVarScopeId(assignedType)); const typeVarContext = new TypeVarContext(getTypeVarScopeId(assignedType));
populateTypeVarContextBasedOnExpectedType( addConstraintsForExpectedType(
evaluatorInterface, evaluatorInterface,
ClassType.cloneForSpecialization( ClassType.cloneForSpecialization(
assignedType, assignedType,
@ -27118,6 +27116,43 @@ export function createTypeEvaluator(
return isLegal; return isLegal;
} }
function isPossibleTypeAliasOrTypedDict(decl: Declaration) {
return isPossibleTypeAliasDeclaration(decl) || isPossibleTypeDictFactoryCall(decl);
}
function isPossibleTypeDictFactoryCall(decl: Declaration) {
if (
decl.type !== DeclarationType.Variable ||
!decl.node.parent ||
decl.node.parent.nodeType !== ParseNodeType.Assignment ||
decl.node.parent.rightExpression?.nodeType !== ParseNodeType.Call
) {
return false;
}
const callLeftNode = decl.node.parent.rightExpression.leftExpression;
// Use a simple heuristic to determine whether this is potentially
// a call to the TypedDict call. This avoids the expensive (and potentially
// recursive) call to getTypeOfExpression in cases where it's not needed.
if (
(callLeftNode.nodeType === ParseNodeType.Name && callLeftNode.value) === 'TypedDict' ||
(callLeftNode.nodeType === ParseNodeType.MemberAccess &&
callLeftNode.memberName.value === 'TypedDict' &&
callLeftNode.leftExpression.nodeType === ParseNodeType.Name)
) {
// See if this is a call to TypedDict. We want to support
// recursive type references in a TypedDict call.
const callType = getTypeOfExpression(callLeftNode, EvaluatorFlags.CallBaseDefaults).type;
if (isInstantiableClass(callType) && ClassType.isBuiltIn(callType, 'TypedDict')) {
return true;
}
}
return false;
}
function printObjectTypeForClass(type: ClassType): string { function printObjectTypeForClass(type: ClassType): string {
return TypePrinter.printObjectTypeForClass( return TypePrinter.printObjectTypeForClass(
type, type,

View File

@ -86,10 +86,9 @@ export const enum EvaluatorFlags {
// than an instance (object) // than an instance (object)
ExpectingInstantiableType = 1 << 7, ExpectingInstantiableType = 1 << 7,
// A type annotation restricts the types of expressions that are // A type expression imposes grammatical and semantic limits on an
// allowed. If this flag is set, illegal type expressions are // expression. If this flag is set, illegal type expressions are
// flagged as errors. ExpectingTypeExpression = 1 << 8,
ExpectingTypeAnnotation = 1 << 8,
// Suppress the reportMissingTypeArgument diagnostic in this context. // Suppress the reportMissingTypeArgument diagnostic in this context.
AllowMissingTypeArgs = 1 << 9, AllowMissingTypeArgs = 1 << 9,

View File

@ -22,7 +22,7 @@ import {
} from '../parser/parseNodes'; } from '../parser/parseNodes';
import { KeywordType, OperatorType } from '../parser/tokenizerTypes'; import { KeywordType, OperatorType } from '../parser/tokenizerTypes';
import { getFileInfo } from './analyzerNodeInfo'; import { getFileInfo } from './analyzerNodeInfo';
import { populateTypeVarContextBasedOnExpectedType } from './constraintSolver'; import { addConstraintsForExpectedType } from './constraintSolver';
import { Declaration, DeclarationType } from './declaration'; import { Declaration, DeclarationType } from './declaration';
import { transformTypeForEnumMember } from './enums'; import { transformTypeForEnumMember } from './enums';
import * as ParseTreeUtils from './parseTreeUtils'; import * as ParseTreeUtils from './parseTreeUtils';
@ -638,7 +638,7 @@ export function getTypeNarrowingCallback(
); );
const arg1Type = arg1TypeResult.type; const arg1Type = arg1TypeResult.type;
const classTypeList = getIsInstanceClassTypes(arg1Type); const classTypeList = getIsInstanceClassTypes(evaluator, arg1Type);
const isIncomplete = !!callTypeResult.isIncomplete || !!arg1TypeResult.isIncomplete; const isIncomplete = !!callTypeResult.isIncomplete || !!arg1TypeResult.isIncomplete;
if (classTypeList) { 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 // that accepts a single class, and a more complex form that accepts a tuple
// of classes (including arbitrarily-nested tuples). This method determines // of classes (including arbitrarily-nested tuples). This method determines
// which form and returns a list of classes or undefined. // 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; let foundNonClassType = false;
const classTypeList: (ClassType | TypeVarType | FunctionType)[] = []; const classTypeList: (ClassType | TypeVarType | FunctionType)[] = [];
@ -1155,7 +1158,7 @@ function getIsInstanceClassTypes(argType: Type): (ClassType | TypeVarType | Func
const addClassTypesToList = (types: Type[]) => { const addClassTypesToList = (types: Type[]) => {
types.forEach((subtype) => { types.forEach((subtype) => {
if (isClass(subtype)) { if (isClass(subtype)) {
subtype = specializeWithUnknownTypeArgs(subtype); subtype = specializeWithUnknownTypeArgs(subtype, evaluator.getTupleClassType());
if (isInstantiableClass(subtype) && ClassType.isBuiltIn(subtype, 'Callable')) { if (isInstantiableClass(subtype) && ClassType.isBuiltIn(subtype, 'Callable')) {
subtype = convertToInstantiable(getUnknownTypeForCallable()); subtype = convertToInstantiable(getUnknownTypeForCallable());
@ -1359,7 +1362,8 @@ function narrowTypeForIsInstanceInternal(
concreteFilterType, concreteFilterType,
/* typeArguments */ undefined, /* typeArguments */ undefined,
/* isTypeArgumentExplicit */ false /* isTypeArgumentExplicit */ false
) ),
evaluator.getTupleClassType()
); );
} }
@ -1451,7 +1455,7 @@ function narrowTypeForIsInstanceInternal(
); );
if ( if (
populateTypeVarContextBasedOnExpectedType( addConstraintsForExpectedType(
evaluator, evaluator,
unspecializedFilterType, unspecializedFilterType,
concreteVarType, concreteVarType,
@ -1463,7 +1467,11 @@ function narrowTypeForIsInstanceInternal(
specializedFilterType = applySolvedTypeVars( specializedFilterType = applySolvedTypeVars(
unspecializedFilterType, unspecializedFilterType,
typeVarContext, typeVarContext,
{ unknownIfNotFound: true, useUnknownOverDefault: true } {
unknownIfNotFound: true,
useUnknownOverDefault: true,
tupleClassType: evaluator.getTupleClassType(),
}
) as ClassType; ) as ClassType;
} }
} }
@ -1764,7 +1772,11 @@ function narrowTypeForIsInstanceInternal(
const filteredType = evaluator.mapSubtypesExpandTypeVars( const filteredType = evaluator.mapSubtypesExpandTypeVars(
expandedTypes, expandedTypes,
/* options */ undefined, {
expandCallback: (type) => {
return evaluator.expandPromotionTypes(errorNode, type);
},
},
(subtype, unexpandedSubtype) => { (subtype, unexpandedSubtype) => {
// If we fail to filter anything in the negative case, we need to decide // If we fail to filter anything in the negative case, we need to decide
// whether to retain the original TypeVar or replace it with its specialized // whether to retain the original TypeVar or replace it with its specialized
@ -2459,33 +2471,69 @@ function narrowTypeForClassComparison(
isPositiveTest: boolean isPositiveTest: boolean
): Type { ): Type {
return mapSubtypes(referenceType, (subtype) => { return mapSubtypes(referenceType, (subtype) => {
const concreteSubtype = evaluator.makeTopLevelTypeVarsConcrete(subtype); let concreteSubtype = evaluator.makeTopLevelTypeVarsConcrete(subtype);
if (isPositiveTest) { if (isPositiveTest) {
if (isNoneInstance(concreteSubtype)) { if (isNoneInstance(concreteSubtype)) {
return undefined; return isNoneTypeClass(classType) ? classType : undefined;
} }
if (isClassInstance(concreteSubtype) && TypeBase.isInstance(subtype)) { if (
if (ClassType.isBuiltIn(concreteSubtype, 'type')) { isClassInstance(concreteSubtype) &&
return classType; TypeBase.isInstance(subtype) &&
ClassType.isBuiltIn(concreteSubtype, 'type')
) {
concreteSubtype =
concreteSubtype.typeArguments && concreteSubtype.typeArguments.length > 0
? convertToInstantiable(concreteSubtype.typeArguments[0])
: UnknownType.create();
}
if (isAnyOrUnknown(concreteSubtype)) {
return classType;
}
if (isClass(concreteSubtype)) {
if (TypeBase.isInstance(concreteSubtype)) {
return ClassType.isBuiltIn(concreteSubtype, 'object') ? classType : undefined;
} }
return undefined; const isSuperType = isIsinstanceFilterSuperclass(
} evaluator,
subtype,
concreteSubtype,
classType,
classType,
/* isInstanceCheck */ false
);
if (isInstantiableClass(concreteSubtype) && ClassType.isFinal(concreteSubtype)) { if (!classType.includeSubclasses) {
if ( // Handle the case where the LHS and RHS operands are specific
!ClassType.isSameGenericClass(concreteSubtype, classType) && // classes, as opposed to types that represent classes and their
!isIsinstanceFilterSuperclass( // subclasses.
if (!concreteSubtype.includeSubclasses) {
return ClassType.isSameGenericClass(concreteSubtype, classType) ? classType : undefined;
}
const isSubType = isIsinstanceFilterSubclass(
evaluator, evaluator,
subtype,
concreteSubtype, concreteSubtype,
classType, classType,
classType,
/* isInstanceCheck */ false /* isInstanceCheck */ false
) );
) {
if (isSuperType) {
return classType;
}
if (isSubType) {
return addConditionToType(classType, getTypeCondition(concreteSubtype));
}
return undefined;
}
if (ClassType.isFinal(concreteSubtype) && !isSuperType) {
return undefined; return undefined;
} }
} }

View File

@ -245,12 +245,13 @@ export const enum AssignTypeFlags {
} }
export interface ApplyTypeVarOptions { export interface ApplyTypeVarOptions {
typeClassType?: ClassType;
tupleClassType?: ClassType;
unknownIfNotFound?: boolean; unknownIfNotFound?: boolean;
useUnknownOverDefault?: boolean; useUnknownOverDefault?: boolean;
unknownExemptTypeVars?: TypeVarType[]; unknownExemptTypeVars?: TypeVarType[];
useNarrowBoundOnly?: boolean; useNarrowBoundOnly?: boolean;
eliminateUnsolvedInUnions?: boolean; eliminateUnsolvedInUnions?: boolean;
typeClassType?: Type;
applyInScopePlaceholders?: boolean; applyInScopePlaceholders?: boolean;
} }
@ -1073,7 +1074,7 @@ export function specializeWithDefaultTypeArgs(type: ClassType): ClassType {
// Specializes the class with "Unknown" type args (or the equivalent for ParamSpecs // Specializes the class with "Unknown" type args (or the equivalent for ParamSpecs
// or TypeVarTuples). // or TypeVarTuples).
export function specializeWithUnknownTypeArgs(type: ClassType): ClassType { export function specializeWithUnknownTypeArgs(type: ClassType, tupleClassType?: ClassType): ClassType {
if (type.details.typeParameters.length === 0) { if (type.details.typeParameters.length === 0) {
return type; return type;
} }
@ -1091,18 +1092,22 @@ export function specializeWithUnknownTypeArgs(type: ClassType): ClassType {
return ClassType.cloneForSpecialization( return ClassType.cloneForSpecialization(
type, type,
type.details.typeParameters.map((param) => getUnknownTypeForTypeVar(param)), type.details.typeParameters.map((param) => getUnknownTypeForTypeVar(param, tupleClassType)),
/* isTypeArgumentExplicit */ false, /* isTypeArgumentExplicit */ false,
/* includeSubclasses */ type.includeSubclasses /* includeSubclasses */ type.includeSubclasses
); );
} }
// Returns "Unknown" for simple TypeVars or the equivalent for a ParamSpec. // 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) { if (typeVar.details.isParamSpec) {
return getUnknownTypeForParamSpec(); return getUnknownTypeForParamSpec();
} }
if (typeVar.details.isVariadic && tupleClassType) {
return getUnknownTypeForVariadicTypeVar(tupleClassType);
}
return UnknownType.create(); return UnknownType.create();
} }
@ -1118,6 +1123,19 @@ export function getUnknownTypeForParamSpec(): FunctionType {
return newFunction; 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]". // Returns the equivalent of "Callable[..., Unknown]".
export function getUnknownTypeForCallable(): FunctionType { export function getUnknownTypeForCallable(): FunctionType {
const newFunction = FunctionType.createSynthesizedInstance('', FunctionTypeFlags.GradualCallableForm); const newFunction = FunctionType.createSynthesizedInstance('', FunctionTypeFlags.GradualCallableForm);
@ -1374,7 +1392,7 @@ export function partiallySpecializeType(
type: Type, type: Type,
contextClassType: ClassType, contextClassType: ClassType,
selfClass?: ClassType | TypeVarType, selfClass?: ClassType | TypeVarType,
typeClassType?: Type typeClassType?: ClassType
): Type { ): Type {
// If the context class is not specialized (or doesn't need specialization), // If the context class is not specialized (or doesn't need specialization),
// then there's no need to do any more work. // then there's no need to do any more work.
@ -3115,7 +3133,7 @@ export function computeMroLinearization(classType: ClassType): boolean {
// The first class in the MRO is the class itself. // The first class in the MRO is the class itself.
const typeVarContext = buildTypeVarContextFromSpecializedClass(classType); const typeVarContext = buildTypeVarContextFromSpecializedClass(classType);
let specializedClassType = applySolvedTypeVars(classType, typeVarContext); let specializedClassType = applySolvedTypeVars(classType, typeVarContext);
if (!isClass(specializedClassType) && !isAny(specializedClassType) && !isUnknown(specializedClassType)) { if (!isClass(specializedClassType) && !isAnyOrUnknown(specializedClassType)) {
specializedClassType = UnknownType.create(); specializedClassType = UnknownType.create();
} }
@ -3159,11 +3177,16 @@ export function computeMroLinearization(classType: ClassType): boolean {
if (!isInstantiableClass(classList[0])) { if (!isInstantiableClass(classList[0])) {
foundValidHead = true; foundValidHead = true;
assert(isClass(classList[0]) || isAnyOrUnknown(classList[0])); let head = classList[0];
classType.details.mro.push(classList[0]); if (!isClass(head) && !isAnyOrUnknown(head)) {
head = UnknownType.create();
}
classType.details.mro.push(head);
classList.shift(); classList.shift();
break; break;
} else if (!isInTail(classList[0], classListsToMerge)) { }
if (!isInTail(classList[0], classListsToMerge)) {
foundValidHead = true; foundValidHead = true;
classType.details.mro.push(classList[0]); classType.details.mro.push(classList[0]);
filterClass(classList[0], classListsToMerge); filterClass(classList[0], classListsToMerge);
@ -3186,8 +3209,11 @@ export function computeMroLinearization(classType: ClassType): boolean {
// Handle the situation by pull the head off the first empty list. // Handle the situation by pull the head off the first empty list.
// This allows us to make forward progress. // This allows us to make forward progress.
if (!isInstantiableClass(nonEmptyList[0])) { if (!isInstantiableClass(nonEmptyList[0])) {
assert(isClass(nonEmptyList[0]) || isAnyOrUnknown(nonEmptyList[0])); let head = nonEmptyList[0];
classType.details.mro.push(nonEmptyList[0]); if (!isClass(head) && !isAnyOrUnknown(head)) {
head = UnknownType.create();
}
classType.details.mro.push(head);
nonEmptyList.shift(); nonEmptyList.shift();
} else { } else {
classType.details.mro.push(nonEmptyList[0]); classType.details.mro.push(nonEmptyList[0]);
@ -3290,6 +3316,8 @@ export function convertTypeToParamSpecValue(type: Type): FunctionType {
newFunction.details.typeVarScopeId = newFunction.details.higherOrderTypeVarScopeIds.pop(); newFunction.details.typeVarScopeId = newFunction.details.higherOrderTypeVarScopeIds.pop();
} }
newFunction.details.constructorTypeVarScopeId = type.details.constructorTypeVarScopeId;
return newFunction; return newFunction;
} }
@ -3328,6 +3356,7 @@ export function convertParamSpecValueToType(type: FunctionType): Type {
FunctionType.addHigherOrderTypeVarScopeIds(functionType, withoutParamSpec.details.typeVarScopeId); FunctionType.addHigherOrderTypeVarScopeIds(functionType, withoutParamSpec.details.typeVarScopeId);
FunctionType.addHigherOrderTypeVarScopeIds(functionType, withoutParamSpec.details.higherOrderTypeVarScopeIds); FunctionType.addHigherOrderTypeVarScopeIds(functionType, withoutParamSpec.details.higherOrderTypeVarScopeIds);
functionType.details.constructorTypeVarScopeId = withoutParamSpec.details.constructorTypeVarScopeId;
withoutParamSpec.details.parameters.forEach((entry, index) => { withoutParamSpec.details.parameters.forEach((entry, index) => {
FunctionType.addParameter(functionType, { FunctionType.addParameter(functionType, {
@ -4122,7 +4151,7 @@ class ApplySolvedTypeVarsTransformer extends TypeVarTransformer {
if (this._options.unknownIfNotFound) { if (this._options.unknownIfNotFound) {
return this._options.useUnknownOverDefault return this._options.useUnknownOverDefault
? specializeWithUnknownTypeArgs(subtype) ? specializeWithUnknownTypeArgs(subtype, this._options.tupleClassType)
: specializeWithDefaultTypeArgs(subtype); : specializeWithDefaultTypeArgs(subtype);
} }
} }
@ -4160,7 +4189,7 @@ class ApplySolvedTypeVarsTransformer extends TypeVarTransformer {
return this._solveDefaultType(typeVar.details.defaultType, recursionCount); return this._solveDefaultType(typeVar.details.defaultType, recursionCount);
} }
return UnknownType.create(); return getUnknownTypeForTypeVar(typeVar, this._options.tupleClassType);
} }
} }

View File

@ -825,9 +825,7 @@ export namespace ClassType {
newClassType.includeSubclasses = true; newClassType.includeSubclasses = true;
} }
newClassType.tupleTypeArguments = tupleTypeArguments?.map((t) => newClassType.tupleTypeArguments = tupleTypeArguments ? [...tupleTypeArguments] : undefined;
isNever(t.type) ? { type: UnknownType.create(), isUnbounded: t.isUnbounded, isOptional: t.isOptional } : t
);
if (isEmptyContainer !== undefined) { if (isEmptyContainer !== undefined) {
newClassType.isEmptyContainer = isEmptyContainer; newClassType.isEmptyContainer = isEmptyContainer;
@ -1766,6 +1764,7 @@ export namespace FunctionType {
FunctionType.addHigherOrderTypeVarScopeIds(newFunction, paramSpecValue.details.typeVarScopeId); FunctionType.addHigherOrderTypeVarScopeIds(newFunction, paramSpecValue.details.typeVarScopeId);
FunctionType.addHigherOrderTypeVarScopeIds(newFunction, paramSpecValue.details.higherOrderTypeVarScopeIds); FunctionType.addHigherOrderTypeVarScopeIds(newFunction, paramSpecValue.details.higherOrderTypeVarScopeIds);
newFunction.details.constructorTypeVarScopeId = paramSpecValue.details.constructorTypeVarScopeId;
if (!newFunction.details.methodClass && paramSpecValue.details.methodClass) { if (!newFunction.details.methodClass && paramSpecValue.details.methodClass) {
newFunction.details.methodClass = paramSpecValue.details.methodClass; newFunction.details.methodClass = paramSpecValue.details.methodClass;

View File

@ -24,11 +24,13 @@ export class BackgroundAnalysis extends BackgroundAnalysisBase {
constructor(serviceProvider: ServiceProvider) { constructor(serviceProvider: ServiceProvider) {
super(serviceProvider.console()); super(serviceProvider.console());
const index = ++BackgroundAnalysis._workerIndex;
const initialData: InitializationData = { const initialData: InitializationData = {
rootUri: getRootUri(serviceProvider)?.toString() ?? '', rootUri: getRootUri(serviceProvider)?.toString() ?? '',
serviceId: index.toString(),
cancellationFolderName: getCancellationFolderName(), cancellationFolderName: getCancellationFolderName(),
runner: undefined, runner: undefined,
workerIndex: ++BackgroundAnalysis._workerIndex, workerIndex: index,
}; };
// this will load this same file in BG thread and start listener // this will load this same file in BG thread and start listener

View File

@ -310,7 +310,14 @@ export abstract class BackgroundAnalysisRunnerBase extends BackgroundThreadBase
const console = this.getConsole(); const console = this.getConsole();
this.logTracker = new LogTracker(console, `BG(${threadId})`); this.logTracker = new LogTracker(console, `BG(${threadId})`);
this._program = new Program(this.importResolver, this._configOptions, serviceProvider, this.logTracker); this._program = new Program(
this.importResolver,
this._configOptions,
serviceProvider,
this.logTracker,
undefined,
data.serviceId
);
} }
get program(): Program { get program(): Program {

View File

@ -251,10 +251,10 @@ export function getBackgroundWaiter<T>(port: MessagePort, deserializer: (v: any)
export interface InitializationData { export interface InitializationData {
rootUri: string; rootUri: string;
serviceId: string;
workerIndex: number;
cancellationFolderName: string | undefined; cancellationFolderName: string | undefined;
runner: string | undefined; runner: string | undefined;
title?: string;
workerIndex: number;
} }
export interface RequestResponse { export interface RequestResponse {

View File

@ -6,7 +6,7 @@
* Helper functions relating to collections and arrays. * Helper functions relating to collections and arrays.
*/ */
import { compareValues, Comparison, equateValues, isArray } from './core'; import { compareValues, Comparison, equateValues, isArray, MapLike } from './core';
export const emptyArray: never[] = [] as never[]; export const emptyArray: never[] = [] as never[];
export type EqualityComparer<T> = (a: T, b: T) => boolean; export type EqualityComparer<T> = (a: T, b: T) => boolean;
@ -318,7 +318,7 @@ export function getNestedProperty(object: any, property: string) {
return value; return value;
} }
export function getOrAdd<K, V>(map: Map<K, V>, key: K, newValueFactory: () => V): V { export function getOrAdd<K, V>(map: MapLike<K, V>, key: K, newValueFactory: () => V): V {
const value = map.get(key); const value = map.get(key);
if (value !== undefined) { if (value !== undefined) {
return value; return value;

View File

@ -102,8 +102,11 @@ const hasOwnProperty = Object.prototype.hasOwnProperty;
* The `in` and `for-in` operators can *not* be safely used, * The `in` and `for-in` operators can *not* be safely used,
* since `Object.prototype` may be modified by outside code. * since `Object.prototype` may be modified by outside code.
*/ */
export interface MapLike<T> { export interface MapLike<K, V> {
[index: string]: T; readonly [Symbol.toStringTag]: string;
get(key: K): V | undefined;
has(key: K): boolean;
set(key: K, value: V): this;
} }
/** /**
@ -112,7 +115,7 @@ export interface MapLike<T> {
* @param map A map-like. * @param map A map-like.
* @param key A property key. * @param key A property key.
*/ */
export function hasProperty(map: MapLike<any>, key: string): boolean { export function hasProperty(map: { [index: string]: any }, key: string): boolean {
return hasOwnProperty.call(map, key); return hasOwnProperty.call(map, key);
} }

View File

@ -70,6 +70,7 @@ export function expandPathVariables(path: string, rootPath: Uri, workspaces: Wor
const ws_regexp = RegExp(`\\$\\{workspaceFolder:${escapedWorkspaceName}\\}`, 'g'); const ws_regexp = RegExp(`\\$\\{workspaceFolder:${escapedWorkspaceName}\\}`, 'g');
path = path.replace(ws_regexp, workspace.rootUri.getPath()); path = path.replace(ws_regexp, workspace.rootUri.getPath());
} }
if (process.env.HOME !== undefined) { if (process.env.HOME !== undefined) {
replace(/\$\{env:HOME\}/g, process.env.HOME || ''); replace(/\$\{env:HOME\}/g, process.env.HOME || '');
} }

View File

@ -46,6 +46,7 @@ import { printLiteralValue } from '../analyzer/typePrinter';
import { import {
ClassType, ClassType,
combineTypes, combineTypes,
EnumLiteral,
FunctionType, FunctionType,
isClass, isClass,
isClassInstance, isClassInstance,
@ -127,6 +128,7 @@ import {
import { DocumentSymbolCollector } from './documentSymbolCollector'; import { DocumentSymbolCollector } from './documentSymbolCollector';
import { getAutoImportText, getDocumentationPartsForTypeAndDecl } from './tooltipUtils'; import { getAutoImportText, getDocumentationPartsForTypeAndDecl } from './tooltipUtils';
import '../common/serviceProviderExtensions'; import '../common/serviceProviderExtensions';
import { transformTypeForEnumMember } from '../analyzer/enums';
namespace Keywords { namespace Keywords {
const base: string[] = [ const base: string[] = [
@ -705,13 +707,7 @@ export class CompletionProvider {
// Handle enum members specially. Enum members normally look like // Handle enum members specially. Enum members normally look like
// variables, but the are declared using assignment expressions // variables, but the are declared using assignment expressions
// within an enum class. // within an enum class.
if ( if (this._isEnumMember(detail.boundObjectOrClass, name)) {
primaryDecl.type === DeclarationType.Variable &&
detail.boundObjectOrClass &&
isInstantiableClass(detail.boundObjectOrClass) &&
ClassType.isEnumClass(detail.boundObjectOrClass) &&
primaryDecl.node.parent?.nodeType === ParseNodeType.Assignment
) {
itemKind = CompletionItemKind.EnumMember; itemKind = CompletionItemKind.EnumMember;
} }
@ -757,19 +753,16 @@ export class CompletionProvider {
if (isClass(subtype)) { if (isClass(subtype)) {
const instance = TypeBase.isInstance(subtype); const instance = TypeBase.isInstance(subtype);
if (ClassType.isEnumClass(subtype) && instance) { getMembersForClass(subtype, symbolTable, instance);
// We don't add members for instances of enum members, but do add members of `enum.Enum` itself.
// ex) 'MyEnum.member.' <= here
const enumType = subtype.details.baseClasses.find(
(t) => isClass(t) && ClassType.isBuiltIn(t, 'Enum')
) as ClassType | undefined;
if (!enumType) {
return;
}
getMembersForClass(enumType, symbolTable, /* instance */ true); if (ClassType.isEnumClass(subtype) && instance) {
} else { // Don't show enum member out of another enum member
getMembersForClass(subtype, symbolTable, instance); // ex) Enum.Member. <= shouldn't show `Member` again.
for (const name of symbolTable.keys()) {
if (this._isEnumMember(subtype, name)) {
symbolTable.delete(name);
}
}
} }
} else if (isModule(subtype)) { } else if (isModule(subtype)) {
getMembersForModule(subtype, symbolTable); getMembersForModule(subtype, symbolTable);
@ -3143,6 +3136,21 @@ export class CompletionProvider {
// before doing more expensive type evaluation. // before doing more expensive type evaluation.
return decl.isMethod && decl.node.decorators.length > 0; return decl.isMethod && decl.node.decorators.length > 0;
} }
private _isEnumMember(containingType: ClassType | undefined, name: string) {
if (!containingType || !ClassType.isEnumClass(containingType)) {
return false;
}
const symbolType = transformTypeForEnumMember(this.evaluator, containingType, name);
return (
symbolType &&
isClassInstance(symbolType) &&
ClassType.isSameGenericClass(symbolType, containingType) &&
symbolType.literalValue instanceof EnumLiteral
);
}
} }
export class CompletionMap { export class CompletionMap {

View File

@ -118,7 +118,7 @@ export function setLocaleOverride(locale: string) {
localeOverride = locale.toLowerCase(); localeOverride = locale.toLowerCase();
} }
export function getLocaleFromEnv() { export function getLocaleFromEnv(): string {
if (localeOverride) { if (localeOverride) {
return localeOverride; return localeOverride;
} }
@ -130,7 +130,7 @@ export function getLocaleFromEnv() {
const vscodeConfigString = env?.VSCODE_NLS_CONFIG; const vscodeConfigString = env?.VSCODE_NLS_CONFIG;
if (vscodeConfigString) { if (vscodeConfigString) {
try { try {
return JSON.parse(vscodeConfigString).locale; return JSON.parse(vscodeConfigString).locale || defaultLocale;
} catch { } catch {
// Fall through // Fall through
} }
@ -142,7 +142,7 @@ export function getLocaleFromEnv() {
// This string may contain a local followed by an encoding (e.g. "en-us.UTF-8"). // This string may contain a local followed by an encoding (e.g. "en-us.UTF-8").
const localeStringSplit = localeString.split('.'); const localeStringSplit = localeString.split('.');
if (localeStringSplit.length > 0 && localeStringSplit[0]) { if (localeStringSplit.length > 0 && localeStringSplit[0]) {
return localeStringSplit[0]; return localeStringSplit[0] || defaultLocale;
} }
} }
} catch { } catch {

View File

@ -158,8 +158,8 @@
"enumMemberDelete": "Člen výčtu {name} se nedá odstranit.", "enumMemberDelete": "Člen výčtu {name} se nedá odstranit.",
"enumMemberSet": "Člen výčtu {name} se nedá přiřadit.", "enumMemberSet": "Člen výčtu {name} se nedá přiřadit.",
"enumMemberTypeAnnotation": "Poznámky typu nejsou pro členy výčtu povolené", "enumMemberTypeAnnotation": "Poznámky typu nejsou pro členy výčtu povolené",
"exceptionGroupIncompatible": "Syntaxe skupiny výjimek (except*) vyžaduje Python 3.11 nebo novější", "exceptionGroupIncompatible": "Syntaxe skupiny výjimek (\"except*\") vyžaduje Python 3.11 nebo novější",
"exceptionGroupTypeIncorrect": "Typ výjimky v kromě* se nedá odvodit z BaseGroupException.", "exceptionGroupTypeIncorrect": "Typ výjimky v except* se nedá odvodit z BaseGroupException.",
"exceptionTypeIncorrect": "„{type}“ se neodvozuje od BaseException", "exceptionTypeIncorrect": "„{type}“ se neodvozuje od BaseException",
"exceptionTypeNotClass": "{type} není platná třída výjimky", "exceptionTypeNotClass": "{type} není platná třída výjimky",
"exceptionTypeNotInstantiable": "Konstruktor pro výjimku typu {type} vyžaduje jeden nebo více argumentů", "exceptionTypeNotInstantiable": "Konstruktor pro výjimku typu {type} vyžaduje jeden nebo více argumentů",
@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Argumenty typu nejsou u třídy Protocol povoleny při použití syntaxe parametru typu", "protocolBaseClassWithTypeArgs": "Argumenty typu nejsou u třídy Protocol povoleny při použití syntaxe parametru typu",
"protocolIllegal": "Použití protokolu vyžaduje Python 3.7 nebo novější", "protocolIllegal": "Použití protokolu vyžaduje Python 3.7 nebo novější",
"protocolNotAllowed": "„Protocol“ nejde v tomto kontextu použít.", "protocolNotAllowed": "„Protocol“ nejde v tomto kontextu použít.",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "Argument typu pro „protokol“ musí být parametr typu",
"protocolUnsafeOverlap": "Třída se nebezpečně překrývá s názvem „{name}“ a může vytvořit shodu při spuštění.", "protocolUnsafeOverlap": "Třída se nebezpečně překrývá s názvem „{name}“ a může vytvořit shodu při spuštění.",
"protocolVarianceContravariant": "Proměnná typu „{variable}“ použitá v obecném protokolu „{class}“ by měla být kontravariantní", "protocolVarianceContravariant": "Proměnná typu „{variable}“ použitá v obecném protokolu „{class}“ by měla být kontravariantní",
"protocolVarianceCovariant": "Proměnná typu „{variable}“ použitá v obecném protokolu „{class}“ by měla být kovariantní", "protocolVarianceCovariant": "Proměnná typu „{variable}“ použitá v obecném protokolu „{class}“ by měla být kovariantní",

View File

@ -159,7 +159,7 @@
"enumMemberSet": "Das Enumerationselement \"{name}\" kann nicht zugewiesen werden.", "enumMemberSet": "Das Enumerationselement \"{name}\" kann nicht zugewiesen werden.",
"enumMemberTypeAnnotation": "Typanmerkungen sind für Enumerationsmember nicht zulässig", "enumMemberTypeAnnotation": "Typanmerkungen sind für Enumerationsmember nicht zulässig",
"exceptionGroupIncompatible": "Die Ausnahmegruppensyntax (\"except*\") erfordert Python 3.11 oder höher.", "exceptionGroupIncompatible": "Die Ausnahmegruppensyntax (\"except*\") erfordert Python 3.11 oder höher.",
"exceptionGroupTypeIncorrect": "Der Ausnahmetyp in except* kann nicht von BaseGroupException abgeleitet werden.", "exceptionGroupTypeIncorrect": "Der Ausnahmetyp in except* kann nicht von BaseGroupException abgeleitet werden.",
"exceptionTypeIncorrect": "\"{type}\" ist nicht von BaseException abgeleitet.", "exceptionTypeIncorrect": "\"{type}\" ist nicht von BaseException abgeleitet.",
"exceptionTypeNotClass": "\"{type}\" ist keine gültige Ausnahmeklasse.", "exceptionTypeNotClass": "\"{type}\" ist keine gültige Ausnahmeklasse.",
"exceptionTypeNotInstantiable": "Der Konstruktor für den Ausnahmetyp \"{type}\" erfordert mindestens ein Argument.", "exceptionTypeNotInstantiable": "Der Konstruktor für den Ausnahmetyp \"{type}\" erfordert mindestens ein Argument.",
@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Typargumente sind mit der Protokollklasse nicht zulässig, wenn die Typparametersyntax verwendet wird.", "protocolBaseClassWithTypeArgs": "Typargumente sind mit der Protokollklasse nicht zulässig, wenn die Typparametersyntax verwendet wird.",
"protocolIllegal": "Die Verwendung von \"Protocol\" erfordert Python 3.7 oder höher.", "protocolIllegal": "Die Verwendung von \"Protocol\" erfordert Python 3.7 oder höher.",
"protocolNotAllowed": "\"Protocol\" kann in diesem Kontext nicht verwendet werden.", "protocolNotAllowed": "\"Protocol\" kann in diesem Kontext nicht verwendet werden.",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "Das Typargument für „Protocol“ muss ein Typparameter sein.",
"protocolUnsafeOverlap": "Die Klasse überlappt unsicher mit „{name}“ und könnte zur Laufzeit eine Übereinstimmung erzeugen.", "protocolUnsafeOverlap": "Die Klasse überlappt unsicher mit „{name}“ und könnte zur Laufzeit eine Übereinstimmung erzeugen.",
"protocolVarianceContravariant": "Die Typvariable \"{variable}\", die im generischen Protokoll \"{class}\" verwendet wird, muss \"contravariant\" sein.", "protocolVarianceContravariant": "Die Typvariable \"{variable}\", die im generischen Protokoll \"{class}\" verwendet wird, muss \"contravariant\" sein.",
"protocolVarianceCovariant": "Die Typvariable \"{variable}\", die im generischen Protokoll \"{class}\" verwendet wird, muss \"covariant\" sein.", "protocolVarianceCovariant": "Die Typvariable \"{variable}\", die im generischen Protokoll \"{class}\" verwendet wird, muss \"covariant\" sein.",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "No se permiten argumentos de tipo con la clase Protocol cuando se usa la sintaxis de parámetro de tipo", "protocolBaseClassWithTypeArgs": "No se permiten argumentos de tipo con la clase Protocol cuando se usa la sintaxis de parámetro de tipo",
"protocolIllegal": "El uso de \"Protocolo\" requiere Python 3.7 o posterior.", "protocolIllegal": "El uso de \"Protocolo\" requiere Python 3.7 o posterior.",
"protocolNotAllowed": "\"Protocolo\" no puede utilizarse en este contexto", "protocolNotAllowed": "\"Protocolo\" no puede utilizarse en este contexto",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "El argumento de tipo para \"Protocol\" debe ser un parámetro de tipo",
"protocolUnsafeOverlap": "La clase se superpone \"{name}\" de forma no segura y podría producir una coincidencia en tiempo de ejecución", "protocolUnsafeOverlap": "La clase se superpone \"{name}\" de forma no segura y podría producir una coincidencia en tiempo de ejecución",
"protocolVarianceContravariant": "La variable de tipo \"{variable}\" usada en el protocolo genérico \"{class}\" debe ser contravariante.", "protocolVarianceContravariant": "La variable de tipo \"{variable}\" usada en el protocolo genérico \"{class}\" debe ser contravariante.",
"protocolVarianceCovariant": "La variable de tipo \"{variable}\" usada en el protocolo genérico \"{class}\" debe ser covariante", "protocolVarianceCovariant": "La variable de tipo \"{variable}\" usada en el protocolo genérico \"{class}\" debe ser covariante",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Les arguments de type ne sont pas autorisés avec la classe Protocol lors de l'utilisation de la syntaxe des paramètres de type", "protocolBaseClassWithTypeArgs": "Les arguments de type ne sont pas autorisés avec la classe Protocol lors de l'utilisation de la syntaxe des paramètres de type",
"protocolIllegal": "Lutilisation de « Protocole » nécessite Python 3.7 ou une version plus récente", "protocolIllegal": "Lutilisation de « Protocole » nécessite Python 3.7 ou une version plus récente",
"protocolNotAllowed": "\"Protocole\" ne peut pas être utilisé dans ce contexte", "protocolNotAllowed": "\"Protocole\" ne peut pas être utilisé dans ce contexte",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "Largument de type pour « Protocol » doit être un paramètre de type",
"protocolUnsafeOverlap": "La classe chevauche « {name} » de manière non sécurisée et peut produire une correspondance au moment de lexécution", "protocolUnsafeOverlap": "La classe chevauche « {name} » de manière non sécurisée et peut produire une correspondance au moment de lexécution",
"protocolVarianceContravariant": "La variable de type \"{variable}\" utilisée dans le protocole générique \"{class}\" doit être contravariante", "protocolVarianceContravariant": "La variable de type \"{variable}\" utilisée dans le protocole générique \"{class}\" doit être contravariante",
"protocolVarianceCovariant": "La variable de type \"{variable}\" utilisée dans le protocole générique \"{class}\" doit être covariante", "protocolVarianceCovariant": "La variable de type \"{variable}\" utilisée dans le protocole générique \"{class}\" doit être covariante",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Gli argomenti tipo non sono consentiti con la classe Protocollo quando si usa la sintassi dei parametri tipo", "protocolBaseClassWithTypeArgs": "Gli argomenti tipo non sono consentiti con la classe Protocollo quando si usa la sintassi dei parametri tipo",
"protocolIllegal": "L'uso del \"protocollo\" richiede Python 3.7 o versione successiva", "protocolIllegal": "L'uso del \"protocollo\" richiede Python 3.7 o versione successiva",
"protocolNotAllowed": "\"Protocol\" non può essere usato in questo contesto", "protocolNotAllowed": "\"Protocol\" non può essere usato in questo contesto",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "L'argomento di tipo per \"Protocol\" deve essere un parametro di tipo",
"protocolUnsafeOverlap": "La classe si sovrappone a \"{name}\" in modo non sicuro e può produrre una corrispondenza in fase di esecuzione", "protocolUnsafeOverlap": "La classe si sovrappone a \"{name}\" in modo non sicuro e può produrre una corrispondenza in fase di esecuzione",
"protocolVarianceContravariant": "La variabile di tipo \"{variable}\" usata nel protocollo generico \"{class}\" deve essere controvariante", "protocolVarianceContravariant": "La variabile di tipo \"{variable}\" usata nel protocollo generico \"{class}\" deve essere controvariante",
"protocolVarianceCovariant": "La variabile di tipo \"{variable}\" usata nel protocollo generico \"{class}\" deve essere covariante", "protocolVarianceCovariant": "La variabile di tipo \"{variable}\" usata nel protocollo generico \"{class}\" deve essere covariante",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "型パラメーター構文を使用する場合、Protocol クラスでは型引数を使用できません", "protocolBaseClassWithTypeArgs": "型パラメーター構文を使用する場合、Protocol クラスでは型引数を使用できません",
"protocolIllegal": "\"Protocol\" を使用するには Python 3.7 以降が必要です", "protocolIllegal": "\"Protocol\" を使用するには Python 3.7 以降が必要です",
"protocolNotAllowed": "\"Protocol\" はこのコンテキストでは使用できません", "protocolNotAllowed": "\"Protocol\" はこのコンテキストでは使用できません",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "\"Protocol\" の型引数は型パラメーターである必要があります",
"protocolUnsafeOverlap": "クラスが安全でない方法で \"{name}\" と重複しており、実行時に一致する可能性があります", "protocolUnsafeOverlap": "クラスが安全でない方法で \"{name}\" と重複しており、実行時に一致する可能性があります",
"protocolVarianceContravariant": "ジェネリック プロトコル \"{class}\" で使用される型変数 \"{variable}\" は反変である必要があります", "protocolVarianceContravariant": "ジェネリック プロトコル \"{class}\" で使用される型変数 \"{variable}\" は反変である必要があります",
"protocolVarianceCovariant": "ジェネリック プロトコル \"{class}\" で使用される型変数 \"{variable}\" は共変である必要があります", "protocolVarianceCovariant": "ジェネリック プロトコル \"{class}\" で使用される型変数 \"{variable}\" は共変である必要があります",

View File

@ -159,7 +159,7 @@
"enumMemberSet": "열거형 멤버 \"{name}\"을(를) 할당할 수 없음", "enumMemberSet": "열거형 멤버 \"{name}\"을(를) 할당할 수 없음",
"enumMemberTypeAnnotation": "열거형 멤버에는 형식 주석을 사용할 수 없습니다.", "enumMemberTypeAnnotation": "열거형 멤버에는 형식 주석을 사용할 수 없습니다.",
"exceptionGroupIncompatible": "예외 그룹 구문(\"except*\")에는 Python 3.11 이상이 필요합니다.", "exceptionGroupIncompatible": "예외 그룹 구문(\"except*\")에는 Python 3.11 이상이 필요합니다.",
"exceptionGroupTypeIncorrect": "exception*의 예외 형식은 BaseGroupException에서 파생될 수 없습니다.", "exceptionGroupTypeIncorrect": "except*의 예외 형식은 BaseGroupException에서 파생될 수 없습니다.",
"exceptionTypeIncorrect": "{type}’은 BaseException에서 파생되지 않습니다.", "exceptionTypeIncorrect": "{type}’은 BaseException에서 파생되지 않습니다.",
"exceptionTypeNotClass": "\"{type}\"은(는) 올바른 예외 클래스가 아닙니다.", "exceptionTypeNotClass": "\"{type}\"은(는) 올바른 예외 클래스가 아닙니다.",
"exceptionTypeNotInstantiable": "예외 형식 \"{type}\"에 대한 생성자에는 하나 이상의 인수가 필요합니다.", "exceptionTypeNotInstantiable": "예외 형식 \"{type}\"에 대한 생성자에는 하나 이상의 인수가 필요합니다.",
@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "형식 매개 변수 구문을 사용할 때는 Protocol 클래스에 형식 인수가 허용되지 않습니다.", "protocolBaseClassWithTypeArgs": "형식 매개 변수 구문을 사용할 때는 Protocol 클래스에 형식 인수가 허용되지 않습니다.",
"protocolIllegal": "\"프로토콜\"을 사용하려면 Python 3.7 이상이 필요합니다.", "protocolIllegal": "\"프로토콜\"을 사용하려면 Python 3.7 이상이 필요합니다.",
"protocolNotAllowed": "이 컨텍스트에서는 \"Protocol\"을 사용할 수 없습니다.", "protocolNotAllowed": "이 컨텍스트에서는 \"Protocol\"을 사용할 수 없습니다.",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "\"Protocol\"의 형식 인수는 형식 매개 변수여야 합니다.",
"protocolUnsafeOverlap": "클래스가 \"{name}\"과(와) 안전하지 않게 겹치며 런타임에 일치 항목을 생성할 수 있습니다.", "protocolUnsafeOverlap": "클래스가 \"{name}\"과(와) 안전하지 않게 겹치며 런타임에 일치 항목을 생성할 수 있습니다.",
"protocolVarianceContravariant": "{class} 제네릭 프로토콜에서 사용되는 {variable} 형식 변수는 반공변이어야 합니다.", "protocolVarianceContravariant": "{class} 제네릭 프로토콜에서 사용되는 {variable} 형식 변수는 반공변이어야 합니다.",
"protocolVarianceCovariant": "{class} 제네릭 프로토콜에서 사용되는 {variable} 형식 변수는 공변이어야 합니다", "protocolVarianceCovariant": "{class} 제네릭 프로토콜에서 사용되는 {variable} 형식 변수는 공변이어야 합니다",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Argumenty typu są niedozwolone w przypadku klasy protokołu, gdy jest używana składnia parametru typu", "protocolBaseClassWithTypeArgs": "Argumenty typu są niedozwolone w przypadku klasy protokołu, gdy jest używana składnia parametru typu",
"protocolIllegal": "Użycie elementu „Protocol” wymaga języka Python w wersji 3.7 lub nowszej", "protocolIllegal": "Użycie elementu „Protocol” wymaga języka Python w wersji 3.7 lub nowszej",
"protocolNotAllowed": "„Protokół” nie może być używany w tym kontekście", "protocolNotAllowed": "„Protokół” nie może być używany w tym kontekście",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "Argument typu dla elementy „Protocol” musi być parametrem typu",
"protocolUnsafeOverlap": "Klasa nakłada się niebezpiecznie na element „{name}” i może utworzyć dopasowanie w czasie wykonywania", "protocolUnsafeOverlap": "Klasa nakłada się niebezpiecznie na element „{name}” i może utworzyć dopasowanie w czasie wykonywania",
"protocolVarianceContravariant": "Zmienna typu „{variable}” używana w klasie protokołu ogólnego „{class}” powinna być kontrawariantna", "protocolVarianceContravariant": "Zmienna typu „{variable}” używana w klasie protokołu ogólnego „{class}” powinna być kontrawariantna",
"protocolVarianceCovariant": "Zmienna typu „{variable}” używana w klasie protokołu ogólnego „{class}” powinna być kowariantna", "protocolVarianceCovariant": "Zmienna typu „{variable}” używana w klasie protokołu ogólnego „{class}” powinna być kowariantna",

View File

@ -158,8 +158,8 @@
"enumMemberDelete": "O membro enumerado \"{name}\" não pode ser excluído", "enumMemberDelete": "O membro enumerado \"{name}\" não pode ser excluído",
"enumMemberSet": "O membro enumerado \"{name}\" não pode ser atribuído", "enumMemberSet": "O membro enumerado \"{name}\" não pode ser atribuído",
"enumMemberTypeAnnotation": "Anotações de tipo não são permitidas para membros de enumeração", "enumMemberTypeAnnotation": "Anotações de tipo não são permitidas para membros de enumeração",
"exceptionGroupIncompatible": "A sintaxe do grupo de exceção (\"exceto*\") requer o Python 3.11 ou mais recente", "exceptionGroupIncompatible": "A sintaxe do grupo de exceção (\"except*\") requer o Python 3.11 ou mais recente",
"exceptionGroupTypeIncorrect": "O tipo de exceção em exceto* não pode derivar de BaseGroupException", "exceptionGroupTypeIncorrect": "O tipo de exceção em except* não pode derivar de BaseGroupException",
"exceptionTypeIncorrect": "\"{type}\" não deriva de BaseException", "exceptionTypeIncorrect": "\"{type}\" não deriva de BaseException",
"exceptionTypeNotClass": "\"{type}\" não é uma classe de exceção válida", "exceptionTypeNotClass": "\"{type}\" não é uma classe de exceção válida",
"exceptionTypeNotInstantiable": "O construtor para o tipo de exceção \"{type}\" requer um ou mais argumentos", "exceptionTypeNotInstantiable": "O construtor para o tipo de exceção \"{type}\" requer um ou mais argumentos",
@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Argumentos de tipo não são permitidos com a classe Protocol ao usar a sintaxe de parâmetro de tipo", "protocolBaseClassWithTypeArgs": "Argumentos de tipo não são permitidos com a classe Protocol ao usar a sintaxe de parâmetro de tipo",
"protocolIllegal": "O uso de \"Protocol\" requer o Python 3.7 ou mais recente", "protocolIllegal": "O uso de \"Protocol\" requer o Python 3.7 ou mais recente",
"protocolNotAllowed": "\"Protocol\" não pode ser usado nesse contexto", "protocolNotAllowed": "\"Protocol\" não pode ser usado nesse contexto",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "O argumento de tipo para o \"Protocolo\" deve ser um parâmetro de tipo",
"protocolUnsafeOverlap": "A classe se sobrepõe a \"{name}\" de forma não segura e pode produzir uma correspondência em runtime", "protocolUnsafeOverlap": "A classe se sobrepõe a \"{name}\" de forma não segura e pode produzir uma correspondência em runtime",
"protocolVarianceContravariant": "A variável de tipo \"{variable}\" usada no protocolo genérico \"{class}\" deve ser contravariante", "protocolVarianceContravariant": "A variável de tipo \"{variable}\" usada no protocolo genérico \"{class}\" deve ser contravariante",
"protocolVarianceCovariant": "A variável de tipo \"{variable}\" usada no protocolo genérico \"{class}\" deve ser covariante", "protocolVarianceCovariant": "A variável de tipo \"{variable}\" usada no protocolo genérico \"{class}\" deve ser covariante",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Аргументы типа не допускаются с классом протокола при использовании синтаксиса параметра типа", "protocolBaseClassWithTypeArgs": "Аргументы типа не допускаются с классом протокола при использовании синтаксиса параметра типа",
"protocolIllegal": "Ключевое слово \"Protocol\" можно использовать в Python версии не ниже 3.7", "protocolIllegal": "Ключевое слово \"Protocol\" можно использовать в Python версии не ниже 3.7",
"protocolNotAllowed": "Невозможно использовать \"Protocol\" в этом контексте", "protocolNotAllowed": "Невозможно использовать \"Protocol\" в этом контексте",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "Аргумент типа для параметра \"Protocol\" должен быть параметром типа",
"protocolUnsafeOverlap": "Класс небезопасно перекрывает \"{name}\" и может вызвать совпадение во время выполнения", "protocolUnsafeOverlap": "Класс небезопасно перекрывает \"{name}\" и может вызвать совпадение во время выполнения",
"protocolVarianceContravariant": "Переменная типа \"{variable}\", используемая в универсальном протоколе \"{class}\", должна быть контравариантной.", "protocolVarianceContravariant": "Переменная типа \"{variable}\", используемая в универсальном протоколе \"{class}\", должна быть контравариантной.",
"protocolVarianceCovariant": "Переменная типа \"{variable}\", используемая в универсальном протоколе \"{class}\", должна быть ковариантной", "protocolVarianceCovariant": "Переменная типа \"{variable}\", используемая в универсальном протоколе \"{class}\", должна быть ковариантной",

View File

@ -159,7 +159,7 @@
"enumMemberSet": "Sabit liste üyesi \"{name}\" atanamıyor", "enumMemberSet": "Sabit liste üyesi \"{name}\" atanamıyor",
"enumMemberTypeAnnotation": "Sabit listesi üyeleri için tür ek açıklamalarına izin verilmiyor", "enumMemberTypeAnnotation": "Sabit listesi üyeleri için tür ek açıklamalarına izin verilmiyor",
"exceptionGroupIncompatible": "Özel durum grubu söz dizimi (\"except*\") için Python 3.11 veya daha yeni bir sürümü gerekiyor", "exceptionGroupIncompatible": "Özel durum grubu söz dizimi (\"except*\") için Python 3.11 veya daha yeni bir sürümü gerekiyor",
"exceptionGroupTypeIncorrect": "Except* altındaki özel durum türü BaseGroupException değerinden türetilemiyor", "exceptionGroupTypeIncorrect": "except* altındaki özel durum türü BaseGroupException değerinden türetilemiyor",
"exceptionTypeIncorrect": "\"{type}\", BaseException türevi değil", "exceptionTypeIncorrect": "\"{type}\", BaseException türevi değil",
"exceptionTypeNotClass": "\"{type}\" geçerli bir özel durum sınıfı değil", "exceptionTypeNotClass": "\"{type}\" geçerli bir özel durum sınıfı değil",
"exceptionTypeNotInstantiable": "\"{type}\" özel durum türü oluşturucusu bir veya daha fazla bağımsız değişken gerektiriyor", "exceptionTypeNotInstantiable": "\"{type}\" özel durum türü oluşturucusu bir veya daha fazla bağımsız değişken gerektiriyor",
@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "Tür parametresi söz dizimi kullanılırken, tür bağımsız değişkenlerinin Protokol sınıfıyla kullanılmasına izin verilmez", "protocolBaseClassWithTypeArgs": "Tür parametresi söz dizimi kullanılırken, tür bağımsız değişkenlerinin Protokol sınıfıyla kullanılmasına izin verilmez",
"protocolIllegal": "\"Protocol\" kullanımı için Python 3.7 veya daha yeni bir sürümü gerekiyor", "protocolIllegal": "\"Protocol\" kullanımı için Python 3.7 veya daha yeni bir sürümü gerekiyor",
"protocolNotAllowed": "\"Protokol\" bu bağlamda kullanılamaz", "protocolNotAllowed": "\"Protokol\" bu bağlamda kullanılamaz",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "“Protokol” için tür bağımsız değişkeni bir tür parametresi olmalıdır",
"protocolUnsafeOverlap": "Sınıf, \"{name}\" ile güvenli olmayan bir şekilde çakışıyor ve çalışma zamanında bir eşleşme üretebilir", "protocolUnsafeOverlap": "Sınıf, \"{name}\" ile güvenli olmayan bir şekilde çakışıyor ve çalışma zamanında bir eşleşme üretebilir",
"protocolVarianceContravariant": "\"{class}\" genel protokolünde kullanılan \"{variable}\" tür değişkeni, değişken karşıtı olmalıdır", "protocolVarianceContravariant": "\"{class}\" genel protokolünde kullanılan \"{variable}\" tür değişkeni, değişken karşıtı olmalıdır",
"protocolVarianceCovariant": "\"{class}\" genel protokolünde kullanılan \"{variable}\" tür değişkeni birlikte değişen olmalıdır", "protocolVarianceCovariant": "\"{class}\" genel protokolünde kullanılan \"{variable}\" tür değişkeni birlikte değişen olmalıdır",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "使用类型参数语法时,协议类不允许使用类型参数", "protocolBaseClassWithTypeArgs": "使用类型参数语法时,协议类不允许使用类型参数",
"protocolIllegal": "使用 \"Protocol\" 需要 Python 3.7 或更高版本", "protocolIllegal": "使用 \"Protocol\" 需要 Python 3.7 或更高版本",
"protocolNotAllowed": "\"Protocol\" 不能用于此上下文", "protocolNotAllowed": "\"Protocol\" 不能用于此上下文",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "“协议”的类型参数必须是类型参数",
"protocolUnsafeOverlap": "类与“{name}”不安全地重叠,并且可能在运行时生成匹配项", "protocolUnsafeOverlap": "类与“{name}”不安全地重叠,并且可能在运行时生成匹配项",
"protocolVarianceContravariant": "泛型协议“{class}”中使用的类型变量“{variable}”应为逆变", "protocolVarianceContravariant": "泛型协议“{class}”中使用的类型变量“{variable}”应为逆变",
"protocolVarianceCovariant": "泛型协议“{class}”中使用的类型变量“{variable}”应为协变", "protocolVarianceCovariant": "泛型协议“{class}”中使用的类型变量“{variable}”应为协变",

View File

@ -403,7 +403,7 @@
"protocolBaseClassWithTypeArgs": "使用型別參數語法時,通訊協定類別不允許使用型別引數", "protocolBaseClassWithTypeArgs": "使用型別參數語法時,通訊協定類別不允許使用型別引數",
"protocolIllegal": "使用 \"Protocol\" 需要 Python 3.7 或更新版本", "protocolIllegal": "使用 \"Protocol\" 需要 Python 3.7 或更新版本",
"protocolNotAllowed": "\"Protocol\" 不能用在此內容中", "protocolNotAllowed": "\"Protocol\" 不能用在此內容中",
"protocolTypeArgMustBeTypeParam": "Type argument for \"Protocol\" must be a type parameter", "protocolTypeArgMustBeTypeParam": "“Protocol” 的型別引數必須是型別參數",
"protocolUnsafeOverlap": "類別以不安全方式重疊 \"{name}\",且可能會在運行時間產生相符專案", "protocolUnsafeOverlap": "類別以不安全方式重疊 \"{name}\",且可能會在運行時間產生相符專案",
"protocolVarianceContravariant": "一般通訊協定 \"{class}\" 中使用的型別變數 \"{variable}\" 必須為逆變數", "protocolVarianceContravariant": "一般通訊協定 \"{class}\" 中使用的型別變數 \"{variable}\" 必須為逆變數",
"protocolVarianceCovariant": "一般通訊協定 \"{class}\" 中使用的型別變數 \"{variable}\" 必須為共變數", "protocolVarianceCovariant": "一般通訊協定 \"{class}\" 中使用的型別變數 \"{variable}\" 必須為共變數",

View File

@ -1302,3 +1302,90 @@ test('import from completion for namespace package', async () => {
}, },
}); });
}); });
test('members off enum member', async () => {
const code = `
// @filename: test.py
//// from enum import Enum
//// class Planet(Enum):
//// MERCURY = (3.303e+23, 2.4397e6)
//// EARTH = (5.976e+24, 6.37814e6)
////
//// def __init__(self, mass, radius):
//// self.mass = mass # in kilograms
//// self.radius = radius # in meters
////
//// @property
//// def surface_gravity(self):
//// # universal gravitational constant (m3 kg-1 s-2)
//// G = 6.67300E-11
//// return G * self.mass / (self.radius * self.radius)
////
//// Planet.EARTH.[|/*marker*/|]
`;
const state = parseAndGetTestState(code).state;
await state.verifyCompletion('excluded', 'markdown', {
['marker']: {
completions: [
{
label: 'MERCURY',
kind: CompletionItemKind.EnumMember,
},
{
label: 'EARTH',
kind: CompletionItemKind.EnumMember,
},
],
},
});
await state.verifyCompletion('included', 'markdown', {
['marker']: {
completions: [
{
label: 'mass',
kind: CompletionItemKind.Variable,
},
{
label: 'radius',
kind: CompletionItemKind.Variable,
},
{
label: 'surface_gravity',
kind: CompletionItemKind.Property,
},
],
},
});
});
test('enum with regular base type', async () => {
const code = `
// @filename: test.py
//// from enum import Enum
//// from datetime import timedelta
//// class Period(timedelta, Enum):
//// Today = -1
////
//// Period.Today.[|/*marker*/|]
`;
const state = parseAndGetTestState(code).state;
await state.verifyCompletion('included', 'markdown', {
['marker']: {
completions: [
{
label: 'days',
kind: CompletionItemKind.Property,
},
{
label: 'seconds',
kind: CompletionItemKind.Property,
},
],
},
});
});

View File

@ -192,4 +192,47 @@ describe(`Basic language server tests`, () => {
assert.equal(diagnostic.diagnostics[3].code, 'reportUnusedImport'); assert.equal(diagnostic.diagnostics[3].code, 'reportUnusedImport');
assert.equal(diagnostic.diagnostics[5].code, 'reportUnusedImport'); assert.equal(diagnostic.diagnostics[5].code, 'reportUnusedImport');
}); });
test('Diagnostic severity overrides test', async () => {
const code = `
// @filename: test.py
//// def test([|/*marker*/x|]): ...
////
// @filename: pyproject.toml
////
`;
const settings = [
{
item: {
scopeUri: `file://${normalizeSlashes(DEFAULT_WORKSPACE_ROOT, '/')}`,
section: 'python.analysis',
},
value: {
diagnosticSeverityOverrides: {
reportUnknownParameterType: 'warning',
},
},
},
];
const info = await runLanguageServer(
DEFAULT_WORKSPACE_ROOT,
code,
/* callInitialize */ true,
settings,
undefined,
/* supportsBackgroundThread */ true
);
// get the file containing the marker that also contains our task list comments
await openFile(info, 'marker');
// Wait for the diagnostics to publish
const diagnostics = await waitForDiagnostics(info);
const diagnostic = diagnostics.find((d) => d.uri.includes('test.py'));
assert(diagnostic);
// Make sure the error has a special rule
assert.equal(diagnostic.diagnostics[0].code, 'reportUnknownParameterType');
});
}); });

View File

@ -7,8 +7,7 @@ from abc import ABC, abstractmethod
class A(ABC): class A(ABC):
@staticmethod @staticmethod
@abstractmethod @abstractmethod
def method1() -> None: def method1() -> None: ...
...
@staticmethod @staticmethod
@abstractmethod @abstractmethod
@ -66,8 +65,7 @@ def func1(a: type[A]):
a.method3() a.method3()
class C(A): class C(A): ...
...
# This should generate an error. # This should generate an error.

View File

@ -18,8 +18,7 @@ class Foo(ABC):
@overload @overload
@abstractmethod @abstractmethod
def func1(self, a: str) -> str: def func1(self, a: str) -> str: ...
...
# This should generate an error because this overload is # This should generate an error because this overload is
# missing an abstractmethod overload. # missing an abstractmethod overload.
@ -27,8 +26,7 @@ class Foo(ABC):
raise NotImplementedError() raise NotImplementedError()
@overload @overload
def func2(self, a: str) -> str: def func2(self, a: str) -> str: ...
...
@overload @overload
@abstractmethod @abstractmethod

View File

@ -23,5 +23,4 @@ class Bar(Foo):
@final @final
# This should generate an error because Foo.foo, Bar.bar, and Bar.bar1 # This should generate an error because Foo.foo, Bar.bar, and Bar.bar1
# are abstract. # are abstract.
class Baz(Bar): class Baz(Bar): ...
...

View File

@ -9,8 +9,7 @@ from typing import NamedTuple
class ClassA(ABC): class ClassA(ABC):
@property @property
@abstractmethod @abstractmethod
def myproperty(self) -> str: def myproperty(self) -> str: ...
...
MixinB = NamedTuple("MixinB", [("myproperty", str)]) MixinB = NamedTuple("MixinB", [("myproperty", str)])

View File

@ -10,9 +10,7 @@ v1: Annotated[str, ClassA, func1(), v2[0]] = ""
v2 = [1, 2, 3] v2 = [1, 2, 3]
class ClassA: class ClassA: ...
...
def func1(): def func1(): ...
...

View File

@ -64,8 +64,7 @@ class ClassD:
str: "str" str: "str"
def int(self): def int(self): ...
...
foo: "int" foo: "int"
@ -147,4 +146,3 @@ x12: b"int"
# This should generate an error because format strings aren't allowed. # This should generate an error because format strings aren't allowed.
x13: f"int" x13: f"int"

View File

@ -27,8 +27,7 @@ class ClassB(ClassA):
def func5(self, x: ClassA): def func5(self, x: ClassA):
x.func0() x.func0()
class ClassA: class ClassA: ...
...
def func6(self, x: ClassC): def func6(self, x: ClassC):
x.my_int x.my_int

View File

@ -53,8 +53,7 @@ e = [3]
e: list[int] e: list[int]
def register(fn: Callable[[], None]) -> None: def register(fn: Callable[[], None]) -> None: ...
...
# These should be be fine because they use the "_" name. # These should be be fine because they use the "_" name.

View File

@ -11,12 +11,10 @@ v1 = cast(Any, 0)
v2 = cast(typing.Any, 0) v2 = cast(typing.Any, 0)
class A(Any): class A(Any): ...
...
class B(typing.Any): class B(typing.Any): ...
...
# This should generate an error because Any is not callable. # This should generate an error because Any is not callable.

View File

@ -20,8 +20,7 @@ class A:
T = TypeVar("T") T = TypeVar("T")
class B(Generic[T]): class B(Generic[T]): ...
...
def func1(v1: list[Any | None], v2: list[int | str]): def func1(v1: list[Any | None], v2: list[int | str]):

View File

@ -38,8 +38,7 @@ d4: dict[str, tuple[int, Callable[[int], int]]] = {
class Adder(Protocol): class Adder(Protocol):
def __call__(self, x: int, y: dict[str, int]) -> int: def __call__(self, x: int, y: dict[str, int]) -> int: ...
...
v1: Adder = lambda x, y: x + y["hi"] v1: Adder = lambda x, y: x + y["hi"]

View File

@ -7,12 +7,10 @@ from typing import Any, TypeVar, overload
class Foo: class Foo:
@overload @overload
def bar(self, obj: None) -> object: def bar(self, obj: None) -> object: ...
...
@overload @overload
def bar(self, obj: object) -> Any: def bar(self, obj: object) -> Any: ...
...
def bar(self, obj: object | None) -> Any: def bar(self, obj: object | None) -> Any:
pass pass

View File

@ -17,8 +17,7 @@ def func1() -> Tuple[str, int]:
return (a, y) return (a, y)
def get_value(x: int) -> int: def get_value(x: int) -> int: ...
...
x = sum(max(value for x in range(10) if (value := get_value(x))) for _ in range(10)) x = sum(max(value for x in range(10) if (value := get_value(x))) for _ in range(10))

View File

@ -7,8 +7,7 @@ from typing import Any, Callable, TypeVar, overload
_T = TypeVar("_T") _T = TypeVar("_T")
def decorator(*args: Any, **kwargs: Any) -> Callable[[_T], _T]: def decorator(*args: Any, **kwargs: Any) -> Callable[[_T], _T]: ...
...
@decorator( @decorator(
@ -19,7 +18,7 @@ def decorator(*args: Any, **kwargs: Any) -> Callable[[_T], _T]:
], ],
) )
def decorated( def decorated(
x: list[str] = [x for x in ["a", "b"] if x in (walrus_target_2 := ["a", "b"])] x: list[str] = [x for x in ["a", "b"] if x in (walrus_target_2 := ["a", "b"])],
): ):
pass pass
@ -29,13 +28,11 @@ reveal_type(walrus_target_2, expected_text="list[str]")
@overload @overload
def func1(value: None = None) -> None: def func1(value: None = None) -> None: ...
...
@overload @overload
def func1(value: str) -> str: def func1(value: str) -> str: ...
...
def func1(value: str | None = None) -> str | None: def func1(value: str | None = None) -> str | None:

View File

@ -19,15 +19,12 @@ class MyPartial[**P, R]:
self.first = first self.first = first
self.func = func self.func = func
def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: def __call__(self, *args: P.args, **kwargs: P.kwargs) -> R: ...
...
class CallbackKeyed[*Ts](Protocol): class CallbackKeyed[*Ts](Protocol):
def __call__(self, *args: *Ts, keyed: bool) -> tuple[*Ts]: def __call__(self, *args: *Ts, keyed: bool) -> tuple[*Ts]: ...
...
def invoke_keyed[*Ts](fn: CallbackKeyed[*Ts], *args: *Ts) -> tuple[*Ts]: def invoke_keyed[*Ts](fn: CallbackKeyed[*Ts], *args: *Ts) -> tuple[*Ts]:
return fn(*args, keyed=True) return fn(*args, keyed=True)

View File

@ -7,12 +7,15 @@ T = TypeVar("T")
T_co = TypeVar("T_co", covariant=True) T_co = TypeVar("T_co", covariant=True)
T_contra = TypeVar("T_contra", contravariant=True) T_contra = TypeVar("T_contra", contravariant=True)
class Parent_Invariant(Generic[T]): class Parent_Invariant(Generic[T]):
pass pass
class ShouldBeInvariant[T](Parent_Invariant[T]): class ShouldBeInvariant[T](Parent_Invariant[T]):
pass pass
# This should generate an error. # This should generate an error.
a1: ShouldBeInvariant[int] = ShouldBeInvariant[float]() a1: ShouldBeInvariant[int] = ShouldBeInvariant[float]()
@ -23,9 +26,11 @@ a2: ShouldBeInvariant[float] = ShouldBeInvariant[int]()
class Parent_Covariant(Generic[T_co]): class Parent_Covariant(Generic[T_co]):
pass pass
class ShouldBeCovariant[T](Parent_Covariant[T]): class ShouldBeCovariant[T](Parent_Covariant[T]):
pass pass
# This should generate an error. # This should generate an error.
b1: ShouldBeCovariant[int] = ShouldBeCovariant[float]() b1: ShouldBeCovariant[int] = ShouldBeCovariant[float]()
@ -35,11 +40,12 @@ b2: ShouldBeCovariant[float] = ShouldBeCovariant[int]()
class Parent_Contravariant(Generic[T_contra]): class Parent_Contravariant(Generic[T_contra]):
pass pass
class ShouldBeContravariant[T](Parent_Contravariant[T]): class ShouldBeContravariant[T](Parent_Contravariant[T]):
pass pass
c1: ShouldBeContravariant[int] = ShouldBeContravariant[float]() c1: ShouldBeContravariant[int] = ShouldBeContravariant[float]()
# This should generate an error. # This should generate an error.
c2: ShouldBeContravariant[float] = ShouldBeContravariant[int]() c2: ShouldBeContravariant[float] = ShouldBeContravariant[int]()

View File

@ -4,12 +4,10 @@
from typing import Any, Hashable, Mapping, Protocol from typing import Any, Hashable, Mapping, Protocol
def requires_hashable_tuple(p1: tuple[Hashable, ...]): def requires_hashable_tuple(p1: tuple[Hashable, ...]): ...
...
def requires_hashable_dict(p1: dict[str, Hashable]): def requires_hashable_dict(p1: dict[str, Hashable]): ...
...
def test_args(*args: Hashable): def test_args(*args: Hashable):
@ -24,8 +22,7 @@ def test_kwargs(**kwargs: Hashable):
requires_hashable_dict(kwargs) requires_hashable_dict(kwargs)
class StrSubclass(str): class StrSubclass(str): ...
...
def test_kwargs2( def test_kwargs2(
@ -51,30 +48,26 @@ def test_kwargs2(
class Callback1(Protocol): class Callback1(Protocol):
def __call__(self) -> None: def __call__(self) -> None: ...
...
def func1( def func1(
value: str = ..., value: str = ...,
*args: object, *args: object,
) -> None: ) -> None: ...
...
def func2( def func2(
value: str = ..., value: str = ...,
**kwargs: object, **kwargs: object,
) -> None: ) -> None: ...
...
def func3( def func3(
value: str = ..., value: str = ...,
*args: object, *args: object,
**kwargs: object, **kwargs: object,
) -> None: ) -> None: ...
...
v1: Callback1 = func1 v1: Callback1 = func1

View File

@ -71,8 +71,7 @@ for a, b in zip(*q6):
reveal_type(b, expected_text="int") reveal_type(b, expected_text="int")
def func1(a: list[str], c: list[int]): def func1(a: list[str], c: list[int]): ...
...
func1(*q6) func1(*q6)

View File

@ -5,31 +5,25 @@
from typing import Any, Generic, TypeVar, Mapping, KeysView from typing import Any, Generic, TypeVar, Mapping, KeysView
class MyMapping(Mapping[str, Any]): class MyMapping(Mapping[str, Any]): ...
...
class StrRecord: class StrRecord:
def __getitem__(self, __key: str) -> str: def __getitem__(self, __key: str) -> str: ...
...
def keys(self) -> KeysView[str]: def keys(self) -> KeysView[str]: ...
...
T = TypeVar("T") T = TypeVar("T")
class GenericRecord(Generic[T]): class GenericRecord(Generic[T]):
def __getitem__(self, __key: str) -> T: def __getitem__(self, __key: str) -> T: ...
...
def keys(self) -> KeysView[T]: def keys(self) -> KeysView[T]: ...
...
def func1(**kwargs: Any) -> None: def func1(**kwargs: Any) -> None: ...
...
m = MyMapping() m = MyMapping()

View File

@ -9,16 +9,14 @@ from typing import Any, Awaitable, Callable, Iterable, Sequence, TypeVar
_T1 = TypeVar("_T1") _T1 = TypeVar("_T1")
def func1(__iterable: Iterable[_T1]) -> _T1: def func1(__iterable: Iterable[_T1]) -> _T1: ...
...
a: Callable[[Sequence[float]], float] = func1 a: Callable[[Sequence[float]], float] = func1
b: Callable[[Sequence[Any]], Any] = func1 b: Callable[[Sequence[Any]], Any] = func1
def func2(__iterable: Sequence[_T1]) -> _T1: def func2(__iterable: Sequence[_T1]) -> _T1: ...
...
# This should generate an error because an Iterable parameter # This should generate an error because an Iterable parameter
@ -29,8 +27,7 @@ c: Callable[[Iterable[float]], float] = func2
_T2 = TypeVar("_T2", bound=float) _T2 = TypeVar("_T2", bound=float)
def func3(__iterable: Iterable[_T2]) -> _T2: def func3(__iterable: Iterable[_T2]) -> _T2: ...
...
d: Callable[[Sequence[int]], int] = func3 d: Callable[[Sequence[int]], int] = func3

View File

@ -8,8 +8,7 @@ T = TypeVar("T")
R = TypeVar("R") R = TypeVar("R")
class ClassA(Generic[R]): class ClassA(Generic[R]): ...
...
class ClassB(Generic[T]): class ClassB(Generic[T]):

View File

@ -8,17 +8,14 @@ T = TypeVar("T")
@overload @overload
def func1(real: float): def func1(real: float): ...
...
@overload @overload
def func1(real: str): def func1(real: str): ...
...
def func1(real: float | str) -> None: def func1(real: float | str) -> None: ...
...
def func2(f: Callable[[T], Any], p: T): def func2(f: Callable[[T], Any], p: T):

View File

@ -1,5 +1,6 @@
# This sample tests the handling of the `__call__` attribute. # This sample tests the handling of the `__call__` attribute.
class A: class A:
def __init__(self): def __init__(self):
self.__call__ = self.method1 self.__call__ = self.method1

View File

@ -140,7 +140,7 @@ class TestClass7:
pass pass
def test_func7(*args: * tuple[int, *tuple[int, ...]]) -> int: def test_func7(*args: *tuple[int, *tuple[int, ...]]) -> int:
return 123 return 123

View File

@ -9,8 +9,7 @@ OutputT = TypeVar("OutputT", covariant=True)
class MyCallable(Protocol[InputT, OutputT]): class MyCallable(Protocol[InputT, OutputT]):
def __call__(self, inputs: InputT) -> OutputT: def __call__(self, inputs: InputT) -> OutputT: ...
...
class Class1: class Class1:

View File

@ -7,17 +7,14 @@ TE = TypeVar("TE", bound=Exception)
class CallbackProtocol1(Protocol[TE]): class CallbackProtocol1(Protocol[TE]):
def __call__(self, s_exc: Exception, t_exc_class: Type[TE]) -> TE: def __call__(self, s_exc: Exception, t_exc_class: Type[TE]) -> TE: ...
...
def func1(s_exc: Exception, t_exc_class: Type[TE]) -> TE: def func1(s_exc: Exception, t_exc_class: Type[TE]) -> TE: ...
...
def func2( def func2(
s_exc_class: Exception, s_exc_class: Exception,
t_exc_class: Type[TE], t_exc_class: Type[TE],
mapper: CallbackProtocol1[TE] = func1, mapper: CallbackProtocol1[TE] = func1,
): ): ...
...

View File

@ -6,15 +6,12 @@ from typing import Any, Protocol, overload
class P1(Protocol): class P1(Protocol):
@overload @overload
def __call__(self, x: int) -> int: def __call__(self, x: int) -> int: ...
...
@overload @overload
def __call__(self, x: str) -> str: def __call__(self, x: str) -> str: ...
...
def __call__(self, x: Any) -> Any: def __call__(self, x: Any) -> Any: ...
...
def func0(x: Any) -> Any: def func0(x: Any) -> Any:
@ -32,13 +29,11 @@ a1: P1 = func1
@overload @overload
def of1(x: int) -> int: def of1(x: int) -> int: ...
...
@overload @overload
def of1(x: str) -> str: def of1(x: str) -> str: ...
...
def of1(x: Any) -> Any: def of1(x: Any) -> Any:
@ -46,13 +41,11 @@ def of1(x: Any) -> Any:
@overload @overload
def of2(x: int) -> complex: def of2(x: int) -> complex: ...
...
@overload @overload
def of2(x: str) -> str: def of2(x: str) -> str: ...
...
def of2(x: Any) -> Any: def of2(x: Any) -> Any:
@ -66,8 +59,7 @@ b1: P1 = of2
class P2(Protocol): class P2(Protocol):
def __call__(self, *args: int) -> Any: def __call__(self, *args: int) -> Any: ...
...
a: P2 = lambda *args: map(lambda arg: arg + 0, args) a: P2 = lambda *args: map(lambda arg: arg + 0, args)

View File

@ -6,22 +6,18 @@ from typing import Protocol
# Callback with positional parameter with default arg value. # Callback with positional parameter with default arg value.
class Callback1(Protocol): class Callback1(Protocol):
def __call__(self, path: str = ...) -> str: def __call__(self, path: str = ...) -> str: ...
...
# Callback with positional parameter without default arg value. # Callback with positional parameter without default arg value.
class Callback2(Protocol): class Callback2(Protocol):
def __call__(self, path: str) -> str: def __call__(self, path: str) -> str: ...
...
def func1_1(path: str = "") -> str: def func1_1(path: str = "") -> str: ...
...
def func1_2(path: str) -> str: def func1_2(path: str) -> str: ...
...
val1_1: Callback1 = func1_1 val1_1: Callback1 = func1_1
@ -36,22 +32,18 @@ val2_2: Callback2 = func1_2
# Callback with keyword parameter with default arg value. # Callback with keyword parameter with default arg value.
class Callback3(Protocol): class Callback3(Protocol):
def __call__(self, *, path: str = ...) -> str: def __call__(self, *, path: str = ...) -> str: ...
...
# Callback with keyword parameter without default arg value. # Callback with keyword parameter without default arg value.
class Callback4(Protocol): class Callback4(Protocol):
def __call__(self, *, path: str) -> str: def __call__(self, *, path: str) -> str: ...
...
def func3_1(*, path: str = "") -> str: def func3_1(*, path: str = "") -> str: ...
...
def func3_2(*, path: str) -> str: def func3_2(*, path: str) -> str: ...
...
val3_1: Callback3 = func3_1 val3_1: Callback3 = func3_1

View File

@ -5,11 +5,10 @@ from typing import Any, Protocol
class X(Protocol): class X(Protocol):
def __call__(self, x: int, /, y: str) -> Any: def __call__(self, x: int, /, y: str) -> Any: ...
...
def f1(x: int, /, y: str, z: None = None) -> Any:
... def f1(x: int, /, y: str, z: None = None) -> Any: ...
x: X = f1 x: X = f1

View File

@ -5,12 +5,10 @@ from typing import Any, Protocol
class P(Protocol): class P(Protocol):
def __call__(self, *args: Any, kwarg0: Any, kwarg1: Any) -> None: def __call__(self, *args: Any, kwarg0: Any, kwarg1: Any) -> None: ...
...
def f(*args: Any, kwarg0: Any, kwarg1: Any) -> None: def f(*args: Any, kwarg0: Any, kwarg1: Any) -> None: ...
...
p: P = f p: P = f

View File

@ -15,8 +15,7 @@ class A:
_T = TypeVar("_T", bound=A) _T = TypeVar("_T", bound=A)
class B(Generic[_T]): class B(Generic[_T]): ...
...
class C(A): class C(A):

View File

@ -9,8 +9,7 @@ class ClassA:
# This should generate a warning because __class_getitem__ # This should generate a warning because __class_getitem__
# is implicitly a classmethod and should use cls rather than # is implicitly a classmethod and should use cls rather than
# self. # self.
def __class_getitem__(self, args: tuple[int, ...]) -> None: def __class_getitem__(self, args: tuple[int, ...]) -> None: ...
...
reveal_type(ClassA[10, 63], expected_text="type[ClassA]") reveal_type(ClassA[10, 63], expected_text="type[ClassA]")
@ -23,8 +22,7 @@ _S = TypeVar("_S")
class ClassB(Generic[_T, _S]): class ClassB(Generic[_T, _S]):
# Even though this class has a __class_getitem__ method, # Even though this class has a __class_getitem__ method,
# it will be assumed to follow normal generic class semantics. # it will be assumed to follow normal generic class semantics.
def __class_getitem__(cls, args: tuple[int, ...]) -> None: def __class_getitem__(cls, args: tuple[int, ...]) -> None: ...
...
reveal_type(ClassB[int, str], expected_text="type[ClassB[int, str]]") reveal_type(ClassB[int, str], expected_text="type[ClassB[int, str]]")

View File

@ -19,7 +19,6 @@ def dynamic_subclass1(cls: type[T_A]):
def dynamic_subclass2(base: type[A] | None): def dynamic_subclass2(base: type[A] | None):
class SubClass(base or A): class SubClass(base or A): ...
...
return SubClass return SubClass

View File

@ -6,34 +6,27 @@ from typing import Collection, Iterator, Mapping, Sequence, TypeVar
# This should generate an error. # This should generate an error.
class A(Mapping[str, int], Collection[int]): class A(Mapping[str, int], Collection[int]):
def __len__(self) -> int: def __len__(self) -> int: ...
...
def __iter__(self) -> Iterator[str]: def __iter__(self) -> Iterator[str]: ...
...
# This should generate an error. # This should generate an error.
class B(Mapping[str, int], Sequence[int]): class B(Mapping[str, int], Sequence[int]): ...
...
# This should generate an error. # This should generate an error.
class C(Sequence[int], Mapping[str, int]): class C(Sequence[int], Mapping[str, int]): ...
...
class D(Sequence[float], Mapping[float, int]): class D(Sequence[float], Mapping[float, int]): ...
...
class E(Sequence[float], Mapping[int, int]): class E(Sequence[float], Mapping[int, int]): ...
...
# This should generate an error. # This should generate an error.
class F(Mapping[int, int], Sequence[float]): class F(Mapping[int, int], Sequence[float]): ...
...
T = TypeVar("T") T = TypeVar("T")
@ -41,16 +34,13 @@ S = TypeVar("S")
class G(Mapping[T, S], Collection[T]): class G(Mapping[T, S], Collection[T]):
def __len__(self) -> int: def __len__(self) -> int: ...
...
def __iter__(self) -> Iterator[T]: ...
def __iter__(self) -> Iterator[T]:
...
# This should generate an error. # This should generate an error.
class H(Mapping[T, S], Collection[S]): class H(Mapping[T, S], Collection[S]):
def __len__(self) -> int: def __len__(self) -> int: ...
...
def __iter__(self) -> Iterator[T]: def __iter__(self) -> Iterator[T]: ...
...

View File

@ -215,8 +215,7 @@ class SubclassTuple2(ParentClass2):
cv_decl_1, cv_decl_2, cv_decl_3 = (3, 4.5, None) cv_decl_1, cv_decl_2, cv_decl_3 = (3, 4.5, None)
class ConfigBase: class ConfigBase: ...
...
class ParentClass3(Protocol): class ParentClass3(Protocol):
@ -225,13 +224,11 @@ class ParentClass3(Protocol):
class ChildClass3(ParentClass3): class ChildClass3(ParentClass3):
class Config1(ConfigBase): class Config1(ConfigBase): ...
...
# This should generate an error if reportIncompatibleVariableOverride # This should generate an error if reportIncompatibleVariableOverride
# is enabled. # is enabled.
class Config2: class Config2: ...
...
class PeerClass1: class PeerClass1:

View File

@ -66,5 +66,4 @@ class TD_A2(TypedDict):
# This should generate an error for x but not y. # This should generate an error for x but not y.
class TD_A(TD_A1, TD_A2): class TD_A(TD_A1, TD_A2): ...
...

View File

@ -5,31 +5,25 @@
from typing import Any, Callable, overload from typing import Any, Callable, overload
class C: class C: ...
...
@overload @overload
def func1(v: Callable[[], int]) -> int: def func1(v: Callable[[], int]) -> int: ...
...
@overload @overload
def func1(v: Callable[[], list[C]]) -> list[C]: def func1(v: Callable[[], list[C]]) -> list[C]: ...
...
def func1(v: Any) -> Any: def func1(v: Any) -> Any: ...
...
def func2(v: list[C]): def func2(v: list[C]): ...
...
t = func1(lambda: func3()) t = func1(lambda: func3())
t.append(C()) t.append(C())
def func3() -> list[C]: def func3() -> list[C]: ...
...

View File

@ -5,31 +5,25 @@
from typing import Any, Callable, overload from typing import Any, Callable, overload
class C: class C: ...
...
@overload @overload
def func1(v: Callable[[], int]) -> int: def func1(v: Callable[[], int]) -> int: ...
...
@overload @overload
def func1(v: Callable[[], list[C]]) -> list[C]: def func1(v: Callable[[], list[C]]) -> list[C]: ...
...
def func1(v: Any) -> Any: def func1(v: Any) -> Any: ...
...
def func2(v: list[C]): def func2(v: list[C]): ...
...
t = func1(lambda: func3()) t = func1(lambda: func3())
t.append(C()) t.append(C())
def func3() -> list[C]: def func3() -> list[C]: ...
...

View File

@ -30,12 +30,10 @@ def func1(os: OS, val: Literal[1, "linux"]):
return True return True
class ClassA: class ClassA: ...
...
class ClassB: class ClassB: ...
...
_T1 = TypeVar("_T1") _T1 = TypeVar("_T1")

View File

@ -8,8 +8,7 @@ b = a + 4
c = 1.2 * a c = 1.2 * a
def requires_complex(val: complex): def requires_complex(val: complex): ...
...
requires_complex(a) requires_complex(a)

View File

@ -18,8 +18,7 @@ def add1(value: _T1) -> _T1:
class IntSubclass2(int): class IntSubclass2(int):
def __add__(self, value: object) -> "IntSubclass2": def __add__(self, value: object) -> "IntSubclass2": ...
...
_T2 = TypeVar("_T2", int, IntSubclass2) _T2 = TypeVar("_T2", int, IntSubclass2)

View File

@ -6,8 +6,7 @@ from os import PathLike
from typing import AnyStr from typing import AnyStr
def func1(path: AnyStr | PathLike[AnyStr]) -> AnyStr: def func1(path: AnyStr | PathLike[AnyStr]) -> AnyStr: ...
...
def func2(value: AnyStr) -> AnyStr: def func2(value: AnyStr) -> AnyStr:

View File

@ -5,16 +5,13 @@
from typing import TypeVar, Generic from typing import TypeVar, Generic
class A: class A: ...
...
class B: class B: ...
...
class A2(A): class A2(A): ...
...
T = TypeVar("T", A, B) T = TypeVar("T", A, B)

View File

@ -5,8 +5,7 @@ from typing import AnyStr, Iterable, TypeVar, Generic
from dataclasses import dataclass from dataclasses import dataclass
class ClassA: class ClassA: ...
...
_T = TypeVar("_T", int | float, ClassA) _T = TypeVar("_T", int | float, ClassA)

View File

@ -13,12 +13,10 @@ _T1 = TypeVar("_T1")
AnyStr = TypeVar("AnyStr", str, bytes) AnyStr = TypeVar("AnyStr", str, bytes)
def exists2(path: AnyStr) -> bool: def exists2(path: AnyStr) -> bool: ...
...
def filter2(f: Callable[[_T1], Any], i: Iterable[_T1]) -> Iterator[_T1]: def filter2(f: Callable[[_T1], Any], i: Iterable[_T1]) -> Iterator[_T1]: ...
...
result = filter2(exists2, ["hello", "world"]) result = filter2(exists2, ["hello", "world"])

View File

@ -8,12 +8,10 @@
from typing import Any, AnyStr, Optional, Protocol, TypeVar, Union from typing import Any, AnyStr, Optional, Protocol, TypeVar, Union
class Array: class Array: ...
...
class MMap: class MMap: ...
...
# Note that this union contains types that are not compatible # Note that this union contains types that are not compatible
@ -25,29 +23,24 @@ _T_co = TypeVar("_T_co", covariant=True)
class BufferedWriter: class BufferedWriter:
def write(self, __buffer: ReadableBuffer) -> int: def write(self, __buffer: ReadableBuffer) -> int: ...
...
class SupportsWrite(Protocol[_T_contra]): class SupportsWrite(Protocol[_T_contra]):
def write(self, __s: _T_contra) -> Any: def write(self, __s: _T_contra) -> Any: ...
...
class SupportsRead(Protocol[_T_co]): class SupportsRead(Protocol[_T_co]):
def read(self, __length: int = ...) -> _T_co: def read(self, __length: int = ...) -> _T_co: ...
...
class BufferedReader: class BufferedReader:
def read(self, __size: Optional[int] = ...) -> bytes: def read(self, __size: Optional[int] = ...) -> bytes: ...
...
def copyfileobj( def copyfileobj(
fsrc: SupportsRead[AnyStr], fdst: SupportsWrite[AnyStr], length: int = ... fsrc: SupportsRead[AnyStr], fdst: SupportsWrite[AnyStr], length: int = ...
) -> AnyStr: ) -> AnyStr: ...
...
def f(fr: BufferedReader, fw: BufferedWriter): def f(fr: BufferedReader, fw: BufferedWriter):

View File

@ -9,13 +9,11 @@ T = TypeVar("T")
class Async: class Async:
def fn(self, returnable: T) -> Awaitable[T]: def fn(self, returnable: T) -> Awaitable[T]: ...
...
class Sync: class Sync:
def fn(self, returnable: T) -> T: def fn(self, returnable: T) -> T: ...
...
T = TypeVar("T", Async, Sync) T = TypeVar("T", Async, Sync)

View File

@ -42,8 +42,7 @@ archive_path = data_dir / "hello"
shutil.rmtree(archive_path) shutil.rmtree(archive_path)
def func1(a: AnyStr, b: AnyStr) -> None: def func1(a: AnyStr, b: AnyStr) -> None: ...
...
def func2(a: Union[str, bytes], b: Union[str, bytes]): def func2(a: Union[str, bytes], b: Union[str, bytes]):
@ -51,27 +50,22 @@ def func2(a: Union[str, bytes], b: Union[str, bytes]):
func1(a, b) func1(a, b)
class A: class A: ...
...
class B: class B: ...
...
class C: class C: ...
...
class D: class D: ...
...
T3 = TypeVar("T3", A, B, Union[C, D]) T3 = TypeVar("T3", A, B, Union[C, D])
def do_something(value: T3) -> T3: def do_something(value: T3) -> T3: ...
...
def func10(value: Union[C, D]): def func10(value: Union[C, D]):

View File

@ -4,8 +4,7 @@
from typing import Iterator, Optional, Sequence, TypeVar, Union from typing import Iterator, Optional, Sequence, TypeVar, Union
def func0(a: Union[int, float]): def func0(a: Union[int, float]): ...
...
_T1 = TypeVar("_T1", int, float) _T1 = TypeVar("_T1", int, float)
@ -39,12 +38,10 @@ def func5(xs: Sequence[Optional[_T2]]) -> Iterator[_T2]:
return func3(xs) return func3(xs)
class A: class A: ...
...
class B(A): class B(A): ...
...
_T4 = TypeVar("_T4", A, B) _T4 = TypeVar("_T4", A, B)

View File

@ -10,8 +10,7 @@ _T = TypeVar("_T")
class A(Iterator[_T_co]): class A(Iterator[_T_co]):
def __new__(cls, __iterable: Iterable[_T]) -> "A[tuple[_T, _T]]": def __new__(cls, __iterable: Iterable[_T]) -> "A[tuple[_T, _T]]": ...
...
def __next__(self) -> _T_co: ... def __next__(self) -> _T_co: ...
@ -22,8 +21,7 @@ def func1(iterable: Iterable[_T]) -> Iterator[tuple[_T, _T, _T]]:
class B(Generic[_T_co]): class B(Generic[_T_co]):
def __new__(cls, __iter1: Iterable[_T]) -> "B[_T]": def __new__(cls, __iter1: Iterable[_T]) -> "B[_T]": ...
...
def func2(p1: list[dict]): def func2(p1: list[dict]):

View File

@ -9,38 +9,32 @@ _M = TypeVar("_M")
class A(Generic[_M, _N]): class A(Generic[_M, _N]):
def __new__(cls, m: _M, n: _N) -> "A[_M, _N]": def __new__(cls, m: _M, n: _N) -> "A[_M, _N]": ...
...
a: A[Literal[3], Literal[4]] = A(3, 4) a: A[Literal[3], Literal[4]] = A(3, 4)
class B(Generic[_M, _N]): class B(Generic[_M, _N]):
def __new__(cls, m: _M, n: _N) -> "B[_M, _N]": def __new__(cls, m: _M, n: _N) -> "B[_M, _N]": ...
...
def __init__(self, *args: Any, **kwargs: Any) -> None: def __init__(self, *args: Any, **kwargs: Any) -> None: ...
...
b: B[Literal[3], Literal[4]] = B(3, 4) b: B[Literal[3], Literal[4]] = B(3, 4)
class C(Generic[_M, _N]): class C(Generic[_M, _N]):
def __new__(cls, m: _M, n: _N) -> "C[_M, _N]": def __new__(cls, m: _M, n: _N) -> "C[_M, _N]": ...
...
def __init__(self, m: _M, n: _N) -> None: def __init__(self, m: _M, n: _N) -> None: ...
...
c: C[Literal[3], Literal[4]] = C(3, 4) c: C[Literal[3], Literal[4]] = C(3, 4)
class D(Generic[_M, _N]): class D(Generic[_M, _N]):
def __new__(cls, m: _M, n: _N) -> Self: def __new__(cls, m: _M, n: _N) -> Self: ...
...
d: D[Literal[3], Literal[4]] = D(3, 4) d: D[Literal[3], Literal[4]] = D(3, 4)

View File

@ -13,24 +13,21 @@ class A(Generic[T]):
class B(Generic[T]): class B(Generic[T]):
def __init__(self): def __init__(self): ...
...
class C(Generic[T]): class C(Generic[T]):
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs) return super().__new__(cls, *args, **kwargs)
def __init__(self): def __init__(self): ...
...
class D(Generic[T]): class D(Generic[T]):
def __new__(cls, *args, **kwargs): def __new__(cls, *args, **kwargs):
return super().__new__(cls, *args, **kwargs) return super().__new__(cls, *args, **kwargs)
def __init__(self, a: T): def __init__(self, a: T): ...
...
class E(Generic[T]): class E(Generic[T]):

View File

@ -178,8 +178,7 @@ def s18():
class Plant(Generic[_T1]): class Plant(Generic[_T1]):
def __new__(cls, o: _T1) -> Self: def __new__(cls, o: _T1) -> Self: ...
...
plant: Plant[float] = Plant(0) plant: Plant[float] = Plant(0)

View File

@ -9,14 +9,11 @@ T = TypeVar("T", covariant=True)
class A(Protocol[T]): class A(Protocol[T]):
def a(self) -> "A[Tuple[T]]": def a(self) -> "A[Tuple[T]]": ...
...
def b(self) -> "A[Tuple[T]]": def b(self) -> "A[Tuple[T]]": ...
...
def c(self) -> "T": def c(self) -> "T": ...
...
class B(Generic[T]): class B(Generic[T]):

View File

@ -72,20 +72,17 @@ def func1(obv: Container[T], default_value: T = None) -> None:
obv.on_next(default_value) obv.on_next(default_value)
class A: class A: ...
...
T_A = TypeVar("T_A", bound=A) T_A = TypeVar("T_A", bound=A)
class B(Generic[T]): class B(Generic[T]):
def __init__(self, c: Callable[[], T]): def __init__(self, c: Callable[[], T]): ...
...
def func2(cls: type[T_A] = A) -> Callable[[], T_A]: def func2(cls: type[T_A] = A) -> Callable[[], T_A]: ...
...
B(func2()) B(func2())

View File

@ -11,22 +11,18 @@ T = TypeVar("T", contravariant=True)
S = TypeVar("S", contravariant=True) S = TypeVar("S", contravariant=True)
class ClassA(Generic[T]): class ClassA(Generic[T]): ...
...
class ClassB(Generic[S, T], ClassA[T]): class ClassB(Generic[S, T], ClassA[T]): ...
...
class ClassC(ClassB[S, T]): class ClassC(ClassB[S, T]):
def __new__(cls, subcon: ClassA[S]) -> ClassC[S, list[S]]: def __new__(cls, subcon: ClassA[S]) -> ClassC[S, list[S]]: ...
...
class ClassD(ClassB[S, T]): class ClassD(ClassB[S, T]):
def __new__(cls, subcon: ClassA[S]) -> ClassD[S, list[S]]: def __new__(cls, subcon: ClassA[S]) -> ClassD[S, list[S]]: ...
...
c = ClassA[int]() c = ClassA[int]()

View File

@ -29,3 +29,11 @@ def func1(t: type[TA]) -> TA: ...
b = B(func1, A) b = B(func1, A)
reveal_type(b, expected_text="B[(t: type[A]), A]") reveal_type(b, expected_text="B[(t: type[A]), A]")
class C(Generic[TA]):
def __init__(self, _type: type[TA]) -> None: ...
c = B(C, A)
reveal_type(c, expected_text="B[(_type: type[A]), C[A]]")

View File

@ -9,8 +9,7 @@ T_A = TypeVar("T_A", bound="A")
class A(ABC): class A(ABC):
@abstractmethod @abstractmethod
def some_method(self) -> str: def some_method(self) -> str: ...
...
def some_factory_method_1(self): def some_factory_method_1(self):
return type(self)() return type(self)()

View File

@ -0,0 +1,17 @@
# This sample tests the case where an inner coroutine with an inferred
# return type is referenced in a manner that results in recursion.
import asyncio
def func1(replace_inner: bool) -> None:
inner = lambda: None
async def wrapper():
inner()
wrapped_fn = wrapper()
asyncio.create_task(wrapped_fn)
if replace_inner:
inner = lambda: None

View File

@ -12,8 +12,9 @@ class IsDataclass(Protocol):
__dataclass_fields__: ClassVar[dict[str, Any]] __dataclass_fields__: ClassVar[dict[str, Any]]
def dataclass_only(x: IsDataclass): def dataclass_only(
... # do something that only makes sense with a dataclass x: IsDataclass,
): ... # do something that only makes sense with a dataclass
@dataclass @dataclass

View File

@ -7,12 +7,10 @@ from typing import Any, cast, overload
class MyDescriptor: class MyDescriptor:
@overload @overload
def __get__(self, __obj: None, __owner: Any) -> "MyDescriptor": def __get__(self, __obj: None, __owner: Any) -> "MyDescriptor": ...
...
@overload @overload
def __get__(self, __obj: object, __owner: Any) -> int: def __get__(self, __obj: object, __owner: Any) -> int: ...
...
def __get__(self, __obj: object | None, __owner: Any) -> "int | MyDescriptor": def __get__(self, __obj: object | None, __owner: Any) -> "int | MyDescriptor":
if __obj is None: if __obj is None:

Some files were not shown because too many files have changed in this diff Show More