Skip to content

Commit 74536cc

Browse files
committed
Report circular type inference errors with -noImplicitAny
1 parent b61c722 commit 74536cc

File tree

8 files changed

+264
-6
lines changed

8 files changed

+264
-6
lines changed

src/compiler/checker.ts

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ module ts {
413413
}
414414
}
415415

416-
function getFullyQualifiedName(symbol: Symbol) {
416+
function getFullyQualifiedName(symbol: Symbol): string {
417417
return symbol.parent ? getFullyQualifiedName(symbol.parent) + "." + symbolToString(symbol) : symbolToString(symbol);
418418
}
419419

@@ -1420,6 +1420,9 @@ module ts {
14201420
}
14211421
else if (links.type === resolvingType) {
14221422
links.type = anyType;
1423+
if (compilerOptions.noImplicitAny) {
1424+
error(symbol.valueDeclaration, Diagnostics._0_implicitly_has_type_any_because_type_inference_encountered_a_circularity, symbolToString(symbol));
1425+
}
14231426
}
14241427
return links.type;
14251428
}
@@ -1475,7 +1478,7 @@ module ts {
14751478
// Otherwise, fall back to 'any'.
14761479
else {
14771480
if (compilerOptions.noImplicitAny) {
1478-
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbol.name);
1481+
error(setter, Diagnostics.Property_0_implicitly_has_type_any_because_its_set_accessor_lacks_a_type_annotation, symbolToString(symbol));
14791482
}
14801483

14811484
type = anyType;
@@ -1489,6 +1492,10 @@ module ts {
14891492
}
14901493
else if (links.type === resolvingType) {
14911494
links.type = anyType;
1495+
if (compilerOptions.noImplicitAny) {
1496+
var getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
1497+
error(getter, Diagnostics._0_implicitly_has_type_any_because_type_inference_encountered_a_circularity, symbolToString(symbol));
1498+
}
14921499
}
14931500
}
14941501

@@ -1552,7 +1559,7 @@ module ts {
15521559

15531560
function hasBaseType(type: InterfaceType, checkBase: InterfaceType) {
15541561
return check(type);
1555-
function check(type: InterfaceType) {
1562+
function check(type: InterfaceType): boolean {
15561563
var target = <InterfaceType>getTargetType(type);
15571564
return target === checkBase || forEach(target.baseTypes, check);
15581565
}
@@ -2036,6 +2043,15 @@ module ts {
20362043
}
20372044
else if (signature.resolvedReturnType === resolvingType) {
20382045
signature.resolvedReturnType = anyType;
2046+
if (compilerOptions.noImplicitAny) {
2047+
var declaration = <Declaration>signature.declaration;
2048+
if (declaration.name) {
2049+
error(declaration.name, Diagnostics._0_implicitly_has_return_type_any_because_type_inference_encountered_a_circularity, identifierToString(declaration.name));
2050+
}
2051+
else {
2052+
error(declaration, Diagnostics.Function_implicitly_has_return_type_any_because_type_inference_encountered_a_circularity);
2053+
}
2054+
}
20392055
}
20402056
return signature.resolvedReturnType;
20412057
}
@@ -6587,7 +6603,7 @@ module ts {
65876603
// Language service support
65886604

65896605
function getNodeAtPosition(sourceFile: SourceFile, position: number): Node {
6590-
function findChildAtPosition(parent: Node) {
6606+
function findChildAtPosition(parent: Node): Node {
65916607
var child = forEachChild(parent, node => {
65926608
if (position >= node.pos && position <= node.end && position >= getTokenPosOfNode(node)) {
65936609
return findChildAtPosition(node);

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,9 @@ module ts {
390390
Object_literal_s_property_0_implicitly_has_an_1_type: { code: 7018, category: DiagnosticCategory.Error, key: "Object literal's property '{0}' implicitly has an '{1}' type." },
391391
Rest_parameter_0_implicitly_has_an_any_type: { code: 7019, category: DiagnosticCategory.Error, key: "Rest parameter '{0}' implicitly has an 'any[]' type." },
392392
Call_signature_which_lacks_return_type_annotation_implicitly_has_an_any_return_type: { code: 7020, category: DiagnosticCategory.Error, key: "Call signature, which lacks return-type annotation, implicitly has an 'any' return type." },
393+
_0_implicitly_has_type_any_because_type_inference_encountered_a_circularity: { code: 7021, category: DiagnosticCategory.Error, key: "'{0}' implicitly has type 'any' because type inference encountered a circularity." },
394+
_0_implicitly_has_return_type_any_because_type_inference_encountered_a_circularity: { code: 7022, category: DiagnosticCategory.Error, key: "'{0}' implicitly has return type 'any' because type inference encountered a circularity." },
395+
Function_implicitly_has_return_type_any_because_type_inference_encountered_a_circularity: { code: 7023, category: DiagnosticCategory.Error, key: "Function implicitly has return type 'any' because type inference encountered a circularity." },
393396
You_cannot_rename_this_element: { code: 8000, category: DiagnosticCategory.Error, key: "You cannot rename this element." },
394397
};
395398
}

src/compiler/diagnosticMessages.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1557,6 +1557,18 @@
15571557
"category": "Error",
15581558
"code": 7020
15591559
},
1560+
"'{0}' implicitly has type 'any' because type inference encountered a circularity.": {
1561+
"category": "Error",
1562+
"code": 7021
1563+
},
1564+
"'{0}' implicitly has return type 'any' because type inference encountered a circularity.": {
1565+
"category": "Error",
1566+
"code": 7022
1567+
},
1568+
"Function implicitly has return type 'any' because type inference encountered a circularity.": {
1569+
"category": "Error",
1570+
"code": 7023
1571+
},
15601572
"You cannot rename this element.": {
15611573
"category": "Error",
15621574
"code": 8000

src/compiler/emitter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1973,7 +1973,7 @@ module ts {
19731973
}
19741974
}
19751975

1976-
function emitNode(node: Node) {
1976+
function emitNode(node: Node): void {
19771977
if (!node) {
19781978
return;
19791979
}

src/compiler/parser.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3533,7 +3533,7 @@ module ts {
35333533
return finishNode(node);
35343534
}
35353535

3536-
function isDeclaration() {
3536+
function isDeclaration(): boolean {
35373537
switch (token) {
35383538
case SyntaxKind.VarKeyword:
35393539
case SyntaxKind.FunctionKeyword:
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
==== tests/cases/compiler/implicitAnyFromCircularInference.ts (9 errors) ====
2+
3+
// Error expected
4+
var a: typeof a;
5+
~
6+
!!! 'a' implicitly has type 'any' because type inference encountered a circularity.
7+
8+
// Error expected on b or c
9+
var b: typeof c;
10+
var c: typeof b;
11+
~
12+
!!! 'c' implicitly has type 'any' because type inference encountered a circularity.
13+
14+
// Error expected
15+
var d: Array<typeof d>;
16+
~
17+
!!! 'd' implicitly has type 'any' because type inference encountered a circularity.
18+
19+
function f() { return f; }
20+
21+
// Error expected
22+
function g() { return g(); }
23+
~
24+
!!! 'g' implicitly has return type 'any' because type inference encountered a circularity.
25+
26+
// Error expected
27+
var f1 = function () {
28+
~~~~~~~~~~~~~
29+
return f1();
30+
~~~~~~~~~~~~~~~~
31+
};
32+
~
33+
!!! Function implicitly has return type 'any' because type inference encountered a circularity.
34+
35+
// Error expected
36+
var f2 = () => f2();
37+
~~~~~~~~~~
38+
!!! Function implicitly has return type 'any' because type inference encountered a circularity.
39+
40+
// Error expected
41+
function h() {
42+
~
43+
!!! 'h' implicitly has return type 'any' because type inference encountered a circularity.
44+
return foo();
45+
function foo() {
46+
return h() || "hello";
47+
}
48+
}
49+
50+
interface A {
51+
s: string;
52+
}
53+
54+
function foo(x: A): string { return "abc"; }
55+
56+
class C {
57+
// Error expected
58+
s = foo(this);
59+
~~~~~~~~~~~~~~
60+
!!! 's' implicitly has type 'any' because type inference encountered a circularity.
61+
}
62+
63+
class D {
64+
// Error expected
65+
get x() {
66+
~~~~~~~~~
67+
return this.x;
68+
~~~~~~~~~~~~~~~~~~~~~~
69+
}
70+
~~~~~
71+
!!! 'x' implicitly has type 'any' because type inference encountered a circularity.
72+
}
73+
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//// [implicitAnyFromCircularInference.ts]
2+
3+
// Error expected
4+
var a: typeof a;
5+
6+
// Error expected on b or c
7+
var b: typeof c;
8+
var c: typeof b;
9+
10+
// Error expected
11+
var d: Array<typeof d>;
12+
13+
function f() { return f; }
14+
15+
// Error expected
16+
function g() { return g(); }
17+
18+
// Error expected
19+
var f1 = function () {
20+
return f1();
21+
};
22+
23+
// Error expected
24+
var f2 = () => f2();
25+
26+
// Error expected
27+
function h() {
28+
return foo();
29+
function foo() {
30+
return h() || "hello";
31+
}
32+
}
33+
34+
interface A {
35+
s: string;
36+
}
37+
38+
function foo(x: A): string { return "abc"; }
39+
40+
class C {
41+
// Error expected
42+
s = foo(this);
43+
}
44+
45+
class D {
46+
// Error expected
47+
get x() {
48+
return this.x;
49+
}
50+
}
51+
52+
53+
//// [implicitAnyFromCircularInference.js]
54+
// Error expected
55+
var a;
56+
// Error expected on b or c
57+
var b;
58+
var c;
59+
// Error expected
60+
var d;
61+
function f() {
62+
return f;
63+
}
64+
// Error expected
65+
function g() {
66+
return g();
67+
}
68+
// Error expected
69+
var f1 = function () {
70+
return f1();
71+
};
72+
// Error expected
73+
var f2 = function () { return f2(); };
74+
// Error expected
75+
function h() {
76+
return foo();
77+
function foo() {
78+
return h() || "hello";
79+
}
80+
}
81+
function foo(x) {
82+
return "abc";
83+
}
84+
var C = (function () {
85+
function C() {
86+
// Error expected
87+
this.s = foo(this);
88+
}
89+
return C;
90+
})();
91+
var D = (function () {
92+
function D() {
93+
}
94+
Object.defineProperty(D.prototype, "x", {
95+
// Error expected
96+
get: function () {
97+
return this.x;
98+
},
99+
enumerable: true,
100+
configurable: true
101+
});
102+
return D;
103+
})();
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
// @noimplicitany: true
2+
// @target: es5
3+
4+
// Error expected
5+
var a: typeof a;
6+
7+
// Error expected on b or c
8+
var b: typeof c;
9+
var c: typeof b;
10+
11+
// Error expected
12+
var d: Array<typeof d>;
13+
14+
function f() { return f; }
15+
16+
// Error expected
17+
function g() { return g(); }
18+
19+
// Error expected
20+
var f1 = function () {
21+
return f1();
22+
};
23+
24+
// Error expected
25+
var f2 = () => f2();
26+
27+
// Error expected
28+
function h() {
29+
return foo();
30+
function foo() {
31+
return h() || "hello";
32+
}
33+
}
34+
35+
interface A {
36+
s: string;
37+
}
38+
39+
function foo(x: A): string { return "abc"; }
40+
41+
class C {
42+
// Error expected
43+
s = foo(this);
44+
}
45+
46+
class D {
47+
// Error expected
48+
get x() {
49+
return this.x;
50+
}
51+
}

0 commit comments

Comments
 (0)