For me the bottleneck now is reading/reviewing code, not writing code. As you said, AI makes it way easier to write, but do you not review the code? And isn't a verbose, cryptic language with lots of nitty gritty memory management not harder to read/review?
I'm not sold on Rust being a great language to use with AI unless the reason to use it is a lot more than just Rust being fashionable.
The verbose error handling diluting the interesting parts is one thing, but the main issue is the weak type system. Having to read the callee's code to check if it deviates from `res xor err`, or if it mutates its arguments. Figuring out which interface that `func (o *Obj) ()` is implementing, if any. Dealing with documentation that is a wall of 100 disappointing oneliners all repeating the function name.
Rust is information-dense and takes longer to master, but it's not inherently cryptic, there's a finite amount of things to know. Memory management sometimes take a bit of thought to write, but it's straightforward to review, you can trust it's correct if it compiles, you just keep an eye out for optimizations.
I don't see the difference in exploring an dense custom type system versus a flatter one. Both force you to look things up when you don't know about them.
In my opinion these problems originate in architectural style. Much of the open source written today is designed to impress the audience instead of focusing on the problem.
In my experience, Rust is only mildly unpleasant to review, if only because the GitHub PR review interface is not an IDE. It can be hard to tell why .as_ref()s and whatnot had to be used without being able to hover over a variable to see its type. This is probably because of the language's preference for type inference, though personally I would rather that than having to skim over explicit types.
Compared to Rust, Go as a language requires a lot more effort to review. You have to be on the lookout for basic gotchas like not checking if a pointer is nil, placing `defer` in the wrong place, using a result when err isn't nil, and so on. Plus, diffs are messier because unused variables are a compilation error, and _, err := can change into _, err = solely due to new lines above.
It's the same logic for human and for AI code: In Rust the compiler catches many bugs so you don't have to.
If the LLM gives you safe code you know there are entire classes of things you don't have to review for.
That said, I agree with you. My experience is that LLMs are great if you are highly competent in the domain in which you let them work. And it's probably easier to be competent in Go than in Rust.
Safe? No compiler is going to catch badly designed code, or intentionally backdoored code. Memory leaks as well. Compilers are the ground floor of validation and the least of your problems with AI generated code.
If the program design follows the principle of making illegal states unrepresentable (credit to Yaron Minsky), the compiler can catch much, much more than most people realize.
The process of designing a program like that itself catches a lot of "badly designed code". And such a design also naturally exposes many kinds of intentional backdoors, because security properties can quite easily be statically checked. For example, IDORs can be made literally impossible in such a design.
In discussions like this, I'm reminded of the William Gibson quote, "the future is already here, it's just unevenly distributed."
I found it's the opposite. Thanks to LLM's whole classes of problems otherwise solved by using Rust are gone. It's now more important that the generated code is easy to read.
Relative to Go? I'm pretty sure your Go code won't be faster if you used LLMs. If you need that, Rust is still preferred.
Relative to C/C++? That'll be very interesting. Do you have some evidence that LLMs can create memory-safe code in C/C++? It'll be truly amazing if true, but given that they apparently struggle to create/maintain big codebases in already-memory-safe languages I seriously doubt it.
IMO neither Go nor Rust are great for reading/reviewing code.
Go is too verbose and the type system isn't expressive enough. Rust code is littered with little memory management details and it requires tons of third party libraries.
I think coding agents will eventually be able to get the low level details right on their own. Reviewers should be able to focus on architecture, design and logic mistakes.
I also think we need a high level formal specification language to tell agents what we expect them to do.
> I also think we need a high level formal specification language to tell agents what we expect them to do.
Let’s make that specification Turing complete while at it.
Jokes aside, IMO it will be a good natural progression. Specify the problem statement in LLM specification, generate the code in Go/Rust whatever is the language of your choice and review the generated code to make sure it adheres to the architecture/design principles that you have set.
It absolutely should be Turing complete. I want to formally specify some constraints/invariants that any generated code has to meet, like very high level test cases.
It doesn't have to be a new language. I'm sure some existing language can be used to create a DSL that serves this purpose.
It can obviously never be complete. Some parts of the spec will always have to be natural language if we want to make the best use of LLMs.
Maybe we can have Large Logic Models instead, and they could have formalized keywords with rigid meanings? Like IF, WHILE and FOREACH maybe. Or even ASYNC if you want to be modern about it.
I do think that AI models should get better at logic. But if code generators are supposed to be tools, we have to tell them what to do. I'm not sure what combination of languages is best for that purpose.
It would be so much easier if we could precisely specify what we wanted, without all the double meanings, slang and general ambiguity that comes from using a natural language.
If only there was an entire class of well-studied languages which don't have any such ambiguity. They'd be perfect for programming LLMs! We could call them "programming languages" perhaps.
Time isn't the constraint here, but ability. Someone complaining about how hard Rust is to write is probably not capable of reviewing Rust code very well.
The usual reaction or opinion from e.g. good C++ programmers switching to Rust is that the added guardrails and expressivity are great and make things easier.
The benefit is if you lean heavily on types then successful compilation is a massive indicator in the feedback loop. Using stop hooks to ensure successful compilation after every iteration is a game changer. Go also has compilation of course but because the type system is so much more robust in Rust the compilation guarantees so much more about the behaviour of your program. You end up just code reviewing the shape and flow of data.
Code compiling is really the lowest bar of code validation, and doesn't say much of anything of the code running correctly. AI will pump out the most convoluted, over engineered, and at the same time sloppy code if you let it - and it will all compile fine.
Well, a good type system like Rust's lets you make impossible states impossible to enter/represent by the system.
Writing code so that impossible states are impossible is one of the hardest parts of software, so a good type system means that the code compiling means that the software is validated to be unable to represent certain states which is a very high bar of validation.
I suppose in your mind you were thinking of more trivial errors like typos, accessing variables that aren't available in scope, and such.
This is the main reason I use Rust over Go these days. The simplicity of Go was great for when I had to hold everything in my head and write everything myself. Rust makes more sense to me in the LLM era where I can offload more modeling/assumptions/invariants to the type system without having to be a Rust veteran.
The pinned invariants in my plan/spec become first-class invariants in the type system. It's great.
Yes, but all else being equal it is a higher bar in Rust than in Go. There are fewer things left for the human to check after a clean build+lint in Rust than in Go. The issue of over-engineered AI output is orthogonal to that.
I'm not sold on Rust being a great language to use with AI unless the reason to use it is a lot more than just Rust being fashionable.