{"article":{"slug":"the-golden-spike-and-resurrecting-the-vale-n-programming-language","title":"The Golden Spike, and Resurrecting the Vale(n) Programming Language","subtitle":null,"summary":"Evan Ovadia describes patching rustc so Valen can call Rust generics, implement Rust traits from Valen closures, and borrow-check across the boundary—true Rust interop beyond the C ABI.","content_type":"blog_post","language":"en","canonical_url":"https://verdagon.dev/blog/golden-spike-reviving-vale-valen","author":{"name":"Evan Ovadia","url":null,"person_slug":null,"person_url":null},"authored_by":"human","publisher":{"name":"Verdagon","url":"https://verdagon.dev/","listing_slug":null,"listing":null},"topics":[{"name":"Programming","slug":"programming","url":"https://listedarticles.com/topics/programming"},{"name":"Rust","slug":"rust","url":"https://listedarticles.com/topics/rust"},{"name":"Systems Programming","slug":"systems-programming","url":"https://listedarticles.com/topics/systems-programming"},{"name":"Open Source","slug":"open-source","url":"https://listedarticles.com/topics/open-source"}],"about_listings":[],"cover_image_url":null,"license":"all-rights-reserved","word_count":3809,"reading_minutes":17,"published_at":"2026-09-17T00:00:00.000Z","added_at":"2026-09-19T06:09:29.171Z","updated_at":"2026-09-19T06:09:29.171Z","added_via":"api","contributor":{"type":"agent","name":"ListedStartups Using Bot","registered":false},"profile_url":"https://listedarticles.com/articles/the-golden-spike-and-resurrecting-the-vale-n-programming-language","markdown_url":"https://listedarticles.com/articles/the-golden-spike-and-resurrecting-the-vale-n-programming-language.md","example":false,"citation":"Evan Ovadia, Verdagon. \"The Golden Spike, and Resurrecting the Vale(n) Programming Language.\" 17 Sept 2026. https://verdagon.dev/blog/golden-spike-reviving-vale-valen (all-rights-reserved)","access":{"human_view":"preview","full_text_available":true,"source_url":"https://verdagon.dev/blog/golden-spike-reviving-vale-valen"},"body_markdown":"There was an incredible moment on May 10th, 1869, when railroad builders finally reached their goal of **joining the east coast rail network with the west coast rail network.**\n\nIn that moment, the first United States transcontinental railroad was born. [0](#note0)\n\nAfter six years of work, [1](#note1) the two rail networks finally joined up in Promontory Summit, Utah.\n\nTo commemmorate the moment, they drove a 17.6-karat **golden spike** into the final tie of the railroad.\n\nTo me, the phrase \"[golden spike](https://en.wikipedia.org/wiki/Golden_spike)\" means an incredibly difficult task joining two separate, distant systems. [2](#note2)\n\nHere in the compiler world, it often feels like every compiler is *worlds* apart from every other compiler.\n\nWhen a language wants to call into another language, one usually has to do acrobatic rituals involving the C ABI, writing \"C bindings\" (wrapper functions), and sometimes making deals with various deities.\n\nAnd even with all that, cross-language generics [3](#note3) don't work (C doesn't have generics), and things definitely won't be memory-safe across the boundary (because C!).\n\n**This is why it's so tricky to build a language on top of Rust.** And then, having memory safety and generics across the C boundary is impossible. And even if it were possible, integrating two compilers is *very, very difficult.*\n\nAnd so I thought to myself, that *this sounds like a worthy goal for 2026!*\n\nSo here we are!\n\nThis post is going to be about the start of my *ridiculously over-ambitious* endeavor to create a language with **true Rust interop,** with a compiler that talks to rustc seamlessly enough that we can use my Rust graphics library [4](#note4) with cross-language generics, memory safety, linear types, Nick Smith's [group borrow checking](https://verdagon.dev/blog/group-borrowing), and a bunch of other juicy, juicy features.\n\n\nTentatively, I'm calling this new language \"Valen\" [5](#note5)  [6](#note6) since it's similar (but different enough) to my existing language [Vale](https://vale.dev/).\n\nSo read on, and this post will explain the journey so far!\n\nThis entire endeavor is *extremely experimental* and many things have holes and sharp edges (see side-note [7](#note7)). It's going to be a glorious few months of cleaning, rewriting, and solidifying this horror before I unleash it on the world. Feel free to check out the [source code](https://github.com/valen-lang/valen), and beware, here be dragons! [8](#note8)\n\n\n(interesting tangential thoughts)\n\n      \n0\nMy stance: if you want someone to take the time to read something, take the time to write it by hand.\n\n \n\nThanks for reading =)\n\n1\n...2 days before this date new troubles arose for the Union Pacific at Piedmont where the car in which Dr. T. C. Durant, the vice-president, was riding was disconnected from the train and shunted onto a side line by some 400 workers (one reporter says 500) who demanded their pay, unpaid since January 1.\n\n \n\nAbsolute madlads!\n\n2\nOn Google Earth, I joined the local-editing app to cloud storage, finally enabling online editing. We called that project \"golden spike\" too. This whole rust interop endeavor brings me back to that moment!\n\n \n\n3\nExplained more below, but basically, being able to use SomeRustStruct<OtherLangStruct>.\n\n \n\n4\n \n\n5\nAnd since its compiler is valenc, we can pronounce it like \"Valence\", which sounds nice!\n\n \n\n6\nAlso, it's pretty funny to me that now V, Val, Vale, Vala, and Valen are all languages that have existed. I'm tempted to release a tiny Rust-interop language for others to use, and call it Va.\n\n \n\n7\n \n\nTo be clear about what works today:\n\n- Valen has linear types, but we can't yet declare that an existing Rust type is linear.\n- Valen has group borrowing (except for closures), and it borrow checks across the boundary.\n- Structs work across the boundary, even Valen structs that implement Rust traits. But they must be zero-sized (filled structs work in my separate prototype, not yet in Valen).\n- Generational references are temporarily disabled, hopefully coming back soon.\n\n8\n \n\n        Green dragons, specifically.\n\nRust is one of my favorite languages [9](#note9) because of its speed, safety, and ecosystem... but there are definitely some things that would make it **simpler and overall nicer** for my use cases.\n\nMy wish list:\n\n- \nA [borrow checker without shared-xor-mutable](https://verdagon.dev/blog/group-borrowing)\n- \nFaster run-time performance [10](#note10)\n- \nResource safety via [linear types](https://www.youtube.com/watch?v=IpuvQUVB8Cg&t=2s)\n- \n[Zig-style comptime](https://verdagon.dev/blog/impossible-optimization)[11](#note11)\n- \n[Generational references](https://verdagon.dev/blog/generational-references)\n- An Rc that can hold mutable data without RefCell or Cell\n- \n...and a lot of other features [12](#note12)\n\nBut I don't just want a new language, because I wouldn't have access to Rust's ecosystem of libraries.\n\nSo how do we do all that, while being able to call into Rust code?\n\n9\nYou guessed it, it's a three-way tie between C++, Scala, and Rust!\n\n \n\n10\n \n\n11\n \n\nZero-cost compiler-optimized DSLs, anyone?\n\n12\n \n\n        \nThis seemed impossible for a *lot* of reasons, explained in [Crossing the Impossible FFI Boundary, and My Gradual Descent Into Madness](/blog/exploring-seamless-rust-interop-part-2).\n\nI had forgotten that the post included this image:\n\n\nHopefully we don't have to do that! (*...foreshadowing intensifies...* [13](#note13))\n\nAnyway, the **more concrete, specific goal** was for this program to work: [14](#note14)\n\nvalen\n\n      ```\nimport rust.nobiliav.NobiliaWindow;\nimport rust.nobiliav.FrameInput;\nimport rust.nobiliav.MainLoopCallback;\n... // Import constants\nexported func main() int {\n  w = NobiliaWindow.new(1200, 900);\n  ... // set up the terrain and entities\n  w.main_loop(\n    // Make a Valen closure that implements the Rust `trait MainLoopCallback`\n    &MainLoopCallback((win, input) => {\n      key = input.key();\n      if (key == key_arrow_left()) {\n        win.rotate_camera(-4, 0);\n      } else if (key == key_arrow_right()) {\n        win.rotate_camera(4, 0);\n      } else if (key == key_arrow_up()) {\n        win.rotate_camera(0, 4);\n      } else if (key == key_arrow_down()) {\n        win.rotate_camera(0, -4);\n      }\n    }));\n  \n  return 0;\n}\n```\nOf course, this required answering a *lot* of very hard questions.\n\nI'll ask them in the code:\n\n```\n// How do we know what things are importable from Rust?\nimport rust.nobiliav.NobiliaWindow;\nimport rust.nobiliav.FrameInput;\nimport rust.nobiliav.MainLoopCallback;\n...\nexported func main() int {\n  // How do we know what static methods exist in a Rust type?\n  // How does Valen know what parameters rustc expects here?\n  w = NobiliaWindow.new(1200, 900);\n  ...\n  w.main_loop(\n    // How do we make a Valen closure implement a Rust trait?\n    // How do we know the methods on a Rust trait?\n    &MainLoopCallback(\n      // How will Rust call BACK into Valen code? Monomorphizer integration?\n      // Can the optimizer inline a Valen function into a Rust function and vice versa?\n      (win, input) => {\n        key = input.key();\n        if (key == key_arrow_left()) {\n          win.rotate_camera(-4, 0);\n        } else if (key == key_arrow_right()) {\n          win.rotate_camera(4, 0);\n        } else if (key == key_arrow_up()) {\n          win.rotate_camera(0, 4);\n        } else if (key == key_arrow_down()) {\n          win.rotate_camera(0, -4);\n        }\n      }\n    )\n  );\n  return 0;\n}\n```\nHowever, these questions hide the real, central question underneath it all.\n\n13\nBack then, I thought I would need to reimplement Rust's generics and traits systems.\n\n \n\n14\n \n\n        As many of you know, the most common way for other languages to call into Rust is if the Rust library exposes its functions as extern \"C\", and exposes its types as repr(C).\n\nThis is because C is the de-facto universal translator between low-level languages.\n\nIt's also because [Rust doesn't have a stable ABI yet.](https://www.reddit.com/r/rust/comments/ss2p6c/what_does_it_mean_when_people_say_that_rust_does/) [15](#note15)\n\n\"What's an ABI?\" you might ask.\n\nTo simplify a bit, an \"ABI\" is basically how Rust answers these questions:\n\n- \"If the user calls a function, passing a struct by value, do we compile it to pass-by-reference, or do we pass it in a register?\"\n- \n\"If the user specifies a bool, then a u64 integer, then a bool, do we put those two bools next to each other to save space?\" [16](#note16)\n\nAlas, Rust hasn't yet committed to an ABI.\n\nSo, using the C ABI (with extern \"C\" and repr(C)) is the only option for other languages to call into Rust.\n\n**But C doesn't have generics.** There's no such thing as void do_something<T>(T* thing) in C.\n\nThis means that other languages can't call into generic Rust functions.\n\n**This is a problem for us,** because... well, recall this main_loop call from above:\n\n```\nexported func main() int {\n  ...\n  w.main_loop(&MainLoopCallback((win, input) => { ... }));\n  ...\n}\n```\nHere's what Rust's main_loop actually is:\n\nrs\n\n      ```\nimpl NobiliaWindow {\n  pub fn main_loop<C: MainLoopCallback>(&mut self, cb: &mut C) {\n    ...\n  }\n  ...\n}\n```\nThat's right, that parameter right there is *generic*, taking anything that implements trait MainLoopCallback.\n\nBut the C ABI has no generics! But we need generics. Blast! We're stuck.\n\nSo **the central question,** the central mystery to solve, is *how do we do cross-language generics?*\n\n15\n \n\n\"ABI\" stands for \"Application Binary Interface\".\n\n16\n \n\n        There are actually two levels to this question:\n\n1. How do we call into a Rust generic function?\n2. \nHow do we call into a Rust generic function *that calls back into Valen?*[17](#note17)\n\nHere's a simpler example to illustrate the first level:\n\n```\nimport rust.std.vec.Vec;\nexported func main() int {\n  my_vec = Vec<int>();\n  my_vec.push(21);\n  my_vec.push(42);\n  // Returns 42\n  return my_vec.pop().unwrap();\n}\n```\nWhen we say my_vec.push(21), we're calling the generic function Vec<T>::push.\n\nLuckily, in the [Madness](/blog/exploring-seamless-rust-interop-part-2) post, I managed to get it working for C:\n\nc\n\n      ```\n// Import a rust type directly (no bindings!)\n#pragma rsuse VecInt = std::vec::Vec<u64>\n// Must specify each method you want to use\n#pragma rsfn VecInt_with_capacity = VecInt::with_capacity\n#pragma rsfn VecInt_capacity = VecInt::capacity\n#pragma rsfn VecInt_drop = VecInt::drop\n// Plus the magic incantation, and...\n#include \"rust_deps/rust_deps.h\"\n#include <stdio.h>\nint main() {\n  // ...presto, we can use rust libraries!\n  VecInt argv = VecInt_with_capacity(42);\n  printf(\"Capacity: %lu\\n\", VecInt_capacity(&argv));\n  VecInt_drop(argv);\n  return 0;\n}\n```\nstdout\n\n      `Capacity: 42`\nI called this my \"most cursed exploration\" because of the acrobatics it had to do:\n\n- It ran rustdoc (yes, the documentation generator!) and parsed its json output with the rustdoc_types library, to figure out what types were usable, and what impls had what methods.\n- It ran rustc with a \"scouting program\" that literally just prints sizes; println!(\"{}\", size_of::<Vec::<u64>>()) prints 24 bytes. (Thanks to matklad and literallyvoid for helping me improve this part!)\n- It then ran rustc again with a \"instantiation program\" which generated a \"wrapper C library\" that the C program could statically link to.\n- Vale's memory safety approach didn't really line up with Rust's, so a user had to stick to certain patterns.\n\nAnd it had some limitations:\n\n- We need to fully spell out the generic args, like VecInt = std::vec::Vec<u64>.\n- \nWe need to import *every* method we use, in a #pragma rsfn.\n\nBut the hardest limitation is that we can't make a C type implement a Rust trait.\n\nThat means you can't use HashMap::get, because its k key must implement the Hash and Eq traits.\n\nStill, as cursed as it was, the 2024 solution was actually a pretty good start.\n\nAbove, I said that there are two levels to the cross-language generics question:\n\n1. How do we call into a Rust generic function?\n2. How do we call into a Rust generic function that calls back into Valen?\n\nThe 2024 solution solved most of #1 in spirit, even though it got information from Rust in an odd way.\n\nAnd it hinted that there might be an answer to #2, if a language was designed with it in mind and Did Things Properly™.\n\n17\n \n\n        \nOf course, there's no such thing as \"doing things properly\", because **everything I'm about to say is *very* unsupported by the Rust compiler.**\n\nBut I felt like the next step in the endeavor would be to talk to rustc directly, [18](#note18) instead of invoking it (twice!) from the outside. [19](#note19)\n\nAnd it turns out, one can actually **run the rust compiler as a library,** using [rustc_driver](https://rustc-dev-guide.rust-lang.org/rustc-driver/intro.html)'s run_compiler function!\n\n```\nuse rustc_driver::{Callbacks, Compilation};\n...\nfn main() {\n  ...\n  let callbacks = ValenRustInteropCallbacks { ... };\n  ...\n  rustc_driver::run_compiler(&rustc_args, &mut callbacks);\n```\nThe two arguments to run_compiler influence what rustc does.\n\n- \nrustc_args tells rustc **what Rust libraries we want to use** , so it loads and compiles them, so the Valen typing pass can ask questions about them.[20](#note20)\n- \ncallbacks specifies observers that tell us when rustc has loaded and compiled all of its dependencies. [21](#note21) Then, the Valen typing pass can ask rustc questions about the Rust crates it depends on, and generate Rust MIR functions from our Valen code.\n\nHowever, there was a problem with that: Valen couldn't lower to Rust's MIR, because it didnt't have the capabilities Valen needed:\n\n- \nMIR's mutable references are unique, which means it can't do our [Group Borrowing](https://verdagon.dev/blog/group-borrowing) memory safety approach, which allows shared mutable references.\n- MIR doesn't let us specify LLVM's alias groups / !alias.scope on load/store instructions, which is something that makes group borrowing faster.\n- MIR can't express comptime metaprogramming, which is on my dream language wish list.\n\nRust's MIR was designed for Rust. So it's a great target for Rust code, not Valen code... alas.\n\nIf anyone wants to know how to do this the MIR way, let me know! Happy to point you in the right direction.\n\nOf course, if Valen used its own IR and backend instead of Rust's, that would mean that the compilers would need to **work with each other** in a very interesting dance.\n\n18\nOf course, doing this requires using the private, unstable APIs. Yikes!\n\n \n\n19\n \n\n20\n \n\nTo do this, we actually:\n\n- Parse the Valen source files, looking for any imports (like import rust.glass_domino.Window).\n- Generate a Rust lib.rs file containing equivalents (like use glass_domino::Window;).\n- Add that \"lib.rs\" path into rustc_args.\n- Add dependency libraries' paths to rustc_args (like --extern glass_domino=target/.../libglass_domino.rlib) so rustc knows where to find it (well, cargo does this).\n\n(This is how it still works today)\n\n21\nThis is rustc's after_expansion callback, run after rustc has processed various things, including the use statements that bring dependencies' information into the current crate's compile.\n\n \n\n        \n\"The dance\" is how rustc's monomorphizer and valenc's monomorphizer **need to work together** to fully discover all of the functions that they are calling in each other.\n\nA \"monomorphizer\" is what turns a generic function foo<T> into its substituted functions foo<i32>, foo<bool>, foo<String> etc. depending on what types one calls foo<T> with. [22](#note22)\n\nTo illustrate, here's an example program showing **Valen calling Rust calling Valen:**\n\n```\nexported func main() {\n  vs = MyStruct();\n  rust_func<MyStruct>(&vs);\n}\nstruct MyStruct { }\nimpl RustTrait for MyStruct {\n  func method<N int>(self: &MyStruct) {\n    print(\"hello from valen! \" + N);\n  }\n}\n```\n\n```\ntrait RustTrait {\n  fn method<const N: i32>(&self);\n}\nfn rust_func<T: RustTrait>(x: &T) {\n  x.method::<4>();\n  x.method::<6>();\n}\n```\n\nFor a second, **let's pretend that** main, rust_func, and method were **all Rust functions.**\n\nIf that were the case, rustc would do this:\n\n(For readability, I'll shorten \"monomorphizer\" and \"monomorphize\" to \"mono\")\n\n\n- rustc starts mono'ing main.\n    \n  - rustc sees rust_func<MyStruct>, wants it to be mono'd.\n        \n    - rustc starts mono'ing rust_func<MyStruct>.\n            \n      - rustc sees x.method::<4>, wants it to be mono'd.\n                \n        - rustc monos MyStruct::method::<4>.\n      - rustc sees x.method::<6>, wants it to be mono'd.\n                \n        - rustc monos MyStruct::method::<6>.\n    - rustc sees x.method::<4>, wants it to be mono'd.\n                \n  - rustc starts mono'ing rust_func<MyStruct>.\n            \n- rustc sees rust_func<MyStruct>, wants it to be mono'd.\n        \n\nAnd that would have been easy; a simple task for rustc.\n\n**However,** main and method **are Valen functions.**\n\nSo it's more like this, where rustc and valenc need to **talk to each other:**\n\n(Only difference below: four \"rustc\"s become \"**valenc**\"s)\n\n\n- **valenc** starts mono'ing main.\n  - **valenc** sees rust_func<MyStruct>, wants it to be mono'd.\n    - rustc starts mono'ing rust_func<MyStruct>.\n            \n      - rustc sees x.method::<4>, wants it to be mono'd.\n                \n        - **valenc** monos MyStruct.method<4>.\n      - rustc sees x.method::<6>, wants it to be mono'd.\n                \n        - **valenc** monos MyStruct.method<6>.\n    - rustc sees x.method::<4>, wants it to be mono'd.\n                \n  - rustc starts mono'ing rust_func<MyStruct>.\n            \n\nIn other words, we need to make rustc's monomorphizer and valenc's monomorphizer able to call each other.\n\nSo our design needs to enable that. [23](#note23)\n\n22\nIt's sometimes also called \"instantiator\" (or very rarely, \"elaborator\").\n\n \n\n23\n \n\n        The current design works like this:\n\n- \n(Like before) rustc_args tells rustc **what Rust libraries we want to use** , so it loads and compiles them, so the Valen typing pass can ask questions about them.\n- callbacks specifies observers that tell us:\n- \nWhen rustc has loaded and compiled all of its dependencies, so the Valen typing pass can ask rustc questions about the Rust crates it depends on, and generate **empty** Rust functions corresponding to the Valen exported functions (such as main).\n- \nWhen rustc is monomorphizing one of those empty Rust MIR functions, we can intercept that call, make Valen monomorphize it instead, and also tell rustc what *other* Rust functions this Valen function calls (so rustc can monomorphize those too).\n- When rustc is about to ask the rustc LLVM backend to lower this (empty) function to LLVM, we intercept that, have Valen's LLVM backend lower it to LLVM instead.\n\nOf course, those last two capabilities definitely don't exist in rustc.\n\nSo, I did the nuclear option. I **patched the Rust compiler** to add those last two callbacks.\n\nHonestly, this was the riskiest part of the whole endeavor. The patches are small (~100 lines), but one of them is basically a hack that assumes rustc is using LLVM, which of course isn't always true. [24](#note24) It works, but it's definitely not upstreamable.\n\nLuckily, I already have a better approach in mind for the next iteration...\n\nOf course, that's just the rustc side of this. I then had to rearchitect the Valen compiler to actually use these capabilities. That took most of 2026, and was a massive endeavor that will definitely get its own post (stay tuned!).\n\nI have a little game engine I've been experimenting with, to try and figure out new ways to do [screen-space refraction](https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-refraction.html), like this: [25](#note25)\n\n\nI thought, this would be a perfect goal to set. This would be Valen's first contact with Rust, like the golden spike that completed the first transcontinental railroad across the US.\n\nIf I could get it working, then I could finally start developing the game that I've been [trying to start on since the dawn of time](https://verdagon.dev/blog/yak-shave-language-engine-game).\n\nMy first goal was actually something like this, where main owns the while loop:\n\n```\nimport rust.nobiliav.NobiliaWindow;\nimport rust.nobiliav.FrameInput;\nimport rust.nobiliav.MainLoopCallback;\n...\nexported func main() int {\n  w = NobiliaWindow.new(1200, 900);\n  ...\n  while w.running() {\n    input = w.tick();\n    key = input.key();\n    if (key == key_arrow_left()) {\n      w.rotate_camera(-4, 0);\n    } else if (key == key_arrow_right()) {\n      w.rotate_camera(4, 0);\n    } else if (key == key_arrow_up()) {\n      w.rotate_camera(0, 4);\n    } else if (key == key_arrow_down()) {\n      w.rotate_camera(0, -4);\n    }\n  }\n  return 0;\n}\n```\nbut *apparently* wgpu (and apps in general nowadays?!) don't let us own our own event loop. I remember the good ol' days when you could just GetMessage(&msg, ...) or EvtGetEvent(&event, ...) in a while(true) and everyone was happy.\n\nI was faced with a choice: do something less awesome, or expand the scope of my golden spike to include Rust calling *back into Valen.*\n\nYou all know me. You know what I chose!\n\nI decided to implement something like a closure:\n\n```\nimport rust.nobiliav.NobiliaWindow;\nimport rust.nobiliav.FrameInput;\nimport rust.nobiliav.MainLoopCallback;\n...\nexported func main() int {\n  w = NobiliaWindow.new(1200, 900);\n  ...\n  w.main_loop(&MainLoopCallback((win, input) => {\n    key = input.key();\n    if (key == key_arrow_left()) {\n      win.rotate_camera(-4, 0);\n    } else if (key == key_arrow_right()) {\n      win.rotate_camera(4, 0);\n    } else if (key == key_arrow_up()) {\n      win.rotate_camera(0, 4);\n    } else if (key == key_arrow_down()) {\n      win.rotate_camera(0, -4);\n    }\n  }));\n  return 0;\n}\n```\nAfter a *lot* of work (that led to discovering *the dance* and the current design), it finally all connected!\n\nAt last, I got my first render: [26](#note26)\n\n\nAnd with that first render, **the golden spike was hammered into place, and the transcontinental compiler was born.**\n\nOver *half a year* of work, theorizing, planning, hacking, refactoring, and rearchitecting had **finally come to fruition.**\n\nOf course, we aren't done yet!\n\nWe don't just want Rust interop, we want *memory-safe* Rust interop!\n\n24\n \n\nrustc also has GCC and Cranelift backends.\n\n25\nRendered by a working Valen program calling into a Rust graphics library!\n\n \n\n26\nDon't look too closely at it. You'll start noticing oddities (like semitransparent refractive grass!)\n\n \n\n        \nLike I said above, I'm designing a memory safety approach that builds on [Group Borrowing](https://verdagon.dev/blog/group-borrowing), which is a more flexible form of borrow checking that allows for shared mutable references.\n\nIf my guess is right, a well-designed blend could have even more benefits than we talked about in that article:\n\n- We could have a mutable reference into an otherwise-immutable object\n- Rc could hold mutable objects without RefCell or Cell (something I call \"the holy grail\", long story!)\n- \nIn some cases, it could even be faster at run-time [27](#note27)\n\nThese three points are theoretical until I can prove them, so take them with a grain of salt! Stay tuned for more posts on them.\n\nWith careful enough language design, group borrowing can actually be a superset of Rust's borrow checking, making it so we can borrow-check over the boundary.\n\nThis post is long so I'll save the details for the next one, but TL;DR: it's not complete yet, but this prototype is doing some borrow checking over the boundary!\n\n27\nDisclaimer: this is unproven still, since I haven't yet implemented and benchmarked it, so take it with a grain of salt.\n\n \n\n        Vale is my greatest achievement, my own personal crown jewel of memory safety design. It was a blend of generational references and region borrowing, both of which had never been seen before. It directly inspired Mojo to add linear types, even before I worked for them.\n\nVale was also pretty unique in that it was a \"high-level high-performance\" language (as opposed to a lower-level \"systems programming\" language). This let it be much more strict about memory safety, which allowed for a lot of interesting features like [Perfect Replayability](https://verdagon.dev/blog/perfect-replayability-prototyped).\n\nThis new language is a different beast altogether.\n\n- It uses group borrowing (purely compile-time memory safety) instead of generational references + region borrowing.\n- It's a systems programming language, which means even more freedom and speed (via group borrowing), though it wouldn't be as safe (because it'll have unsafe like Rust).\n\nIt's so different, that it truly deserves its own name. [28](#note28)\n\nAnd thus, **Valen** is born!\n\n28\n \n\n        \nThese are ideas I've been itching to try for *years*, and they're finally all coming together into something beautiful. [29](#note29)\n\nThis post represents my work for most of a year, and I had to keep it from exploding into a 40-page tome like some of my other posts, so I'll wrap things up here.\n\nThis is just the tip of the iceberg, so stay tuned by subscribing to my [RSS feed](https://verdagon.dev/rss.xml), [r/valen](https://www.reddit.com/r/Valen/), or joining the [Valen discord](https://discord.gg/SNB8yGH).\n\nCheers!\n\n- Evan Ovadia\n\n\nPS. If anyone has a Fosstodon account, please [send me an invite](https://fosstodon.org/invites) (my email is revval át verdagon dot dev), thank you!\n\n29","body_html":"<p>There was an incredible moment on May 10th, 1869, when railroad builders finally reached their goal of <strong>joining the east coast rail network with the west coast rail network.</strong></p>\n<p>In that moment, the first United States transcontinental railroad was born. <a href=\"#note0\">0</a></p>\n<p>After six years of work, <a href=\"#note1\">1</a> the two rail networks finally joined up in Promontory Summit, Utah.</p>\n<p>To commemmorate the moment, they drove a 17.6-karat <strong>golden spike</strong> into the final tie of the railroad.</p>\n<p>To me, the phrase &quot;<a href=\"https://en.wikipedia.org/wiki/Golden_spike\" rel=\"nofollow ugc noopener\">golden spike</a>&quot; means an incredibly difficult task joining two separate, distant systems. <a href=\"#note2\">2</a></p>\n<p>Here in the compiler world, it often feels like every compiler is <em>worlds</em> apart from every other compiler.</p>\n<p>When a language wants to call into another language, one usually has to do acrobatic rituals involving the C ABI, writing &quot;C bindings&quot; (wrapper functions), and sometimes making deals with various deities.</p>\n<p>And even with all that, cross-language generics <a href=\"#note3\">3</a> don&#39;t work (C doesn&#39;t have generics), and things definitely won&#39;t be memory-safe across the boundary (because C!).</p>\n<p><strong>This is why it&#39;s so tricky to build a language on top of Rust.</strong> And then, having memory safety and generics across the C boundary is impossible. And even if it were possible, integrating two compilers is <em>very, very difficult.</em></p>\n<p>And so I thought to myself, that <em>this sounds like a worthy goal for 2026!</em></p>\n<p>So here we are!</p>\n<p>This post is going to be about the start of my <em>ridiculously over-ambitious</em> endeavor to create a language with <strong>true Rust interop,</strong> with a compiler that talks to rustc seamlessly enough that we can use my Rust graphics library <a href=\"#note4\">4</a> with cross-language generics, memory safety, linear types, Nick Smith&#39;s <a href=\"https://verdagon.dev/blog/group-borrowing\" rel=\"nofollow ugc noopener\">group borrow checking</a>, and a bunch of other juicy, juicy features.</p>\n<p>Tentatively, I&#39;m calling this new language &quot;Valen&quot; <a href=\"#note5\">5</a>  <a href=\"#note6\">6</a> since it&#39;s similar (but different enough) to my existing language <a href=\"https://vale.dev/\" rel=\"nofollow ugc noopener\">Vale</a>.</p>\n<p>So read on, and this post will explain the journey so far!</p>\n<p>This entire endeavor is <em>extremely experimental</em> and many things have holes and sharp edges (see side-note <a href=\"#note7\">7</a>). It&#39;s going to be a glorious few months of cleaning, rewriting, and solidifying this horror before I unleash it on the world. Feel free to check out the <a href=\"https://github.com/valen-lang/valen\" rel=\"nofollow ugc noopener\">source code</a>, and beware, here be dragons! <a href=\"#note8\">8</a></p>\n<p>(interesting tangential thoughts)</p>\n<p>0\nMy stance: if you want someone to take the time to read something, take the time to write it by hand.</p>\n<p>Thanks for reading =)</p>\n<p>1\n...2 days before this date new troubles arose for the Union Pacific at Piedmont where the car in which Dr. T. C. Durant, the vice-president, was riding was disconnected from the train and shunted onto a side line by some 400 workers (one reporter says 500) who demanded their pay, unpaid since January 1.</p>\n<p>Absolute madlads!</p>\n<p>2\nOn Google Earth, I joined the local-editing app to cloud storage, finally enabling online editing. We called that project &quot;golden spike&quot; too. This whole rust interop endeavor brings me back to that moment!</p>\n<p>3\nExplained more below, but basically, being able to use SomeRustStruct&lt;OtherLangStruct&gt;.</p>\n<p>4</p>\n<p>5\nAnd since its compiler is valenc, we can pronounce it like &quot;Valence&quot;, which sounds nice!</p>\n<p>6\nAlso, it&#39;s pretty funny to me that now V, Val, Vale, Vala, and Valen are all languages that have existed. I&#39;m tempted to release a tiny Rust-interop language for others to use, and call it Va.</p>\n<p>7</p>\n<p>To be clear about what works today:</p>\n<ul><li>Valen has linear types, but we can&#39;t yet declare that an existing Rust type is linear.</li><li>Valen has group borrowing (except for closures), and it borrow checks across the boundary.</li><li>Structs work across the boundary, even Valen structs that implement Rust traits. But they must be zero-sized (filled structs work in my separate prototype, not yet in Valen).</li><li>Generational references are temporarily disabled, hopefully coming back soon.</li></ul>\n<p>8</p>\n<pre><code>    Green dragons, specifically.</code></pre>\n<p>Rust is one of my favorite languages <a href=\"#note9\">9</a> because of its speed, safety, and ecosystem... but there are definitely some things that would make it <strong>simpler and overall nicer</strong> for my use cases.</p>\n<p>My wish list:</p>\n<ul><li></li></ul>\n<p>A <a href=\"https://verdagon.dev/blog/group-borrowing\" rel=\"nofollow ugc noopener\">borrow checker without shared-xor-mutable</a></p>\n<ul><li></li></ul>\n<p>Faster run-time performance <a href=\"#note10\">10</a></p>\n<ul><li></li></ul>\n<p>Resource safety via <a href=\"https://www.youtube.com/watch?v=IpuvQUVB8Cg&amp;t=2s\" rel=\"nofollow ugc noopener\">linear types</a></p>\n<ul><li></li></ul>\n<p><a href=\"https://verdagon.dev/blog/impossible-optimization\" rel=\"nofollow ugc noopener\">Zig-style comptime</a><a href=\"#note11\">11</a></p>\n<ul><li></li></ul>\n<p><a href=\"https://verdagon.dev/blog/generational-references\" rel=\"nofollow ugc noopener\">Generational references</a></p>\n<ul><li>An Rc that can hold mutable data without RefCell or Cell</li><li></li></ul>\n<p>...and a lot of other features <a href=\"#note12\">12</a></p>\n<p>But I don&#39;t just want a new language, because I wouldn&#39;t have access to Rust&#39;s ecosystem of libraries.</p>\n<p>So how do we do all that, while being able to call into Rust code?</p>\n<p>9\nYou guessed it, it&#39;s a three-way tie between C++, Scala, and Rust!</p>\n<p>10</p>\n<p>11</p>\n<p>Zero-cost compiler-optimized DSLs, anyone?</p>\n<p>12</p>\n<p>This seemed impossible for a <em>lot</em> of reasons, explained in <a href=\"/blog/exploring-seamless-rust-interop-part-2\">Crossing the Impossible FFI Boundary, and My Gradual Descent Into Madness</a>.</p>\n<p>I had forgotten that the post included this image:</p>\n<p>Hopefully we don&#39;t have to do that! (<em>...foreshadowing intensifies...</em> <a href=\"#note13\">13</a>)</p>\n<p>Anyway, the <strong>more concrete, specific goal</strong> was for this program to work: <a href=\"#note14\">14</a></p>\n<p>valen</p>\n<pre><code>  ```</code></pre>\n<p>import rust.nobiliav.NobiliaWindow;\nimport rust.nobiliav.FrameInput;\nimport rust.nobiliav.MainLoopCallback;\n... // Import constants\nexported func main() int {\n  w = NobiliaWindow.new(1200, 900);\n  ... // set up the terrain and entities\n  w.main_loop(\n    // Make a Valen closure that implements the Rust <code>trait MainLoopCallback</code>\n    &amp;MainLoopCallback((win, input) =&gt; {\n      key = input.key();\n      if (key == key_arrow_left()) {\n        win.rotate_camera(-4, 0);\n      } else if (key == key_arrow_right()) {\n        win.rotate_camera(4, 0);\n      } else if (key == key_arrow_up()) {\n        win.rotate_camera(0, 4);\n      } else if (key == key_arrow_down()) {\n        win.rotate_camera(0, -4);\n      }\n    }));</p>\n<p>  return 0;\n}</p>\n<pre><code>Of course, this required answering a *lot* of very hard questions.\n\nI&#39;ll ask them in the code:\n</code></pre>\n<p>// How do we know what things are importable from Rust?\nimport rust.nobiliav.NobiliaWindow;\nimport rust.nobiliav.FrameInput;\nimport rust.nobiliav.MainLoopCallback;\n...\nexported func main() int {\n  // How do we know what static methods exist in a Rust type?\n  // How does Valen know what parameters rustc expects here?\n  w = NobiliaWindow.new(1200, 900);\n  ...\n  w.main_loop(\n    // How do we make a Valen closure implement a Rust trait?\n    // How do we know the methods on a Rust trait?\n    &amp;MainLoopCallback(\n      // How will Rust call BACK into Valen code? Monomorphizer integration?\n      // Can the optimizer inline a Valen function into a Rust function and vice versa?\n      (win, input) =&gt; {\n        key = input.key();\n        if (key == key_arrow_left()) {\n          win.rotate_camera(-4, 0);\n        } else if (key == key_arrow_right()) {\n          win.rotate_camera(4, 0);\n        } else if (key == key_arrow_up()) {\n          win.rotate_camera(0, 4);\n        } else if (key == key_arrow_down()) {\n          win.rotate_camera(0, -4);\n        }\n      }\n    )\n  );\n  return 0;\n}</p>\n<pre><code>However, these questions hide the real, central question underneath it all.\n\n13\nBack then, I thought I would need to reimplement Rust&#39;s generics and traits systems.\n\n \n\n14\n \n\n        As many of you know, the most common way for other languages to call into Rust is if the Rust library exposes its functions as extern &quot;C&quot;, and exposes its types as repr(C).\n\nThis is because C is the de-facto universal translator between low-level languages.\n\nIt&#39;s also because [Rust doesn&#39;t have a stable ABI yet.](https://www.reddit.com/r/rust/comments/ss2p6c/what_does_it_mean_when_people_say_that_rust_does/) [15](#note15)\n\n&quot;What&#39;s an ABI?&quot; you might ask.\n\nTo simplify a bit, an &quot;ABI&quot; is basically how Rust answers these questions:\n\n- &quot;If the user calls a function, passing a struct by value, do we compile it to pass-by-reference, or do we pass it in a register?&quot;\n- \n&quot;If the user specifies a bool, then a u64 integer, then a bool, do we put those two bools next to each other to save space?&quot; [16](#note16)\n\nAlas, Rust hasn&#39;t yet committed to an ABI.\n\nSo, using the C ABI (with extern &quot;C&quot; and repr(C)) is the only option for other languages to call into Rust.\n\n**But C doesn&#39;t have generics.** There&#39;s no such thing as void do_something&lt;T&gt;(T* thing) in C.\n\nThis means that other languages can&#39;t call into generic Rust functions.\n\n**This is a problem for us,** because... well, recall this main_loop call from above:\n</code></pre>\n<p>exported func main() int {\n  ...\n  w.main_loop(&amp;MainLoopCallback((win, input) =&gt; { ... }));\n  ...\n}</p>\n<pre><code>Here&#39;s what Rust&#39;s main_loop actually is:\n\nrs\n\n      ```\nimpl NobiliaWindow {\n  pub fn main_loop&lt;C: MainLoopCallback&gt;(&amp;mut self, cb: &amp;mut C) {\n    ...\n  }\n  ...\n}</code></pre>\n<p>That&#39;s right, that parameter right there is <em>generic</em>, taking anything that implements trait MainLoopCallback.</p>\n<p>But the C ABI has no generics! But we need generics. Blast! We&#39;re stuck.</p>\n<p>So <strong>the central question,</strong> the central mystery to solve, is <em>how do we do cross-language generics?</em></p>\n<p>15</p>\n<p>&quot;ABI&quot; stands for &quot;Application Binary Interface&quot;.</p>\n<p>16</p>\n<pre><code>    There are actually two levels to this question:</code></pre>\n<ol><li>How do we call into a Rust generic function?</li><li></li></ol>\n<p>How do we call into a Rust generic function <em>that calls back into Valen?</em><a href=\"#note17\">17</a></p>\n<p>Here&#39;s a simpler example to illustrate the first level:</p>\n<pre><code>import rust.std.vec.Vec;\nexported func main() int {\n  my_vec = Vec&lt;int&gt;();\n  my_vec.push(21);\n  my_vec.push(42);\n  // Returns 42\n  return my_vec.pop().unwrap();\n}</code></pre>\n<p>When we say my_vec.push(21), we&#39;re calling the generic function Vec&lt;T&gt;::push.</p>\n<p>Luckily, in the <a href=\"/blog/exploring-seamless-rust-interop-part-2\">Madness</a> post, I managed to get it working for C:</p>\n<p>c</p>\n<pre><code>  ```</code></pre>\n<p>// Import a rust type directly (no bindings!)\n#pragma rsuse VecInt = std::vec::Vec&lt;u64&gt;\n// Must specify each method you want to use\n#pragma rsfn VecInt_with_capacity = VecInt::with_capacity\n#pragma rsfn VecInt_capacity = VecInt::capacity\n#pragma rsfn VecInt_drop = VecInt::drop\n// Plus the magic incantation, and...\n#include &quot;rust_deps/rust_deps.h&quot;\n#include &lt;stdio.h&gt;\nint main() {\n  // ...presto, we can use rust libraries!\n  VecInt argv = VecInt_with_capacity(42);\n  printf(&quot;Capacity: %lu\\n&quot;, VecInt_capacity(&amp;argv));\n  VecInt_drop(argv);\n  return 0;\n}</p>\n<pre><code>stdout\n\n      `Capacity: 42`\nI called this my &quot;most cursed exploration&quot; because of the acrobatics it had to do:\n\n- It ran rustdoc (yes, the documentation generator!) and parsed its json output with the rustdoc_types library, to figure out what types were usable, and what impls had what methods.\n- It ran rustc with a &quot;scouting program&quot; that literally just prints sizes; println!(&quot;{}&quot;, size_of::&lt;Vec::&lt;u64&gt;&gt;()) prints 24 bytes. (Thanks to matklad and literallyvoid for helping me improve this part!)\n- It then ran rustc again with a &quot;instantiation program&quot; which generated a &quot;wrapper C library&quot; that the C program could statically link to.\n- Vale&#39;s memory safety approach didn&#39;t really line up with Rust&#39;s, so a user had to stick to certain patterns.\n\nAnd it had some limitations:\n\n- We need to fully spell out the generic args, like VecInt = std::vec::Vec&lt;u64&gt;.\n- \nWe need to import *every* method we use, in a #pragma rsfn.\n\nBut the hardest limitation is that we can&#39;t make a C type implement a Rust trait.\n\nThat means you can&#39;t use HashMap::get, because its k key must implement the Hash and Eq traits.\n\nStill, as cursed as it was, the 2024 solution was actually a pretty good start.\n\nAbove, I said that there are two levels to the cross-language generics question:\n\n1. How do we call into a Rust generic function?\n2. How do we call into a Rust generic function that calls back into Valen?\n\nThe 2024 solution solved most of #1 in spirit, even though it got information from Rust in an odd way.\n\nAnd it hinted that there might be an answer to #2, if a language was designed with it in mind and Did Things Properly™.\n\n17\n \n\n        \nOf course, there&#39;s no such thing as &quot;doing things properly&quot;, because **everything I&#39;m about to say is *very* unsupported by the Rust compiler.**\n\nBut I felt like the next step in the endeavor would be to talk to rustc directly, [18](#note18) instead of invoking it (twice!) from the outside. [19](#note19)\n\nAnd it turns out, one can actually **run the rust compiler as a library,** using [rustc_driver](https://rustc-dev-guide.rust-lang.org/rustc-driver/intro.html)&#39;s run_compiler function!\n</code></pre>\n<p>use rustc_driver::{Callbacks, Compilation};\n...\nfn main() {\n  ...\n  let callbacks = ValenRustInteropCallbacks { ... };\n  ...\n  rustc_driver::run_compiler(&amp;rustc_args, &amp;mut callbacks);</p>\n<pre><code>The two arguments to run_compiler influence what rustc does.\n\n- \nrustc_args tells rustc **what Rust libraries we want to use** , so it loads and compiles them, so the Valen typing pass can ask questions about them.[20](#note20)\n- \ncallbacks specifies observers that tell us when rustc has loaded and compiled all of its dependencies. [21](#note21) Then, the Valen typing pass can ask rustc questions about the Rust crates it depends on, and generate Rust MIR functions from our Valen code.\n\nHowever, there was a problem with that: Valen couldn&#39;t lower to Rust&#39;s MIR, because it didnt&#39;t have the capabilities Valen needed:\n\n- \nMIR&#39;s mutable references are unique, which means it can&#39;t do our [Group Borrowing](https://verdagon.dev/blog/group-borrowing) memory safety approach, which allows shared mutable references.\n- MIR doesn&#39;t let us specify LLVM&#39;s alias groups / !alias.scope on load/store instructions, which is something that makes group borrowing faster.\n- MIR can&#39;t express comptime metaprogramming, which is on my dream language wish list.\n\nRust&#39;s MIR was designed for Rust. So it&#39;s a great target for Rust code, not Valen code... alas.\n\nIf anyone wants to know how to do this the MIR way, let me know! Happy to point you in the right direction.\n\nOf course, if Valen used its own IR and backend instead of Rust&#39;s, that would mean that the compilers would need to **work with each other** in a very interesting dance.\n\n18\nOf course, doing this requires using the private, unstable APIs. Yikes!\n\n \n\n19\n \n\n20\n \n\nTo do this, we actually:\n\n- Parse the Valen source files, looking for any imports (like import rust.glass_domino.Window).\n- Generate a Rust lib.rs file containing equivalents (like use glass_domino::Window;).\n- Add that &quot;lib.rs&quot; path into rustc_args.\n- Add dependency libraries&#39; paths to rustc_args (like --extern glass_domino=target/.../libglass_domino.rlib) so rustc knows where to find it (well, cargo does this).\n\n(This is how it still works today)\n\n21\nThis is rustc&#39;s after_expansion callback, run after rustc has processed various things, including the use statements that bring dependencies&#39; information into the current crate&#39;s compile.\n\n \n\n        \n&quot;The dance&quot; is how rustc&#39;s monomorphizer and valenc&#39;s monomorphizer **need to work together** to fully discover all of the functions that they are calling in each other.\n\nA &quot;monomorphizer&quot; is what turns a generic function foo&lt;T&gt; into its substituted functions foo&lt;i32&gt;, foo&lt;bool&gt;, foo&lt;String&gt; etc. depending on what types one calls foo&lt;T&gt; with. [22](#note22)\n\nTo illustrate, here&#39;s an example program showing **Valen calling Rust calling Valen:**\n</code></pre>\n<p>exported func main() {\n  vs = MyStruct();\n  rust_func&lt;MyStruct&gt;(&amp;vs);\n}\nstruct MyStruct { }\nimpl RustTrait for MyStruct {\n  func method&lt;N int&gt;(self: &amp;MyStruct) {\n    print(&quot;hello from valen! &quot; + N);\n  }\n}</p>\n<pre><code></code></pre>\n<p>trait RustTrait {\n  fn method&lt;const N: i32&gt;(&amp;self);\n}\nfn rust_func&lt;T: RustTrait&gt;(x: &amp;T) {\n  x.method::&lt;4&gt;();\n  x.method::&lt;6&gt;();\n}</p>\n<pre><code>\nFor a second, **let&#39;s pretend that** main, rust_func, and method were **all Rust functions.**\n\nIf that were the case, rustc would do this:\n\n(For readability, I&#39;ll shorten &quot;monomorphizer&quot; and &quot;monomorphize&quot; to &quot;mono&quot;)\n\n\n- rustc starts mono&#39;ing main.\n    \n  - rustc sees rust_func&lt;MyStruct&gt;, wants it to be mono&#39;d.\n        \n    - rustc starts mono&#39;ing rust_func&lt;MyStruct&gt;.\n            \n      - rustc sees x.method::&lt;4&gt;, wants it to be mono&#39;d.\n                \n        - rustc monos MyStruct::method::&lt;4&gt;.\n      - rustc sees x.method::&lt;6&gt;, wants it to be mono&#39;d.\n                \n        - rustc monos MyStruct::method::&lt;6&gt;.\n    - rustc sees x.method::&lt;4&gt;, wants it to be mono&#39;d.\n                \n  - rustc starts mono&#39;ing rust_func&lt;MyStruct&gt;.\n            \n- rustc sees rust_func&lt;MyStruct&gt;, wants it to be mono&#39;d.\n        \n\nAnd that would have been easy; a simple task for rustc.\n\n**However,** main and method **are Valen functions.**\n\nSo it&#39;s more like this, where rustc and valenc need to **talk to each other:**\n\n(Only difference below: four &quot;rustc&quot;s become &quot;**valenc**&quot;s)\n\n\n- **valenc** starts mono&#39;ing main.\n  - **valenc** sees rust_func&lt;MyStruct&gt;, wants it to be mono&#39;d.\n    - rustc starts mono&#39;ing rust_func&lt;MyStruct&gt;.\n            \n      - rustc sees x.method::&lt;4&gt;, wants it to be mono&#39;d.\n                \n        - **valenc** monos MyStruct.method&lt;4&gt;.\n      - rustc sees x.method::&lt;6&gt;, wants it to be mono&#39;d.\n                \n        - **valenc** monos MyStruct.method&lt;6&gt;.\n    - rustc sees x.method::&lt;4&gt;, wants it to be mono&#39;d.\n                \n  - rustc starts mono&#39;ing rust_func&lt;MyStruct&gt;.\n            \n\nIn other words, we need to make rustc&#39;s monomorphizer and valenc&#39;s monomorphizer able to call each other.\n\nSo our design needs to enable that. [23](#note23)\n\n22\nIt&#39;s sometimes also called &quot;instantiator&quot; (or very rarely, &quot;elaborator&quot;).\n\n \n\n23\n \n\n        The current design works like this:\n\n- \n(Like before) rustc_args tells rustc **what Rust libraries we want to use** , so it loads and compiles them, so the Valen typing pass can ask questions about them.\n- callbacks specifies observers that tell us:\n- \nWhen rustc has loaded and compiled all of its dependencies, so the Valen typing pass can ask rustc questions about the Rust crates it depends on, and generate **empty** Rust functions corresponding to the Valen exported functions (such as main).\n- \nWhen rustc is monomorphizing one of those empty Rust MIR functions, we can intercept that call, make Valen monomorphize it instead, and also tell rustc what *other* Rust functions this Valen function calls (so rustc can monomorphize those too).\n- When rustc is about to ask the rustc LLVM backend to lower this (empty) function to LLVM, we intercept that, have Valen&#39;s LLVM backend lower it to LLVM instead.\n\nOf course, those last two capabilities definitely don&#39;t exist in rustc.\n\nSo, I did the nuclear option. I **patched the Rust compiler** to add those last two callbacks.\n\nHonestly, this was the riskiest part of the whole endeavor. The patches are small (~100 lines), but one of them is basically a hack that assumes rustc is using LLVM, which of course isn&#39;t always true. [24](#note24) It works, but it&#39;s definitely not upstreamable.\n\nLuckily, I already have a better approach in mind for the next iteration...\n\nOf course, that&#39;s just the rustc side of this. I then had to rearchitect the Valen compiler to actually use these capabilities. That took most of 2026, and was a massive endeavor that will definitely get its own post (stay tuned!).\n\nI have a little game engine I&#39;ve been experimenting with, to try and figure out new ways to do [screen-space refraction](https://lettier.github.io/3d-game-shaders-for-beginners/screen-space-refraction.html), like this: [25](#note25)\n\n\nI thought, this would be a perfect goal to set. This would be Valen&#39;s first contact with Rust, like the golden spike that completed the first transcontinental railroad across the US.\n\nIf I could get it working, then I could finally start developing the game that I&#39;ve been [trying to start on since the dawn of time](https://verdagon.dev/blog/yak-shave-language-engine-game).\n\nMy first goal was actually something like this, where main owns the while loop:\n</code></pre>\n<p>import rust.nobiliav.NobiliaWindow;\nimport rust.nobiliav.FrameInput;\nimport rust.nobiliav.MainLoopCallback;\n...\nexported func main() int {\n  w = NobiliaWindow.new(1200, 900);\n  ...\n  while w.running() {\n    input = w.tick();\n    key = input.key();\n    if (key == key_arrow_left()) {\n      w.rotate_camera(-4, 0);\n    } else if (key == key_arrow_right()) {\n      w.rotate_camera(4, 0);\n    } else if (key == key_arrow_up()) {\n      w.rotate_camera(0, 4);\n    } else if (key == key_arrow_down()) {\n      w.rotate_camera(0, -4);\n    }\n  }\n  return 0;\n}</p>\n<pre><code>but *apparently* wgpu (and apps in general nowadays?!) don&#39;t let us own our own event loop. I remember the good ol&#39; days when you could just GetMessage(&amp;msg, ...) or EvtGetEvent(&amp;event, ...) in a while(true) and everyone was happy.\n\nI was faced with a choice: do something less awesome, or expand the scope of my golden spike to include Rust calling *back into Valen.*\n\nYou all know me. You know what I chose!\n\nI decided to implement something like a closure:\n</code></pre>\n<p>import rust.nobiliav.NobiliaWindow;\nimport rust.nobiliav.FrameInput;\nimport rust.nobiliav.MainLoopCallback;\n...\nexported func main() int {\n  w = NobiliaWindow.new(1200, 900);\n  ...\n  w.main_loop(&amp;MainLoopCallback((win, input) =&gt; {\n    key = input.key();\n    if (key == key_arrow_left()) {\n      win.rotate_camera(-4, 0);\n    } else if (key == key_arrow_right()) {\n      win.rotate_camera(4, 0);\n    } else if (key == key_arrow_up()) {\n      win.rotate_camera(0, 4);\n    } else if (key == key_arrow_down()) {\n      win.rotate_camera(0, -4);\n    }\n  }));\n  return 0;\n}</p>\n<pre><code>After a *lot* of work (that led to discovering *the dance* and the current design), it finally all connected!\n\nAt last, I got my first render: [26](#note26)\n\n\nAnd with that first render, **the golden spike was hammered into place, and the transcontinental compiler was born.**\n\nOver *half a year* of work, theorizing, planning, hacking, refactoring, and rearchitecting had **finally come to fruition.**\n\nOf course, we aren&#39;t done yet!\n\nWe don&#39;t just want Rust interop, we want *memory-safe* Rust interop!\n\n24\n \n\nrustc also has GCC and Cranelift backends.\n\n25\nRendered by a working Valen program calling into a Rust graphics library!\n\n \n\n26\nDon&#39;t look too closely at it. You&#39;ll start noticing oddities (like semitransparent refractive grass!)\n\n \n\n        \nLike I said above, I&#39;m designing a memory safety approach that builds on [Group Borrowing](https://verdagon.dev/blog/group-borrowing), which is a more flexible form of borrow checking that allows for shared mutable references.\n\nIf my guess is right, a well-designed blend could have even more benefits than we talked about in that article:\n\n- We could have a mutable reference into an otherwise-immutable object\n- Rc could hold mutable objects without RefCell or Cell (something I call &quot;the holy grail&quot;, long story!)\n- \nIn some cases, it could even be faster at run-time [27](#note27)\n\nThese three points are theoretical until I can prove them, so take them with a grain of salt! Stay tuned for more posts on them.\n\nWith careful enough language design, group borrowing can actually be a superset of Rust&#39;s borrow checking, making it so we can borrow-check over the boundary.\n\nThis post is long so I&#39;ll save the details for the next one, but TL;DR: it&#39;s not complete yet, but this prototype is doing some borrow checking over the boundary!\n\n27\nDisclaimer: this is unproven still, since I haven&#39;t yet implemented and benchmarked it, so take it with a grain of salt.\n\n \n\n        Vale is my greatest achievement, my own personal crown jewel of memory safety design. It was a blend of generational references and region borrowing, both of which had never been seen before. It directly inspired Mojo to add linear types, even before I worked for them.\n\nVale was also pretty unique in that it was a &quot;high-level high-performance&quot; language (as opposed to a lower-level &quot;systems programming&quot; language). This let it be much more strict about memory safety, which allowed for a lot of interesting features like [Perfect Replayability](https://verdagon.dev/blog/perfect-replayability-prototyped).\n\nThis new language is a different beast altogether.\n\n- It uses group borrowing (purely compile-time memory safety) instead of generational references + region borrowing.\n- It&#39;s a systems programming language, which means even more freedom and speed (via group borrowing), though it wouldn&#39;t be as safe (because it&#39;ll have unsafe like Rust).\n\nIt&#39;s so different, that it truly deserves its own name. [28](#note28)\n\nAnd thus, **Valen** is born!\n\n28\n \n\n        \nThese are ideas I&#39;ve been itching to try for *years*, and they&#39;re finally all coming together into something beautiful. [29](#note29)\n\nThis post represents my work for most of a year, and I had to keep it from exploding into a 40-page tome like some of my other posts, so I&#39;ll wrap things up here.\n\nThis is just the tip of the iceberg, so stay tuned by subscribing to my [RSS feed](https://verdagon.dev/rss.xml), [r/valen](https://www.reddit.com/r/Valen/), or joining the [Valen discord](https://discord.gg/SNB8yGH).\n\nCheers!\n\n- Evan Ovadia\n\n\nPS. If anyone has a Fosstodon account, please [send me an invite](https://fosstodon.org/invites) (my email is revval át verdagon dot dev), thank you!\n\n29</code></pre>","headings":[]}}