Skip to content

Commit ac74295

Browse files
author
Andy Hanson
committed
Mark type arguments as used even if used in an invalid way
1 parent 78df754 commit ac74295

20 files changed

+534
-29
lines changed

src/compiler/checker.ts

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4714,7 +4714,7 @@ namespace ts {
47144714
// When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the
47154715
// class and all return the instance type of the class. There is no need for further checks and we can apply the
47164716
// type arguments in the same manner as a type reference to get the same error reporting experience.
4717-
baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol);
4717+
baseType = getTypeFromClassOrInterfaceReference(baseTypeNode, baseConstructorType.symbol, typeArgumentsFromTypeReferenceNode(baseTypeNode));
47184718
}
47194719
else if (baseConstructorType.flags & TypeFlags.Any) {
47204720
baseType = baseConstructorType;
@@ -5238,7 +5238,7 @@ namespace ts {
52385238
}
52395239
const baseTypeNode = getBaseTypeNodeOfClass(classType);
52405240
const isJavaScript = isInJavaScriptFile(baseTypeNode);
5241-
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
5241+
const typeArguments = typeArgumentsFromTypeReferenceNode(baseTypeNode);
52425242
const typeArgCount = length(typeArguments);
52435243
const result: Signature[] = [];
52445244
for (const baseSig of baseSignatures) {
@@ -6501,7 +6501,7 @@ namespace ts {
65016501
}
65026502

65036503
// Get type from reference to class or interface
6504-
function getTypeFromClassOrInterfaceReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol): Type {
6504+
function getTypeFromClassOrInterfaceReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol, typeArgs: Type[]): Type {
65056505
const type = <InterfaceType>getDeclaredTypeOfSymbol(getMergedSymbol(symbol));
65066506
const typeParameters = type.localTypeParameters;
65076507
if (typeParameters) {
@@ -6520,7 +6520,7 @@ namespace ts {
65206520
// In a type reference, the outer type parameters of the referenced class or interface are automatically
65216521
// supplied as type arguments and the type reference only specifies arguments for the local type parameters
65226522
// of the class or interface.
6523-
const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(map(node.typeArguments, getTypeFromTypeNode), typeParameters, minTypeArgumentCount, node));
6523+
const typeArguments = concatenate(type.outerTypeParameters, fillMissingTypeArguments(typeArgs, typeParameters, minTypeArgumentCount, node));
65246524
return createTypeReference(<GenericType>type, typeArguments);
65256525
}
65266526
if (node.typeArguments) {
@@ -6545,7 +6545,7 @@ namespace ts {
65456545
// Get type from reference to type alias. When a type alias is generic, the declared type of the type alias may include
65466546
// references to the type parameters of the alias. We replace those with the actual type arguments by instantiating the
65476547
// declared type. Instantiations are cached using the type identities of the type arguments as the key.
6548-
function getTypeFromTypeAliasReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol): Type {
6548+
function getTypeFromTypeAliasReference(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol, typeArguments: Type[]): Type {
65496549
const type = getDeclaredTypeOfSymbol(symbol);
65506550
const typeParameters = getSymbolLinks(symbol).typeParameters;
65516551
if (typeParameters) {
@@ -6561,7 +6561,6 @@ namespace ts {
65616561
typeParameters.length);
65626562
return unknownType;
65636563
}
6564-
const typeArguments = map(node.typeArguments, getTypeFromTypeNode);
65656564
return getTypeAliasInstantiation(symbol, typeArguments);
65666565
}
65676566
if (node.typeArguments) {
@@ -6609,16 +6608,18 @@ namespace ts {
66096608
}
66106609

66116610
function getTypeReferenceType(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference, symbol: Symbol) {
6611+
const typeArguments = typeArgumentsFromTypeReferenceNode(node); // Do unconditionally so we mark type arguments as referenced.
6612+
66126613
if (symbol === unknownSymbol) {
66136614
return unknownType;
66146615
}
66156616

66166617
if (symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface)) {
6617-
return getTypeFromClassOrInterfaceReference(node, symbol);
6618+
return getTypeFromClassOrInterfaceReference(node, symbol, typeArguments);
66186619
}
66196620

66206621
if (symbol.flags & SymbolFlags.TypeAlias) {
6621-
return getTypeFromTypeAliasReference(node, symbol);
6622+
return getTypeFromTypeAliasReference(node, symbol, typeArguments);
66226623
}
66236624

66246625
if (symbol.flags & SymbolFlags.Value && node.kind === SyntaxKind.JSDocTypeReference) {
@@ -6686,9 +6687,10 @@ namespace ts {
66866687
? <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression
66876688
: undefined;
66886689
symbol = typeNameOrExpression && resolveEntityName(typeNameOrExpression, SymbolFlags.Type) || unknownSymbol;
6690+
const typeArguments = typeArgumentsFromTypeReferenceNode(node);
66896691
type = symbol === unknownSymbol ? unknownType :
6690-
symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol) :
6691-
symbol.flags & SymbolFlags.TypeAlias ? getTypeFromTypeAliasReference(node, symbol) :
6692+
symbol.flags & (SymbolFlags.Class | SymbolFlags.Interface) ? getTypeFromClassOrInterfaceReference(node, symbol, typeArguments) :
6693+
symbol.flags & SymbolFlags.TypeAlias ? getTypeFromTypeAliasReference(node, symbol, typeArguments) :
66926694
getTypeFromNonGenericTypeReference(node, symbol);
66936695
}
66946696
// Cache both the resolved symbol and the resolved type. The resolved symbol is needed in when we check the
@@ -6699,6 +6701,10 @@ namespace ts {
66996701
return links.resolvedType;
67006702
}
67016703

6704+
function typeArgumentsFromTypeReferenceNode(node: TypeReferenceNode | ExpressionWithTypeArguments | JSDocTypeReference): Type[] {
6705+
return map(node.typeArguments, getTypeFromTypeNode);
6706+
}
6707+
67026708
function getTypeFromTypeQueryNode(node: TypeQueryNode): Type {
67036709
const links = getNodeLinks(node);
67046710
if (!links.resolvedType) {
@@ -14303,7 +14309,17 @@ namespace ts {
1430314309
return true;
1430414310
}
1430514311

14312+
function callLikeExpressionMayHaveTypeArguments(node: CallLikeExpression): node is CallExpression | NewExpression {
14313+
return node.kind === SyntaxKind.CallExpression || node.kind === SyntaxKind.NewExpression;
14314+
}
14315+
1430614316
function resolveUntypedCall(node: CallLikeExpression): Signature {
14317+
if (callLikeExpressionMayHaveTypeArguments(node)) {
14318+
// Check type arguments even though we will give an error that untyped calls may not accept type arguments.
14319+
// This gets us diagnostics for the type arguments and marks them as referenced.
14320+
forEach(node.typeArguments, checkSourceElement);
14321+
}
14322+
1430714323
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
1430814324
checkExpression((<TaggedTemplateExpression>node).template);
1430914325
}
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
tests/cases/compiler/callExpressionWithMissingTypeArgument1.ts(1,1): error TS2304: Cannot find name 'Foo'.
2+
tests/cases/compiler/callExpressionWithMissingTypeArgument1.ts(1,5): error TS2304: Cannot find name 'a'.
23
tests/cases/compiler/callExpressionWithMissingTypeArgument1.ts(1,7): error TS1110: Type expected.
4+
tests/cases/compiler/callExpressionWithMissingTypeArgument1.ts(1,8): error TS2304: Cannot find name 'b'.
35

46

5-
==== tests/cases/compiler/callExpressionWithMissingTypeArgument1.ts (2 errors) ====
7+
==== tests/cases/compiler/callExpressionWithMissingTypeArgument1.ts (4 errors) ====
68
Foo<a,,b>();
79
~~~
810
!!! error TS2304: Cannot find name 'Foo'.
11+
~
12+
!!! error TS2304: Cannot find name 'a'.
913
~
10-
!!! error TS1110: Type expected.
14+
!!! error TS1110: Type expected.
15+
~
16+
!!! error TS2304: Cannot find name 'b'.

tests/baselines/reference/functionCalls.errors.txt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
tests/cases/conformance/expressions/functionCalls/functionCalls.ts(8,1): error TS2347: Untyped function calls may not accept type arguments.
22
tests/cases/conformance/expressions/functionCalls/functionCalls.ts(9,1): error TS2347: Untyped function calls may not accept type arguments.
33
tests/cases/conformance/expressions/functionCalls/functionCalls.ts(10,1): error TS2347: Untyped function calls may not accept type arguments.
4+
tests/cases/conformance/expressions/functionCalls/functionCalls.ts(10,8): error TS2304: Cannot find name 'Window'.
45
tests/cases/conformance/expressions/functionCalls/functionCalls.ts(25,1): error TS2347: Untyped function calls may not accept type arguments.
56
tests/cases/conformance/expressions/functionCalls/functionCalls.ts(26,1): error TS2347: Untyped function calls may not accept type arguments.
67
tests/cases/conformance/expressions/functionCalls/functionCalls.ts(27,1): error TS2347: Untyped function calls may not accept type arguments.
@@ -9,7 +10,7 @@ tests/cases/conformance/expressions/functionCalls/functionCalls.ts(33,1): error
910
tests/cases/conformance/expressions/functionCalls/functionCalls.ts(34,1): error TS2347: Untyped function calls may not accept type arguments.
1011

1112

12-
==== tests/cases/conformance/expressions/functionCalls/functionCalls.ts (9 errors) ====
13+
==== tests/cases/conformance/expressions/functionCalls/functionCalls.ts (10 errors) ====
1314
// Invoke function call on value of type 'any' with no type arguments
1415
var anyVar: any;
1516
anyVar(0);
@@ -26,6 +27,8 @@ tests/cases/conformance/expressions/functionCalls/functionCalls.ts(34,1): error
2627
anyVar<Window>(undefined);
2728
~~~~~~~~~~~~~~~~~~~~~~~~~
2829
!!! error TS2347: Untyped function calls may not accept type arguments.
30+
~~~~~~
31+
!!! error TS2304: Cannot find name 'Window'.
2932

3033

3134
// Invoke function call on value of a subtype of Function with no call signatures with no type arguments
Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
tests/cases/conformance/parser/ecmascript5/Generics/parserAmbiguity1.ts(1,1): error TS2304: Cannot find name 'f'.
22
tests/cases/conformance/parser/ecmascript5/Generics/parserAmbiguity1.ts(1,3): error TS2304: Cannot find name 'g'.
3+
tests/cases/conformance/parser/ecmascript5/Generics/parserAmbiguity1.ts(1,5): error TS2304: Cannot find name 'A'.
4+
tests/cases/conformance/parser/ecmascript5/Generics/parserAmbiguity1.ts(1,8): error TS2304: Cannot find name 'B'.
35

46

5-
==== tests/cases/conformance/parser/ecmascript5/Generics/parserAmbiguity1.ts (2 errors) ====
7+
==== tests/cases/conformance/parser/ecmascript5/Generics/parserAmbiguity1.ts (4 errors) ====
68
f(g<A, B>(7));
79
~
810
!!! error TS2304: Cannot find name 'f'.
911
~
10-
!!! error TS2304: Cannot find name 'g'.
12+
!!! error TS2304: Cannot find name 'g'.
13+
~
14+
!!! error TS2304: Cannot find name 'A'.
15+
~
16+
!!! error TS2304: Cannot find name 'B'.
Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
tests/cases/conformance/parser/ecmascript5/Generics/parserAmbiguityWithBinaryOperator4.ts(3,9): error TS2347: Untyped function calls may not accept type arguments.
2+
tests/cases/conformance/parser/ecmascript5/Generics/parserAmbiguityWithBinaryOperator4.ts(3,11): error TS2304: Cannot find name 'b'.
3+
tests/cases/conformance/parser/ecmascript5/Generics/parserAmbiguityWithBinaryOperator4.ts(3,14): error TS2304: Cannot find name 'b'.
24

35

4-
==== tests/cases/conformance/parser/ecmascript5/Generics/parserAmbiguityWithBinaryOperator4.ts (1 errors) ====
6+
==== tests/cases/conformance/parser/ecmascript5/Generics/parserAmbiguityWithBinaryOperator4.ts (3 errors) ====
57
function g() {
68
var a, b, c;
79
if (a<b, b>(c + 1)) { }
810
~~~~~~~~~~~~~~
911
!!! error TS2347: Untyped function calls may not accept type arguments.
12+
~
13+
!!! error TS2304: Cannot find name 'b'.
14+
~
15+
!!! error TS2304: Cannot find name 'b'.
1016
}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint4.ts(1,19): error TS2304: Cannot find name 'List'.
2+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint4.ts(1,24): error TS2304: Cannot find name 'List'.
23

34

4-
==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint4.ts (1 errors) ====
5+
==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint4.ts (2 errors) ====
56
class C<T extends List<List<T> > > {
67
~~~~
8+
!!! error TS2304: Cannot find name 'List'.
9+
~~~~
710
!!! error TS2304: Cannot find name 'List'.
811
}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint5.ts(1,19): error TS2304: Cannot find name 'List'.
2+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint5.ts(1,24): error TS2304: Cannot find name 'List'.
23

34

4-
==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint5.ts (1 errors) ====
5+
==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint5.ts (2 errors) ====
56
class C<T extends List<List<T>> > {
67
~~~~
8+
!!! error TS2304: Cannot find name 'List'.
9+
~~~~
710
!!! error TS2304: Cannot find name 'List'.
811
}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint6.ts(1,19): error TS2304: Cannot find name 'List'.
2+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint6.ts(1,24): error TS2304: Cannot find name 'List'.
23

34

4-
==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint6.ts (1 errors) ====
5+
==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint6.ts (2 errors) ====
56
class C<T extends List<List<T> >> {
67
~~~~
8+
!!! error TS2304: Cannot find name 'List'.
9+
~~~~
710
!!! error TS2304: Cannot find name 'List'.
811
}
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint7.ts(1,19): error TS2304: Cannot find name 'List'.
2+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint7.ts(1,24): error TS2304: Cannot find name 'List'.
23

34

4-
==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint7.ts (1 errors) ====
5+
==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericConstraint7.ts (2 errors) ====
56
class C<T extends List<List<T>>> {
67
~~~~
8+
!!! error TS2304: Cannot find name 'List'.
9+
~~~~
710
!!! error TS2304: Cannot find name 'List'.
811
}
Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,71 @@
11
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(1,17): error TS2304: Cannot find name 'A'.
22
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(1,33): error TS2304: Cannot find name 'B'.
3+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(1,35): error TS2304: Cannot find name 'T'.
34
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(4,9): error TS2315: Type 'C' is not generic.
5+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(4,11): error TS2304: Cannot find name 'T'.
46
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(5,9): error TS2304: Cannot find name 'D'.
7+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(5,11): error TS2304: Cannot find name 'T'.
58
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(6,9): error TS2503: Cannot find namespace 'E'.
9+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(6,13): error TS2304: Cannot find name 'T'.
610
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(7,9): error TS2503: Cannot find namespace 'G'.
11+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(7,15): error TS2304: Cannot find name 'T'.
712
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(8,9): error TS2304: Cannot find name 'K'.
13+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(8,11): error TS2304: Cannot find name 'T'.
814
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(11,16): error TS2304: Cannot find name 'E'.
15+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(11,18): error TS2304: Cannot find name 'T'.
916
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(14,16): error TS2304: Cannot find name 'F'.
17+
tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts(14,18): error TS2304: Cannot find name 'T'.
1018

1119

12-
==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts (9 errors) ====
20+
==== tests/cases/conformance/parser/ecmascript5/Generics/parserGenericsInTypeContexts1.ts (17 errors) ====
1321
class C extends A<T> implements B<T> {
1422
~
1523
!!! error TS2304: Cannot find name 'A'.
1624
~
1725
!!! error TS2304: Cannot find name 'B'.
26+
~
27+
!!! error TS2304: Cannot find name 'T'.
1828
}
1929

2030
var v1: C<T>;
2131
~~~~
2232
!!! error TS2315: Type 'C' is not generic.
33+
~
34+
!!! error TS2304: Cannot find name 'T'.
2335
var v2: D<T> = null;
2436
~
2537
!!! error TS2304: Cannot find name 'D'.
38+
~
39+
!!! error TS2304: Cannot find name 'T'.
2640
var v3: E.F<T>;
2741
~
2842
!!! error TS2503: Cannot find namespace 'E'.
43+
~
44+
!!! error TS2304: Cannot find name 'T'.
2945
var v3: G.H.I<T>;
3046
~
3147
!!! error TS2503: Cannot find namespace 'G'.
48+
~
49+
!!! error TS2304: Cannot find name 'T'.
3250
var v6: K<T>[];
3351
~
3452
!!! error TS2304: Cannot find name 'K'.
53+
~
54+
!!! error TS2304: Cannot find name 'T'.
3555

3656

3757
function f1(a: E<T>) {
3858
~
3959
!!! error TS2304: Cannot find name 'E'.
60+
~
61+
!!! error TS2304: Cannot find name 'T'.
4062
}
4163

4264
function f2(): F<T> {
4365
~
4466
!!! error TS2304: Cannot find name 'F'.
67+
~
68+
!!! error TS2304: Cannot find name 'T'.
4569
}
4670

4771

0 commit comments

Comments
 (0)