#Rust

Dada: A Programming Language Experiment in Streamlined Rust Semantics

Tech Essays Reporter
6 min read

An exploration of Dada, a personal programming language project that reimagines Rust's ownership model with fewer distinctions and compile-time reflection capabilities through WebAssembly.

In the ever-evolving landscape of programming language design, personal experiments often yield insights that transcend their original scope. Such is the case with Dada, a programming language project that began in 2021 as a gradual typing experiment and has since transformed into something far more ambitious—a streamlined reimagining of Rust's ownership model with unique compile-time capabilities.

The Origins of Dada

The journey began with a simple question: could a gradually typed language make Rust's ownership concepts more accessible to newcomers? The initial vision for Dada was to create a language where developers could start writing code without any type annotations and gradually add types as they became more comfortable with the concepts. This wasn't merely about removing type annotations—it was about creating an interactive learning environment.

The prototype included an interactive playground that would visualize the "borrow checker" state, what Dada calls "permissions," as developers stepped through their code. The idea was revolutionary in its simplicity: instead of wrestling with cryptic compiler errors, developers could see exactly how their code affected ownership and borrowing in real-time. This approach promised to make Rust's notoriously difficult borrow checker more approachable.

However, the gradually typed approach revealed fundamental limitations. To provide meaningful feedback without type annotations, the system had to track extensive runtime information—essentially what tools like miri do for Rust. While this made for an excellent teaching tool, it added significant complexity to the language design for what would only benefit developers in the earliest stages of their learning journey.

A Streamlined Vision Emerges

This realization led to a pivotal decision: abandon gradual typing in favor of focusing on the static type checking aspects that made Rust powerful. The new vision for Dada crystallized into something both familiar and revolutionary—"Rust where you never have to call as_ref()."

In Rust, developers frequently encounter semantically equivalent types that differ only in their representation. Consider the distinction between &Option<String> and Option<&String>—both represent the same conceptual data, but Rust forces developers to carefully distinguish between them. Dada eliminates this friction entirely. Whether you're working with &Vec<String>, &Vec<&String>, &[String], or &[&str], these are all treated as the same type.

This streamlining extends beyond mere convenience. By collapsing these distinctions, Dada creates a more intuitive programming experience while maintaining the core principles of ownership-oriented programming. The language achieves this without resorting to heap allocation for everything or introducing garbage collection—a testament to the elegance of its underlying design.

A Fancier Borrow Checker

Dada's borrow checker represents another significant departure from Rust's approach. While it doesn't yet implement view types, it already demonstrates many of the capabilities that make Rust's borrow checker so powerful. The system supports internal borrows, allowing developers to create structs with fields that borrow from other fields within the same struct. It also implements borrow checking without lifetimes, simplifying one of Rust's most challenging concepts.

These innovations aren't merely academic exercises. They represent practical improvements that could potentially be brought back to Rust itself. The experience of designing and implementing these features in Dada provides valuable insights into how ownership systems can evolve.

WebAssembly as a Foundation

The decision to target WebAssembly natively proved to be transformative. Initially chosen for its simplicity and clean assembly language semantics, WebAssembly offered several advantages: easy compiler backend development, built-in FFI solutions through components, and access to WASI's comprehensive standard library.

However, the true power of WebAssembly emerged in an unexpected way. By structuring the Dada compiler to compile functions on-demand to WebAssembly bytecode, the team discovered they could execute compiled code directly from within the compiler using wasmtime's high-quality JIT. This created a sandboxed execution environment that runs extremely fast.

This architecture effectively provides compile-time reflection capabilities "almost for free." Functions can be compiled and executed during compilation to produce code that other parts of the compilation process will use. The result is something akin to miri or Zig's comptime functionality, but achieved through the natural architecture of targeting WebAssembly.

The Road Ahead

Despite its promising foundations, Dada remains a work in progress. The compiler doesn't yet work reliably because the language continues to evolve before reaching stability. This constant iteration isn't a bug—it's a feature. Dada serves as a "stress relief valve" for its creator, a space where backwards compatibility concerns and RFC processes don't constrain experimentation.

Yet this experimental playground has already yielded practical results. The experience of designing Dada directly influenced the new salsa design, which is now used by both rust-analyzer and Astral's ty. This demonstrates how personal language experiments can contribute to the broader ecosystem in unexpected ways.

Why It Matters

The significance of projects like Dada extends beyond their immediate technical contributions. In an era where large language models are transforming how we think about programming, Dada represents a different kind of exploration—one focused on making programming languages more intuitive and powerful for humans.

The creator's journey also reflects a broader truth about language design: it's often driven by personal curiosity and the desire to solve specific problems. The decision to return to Dada after a year-long hiatus, prompted by renewed interest and the perfect opportunity to document the work through blogging, illustrates how these projects evolve organically.

The Trade-offs

Dada's streamlining comes with trade-offs. By eliminating distinctions between semantically equivalent types, the language sacrifices some of the flexibility that makes Rust so powerful. Projects like Rust for Linux, which rely on precise control over memory representation, might not be feasible in Dada's more constrained environment.

However, these trade-offs are intentional and well-considered. The goal isn't to replace Rust but to explore what a more streamlined ownership-oriented language might look like. The insights gained from this exploration could inform future language designs or even influence how Rust itself evolves.

Looking Forward

The plan moving forward involves documenting the type system, borrow checker, and compiler architecture through a series of blog posts. This documentation serves dual purposes: helping the creator rediscover the work and sharing the insights with the broader community.

The excitement about potentially creating a live demo is palpable, even as the practical challenges of getting the compiler working reliably remain. The journey from a gradual typing experiment to a WebAssembly-powered language with sophisticated compile-time capabilities demonstrates how language design often takes unexpected turns.

In the end, Dada represents something profound about programming language development: sometimes the most valuable insights come not from trying to build the perfect language, but from creating a space where experimentation is unconstrained and learning is continuous. Whether or not Dada ever becomes a production-ready language, its contributions to our understanding of ownership systems, compile-time execution, and language design principles are already significant.

As the creator notes, designing new programming languages is how they relax—and perhaps that's precisely why projects like Dada matter. They remind us that at its core, programming language design is a creative endeavor, driven by curiosity and the joy of exploration rather than just practical necessity.

Comments

Loading comments...