Skip to content

Fixed a crash when inferring return type of an accessor with errors in its return statement - #56258

Merged
Daniel Rosenwasser (DanielRosenwasser) merged 1 commit into
microsoft:mainfrom
Andarist:fix/crash-accessor-serialization
Nov 16, 2023
Merged

Fixed a crash when inferring return type of an accessor with errors in its return statement#56258
Daniel Rosenwasser (DanielRosenwasser) merged 1 commit into
microsoft:mainfrom
Andarist:fix/crash-accessor-serialization

Conversation

@Andarist

Copy link
Copy Markdown
Contributor

fixes what has been reported here

@typescript-botTypeScript Bot (typescript-bot) added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Oct 30, 2023
@typescript-bot

Copy link
Copy Markdown
Contributor

This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise.

if (propertySymbol.flags & SymbolFlags.Accessor) {
const writeType = getWriteTypeOfSymbol(propertySymbol);
if (propertyType !== writeType) {
if (propertyType !== writeType && !isErrorType(propertyType) && !isErrorType(writeType)) {

Copy link
Copy Markdown
ContributorAuthor

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 errorTypeand 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// errorTypewriteType// 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:

exportdeclarevarbasePrototype: {getprimaryPath(): string;setprimaryPath(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.

Copy link
Copy Markdown
Member

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?

@DanielRosenwasserDaniel Rosenwasser (DanielRosenwasser)Nov 14, 2023

Copy link
Copy Markdown
Member

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!)

Copy link
Copy Markdown
ContributorAuthor

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 anyTypehere. A similar situation ("converting" errorType to anyType) can be seen in getTypeOfAccessorshere and in getWriteTypeOfAccessorshere.

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.

Copy link
Copy Markdown
ContributorAuthor

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.

@AndaristMateusz Burzyński (Andarist) changed the title Fixed a crash when inferring return type of an accessor with errors in its return statetementFixed a crash when inferring return type of an accessor with errors in its return statementNov 13, 2023
@jakebailey

Copy link
Copy Markdown
Member

@typescript-bot

TypeScript Bot (typescript-bot) commented Nov 14, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@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!

@typescript-bot

TypeScript Bot (typescript-bot) commented Nov 14, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@jakebailey), I've started to run the tarball bundle task on this PR at 3802cbe. You can monitor the build here.

@typescript-bot

TypeScript Bot (typescript-bot) commented Nov 14, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@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!

@typescript-bot

TypeScript Bot (typescript-bot) commented Nov 14, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@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!

@typescript-bot

TypeScript Bot (typescript-bot) commented Nov 14, 2023

Copy link
Copy Markdown
Contributor

Heya Jake Bailey (@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!

@typescript-bot

Copy link
Copy Markdown
Contributor

Hey Jake Bailey (@jakebailey), I've packed this into an installable tgz. You can install it for testing by referencing it in your package.json like so:

{
"devDependencies": {
"typescript": "https://typescript.visualstudio.com/cf7ac146-d525-443c-b23c-0d58337efebc/_apis/build/builds/158586/artifacts?artifactName=tgz&fileId=87066A8BCA66B8EE26BD12594FADBDE17762947288735EF839E565FE69496E0502&fileName=/typescript-5.4.0-insiders.20231114.tgz"
}
}

and then running npm install.

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the user test suite comparing main and refs/pull/56258/merge:

There were infrastructure failures potentially unrelated to your change:

  • 2 instances of "Package install failed"

Otherwise...

Something interesting changed - please have a look.

Details

puppeteer

packages/browsers/test/src/tsconfig.json

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey)
The results of the perf run you requested are in!

Here they are:

Compiler

Comparison Report - baseline..pr
MetricbaselineprDeltaBestWorstp-value
Angular - node (v18.15.0, x64)
Memory used295,162k (± 0.01%)295,197k (± 0.01%)+35k (+ 0.01%)295,163k295,216kp=0.020 n=6
Parse Time2.64s (± 0.31%)2.65s (± 0.37%)~2.64s2.66sp=0.498 n=6
Bind Time0.82s (± 1.20%)0.83s (± 1.01%)~0.82s0.84sp=0.445 n=6
Check Time8.04s (± 0.23%)8.03s (± 0.35%)~8.00s8.08sp=0.624 n=6
Emit Time7.07s (± 0.17%)7.09s (± 0.21%)~7.07s7.11sp=0.073 n=6
Total Time18.57s (± 0.16%)18.59s (± 0.16%)~18.56s18.63sp=0.416 n=6
Compiler-Unions - node (v18.15.0, x64)
Memory used190,700k (± 0.01%)192,626k (± 1.54%)~190,687k196,473kp=0.471 n=6
Parse Time1.36s (± 0.98%)1.35s (± 1.01%)~1.34s1.38sp=0.282 n=6
Bind Time0.72s (± 0.00%)0.72s (± 0.57%)~0.72s0.73sp=0.405 n=6
Check Time9.17s (± 0.29%)9.18s (± 0.21%)~9.15s9.20sp=0.681 n=6
Emit Time2.63s (± 0.62%)2.62s (± 0.56%)~2.60s2.64sp=0.413 n=6
Total Time13.88s (± 0.28%)13.87s (± 0.17%)~13.83s13.89sp=0.808 n=6
Monaco - node (v18.15.0, x64)
Memory used347,355k (± 0.00%)347,356k (± 0.00%)~347,328k347,377kp=1.000 n=6
Parse Time2.45s (± 0.54%)2.46s (± 0.21%)~2.45s2.46sp=0.546 n=6
Bind Time0.92s (± 0.59%)0.92s (± 0.59%)~0.92s0.93sp=1.000 n=6
Check Time6.94s (± 0.50%)6.92s (± 0.41%)~6.88s6.97sp=0.683 n=6
Emit Time4.07s (± 0.57%)4.05s (± 0.43%)~4.02s4.07sp=0.106 n=6
Total Time14.38s (± 0.36%)14.35s (± 0.25%)~14.32s14.41sp=0.297 n=6
TFS - node (v18.15.0, x64)
Memory used302,652k (± 0.01%)302,667k (± 0.01%)~302,618k302,731kp=0.471 n=6
Parse Time2.00s (± 1.08%)1.99s (± 1.13%)~1.96s2.03sp=0.413 n=6
Bind Time1.00s (± 0.41%)1.00s (± 0.41%)~0.99s1.00sp=1.000 n=6
Check Time6.27s (± 0.55%)6.28s (± 0.60%)~6.23s6.32sp=0.809 n=6
Emit Time3.58s (± 0.54%)3.58s (± 0.70%)~3.55s3.62sp=0.515 n=6
Total Time12.85s (± 0.39%)12.86s (± 0.38%)~12.79s12.92sp=0.872 n=6
material-ui - node (v18.15.0, x64)
Memory used470,551k (± 0.01%)470,536k (± 0.01%)~470,501k470,574kp=0.520 n=6
Parse Time2.57s (± 0.58%)2.58s (± 0.57%)~2.56s2.60sp=0.676 n=6
Bind Time0.98s (± 1.23%)0.99s (± 0.99%)~0.98s1.01sp=0.340 n=6
Check Time16.67s (± 0.30%)16.64s (± 0.61%)~16.47s16.76sp=0.748 n=6
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)~0.00s0.00sp=1.000 n=6
Total Time20.22s (± 0.24%)20.21s (± 0.54%)~20.03s20.33sp=1.000 n=6
xstate - node (v18.15.0, x64)
Memory used512,838k (± 0.01%)512,820k (± 0.01%)~512,743k512,908kp=0.689 n=6
Parse Time3.27s (± 0.23%)3.27s (± 0.16%)~3.27s3.28sp=0.241 n=6
Bind Time1.54s (± 0.53%)1.54s (± 0.90%)~1.51s1.55sp=0.932 n=6
Check Time2.85s (± 0.44%)2.86s (± 0.69%)~2.83s2.89sp=0.868 n=6
Emit Time0.08s (± 4.99%)0.08s (± 0.00%)~0.08s0.08sp=0.405 n=6
Total Time7.73s (± 0.18%)7.74s (± 0.29%)~7.72s7.77sp=0.686 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • Angular - node (v18.15.0, x64)
  • Compiler-Unions - node (v18.15.0, x64)
  • Monaco - node (v18.15.0, x64)
  • TFS - node (v18.15.0, x64)
  • material-ui - node (v18.15.0, x64)
  • xstate - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

tsserver

Comparison Report - baseline..pr
MetricbaselineprDeltaBestWorstp-value
Compiler-UnionsTSServer - node (v18.15.0, x64)
Req 1 - updateOpen2,362ms (± 0.53%)2,373ms (± 0.57%)~2,353ms2,389msp=0.336 n=6
Req 2 - geterr5,369ms (± 1.31%)5,385ms (± 1.54%)~5,310ms5,493msp=0.575 n=6
Req 3 - references326ms (± 0.94%)326ms (± 0.61%)~323ms329msp=1.000 n=6
Req 4 - navto278ms (± 1.20%)277ms (± 1.17%)~273ms280msp=0.615 n=6
Req 5 - completionInfo count1,356 (± 0.00%)1,356 (± 0.00%)~1,3561,356p=1.000 n=6
Req 5 - completionInfo83ms (± 6.81%)82ms (± 8.03%)~75ms90msp=0.466 n=6
CompilerTSServer - node (v18.15.0, x64)
Req 1 - updateOpen2,504ms (± 0.71%)2,484ms (± 0.82%)~2,455ms2,519msp=0.173 n=6
Req 2 - geterr4,059ms (± 1.52%)4,149ms (± 1.19%)~4,049ms4,184msp=0.066 n=6
Req 3 - references342ms (± 1.31%)336ms (± 1.43%)~332ms345msp=0.145 n=6
Req 4 - navto283ms (± 0.27%)282ms (± 0.48%)~280ms284msp=0.273 n=6
Req 5 - completionInfo count1,518 (± 0.00%)1,518 (± 0.00%)~1,5181,518p=1.000 n=6
Req 5 - completionInfo88ms (± 5.01%)80ms (± 6.43%)🟩-8ms (- 9.30%)77ms90msp=0.029 n=6
xstateTSServer - node (v18.15.0, x64)
Req 1 - updateOpen2,598ms (± 0.25%)2,593ms (± 0.22%)~2,585ms2,602msp=0.289 n=6
Req 2 - geterr1,733ms (± 1.84%)1,708ms (± 2.17%)~1,663ms1,746msp=0.335 n=6
Req 3 - references114ms (± 9.27%)116ms (± 9.17%)~101ms123msp=0.935 n=6
Req 4 - navto367ms (± 1.12%)366ms (± 0.44%)~364ms368msp=1.000 n=6
Req 5 - completionInfo count2,073 (± 0.00%)2,073 (± 0.00%)~2,0732,073p=1.000 n=6
Req 5 - completionInfo310ms (± 1.70%)311ms (± 1.50%)~305ms316msp=0.686 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • CompilerTSServer - node (v18.15.0, x64)
  • Compiler-UnionsTSServer - node (v18.15.0, x64)
  • xstateTSServer - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

Startup

Comparison Report - baseline..pr
MetricbaselineprDeltaBestWorstp-value
tsc-startup - node (v18.15.0, x64)
Execution time152.48ms (± 0.17%)152.54ms (± 0.17%)+0.06ms (+ 0.04%)151.15ms154.61msp=0.022 n=600
tsserver-startup - node (v18.15.0, x64)
Execution time227.81ms (± 0.14%)227.64ms (± 0.17%)-0.17ms (- 0.08%)226.16ms232.00msp=0.000 n=600
tsserverlibrary-startup - node (v18.15.0, x64)
Execution time228.76ms (± 0.17%)228.81ms (± 0.24%)~227.13ms246.63msp=0.620 n=600
typescript-startup - node (v18.15.0, x64)
Execution time228.97ms (± 0.18%)228.85ms (± 0.16%)-0.12ms (- 0.05%)227.41ms231.99msp=0.006 n=600
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • tsc-startup - node (v18.15.0, x64)
  • tsserver-startup - node (v18.15.0, x64)
  • tsserverlibrary-startup - node (v18.15.0, x64)
  • typescript-startup - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

Developer Information:

Download Benchmarks

@typescript-bot

Copy link
Copy Markdown
Contributor

Hey Jake Bailey (@jakebailey), the results of running the DT tests are ready.
Everything looks the same!
You can check the log here.

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the top-repos suite comparing main and refs/pull/56258/merge:

Everything looks good!

Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

For Uncommitted BugPR for untriaged, rejected, closed or missing bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@Andarist@typescript-bot@jakebailey@DanielRosenwasser