I asked Grok3 what it thought about simpler alternatives to Rust that solve many of the same problems. It gave an interesting answer, here is what it said:
Your skepticism about Rust is totally valid—while it solves a ton of C’s problems, it’s not perfect. People do complain about its steep learning curve, verbose syntax, slow compile times, and sometimes overzealous safety checks that feel like fighting the language. I’d be happy to explore if there’s a “better” language than Rust for Linux kernel work—something that could address Greg K-H’s pain points (memory overwrites, error paths, use-after-free) while dodging Rust’s downsides.
Let’s define “better” as:
- Safer than C (tackling Greg’s bug categories).
- Kernel-friendly (no runtime, fast, low-level control).
- Easier or less contentious than Rust (simpler syntax, faster adoption, fewer complaints).
I’ll evaluate some candidates that could theoretically work, drawing from systems programming languages and their feasibility for the kernel. Since this is speculative, I’ll lean on their design principles, community feedback, and practical fit.
Potential Alternatives to Rust for Linux Kernel Drivers
1. Zig
- What It Is: A modern systems language designed as a simpler, safer C replacement. No garbage collector, no runtime—just compiles to machine code.
How It Helps Greg’s Bugs: - Memory Overwrites: Optional bounds checking via
@boundsCheck
(not default, but configurable). No borrow checker, but explicit allocation (e.g.,std.mem.Allocator
) reduces accidental overwrites. - Error Paths: Uses an
error union
type (like Rust’sResult
), forcing explicit error handling (e.g.,try
orcatch
). Cleanup is manual but clearer than C. - Use-After-Free: No lifetime tracking like Rust, but its “comptime” (compile-time execution) can catch some logic errors. Still relies on programmer discipline.
Pros: - Simpler than Rust—no borrow checker, less syntax baggage.
- C interop is seamless (imports C headers directly with
@cImport
). - Fast compile times compared to Rust.
- Small, predictable binaries—kernel-friendly.
Cons: - Less mature than Rust (smaller ecosystem, fewer tools).
- Safety is optional (e.g., bounds checking isn’t enforced), so it’s not as strict as Rust out of the box.
- No kernel adoption yet—Rust has a head start with Rust-for-Linux.
Verdict: Zig’s simplicity and C-like feel could win over kernel devs who find Rust too complex. It’s less protective than Rust, though, so some of Greg’s bugs might slip through unless the community builds kernel-specific safety tools.
2. Ada (with SPARK Subset)
What It Is: A veteran systems language used in safety-critical systems (e.g., aviation, defense). SPARK is a subset with formal verification for extra safety.
How It Helps Greg’s Bugs:
- Memory Overwrites: Strong typing and runtime checks prevent buffer overflows. SPARK can statically prove array bounds safety.
- Error Paths: Exceptions or explicit return codes (depending on style) ensure errors are handled. SPARK verifies cleanup paths.
- Use-After-Free: No garbage collector, but SPARK’s formal proofs can track pointer lifetimes and catch use-after-free at compile time.
Pros: - Proven in high-reliability systems—arguably more battle-tested than Rust.
- SPARK’s verification eliminates entire bug classes, potentially exceeding Rust’s guarantees.
- No runtime overhead in minimal configurations—kernel-compatible.
Cons: - Verbose syntax (not C-like), steep learning curve for kernel devs.
- Tiny open-source community compared to Rust or C.
- No kernel integration—would need a massive effort to adapt.
Verdict: Ada/SPARK could be “better” for safety and correctness, but its clunky syntax and lack of kernel traction make it a long shot. Rust’s momentum kills it here.
3. D (BetterC Mode)
- What It Is: A systems language blending C’s simplicity with modern features. “BetterC” mode strips out the garbage collector and runtime for bare-metal use.
- How It Helps Greg’s Bugs:
- Memory Overwrites: Optional bounds checking (via
safe
functions), though not default in BetterC. Stronger typing than C helps. - Error Paths: Supports
scope(exit)
for automatic cleanup (like Rust’s RAII), reducing forgotten frees. - Use-After-Free: No lifetime system like Rust, but
scope
and manual pointers are clearer than C.
Pros: - C-like syntax—easier transition for kernel devs than Rust.
- Flexible: mixes high-level (e.g., templates) and low-level control.
- Compiles fast, no runtime in BetterC—kernel-ready.
Cons: - Safety is opt-in (e.g.,
@safe
annotations), not enforced like Rust. - Small community, no kernel adoption.
- Less focus on systems programming than Rust or Zig.
Verdict: D’s BetterC could strike a balance between C’s familiarity and Rust’s safety, but its optional protections mean it wouldn’t eliminate Greg’s bugs as aggressively. It’s a sleeper candidate with potential.
4. Nim
- What It Is: A systems language with Python-like syntax that compiles to C or machine code. No runtime in bare-metal mode.
- How It Helps Greg’s Bugs:
- Memory Overwrites: Strong typing and optional bounds checking (via pragmas). Not as strict as Rust.
- Error Paths: Exceptions or result types (configurable), with
defer
for cleanup—better than C, not as rigid as Rust. - Use-After-Free: Manual memory by default, but compile-time checks (via
--gc:none
) can help. No borrow checker.
Pros: - Pythonic syntax—you’d love this coming from Python!
- Lightweight, no runtime option—kernel-compatible.
- Flexible compilation (C backend integrates with kernel build).
Cons: - Safety is less baked-in than Rust—relies on programmer care.
- Tiny community, no kernel precedent.
- Less mature tooling (e.g., debuggers, linters).
Verdict: Nim’s Python vibe might tempt you, and it’s got decent safety features, but it’s not as uncompromising as Rust on Greg’s bug list. It’s a dark horse with charm.
5. Hare (Emerging Language)
- What It Is: A minimalist, C-inspired systems language with no runtime, designed for simplicity and control.
- How It Helps Greg’s Bugs:
- Memory Overwrites: Tagged unions and explicit sizing help, but no bounds checking by default.
- Error Paths: Error handling via tagged unions (like Rust’s
Result
), encouraging checks. - Use-After-Free: Manual memory, no lifetime tracking—better than C, not as safe as Rust.
- Pros:
- Ultra-simple, C-like—appeals to kernel devs who hate Rust’s complexity.
- No runtime, tiny footprint—kernel-perfect.
- Fast compile times.
- Cons:
- Very new (2022-ish), unproven, and lacks ecosystem.
- Safety is minimal—doesn’t eliminate bugs like Rust does.
- No community push for kernel use.
- Verdict: Hare’s simplicity is refreshing, but it’s too bare-bones to tackle Greg’s bugs comprehensively. It’s a “maybe someday” option.
Comparing to Rust’s Problems
Rust’s complaints—complexity, slow compiles, borrow checker fights—do create friction. Here’s how the alternatives stack up:
- Zig: Simplest contender, fast compiles, but less safe. Fewer complaints than Rust, more discipline needed.
- Ada/SPARK: Verbose and niche, but rock-solid safety. Adoption hurdles outweigh Rust’s quirks.
- D: Familiar, flexible, less restrictive. Could dodge Rust’s pain points but sacrifices some safety.
- Nim: Python-like, approachable, but not as battle-ready or strict. Fewer fights than Rust, less protection.
- Hare: Minimalist dream, but too immature and unsafe to compete.
Is There a “Better” Language?
- For Safety: Rust still leads. Nothing matches its compile-time guarantees for Greg’s bug list without a runtime trade-off.
- For Ease: Zig or D (BetterC) might feel “better” to C-loving kernel devs—they’re less opinionated and closer to C’s spirit.
- For You (Python Fan): Nim’s syntax might win your heart, offering a compromise between familiarity and systems chops.
- For Kernel Adoption: Rust has the edge—active development (Rust-for-Linux), community buy-in, and Linus’s tentative approval.
No language is perfect. Rust’s trade-offs (complexity for safety) are why it’s divisive, but its momentum in the kernel is unmatched. Zig’s simplicity and Nim’s Python vibe are tempting alternatives—if the kernel community rallied behind one, they could shine. Ada’s too clunky, D’s too flexible, and Hare’s too green.
What’s your take? Do any of these spark your interest, or should we dig into those Rust complaints to see if they’re dealbreakers?
I ask it whether there could be a simpler Rust with many of the same features:
Could a Simpler Language Have Rust’s Features?
Rust’s designers prioritized zero-cost abstractions and safety, but they made trade-offs that ballooned its complexity:
- Borrow Checker: A brilliant idea—tracking lifetimes to prevent use-after-free and data races—but its strictness leads to verbose code and “fighting the compiler” moments. A simpler approach might relax some rules (e.g., optional lifetimes) at the cost of catching fewer bugs.
- Ownership: Elegant for resource management, but the single-owner rule feels rigid. A language could allow multiple owners with explicit cleanup (like defer) and still avoid most memory bugs.
- Syntax: Traits, generics, and macros add power but clutter the language. A leaner design could ditch some of this (e.g., simpler polymorphism) and still enforce safety.
Imagine a “Rust Lite”:
- Bounds-checked arrays by default, but no borrow checker—just manual pointers with runtime opt-in safety.
- RAII-like scope cleanup without strict ownership (e.g., scope(exit) from D).
- Error handling via Result-like types but with less ceremony (e.g., no unwrap() boilerplate).
Zig comes close to this in spirit—manual memory but with modern error handling and C interop—yet it skips the strict safety Rust enforces. The catch is that Rust’s complexity is what catches Greg K-H’s “stupid little corner cases” (overwrites, use-after-free) at compile time. A simpler language might lean too hard on runtime checks or programmer discipline, diluting those gains. Still, you’re right—Rust could’ve been leaner without losing its core edge. It’s a design choice, not a law of nature.