Skip to content

Commit

Permalink
Report implict any error when widening null/undefined in presence of … (
Browse files Browse the repository at this point in the history
  • Loading branch information
rbuckton authored Sep 26, 2024
1 parent 825826f commit 25ab551
Show file tree
Hide file tree
Showing 9 changed files with 363 additions and 12 deletions.
38 changes: 33 additions & 5 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25674,7 +25674,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
case SyntaxKind.ArrowFunction:
if (noImplicitAny && !(declaration as NamedDeclaration).name) {
if (wideningKind === WideningKind.GeneratorYield) {
error(declaration, Diagnostics.Generator_implicitly_has_yield_type_0_because_it_does_not_yield_any_values_Consider_supplying_a_return_type_annotation, typeAsString);
error(declaration, Diagnostics.Generator_implicitly_has_yield_type_0_Consider_supplying_a_return_type_annotation, typeAsString);
}
else {
error(declaration, Diagnostics.Function_expression_which_lacks_return_type_annotation_implicitly_has_an_0_return_type, typeAsString);
Expand All @@ -25696,12 +25696,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
errorOrSuggestion(noImplicitAny, declaration, diagnostic, declarationNameToString(getNameOfDeclaration(declaration)), typeAsString);
}

function shouldReportErrorsFromWideningWithContextualSignature(declaration: FunctionLikeDeclaration, wideningKind: WideningKind) {
const signature = getContextualSignatureForFunctionLikeDeclaration(declaration);
if (!signature) {
return true;
}
let returnType = getReturnTypeOfSignature(signature);
const flags = getFunctionFlags(declaration);
switch (wideningKind) {
case WideningKind.FunctionReturn:
if (flags & FunctionFlags.Generator) {
returnType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Return, returnType, !!(flags & FunctionFlags.Async)) ?? returnType;
}
else if (flags & FunctionFlags.Async) {
returnType = getAwaitedTypeNoAlias(returnType) ?? returnType;
}
return isGenericType(returnType);
case WideningKind.GeneratorYield:
const yieldType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Yield, returnType, !!(flags & FunctionFlags.Async));
return !!yieldType && isGenericType(yieldType);
case WideningKind.GeneratorNext:
const nextType = getIterationTypeOfGeneratorFunctionReturnType(IterationTypeKind.Next, returnType, !!(flags & FunctionFlags.Async));
return !!nextType && isGenericType(nextType);
}
return false;
}

function reportErrorsFromWidening(declaration: Declaration, type: Type, wideningKind?: WideningKind) {
addLazyDiagnostic(() => {
if (noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType && (!wideningKind || !getContextualSignatureForFunctionLikeDeclaration(declaration as FunctionLikeDeclaration))) {
// Report implicit any error within type if possible, otherwise report error on declaration
if (!reportWideningErrorsInType(type)) {
reportImplicitAny(declaration, type, wideningKind);
if (noImplicitAny && getObjectFlags(type) & ObjectFlags.ContainsWideningType) {
if (!wideningKind || isFunctionLikeDeclaration(declaration) && shouldReportErrorsFromWideningWithContextualSignature(declaration, wideningKind)) {
// Report implicit any error within type if possible, otherwise report error on declaration
if (!reportWideningErrorsInType(type)) {
reportImplicitAny(declaration, type, wideningKind);
}
}
}
});
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -6667,7 +6667,7 @@
"category": "Error",
"code": 7024
},
"Generator implicitly has yield type '{0}' because it does not yield any values. Consider supplying a return type annotation.": {
"Generator implicitly has yield type '{0}'. Consider supplying a return type annotation.": {
"category": "Error",
"code": 7025
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ generatorReturnTypeInferenceNonStrict.ts(74,15): error TS7057: 'yield' expressio
generatorReturnTypeInferenceNonStrict.ts(79,11): error TS7055: 'g301', which lacks return-type annotation, implicitly has an 'any' yield type.
generatorReturnTypeInferenceNonStrict.ts(89,11): error TS7055: 'g303', which lacks return-type annotation, implicitly has an 'any' yield type.
generatorReturnTypeInferenceNonStrict.ts(126,11): error TS7055: 'g310', which lacks return-type annotation, implicitly has an 'any' yield type.
generatorReturnTypeInferenceNonStrict.ts(131,10): error TS7025: Generator implicitly has yield type 'any' because it does not yield any values. Consider supplying a return type annotation.
generatorReturnTypeInferenceNonStrict.ts(131,10): error TS7025: Generator implicitly has yield type 'any'. Consider supplying a return type annotation.


==== generatorReturnTypeInferenceNonStrict.ts (7 errors) ====
Expand Down Expand Up @@ -152,7 +152,7 @@ generatorReturnTypeInferenceNonStrict.ts(131,10): error TS7025: Generator implic
function* g311() { // Generator<any (implicit), void, string>
yield* (function*() {
~~~~~~~~
!!! error TS7025: Generator implicitly has yield type 'any' because it does not yield any values. Consider supplying a return type annotation.
!!! error TS7025: Generator implicitly has yield type 'any'. Consider supplying a return type annotation.
const y: string = yield;
})();
}
Expand Down
5 changes: 4 additions & 1 deletion tests/baselines/reference/generatorTypeCheck62.errors.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@ generatorTypeCheck62.ts(32,62): error TS2345: Argument of type '(state: State) =
Type 'IteratorReturnResult<State>' is not assignable to type 'IteratorResult<any, void>'.
Type 'IteratorReturnResult<State>' is not assignable to type 'IteratorReturnResult<void>'.
Type 'State' is not assignable to type 'void'.
generatorTypeCheck62.ts(32,62): error TS7025: Generator implicitly has yield type 'any'. Consider supplying a return type annotation.


==== generatorTypeCheck62.ts (2 errors) ====
==== generatorTypeCheck62.ts (3 errors) ====
export interface StrategicState {
lastStrategyApplied?: string;
}
Expand Down Expand Up @@ -63,6 +64,8 @@ generatorTypeCheck62.ts(32,62): error TS2345: Argument of type '(state: State) =
!!! error TS2345: Type 'IteratorReturnResult<State>' is not assignable to type 'IteratorResult<any, void>'.
!!! error TS2345: Type 'IteratorReturnResult<State>' is not assignable to type 'IteratorReturnResult<void>'.
!!! error TS2345: Type 'State' is not assignable to type 'void'.
~~~~~~~~
!!! error TS7025: Generator implicitly has yield type 'any'. Consider supplying a return type annotation.
yield ;
return state; // `return`/`TReturn` isn't supported by `strategy`, so this should error.
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
implicitAnyGenericTypeInference.ts(10,4): error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.
implicitAnyGenericTypeInference.ts(13,4): error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.
implicitAnyGenericTypeInference.ts(16,4): error TS7025: Generator implicitly has yield type 'any'. Consider supplying a return type annotation.
implicitAnyGenericTypeInference.ts(19,4): error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.
implicitAnyGenericTypeInference.ts(22,4): error TS7025: Generator implicitly has yield type 'any'. Consider supplying a return type annotation.
implicitAnyGenericTypeInference.ts(25,4): error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.
implicitAnyGenericTypeInference.ts(28,25): error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.
implicitAnyGenericTypeInference.ts(29,24): error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.


==== implicitAnyGenericTypeInference.ts (8 errors) ====
interface Comparer<T> {
compareTo<U>(x: T, y: U): U;
}

var c: Comparer<any>;
c = { compareTo: (x, y) => { return y; } };
var r = c.compareTo(1, '');

declare function f1<T>(cb: () => T): void;
f1(() => null);
~~~~~~~~~~
!!! error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.

declare function f2<T>(cb: () => PromiseLike<T>): void;
f2(async () => null);
~~~~~~~~~~~~~~~~
!!! error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.

declare function f3<T>(cb: () => Generator<T>): void;
f3(function* () { yield null; });
~~~~~~~~
!!! error TS7025: Generator implicitly has yield type 'any'. Consider supplying a return type annotation.

declare function f4<T>(cb: () => Generator<unknown, T>): void;
f4(function* () { return null; });
~~~~~~~~
!!! error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.

declare function f5<T>(cb: () => AsyncGenerator<T>): void;
f5(async function* () { yield null; });
~~~~~
!!! error TS7025: Generator implicitly has yield type 'any'. Consider supplying a return type annotation.

declare function f6<T>(cb: () => AsyncGenerator<unknown, T>): void;
f6(async function* () { return null; });
~~~~~
!!! error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.

// https://github.com/microsoft/TypeScript/issues/44913
Promise.resolve().catch(e => null);
~~~~~~~~~
!!! error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.
Promise.resolve().then(v => null);
~~~~~~~~~
!!! error TS7011: Function expression, which lacks return-type annotation, implicitly has an 'any' return type.
35 changes: 33 additions & 2 deletions tests/baselines/reference/implicitAnyGenericTypeInference.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,40 @@ interface Comparer<T> {

var c: Comparer<any>;
c = { compareTo: (x, y) => { return y; } };
var r = c.compareTo(1, '');
var r = c.compareTo(1, '');

declare function f1<T>(cb: () => T): void;
f1(() => null);

declare function f2<T>(cb: () => PromiseLike<T>): void;
f2(async () => null);

declare function f3<T>(cb: () => Generator<T>): void;
f3(function* () { yield null; });

declare function f4<T>(cb: () => Generator<unknown, T>): void;
f4(function* () { return null; });

declare function f5<T>(cb: () => AsyncGenerator<T>): void;
f5(async function* () { yield null; });

declare function f6<T>(cb: () => AsyncGenerator<unknown, T>): void;
f6(async function* () { return null; });

// https://github.com/microsoft/TypeScript/issues/44913
Promise.resolve().catch(e => null);
Promise.resolve().then(v => null);

//// [implicitAnyGenericTypeInference.js]
var c;
c = { compareTo: function (x, y) { return y; } };
c = { compareTo: (x, y) => { return y; } };
var r = c.compareTo(1, '');
f1(() => null);
f2(async () => null);
f3(function* () { yield null; });
f4(function* () { return null; });
f5(async function* () { yield null; });
f6(async function* () { return null; });
// https://github.com/microsoft/TypeScript/issues/44913
Promise.resolve().catch(e => null);
Promise.resolve().then(v => null);
76 changes: 76 additions & 0 deletions tests/baselines/reference/implicitAnyGenericTypeInference.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,79 @@ var r = c.compareTo(1, '');
>c : Symbol(c, Decl(implicitAnyGenericTypeInference.ts, 4, 3))
>compareTo : Symbol(Comparer.compareTo, Decl(implicitAnyGenericTypeInference.ts, 0, 23))

declare function f1<T>(cb: () => T): void;
>f1 : Symbol(f1, Decl(implicitAnyGenericTypeInference.ts, 6, 27))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 8, 20))
>cb : Symbol(cb, Decl(implicitAnyGenericTypeInference.ts, 8, 23))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 8, 20))

f1(() => null);
>f1 : Symbol(f1, Decl(implicitAnyGenericTypeInference.ts, 6, 27))

declare function f2<T>(cb: () => PromiseLike<T>): void;
>f2 : Symbol(f2, Decl(implicitAnyGenericTypeInference.ts, 9, 15))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 11, 20))
>cb : Symbol(cb, Decl(implicitAnyGenericTypeInference.ts, 11, 23))
>PromiseLike : Symbol(PromiseLike, Decl(lib.es5.d.ts, --, --))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 11, 20))

f2(async () => null);
>f2 : Symbol(f2, Decl(implicitAnyGenericTypeInference.ts, 9, 15))

declare function f3<T>(cb: () => Generator<T>): void;
>f3 : Symbol(f3, Decl(implicitAnyGenericTypeInference.ts, 12, 21))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 14, 20))
>cb : Symbol(cb, Decl(implicitAnyGenericTypeInference.ts, 14, 23))
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 14, 20))

f3(function* () { yield null; });
>f3 : Symbol(f3, Decl(implicitAnyGenericTypeInference.ts, 12, 21))

declare function f4<T>(cb: () => Generator<unknown, T>): void;
>f4 : Symbol(f4, Decl(implicitAnyGenericTypeInference.ts, 15, 33))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 17, 20))
>cb : Symbol(cb, Decl(implicitAnyGenericTypeInference.ts, 17, 23))
>Generator : Symbol(Generator, Decl(lib.es2015.generator.d.ts, --, --))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 17, 20))

f4(function* () { return null; });
>f4 : Symbol(f4, Decl(implicitAnyGenericTypeInference.ts, 15, 33))

declare function f5<T>(cb: () => AsyncGenerator<T>): void;
>f5 : Symbol(f5, Decl(implicitAnyGenericTypeInference.ts, 18, 34))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 20, 20))
>cb : Symbol(cb, Decl(implicitAnyGenericTypeInference.ts, 20, 23))
>AsyncGenerator : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 20, 20))

f5(async function* () { yield null; });
>f5 : Symbol(f5, Decl(implicitAnyGenericTypeInference.ts, 18, 34))

declare function f6<T>(cb: () => AsyncGenerator<unknown, T>): void;
>f6 : Symbol(f6, Decl(implicitAnyGenericTypeInference.ts, 21, 39))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 23, 20))
>cb : Symbol(cb, Decl(implicitAnyGenericTypeInference.ts, 23, 23))
>AsyncGenerator : Symbol(AsyncGenerator, Decl(lib.es2018.asyncgenerator.d.ts, --, --))
>T : Symbol(T, Decl(implicitAnyGenericTypeInference.ts, 23, 20))

f6(async function* () { return null; });
>f6 : Symbol(f6, Decl(implicitAnyGenericTypeInference.ts, 21, 39))

// https://github.com/microsoft/TypeScript/issues/44913
Promise.resolve().catch(e => null);
>Promise.resolve().catch : Symbol(Promise.catch, Decl(lib.es5.d.ts, --, --))
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
>catch : Symbol(Promise.catch, Decl(lib.es5.d.ts, --, --))
>e : Symbol(e, Decl(implicitAnyGenericTypeInference.ts, 27, 24))

Promise.resolve().then(v => null);
>Promise.resolve().then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --))
>Promise.resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2018.promise.d.ts, --, --))
>resolve : Symbol(PromiseConstructor.resolve, Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --))
>then : Symbol(Promise.then, Decl(lib.es5.d.ts, --, --))
>v : Symbol(v, Decl(implicitAnyGenericTypeInference.ts, 28, 23))

Loading

0 comments on commit 25ab551

Please sign in to comment.