What agents mean for Rust (and vice versa)
smallcultfollowing.com
smallcultfollowing.com
I have found that agents are good at writing Verus proofs in a Rust code base, and that these proofs have only a minimal negative effect on the normal compilation path. I have a skill for using Verus: https://github.com/gregwebs/skills-sdlc/blob/main/skills/rus...
I’ve switched one of my projects to Go and it took a day for Opus to do the port and another couple of days to finish the features I wanted. I’ve never liked the language and still use Rust in plenty of places, but I can’t argue with how much faster iteration is.
Ask your agent to build a simple bash/zsh/whatever cargo wrapper that maintains a machine build lock.
It should exclude cargo check, tree etc. ofc.
CPU contention from parallel cargo runs absolutely kills (build) performance.
Also my setup has instructions that agents keep working if they have open items while the lock is taken; i.e. launch a subagent or a shell with a watcher to run the build and don't block on it.
This makes all the difference when you have multiple agents on multiple workstreams on the same machine and they target Rust.
One of my spare time projects is a "prompted" 3D modeling app that is now (incl sub-crates I maintain) about 500k lines of Rust.
The link stage is the longest. An incremental build (w. sccache+mold) where I changed a few source files is done and runs after maybe 20s max on my 2022 Rhyzen 6800H-powered laptop.
I think this is acceptable when working on that kind of project.
For games where this matters I usually prototype in some other language first, TS, Python, Lua, whatever then translate to Rust when game mechanics and magic numbers are settled.
Or you simply put those into a config file that gets watched by the game.
At work we have an image manipulation crate that takes like 30mins to 'dev' and about an hour to 'release' build.
The WASM version takes even longer, about 2h, and needs like 55GB RAM during build.
But that crate has only to be built once a month.
And if it mattered we could split it because it's a metacrate made of ~20 sub-crates.
Yeah, it would be nice if Rust were even faster (I remember compile times almost a decade ago, when I started using it)!
But I think for the typical use cases where you would (should!) reach for it, it's quite ok already.
And if not you can work around it quite painlessly.
Isn't that the point of agents?
The average feature I spec and have an agent implement takes an hour or two (Either Opus 5.5 or DeepSeek 4.1 Flash, both at high and using subagents).
In-between the agents do not build that often because that is instructed in my setup.
They build maybe every 20mins when the target is Rust.
Ofc the models do not work like this by default. In fact they want to build all the time.
But as always, you need to tune the harness/setup for what you're using.
IMHO: if you use these models with Rust w/o those constraints/instructions "you're holding it wrong".
It gets it right after a few attempts.
My new favourite thing is to use records to type interfaces for more C style libraries with lots of IO. The trick is to use Generic and a type class to gather the interface into a list or similar and running that in IO using the library. Say, using a record to type audio and midi inputs and outputs in an audio plugin.
Opus can do this correctly first try, you just need to give it the idea!
Be careful what you wish for, etc
The hard reality is none of them.
We will have some kind of type system/profs to help drive LLMs output, and those that still will have a job as system architects or whatever, will generate applications directly.
And just it happens with optimising compilers, there will be a way to generate some kind of intermediate representation, like the -S switch, but that is it.
Generating source code for 3 GL languages is an intermediate step.
Who thinks otherwise should spend sometime looking into papers of AI role in compiler development.
For example,
"CGO 2022 Keynote: Compiler 2.0"
https://www.youtube.com/watch?v=w_sX9aZoZxg
"Machine-Generated, Machine-Checked Proofs for a Verified Compiler"
Yes, and there's a good chance that will be Rust, at least in the short term.
You can't realistically write a whole program in Lean. So you want a good type system that combines well with a prover. Rust has a good type system, and annotating unsafe sections with proofs is becoming common practice in Rust. Right now you have to choose the proof syntax among several alternatives, but there are efforts to unify.
That's the future of Rust in many companies, agents or no: unsafe code must be annotated with proofs to eliminate undefined behavior.
Now certainly a purpose built system may be better than adding annotations to an existing language, but it'll probably work better if that happens after people & agents get experience writing the awkward combination.
I think we are on the Rewrite in Rust hype cycle now, eventually the dust will settle, when folks realise agents are an evolution of garbage collected systems.
I also explicitly stated that this was not likely the best way to do this.
Many folks not into Rust land will favour other tooling approaches for their LLMs, who knows might even be something based in Markdown or YAML, as these kind of things usually turn out.
Also, this doesn't necessarily mean there won't be any compilers either. It might just mean that the AI builds a dedicated compiler for each individual function.
Why a dedicated compiler for function? The whole infrastructure generates the code.
I suggest some sceptics to try to do a ecommerce like application only with low code agentic tools, that already gives a glimpse where we are going.
Get an headless ecommerce or CMS SaaS product like Alokai (https://alokai.com), an iPaaS agentic platform like Workato (https://www.workato.com), and the whole application logic will be diagrams with English prompts, naturally with guardrails to the IA infrastructure more or else inline with the desired behaviour.
That is all, that is the application, these lego pieces connected via prompts.
For instance
; Sysv native vectors. Initializer values require matching [].
(mut x (the v64 [10 20]))
(set x (+ x 5))
(at x 0 17)
(print (at x 1))
(print (all (= x (the v64 [17 25]))))
; Parameter and result types can be written inline
(fn add4 ((a w64) (b w64)) -> w64 (+ a b))
(let ((result (add4 (the w64 [1 2 3 4]) (the w64 [10 20 30 40]))))
(print (at result 3)))
You also get full fp primitives ; helpers reused below
(fn inc (x) (+ x 1))
(fn dbl (x) (* x 2))
(fn sq (x) (* x x))
(fn pair (a b) (+ a b))
(fn add3 (a b c) (+ a b c))
(fn dv (a b) (/ a b))
(fn id (x) x)
(fn zero (x) 0)
; |> : pipe a value left-to-right through functions.
(print (|> 5 inc dbl sq)) ; => 144 (sq(dbl(inc 5)))
; >> : left-to-right compose; << : right-to-left compose.
(print ((>> inc dbl) 5)) ; => 12 (dbl(inc 5))
(print ((<< dbl inc) 5)) ; => 12 (dbl(inc 5))
; fmap / <$> : apply f, then g (same as >>).
(print ((fmap inc dbl) 5)) ; => 12
(print ((<$> inc dbl) 5)) ; => 12 (11 on sysv: (inc (dbl 5)), function-first)
; <*> (and its alias <>) : the S combinator, (f x (g x)).
(print ((<*> + (lambda (x) (+ x 2))) 5)) ; => 12 (5 + (5+2))
; <&> : flipped fmap, a(b x). <**> : flipped S, (g x (f x)).
(print ((<&> inc dbl) 5)) ; => 11 (inc(dbl 5))
(print ((<**> (lambda (x) (+ x 2)) +) 5)) ; => 12 (5 + (5+2))Case in point: claude code is in the bun runtime of JS. Not in any fancy optimized binary
Now, I will say im extremely productive with rust and LLMs, and its also comfortable to know that I wont have to rewrite anything to a new language, rust is already the best.
A famous swedish comedian talks about heroin as the "best drug". Where people usually end up and don't want to stop taking.
The current slop-code though ... I don't think many would miss it.
Others "heroin", as analogy, isn't one convincing to get into the slop addict scene really, in my opinion.
Useful error messages at compile time
Fast compilation to iterate and fix those errors
Efficient memory, CPU, and maybe GPU at runtime
Familiar from the training data [0]
One obvious/preferred way to do things
Explicit types
Rust hits some of those, but not all. I can't think of a language that hits all of them, but a lot of people sure love to rationalize why their own favorite language is the best choice. LLMs don't need syntax sugar and other niceties, and any errors postponed to runtime are a burden on you, not the model.We could add a few more rarely seen features to increase confidence in the results and make future modifications or switching models go better:
Required pre-conditions and post-conditions
Enforced limits on function or method length
Mandatory test cases
Enforced naming conventions
Lean style proofs of correctness? (probably not)
I'm on the fence about things like linear/affine types for memory management vs garbage collection. Obviously you want memory safety, but there's more than one to get that, and I don't know that you want to force contortions to build simple data structures.[0] LLMs are very capable of programming in languages they've never seen before. I've had them write programs using my own toy compilers for my own toy languages. However, you waste a lot of prompt tokens up front explaining things, and then they waste a lot of thinking tokens trying to get it right. Any new language would have a chicken and egg problem here, but LoRAs and model refinement could bridge the gap.
Error messages are mostly useful; compilation is quick (relative to an LLM); memory is not really optimal in most cases, but it's "good enough" and the language puts up a lot of guardrails around the programmer to keep them on the path to accidental success in this regard; the training data is full of .NET code; there's a well defined set of ways of working & best practices with .NET; types are explicit.
How would you be able to tell if it's the lesser amount of training data or the difficulty of the language that's making the difference?
Love the experience in general except that part.
I just asked chatgpt today for research on whether any feature of a programming language which has been identified in studies to make it better suited for agentic coding. Or whether popularity in the data-set has been proven to matter or even cross-language learning (knowledge from one language benefitting the LLM in writing in another).
Aside from popularity, nothing I could dredge up could prove strong correlations with anything else - including types
To me this is a sad development. AI skynet slop is winning. Does any real human, aside from the fanboi faction, really love "agentic programming"? That is to use prompts to autogenerate text that is source code? I find that both sad and horribly uninteresting. I also stopped reading AI slop generated descriptions - they are just spam, babelfish 2.0 if you will. When I know that the human behind that text, was too lazy to write it himself or herself, why would I want to read that text? That's just a waste of my time.
> But I think Rust is popular for another reason: because Rust happens to be a really good fit for agentic coding.
Ok, so Rust is the perfect language for bots. Wasn't the original idea to be a great language for humans? What is the point here if AI slop auto-generates everything? Why would you need a human here?
> Rust is designed to give “good performance by default”, making the idiomatic thing typically also be the fastest thing. But another key part of Rust is that you have the knobs to eke out better performance when you need it.
Ok but why does this then not apply to C, C++, Java, C#, D? These can not be used rather than Rust? And you also should not run into memory issues with C like pointers - after all, AI skynet slop should generate bug-free code in C or C++ too. So I don't get why Rust would be THE ultimate slop language here. To me, if AI works, then any language can be slopped down.
This reminds me of the incredibly sad presentation DHH gave on a rails-conf, aka now slop-conf, where he spoke about how AI will win and how Rust beats Ruby hands down and he only AI-slop-spams now (busy on Omarchyslop). These people don't have a "vision" that is decoupled from AI - they are businesspeople and promo-people, convincing you that AI slop is the future. To me this is very sad rather than ... "exciting".
Not quite the advantage in the AI era. Quite the contrary. Dynamic linking is something Rust will have to solve.
I've been doing Rust full time for the last half-decade and hobby before that, and its slow compile times have always been a pain point.
And I've found its slow cycle around compile-then-test is a real pain point with agentic development. Agents get into loops trying things out, and verifying their results, and they tend to accumulate a pile of tests on top of that (which require periodic cleanup). Forward progress often gets successively more slow and painful as compile times start to dominate most of what the agent is doing.
For application -- not systems dev work -- I've been considering making a move to using something like OCaml instead.
Also there is the part that why not generate machine code directly, where some always jump to answer "but non-determism!", well we have survived thus far with non-determinism in JIT compilers, tracing GC implementations, PGO metadata outcomes in AOT compilers, integration of machine learning in optimising compiler passes, how shader code executes in actual hardware,... the determinism ship is long gone.
So yeah, sad state of affairs, however the pandora box is open, is like Assembly devs wishing that compilers would just be a fluke and everyone would be shortly back into macro assemblers.
I don't love it, but it's my job now and I would prefer keeping it.
I'm not breaking any new ground with the project I'm in - just serving our users and there's a lot of stuff requiring improvement that would normally take a great deal of time to finish if it weren't for LLMs.
For my own things I would rather not use LLMs, but it's tempting, considering how little time I have for such activities nowadays.