Skip to content

Commit ae11ae5

Browse files
committed
Fix getReturnTypeFromBody widening
1 parent b9dbf5d commit ae11ae5

File tree

60 files changed

+3865
-427
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+3865
-427
lines changed

src/compiler/checker.ts

+45-28
Original file line numberDiff line numberDiff line change
@@ -3360,8 +3360,13 @@ namespace ts {
33603360
writeAnonymousType(<ObjectType>type, nextFlags);
33613361
}
33623362
else if (type.flags & TypeFlags.UniqueESSymbol) {
3363-
writeKeyword(writer, SyntaxKind.UniqueKeyword);
3364-
writeSpace(writer);
3363+
if (flags & TypeFormatFlags.AllowUniqueESSymbolType) {
3364+
writeKeyword(writer, SyntaxKind.UniqueKeyword);
3365+
writeSpace(writer);
3366+
}
3367+
else {
3368+
writer.reportInaccessibleUniqueSymbolError();
3369+
}
33653370
writeKeyword(writer, SyntaxKind.SymbolKeyword);
33663371
}
33673372
else if (type.flags & TypeFlags.StringOrNumberLiteral) {
@@ -8365,9 +8370,7 @@ namespace ts {
83658370
}
83668371

83678372
function getESSymbolLikeTypeForNode(node: Node) {
8368-
if (isVariableDeclaration(node) ? isConst(node) && isIdentifier(node.name) && isVariableDeclarationInVariableStatement(node) :
8369-
isPropertyDeclaration(node) ? hasReadonlyModifier(node) && hasStaticModifier(node) :
8370-
isPropertySignature(node) && hasReadonlyModifier(node)) {
8373+
if (isValidESSymbolDeclaration(node)) {
83718374
const symbol = getSymbolOfNode(node);
83728375
const links = getSymbolLinks(symbol);
83738376
return links.type || (links.type = createUniqueESSymbolType(symbol));
@@ -17694,9 +17697,6 @@ namespace ts {
1769417697
// the native Promise<T> type later in this function.
1769517698
type = checkAwaitedType(type, /*errorNode*/ func, Diagnostics.The_return_type_of_an_async_function_must_either_be_a_valid_promise_or_must_not_contain_a_callable_then_member);
1769617699
}
17697-
17698-
// widen 'unique symbol' types when we infer the return type.
17699-
type = getWidenedUniqueESSymbolType(type);
1770017700
}
1770117701
else {
1770217702
let types: Type[];
@@ -17728,37 +17728,49 @@ namespace ts {
1772817728
: voidType; // Normal function
1772917729
}
1773017730
}
17731+
1773117732
// Return a union of the return expression types.
1773217733
type = getUnionType(types, /*subtypeReduction*/ true);
17733-
17734-
// widen 'unique symbol' types when we infer the return type.
17735-
type = getWidenedUniqueESSymbolType(type);
17736-
17737-
if (functionFlags & FunctionFlags.Generator) { // AsyncGenerator function or Generator function
17738-
type = functionFlags & FunctionFlags.Async
17739-
? createAsyncIterableIteratorType(type) // AsyncGenerator function
17740-
: createIterableIteratorType(type); // Generator function
17741-
}
1774217734
}
1774317735

1774417736
if (!contextualSignature) {
1774517737
reportErrorsFromWidening(func, type);
1774617738
}
1774717739

17748-
if (isUnitType(type) &&
17749-
!(contextualSignature &&
17750-
isLiteralContextualType(
17751-
contextualSignature === getSignatureFromDeclaration(func) ? type : getReturnTypeOfSignature(contextualSignature)))) {
17752-
type = getWidenedLiteralType(type);
17740+
if (isUnitType(type)) {
17741+
let contextualType = !contextualSignature ? undefined :
17742+
contextualSignature === getSignatureFromDeclaration(func) ? type :
17743+
getReturnTypeOfSignature(contextualSignature);
17744+
if (contextualType) {
17745+
switch (functionFlags & FunctionFlags.AsyncGenerator) {
17746+
case FunctionFlags.AsyncGenerator:
17747+
contextualType = getIteratedTypeOfGenerator(contextualType, /*isAsyncGenerator*/ true);
17748+
break;
17749+
case FunctionFlags.Generator:
17750+
contextualType = getIteratedTypeOfGenerator(contextualType, /*isAsyncGenerator*/ false);
17751+
break;
17752+
case FunctionFlags.Async:
17753+
contextualType = getPromisedTypeOfPromise(contextualType);
17754+
break;
17755+
}
17756+
}
17757+
type = getWidenedLiteralLikeTypeForContextualType(type, contextualType);
1775317758
}
1775417759

1775517760
const widenedType = getWidenedType(type);
17756-
// From within an async function you can return either a non-promise value or a promise. Any
17757-
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
17758-
// return type of the body is awaited type of the body, wrapped in a native Promise<T> type.
17759-
return (functionFlags & FunctionFlags.AsyncGenerator) === FunctionFlags.Async
17760-
? createPromiseReturnType(func, widenedType) // Async function
17761-
: widenedType; // Generator function, AsyncGenerator function, or normal function
17761+
switch (functionFlags & FunctionFlags.AsyncGenerator) {
17762+
case FunctionFlags.AsyncGenerator:
17763+
return createAsyncIterableIteratorType(widenedType);
17764+
case FunctionFlags.Generator:
17765+
return createIterableIteratorType(widenedType);
17766+
case FunctionFlags.Async:
17767+
// From within an async function you can return either a non-promise value or a promise. Any
17768+
// Promise/A+ compatible implementation will always assimilate any foreign promise, so the
17769+
// return type of the body is awaited type of the body, wrapped in a native Promise<T> type.
17770+
return createPromiseType(widenedType);
17771+
default:
17772+
return widenedType;
17773+
}
1776217774
}
1776317775

1776417776
function checkAndAggregateYieldOperandTypes(func: FunctionLikeDeclaration, checkMode: CheckMode): Type[] {
@@ -24627,9 +24639,14 @@ namespace ts {
2462724639
let type = symbol && !(symbol.flags & (SymbolFlags.TypeLiteral | SymbolFlags.Signature))
2462824640
? getWidenedLiteralType(getTypeOfSymbol(symbol))
2462924641
: unknownType;
24642+
if (type.flags & TypeFlags.UniqueESSymbol &&
24643+
type.symbol === symbol) {
24644+
flags |= TypeFormatFlags.AllowUniqueESSymbolType;
24645+
}
2463024646
if (flags & TypeFormatFlags.AddUndefined) {
2463124647
type = getNullableType(type, TypeFlags.Undefined);
2463224648
}
24649+
2463324650
getSymbolDisplayBuilder().buildTypeDisplay(type, writer, enclosingDeclaration, flags);
2463424651
}
2463524652

src/compiler/declarationEmitter.ts

+13-2
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ namespace ts {
190190
const writer = <EmitTextWriterWithSymbolWriter>createTextWriter(newLine);
191191
writer.trackSymbol = trackSymbol;
192192
writer.reportInaccessibleThisError = reportInaccessibleThisError;
193+
writer.reportInaccessibleUniqueSymbolError = reportInaccessibleUniqueSymbolError;
193194
writer.reportPrivateInBaseOfClassExpression = reportPrivateInBaseOfClassExpression;
194195
writer.writeKeyword = writer.write;
195196
writer.writeOperator = writer.write;
@@ -322,11 +323,21 @@ namespace ts {
322323
}
323324
}
324325

326+
function reportInaccessibleUniqueSymbolError() {
327+
if (errorNameNode) {
328+
reportedDeclarationError = true;
329+
emitterDiagnostics.add(createDiagnosticForNode(errorNameNode, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary,
330+
declarationNameToString(errorNameNode),
331+
"unique symbol"));
332+
}
333+
}
334+
325335
function reportInaccessibleThisError() {
326336
if (errorNameNode) {
327337
reportedDeclarationError = true;
328-
emitterDiagnostics.add(createDiagnosticForNode(errorNameNode, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_this_type_A_type_annotation_is_necessary,
329-
declarationNameToString(errorNameNode)));
338+
emitterDiagnostics.add(createDiagnosticForNode(errorNameNode, Diagnostics.The_inferred_type_of_0_references_an_inaccessible_1_type_A_type_annotation_is_necessary,
339+
declarationNameToString(errorNameNode),
340+
"this"));
330341
}
331342
}
332343

src/compiler/diagnosticMessages.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1804,7 +1804,7 @@
18041804
"category": "Error",
18051805
"code": 2526
18061806
},
1807-
"The inferred type of '{0}' references an inaccessible 'this' type. A type annotation is necessary.": {
1807+
"The inferred type of '{0}' references an inaccessible '{1}' type. A type annotation is necessary.": {
18081808
"category": "Error",
18091809
"code": 2527
18101810
},

src/compiler/types.ts

+2
Original file line numberDiff line numberDiff line change
@@ -2857,6 +2857,7 @@ namespace ts {
28572857
trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
28582858
reportInaccessibleThisError(): void;
28592859
reportPrivateInBaseOfClassExpression(propertyName: string): void;
2860+
reportInaccessibleUniqueSymbolError(): void;
28602861
}
28612862

28622863
export const enum TypeFormatFlags {
@@ -2877,6 +2878,7 @@ namespace ts {
28772878
InArrayType = 1 << 15, // Writing an array element type
28782879
UseAliasDefinedOutsideCurrentScope = 1 << 16, // For a `type T = ... ` defined in a different file, write `T` instead of its value,
28792880
// even though `T` can't be accessed in the current scope.
2881+
AllowUniqueESSymbolType = 1 << 17,
28802882
}
28812883

28822884
export const enum SymbolFormatFlags {

src/compiler/utilities.ts

+7
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ namespace ts {
5656
clear: () => str = "",
5757
trackSymbol: noop,
5858
reportInaccessibleThisError: noop,
59+
reportInaccessibleUniqueSymbolError: noop,
5960
reportPrivateInBaseOfClassExpression: noop,
6061
};
6162
}
@@ -945,6 +946,12 @@ namespace ts {
945946
&& node.parent.parent.kind === SyntaxKind.VariableStatement;
946947
}
947948

949+
export function isValidESSymbolDeclaration(node: Node) {
950+
return isVariableDeclaration(node) ? isConst(node) && isIdentifier(node.name) && isVariableDeclarationInVariableStatement(node) :
951+
isPropertyDeclaration(node) ? hasReadonlyModifier(node) && hasStaticModifier(node) :
952+
isPropertySignature(node) && hasReadonlyModifier(node);
953+
}
954+
948955
export function introducesArgumentsExoticObject(node: Node) {
949956
switch (node.kind) {
950957
case SyntaxKind.MethodDeclaration:

src/services/codefixes/inferFromUsage.ts

+1
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,7 @@ namespace ts.codefix {
246246
},
247247
reportInaccessibleThisError: () => { typeIsAccessible = false; },
248248
reportPrivateInBaseOfClassExpression: () => { typeIsAccessible = false; },
249+
reportInaccessibleUniqueSymbolError: () => { typeIsAccessible = false; }
249250
};
250251
}
251252
writer.clear();

src/services/utilities.ts

+1
Original file line numberDiff line numberDiff line change
@@ -1130,6 +1130,7 @@ namespace ts {
11301130
clear: resetWriter,
11311131
trackSymbol: noop,
11321132
reportInaccessibleThisError: noop,
1133+
reportInaccessibleUniqueSymbolError: noop,
11331134
reportPrivateInBaseOfClassExpression: noop,
11341135
};
11351136

tests/baselines/reference/YieldStarExpression4_es6.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
=== tests/cases/conformance/es6/yieldExpressions/YieldStarExpression4_es6.ts ===
22
function *g() {
3-
>g : () => IterableIterator<undefined>
3+
>g : () => IterableIterator<any>
44

55
yield * [];
66
>yield * [] : any

tests/baselines/reference/api/tsserverlibrary.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1826,6 +1826,7 @@ declare namespace ts {
18261826
trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
18271827
reportInaccessibleThisError(): void;
18281828
reportPrivateInBaseOfClassExpression(propertyName: string): void;
1829+
reportInaccessibleUniqueSymbolError(): void;
18291830
}
18301831
enum TypeFormatFlags {
18311832
None = 0,
@@ -1844,6 +1845,7 @@ declare namespace ts {
18441845
WriteClassExpressionAsTypeLiteral = 16384,
18451846
InArrayType = 32768,
18461847
UseAliasDefinedOutsideCurrentScope = 65536,
1848+
AllowUniqueESSymbolType = 131072,
18471849
}
18481850
enum SymbolFormatFlags {
18491851
None = 0,

tests/baselines/reference/api/typescript.d.ts

+2
Original file line numberDiff line numberDiff line change
@@ -1826,6 +1826,7 @@ declare namespace ts {
18261826
trackSymbol(symbol: Symbol, enclosingDeclaration?: Node, meaning?: SymbolFlags): void;
18271827
reportInaccessibleThisError(): void;
18281828
reportPrivateInBaseOfClassExpression(propertyName: string): void;
1829+
reportInaccessibleUniqueSymbolError(): void;
18291830
}
18301831
enum TypeFormatFlags {
18311832
None = 0,
@@ -1844,6 +1845,7 @@ declare namespace ts {
18441845
WriteClassExpressionAsTypeLiteral = 16384,
18451846
InArrayType = 32768,
18461847
UseAliasDefinedOutsideCurrentScope = 65536,
1848+
AllowUniqueESSymbolType = 131072,
18471849
}
18481850
enum SymbolFormatFlags {
18491851
None = 0,

tests/baselines/reference/asyncImportNestedYield.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
=== tests/cases/compiler/asyncImportNestedYield.ts ===
22
async function* foo() {
3-
>foo : () => AsyncIterableIterator<"foo">
3+
>foo : () => AsyncIterableIterator<string>
44

55
import((await import(yield "foo")).default);
66
>import((await import(yield "foo")).default) : Promise<any>

tests/baselines/reference/emitter.asyncGenerators.classMethods.es2015.types

+6-6
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class C3 {
2323
>C3 : C3
2424

2525
async * f() {
26-
>f : () => AsyncIterableIterator<1>
26+
>f : () => AsyncIterableIterator<number>
2727

2828
const x = yield 1;
2929
>x : any
@@ -50,14 +50,14 @@ class C5 {
5050
>C5 : C5
5151

5252
async * f() {
53-
>f : () => AsyncIterableIterator<1>
53+
>f : () => AsyncIterableIterator<number>
5454

5555
const x = yield* (async function*() { yield 1; })();
5656
>x : any
5757
>yield* (async function*() { yield 1; })() : any
58-
>(async function*() { yield 1; })() : AsyncIterableIterator<1>
59-
>(async function*() { yield 1; }) : () => AsyncIterableIterator<1>
60-
>async function*() { yield 1; } : () => AsyncIterableIterator<1>
58+
>(async function*() { yield 1; })() : AsyncIterableIterator<number>
59+
>(async function*() { yield 1; }) : () => AsyncIterableIterator<number>
60+
>async function*() { yield 1; } : () => AsyncIterableIterator<number>
6161
>yield 1 : any
6262
>1 : 1
6363
}
@@ -80,7 +80,7 @@ class C7 {
8080
>C7 : C7
8181

8282
async * f() {
83-
>f : () => AsyncIterableIterator<1>
83+
>f : () => AsyncIterableIterator<number>
8484

8585
return 1;
8686
>1 : 1

tests/baselines/reference/emitter.asyncGenerators.classMethods.es5.types

+6-6
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class C3 {
2323
>C3 : C3
2424

2525
async * f() {
26-
>f : () => AsyncIterableIterator<1>
26+
>f : () => AsyncIterableIterator<number>
2727

2828
const x = yield 1;
2929
>x : any
@@ -50,14 +50,14 @@ class C5 {
5050
>C5 : C5
5151

5252
async * f() {
53-
>f : () => AsyncIterableIterator<1>
53+
>f : () => AsyncIterableIterator<number>
5454

5555
const x = yield* (async function*() { yield 1; })();
5656
>x : any
5757
>yield* (async function*() { yield 1; })() : any
58-
>(async function*() { yield 1; })() : AsyncIterableIterator<1>
59-
>(async function*() { yield 1; }) : () => AsyncIterableIterator<1>
60-
>async function*() { yield 1; } : () => AsyncIterableIterator<1>
58+
>(async function*() { yield 1; })() : AsyncIterableIterator<number>
59+
>(async function*() { yield 1; }) : () => AsyncIterableIterator<number>
60+
>async function*() { yield 1; } : () => AsyncIterableIterator<number>
6161
>yield 1 : any
6262
>1 : 1
6363
}
@@ -80,7 +80,7 @@ class C7 {
8080
>C7 : C7
8181

8282
async * f() {
83-
>f : () => AsyncIterableIterator<1>
83+
>f : () => AsyncIterableIterator<number>
8484

8585
return 1;
8686
>1 : 1

tests/baselines/reference/emitter.asyncGenerators.classMethods.esnext.types

+6-6
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class C3 {
2323
>C3 : C3
2424

2525
async * f() {
26-
>f : () => AsyncIterableIterator<1>
26+
>f : () => AsyncIterableIterator<number>
2727

2828
const x = yield 1;
2929
>x : any
@@ -50,14 +50,14 @@ class C5 {
5050
>C5 : C5
5151

5252
async * f() {
53-
>f : () => AsyncIterableIterator<1>
53+
>f : () => AsyncIterableIterator<number>
5454

5555
const x = yield* (async function*() { yield 1; })();
5656
>x : any
5757
>yield* (async function*() { yield 1; })() : any
58-
>(async function*() { yield 1; })() : AsyncIterableIterator<1>
59-
>(async function*() { yield 1; }) : () => AsyncIterableIterator<1>
60-
>async function*() { yield 1; } : () => AsyncIterableIterator<1>
58+
>(async function*() { yield 1; })() : AsyncIterableIterator<number>
59+
>(async function*() { yield 1; }) : () => AsyncIterableIterator<number>
60+
>async function*() { yield 1; } : () => AsyncIterableIterator<number>
6161
>yield 1 : any
6262
>1 : 1
6363
}
@@ -80,7 +80,7 @@ class C7 {
8080
>C7 : C7
8181

8282
async * f() {
83-
>f : () => AsyncIterableIterator<1>
83+
>f : () => AsyncIterableIterator<number>
8484

8585
return 1;
8686
>1 : 1

0 commit comments

Comments
 (0)