8000 Strict function types by ahejlsberg · Pull Request #18654 · microsoft/TypeScript · GitHub
[go: up one dir, main page]

Skip to content

Strict function types #18654

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

Merged
merged 25 commits into from
Oct 2, 2017
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
12f5dd8
Introduce --strictFunctionTypes mode
ahejlsberg Sep 18, 2017
f8ff7f7
Use dedicated marker types for variance determination
ahejlsberg Sep 18, 2017
670d711
Add quick path for computing array variance as it is already known
ahejlsberg Sep 18, 2017
a0fa69f
Handle contravariance in type inference
ahejlsberg Sep 19, 2017
b58e0fb
Add comments
ahejlsberg Sep 19, 2017
84f7afd
Handle special case of 'void' type arguments for covariant type param…
ahejlsberg Sep 19, 2017
54eadef
Accept new baselines
ahejlsberg Sep 19, 2017
44cc8c5
Use methods in dom.generated.d.ts to opt out of strict checks
ahejlsberg Sep 19, 2017
dd466ae
Update tsconfig baselines
ahejlsberg Sep 19, 2017
24698dd
Revert dom.generated.d.ts and fix duplicate declarations
ahejlsberg Sep 20, 2017
f8e2cc1
Properly flag and structurally compare marker type references
ahejlsberg Sep 21, 2017
589e1f4
Update comment
ahejlsberg Sep 21, 2017
afc8a26
Always perform structural comparison when variance check fails
ahejlsberg Sep 22, 2017
70e8f73
Add tests
ahejlsberg Sep 22, 2017
91691f6
Strict function type checking only for certain function types
ahejlsberg Sep 25, 2017
6a481e8
Update tests
ahejlsberg Sep 25, 2017
1795614
Accept new baselines
ahejlsberg Sep 26, 2017
5613be4
Only methods and constructors are bivariant in --strictFunctionTypes …
ahejlsberg Sep 28, 2017
1609196
Accept new baselines
ahejlsberg Sep 28, 2017
0756aa1
Merge branch 'master' into strictFunctionTypes
ahejlsberg Sep 28, 2017
c626d9d
Accept new baselines
ahejlsberg Sep 28, 2017
936f98d
Addressing CR feedback
ahejlsberg Sep 29, 2017
bf75a3f
Emit .d.ts file in test
ahejlsberg Oct 2, 2017
bff843a
Improve error elaboration for invariant generic types
ahejlsberg Oct 2, 2017
c2344e0
Add error elaboration test
ahejlsberg Oct 2, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Handle contravariance in type inference
  • Loading branch information
ahejlsberg committed Sep 19, 2017
commit a0fa69ff6c8ffc2ee533407f57ea53d61a28de8c
30 changes: 26 additions & 4 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10129,6 +10129,10 @@ namespace ts {
getUnionType(types, /*subtypeReduction*/ true);
}

function getCommonSubtype(types: Type[]) {
return reduceLeft(types, (s, t) => isTypeSubtypeOf(t, s) ? t : s);
}

function isArrayType(type: Type): boolean {
return getObjectFlags(type) & ObjectFlags.Reference && (<TypeReference>type).target === globalArrayType;
}
Expand Down Expand Up @@ -10655,8 +10659,14 @@ namespace ts {
const sourceTypes = (<TypeReference>source).typeArguments || emptyArray;
const targetTypes = (<TypeReference>target).typeArguments || emptyArray;
const count = sourceTypes.length < targetTypes.length ? sourceTypes.length : targetTypes.length;
const variances = strictFunctionTypes ? getVariances((<TypeReference>source).target) : undefined;
for (let i = 0; i < count; i++) {
inferFromTypes(sourceTypes[i], targetTypes[i]);
if (variances && i < variances.length && variances[i] === Variance.Contravariant) {
inferFromContravariantTypes(sourceTypes[i], targetTypes[i]);
}
else {
inferFromTypes(sourceTypes[i], targetTypes[i]);
}
}
}
else if (source.flags & TypeFlags.Index && target.flags & TypeFlags.Index) {
Expand Down Expand Up @@ -10727,6 +10737,17 @@ namespace ts {
}
}

function inferFromContravariantTypes(source: Type, target: Type) {
if (strictFunctionTypes) {
priority ^= InferencePriority.Contravariant;
inferFromTypes(source, target);
priority ^= InferencePriority.Contravariant;
}
else {
inferFromTypes(source, target);
}
}

function getInferenceInfoForType(type: Type) {
if (type.flags & TypeFlags.TypeVariable) {
for (const inference of inferences) {
Expand Down Expand Up @@ -10804,7 +10825,7 @@ namespace ts {
}

function inferFromSignature(source: Signature, target: Signature) {
forEachMatchingParameterType(source, target, inferFromTypes);
forEachMatchingParameterType(source, target, inferFromContravariantTypes);

if (source.typePredicate && target.typePredicate && source.typePredicate.kind === target.typePredicate.kind) {
inferFromTypes(source.typePredicate.type, target.typePredicate.type);
Expand Down Expand Up @@ -10879,8 +10900,9 @@ namespace ts {
const baseCandidates = widenLiteralTypes ? sameMap(inference.candidates, getWidenedLiteralType) : inference.candidates;
// Infer widened union or supertype, or the unknown type for no common supertype. We infer union types
// for inferences coming from return types in order to avoid common supertype failures.
const unionOrSuperType = context.flags & InferenceFlags.InferUnionTypes || inference.priority & InferencePriority.ReturnType ?
getUnionType(baseCandidates, /*subtypeReduction*/ true) : getCommonSupertype(baseCandidates);
const unionOrSuperType = inference.priority & InferencePriority.Contravariant ? getCommonSubtype(baseCandidates) :
context.flags & InferenceFlags.InferUnionTypes || inference.priority & InferencePriority.ReturnType ? getUnionType(baseCandidates, /*subtypeReduction*/ true) :
getCommonSupertype(baseCandidates);
inferredType = getWidenedType(unionOrSuperType);
}
else if (context.flags & InferenceFlags.NoDefault) {
Expand Down
7 changes: 4 additions & 3 deletions src/compiler/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3532,9 +3532,10 @@ namespace ts {
}

export const enum InferencePriority {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should probably be @internal

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably, but not really related to this PR since the type already existed before. I'm going to leave it be for now.

NakedTypeVariable = 1 << 0, // Naked type variable in union or intersection type
MappedType = 1 << 1, // Reverse inference for mapped type
ReturnType = 1 << 2, // Inference made from return type of generic function
Contravariant = 1 << 0, // Contravariant inference
NakedTypeVariable = 1 << 1, // Naked type variable in union or intersection type
MappedType = 1 << 2, // Reverse inference for mapped type
ReturnType = 1 << 3, // Inference made from return type of generic function
}

export interface InferenceInfo {
Expand Down
0