-
Notifications
You must be signed in to change notification settings - Fork 12.8k
Increase selectivity of subtype relationship for signatures #35659
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
Conversation
Do we likewise now consider |
@weswigham No, but it probably wouldn't be too hard to add. |
@typescript-bot test this |
Heya @ahejlsberg, I've started to run the extended test suite on this PR at 6d67054. You can monitor the build here. It should now contribute to this PR's status checks. |
Heya @ahejlsberg, I've started to run the parallelized community code test suite on this PR at 6d67054. You can monitor the build here. It should now contribute to this PR's status checks. |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at 6d67054. You can monitor the build here. It should now contribute to this PR's status checks. |
Hm, I think I misspoke earlier, though - since |
The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master. |
@typescript-bot test this |
Heya @ahejlsberg, I've started to run the parallelized Definitely Typed test suite on this PR at e60d7ff. You can monitor the build here. It should now contribute to this PR's status checks. |
Heya @ahejlsberg, I've started to run the extended test suite on this PR at e60d7ff. You can monitor the build here. It should now contribute to this PR's status checks. |
Heya @ahejlsberg, I've started to run the perf test suite on this PR at e60d7ff. You can monitor the build here. It should now contribute to this PR's status checks. Update: The results are in! |
Heya @ahejlsberg, I've started to run the parallelized community code test suite on this PR at e60d7ff. You can monitor the build here. It should now contribute to this PR's status checks. |
@ahejlsberg Here they are:Comparison Report - master..35659
System
Hosts
Scenarios
|
The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master. |
@typescript-bot user test this |
Heya @ahejlsberg, I've started to run the parallelized community code test suite on this PR at 7df76b6. You can monitor the build here. It should now contribute to this PR's status checks. |
The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master. |
Summary of impact on test suites:
Overall I think the breaks are acceptable. |
src/compiler/checker.ts
Outdated
@@ -15490,7 +15495,6 @@ namespace ts { | |||
// to X. Failing both of those we want to check if the aggregation of A and B's members structurally | |||
// relates to X. Thus, we include intersection types on the source side here. | |||
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Object) { | |||
// Report structural errors only if we haven't reported any errors yet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you mean to remove this comment?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, I'll put it back.
compareSignaturesRelated(targetSig!, sourceSig!, (checkMode & SignatureCheckMode.StrictArity) | (strictVariance ? SignatureCheckMode.StrictCallback : SignatureCheckMode.BivariantCallback), reportErrors, errorReporter, incompatibleErrorReporter, compareTypes, reportUnreliableMarkers) : | ||
!(checkMode & SignatureCheckMode.Callback) && !strictVariance && compareTypes(sourceType, targetType, /*reportErrors*/ false) || compareTypes(targetType, sourceType, reportErrors); | ||
// With strict arity, (x: number | undefined) => void is a subtype of (x?: number | undefined) => void | ||
if (related && checkMode & SignatureCheckMode.StrictArity && i >= getMinArgumentCount(source) && i < getMinArgumentCount(target) && isTypeIdenticalTo(sourceType, targetType)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the isTypeIdenticalTo
check here for?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Without it a signature like (x?: string | undefined) => void
wouldn't be a subtype of (x: string) => void
. We want it to be such that we reduce a union to just (x: string) => void
. It's basically a tiebreaker for positions with identical types but one with and one without the ?
modifier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
...Mmm, but isTypeIdenticalTo
doesn't seem quite right...? Shouldn't it be compareTypes(sourceType, targetType, /*reportErrors*/ false)
? The difference, I think, should really only be visible, but from what I gather is important when callbacks with optional parameters are the parameter type of callbacks with optional parameters, eg (x?: (x?: string | undefined) => void) => void
and (x: (x: string | undefined) => void) => void
The first should be a subtype of the second because the second's parameter is a subtype of the first's.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, probably better to use compareTypes
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should probably add this cache to getRelationCacheSizes
for diagnostic purposes, too.
This PR introduces a new strict subtype relationship and uses this relationship in union subtype reduction. The new strict subtype relationship increases selectivity for signatures which in turn increases the stability of subtype reduction in union types. Specifically
() => void
is now always considered a strict subtype of(x?: string) => void
(it previously was only for strictly checked function types, see Strict function types #18654), and(x: string | undefined) => void
is now considered a strict subtype of(x?: string) => void
.Beyond these differences, the strict subtype relationship is the same as our existing subtype relationship. Ideally we'd use the new strict subtype relationship everywhere, but to reduce breaking changes we're only using it for union subtype reduction.
An example:
Previously errors were reported in both functions above.
Fixes #35414.