Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port #30856 & #30963 #30966

Merged
merged 2 commits into from Apr 16, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 16 additions & 26 deletions src/compiler/checker.ts
Expand Up @@ -403,10 +403,10 @@ namespace ts {
const wildcardType = createIntrinsicType(TypeFlags.Any, "any");
const errorType = createIntrinsicType(TypeFlags.Any, "error");
const unknownType = createIntrinsicType(TypeFlags.Unknown, "unknown");
const undefinedType = createNullableType(TypeFlags.Undefined, "undefined", 0);
const undefinedWideningType = strictNullChecks ? undefinedType : createNullableType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType);
const nullType = createNullableType(TypeFlags.Null, "null", 0);
const nullWideningType = strictNullChecks ? nullType : createNullableType(TypeFlags.Null, "null", ObjectFlags.ContainsWideningType);
const undefinedType = createIntrinsicType(TypeFlags.Undefined, "undefined");
const undefinedWideningType = strictNullChecks ? undefinedType : createIntrinsicType(TypeFlags.Undefined, "undefined", ObjectFlags.ContainsWideningType);
const nullType = createIntrinsicType(TypeFlags.Null, "null");
const nullWideningType = strictNullChecks ? nullType : createIntrinsicType(TypeFlags.Null, "null", ObjectFlags.ContainsWideningType);
const stringType = createIntrinsicType(TypeFlags.String, "string");
const numberType = createIntrinsicType(TypeFlags.Number, "number");
const bigintType = createIntrinsicType(TypeFlags.BigInt, "bigint");
Expand All @@ -432,6 +432,7 @@ namespace ts {
const voidType = createIntrinsicType(TypeFlags.Void, "void");
const neverType = createIntrinsicType(TypeFlags.Never, "never");
const silentNeverType = createIntrinsicType(TypeFlags.Never, "never");
const nonInferrableType = createIntrinsicType(TypeFlags.Never, "never", ObjectFlags.NonInferrableType);
const implicitNeverType = createIntrinsicType(TypeFlags.Never, "never");
const nonPrimitiveType = createIntrinsicType(TypeFlags.NonPrimitive, "object");
const stringNumberSymbolType = getUnionType([stringType, numberType, esSymbolType]);
Expand All @@ -452,7 +453,7 @@ namespace ts {
const anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
// The anyFunctionType contains the anyFunctionType by definition. The flag is further propagated
// in getPropagatingFlagsOfTypes, and it is checked in inferFromTypes.
anyFunctionType.objectFlags |= ObjectFlags.ContainsAnyFunctionType;
anyFunctionType.objectFlags |= ObjectFlags.NonInferrableType;

const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
const circularConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
Expand Down Expand Up @@ -2753,14 +2754,9 @@ namespace ts {
return result;
}

function createIntrinsicType(kind: TypeFlags, intrinsicName: string): IntrinsicType {
function createIntrinsicType(kind: TypeFlags, intrinsicName: string, objectFlags: ObjectFlags = 0): IntrinsicType {
const type = <IntrinsicType>createType(kind);
type.intrinsicName = intrinsicName;
return type;
}

function createNullableType(kind: TypeFlags, intrinsicName: string, objectFlags: ObjectFlags): NullableType {
const type = createIntrinsicType(kind, intrinsicName);
type.objectFlags = objectFlags;
return type;
}
Expand Down Expand Up @@ -14137,7 +14133,7 @@ namespace ts {
const result = createAnonymousType(type.symbol, members, emptyArray, emptyArray,
stringIndexInfo && createIndexInfo(getWidenedType(stringIndexInfo.type), stringIndexInfo.isReadonly),
numberIndexInfo && createIndexInfo(getWidenedType(numberIndexInfo.type), numberIndexInfo.isReadonly));
result.objectFlags |= (getObjectFlags(type) & ObjectFlags.JSLiteral); // Retain js literal flag through widening
result.objectFlags |= (getObjectFlags(type) & (ObjectFlags.JSLiteral | ObjectFlags.NonInferrableType)); // Retain js literal flag through widening
return result;
}

Expand Down Expand Up @@ -14455,16 +14451,10 @@ namespace ts {
}

function createReverseMappedType(source: Type, target: MappedType, constraint: IndexType) {
const properties = getPropertiesOfType(source);
if (properties.length === 0 && !getIndexInfoOfType(source, IndexKind.String)) {
return undefined;
}
// If any property contains context sensitive functions that have been skipped, the source type
// is incomplete and we can't infer a meaningful input type.
for (const prop of properties) {
if (getObjectFlags(getTypeOfSymbol(prop)) & ObjectFlags.ContainsAnyFunctionType) {
return undefined;
}
if (getObjectFlags(source) & ObjectFlags.NonInferrableType || getPropertiesOfType(source).length === 0 && !getIndexInfoOfType(source, IndexKind.String)) {
return undefined;
}
// For arrays and tuples we infer new arrays and tuples where the reverse mapping has been
// applied to the element type(s).
Expand Down Expand Up @@ -14619,7 +14609,7 @@ namespace ts {
// not contain anyFunctionType when we come back to this argument for its second round
// of inference. Also, we exclude inferences for silentNeverType (which is used as a wildcard
// when constructing types from type parameters that had no inference candidates).
if (getObjectFlags(source) & ObjectFlags.ContainsAnyFunctionType || source === silentNeverType || (priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType))) {
if (getObjectFlags(source) & ObjectFlags.NonInferrableType || source === silentNeverType || (priority & InferencePriority.ReturnType && (source === autoType || source === autoArrayType))) {
return;
}
const inference = getInferenceInfoForType(target);
Expand Down Expand Up @@ -14932,7 +14922,7 @@ namespace ts {
const sourceLen = sourceSignatures.length;
const targetLen = targetSignatures.length;
const len = sourceLen < targetLen ? sourceLen : targetLen;
const skipParameters = !!(getObjectFlags(source) & ObjectFlags.ContainsAnyFunctionType);
const skipParameters = !!(getObjectFlags(source) & ObjectFlags.NonInferrableType);
for (let i = 0; i < len; i++) {
inferFromSignature(getBaseSignature(sourceSignatures[sourceLen - len + i]), getBaseSignature(targetSignatures[targetLen - len + i]), skipParameters);
}
Expand Down Expand Up @@ -21052,7 +21042,7 @@ namespace ts {
// returns a function type, we choose to defer processing. This narrowly permits function composition
// operators to flow inferences through return types, but otherwise processes calls right away. We
// use the resolvingSignature singleton to indicate that we deferred processing. This result will be
// propagated out and eventually turned into silentNeverType (a type that is assignable to anything and
// propagated out and eventually turned into nonInferrableType (a type that is assignable to anything and
// from which we never make inferences).
if (checkMode & CheckMode.SkipGenericFunctions && !node.typeArguments && callSignatures.some(isGenericFunctionReturningFunction)) {
skippedGenericFunction(node, checkMode);
Expand Down Expand Up @@ -21535,8 +21525,8 @@ namespace ts {
const signature = getResolvedSignature(node, /*candidatesOutArray*/ undefined, checkMode);
if (signature === resolvingSignature) {
// CheckMode.SkipGenericFunctions is enabled and this is a call to a generic function that
// returns a function type. We defer checking and return anyFunctionType.
return silentNeverType;
// returns a function type. We defer checking and return nonInferrableType.
return nonInferrableType;
}

if (node.expression.kind === SyntaxKind.SuperKeyword) {
Expand Down Expand Up @@ -22343,7 +22333,7 @@ namespace ts {
const returnType = getReturnTypeFromBody(node, checkMode);
const returnOnlySignature = createSignature(undefined, undefined, undefined, emptyArray, returnType, /*resolvedTypePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
const returnOnlyType = createAnonymousType(node.symbol, emptySymbols, [returnOnlySignature], emptyArray, undefined, undefined);
returnOnlyType.objectFlags |= ObjectFlags.ContainsAnyFunctionType;
returnOnlyType.objectFlags |= ObjectFlags.NonInferrableType;
return links.contextFreeType = returnOnlyType;
}
return anyFunctionType;
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/types.ts
Expand Up @@ -3944,7 +3944,7 @@ namespace ts {
Instantiable = InstantiableNonPrimitive | InstantiablePrimitive,
StructuredOrInstantiable = StructuredType | Instantiable,
/* @internal */
ObjectFlagsType = Nullable | Object | Union | Intersection,
ObjectFlagsType = Nullable | Never | Object | Union | Intersection,
// 'Narrowable' types are types where narrowing actually narrows.
// This *should* be every type other than null, undefined, void, and never
Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive,
Expand Down Expand Up @@ -4064,12 +4064,12 @@ namespace ts {
/* @internal */
ContainsObjectLiteral = 1 << 18, // Type is or contains object literal type
/* @internal */
ContainsAnyFunctionType = 1 << 19, // Type is or contains the anyFunctionType
NonInferrableType = 1 << 19, // Type is or contains anyFunctionType or silentNeverType
ClassOrInterface = Class | Interface,
/* @internal */
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
/* @internal */
PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | ContainsAnyFunctionType
PropagatingFlags = ContainsWideningType | ContainsObjectLiteral | NonInferrableType
}

/* @internal */
Expand Down
46 changes: 46 additions & 0 deletions tests/baselines/reference/genericFunctionInference2.js
@@ -0,0 +1,46 @@
//// [genericFunctionInference2.ts]
// Repro from #30685

type Reducer<S> = (state: S) => S;
declare function combineReducers<S>(reducers: { [K in keyof S]: Reducer<S[K]> }): Reducer<S>;

type MyState = { combined: { foo: number } };
declare const foo: Reducer<MyState['combined']['foo']>;

const myReducer1: Reducer<MyState> = combineReducers({
combined: combineReducers({ foo }),
});

const myReducer2 = combineReducers({
combined: combineReducers({ foo }),
});

// Repro from #30942

declare function withH<T, U>(handlerCreators: HandleCreatorsFactory<T, U>): U;

type Props = { out: number }

type HandleCreatorsFactory<T, U> = (initialProps: T) => { [P in keyof U]: (props: T) => U[P] };

const enhancer4 = withH((props: Props) => ({
onChange: (props) => (e: any) => {},
onSubmit: (props) => (e: any) => {},
}));

enhancer4.onChange(null);


//// [genericFunctionInference2.js]
// Repro from #30685
var myReducer1 = combineReducers({
combined: combineReducers({ foo: foo })
});
var myReducer2 = combineReducers({
combined: combineReducers({ foo: foo })
});
var enhancer4 = withH(function (props) { return ({
onChange: function (props) { return function (e) { }; },
onSubmit: function (props) { return function (e) { }; }
}); });
enhancer4.onChange(null);
108 changes: 108 additions & 0 deletions tests/baselines/reference/genericFunctionInference2.symbols
@@ -0,0 +1,108 @@
=== tests/cases/compiler/genericFunctionInference2.ts ===
// Repro from #30685

type Reducer<S> = (state: S) => S;
>Reducer : Symbol(Reducer, Decl(genericFunctionInference2.ts, 0, 0))
>S : Symbol(S, Decl(genericFunctionInference2.ts, 2, 13))
>state : Symbol(state, Decl(genericFunctionInference2.ts, 2, 19))
>S : Symbol(S, Decl(genericFunctionInference2.ts, 2, 13))
>S : Symbol(S, Decl(genericFunctionInference2.ts, 2, 13))

declare function combineReducers<S>(reducers: { [K in keyof S]: Reducer<S[K]> }): Reducer<S>;
>combineReducers : Symbol(combineReducers, Decl(genericFunctionInference2.ts, 2, 34))
>S : Symbol(S, Decl(genericFunctionInference2.ts, 3, 33))
>reducers : Symbol(reducers, Decl(genericFunctionInference2.ts, 3, 36))
>K : Symbol(K, Decl(genericFunctionInference2.ts, 3, 49))
>S : Symbol(S, Decl(genericFunctionInference2.ts, 3, 33))
>Reducer : Symbol(Reducer, Decl(genericFunctionInference2.ts, 0, 0))
>S : Symbol(S, Decl(genericFunctionInference2.ts, 3, 33))
>K : Symbol(K, Decl(genericFunctionInference2.ts, 3, 49))
>Reducer : Symbol(Reducer, Decl(genericFunctionInference2.ts, 0, 0))
>S : Symbol(S, Decl(genericFunctionInference2.ts, 3, 33))

type MyState = { combined: { foo: number } };
>MyState : Symbol(MyState, Decl(genericFunctionInference2.ts, 3, 93))
>combined : Symbol(combined, Decl(genericFunctionInference2.ts, 5, 16))
>foo : Symbol(foo, Decl(genericFunctionInference2.ts, 5, 28))

declare const foo: Reducer<MyState['combined']['foo']>;
>foo : Symbol(foo, Decl(genericFunctionInference2.ts, 6, 13))
>Reducer : Symbol(Reducer, Decl(genericFunctionInference2.ts, 0, 0))
>MyState : Symbol(MyState, Decl(genericFunctionInference2.ts, 3, 93))

const myReducer1: Reducer<MyState> = combineReducers({
>myReducer1 : Symbol(myReducer1, Decl(genericFunctionInference2.ts, 8, 5))
>Reducer : Symbol(Reducer, Decl(genericFunctionInference2.ts, 0, 0))
>MyState : Symbol(MyState, Decl(genericFunctionInference2.ts, 3, 93))
>combineReducers : Symbol(combineReducers, Decl(genericFunctionInference2.ts, 2, 34))

combined: combineReducers({ foo }),
>combined : Symbol(combined, Decl(genericFunctionInference2.ts, 8, 54))
>combineReducers : Symbol(combineReducers, Decl(genericFunctionInference2.ts, 2, 34))
>foo : Symbol(foo, Decl(genericFunctionInference2.ts, 9, 31))

});

const myReducer2 = combineReducers({
>myReducer2 : Symbol(myReducer2, Decl(genericFunctionInference2.ts, 12, 5))
>combineReducers : Symbol(combineReducers, Decl(genericFunctionInference2.ts, 2, 34))

combined: combineReducers({ foo }),
>combined : Symbol(combined, Decl(genericFunctionInference2.ts, 12, 36))
>combineReducers : Symbol(combineReducers, Decl(genericFunctionInference2.ts, 2, 34))
>foo : Symbol(foo, Decl(genericFunctionInference2.ts, 13, 31))

});

// Repro from #30942

declare function withH<T, U>(handlerCreators: HandleCreatorsFactory<T, U>): U;
>withH : Symbol(withH, Decl(genericFunctionInference2.ts, 14, 3))
>T : Symbol(T, Decl(genericFunctionInference2.ts, 18, 23))
>U : Symbol(U, Decl(genericFunctionInference2.ts, 18, 25))
>handlerCreators : Symbol(handlerCreators, Decl(genericFunctionInference2.ts, 18, 29))
>HandleCreatorsFactory : Symbol(HandleCreatorsFactory, Decl(genericFunctionInference2.ts, 20, 28))
>T : Symbol(T, Decl(genericFunctionInference2.ts, 18, 23))
>U : Symbol(U, Decl(genericFunctionInference2.ts, 18, 25))
>U : Symbol(U, Decl(genericFunctionInference2.ts, 18, 25))

type Props = { out: number }
>Props : Symbol(Props, Decl(genericFunctionInference2.ts, 18, 78))
>out : Symbol(out, Decl(genericFunctionInference2.ts, 20, 14))

type HandleCreatorsFactory<T, U> = (initialProps: T) => { [P in keyof U]: (props: T) => U[P] };
>HandleCreatorsFactory : Symbol(HandleCreatorsFactory, Decl(genericFunctionInference2.ts, 20, 28))
>T : Symbol(T, Decl(genericFunctionInference2.ts, 22, 27))
>U : Symbol(U, Decl(genericFunctionInference2.ts, 22, 29))
>initialProps : Symbol(initialProps, Decl(genericFunctionInference2.ts, 22, 36))
>T : Symbol(T, Decl(genericFunctionInference2.ts, 22, 27))
>P : Symbol(P, Decl(genericFunctionInference2.ts, 22, 59))
>U : Symbol(U, Decl(genericFunctionInference2.ts, 22, 29))
>props : Symbol(props, Decl(genericFunctionInference2.ts, 22, 75))
>T : Symbol(T, Decl(genericFunctionInference2.ts, 22, 27))
>U : Symbol(U, Decl(genericFunctionInference2.ts, 22, 29))
>P : Symbol(P, Decl(genericFunctionInference2.ts, 22, 59))

const enhancer4 = withH((props: Props) => ({
>enhancer4 : Symbol(enhancer4, Decl(genericFunctionInference2.ts, 24, 5))
>withH : Symbol(withH, Decl(genericFunctionInference2.ts, 14, 3))
>props : Symbol(props, Decl(genericFunctionInference2.ts, 24, 25))
>Props : Symbol(Props, Decl(genericFunctionInference2.ts, 18, 78))

onChange: (props) => (e: any) => {},
>onChange : Symbol(onChange, Decl(genericFunctionInference2.ts, 24, 44))
>props : Symbol(props, Decl(genericFunctionInference2.ts, 25, 15))
>e : Symbol(e, Decl(genericFunctionInference2.ts, 25, 26))

onSubmit: (props) => (e: any) => {},
>onSubmit : Symbol(onSubmit, Decl(genericFunctionInference2.ts, 25, 40))
>props : Symbol(props, Decl(genericFunctionInference2.ts, 26, 15))
>e : Symbol(e, Decl(genericFunctionInference2.ts, 26, 26))

}));

enhancer4.onChange(null);
>enhancer4.onChange : Symbol(onChange, Decl(genericFunctionInference2.ts, 24, 44))
>enhancer4 : Symbol(enhancer4, Decl(genericFunctionInference2.ts, 24, 5))
>onChange : Symbol(onChange, Decl(genericFunctionInference2.ts, 24, 44))