diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index c7576523e14..3d13ba63fab 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -8975,7 +8975,7 @@ namespace ts { function getTypeWithDefault(type: Type, defaultExpression: Expression) { if (defaultExpression) { - const defaultType = checkExpression(defaultExpression); + const defaultType = getTypeOfExpression(defaultExpression); return getUnionType([getTypeWithFacts(type, TypeFacts.NEUndefined), defaultType]); } return type; @@ -9002,7 +9002,7 @@ namespace ts { function getAssignedTypeOfBinaryExpression(node: BinaryExpression): Type { return node.parent.kind === SyntaxKind.ArrayLiteralExpression || node.parent.kind === SyntaxKind.PropertyAssignment ? getTypeWithDefault(getAssignedType(node), node.right) : - checkExpression(node.right); + getTypeOfExpression(node.right); } function getAssignedTypeOfArrayLiteralElement(node: ArrayLiteralExpression, element: Expression): Type { @@ -9060,7 +9060,7 @@ namespace ts { // from its initializer, we'll already have cached the type. Otherwise we compute it now // without caching such that transient types are reflected. const links = getNodeLinks(node); - return links.resolvedType || checkExpression(node); + return links.resolvedType || getTypeOfExpression(node); } function getInitialTypeOfVariableDeclaration(node: VariableDeclaration) { @@ -9120,7 +9120,7 @@ namespace ts { function getTypeOfSwitchClause(clause: CaseClause | DefaultClause) { if (clause.kind === SyntaxKind.CaseClause) { - const caseType = getRegularTypeOfLiteralType(checkExpression((clause).expression)); + const caseType = getRegularTypeOfLiteralType(getTypeOfExpression((clause).expression)); return isUnitType(caseType) ? caseType : undefined; } return neverType; @@ -9225,7 +9225,7 @@ namespace ts { // we defer subtype reduction until the evolving array type is finalized into a manifest // array type. function addEvolvingArrayElementType(evolvingArrayType: EvolvingArrayType, node: Expression): EvolvingArrayType { - const elementType = getBaseTypeOfLiteralType(checkExpression(node)); + const elementType = getBaseTypeOfLiteralType(getTypeOfExpression(node)); return isTypeSubsetOf(elementType, evolvingArrayType.elementType) ? evolvingArrayType : getEvolvingArrayType(getUnionType([evolvingArrayType.elementType, elementType])); } @@ -9286,7 +9286,7 @@ namespace ts { (parent.parent).operatorToken.kind === SyntaxKind.EqualsToken && (parent.parent).left === parent && !isAssignmentTarget(parent.parent) && - isTypeAnyOrAllConstituentTypesHaveKind(checkExpression((parent).argumentExpression), TypeFlags.NumberLike | TypeFlags.Undefined); + isTypeAnyOrAllConstituentTypesHaveKind(getTypeOfExpression((parent).argumentExpression), TypeFlags.NumberLike | TypeFlags.Undefined); return isLengthPushOrUnshift || isElementAssignment; } @@ -9448,7 +9448,7 @@ namespace ts { } } else { - const indexType = checkExpression(((node).left).argumentExpression); + const indexType = getTypeOfExpression(((node).left).argumentExpression); if (isTypeAnyOrAllConstituentTypesHaveKind(indexType, TypeFlags.NumberLike | TypeFlags.Undefined)) { evolvedType = addEvolvingArrayElementType(evolvedType, (node).right); } @@ -9673,7 +9673,7 @@ namespace ts { if (operator === SyntaxKind.ExclamationEqualsToken || operator === SyntaxKind.ExclamationEqualsEqualsToken) { assumeTrue = !assumeTrue; } - const valueType = checkExpression(value); + const valueType = getTypeOfExpression(value); if (valueType.flags & TypeFlags.Nullable) { if (!strictNullChecks) { return type; @@ -9760,7 +9760,7 @@ namespace ts { } // Check that right operand is a function type with a prototype property - const rightType = checkExpression(expr.right); + const rightType = getTypeOfExpression(expr.right); if (!isTypeSubtypeOf(rightType, globalFunctionType)) { return type; } @@ -9901,7 +9901,7 @@ namespace ts { location = location.parent; } if (isPartOfExpression(location) && !isAssignmentTarget(location)) { - const type = checkExpression(location); + const type = getTypeOfExpression(location); if (getExportSymbolOfValueSymbolIfExported(getNodeLinks(location).resolvedSymbol) === symbol) { return type; } @@ -10769,7 +10769,7 @@ namespace ts { // In an assignment expression, the right operand is contextually typed by the type of the left operand. if (node === binaryExpression.right) { - return checkExpression(binaryExpression.left); + return getTypeOfExpression(binaryExpression.left); } } else if (operator === SyntaxKind.BarBarToken) { @@ -10777,7 +10777,7 @@ namespace ts { // expression has no contextual type, the right operand is contextually typed by the type of the left operand. let type = getContextualType(binaryExpression); if (!type && node === binaryExpression.right) { - type = checkExpression(binaryExpression.left); + type = getTypeOfExpression(binaryExpression.left); } return type; } @@ -12148,7 +12148,7 @@ namespace ts { if (node.kind === SyntaxKind.ForInStatement && child === (node).statement && getForInVariableSymbol(node) === symbol && - hasNumericPropertyNames(checkExpression((node).expression))) { + hasNumericPropertyNames(getTypeOfExpression((node).expression))) { return true; } child = node; @@ -13784,7 +13784,7 @@ namespace ts { if (!node.possiblyExhaustive) { return false; } - const type = checkExpression(node.expression); + const type = getTypeOfExpression(node.expression); if (!isLiteralType(type)) { return false; } @@ -14876,6 +14876,24 @@ namespace ts { return type; } + // Returns the type of an expression. Unlike checkExpression, this function is simply concerned + // with computing the type and may not fully check all contained sub-expressions for errors. + function getTypeOfExpression(node: Expression) { + // Optimize for the common case of a call to a function with a single non-generic call + // signature where we can just fetch the return type without checking the arguments. + if (node.kind === SyntaxKind.CallExpression && (node).expression.kind !== SyntaxKind.SuperKeyword) { + const funcType = checkNonNullExpression((node).expression); + const signature = getSingleCallSignature(funcType); + if (signature && !signature.typeParameters) { + return getReturnTypeOfSignature(signature); + } + } + // Otherwise simply call checkExpression. Ideally, the entire family of checkXXX functions + // should have a parameter that indicates whether full error checking is required such that + // we can perform the optimizations locally. + return checkExpression(node); + } + // Checks an expression and returns its type. The contextualMapper parameter serves two purposes: When // contextualMapper is not undefined and not equal to the identityMapper function object it indicates that the // expression is being inferentially typed (section 4.15.2 in spec) and provides the type mapper to use in @@ -18258,7 +18276,7 @@ namespace ts { } } - enumType = checkExpression(expression); + enumType = getTypeOfExpression(expression); // allow references to constant members of other enums if (!(enumType.symbol && (enumType.symbol.flags & SymbolFlags.Enum))) { return undefined; @@ -19428,7 +19446,7 @@ namespace ts { // fallthrough case SyntaxKind.SuperKeyword: - const type = isPartOfExpression(node) ? checkExpression(node) : getTypeFromTypeNode(node); + const type = isPartOfExpression(node) ? getTypeOfExpression(node) : getTypeFromTypeNode(node); return type.symbol; case SyntaxKind.ThisType: @@ -19458,7 +19476,7 @@ namespace ts { case SyntaxKind.NumericLiteral: // index access if (node.parent.kind === SyntaxKind.ElementAccessExpression && (node.parent).argumentExpression === node) { - const objectType = checkExpression((node.parent).expression); + const objectType = getTypeOfExpression((node.parent).expression); if (objectType === unknownType) return undefined; const apparentType = getApparentType(objectType); if (apparentType === unknownType) return undefined; @@ -19497,7 +19515,7 @@ namespace ts { } if (isPartOfExpression(node)) { - return getTypeOfExpression(node); + return getRegularTypeOfExpression(node); } if (isExpressionWithTypeArgumentsInClassExtendsClause(node)) { @@ -19559,7 +19577,7 @@ namespace ts { // If this is from "for" initializer // for ({a } = elems[0];.....) { } if (expr.parent.kind === SyntaxKind.BinaryExpression) { - const iteratedType = checkExpression((expr.parent).right); + const iteratedType = getTypeOfExpression((expr.parent).right); return checkDestructuringAssignment(expr, iteratedType || unknownType); } // If this is from nested object binding pattern @@ -19589,11 +19607,11 @@ namespace ts { return typeOfObjectLiteral && getPropertyOfType(typeOfObjectLiteral, location.text); } - function getTypeOfExpression(expr: Expression): Type { + function getRegularTypeOfExpression(expr: Expression): Type { if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) { expr = expr.parent; } - return getRegularTypeOfLiteralType(checkExpression(expr)); + return getRegularTypeOfLiteralType(getTypeOfExpression(expr)); } /** @@ -20020,7 +20038,7 @@ namespace ts { } function writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) { - const type = getWidenedType(getTypeOfExpression(expr)); + const type = getWidenedType(getRegularTypeOfExpression(expr)); getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags); } diff --git a/tests/baselines/reference/ambientRequireFunction.types b/tests/baselines/reference/ambientRequireFunction.types index 7b01a59268f..e0341d97ec3 100644 --- a/tests/baselines/reference/ambientRequireFunction.types +++ b/tests/baselines/reference/ambientRequireFunction.types @@ -3,7 +3,7 @@ const fs = require("fs"); >fs : typeof "fs" ->require("fs") : typeof "fs" +>require("fs") : any >require : (moduleName: string) => any >"fs" : "fs" diff --git a/tests/baselines/reference/controlFlowSelfReferentialLoop.errors.txt b/tests/baselines/reference/controlFlowSelfReferentialLoop.errors.txt new file mode 100644 index 00000000000..deef6403761 --- /dev/null +++ b/tests/baselines/reference/controlFlowSelfReferentialLoop.errors.txt @@ -0,0 +1,188 @@ +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(6,17): error TS7006: Parameter 'a' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(6,19): error TS7006: Parameter 'b' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(6,21): error TS7006: Parameter 'c' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(6,23): error TS7006: Parameter 'd' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(6,25): error TS7006: Parameter 'x' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(6,27): error TS7006: Parameter 's' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(6,29): error TS7006: Parameter 'ac' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(10,17): error TS7006: Parameter 'a' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(10,19): error TS7006: Parameter 'b' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(10,21): error TS7006: Parameter 'c' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(10,23): error TS7006: Parameter 'd' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(10,25): error TS7006: Parameter 'x' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(10,27): error TS7006: Parameter 's' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(10,29): error TS7006: Parameter 'ac' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(14,17): error TS7006: Parameter 'a' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(14,19): error TS7006: Parameter 'b' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(14,21): error TS7006: Parameter 'c' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(14,23): error TS7006: Parameter 'd' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(14,25): error TS7006: Parameter 'x' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(14,27): error TS7006: Parameter 's' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(14,29): error TS7006: Parameter 'ac' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(18,17): error TS7006: Parameter 'a' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(18,19): error TS7006: Parameter 'b' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(18,21): error TS7006: Parameter 'c' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(18,23): error TS7006: Parameter 'd' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(18,25): error TS7006: Parameter 'x' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(18,27): error TS7006: Parameter 's' implicitly has an 'any' type. +tests/cases/compiler/controlFlowSelfReferentialLoop.ts(18,29): error TS7006: Parameter 'ac' implicitly has an 'any' type. + + +==== tests/cases/compiler/controlFlowSelfReferentialLoop.ts (28 errors) ==== + + // Repro from #12319 + + function md5(string:string): void { + + function FF(a,b,c,d,x,s,ac) { + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'b' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'c' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'd' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'x' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 's' implicitly has an 'any' type. + ~~ +!!! error TS7006: Parameter 'ac' implicitly has an 'any' type. + return 0; + }; + + function GG(a,b,c,d,x,s,ac) { + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'b' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'c' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'd' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'x' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 's' implicitly has an 'any' type. + ~~ +!!! error TS7006: Parameter 'ac' implicitly has an 'any' type. + return 0; + }; + + function HH(a,b,c,d,x,s,ac) { + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'b' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'c' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'd' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'x' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 's' implicitly has an 'any' type. + ~~ +!!! error TS7006: Parameter 'ac' implicitly has an 'any' type. + return 0; + }; + + function II(a,b,c,d,x,s,ac) { + ~ +!!! error TS7006: Parameter 'a' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'b' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'c' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'd' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 'x' implicitly has an 'any' type. + ~ +!!! error TS7006: Parameter 's' implicitly has an 'any' type. + ~~ +!!! error TS7006: Parameter 'ac' implicitly has an 'any' type. + return 0; + }; + + var x=Array(); + var k,AA,BB,CC,DD,a,b,c,d; + var S11=7, S12=12, S13=17, S14=22; + var S21=5, S22=9 , S23=14, S24=20; + var S31=4, S32=11, S33=16, S34=23; + var S41=6, S42=10, S43=15, S44=21; + + x = [1]; + + a = 0x67452301; b = 0xEFCDAB89; c = 0x98BADCFE; d = 0x10325476; + + for (k=0;k