Skip to content

Commit

Permalink
Minor code cleanup — rename constant for clarity and refactor validat…
Browse files Browse the repository at this point in the history
…ion function. No functional change.
  • Loading branch information
msfterictraut committed Jun 18, 2023
1 parent 53cb3f9 commit 7ea11a1
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 43 deletions.
4 changes: 2 additions & 2 deletions packages/pyright-internal/src/analyzer/operations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -622,12 +622,12 @@ export function getTypeOfBinaryOperation(
adjustedLeftType = evaluator.reportMissingTypeArguments(
node.leftExpression,
adjustedLeftType,
flags | EvaluatorFlags.ExpectingType
flags | EvaluatorFlags.ExpectingInstantiableType
);
adjustedRightType = evaluator.reportMissingTypeArguments(
node.rightExpression,
adjustedRightType,
flags | EvaluatorFlags.ExpectingType
flags | EvaluatorFlags.ExpectingInstantiableType
);

const newUnion = combineTypes([adjustedLeftType, adjustedRightType]);
Expand Down
100 changes: 61 additions & 39 deletions packages/pyright-internal/src/analyzer/typeEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -936,7 +936,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
initializedBasicTypes(node);

let typeResult: TypeResult | undefined;
let reportExpectingTypeErrors = (flags & EvaluatorFlags.ExpectingType) !== 0;
let expectingInstantiable = (flags & EvaluatorFlags.ExpectingInstantiableType) !== 0;

switch (node.nodeType) {
case ParseNodeType.Name: {
Expand Down Expand Up @@ -976,7 +976,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
if (isExpectingType) {
// Don't report expecting type errors again. We will have already
// reported them when analyzing the contents of the string.
reportExpectingTypeErrors = false;
expectingInstantiable = false;
}

typeResult = getTypeOfStringList(node, flags, isExpectingType);
Expand Down Expand Up @@ -1087,7 +1087,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
case ParseNodeType.TypeAnnotation: {
typeResult = getTypeOfExpression(
node.typeAnnotation,
EvaluatorFlags.ExpectingType |
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ExpectingTypeAnnotation |
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.DisallowParamSpec |
Expand Down Expand Up @@ -1124,26 +1124,9 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
fail(`Unhandled expression type '${ParseTreeUtils.printExpression(node)}'`);
}

if (reportExpectingTypeErrors && !typeResult.isIncomplete) {
if (flags & EvaluatorFlags.DisallowTypeVarTuple) {
if (isVariadicTypeVar(typeResult.type) && !typeResult.type.isVariadicInUnion) {
addError(Localizer.Diagnostic.typeVarTupleContext(), node);
typeResult.type = UnknownType.create();
}
}

if (!isEffectivelyInstantiable(typeResult.type)) {
const isEmptyVariadic =
isClassInstance(typeResult.type) &&
ClassType.isTupleClass(typeResult.type) &&
typeResult.type.tupleTypeArguments?.length === 0;

if (!isEmptyVariadic) {
addExpectedClassDiagnostic(typeResult.type, node);
typeResult.type = UnknownType.create();
typeResult.typeErrors = true;
}
}
// Do we need to validate that the type is instantiable?
if (expectingInstantiable) {
validateTypeIsInstantiable(typeResult, flags, node);
}

writeTypeCache(node, typeResult, flags, inferenceContext, /* allowSpeculativeCaching */ true);
Expand Down Expand Up @@ -1199,6 +1182,33 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
return typeResult;
}

function validateTypeIsInstantiable(typeResult: TypeResult, flags: EvaluatorFlags, node: ExpressionNode) {
// If the type is incomplete, don't log any diagnostics yet.
if (typeResult.isIncomplete) {
return;
}

if (flags & EvaluatorFlags.DisallowTypeVarTuple) {
if (isVariadicTypeVar(typeResult.type) && !typeResult.type.isVariadicInUnion) {
addError(Localizer.Diagnostic.typeVarTupleContext(), node);
typeResult.type = UnknownType.create();
}
}

if (!isEffectivelyInstantiable(typeResult.type)) {
const isEmptyVariadic =
isClassInstance(typeResult.type) &&
ClassType.isTupleClass(typeResult.type) &&
typeResult.type.tupleTypeArguments?.length === 0;

if (!isEmptyVariadic) {
addExpectedClassDiagnostic(typeResult.type, node);
typeResult.type = UnknownType.create();
typeResult.typeErrors = true;
}
}
}

function getTypeOfAwaitOperator(node: AwaitNode, flags: EvaluatorFlags, inferenceContext?: InferenceContext) {
const effectiveExpectedType = inferenceContext
? createAwaitableReturnType(node, inferenceContext.expectedType, /* isGenerator */ false)
Expand Down Expand Up @@ -1287,7 +1297,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
let typeResult: TypeResult | undefined;

if (isExpectingType) {
let updatedFlags = flags | EvaluatorFlags.AllowForwardReferences | EvaluatorFlags.ExpectingType;
let updatedFlags = flags | EvaluatorFlags.AllowForwardReferences | EvaluatorFlags.ExpectingInstantiableType;

// In most cases, annotations within a string are not parsed by the interpreter.
// There are a few exceptions (e.g. the "bound" value for a TypeVar constructor).
Expand Down Expand Up @@ -1486,7 +1496,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
}

let evaluatorFlags =
EvaluatorFlags.ExpectingType |
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ExpectingTypeAnnotation |
EvaluatorFlags.ConvertEllipsisToAny |
EvaluatorFlags.EvaluateStringLiteralAsType;
Expand Down Expand Up @@ -4338,7 +4348,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
isTypeVar(type) &&
!type.details.isParamSpec &&
!type.isVariadicInUnion &&
(flags & EvaluatorFlags.ExpectingType) === 0 &&
(flags & EvaluatorFlags.ExpectingInstantiableType) === 0 &&
type.details.name === name
) {
// Handle the special case of a PEP 604 union. These can appear within
Expand All @@ -4361,7 +4371,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
}
}

if ((flags & EvaluatorFlags.ExpectingType) !== 0) {
if ((flags & EvaluatorFlags.ExpectingInstantiableType) !== 0) {
if ((flags & EvaluatorFlags.AllowGenericClassType) === 0) {
if (isInstantiableClass(type) && ClassType.isBuiltIn(type, 'Generic')) {
addDiagnostic(
Expand Down Expand Up @@ -4622,7 +4632,10 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions

// Is this a generic class that needs to be specialized?
if (isInstantiableClass(type)) {
if ((flags & EvaluatorFlags.ExpectingType) !== 0 && (flags & EvaluatorFlags.AllowMissingTypeArgs) === 0) {
if (
(flags & EvaluatorFlags.ExpectingInstantiableType) !== 0 &&
(flags & EvaluatorFlags.AllowMissingTypeArgs) === 0
) {
if (!type.typeAliasInfo && requiresTypeArguments(type)) {
if (!type.typeArguments || !type.isTypeArgumentExplicit) {
addDiagnostic(
Expand All @@ -4644,7 +4657,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions

// Is this a generic type alias that needs to be specialized?
if (
(flags & EvaluatorFlags.ExpectingType) !== 0 &&
(flags & EvaluatorFlags.ExpectingInstantiableType) !== 0 &&
type.typeAliasInfo &&
type.typeAliasInfo.typeParameters &&
type.typeAliasInfo.typeParameters.length > 0 &&
Expand Down Expand Up @@ -6126,7 +6139,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
// If this is meant to be a type and the base expression is a string expression,
// emit an error because this will generate a runtime exception in Python versions
// less than 3.10.
if (flags & EvaluatorFlags.ExpectingType) {
if (flags & EvaluatorFlags.ExpectingInstantiableType) {
if (node.baseExpression.nodeType === ParseNodeType.StringList) {
const fileInfo = AnalyzerNodeInfo.getFileInfo(node);
if (!fileInfo.isStubFile && fileInfo.executionEnvironment.pythonVersion < PythonVersion.V3_10) {
Expand Down Expand Up @@ -6606,7 +6619,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
return concreteSubtype;
}

if (flags & EvaluatorFlags.ExpectingType) {
if (flags & EvaluatorFlags.ExpectingInstantiableType) {
if (isTypeVar(unexpandedSubtype)) {
addDiagnostic(
AnalyzerNodeInfo.getFileInfo(node).diagnosticRuleSet.reportGeneralTypeIssues,
Expand All @@ -6630,7 +6643,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
concreteSubtype.details.effectiveMetaclass &&
isInstantiableClass(concreteSubtype.details.effectiveMetaclass) &&
!ClassType.isBuiltIn(concreteSubtype.details.effectiveMetaclass, ['type', '_InitVarMeta']) &&
(flags & EvaluatorFlags.ExpectingType) === 0
(flags & EvaluatorFlags.ExpectingInstantiableType) === 0
) {
const itemMethodType = getTypeOfClassMember(
node,
Expand Down Expand Up @@ -7314,7 +7327,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions

let adjustedFlags =
flags |
EvaluatorFlags.ExpectingType |
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ConvertEllipsisToAny |
EvaluatorFlags.EvaluateStringLiteralAsType;

Expand Down Expand Up @@ -7375,7 +7388,11 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
flags: EvaluatorFlags,
inferenceContext: InferenceContext | undefined
): TypeResult {
if ((flags & EvaluatorFlags.ExpectingType) !== 0 && node.expressions.length === 0 && !inferenceContext) {
if (
(flags & EvaluatorFlags.ExpectingInstantiableType) !== 0 &&
node.expressions.length === 0 &&
!inferenceContext
) {
return { type: makeTupleObject([]), isEmptyTupleShorthand: true };
}

Expand Down Expand Up @@ -11930,7 +11947,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
typeParameters = [];
let isTypeParamListValid = true;
typeParamsExpr.expressions.map((expr) => {
let entryType = getTypeOfExpression(expr, EvaluatorFlags.ExpectingType).type;
let entryType = getTypeOfExpression(expr, EvaluatorFlags.ExpectingInstantiableType).type;
if (isTypeVar(entryType)) {
if (entryType.scopeId) {
isTypeParamListValid = false;
Expand Down Expand Up @@ -12147,7 +12164,10 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
let type: Type | undefined;

if (node.constType === KeywordType.None) {
type = (flags & EvaluatorFlags.ExpectingType) !== 0 ? NoneType.createType() : NoneType.createInstance();
type =
(flags & EvaluatorFlags.ExpectingInstantiableType) !== 0
? NoneType.createType()
: NoneType.createInstance();
} else if (
node.constType === KeywordType.True ||
node.constType === KeywordType.False ||
Expand Down Expand Up @@ -14720,7 +14740,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions

if (isDeclaredTypeAlias(node.leftExpression)) {
flags |=
EvaluatorFlags.ExpectingType |
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.ExpectingTypeAnnotation |
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.DisallowParamSpec |
Expand Down Expand Up @@ -15131,7 +15151,7 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions
const initSubclassArgs: FunctionArgument[] = [];
let metaclassNode: ExpressionNode | undefined;
let exprFlags =
EvaluatorFlags.ExpectingType |
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.AllowGenericClassType |
EvaluatorFlags.DisallowNakedGeneric |
EvaluatorFlags.DisallowTypeVarsWithScopeId |
Expand Down Expand Up @@ -19203,7 +19223,9 @@ export function createTypeEvaluator(importLookup: ImportLookup, evaluatorOptions

function getTypeOfExpressionExpectingType(node: ExpressionNode, options?: ExpectedTypeOptions): TypeResult {
let flags =
EvaluatorFlags.ExpectingType | EvaluatorFlags.EvaluateStringLiteralAsType | EvaluatorFlags.DisallowClassVar;
EvaluatorFlags.ExpectingInstantiableType |
EvaluatorFlags.EvaluateStringLiteralAsType |
EvaluatorFlags.DisallowClassVar;

if (!options?.allowTypeVarsWithoutScopeId) {
flags |= EvaluatorFlags.DisallowTypeVarsWithoutScopeId;
Expand Down
4 changes: 2 additions & 2 deletions packages/pyright-internal/src/analyzer/typeEvaluatorTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ export const enum EvaluatorFlags {
// A TypeVarTuple isn't allowed in this context.
DisallowTypeVarTuple = 1 << 6,

// Expression is expected to be a type (class) rather
// Expression is expected to be an instantiable type rather
// than an instance (object)
ExpectingType = 1 << 7,
ExpectingInstantiableType = 1 << 7,

// A type annotation restricts the types of expressions that are
// allowed. If this flag is set, illegal type expressions are
Expand Down

0 comments on commit 7ea11a1

Please sign in to comment.