Implemented lazy evaluation of inferred function return types.

This commit is contained in:
Eric Traut 2019-11-14 00:21:35 -08:00
parent 728fff47dd
commit c4e155cb5f
3 changed files with 106 additions and 58 deletions

View File

@ -1014,7 +1014,7 @@ export class Checker extends ParseTreeWalker {
} }
} }
} else { } else {
const inferredReturnType = functionType.inferredReturnType || UnknownType.create(); const inferredReturnType = this._evaluator.getFunctionInferredReturnType(functionType);
if (inferredReturnType.category === TypeCategory.Unknown) { if (inferredReturnType.category === TypeCategory.Unknown) {
this._evaluator.addDiagnostic( this._evaluator.addDiagnostic(
this._fileInfo.diagnosticSettings.reportUnknownParameterType, this._fileInfo.diagnosticSettings.reportUnknownParameterType,

View File

@ -56,10 +56,10 @@ import { addDefaultFunctionParameters, addTypeVarsToListIfUnique, applyExpectedT
canBeTruthy, ClassMember, ClassMemberLookupFlags, cloneTypeVarMap, containsUnknown, convertClassToObject, canBeTruthy, ClassMember, ClassMemberLookupFlags, cloneTypeVarMap, containsUnknown, convertClassToObject,
derivesFromClassRecursive, doForSubtypes, getConcreteTypeFromTypeVar, getDeclaredGeneratorReturnType, derivesFromClassRecursive, doForSubtypes, getConcreteTypeFromTypeVar, getDeclaredGeneratorReturnType,
getDeclaredGeneratorSendType, getMetaclass, getSpecializedTupleType, getTypeVarArgumentsRecursive, getDeclaredGeneratorSendType, getMetaclass, getSpecializedTupleType, getTypeVarArgumentsRecursive,
isEllipsisType, isOptionalType, lookUpClassMember, lookUpObjectMember, partiallySpecializeType, isEllipsisType, isNoReturnType, isOptionalType, lookUpClassMember, lookUpObjectMember,
printLiteralValue, removeFalsinessFromType, removeTruthinessFromType, partiallySpecializeType, printLiteralValue, removeFalsinessFromType,
requiresSpecialization, selfSpecializeClassType, specializeType, specializeTypeVarType, removeTruthinessFromType, requiresSpecialization, selfSpecializeClassType, specializeType,
stripFirstParameter, stripLiteralValue, transformTypeObjectToClass, TypedDictEntry } from './typeUtils'; specializeTypeVarType, stripFirstParameter, stripLiteralValue, transformTypeObjectToClass, TypedDictEntry } from './typeUtils';
interface TypeResult { interface TypeResult {
type: Type; type: Type;
@ -233,6 +233,7 @@ export interface TypeEvaluator {
getEffectiveTypeOfSymbol: (symbol: Symbol) => Type; getEffectiveTypeOfSymbol: (symbol: Symbol) => Type;
getFunctionDeclaredReturnType: (node: FunctionNode) => Type | undefined; getFunctionDeclaredReturnType: (node: FunctionNode) => Type | undefined;
getFunctionInferredReturnType: (type: FunctionType) => Type;
getBuiltInType: (node: ParseNode, name: string) => Type; getBuiltInType: (node: ParseNode, name: string) => Type;
getTypeOfMember: (member: ClassMember) => Type; getTypeOfMember: (member: ClassMember) => Type;
bindFunctionToClassOrObject: (baseType: ClassType | ObjectType | undefined, bindFunctionToClassOrObject: (baseType: ClassType | ObjectType | undefined,
@ -958,14 +959,14 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
type: classType type: classType
}); });
addDefaultFunctionParameters(newType); addDefaultFunctionParameters(newType);
FunctionType.setDeclaredReturnType(newType, ObjectType.create(classType)); newType.details.declaredReturnType = ObjectType.create(classType);
FunctionType.addParameter(initType, { FunctionType.addParameter(initType, {
category: ParameterCategory.Simple, category: ParameterCategory.Simple,
name: 'self', name: 'self',
type: ObjectType.create(classType) type: ObjectType.create(classType)
}); });
FunctionType.setDeclaredReturnType(initType, NoneType.create()); initType.details.declaredReturnType = NoneType.create();
// Maintain a list of all dataclass parameters (including // Maintain a list of all dataclass parameters (including
// those from inherited classes) plus a list of only those // those from inherited classes) plus a list of only those
@ -1071,7 +1072,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
type: classType type: classType
}); });
addDefaultFunctionParameters(newType); addDefaultFunctionParameters(newType);
FunctionType.setDeclaredReturnType(newType, ObjectType.create(classType)); newType.details.declaredReturnType = ObjectType.create(classType);
// Synthesize an __init__ method. // Synthesize an __init__ method.
const initType = FunctionType.create( const initType = FunctionType.create(
@ -1081,7 +1082,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
name: 'self', name: 'self',
type: ObjectType.create(classType) type: ObjectType.create(classType)
}); });
FunctionType.setDeclaredReturnType(initType, NoneType.create()); initType.details.declaredReturnType = NoneType.create();
// All parameters must be named, so insert an empty "*". // All parameters must be named, so insert an empty "*".
FunctionType.addParameter(initType, { FunctionType.addParameter(initType, {
@ -1743,7 +1744,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
if (memberType.category === TypeCategory.Function) { if (memberType.category === TypeCategory.Function) {
const methodType = bindFunctionToClassOrObject(objType, memberType) as FunctionType; const methodType = bindFunctionToClassOrObject(objType, memberType) as FunctionType;
return getEffectiveReturnType(methodType); return getFunctionEffectiveReturnType(methodType);
} }
return undefined; return undefined;
@ -1770,7 +1771,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
if (memberType.category === TypeCategory.Function) { if (memberType.category === TypeCategory.Function) {
const methodType = bindFunctionToClassOrObject( const methodType = bindFunctionToClassOrObject(
classType, memberType, true) as FunctionType; classType, memberType, true) as FunctionType;
return getEffectiveReturnType(methodType); return getFunctionEffectiveReturnType(methodType);
} }
return undefined; return undefined;
@ -1979,7 +1980,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
name: 'fn', name: 'fn',
type: UnknownType.create() type: UnknownType.create()
}); });
FunctionType.setDeclaredReturnType(decoratorType, baseType); decoratorType.details.declaredReturnType = baseType;
type = decoratorType; type = decoratorType;
} else { } else {
diag.addMessage(`Unknown property member`); diag.addMessage(`Unknown property member`);
@ -2179,7 +2180,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
const getMemberType = getTypeOfMember(getMember); const getMemberType = getTypeOfMember(getMember);
if (getMemberType.category === TypeCategory.Function) { if (getMemberType.category === TypeCategory.Function) {
if (usage.method === 'get') { if (usage.method === 'get') {
type = getEffectiveReturnType(getMemberType); type = getFunctionEffectiveReturnType(getMemberType);
} else { } else {
// The type isn't important for set or delete usage. // The type isn't important for set or delete usage.
// We just need to return some defined type. // We just need to return some defined type.
@ -2250,7 +2251,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
if (getAttribType && getAttribType.category === TypeCategory.Function) { if (getAttribType && getAttribType.category === TypeCategory.Function) {
return { return {
type: getEffectiveReturnType(getAttribType), type: getFunctionEffectiveReturnType(getAttribType),
isClassMember: false isClassMember: false
}; };
} }
@ -2259,7 +2260,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
'__getattr__', { method: 'get' }, MemberAccessFlags.SkipForMethodLookup); '__getattr__', { method: 'get' }, MemberAccessFlags.SkipForMethodLookup);
if (getAttrType && getAttrType.category === TypeCategory.Function) { if (getAttrType && getAttrType.category === TypeCategory.Function) {
return { return {
type: getEffectiveReturnType(getAttrType), type: getFunctionEffectiveReturnType(getAttrType),
isClassMember: false isClassMember: false
}; };
} }
@ -3449,7 +3450,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
return undefined; return undefined;
} }
return specializeType(getEffectiveReturnType(type), typeVarMap); return specializeType(getFunctionEffectiveReturnType(type), typeVarMap);
} }
function validateArgType(argParam: ValidateArgTypeParams, typeVarMap: TypeVarMap, function validateArgType(argParam: ValidateArgTypeParams, typeVarMap: TypeVarMap,
@ -3820,7 +3821,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
const constructorType = FunctionType.create( const constructorType = FunctionType.create(
FunctionTypeFlags.StaticMethod | FunctionTypeFlags.ConstructorMethod | FunctionTypeFlags.StaticMethod | FunctionTypeFlags.ConstructorMethod |
FunctionTypeFlags.SynthesizedMethod); FunctionTypeFlags.SynthesizedMethod);
FunctionType.setDeclaredReturnType(constructorType, ObjectType.create(classType)); constructorType.details.declaredReturnType = ObjectType.create(classType);
FunctionType.addParameter(constructorType, { FunctionType.addParameter(constructorType, {
category: ParameterCategory.Simple, category: ParameterCategory.Simple,
name: 'cls', name: 'cls',
@ -3975,27 +3976,27 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
FunctionTypeFlags.InstanceMethod | FunctionTypeFlags.SynthesizedMethod); FunctionTypeFlags.InstanceMethod | FunctionTypeFlags.SynthesizedMethod);
FunctionType.addParameter(initType, selfParameter); FunctionType.addParameter(initType, selfParameter);
addDefaultFunctionParameters(initType); addDefaultFunctionParameters(initType);
FunctionType.setDeclaredReturnType(initType, NoneType.create()); initType.details.declaredReturnType = NoneType.create();
classFields.set('__new__', Symbol.createWithType(SymbolFlags.ClassMember, constructorType)); classFields.set('__new__', Symbol.createWithType(SymbolFlags.ClassMember, constructorType));
classFields.set('__init__', Symbol.createWithType(SymbolFlags.ClassMember, initType)); classFields.set('__init__', Symbol.createWithType(SymbolFlags.ClassMember, initType));
const keysItemType = FunctionType.create(FunctionTypeFlags.SynthesizedMethod); const keysItemType = FunctionType.create(FunctionTypeFlags.SynthesizedMethod);
FunctionType.setDeclaredReturnType(keysItemType, getBuiltInObject(errorNode, 'list', keysItemType.details.declaredReturnType = getBuiltInObject(errorNode, 'list',
[getBuiltInObject(errorNode, 'str')])); [getBuiltInObject(errorNode, 'str')]);
classFields.set('keys', Symbol.createWithType(SymbolFlags.InstanceMember, keysItemType)); classFields.set('keys', Symbol.createWithType(SymbolFlags.InstanceMember, keysItemType));
classFields.set('items', Symbol.createWithType(SymbolFlags.InstanceMember, keysItemType)); classFields.set('items', Symbol.createWithType(SymbolFlags.InstanceMember, keysItemType));
const lenType = FunctionType.create( const lenType = FunctionType.create(
FunctionTypeFlags.InstanceMethod | FunctionTypeFlags.SynthesizedMethod); FunctionTypeFlags.InstanceMethod | FunctionTypeFlags.SynthesizedMethod);
FunctionType.setDeclaredReturnType(lenType, getBuiltInObject(errorNode, 'int')); lenType.details.declaredReturnType = getBuiltInObject(errorNode, 'int');
FunctionType.addParameter(lenType, selfParameter); FunctionType.addParameter(lenType, selfParameter);
classFields.set('__len__', Symbol.createWithType(SymbolFlags.ClassMember, lenType)); classFields.set('__len__', Symbol.createWithType(SymbolFlags.ClassMember, lenType));
if (addGenericGetAttribute) { if (addGenericGetAttribute) {
const getAttribType = FunctionType.create( const getAttribType = FunctionType.create(
FunctionTypeFlags.InstanceMethod | FunctionTypeFlags.SynthesizedMethod); FunctionTypeFlags.InstanceMethod | FunctionTypeFlags.SynthesizedMethod);
FunctionType.setDeclaredReturnType(getAttribType, AnyType.create()); getAttribType.details.declaredReturnType = AnyType.create();
FunctionType.addParameter(getAttribType, selfParameter); FunctionType.addParameter(getAttribType, selfParameter);
FunctionType.addParameter(getAttribType, { FunctionType.addParameter(getAttribType, {
category: ParameterCategory.Simple, category: ParameterCategory.Simple,
@ -4794,7 +4795,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
// present, should specify the return type. // present, should specify the return type.
function createCallableType(typeArgs?: TypeResult[]): FunctionType { function createCallableType(typeArgs?: TypeResult[]): FunctionType {
const functionType = FunctionType.create(FunctionTypeFlags.None); const functionType = FunctionType.create(FunctionTypeFlags.None);
FunctionType.setDeclaredReturnType(functionType, AnyType.create()); functionType.details.declaredReturnType = AnyType.create();
if (typeArgs && typeArgs.length > 0) { if (typeArgs && typeArgs.length > 0) {
if (typeArgs[0].typeList) { if (typeArgs[0].typeList) {
@ -4826,9 +4827,9 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
} else if (typeArgs[1].type.category === TypeCategory.Module) { } else if (typeArgs[1].type.category === TypeCategory.Module) {
addError(`Module not allowed in this context`, typeArgs[1].node); addError(`Module not allowed in this context`, typeArgs[1].node);
} }
FunctionType.setDeclaredReturnType(functionType, convertClassToObject(typeArgs[1].type)); functionType.details.declaredReturnType = convertClassToObject(typeArgs[1].type);
} else { } else {
FunctionType.setDeclaredReturnType(functionType, AnyType.create()); functionType.details.declaredReturnType = AnyType.create();
} }
if (typeArgs && typeArgs.length > 2) { if (typeArgs && typeArgs.length > 2) {
@ -5573,7 +5574,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
// validated against this type. // validated against this type.
if (node.returnTypeAnnotation) { if (node.returnTypeAnnotation) {
const returnType = getTypeOfAnnotation(node.returnTypeAnnotation); const returnType = getTypeOfAnnotation(node.returnTypeAnnotation);
FunctionType.setDeclaredReturnType(functionType, returnType); functionType.details.declaredReturnType = returnType;
} }
// Mark the class as abstract if it contains at least one abstract method. // Mark the class as abstract if it contains at least one abstract method.
@ -5688,14 +5689,9 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
} }
}); });
// Infer the return type based on the body of the function.
if (!node.returnTypeAnnotation) {
functionType.inferredReturnType = inferFunctionReturnType(
node, FunctionType.isAbstractMethod(functionType));
}
// If it's an async function, wrap the return type in an Awaitable or Generator. // If it's an async function, wrap the return type in an Awaitable or Generator.
const preDecoratedType = node.isAsync ? createAwaitableFunction(node, functionType) : functionType; const preDecoratedType = node.isAsync ?
createAwaitableFunction(node, functionType) : functionType;
// Apply all of the decorators in reverse order. // Apply all of the decorators in reverse order.
decoratedType = preDecoratedType; decoratedType = preDecoratedType;
@ -5924,12 +5920,24 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
return type; return type;
} }
function createAwaitableFunction(node: ParseNode, functionType: FunctionType): FunctionType { function createAwaitableFunction(node: FunctionNode, functionType: FunctionType): FunctionType {
const returnType = functionType.details.declaredReturnType || functionType.inferredReturnType; // Clone the original function and replace its return type with an
if (!returnType) { // Awaitable[<returnType>].
return functionType; const awaitableFunctionType = FunctionType.clone(functionType);
if (functionType.details.declaredReturnType) {
awaitableFunctionType.details.declaredReturnType = createAwaitableReturnType(
node, functionType.details.declaredReturnType);
} }
// Note that the inferred type, once lazily computed, needs to wrap the
// resulting type in an awaitable.
awaitableFunctionType.details.flags |= FunctionTypeFlags.WrapReturnTypeInAwait;
return awaitableFunctionType;
}
function createAwaitableReturnType(node: ParseNode, returnType: Type): Type {
let awaitableReturnType: Type | undefined; let awaitableReturnType: Type | undefined;
if (returnType.category === TypeCategory.Object) { if (returnType.category === TypeCategory.Object) {
@ -5968,12 +5976,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
} }
} }
// Clone the original function and replace its return type with an return awaitableReturnType;
// Awaitable[<returnType>].
const awaitableFunctionType = FunctionType.clone(functionType);
FunctionType.setDeclaredReturnType(awaitableFunctionType, awaitableReturnType);
return awaitableFunctionType;
} }
function inferFunctionReturnType(node: FunctionNode, isAbstract: boolean): Type | undefined { function inferFunctionReturnType(node: FunctionNode, isAbstract: boolean): Type | undefined {
@ -6211,7 +6214,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
if (memberType) { if (memberType) {
let memberReturnType: Type; let memberReturnType: Type;
if (memberType.category === TypeCategory.Function) { if (memberType.category === TypeCategory.Function) {
memberReturnType = getEffectiveReturnType(memberType); memberReturnType = getFunctionEffectiveReturnType(memberType);
} else { } else {
memberReturnType = UnknownType.create(); memberReturnType = UnknownType.create();
} }
@ -7235,6 +7238,13 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
function useSpeculativeMode(callback: () => void) { function useSpeculativeMode(callback: () => void) {
const prevSpeculativeMode = isSpeculativeMode; const prevSpeculativeMode = isSpeculativeMode;
isSpeculativeMode = true; isSpeculativeMode = true;
callback();
isSpeculativeMode = prevSpeculativeMode;
}
function disableSpeculativeMode(callback: () => void) {
const prevSpeculativeMode = isSpeculativeMode;
isSpeculativeMode = false;
callback(); callback();
@ -7639,13 +7649,49 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
return type; return type;
} }
function getEffectiveReturnType(type: FunctionType) { function getFunctionEffectiveReturnType(type: FunctionType) {
const specializedReturnType = FunctionType.getSpecializedReturnType(type); const specializedReturnType = FunctionType.getSpecializedReturnType(type);
if (specializedReturnType) { if (specializedReturnType) {
return specializedReturnType; return specializedReturnType;
} }
return type.inferredReturnType || UnknownType.create(); return getFunctionInferredReturnType(type);
}
function getFunctionInferredReturnType(type: FunctionType) {
// If the return type has already been lazily evaluated,
// don't bother computing it again.
if (type.inferredReturnType) {
return type.inferredReturnType;
}
let returnType: Type | undefined;
if (type.details.declaration) {
const functionNode = type.details.declaration.node;
// We should never get here if there is a type annotation.
assert(!functionNode.returnTypeAnnotation);
// Temporarily disable speculative mode while we
// lazily evaluate the return type.
disableSpeculativeMode(() => {
returnType = inferFunctionReturnType(functionNode, FunctionType.isAbstractMethod(type));
});
// Do we need to wrap this in an awaitable?
if (returnType && FunctionType.isWrapReturnTypeInAwait(type) && !isNoReturnType(returnType)) {
returnType = createAwaitableReturnType(functionNode, returnType);
}
}
if (!returnType) {
returnType = UnknownType.create();
}
// Cache the type for next time.
type.inferredReturnType = returnType;
return returnType;
} }
function getFunctionDeclaredReturnType(node: FunctionNode): Type | undefined { function getFunctionDeclaredReturnType(node: FunctionNode): Type | undefined {
@ -8239,7 +8285,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
const constructorFunction = FunctionType.create( const constructorFunction = FunctionType.create(
FunctionTypeFlags.StaticMethod | FunctionTypeFlags.ConstructorMethod | FunctionTypeFlags.StaticMethod | FunctionTypeFlags.ConstructorMethod |
FunctionTypeFlags.SynthesizedMethod); FunctionTypeFlags.SynthesizedMethod);
FunctionType.setDeclaredReturnType(constructorFunction, ObjectType.create(srcType)); constructorFunction.details.declaredReturnType = ObjectType.create(srcType);
const newMemberInfo = lookUpClassMember(srcType, '__new__', importLookup, const newMemberInfo = lookUpClassMember(srcType, '__new__', importLookup,
ClassMemberLookupFlags.SkipInstanceVariables | ClassMemberLookupFlags.SkipObjectBaseClass); ClassMemberLookupFlags.SkipInstanceVariables | ClassMemberLookupFlags.SkipObjectBaseClass);
@ -8439,8 +8485,8 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
} }
// Match the return parameter. // Match the return parameter.
const srcReturnType = getEffectiveReturnType(srcType); const srcReturnType = getFunctionEffectiveReturnType(srcType);
const destReturnType = getEffectiveReturnType(destType); const destReturnType = getFunctionEffectiveReturnType(destType);
if (!canAssignType(destReturnType, srcReturnType, diag.createAddendum(), if (!canAssignType(destReturnType, srcReturnType, diag.createAddendum(),
typeVarMap, CanAssignFlags.Default, recursionCount + 1)) { typeVarMap, CanAssignFlags.Default, recursionCount + 1)) {
@ -8519,8 +8565,8 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
} }
} }
const baseReturnType = getEffectiveReturnType(baseMethod); const baseReturnType = getFunctionEffectiveReturnType(baseMethod);
const overrideReturnType = getEffectiveReturnType(overrideMethod); const overrideReturnType = getFunctionEffectiveReturnType(overrideMethod);
if (!canAssignType(baseReturnType, overrideReturnType, diag.createAddendum())) { if (!canAssignType(baseReturnType, overrideReturnType, diag.createAddendum())) {
diag.addMessage(`Return type mismatch: ` + diag.addMessage(`Return type mismatch: ` +
`base method returns type '${printType(baseReturnType)}, ` + `base method returns type '${printType(baseReturnType)}, ` +
@ -8839,7 +8885,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
return paramString; return paramString;
}); });
const returnType = getEffectiveReturnType(type); const returnType = getFunctionEffectiveReturnType(type);
const returnTypeString = recursionCount < maxTypeRecursionCount ? const returnTypeString = recursionCount < maxTypeRecursionCount ?
printType(returnType, recursionCount + 1) : ''; printType(returnType, recursionCount + 1) : '';
return [paramTypeStrings, returnTypeString]; return [paramTypeStrings, returnTypeString];
@ -8888,7 +8934,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
case TypeCategory.Property: { case TypeCategory.Property: {
const propertyType = type; const propertyType = type;
const returnType = getEffectiveReturnType(propertyType.getter); const returnType = getFunctionEffectiveReturnType(propertyType.getter);
const returnTypeString = recursionCount < maxTypeRecursionCount ? const returnTypeString = recursionCount < maxTypeRecursionCount ?
printType(returnType, recursionCount + 1) : ''; printType(returnType, recursionCount + 1) : '';
return returnTypeString; return returnTypeString;
@ -8963,6 +9009,7 @@ export function createTypeEvaluator(importLookup: ImportLookup): TypeEvaluator {
resolveAliasDeclaration, resolveAliasDeclaration,
getEffectiveTypeOfSymbol, getEffectiveTypeOfSymbol,
getFunctionDeclaredReturnType, getFunctionDeclaredReturnType,
getFunctionInferredReturnType,
getBuiltInType, getBuiltInType,
getTypeOfMember, getTypeOfMember,
bindFunctionToClassOrObject, bindFunctionToClassOrObject,

View File

@ -515,7 +515,8 @@ export const enum FunctionTypeFlags {
DisableDefaultChecks = 1 << 6, DisableDefaultChecks = 1 << 6,
SynthesizedMethod = 1 << 7, SynthesizedMethod = 1 << 7,
Overloaded = 1 << 8, Overloaded = 1 << 8,
Async = 1 << 9 Async = 1 << 9,
WrapReturnTypeInAwait = 1 << 10
} }
interface FunctionDetails { interface FunctionDetails {
@ -646,6 +647,10 @@ export namespace FunctionType {
return (type.details.flags & FunctionTypeFlags.Async) !== 0; return (type.details.flags & FunctionTypeFlags.Async) !== 0;
} }
export function isWrapReturnTypeInAwait(type: FunctionType) {
return (type.details.flags & FunctionTypeFlags.WrapReturnTypeInAwait) !== 0;
}
export function getEffectiveParameterType(type: FunctionType, index: number): Type { export function getEffectiveParameterType(type: FunctionType, index: number): Type {
assert(index < type.details.parameters.length); assert(index < type.details.parameters.length);
if (type.specializedTypes) { if (type.specializedTypes) {
@ -663,10 +668,6 @@ export namespace FunctionType {
return type.specializedTypes && type.specializedTypes.returnType ? return type.specializedTypes && type.specializedTypes.returnType ?
type.specializedTypes.returnType : type.details.declaredReturnType; type.specializedTypes.returnType : type.details.declaredReturnType;
} }
export function setDeclaredReturnType(type: FunctionType, returnType?: Type) {
type.details.declaredReturnType = returnType;
}
} }
export interface OverloadedFunctionType extends TypeBase { export interface OverloadedFunctionType extends TypeBase {