Microsoft/TypeScript

Tail recursion optimization limit 999 may be manipulated

Open

#49,459 建立於 2022年6月9日

在 GitHub 查看
 (5 留言) (0 反應) (0 負責人)TypeScript (6,726 fork)batch import
BugDomain: Conditional TypesHelp Wanted

倉庫指標

Star
 (48,455 star)
PR 合併指標
 (平均合併 6天 17小時) (30 天內合併 9 個 PR)

描述

Bug Report

🔎 Search Terms

tail recursion, tail recursion optimization, tail recursion detection, tail recursion limit

🕗 Version & Regression Information

  • This is a crash: yes
  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about: yes

⏯ Playground Link

Playground link with relevant code

💻 Code

type NumberToTuple1<Num extends number, Tuple extends 0[] = []> = 0 extends 1 ? never :
  Tuple['length'] extends Num ? Tuple : NumberToTuple1<Num, [...Tuple, 0]>; // this line

type NumberToTuple2<Num extends number, Tuple extends 0[] = []> =
  Tuple['length'] extends Num ? Tuple : NumberToTuple2<Num, [...Tuple, 0]>; // is the same as this line

type BigTuple_Computed = NumberToTuple1<1000>

type BigTuple_Error = NumberToTuple2<1000> // Type instantiation is excessively deep and possibly infinite.(2589)

🙁 Actual behavior

NumberToTuple1 is using the tail recursion optimization so BigTuple_Computed type is [0, 0, 0, ..., 0], just as expected. NumberToTuple2 is NOT using tail recursion optimization using tail recursion optimization in a different maneer so BigTuple_Error type is any. The difference between them is only in junk piece of code 0 extends 1 ? never : that is doing nothing.

UPD: NumberToTuple2 is working up to 999, while NumberToTuple1 is working up to 3153

🙂 Expected behavior

According to the article introducing tail call optimization to TypeScript, tail call optimization should be applied to both NumberToTuple1 and NumberToTuple2 the same, because non of them is doing any on-stack transformations with the call results. Recursion limit is expected to remain the same

貢獻者指南