mirror of
https://github.com/microsoft/pyright.git
synced 2024-10-03 19:37:39 +03:00
Changed the hard-coded type of the __class__
symbol to be Self@T
rather than T
(where T
is the enclosing class). This addresses #8305. (#8307)
This commit is contained in:
parent
d7c5d0691a
commit
8ed6c10486
@ -532,7 +532,7 @@ export class Binder extends ParseTreeWalker {
|
||||
const enclosingClass = ParseTreeUtils.getEnclosingClass(node);
|
||||
if (enclosingClass) {
|
||||
// Add the implicit "__class__" symbol described in PEP 3135.
|
||||
this._addImplicitSymbolToCurrentScope('__class__', node, 'class');
|
||||
this._addImplicitSymbolToCurrentScope('__class__', node, 'type[self]');
|
||||
}
|
||||
|
||||
this._deferBinding(() => {
|
||||
|
@ -46,7 +46,7 @@ export const enum DeclarationType {
|
||||
Alias,
|
||||
}
|
||||
|
||||
export type IntrinsicType = 'Any' | 'str' | 'str | None' | 'int' | 'Iterable[str]' | 'class' | 'Dict[str, Any]';
|
||||
export type IntrinsicType = 'Any' | 'str' | 'str | None' | 'int' | 'Iterable[str]' | 'type[self]' | 'Dict[str, Any]';
|
||||
|
||||
export interface DeclarationBase {
|
||||
// Category of this symbol (function, variable, etc.).
|
||||
|
@ -8396,7 +8396,6 @@ export function createTypeEvaluator(
|
||||
|
||||
if ((functionInfo?.flags & FunctionTypeFlags.StaticMethod) !== 0) {
|
||||
addError(LocMessage.superCallZeroArgFormStaticMethod(), node.leftExpression);
|
||||
targetClassType = UnknownType.create();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -8405,6 +8404,8 @@ export function createTypeEvaluator(
|
||||
}
|
||||
}
|
||||
|
||||
const concreteTargetClassType = makeTopLevelTypeVarsConcrete(targetClassType);
|
||||
|
||||
// Determine whether to further narrow the type.
|
||||
let bindToType: ClassType | undefined;
|
||||
if (node.arguments.length > 1) {
|
||||
@ -8417,11 +8418,11 @@ export function createTypeEvaluator(
|
||||
if (isAnyOrUnknown(secondArgType)) {
|
||||
// Ignore unknown or any types.
|
||||
} else if (isClassInstance(secondArgType)) {
|
||||
if (isInstantiableClass(targetClassType)) {
|
||||
if (isInstantiableClass(concreteTargetClassType)) {
|
||||
if (
|
||||
!derivesFromClassRecursive(
|
||||
ClassType.cloneAsInstantiable(secondArgType),
|
||||
targetClassType,
|
||||
concreteTargetClassType,
|
||||
/* ignoreUnknown */ true
|
||||
)
|
||||
) {
|
||||
@ -8430,10 +8431,10 @@ export function createTypeEvaluator(
|
||||
}
|
||||
bindToType = secondArgType;
|
||||
} else if (isInstantiableClass(secondArgType)) {
|
||||
if (isInstantiableClass(targetClassType)) {
|
||||
if (isInstantiableClass(concreteTargetClassType)) {
|
||||
if (
|
||||
!ClassType.isBuiltIn(targetClassType, 'type') &&
|
||||
!derivesFromClassRecursive(secondArgType, targetClassType, /* ignoreUnknown */ true)
|
||||
!ClassType.isBuiltIn(concreteTargetClassType, 'type') &&
|
||||
!derivesFromClassRecursive(secondArgType, concreteTargetClassType, /* ignoreUnknown */ true)
|
||||
) {
|
||||
reportError = true;
|
||||
}
|
||||
@ -8514,7 +8515,7 @@ export function createTypeEvaluator(
|
||||
const parentNode = node.parent;
|
||||
if (parentNode?.nodeType === ParseNodeType.MemberAccess) {
|
||||
const memberName = parentNode.memberName.value;
|
||||
let effectiveTargetClass = isClass(targetClassType) ? targetClassType : undefined;
|
||||
let effectiveTargetClass = isClass(concreteTargetClassType) ? concreteTargetClassType : undefined;
|
||||
|
||||
// If the bind-to type is a protocol, don't use the effective target class.
|
||||
// This pattern is used for mixins, where the mixin type is a protocol class
|
||||
@ -8568,7 +8569,7 @@ export function createTypeEvaluator(
|
||||
}
|
||||
|
||||
// Handle the super() call when used outside of a member access expression.
|
||||
if (isInstantiableClass(targetClassType)) {
|
||||
if (isInstantiableClass(concreteTargetClassType)) {
|
||||
// We don't know which member is going to be accessed, so we cannot
|
||||
// deterministically determine the correct type in this case. We'll
|
||||
// use a heuristic that produces the "correct" (desired) behavior in
|
||||
@ -8578,14 +8579,15 @@ export function createTypeEvaluator(
|
||||
if (bindToType) {
|
||||
let nextBaseClassType: Type | undefined;
|
||||
|
||||
if (ClassType.isSameGenericClass(bindToType, targetClassType)) {
|
||||
if (ClassType.isSameGenericClass(bindToType, concreteTargetClassType)) {
|
||||
if (bindToType.details.baseClasses.length > 0) {
|
||||
nextBaseClassType = bindToType.details.baseClasses[0];
|
||||
}
|
||||
} else {
|
||||
const baseClassIndex = bindToType.details.baseClasses.findIndex(
|
||||
(baseClass) =>
|
||||
isClass(baseClass) && ClassType.isSameGenericClass(baseClass, targetClassType as ClassType)
|
||||
isClass(baseClass) &&
|
||||
ClassType.isSameGenericClass(baseClass, concreteTargetClassType as ClassType)
|
||||
);
|
||||
|
||||
if (baseClassIndex >= 0 && baseClassIndex < bindToType.details.baseClasses.length - 1) {
|
||||
@ -8609,11 +8611,11 @@ export function createTypeEvaluator(
|
||||
} else {
|
||||
// If the class derives from one or more unknown classes,
|
||||
// return unknown here to prevent spurious errors.
|
||||
if (targetClassType.details.mro.some((mroBase) => isAnyOrUnknown(mroBase))) {
|
||||
if (concreteTargetClassType.details.mro.some((mroBase) => isAnyOrUnknown(mroBase))) {
|
||||
return { type: UnknownType.create() };
|
||||
}
|
||||
|
||||
const baseClasses = targetClassType.details.baseClasses;
|
||||
const baseClasses = concreteTargetClassType.details.baseClasses;
|
||||
if (baseClasses.length > 0) {
|
||||
const baseClassType = baseClasses[0];
|
||||
if (isInstantiableClass(baseClassType)) {
|
||||
@ -20977,10 +20979,14 @@ export function createTypeEvaluator(
|
||||
return { type: AnyType.create() };
|
||||
}
|
||||
|
||||
if (declaration.intrinsicType === 'class') {
|
||||
if (declaration.intrinsicType === 'type[self]') {
|
||||
const classNode = ParseTreeUtils.getEnclosingClass(declaration.node) as ClassNode;
|
||||
const classTypeInfo = getTypeOfClass(classNode);
|
||||
return { type: classTypeInfo?.classType };
|
||||
return {
|
||||
type: classTypeInfo
|
||||
? synthesizeTypeVarForSelfCls(classTypeInfo.classType, /* isClsParam */ true)
|
||||
: UnknownType.create(),
|
||||
};
|
||||
}
|
||||
|
||||
const strType = getBuiltInObject(declaration.node, 'str');
|
||||
|
@ -29,6 +29,7 @@ import {
|
||||
VariableDeclaration,
|
||||
} from '../analyzer/declaration';
|
||||
import { isDefinedInFile } from '../analyzer/declarationUtils';
|
||||
import { transformTypeForEnumMember } from '../analyzer/enums';
|
||||
import { ImportedModuleDescriptor, ImportResolver } from '../analyzer/importResolver';
|
||||
import { ImportResult } from '../analyzer/importResult';
|
||||
import { getParameterListDetails, ParameterKind } from '../analyzer/parameterUtils';
|
||||
@ -80,6 +81,7 @@ import { ProgramView } from '../common/extensibility';
|
||||
import { fromLSPAny, toLSPAny } from '../common/lspUtils';
|
||||
import { convertOffsetToPosition, convertPositionToOffset } from '../common/positionUtils';
|
||||
import { PythonVersion, pythonVersion3_10, pythonVersion3_5 } from '../common/pythonVersion';
|
||||
import '../common/serviceProviderExtensions';
|
||||
import * as StringUtils from '../common/stringUtils';
|
||||
import { comparePositions, Position, TextRange } from '../common/textRange';
|
||||
import { TextRangeCollection } from '../common/textRangeCollection';
|
||||
@ -127,8 +129,6 @@ import {
|
||||
} from './completionProviderUtils';
|
||||
import { DocumentSymbolCollector } from './documentSymbolCollector';
|
||||
import { getAutoImportText, getDocumentationPartsForTypeAndDecl } from './tooltipUtils';
|
||||
import '../common/serviceProviderExtensions';
|
||||
import { transformTypeForEnumMember } from '../analyzer/enums';
|
||||
|
||||
namespace Keywords {
|
||||
const base: string[] = [
|
||||
@ -3033,7 +3033,7 @@ export class CompletionProvider {
|
||||
|
||||
switch (resolvedDeclaration.type) {
|
||||
case DeclarationType.Intrinsic:
|
||||
return resolvedDeclaration.intrinsicType === 'class'
|
||||
return resolvedDeclaration.intrinsicType === 'type[self]'
|
||||
? CompletionItemKind.Class
|
||||
: CompletionItemKind.Variable;
|
||||
|
||||
|
@ -38,7 +38,7 @@ class F(E):
|
||||
|
||||
class G(E, metaclass=type):
|
||||
def my_method(self):
|
||||
print(__class__)
|
||||
reveal_type(__class__, expected_text="type[Self@G]")
|
||||
|
||||
|
||||
# This should generate an error because only one metaclass is supported.
|
||||
|
Loading…
Reference in New Issue
Block a user