Skip to content

Handle recursive type references up to a certain level of expansion in inference - #38011

Merged
weswigham merged 3 commits into
microsoft:masterfrom
weswigham:recursive-type-reference-inference-mk2
Jun 24, 2020
Merged

Handle recursive type references up to a certain level of expansion in inference#38011
weswigham merged 3 commits into
microsoft:masterfrom
weswigham:recursive-type-reference-inference-mk2

Conversation

@weswigham

Copy link
Copy Markdown
Member

Fixes#37982, which regressed with #33678 which this modifies.

When #33678 moved inference of recursive type references into inferFromObjectTypesWorker, it implicitly forbade all nested inferences from nested recursive types of the same target. Eg, if you have a Recursive<string | Recursive<boolean>>, it prevented any inference from occurring on the inner reference. With this change to the circularity checking logic in inferFromObjectTypes (and expanded isDeeplyNestedType to handle expanding recursive type references), we can now make inferences multiple times as the reference expands (if it does), up to a limit. (Namely 5 expansions - the same limit we have in place in relationship checking).

const isNonConstructorObject = target.flags & TypeFlags.Object &&
!(getObjectFlags(target) & ObjectFlags.Anonymous && target.symbol && target.symbol.flags & SymbolFlags.Class);
const symbolOrType = isNonConstructorObject ? isTupleType(target) ? target.target : target.symbol : undefined;
const symbolOrType = getObjectFlags(target) & ObjectFlags.Reference && (target as TypeReference).node ? getNormalizedType(target, /*writing*/ false) : isNonConstructorObject ? isTupleType(target) ? target.target : target.symbol : undefined;

Copy link
Copy Markdown
MemberAuthor

Choose a reason for hiding this comment

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

This line (and the bail without setting Circularity below) essentially "undoes" #33678 insofar as if I only made this change, #37982 would be fixed (as now we'd explore all recursive type references so long as their normalized forms aren't identical), however doing just that reintroduces the issue #33678 fixed, since in that case, we have something like type T = [A<NonNullable<T>>] which expands to [A<NonNullable<NonNullable<T>>>] and so on. As it expands, at no point are the types "identical" (notable future work: collapsing noop conditional types like repeated NonNullable!), in fact, all that's shared is that the type reference is sourced from the same .target and .node. So when it was eliminating the recursion based on .target alone. it was essentially saying "you can't infer to a 1-tuple while inferring to a 1-tuple, if that 1-tuple is marked as recursive" (which, while in line with how limited inference is for other symbol-based object types without #31633, is a regression in behavior for recursive type references), which, in turn, meant you couldn't infer to, say, the second Q reference of [Q<string>, [Q<boolean | number>]] if Q caused the containing tuples to be marked as potentially recursive!

All this to say: the change in behavior was a direct consequence of two things: #33678 limited recursive type reference inference, and recursive type references are made syntactically, so they way they are declared changes if they're marked as potentially recursive or not, resulting in the differences noted in #37982. So the bulk of this change is about improving #33678 to allow exploring multiple instances of the "same" recursive type reference, so that syntactic determination if the reference is possibly recursive or not cannot be observed (up to a limit).

@weswigham

weswigham commented Apr 16, 2020

Copy link
Copy Markdown
MemberAuthor

@typescript-bot user test this
@typescript-bot run dt
@typescript-bot test this

@typescript-bot

typescript-bot commented Apr 16, 2020

Copy link
Copy Markdown
Contributor

Heya @weswigham, I've started to run the parallelized community code test suite on this PR at 73317dc. You can monitor the build here.

@typescript-bot

typescript-bot commented Apr 16, 2020

Copy link
Copy Markdown
Contributor

Heya @weswigham, I've started to run the parallelized Definitely Typed test suite on this PR at 73317dc. You can monitor the build here.

@typescript-bot

typescript-bot commented Apr 16, 2020

Copy link
Copy Markdown
Contributor

Heya @weswigham, I've started to run the extended test suite on this PR at 73317dc. You can monitor the build here.

@weswigham

Copy link
Copy Markdown
MemberAuthor

@typescript-bot perf test this

@typescript-bot

typescript-bot commented Apr 16, 2020

Copy link
Copy Markdown
Contributor

Heya @weswigham, I've started to run the perf test suite on this PR at 73317dc. You can monitor the build here.

Update: The results are in!

@typescript-bot

Copy link
Copy Markdown
Contributor

The user suite test run you requested has finished and failed. I've opened a PR with the baseline diff from master.

@weswigham

Copy link
Copy Markdown
MemberAuthor

RWC and user baselines look fine, just waiting for DT and perf to come back~

@typescript-bot

Copy link
Copy Markdown
Contributor

@weswigham
The results of the perf run you requested are in!

Here they are:

Comparison Report - master..38011

Metricmaster38011DeltaBestWorst
Angular - node (v10.16.3, x64)
Memory used327,745k (± 0.03%)327,175k (± 0.03%)-570k (- 0.17%)327,013k327,348k
Parse Time1.64s (± 0.53%)1.64s (± 0.54%)+0.00s (+ 0.06%)1.62s1.66s
Bind Time0.89s (± 0.67%)0.88s (± 0.74%)-0.01s (- 0.90%)0.87s0.89s
Check Time4.76s (± 0.39%)4.78s (± 0.73%)+0.02s (+ 0.38%)4.69s4.84s
Emit Time5.36s (± 0.50%)5.33s (± 0.70%)-0.03s (- 0.58%)5.25s5.43s
Total Time12.66s (± 0.31%)12.63s (± 0.48%)-0.03s (- 0.21%)12.52s12.77s
Monaco - node (v10.16.3, x64)
Memory used327,093k (± 0.02%)327,040k (± 0.02%)-54k (- 0.02%)326,872k327,171k
Parse Time1.26s (± 0.39%)1.26s (± 0.47%)-0.00s (- 0.08%)1.25s1.28s
Bind Time0.77s (± 0.77%)0.78s (± 0.61%)+0.00s (+ 0.39%)0.77s0.79s
Check Time4.78s (± 0.31%)4.78s (± 0.34%)+0.00s (+ 0.06%)4.74s4.83s
Emit Time2.92s (± 0.50%)2.93s (± 0.79%)+0.01s (+ 0.34%)2.88s2.97s
Total Time9.73s (± 0.17%)9.74s (± 0.34%)+0.01s (+ 0.13%)9.67s9.83s
TFS - node (v10.16.3, x64)
Memory used292,027k (± 0.02%)292,009k (± 0.02%)-17k (- 0.01%)291,890k292,210k
Parse Time0.97s (± 0.70%)0.96s (± 0.81%)-0.01s (- 0.52%)0.94s0.98s
Bind Time0.75s (± 0.69%)0.75s (± 0.89%)+0.00s (+ 0.53%)0.74s0.77s
Check Time4.31s (± 0.57%)4.33s (± 0.62%)+0.03s (+ 0.63%)4.29s4.40s
Emit Time3.07s (± 0.64%)3.06s (± 0.84%)-0.01s (- 0.23%)3.00s3.11s
Total Time9.09s (± 0.37%)9.11s (± 0.24%)+0.02s (+ 0.19%)9.05s9.15s
material-ui - node (v10.16.3, x64)
Memory used450,560k (± 0.01%)450,333k (± 0.01%)-227k (- 0.05%)450,179k450,449k
Parse Time1.78s (± 0.55%)1.78s (± 0.47%)-0.00s (- 0.17%)1.76s1.80s
Bind Time0.69s (± 0.69%)0.68s (± 1.11%)-0.00s (- 0.29%)0.67s0.71s
Check Time12.70s (± 0.48%)12.67s (± 0.56%)-0.03s (- 0.26%)12.53s12.85s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time15.17s (± 0.41%)15.14s (± 0.48%)-0.04s (- 0.25%)15.01s15.33s
Angular - node (v12.1.0, x64)
Memory used303,225k (± 0.03%)302,739k (± 0.03%)-486k (- 0.16%)302,528k302,931k
Parse Time1.59s (± 0.67%)1.59s (± 0.60%)-0.01s (- 0.50%)1.57s1.60s
Bind Time0.88s (± 0.78%)0.87s (± 0.64%)-0.00s (- 0.46%)0.86s0.89s
Check Time4.66s (± 0.32%)4.66s (± 0.41%)-0.00s (- 0.04%)4.63s4.72s
Emit Time5.52s (± 0.76%)5.50s (± 0.59%)-0.02s (- 0.34%)5.41s5.55s
Total Time12.65s (± 0.30%)12.62s (± 0.34%)-0.03s (- 0.24%)12.52s12.73s
Monaco - node (v12.1.0, x64)
Memory used307,051k (± 0.02%)307,031k (± 0.02%)-20k (- 0.01%)306,903k307,124k
Parse Time1.23s (± 0.91%)1.22s (± 0.74%)-0.00s (- 0.33%)1.21s1.25s
Bind Time0.75s (± 1.11%)0.75s (± 0.49%)+0.00s (+ 0.00%)0.74s0.75s
Check Time4.60s (± 0.44%)4.60s (± 0.44%)-0.00s (- 0.04%)4.55s4.64s
Emit Time2.98s (± 0.83%)2.96s (± 0.56%)-0.02s (- 0.77%)2.92s3.00s
Total Time9.55s (± 0.35%)9.52s (± 0.23%)-0.03s (- 0.30%)9.48s9.56s
TFS - node (v12.1.0, x64)
Memory used274,350k (± 0.03%)274,339k (± 0.02%)-11k (- 0.00%)274,230k274,446k
Parse Time0.95s (± 1.11%)0.94s (± 0.92%)-0.01s (- 0.53%)0.92s0.96s
Bind Time0.71s (± 0.83%)0.71s (± 1.60%)-0.00s (- 0.28%)0.70s0.74s
Check Time4.24s (± 0.69%)4.23s (± 0.45%)-0.01s (- 0.24%)4.20s4.29s
Emit Time3.11s (± 1.11%)3.09s (± 0.57%)-0.02s (- 0.68%)3.05s3.13s
Total Time9.02s (± 0.53%)8.98s (± 0.40%)-0.04s (- 0.43%)8.90s9.07s
material-ui - node (v12.1.0, x64)
Memory used427,975k (± 0.06%)427,689k (± 0.06%)-286k (- 0.07%)426,733k427,937k
Parse Time1.76s (± 0.37%)1.76s (± 0.58%)+0.00s (+ 0.06%)1.74s1.78s
Bind Time0.63s (± 0.93%)0.64s (± 1.20%)+0.01s (+ 1.28%)0.61s0.65s
Check Time11.33s (± 1.02%)11.32s (± 0.64%)-0.01s (- 0.11%)11.21s11.49s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time13.71s (± 0.87%)13.71s (± 0.51%)-0.01s (- 0.04%)13.58s13.89s
Angular - node (v8.9.0, x64)
Memory used322,562k (± 0.02%)322,080k (± 0.02%)-481k (- 0.15%)321,963k322,283k
Parse Time2.12s (± 0.26%)2.13s (± 0.59%)+0.00s (+ 0.19%)2.10s2.16s
Bind Time0.92s (± 1.27%)0.93s (± 0.91%)+0.01s (+ 0.87%)0.91s0.95s
Check Time5.42s (± 1.70%)5.35s (± 1.50%)-0.07s (- 1.31%)5.22s5.51s
Emit Time6.30s (± 0.71%)6.40s (± 2.05%)+0.10s (+ 1.60%)6.04s6.64s
Total Time14.76s (± 0.52%)14.80s (± 0.57%)+0.04s (+ 0.28%)14.56s14.97s
Monaco - node (v8.9.0, x64)
Memory used325,535k (± 0.01%)325,535k (± 0.01%)-0k (- 0.00%)325,390k325,609k
Parse Time1.55s (± 0.36%)1.55s (± 0.40%)-0.00s (- 0.06%)1.54s1.56s
Bind Time0.90s (± 0.66%)0.91s (± 1.32%)+0.01s (+ 0.66%)0.89s0.94s
Check Time5.38s (± 0.55%)5.35s (± 0.50%)-0.04s (- 0.65%)5.27s5.39s
Emit Time3.52s (± 0.55%)3.47s (± 0.97%)-0.06s (- 1.56%)3.38s3.52s
Total Time11.36s (± 0.37%)11.27s (± 0.35%)-0.09s (- 0.76%)11.17s11.33s
TFS - node (v8.9.0, x64)
Memory used291,545k (± 0.01%)291,527k (± 0.01%)-18k (- 0.01%)291,436k291,622k
Parse Time1.26s (± 0.54%)1.26s (± 0.56%)-0.01s (- 0.47%)1.24s1.27s
Bind Time0.75s (± 0.77%)0.75s (± 0.46%)-0.01s (- 0.80%)0.74s0.75s
Check Time4.97s (± 1.41%)4.95s (± 1.72%)-0.02s (- 0.48%)4.83s5.16s
Emit Time3.29s (± 2.97%)3.29s (± 2.36%)-0.00s (- 0.06%)3.11s3.39s
Total Time10.28s (± 0.47%)10.24s (± 0.33%)-0.04s (- 0.37%)10.17s10.32s
material-ui - node (v8.9.0, x64)
Memory used453,093k (± 0.01%)452,902k (± 0.01%)-191k (- 0.04%)452,790k453,007k
Parse Time2.13s (± 0.78%)2.11s (± 0.45%)-0.01s (- 0.61%)2.09s2.13s
Bind Time0.81s (± 0.90%)0.81s (± 0.71%)+0.00s (+ 0.25%)0.80s0.82s
Check Time16.85s (± 1.04%)16.78s (± 1.11%)-0.07s (- 0.43%)16.32s17.16s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time19.79s (± 0.84%)19.70s (± 0.93%)-0.08s (- 0.42%)19.26s20.08s
Angular - node (v8.9.0, x86)
Memory used185,695k (± 0.02%)185,454k (± 0.02%)-241k (- 0.13%)185,370k185,564k
Parse Time2.07s (± 0.28%)2.06s (± 0.52%)-0.02s (- 0.82%)2.04s2.08s
Bind Time1.07s (± 0.37%)1.07s (± 0.77%)+0.01s (+ 0.47%)1.06s1.09s
Check Time5.02s (± 0.60%)5.02s (± 0.79%)+0.00s (+ 0.08%)4.96s5.14s
Emit Time6.07s (± 0.41%)6.06s (± 1.73%)-0.01s (- 0.18%)5.80s6.41s
Total Time14.23s (± 0.28%)14.21s (± 0.86%)-0.02s (- 0.12%)13.93s14.61s
Monaco - node (v8.9.0, x86)
Memory used185,352k (± 0.02%)185,392k (± 0.02%)+40k (+ 0.02%)185,315k185,452k
Parse Time1.59s (± 0.33%)1.61s (± 1.12%)+0.02s (+ 1.38%)1.58s1.67s
Bind Time0.77s (± 0.78%)0.77s (± 0.44%)+0.00s (+ 0.13%)0.76s0.77s
Check Time5.43s (± 0.40%)5.44s (± 0.51%)+0.01s (+ 0.13%)5.39s5.50s
Emit Time2.90s (± 1.31%)2.86s (± 0.59%)-0.04s (- 1.21%)2.84s2.92s
Total Time10.69s (± 0.51%)10.68s (± 0.42%)-0.01s (- 0.07%)10.61s10.82s
TFS - node (v8.9.0, x86)
Memory used166,941k (± 0.02%)166,940k (± 0.02%)-1k (- 0.00%)166,866k167,054k
Parse Time1.29s (± 0.81%)1.29s (± 0.73%)+0.00s (+ 0.08%)1.28s1.33s
Bind Time0.72s (± 1.04%)0.71s (± 0.56%)-0.01s (- 1.12%)0.70s0.72s
Check Time4.66s (± 0.55%)4.66s (± 0.43%)+0.00s (+ 0.11%)4.63s4.71s
Emit Time3.04s (± 2.96%)2.96s (± 0.65%)-0.08s (- 2.70%)2.90s3.00s
Total Time9.71s (± 0.89%)9.63s (± 0.35%)-0.08s (- 0.82%)9.56s9.70s
material-ui - node (v8.9.0, x86)
Memory used256,581k (± 0.01%)256,440k (± 0.01%)-141k (- 0.06%)256,362k256,516k
Parse Time2.18s (± 0.53%)2.19s (± 0.40%)+0.00s (+ 0.18%)2.17s2.21s
Bind Time0.68s (± 1.00%)0.69s (± 0.75%)+0.00s (+ 0.73%)0.68s0.70s
Check Time15.32s (± 0.72%)15.41s (± 0.69%)+0.10s (+ 0.65%)15.18s15.74s
Emit Time0.00s (± 0.00%)0.00s (± 0.00%)0.00s ( NaN%)0.00s0.00s
Total Time18.18s (± 0.63%)18.29s (± 0.57%)+0.11s (+ 0.59%)18.06s18.59s
System
Machine Namets-ci-ubuntu
Platformlinux 4.4.0-166-generic
Architecturex64
Available Memory16 GB
Available Memory1 GB
CPUs4 × Intel(R) Core(TM) i7-4770 CPU @ 3.40GHz
Hosts
  • node (v10.16.3, x64)
  • node (v12.1.0, x64)
  • node (v8.9.0, x64)
  • node (v8.9.0, x86)
Scenarios
  • Angular - node (v10.16.3, x64)
  • Angular - node (v12.1.0, x64)
  • Angular - node (v8.9.0, x64)
  • Angular - node (v8.9.0, x86)
  • Monaco - node (v10.16.3, x64)
  • Monaco - node (v12.1.0, x64)
  • Monaco - node (v8.9.0, x64)
  • Monaco - node (v8.9.0, x86)
  • TFS - node (v10.16.3, x64)
  • TFS - node (v12.1.0, x64)
  • TFS - node (v8.9.0, x64)
  • TFS - node (v8.9.0, x86)
  • material-ui - node (v10.16.3, x64)
  • material-ui - node (v12.1.0, x64)
  • material-ui - node (v8.9.0, x64)
  • material-ui - node (v8.9.0, x86)
BenchmarkNameIterations
Current3801110
Baselinemaster10

@weswigham

Copy link
Copy Markdown
MemberAuthor

Perf and DT both look good, too~

@sandersnsandersn assigned ahejlsberg and unassigned weswighamMay 5, 2020
@sandersnsandersn added the For Milestone Bug PRs that fix a bug with a specific milestone label May 5, 2020
@weswigham

Copy link
Copy Markdown
MemberAuthor

ping @ahejlsberg

@ahejlsbergahejlsberg left a comment

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.

Just a minor suggested change.

Comment threadsrc/compiler/checker.ts Outdated
@weswigham
weswigham merged commit a3ee09d into microsoft:masterJun 24, 2020
@weswigham
weswigham deleted the recursive-type-reference-inference-mk2 branch June 24, 2020 21:25
cangSDARM added a commit to cangSDARM/TypeScript that referenced this pull request Jun 28, 2020
* upstream/master:
LEGO: check in for master to temporary branch.
Preserve newlines between try/catch/finally, if/else, do/while (microsoft#39280)
not narrow static property without type annotation in constructor. (microsoft#39252)
Switch to ES Map/Set internally (microsoft#33771)
fix(38840): omit completions for a spread like argument in a function definition (microsoft#38897)
fix(38785): include in NavigationBar child items from default exported functions (microsoft#38915)
LEGO: check in for master to temporary branch.
LEGO: check in for master to temporary branch.
Avoid effect of element access expression (microsoft#39174)
Update typescript-eslint to 3.4.1-alpha.1 (microsoft#39260)
Handle 'keyof' for generic tuple types (microsoft#39218)
Disable unsound T[K] rule in subtype relations (microsoft#39249)
LEGO: check in for master to temporary branch.
Upgrade typescript-eslint version (microsoft#39242)
Handle recursive type references up to a certain level of expansion in inference (microsoft#38011)
Do not consider binding patterns in contextual types for return type inference where all the signature type parameters have defaults (microsoft#39081)
LEGO: check in for master to temporary branch.
# Conflicts:
#	src/compiler/program.ts
#	src/compiler/types.ts
@microsoftmicrosoft locked as resolved and limited conversation to collaborators Oct 21, 2025
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Author: TeamFor Milestone BugPRs that fix a bug with a specific milestone

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

[3.9.0 BUG] Recursive type infer behaves differently when passing type literal and passing type alias

4 participants

@weswigham@typescript-bot@ahejlsberg@sandersn