-
Notifications
You must be signed in to change notification settings - Fork 12.5k
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
Fixed a crash when inferring return type of an accessor with errors in its return statement #56258
Fixed a crash when inferring return type of an accessor with errors in its return statement #56258
Conversation
…n its return statetement
This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise. |
@@ -7312,7 +7312,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { | |||
|
|||
if (propertySymbol.flags & SymbolFlags.Accessor) { | |||
const writeType = getWriteTypeOfSymbol(propertySymbol); | |||
if (propertyType !== writeType) { | |||
if (propertyType !== writeType && !isErrorType(propertyType) && !isErrorType(writeType)) { |
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.
I feel like it might be seen as a little bit of an ad-hoc fix. The problem is that a resolved type of a position with a cycle usually is anyType
but when we are resolving the type initially that type is returned as an error type when the cycle is detected.
So there is some small mismatch between the return values of functions like getTypeOfAccessors
- one that depends on the timing of the call to them. I assume that this is intentional.
I noticed that getWriteTypeOfAccessors
could accidentally-ish return the errorType
and cache it. So I tried to fix it with:
diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index 074c3d3034..59c538e298 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -11758,7 +11758,11 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
writeType = anyType;
}
// Absent an explicit setter type annotation we use the read type of the accessor.
- links.writeType = writeType || getTypeOfAccessors(symbol);
+ if (!writeType) {
+ const readType = getTypeOfAccessors(symbol);
+ writeType = readType !== errorType ? readType : anyType;
+ }
+ links.writeType = writeType;
}
return links.writeType;
}
That didn't fix the issue though because when this line (the one that I'm changing here) was hit for the first time we had a situation like this:
propertyType // errorType
writeType // anyType
So the mismatch was still here - it just happened sooner. Originally, the mismatch could happen later when the property type already had a chance to "settle" as anyType
but the writeType
was already cached as the errorType
.
I think this fix is quite fine since errorType
being returned while resolving the type initially is expected and when that happens we don't quite need to serialize the property as one with divergent accessors. Maybe some further fine-tuning can be done here. I imagine that maybe there is some value in cases that could be serialized as:
export declare var basePrototype: {
get primaryPath(): string;
set primaryPath(v: any); // coming from the error
};
I don't have a test case for that at hand though. This whole issue that is being fixed by this PR is a regression so it's worth fixing it sooner than later 😉
I also think that maybe the patch that I posted above might still be worth pulling in since caching errorType
here looks like something that is not intended. I don't have any test case that would prove it though.
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.
The problem is that a resolved type of a position with a cycle usually is anyType
Maybe my memory is shot, but I kinda thought that we always returned errorType
whenever a cycle occurred? Maybe that's just in the push/pop resolution world?
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.
I don't think there is anything wrong with letting an errorType
propagate further (or get cached or whatever). It exists to act as an any
and to specially handle more permissively in other cases.
(I could be wrong!)
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.
Perhaps this is just somewhat inconsistent across different callers. I see that some similar ones are returning errorType
just fine. However, for example here the cycle is detected and errorType
is returned immediately but when we climb up the stack to the first "visitor" of this type that errorType
is converted to anyType
here. A similar situation ("converting" errorType
to anyType
) can be seen in getTypeOfAccessors
here and in getWriteTypeOfAccessors
here.
I don't think there is anything wrong with letting an errorType propagate further (or get cached or whatever). It exists to act as an any and to specially handle more permissively in other cases.
Ye, it might not be a problem at all. I just tried to follow the pre-existing conventions in other functions.
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.
I'll prepare an experiment later that will just return/cache errorType
in all of those locations that detect the cycle.
@typescript-bot test top200 @typescript-bot perf test this |
Heya @jakebailey, I've started to run the diff-based top-repos suite on this PR at 3802cbe. You can monitor the build here. Update: The results are in! |
Heya @jakebailey, I've started to run the tarball bundle task on this PR at 3802cbe. You can monitor the build here. |
Heya @jakebailey, I've started to run the parallelized Definitely Typed test suite on this PR at 3802cbe. You can monitor the build here. Update: The results are in! |
Heya @jakebailey, I've started to run the regular perf test suite on this PR at 3802cbe. You can monitor the build here. Update: The results are in! |
Heya @jakebailey, I've started to run the diff-based user code test suite on this PR at 3802cbe. You can monitor the build here. Update: The results are in! |
Hey @jakebailey, I've packed this into an installable tgz. You can install it for testing by referencing it in your
and then running |
@jakebailey Here are the results of running the user test suite comparing There were infrastructure failures potentially unrelated to your change:
Otherwise... Something interesting changed - please have a look. Details
|
@jakebailey Here they are:
CompilerComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
tsserverComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
StartupComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
Hey @jakebailey, the results of running the DT tests are ready. |
@jakebailey Here are the results of running the top-repos suite comparing Everything looks good! |
…n its return statement (#56258)
…n its return statement (#56258)
fixes what has been reported here