Hejlsberg Picks Go Over Rust for Native TypeScript Compiler Port

Creator of TypeScript: Why We Chose Go For Our Rewrite | Anders Hejlsberg — Ryan Peterman

Ryan Peterman

Go won the TypeScript compiler port over Rust because Rust's borrow checker cannot accommodate the codebase's circular data structures without forcing a complete architectural rewrite.

AI-assisted summary of Creator of TypeScript: Why We Chose Go For Our Rewrite | Anders Hejlsberg — original source. Check the original for full context.

Source published:

Key ideas

  • The TypeScript compiler is transitioning away from JavaScript to native code to eliminate a baseline 2x to 3x compute penalty and unlock multi-core scaling. (0:00)
  • The team pursued a direct port rather than a clean-slate rewrite to preserve exact compiler semantics, diagnostics, and backwards compatibility for existing codebases. (2:52)
  • Go was chosen because its built-in garbage collection, first-class functions, and shared-memory concurrency closely matched TypeScript's architectural assumptions. (2:52)
  • Rust was evaluated but deemed unfeasible due to the borrow checker's inability to handle the compiler's heavily cyclic data structures, including AST parent pointers and recursive types. (4:47)

Detailed notes

## Background Published on YouTube by Ryan Peterman on September 11, 2026, this interview clip features TypeScript and C# creator Anders Hejlsberg discussing the technical motivations behind rewriting the TypeScript compiler. According to the description, the conversation explores how moving to Go yielded a 10x performance boost, as well as broader thoughts on AI in software engineering.

## TL;DR Anders Hejlsberg explains that the TypeScript compiler outgrew JavaScript due to pure compute execution penalties and single-threaded memory constraints that prevented it from leveraging multi-core hardware. Rather than undertaking a greenfield rewrite that risked breaking subtle compatibility behaviors, the team executed a direct port that required native code generation, garbage collection, and shared-memory concurrency. Go fit these requirements seamlessly, whereas Rust was rejected after experimentation because its borrow checker clashed fundamentally with the compiler's heavily circular ASTs, recursive types, and symbol graphs.

## Atmosphere & style The conversation carries a relaxed, master-class atmosphere characterized by pragmatic systems-engineering wisdom rather than dogmatic language advocacy. Hejlsberg speaks with calm clarity and self-effacing humor, visibly amused when recalling how quickly Rust's borrow checker stymied their attempt to preserve complex graph structures. Listening feels like sitting in on an honest, high-level post-mortem where decades of language design experience cut cleanly through industry hype.

## Bulletin - [00:00](https://www.youtube.com/watch?v=rX9kkMonrG8&t=0s) The TypeScript compiler is transitioning away from JavaScript to native code to eliminate a baseline 2x to 3x compute penalty and unlock multi-core scaling. - [02:52](https://www.youtube.com/watch?v=rX9kkMonrG8&t=172s) The team pursued a direct port rather than a clean-slate rewrite to preserve exact compiler semantics, diagnostics, and backwards compatibility for existing codebases. - [02:52](https://www.youtube.com/watch?v=rX9kkMonrG8&t=172s) Go was chosen because its built-in garbage collection, first-class functions, and shared-memory concurrency closely matched TypeScript's architectural assumptions. - [04:47](https://www.youtube.com/watch?v=rX9kkMonrG8&t=287s) Rust was evaluated but deemed unfeasible due to the borrow checker's inability to handle the compiler's heavily cyclic data structures, including AST parent pointers and recursive types.

## Key takeaways - [00:00](https://www.youtube.com/watch?v=rX9kkMonrG8&t=0s) The decision to rewrite the TypeScript compiler in native code was driven entirely by performance and scalability needs. - [00:00](https://www.youtube.com/watch?v=rX9kkMonrG8&t=0s) JavaScript was designed for browser UI tasks and small scripts, incurring an immediate 2x to 3x performance penalty on pure compute workloads like compilers. - [00:00](https://www.youtube.com/watch?v=rX9kkMonrG8&t=0s) JavaScript's single-threaded nature shields developers from concurrency bugs but leaves modern multi-core hardware severely underutilized. - [00:00](https://www.youtube.com/watch?v=rX9kkMonrG8&t=0s) Web workers do not support shared-memory concurrency, forcing expensive data serialization rather than direct access to in-memory object graphs. - [00:00](https://www.youtube.com/watch?v=rX9kkMonrG8&t=0s) Because Moore's Law now scales through additional CPU cores rather than clock speeds, shared-memory concurrency is essential to avoid leaving performance on the table. - [02:52](https://www.youtube.com/watch?v=rX9kkMonrG8&t=172s) The team chose a line-by-line port instead of a greenfield rewrite to guarantee bug-for-bug compatibility and preserve subtle type-checking behaviors. - [02:52](https://www.youtube.com/watch?v=rX9kkMonrG8&t=172s) Porting required a target language that naturally supported garbage collection and closures capturing outer state. - [02:52](https://www.youtube.com/watch?v=rX9kkMonrG8&t=172s) Go offered mature native code generation, built-in garbage collection, and shared-memory primitives that aligned directly with the existing TypeScript codebase. - [04:47](https://www.youtube.com/watch?v=rX9kkMonrG8&t=287s) Rust's ownership model and borrow checker fundamentally reject circular references and shared mutable graphs. - [04:47](https://www.youtube.com/watch?v=rX9kkMonrG8&t=287s) The TypeScript compiler relies extensively on cyclic data structures, such as syntax trees with upward parent pointers, recursive types, and interconnected symbol tables. - [04:47](https://www.youtube.com/watch?v=rX9kkMonrG8&t=287s) An experimental port to Rust was abandoned because it required redesigning core data structures and created self-inflicted architectural friction. - [04:47](https://www.youtube.com/watch?v=rX9kkMonrG8&t=287s) Workarounds for cyclic graphs in Rust, such as reference counting and arenas, frequently lead to using unsafe blocks that undermine safety guarantees. - [04:47](https://www.youtube.com/watch?v=rX9kkMonrG8&t=287s) Go delivered the necessary performance gains and concurrency benefits with substantially lower implementation friction than Rust.

## Detailed walkthrough ### [00:00](https://www.youtube.com/watch?v=rX9kkMonrG8&t=0s) The Bottlenecks of JavaScript: Compute Penalties and Single-Threaded Limits

Ryan Peterman opens the discussion by asking Anders Hejlsberg about the decision to move the TypeScript compiler away from its original pure JavaScript implementation and rewrite it in native code. Anders explains that the motivation boils down to "performance and scalability." JavaScript was originally designed to handle browser user interfaces and run small scripts—perhaps roughly a hundred lines of code—rather than execute heavy compute workloads like language compilers. When running pure compute tasks in JavaScript, developers pay an immediate 2x to 3x performance penalty compared to native machine code.

Even more restrictive than raw execution speed is JavaScript's lack of concurrency. Anders highlights that JavaScript was fundamentally designed as a single-threaded environment, which is why the ecosystem relies heavily on callbacks, promises, and `async`/`await`. While single-threading shields developers from the subtle bugs, race conditions, and deadlocks common in languages with mutable state—unlike functional programming languages where immutable data simplifies reasoning—it leaves modern hardware severely underutilized. JavaScript offers web workers, but they do not support shared-memory concurrency; data passed between workers must be remoted or serialized (such as via JSON) rather than directly referencing shared in-memory object graphs.

With Moore's Law no longer delivering faster single-core clock speeds, hardware manufacturers instead supply more CPU cores. Because TypeScript could not take advantage of those cores through shared-memory multithreading, Anders notes the team was "leaving money on the table in multiple ways." To capture all the available hardware performance, they needed a language that produced fast native code and provided true shared-memory concurrency.

```mermaid flowchart TD accTitle: TypeScript Execution Constraints accDescr: Comparison of JavaScript execution limits versus native shared-memory architecture.

subgraph JS["JavaScript Compiler Constraints"] JS_Perf["2x–3x Compute Penalty vs Native"] JS_Thread["Single-Threaded Model"] JS_Workers["Web Workers (Isolated Memory / JSON Serialization)"] JS_Perf --- JS_Thread --- JS_Workers end

subgraph Native["Native Multi-Core Goal"] Native_Exec["Direct Native Execution"] Shared_Mem["Shared-Memory Concurrency across Cores"] Native_Exec --- Shared_Mem end

JS -.->|"Port to Native Runtime"| Native ```

[02:52](https://www.youtube.com/watch?v=rX9kkMonrG8&t=172s) Porting vs. Rewriting: Why Go Checked Every Box

When asked why Go was selected over popular modern systems languages like Rust or Zig, Anders clarifies an essential distinction: the team decided early on not to do a greenfield rewrite, but rather a direct port. Porting was mandatory to preserve the exact semantics, internal algorithms, and idiosyncratic behaviors of the existing TypeScript compiler, which millions of developers rely upon for backwards compatibility. A total rewrite from scratch would inevitably yield subtle discrepancies in type-checking decisions, different error diagnostics, or diverging behavior when resolving ambiguous language constructs.

Because the strategy was a line-by-line port, the target language had to match the fundamental architectural assumptions already baked into the TypeScript codebase. Specifically, the TypeScript compiler heavily depends on garbage collection and first-class functions (closures that capture outer state). Go emerged as the clear winner because it matched these design requirements without friction:

- **Mature Native Code Generation**: Highly robust, battle-tested compilation targets across all major operating systems and architectures. - **Built-in Garbage Collection**: Native memory reclamation that seamlessly accommodates existing JavaScript object lifetimes. - **Shared-Memory Concurrency**: Clean, powerful primitives for running concurrent operations across multiple CPU cores against shared data structures.

Anders notes that while other languages had individual strengths, virtually every alternative had characteristics that actively fought against their primary porting goals. For this specific workload, Go was uniquely aligned.

[04:47](https://www.youtube.com/watch?v=rX9kkMonrG8&t=287s) Why Rust Fell Short: The Problem with Circular Graphs and Borrow Checking

Ryan specifically asks what Rust lacked that prevented them from adopting it. Anders points directly to Rust's ownership model and borrow checker. While Rust avoids runtime garbage collection by enforcing strict compile-time ownership, its borrow checker fundamentally rejects circular references and shared mutable graphs. Anders emphasizes that the TypeScript compiler is "chock full of circular data structures"—including syntax trees with upward parent pointers, recursive type definitions, and complex symbol tables referencing one another in cycles.

The team actually attempted to make Rust work, but Anders admits with a laugh that "it just wasn't feasible." Successfully adapting the compiler to Rust would have required completely redesigning the data structures and solving a multitude of self-inflicted architectural problems instead of directly porting the logic. Furthermore, Anders points out that Rust would not have delivered meaningful advantages over Go in real-world code quality or multithreaded concurrency gains for this workload. Choosing Go allowed the team to get all the performance benefits ("all the bennies") with significantly less developer friction.

- Rust's borrow checker rejects cyclical graphs, whereas compiler ASTs require parent links, recursive types, and cross-referencing symbols. - Alternative memory management in Rust (such as reference counting or arena allocators) frequently requires reaching for `unsafe` blocks, compromising the desired safety guarantees. - Go provides out-of-the-box type safety and memory safety without stray pointers, treating garbage collection as a separate, fully integrated runtime concern rather than a manual burden imposed on every data structure.

## Notable quotes > [00:00](https://www.youtube.com/watch?v=rX9kkMonrG8&t=0s) performance and scalability — Anders Hejlsberg

> [00:00](https://www.youtube.com/watch?v=rX9kkMonrG8&t=0s) When running pure compute tasks in JavaScript, developers pay an immediate 2x to 3x performance penalty compared to native machine code. — Anders Hejlsberg

> [00:00](https://www.youtube.com/watch?v=rX9kkMonrG8&t=0s) JavaScript was fundamentally designed as a single-threaded environment, which is why the ecosystem relies heavily on callbacks, promises, and async/await. — Anders Hejlsberg

> [00:00](https://www.youtube.com/watch?v=rX9kkMonrG8&t=0s) leaving money on the table in multiple ways — Anders Hejlsberg

> [02:52](https://www.youtube.com/watch?v=rX9kkMonrG8&t=172s) the team decided early on not to do a greenfield rewrite, but rather a direct port. — Anders Hejlsberg

> [02:52](https://www.youtube.com/watch?v=rX9kkMonrG8&t=172s) Porting was mandatory to preserve the exact semantics, internal algorithms, and idiosyncratic behaviors of the existing TypeScript compiler — Anders Hejlsberg

> [02:52](https://www.youtube.com/watch?v=rX9kkMonrG8&t=172s) virtually every alternative had characteristics that actively fought against their primary porting goals. — Anders Hejlsberg

> [04:47](https://www.youtube.com/watch?v=rX9kkMonrG8&t=287s) chock full of circular data structures — Anders Hejlsberg

> [04:47](https://www.youtube.com/watch?v=rX9kkMonrG8&t=287s) it just wasn't feasible — Anders Hejlsberg

> [04:47](https://www.youtube.com/watch?v=rX9kkMonrG8&t=287s) Rust would not have delivered meaningful advantages over Go in real-world code quality or multithreaded concurrency gains for this workload. — Anders Hejlsberg

> [04:47](https://www.youtube.com/watch?v=rX9kkMonrG8&t=287s) all the bennies — Anders Hejlsberg

## Mentioned Anders Hejlsberg, Ryan Peterman, TypeScript, Go, JavaScript, Rust, Zig, C#, Moore's Law, JSON

## Video description Anders Hejlsberg is the creator of TypeScript and C#, and I asked him about how the TypeScript compiler got 10x faster through a rewrite in Go and his thoughts on how AI has impacted software engineering.

Watch the full episode: https://www.youtube.com/watch?v=cywK3XYYJ2o

[Source](https://www.youtube.com/watch?v=rX9kkMonrG8)

中文简报

Hejlsberg 选择 Go 而非 Rust 移植原生 TypeScript 编译器 Go 在 TypeScript 编译器移植中战胜 Rust,因 Rust 的借用检查器若不进行彻底的架构重写,便无法兼容代码库中的循环数据结构。 Anders Hejlsberg 解释称,由于纯计算执行性能损耗以及限制其利用多核硬件的单线程内存约束,TypeScript 编译器已不再适合局限于 JavaScript。团队并未采取可能破坏细微兼容行为的全新重写方案,而是选择直接移植,这需要原生代码生成、垃圾回收以及共享内存并发支持。Go 完美契合了这些需求;而在实验评估后,Rust 因借用检查器与编译器中高度循环的 AST、递归类型及符号图存在根本性冲突而被否决。 TypeScript 编译器正从 JavaScript 转向原生代码,以消除 2 至 3 倍的基础计算损耗并实现多核扩展。 (0:00) 团队选择了直接移植而非从零重写,以完整保留编译器语义、诊断信息以及对现有代码库的向后兼容性。 (2:52) 选用 Go 是因为其内置垃圾回收、头等函数以及共享内存并发机制高度契合 TypeScript 的架构假设。 (2:52) 团队曾对 Rust 进行评估,但因其借用检查器无法处理编译器中高度循环的数据结构(包括 AST 父指针和递归类型)而认定其不可行。 (4:47)

Reading summary

TypeScript creator Anders Hejlsberg explains that the team chose Go over Rust to port the TypeScript compiler because Go's native compilation, built-in garbage collection, and shared-memory concurrency directly matched the compiler's existing circular data structures and semantic requirements. Concurrency and Compute Limits in JavaScript (0:00) Anders Hejlsberg notes that the TypeScript team moved away from their original pure JavaScript implementation because the language incurs an immediate 2x to 3x performance penalty on compute-heavy tasks compared to native machine code. JavaScript was originally designed for lightweight browser scripts rather than intensive compiler workloads. More critically, JavaScript's single-threaded execution model restricts hardware utilization. While single-threading prevents race conditions and state-mutation bugs, it prevents programs from taking advantage of multi-core processors. JavaScript's web workers run in isolated memory spaces that require data serialization, such as JSON, rather than shared-memory references. Because Moore's Law no longer provides faster single-core clock speeds, Hejlsberg argues that TypeScript was leaving substantial hardware performance uncaptured. Preserving Compiler Semantics via a Direct Port (2:52) Rather than undertaking a greenfield rewrite, the team opted for a line-by-line port of the existing codebase. Hejlsberg emphasizes that millions of developers depend on TypeScript's backwards compatibility, which relies on nuanced internal algorithms, type-checking decisions, error diagnostics, and edge-case behaviors. A rewrite from scratch would have inevitably caused subtle behavioral divergences. To succeed, the target language had to support the existing architecture's foundational assumptions, specifically native garbage collection and first-class closures that capture outer state. Go fulfilled these requirements by combining mature native code generation across major platforms with built-in garbage collection and shared-memory concurrency. This permitted the team to preserve object lifetimes and execute multi-threaded operations across shared data structures without re-architecting the compiler's core logic. Borrow Checker Friction with Circular Compiler Graphs (4:47) When evaluating Rust, the team found its ownership model and compile-time borrow checker fundamentally incompatible with the compiler's internal design. Hejlsberg explains that the TypeScript compiler relies extensively on circular data structures, including abstract syntax trees with parent pointers, recursive type definitions, and cyclically linked symbol tables. An attempt to adapt the compiler to Rust proved unfeasible because satisfying the borrow checker would have forced an extensive redesign of these core data structures. Hejlsberg notes that workarounds such as reference counting or arena allocators often require reaching for unsafe code blocks, compromising Rust's safety guarantees. He concludes that Rust offered no real-world performance or concurrency advantages over Go for this workload, while Go delivered native speed and memory safety with substantially less friction. By choosing Go for a direct port, the TypeScript team gained native execution speeds and multi-core scaling while preserving the exact semantics of their existing compiler. The decision highlights that for systems heavily reliant on circular, mutable object graphs, runtime garbage collection can prove more practical than compile-time borrow checking.

Source quotes

[0:00] Anders Hejlsberg: performance and scalability [0:00] Anders Hejlsberg: When running pure compute tasks in JavaScript, developers pay an immediate 2x to 3x performance penalty compared to native machine code. [0:00] Anders Hejlsberg: JavaScript was fundamentally designed as a single-threaded environment, which is why the ecosystem relies heavily on callbacks, promises, and async/await. [0:00] Anders Hejlsberg: leaving money on the table in multiple ways [2:52] Anders Hejlsberg: the team decided early on not to do a greenfield rewrite, but rather a direct port. [2:52] Anders Hejlsberg: Porting was mandatory to preserve the exact semantics, internal algorithms, and idiosyncratic behaviors of the existing TypeScript compiler [2:52] Anders Hejlsberg: virtually every alternative had characteristics that actively fought against their primary porting goals. [4:47] Anders Hejlsberg: chock full of circular data structures [4:47] Anders Hejlsberg: it just wasn't feasible [4:47] Anders Hejlsberg: Rust would not have delivered meaningful advantages over Go in real-world code quality or multithreaded concurrency gains for this workload. [4:47] Anders Hejlsberg: all the bennies

Original transcript

[0:00] So with the the native rewrite of this [0:03] originally fully JavaScript compiler, [0:06] what was the problem you were trying to [0:08] solve with the rewrite and why did you [0:10] end up write rewriting it in native [0:12] code? [0:13] >> Well, I mean the the problem we were [0:15] trying to solve it's real simple [0:17] performance and scalability. [0:18] >> JavaScript was never really optimized [0:21] for compute inensive workloads like [0:24] compilers, right? JavaScript is more [0:26] about creating UI that runs in a [0:29] browser. Was originally intended for [0:31] just like maybe a 100 lines of code, but [0:34] now of course it's gotten to be a lot [0:35] more. Um, but it's not it's not a place [0:39] that that you would optimize for um for [0:43] the kind of workload that that we are. [0:46] So in JavaScript, first of all, you pay [0:49] a 2 to 3x perf penalty compared to [0:52] native code. I mean it depends on on the [0:54] workload you know but that's but if if [0:56] you're doing compute that's about where [0:58] it's at. Um and then secondly in [1:02] JavaScript there are a lot of [1:04] restrictions around use of concurrency. [1:06] Uh JavaScript was always engineered in [1:09] fact to be a single threaded language. [1:11] That's why we have callbacks and async [1:13] and and and whatever. It's because you [1:15] can't spin up threads. Um, and that's a [1:19] good thing mostly because concurrency in [1:22] a language with mutable data is very [1:25] very hard because you can have races and [1:27] deadlocks and all of this good stuff, [1:29] right? That's why functional programming [1:31] languages are easier with concurrency [1:34] because all the data is immutable and [1:36] it's much easier to reason about. Um [1:40] so JavaScript doesn't give you access to [1:43] concurrency other than web workers and [1:46] but web workers can't share data between [1:49] each other other than by remoting it. So [1:51] you can you can have one web worker [1:53] compute some something but if it wants [1:54] to give it to some other web worker it [1:57] has to turn it into JSON or it can't [1:59] just hand it objects and that means you [2:03] can't have one worker compute some data [2:06] structure and then have someone else use [2:09] it. In other words, you can't have [2:10] shared memory concurrency. And really [2:13] that's what we wanted in order to gain [2:16] all of the perf that we were leaving on [2:19] the table by not utilizing multi-core [2:21] CPUs that everyone has today, right? [2:24] Because Moore's law has stopped giving [2:25] us faster CPUs. It's giving us more CPUs [2:29] and we got to like find ways to use them [2:31] in our in our compute intensive [2:33] workloads or else we're leaving money on [2:35] the table. And so we were leaving money [2:36] on the table in multiple ways, right? [2:39] And so native code and that was why we [2:42] we looked for a language that [2:45] would get us out of both of those binds. [2:48] It had to be native and it had to have [2:50] access to shared memory concurrency. [2:52] >> I saw for the language choice you went [2:54] with Go. And when I think of all the [2:57] systems languages, the ones that are [2:58] often hot or maybe you know Rust or [3:01] Zigg, why did you choose Go for the [3:04] native rewrite? I think the decision [3:07] process was actually pretty structured. [3:10] You know, the first decision we made was [3:13] we're not going to rewrite. We're going [3:15] to port because only by porting can we [3:18] preserve the semantics and the [3:20] algorithms and the exact behavior of our [3:23] existing compiler which everyone depends [3:25] on for backwards compatibility. Now we [3:28] could have we could have cleaned the [3:30] slate and started completely from [3:31] scratch but we would have come we would [3:33] have come up with a different language [3:34] in the sense that it would give you [3:36] different errors or behave differently [3:38] in certain situations where it has to [3:40] make choices between multiple [3:43] possibilities and and what have you. [3:45] Right? So we wanted to port and that [3:48] meant our code makes certain assumptions [3:51] like our code for example assumes the [3:53] existence of garbage collection. It [3:56] assumes the existence of first class um [4:01] uh treatment of functions. You know, you [4:03] can have functions within functions and [4:05] you can close over over out of state and [4:07] so forth. Um and as we evaluated all of [4:11] these, [4:12] go was was the one that checked the most [4:14] boxes. You know, it gives us it gives us [4:19] very robust and mature native code [4:21] generation on all major platforms. It [4:25] has garbage collection and it has access [4:28] excellent access to shared memory [4:30] concurrency. Um, and those were like the [4:33] high order bits that we wanted to check. [4:34] And every other language had something [4:39] that kind of worked against those [4:40] objectives. So for this particular [4:42] workload, Go was the right was the right [4:44] choice for us and it's worked out well. [4:47] >> If you think about Rusk, what didn't it [4:50] have that if it had it, you would have [4:52] picked it? I mean I think there are [4:54] there are there are two things um it [4:56] doesn't have uh garbage collection [5:00] it's done manually you know uh well or [5:03] it's done through the borrow checker but [5:05] the borrow checker doesn't allow [5:07] circular data structures and our [5:10] compiler is chalk full of circular data [5:12] structures we have trees with parent [5:14] pointers we have types that are [5:16] recursive we have symbols that refer I [5:18] mean it's everywhere and like I said if [5:20] we had chosen to rewrite we could [5:22] probably solved all of that, but it [5:25] wouldn't have been just porting the [5:27] code. It would also have been like [5:28] solving a whole bunch of new problems [5:30] that we had bought ourselves by by going [5:32] that route. We tried [laughter] [5:35] and it just wasn't feasible, you know, [5:38] uh and and and so so we were we were [5:40] just trying to optimize for, you know, [5:43] doing as little work as possible to get [5:45] us to the payout, which is which and [5:49] honestly, Rust is no better when it [5:51] comes to like the quality of the [5:52] generated code or the or the the [5:55] concurrency gains that we could have [5:56] gotten out of it. [5:58] Go just it's great. I mean, so so we got [6:02] we got all the bennies with for less [6:04] work by by going that route. [6:06] >> I know some languages they're when you [6:08] say they're garbage collected, they [6:11] >> there's something in the the language [6:13] itself that is doing garbage collection, [6:15] but um there's also independent [6:19] libraries that can provide garbage [6:21] collection, right? [6:23] There is, but it it but it comes often [6:26] with a whole bunch of restrictions and [6:28] and and it doesn't come necessarily with [6:31] the safety guarantees that we were [6:33] looking for. I mean like Go is type safe [6:35] and memory safe. uh meaning that you [6:38] don't get to just like have stray [6:40] pointers or or whatever where rust you [6:44] can do ref counting or you can do you [6:46] can do all sorts of different strategies [6:48] but there's always like that little bit [6:50] of unsafe where you have to like do this [6:53] in order to make it all work you know uh [6:56] where where if garbage collection is [6:59] engineered into the language it really [7:01] is a a separate concern that is you you [7:04] you don't you don't have to do anything [7:06] special in I mean of course you you you [7:09] have to like not hold on to data that [7:11] you no longer need and whatever you know [7:13] but that's true of ref counting as well [7:15] right but but it is inherent in in the [7:18] language