Skip to content

Commit

Permalink
fix56509: return type if tryCreateAwaitedType fails (#58547)
Browse files Browse the repository at this point in the history
  • Loading branch information
iisaduan authored May 16, 2024
1 parent 5c21b7f commit 4da470d
Show file tree
Hide file tree
Showing 6 changed files with 302 additions and 4 deletions.
5 changes: 1 addition & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41889,10 +41889,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
// - The base constraint of `T` is an object type with a callable `then` method.

if (isAwaitedTypeNeeded(type)) {
const awaitedType = tryCreateAwaitedType(type);
if (awaitedType) {
return awaitedType;
}
return tryCreateAwaitedType(type) ?? type;
}

Debug.assert(isAwaitedTypeInstantiation(type) || getPromisedTypeOfPromise(type) === undefined, "type provided should not be a non-generic 'promise'-like.");
Expand Down
63 changes: 63 additions & 0 deletions tests/baselines/reference/awaitedTypeNoLib.errors.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
error TS2318: Cannot find global type 'Array'.
error TS2318: Cannot find global type 'Awaited'.
error TS2318: Cannot find global type 'Boolean'.
error TS2318: Cannot find global type 'Function'.
error TS2318: Cannot find global type 'IArguments'.
error TS2318: Cannot find global type 'Number'.
error TS2318: Cannot find global type 'Object'.
error TS2318: Cannot find global type 'RegExp'.
error TS2318: Cannot find global type 'String'.
awaitedTypeNoLib.ts(3,15): error TS2304: Cannot find name 'PromiseLike'.
awaitedTypeNoLib.ts(18,27): error TS2345: Argument of type 'NotPromise<TResult> | Thenable<NotPromise<TResult>>' is not assignable to parameter of type 'Thenable<TResult>'.
Type 'NotPromise<TResult>' is not assignable to type 'Thenable<TResult>'.
Type 'TResult | (TResult extends PromiseLike<unknown> ? never : TResult)' is not assignable to type 'Thenable<TResult>'.
Type 'Thenable<unknown> & TResult' is not assignable to type 'Thenable<TResult>'.
Type 'unknown' is not assignable to type 'TResult'.
'TResult' could be instantiated with an arbitrary type which could be unrelated to 'unknown'.


!!! error TS2318: Cannot find global type 'Array'.
!!! error TS2318: Cannot find global type 'Awaited'.
!!! error TS2318: Cannot find global type 'Boolean'.
!!! error TS2318: Cannot find global type 'Function'.
!!! error TS2318: Cannot find global type 'IArguments'.
!!! error TS2318: Cannot find global type 'Number'.
!!! error TS2318: Cannot find global type 'Object'.
!!! error TS2318: Cannot find global type 'RegExp'.
!!! error TS2318: Cannot find global type 'String'.
==== awaitedTypeNoLib.ts (2 errors) ====
type NotPromise<T> = T extends Thenable<unknown>
? T
: T extends PromiseLike<unknown>
~~~~~~~~~~~
!!! error TS2304: Cannot find name 'PromiseLike'.
? never
: T;

type Receiver<T> = (value: NotPromise<T>) => void;

class Thenable<T> {
then(a: Receiver<T>) {}

private handleResolve<TResult>(
result: NotPromise<TResult> | Thenable<NotPromise<TResult>>,
resolve: Receiver<TResult>,
) {
if (result instanceof Thenable) {
// #58547 This previously was a Debug Failure. False expression: type provided should not be a non-generic 'promise'-like.
this.resolvePromise(result, resolve);
~~~~~~
!!! error TS2345: Argument of type 'NotPromise<TResult> | Thenable<NotPromise<TResult>>' is not assignable to parameter of type 'Thenable<TResult>'.
!!! error TS2345: Type 'NotPromise<TResult>' is not assignable to type 'Thenable<TResult>'.
!!! error TS2345: Type 'TResult | (TResult extends PromiseLike<unknown> ? never : TResult)' is not assignable to type 'Thenable<TResult>'.
!!! error TS2345: Type 'Thenable<unknown> & TResult' is not assignable to type 'Thenable<TResult>'.
!!! error TS2345: Type 'unknown' is not assignable to type 'TResult'.
!!! error TS2345: 'TResult' could be instantiated with an arbitrary type which could be unrelated to 'unknown'.
}
}

private resolvePromise<TResult>(
result: Thenable<TResult>,
resolve: Receiver<TResult>,
) {}
}
44 changes: 44 additions & 0 deletions tests/baselines/reference/awaitedTypeNoLib.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
//// [tests/cases/compiler/awaitedTypeNoLib.ts] ////

//// [awaitedTypeNoLib.ts]
type NotPromise<T> = T extends Thenable<unknown>
? T
: T extends PromiseLike<unknown>
? never
: T;

type Receiver<T> = (value: NotPromise<T>) => void;

class Thenable<T> {
then(a: Receiver<T>) {}

private handleResolve<TResult>(
result: NotPromise<TResult> | Thenable<NotPromise<TResult>>,
resolve: Receiver<TResult>,
) {
if (result instanceof Thenable) {
// #58547 This previously was a Debug Failure. False expression: type provided should not be a non-generic 'promise'-like.
this.resolvePromise(result, resolve);
}
}

private resolvePromise<TResult>(
result: Thenable<TResult>,
resolve: Receiver<TResult>,
) {}
}

//// [awaitedTypeNoLib.js]
var Thenable = /** @class */ (function () {
function Thenable() {
}
Thenable.prototype.then = function (a) { };
Thenable.prototype.handleResolve = function (result, resolve) {
if (result instanceof Thenable) {
// #58547 This previously was a Debug Failure. False expression: type provided should not be a non-generic 'promise'-like.
this.resolvePromise(result, resolve);
}
};
Thenable.prototype.resolvePromise = function (result, resolve) { };
return Thenable;
}());
85 changes: 85 additions & 0 deletions tests/baselines/reference/awaitedTypeNoLib.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
//// [tests/cases/compiler/awaitedTypeNoLib.ts] ////

=== awaitedTypeNoLib.ts ===
type NotPromise<T> = T extends Thenable<unknown>
>NotPromise : Symbol(NotPromise, Decl(awaitedTypeNoLib.ts, 0, 0))
>T : Symbol(T, Decl(awaitedTypeNoLib.ts, 0, 16))
>T : Symbol(T, Decl(awaitedTypeNoLib.ts, 0, 16))
>Thenable : Symbol(Thenable, Decl(awaitedTypeNoLib.ts, 6, 50))

? T
>T : Symbol(T, Decl(awaitedTypeNoLib.ts, 0, 16))

: T extends PromiseLike<unknown>
>T : Symbol(T, Decl(awaitedTypeNoLib.ts, 0, 16))
>PromiseLike : Symbol(PromiseLike)

? never
: T;
>T : Symbol(T, Decl(awaitedTypeNoLib.ts, 0, 16))

type Receiver<T> = (value: NotPromise<T>) => void;
>Receiver : Symbol(Receiver, Decl(awaitedTypeNoLib.ts, 4, 6))
>T : Symbol(T, Decl(awaitedTypeNoLib.ts, 6, 14))
>value : Symbol(value, Decl(awaitedTypeNoLib.ts, 6, 20))
>NotPromise : Symbol(NotPromise, Decl(awaitedTypeNoLib.ts, 0, 0))
>T : Symbol(T, Decl(awaitedTypeNoLib.ts, 6, 14))

class Thenable<T> {
>Thenable : Symbol(Thenable, Decl(awaitedTypeNoLib.ts, 6, 50))
>T : Symbol(T, Decl(awaitedTypeNoLib.ts, 8, 15))

then(a: Receiver<T>) {}
>then : Symbol(Thenable.then, Decl(awaitedTypeNoLib.ts, 8, 19))
>a : Symbol(a, Decl(awaitedTypeNoLib.ts, 9, 7))
>Receiver : Symbol(Receiver, Decl(awaitedTypeNoLib.ts, 4, 6))
>T : Symbol(T, Decl(awaitedTypeNoLib.ts, 8, 15))

private handleResolve<TResult>(
>handleResolve : Symbol(Thenable.handleResolve, Decl(awaitedTypeNoLib.ts, 9, 25))
>TResult : Symbol(TResult, Decl(awaitedTypeNoLib.ts, 11, 24))

result: NotPromise<TResult> | Thenable<NotPromise<TResult>>,
>result : Symbol(result, Decl(awaitedTypeNoLib.ts, 11, 33))
>NotPromise : Symbol(NotPromise, Decl(awaitedTypeNoLib.ts, 0, 0))
>TResult : Symbol(TResult, Decl(awaitedTypeNoLib.ts, 11, 24))
>Thenable : Symbol(Thenable, Decl(awaitedTypeNoLib.ts, 6, 50))
>NotPromise : Symbol(NotPromise, Decl(awaitedTypeNoLib.ts, 0, 0))
>TResult : Symbol(TResult, Decl(awaitedTypeNoLib.ts, 11, 24))

resolve: Receiver<TResult>,
>resolve : Symbol(resolve, Decl(awaitedTypeNoLib.ts, 12, 64))
>Receiver : Symbol(Receiver, Decl(awaitedTypeNoLib.ts, 4, 6))
>TResult : Symbol(TResult, Decl(awaitedTypeNoLib.ts, 11, 24))

) {
if (result instanceof Thenable) {
>result : Symbol(result, Decl(awaitedTypeNoLib.ts, 11, 33))
>Thenable : Symbol(Thenable, Decl(awaitedTypeNoLib.ts, 6, 50))

// #58547 This previously was a Debug Failure. False expression: type provided should not be a non-generic 'promise'-like.
this.resolvePromise(result, resolve);
>this.resolvePromise : Symbol(Thenable.resolvePromise, Decl(awaitedTypeNoLib.ts, 19, 3))
>this : Symbol(Thenable, Decl(awaitedTypeNoLib.ts, 6, 50))
>resolvePromise : Symbol(Thenable.resolvePromise, Decl(awaitedTypeNoLib.ts, 19, 3))
>result : Symbol(result, Decl(awaitedTypeNoLib.ts, 11, 33))
>resolve : Symbol(resolve, Decl(awaitedTypeNoLib.ts, 12, 64))
}
}

private resolvePromise<TResult>(
>resolvePromise : Symbol(Thenable.resolvePromise, Decl(awaitedTypeNoLib.ts, 19, 3))
>TResult : Symbol(TResult, Decl(awaitedTypeNoLib.ts, 21, 25))

result: Thenable<TResult>,
>result : Symbol(result, Decl(awaitedTypeNoLib.ts, 21, 34))
>Thenable : Symbol(Thenable, Decl(awaitedTypeNoLib.ts, 6, 50))
>TResult : Symbol(TResult, Decl(awaitedTypeNoLib.ts, 21, 25))

resolve: Receiver<TResult>,
>resolve : Symbol(resolve, Decl(awaitedTypeNoLib.ts, 22, 30))
>Receiver : Symbol(Receiver, Decl(awaitedTypeNoLib.ts, 4, 6))
>TResult : Symbol(TResult, Decl(awaitedTypeNoLib.ts, 21, 25))

) {}
}
80 changes: 80 additions & 0 deletions tests/baselines/reference/awaitedTypeNoLib.types
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//// [tests/cases/compiler/awaitedTypeNoLib.ts] ////

=== awaitedTypeNoLib.ts ===
type NotPromise<T> = T extends Thenable<unknown>
>NotPromise : NotPromise<T>
> : ^^^^^^^^^^^^^

? T
: T extends PromiseLike<unknown>
? never
: T;

type Receiver<T> = (value: NotPromise<T>) => void;
>Receiver : Receiver<T>
> : ^^^^^^^^^^^
>value : NotPromise<T>
> : ^^^^^^^^^^^^^

class Thenable<T> {
>Thenable : Thenable<T>
> : ^^^^^^^^^^^

then(a: Receiver<T>) {}
>then : (a: Receiver<T>) => void
> : ^ ^^ ^^^^^^^^^
>a : Receiver<T>
> : ^^^^^^^^^^^

private handleResolve<TResult>(
>handleResolve : <TResult>(result: NotPromise<TResult> | Thenable<NotPromise<TResult>>, resolve: Receiver<TResult>) => void
> : ^ ^^ ^^ ^^ ^^ ^^^^^^^^^

result: NotPromise<TResult> | Thenable<NotPromise<TResult>>,
>result : NotPromise<TResult> | Thenable<NotPromise<TResult>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

resolve: Receiver<TResult>,
>resolve : Receiver<TResult>
> : ^^^^^^^^^^^^^^^^^

) {
if (result instanceof Thenable) {
>result instanceof Thenable : boolean
> : ^^^^^^^
>result : NotPromise<TResult> | Thenable<NotPromise<TResult>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>Thenable : typeof Thenable
> : ^^^^^^^^^^^^^^^

// #58547 This previously was a Debug Failure. False expression: type provided should not be a non-generic 'promise'-like.
this.resolvePromise(result, resolve);
>this.resolvePromise(result, resolve) : void
> : ^^^^
>this.resolvePromise : <TResult_1>(result: Thenable<TResult_1>, resolve: Receiver<TResult_1>) => void
> : ^ ^^ ^^ ^^ ^^ ^^^^^^^^^
>this : this
> : ^^^^
>resolvePromise : <TResult_1>(result: Thenable<TResult_1>, resolve: Receiver<TResult_1>) => void
> : ^ ^^ ^^ ^^ ^^ ^^^^^^^^^
>result : NotPromise<TResult> | Thenable<NotPromise<TResult>>
> : ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>resolve : Receiver<TResult>
> : ^^^^^^^^^^^^^^^^^
}
}

private resolvePromise<TResult>(
>resolvePromise : <TResult>(result: Thenable<TResult>, resolve: Receiver<TResult>) => void
> : ^ ^^ ^^ ^^ ^^ ^^^^^^^^^

result: Thenable<TResult>,
>result : Thenable<TResult>
> : ^^^^^^^^^^^^^^^^^

resolve: Receiver<TResult>,
>resolve : Receiver<TResult>
> : ^^^^^^^^^^^^^^^^^

) {}
}
29 changes: 29 additions & 0 deletions tests/cases/compiler/awaitedTypeNoLib.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// @strictFunctionTypes: true
// @noLib: true

type NotPromise<T> = T extends Thenable<unknown>
? T
: T extends PromiseLike<unknown>
? never
: T;

type Receiver<T> = (value: NotPromise<T>) => void;

class Thenable<T> {
then(a: Receiver<T>) {}

private handleResolve<TResult>(
result: NotPromise<TResult> | Thenable<NotPromise<TResult>>,
resolve: Receiver<TResult>,
) {
if (result instanceof Thenable) {
// #58547 This previously was a Debug Failure. False expression: type provided should not be a non-generic 'promise'-like.
this.resolvePromise(result, resolve);
}
}

private resolvePromise<TResult>(
result: Thenable<TResult>,
resolve: Receiver<TResult>,
) {}
}

0 comments on commit 4da470d

Please sign in to comment.