Skip to content

Control flow analysis for element access with variable constant-like index in for statements - #60715

Closed
Mateusz Burzyński (Andarist) wants to merge 1 commit into
microsoft:mainfrom
Andarist:cfa-element-access-for-loop
Closed

Control flow analysis for element access with variable constant-like index in for statements#60715
Mateusz Burzyński (Andarist) wants to merge 1 commit into
microsoft:mainfrom
Andarist:cfa-element-access-for-loop

Conversation

@Andarist

@AndaristMateusz Burzyński (Andarist) commented Dec 9, 2024

Copy link
Copy Markdown
Contributor

This is a small extension of #57847
closes#58803

let variables in for loops are special, despite them being mutable and "shared" for the loop - each iteration gets its own unique copy of that variable. A mutation in the incrementor has no effect on the loop's body so, to the best of my understanding, it can safely be ignored.

@typescript-botTypeScript Bot (typescript-bot) added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Dec 9, 2024
Comment on lines +29635 to +29645
function isSymbolAssignedInForStatementBody(symbol: Symbol) {
const forStatement = getRootDeclaration(symbol.valueDeclaration!).parent.parent;
Debug.assert(isForStatement(forStatement));
return !isPastLastAssignment(symbol, forStatement.statement);
}

function isUsedInForStatementBody(symbol: Symbol, location: Node) {
const forStatement = getRootDeclaration(symbol.valueDeclaration!).parent.parent;
Debug.assert(isForStatement(forStatement));
return location.pos >= forStatement.statement.pos && location.end <= forStatement.statement.end;
}

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'd love to combine those 2 but I've failed so far to figure out an elegant function name for a function that would do both 😅

@jakebailey

Copy link
Copy Markdown
Member

TypeScript Bot (@typescript-bot) test it

@typescript-bot

TypeScript Bot (typescript-bot) commented Dec 9, 2024

Copy link
Copy Markdown
Contributor

Starting jobs; this comment will be updated as builds start and complete.

CommandStatusResults
test top400✅ Started👀 Results
user test this✅ Started✅ Results
run dt✅ Started✅ Results
perf test this faster✅ Started👀 Results

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the user tests with tsc comparing main and refs/pull/60715/merge:

Everything looks good!

@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)
The results of the perf run you requested are in!

Here they are:

tsc

Comparison Report - baseline..pr
MetricbaselineprDeltaBestWorstp-value
Compiler-Unions - node (v18.15.0, x64)
Errors3434~~~p=1.000 n=6
Symbols62,36362,363~~~p=1.000 n=6
Types50,39550,395~~~p=1.000 n=6
Memory used194,235k (± 0.97%)193,705k (± 0.76%)~193,012k196,693kp=0.936 n=6
Parse Time1.31s (± 0.84%)1.31s (± 0.75%)~1.29s1.32sp=0.718 n=6
Bind Time0.72s0.72s~~~p=1.000 n=6
Check Time9.77s (± 0.48%)9.76s (± 0.33%)~9.72s9.81sp=0.573 n=6
Emit Time2.74s (± 0.44%)2.73s (± 0.95%)~2.69s2.76sp=0.806 n=6
Total Time14.54s (± 0.40%)14.52s (± 0.30%)~14.44s14.57sp=0.468 n=6
angular-1 - node (v18.15.0, x64)
Errors3738+1 (+ 2.70%)~~p=0.001 n=6
Symbols947,936947,936~~~p=1.000 n=6
Types410,955410,965+10 (+ 0.00%)~~p=0.001 n=6
Memory used1,225,832k (± 0.00%)1,225,923k (± 0.00%)+92k (+ 0.01%)1,225,883k1,225,985kp=0.005 n=6
Parse Time6.61s (± 0.62%)6.63s (± 0.63%)~6.59s6.71sp=0.257 n=6
Bind Time1.89s (± 0.33%)1.89s (± 0.43%)~1.88s1.90sp=0.432 n=6
Check Time31.96s (± 0.31%)32.05s (± 0.28%)~31.89s32.14sp=0.121 n=6
Emit Time15.14s (± 0.50%)15.16s (± 0.23%)~15.11s15.20sp=0.936 n=6
Total Time55.60s (± 0.36%)55.73s (± 0.18%)~55.60s55.85sp=0.378 n=6
mui-docs - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols2,447,0282,447,028~~~p=1.000 n=6
Types896,160896,160~~~p=1.000 n=6
Memory used2,318,460k (± 0.00%)2,318,452k (± 0.00%)~2,318,387k2,318,517kp=1.000 n=6
Parse Time9.44s (± 0.29%)9.44s (± 0.23%)~9.40s9.46sp=0.625 n=6
Bind Time2.23s (± 0.37%)2.23s (± 0.46%)~2.21s2.24sp=1.000 n=6
Check Time73.29s (± 0.41%)73.65s (± 0.45%)~73.19s74.03sp=0.092 n=6
Emit Time0.29s (± 2.61%)0.29s (± 3.68%)~0.27s0.30sp=0.611 n=6
Total Time85.24s (± 0.36%)85.60s (± 0.40%)~85.13s85.99sp=0.093 n=6
self-build-src - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,225,3281,225,338+10 (+ 0.00%)~~p=0.001 n=6
Types266,569266,575+6 (+ 0.00%)~~p=0.001 n=6
Memory used2,414,691k (± 6.13%)2,354,565k (± 0.03%)~2,353,602k2,355,589kp=0.689 n=6
Parse Time5.24s (± 0.88%)5.21s (± 1.41%)~5.13s5.32sp=0.468 n=6
Bind Time1.77s (± 1.09%)1.77s (± 1.27%)~1.75s1.80sp=1.000 n=6
Check Time35.13s (± 0.56%)35.24s (± 0.15%)~35.18s35.31sp=0.173 n=6
Emit Time2.95s (± 0.76%)2.93s (± 2.51%)~2.81s2.99sp=0.688 n=6
Total Time45.11s (± 0.39%)45.19s (± 0.33%)~44.94s45.38sp=0.230 n=6
self-build-src-public-api - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols1,225,3281,225,338+10 (+ 0.00%)~~p=0.001 n=6
Types266,569266,575+6 (+ 0.00%)~~p=0.001 n=6
Memory used2,908,034k (±12.85%)3,030,024k (± 9.75%)~2,426,400k3,151,558kp=0.128 n=6
Parse Time6.95s (± 1.84%)7.00s (± 1.47%)~6.85s7.10sp=0.423 n=6
Bind Time2.17s (± 1.19%)2.15s (± 0.68%)~2.13s2.17sp=0.125 n=6
Check Time42.74s (± 0.59%)42.84s (± 0.54%)~42.43s43.08sp=0.630 n=6
Emit Time3.51s (± 2.96%)3.50s (± 1.67%)~3.44s3.59sp=0.873 n=6
Total Time55.37s (± 0.73%)55.50s (± 0.50%)~55.00s55.71sp=0.688 n=6
self-compiler - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols262,267262,277+10 (+ 0.00%)~~p=0.001 n=6
Types106,628106,634+6 (+ 0.01%)~~p=0.001 n=6
Memory used439,879k (± 0.01%)440,070k (± 0.01%)+191k (+ 0.04%)439,994k440,163kp=0.005 n=6
Parse Time3.54s (± 0.39%)3.54s (± 1.02%)~3.49s3.59sp=0.745 n=6
Bind Time1.32s (± 1.34%)1.32s (± 0.78%)~1.30s1.33sp=0.805 n=6
Check Time18.94s (± 0.74%)18.96s (± 0.38%)~18.88s19.06sp=0.810 n=6
Emit Time1.53s (± 0.76%)1.53s (± 0.87%)~1.52s1.55sp=1.000 n=6
Total Time25.32s (± 0.65%)25.35s (± 0.26%)~25.22s25.40sp=1.000 n=6
ts-pre-modules - node (v18.15.0, x64)
Errors7070~~~p=1.000 n=6
Symbols226,062226,062~~~p=1.000 n=6
Types94,48894,491+3 (+ 0.00%)~~p=0.001 n=6
Memory used371,615k (± 0.01%)371,741k (± 0.03%)+126k (+ 0.03%)371,638k371,926kp=0.020 n=6
Parse Time2.91s (± 1.45%)2.88s (± 0.58%)~2.87s2.91sp=0.119 n=6
Bind Time1.59s (± 1.79%)1.59s (± 0.86%)~1.57s1.61sp=1.000 n=6
Check Time16.50s (± 0.39%)16.53s (± 0.21%)~16.50s16.59sp=0.574 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time21.00s (± 0.17%)20.99s (± 0.13%)~20.96s21.04sp=0.871 n=6
vscode - node (v18.15.0, x64)
Errors33~~~p=1.000 n=6
Symbols3,197,7833,197,783~~~p=1.000 n=6
Types1,099,2561,099,258+2 (+ 0.00%)~~p=0.001 n=6
Memory used3,271,546k (± 0.01%)3,272,164k (± 0.01%)+618k (+ 0.02%)3,271,726k3,272,545kp=0.031 n=6
Parse Time14.14s (± 0.31%)14.23s (± 0.56%)~14.14s14.37sp=0.054 n=6
Bind Time4.53s (± 0.55%)4.52s (± 0.69%)~4.47s4.56sp=0.808 n=6
Check Time86.56s (± 0.42%)86.43s (± 0.59%)~85.79s87.34sp=0.298 n=6
Emit Time28.13s (± 2.01%)27.91s (± 2.97%)~27.25s29.27sp=0.748 n=6
Total Time133.36s (± 0.44%)133.10s (± 0.91%)~131.69s134.66sp=0.471 n=6
webpack - node (v18.15.0, x64)
Errors00~~~p=1.000 n=6
Symbols288,747288,747~~~p=1.000 n=6
Types117,158117,158~~~p=1.000 n=6
Memory used440,915k (± 0.02%)441,098k (± 0.04%)+183k (+ 0.04%)440,914k441,429kp=0.045 n=6
Parse Time4.10s (± 0.78%)4.06s (± 1.33%)~3.99s4.15sp=0.228 n=6
Bind Time1.76s (± 1.70%)1.76s (± 1.05%)~1.74s1.79sp=0.871 n=6
Check Time18.84s (± 0.39%)18.86s (± 0.53%)~18.79s19.06sp=0.688 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time24.70s (± 0.54%)24.69s (± 0.55%)~24.55s24.94sp=0.518 n=6
xstate-main - node (v18.15.0, x64)
Errors55~~~p=1.000 n=6
Symbols552,389552,389~~~p=1.000 n=6
Types185,093185,093~~~p=1.000 n=6
Memory used492,423k (± 0.02%)492,524k (± 0.01%)+101k (+ 0.02%)492,404k492,598kp=0.045 n=6
Parse Time3.41s (± 1.03%)3.41s (± 0.51%)~3.38s3.43sp=0.627 n=6
Bind Time1.17s (± 1.71%)1.17s (± 1.17%)~1.15s1.19sp=0.869 n=6
Check Time19.59s (± 1.26%)19.46s (± 0.21%)~19.40s19.52sp=0.196 n=6
Emit Time0.00s0.00s~~~p=1.000 n=6
Total Time24.17s (± 1.01%)24.06s (± 0.19%)~24.00s24.11sp=0.335 n=6
System info unknown
Hosts
  • node (v18.15.0, x64)
Scenarios
  • Compiler-Unions - node (v18.15.0, x64)
  • angular-1 - node (v18.15.0, x64)
  • mui-docs - node (v18.15.0, x64)
  • self-build-src - node (v18.15.0, x64)
  • self-build-src-public-api - node (v18.15.0, x64)
  • self-compiler - node (v18.15.0, x64)
  • ts-pre-modules - node (v18.15.0, x64)
  • vscode - node (v18.15.0, x64)
  • webpack - node (v18.15.0, x64)
  • xstate-main - node (v18.15.0, x64)
BenchmarkNameIterations
Currentpr6
Baselinebaseline6

Developer Information:

Download Benchmarks

@typescript-bot

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey) Here are the results of running the top 400 repos with tsc comparing main and refs/pull/60715/merge:

Something interesting changed - please have a look.

Details

snabbdom/snabbdom

1 of 2 projects failed to build with the old tsc and were ignored

tsconfig.json

  • error TS2345: Argument of type 'string | number' is not assignable to parameter of type 'string | undefined'.

@Andarist

Copy link
Copy Markdown
ContributorAuthor

The snabbdom break isn't harmful. It boils down to a code like this:

declarefunctionisPrimitive(s: any): s is string|number;exportfunctiontest(){letc: any;for(leti=0;i<c.length;++i){if(isPrimitive(c[i])){consttarget: string|undefined=c[i];}}}

The problem is that c is any and thus, before this change, c[i] stayed as any too so it was, naturally, assignable to string | undefined. But isPrimitive is a type predicate and it can narrow down any:

declarefunctionisPrimitive(s: any): s is string|number;declareconstfoo: any;if(isPrimitive(foo)){foo;// string | number}

Since now this constant-like c[i] can be narrowed down it breaks because string | number isn't assignable to string | undefined

@typescript-bot

Copy link
Copy Markdown
Contributor

With 6.0 out as the final release vehicle for this codebase, we're closing all PRs that don't fit the merge criteria for post-6.0 patches. If you think this was a mistake and this PR fits the post-6.0 patch criteria, please post to the 6.0 iteration issue with details (specifically, which PR and which patch criteria it satisfies).

Next steps for PRs:

  • For crash bugfixes or language service improvements, PRs are currently accepted at the typescript-go repo
  • Changes to type system behavior should wait until after 7.0, at which point mainline TypeScript development will resume in this repository with the Go codebase
  • Library file updates (lib.d.ts etc) continue to live in this repo or the DOM Generator repo as appropriate

@github-project-automationgithub-project-automationBot moved this from Not started to Done in PR BacklogMar 24, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

Narrowing for constant indexed access fails on array getter

4 participants

@Andarist@jakebailey@typescript-bot@RyanCavanaugh