I have a feeling there will be some people here that will take this very seriously and will spend a lot of time criticizing this project in angry comment threads that go on for miles.
Honestly, I thought it was serious because I’ve seen people do things exactly like this, just in different languages.
By “this” I mean “spend all their time fighting against the language/framework because they don’t like it, rather than just picking a different language.”
Those are excellent reasons but then you shouldn’t fight the language, you should go with the language/framework conventions as much as possible. Trying to fight the language design will only lead to buggy, hard to understand code, so either suck it up or get a different job.
EDIT: That last sentence is a bit harsher than I intended. I’m trying to convey the importance of professionalism in our work and remembering the experience of working with people who couldn’t do this brought back some bad memories!
Don't worry, they probably wouldn't want to work with you either.
Some programmers think and care a lot about software correctness in a kind of mathematical way. Others just want to ship features and enjoy their lives. Both approaches are fine. They just don't necessarily mix super well.
Some people like to tell you that diverse teams work better. Years ago I worked with someone who had a PhD in psychometrics. She said that's kind of a lie. If you actually look at the research it shows something more interesting. She said the research shows that having a diverse set of backgrounds makes a team perform better. But having a diverse set of values makes a team perform worse. It makes sense. If one person on the team wants to vibe code and someone else wants to make every line of code perfect, you're all in for a bad time.
There is a third kind. Those who want to have a lot of fun by using their imagination to come up with interesting ways build something, but in rust, the borrow checker often won't have any of it.
In rust you have to learn and internalize lot of the non-intutive borrow checker reasoning to remain sane. If you remember to spend a fraction of that effort to remember the "unsafe" things you could end up doing in C, then I think most people would be fine.
But rust enforces it, which is good for a small fraction of all software that is being written. But "Rust for everything!?"..Give me a fucking break!
This can't possibly be guaranteed to work just by disabling the checker, can it? If Rust optimizes based on borrow-checker assumptions (which I understand it can and does) then wouldn't violating them be UB, unless you also mess with the compiler to disable those optimizations?
If you write correct Rust code it'll work, the borrowck is just that, a check, if the teacher doesn't check your homework where you wrote that 10 + 5 = 15 it's still correct. If you write incorrect code where you break Rust's borrowing rules it'll have unbounded Undefined Behaviour, unlike the actual Rust where that'd be an error this thing will just give you broken garbage, exactly like a C++ compiler.
Evidently millions of people want broken garbage, Herb Sutter even wrote a piece celebrating how many more C++ programmers and projects there were last year, churning out yet more broken garbage, it's a metaphor for 2025 I guess.
> This can't possibly be guaranteed to work just by disabling the checker, can it?
It works in the sense that the borrow checker stops bothering you and the compiler will compile your code. It will even work fine as long as you don't write code which invokes UB (which does include code which would not pass the borrow checker, as the borrow checker necessarily rejects valid programs in order to forbid all invalid programs).
> It will even work fine as long as you don't write code which invokes UB (which does include code which would not pass the borrow checker, as the borrow checker necessarily rejects valid programs in order to forbid all invalid programs).
To be clear, by "this" I meant "[allowing] code that would normally violate Rust's borrowing rules to compile and run successfully," which both of us seem to believe to be UB.
Yes. An analog would be uninitialized memory. The compiler is free to make optimizations that assume that uninitialized memory holds every value and no value simultaneously (because it is undefined behavior to ever read it).
In the following example, z is dereferenced one time and assigned to both x and y, but if z and x are aliased, then this is an invalid optimization.
What are protental issues with compiler, by just disabling borrow checker? If I recall correctly some compiler optimisations for rust can not be done in C/C++ because of restrictions implied by borrow checker.
The crazy part about this is that (auto) vectorization in Rust looks something like this: iter.chunks(32).map(vectorized)
Where the vectorized function checks if the chunk has length 32, if yes run the algorithm, else run the algorithm.
The compiler knows that the chunk has a fixed size at compile time in the first block, which means it can now attempt to vectorize the algorithm with a SIMD size of 32. The else block handles the scalar case, where the chunk is smaller than 32.
The borrow checker does not deal with ownership, which is what rust’s memory management leverages. The borrow checker validates that borrows (references) are valid aka that they don’t outlive their sources and that exclusive borrows don’t overlap.
The borrow checker does not influence codegen at all.
It would be the same as in any language with manual memory management, you'd simply get a dangling pointer access. The 'move-by-default' semantics of Rust just makes this a lot trickier than in a 'copy-by-default' language though.
It's actually interesting to me that the Rust borrow checker can 'simply' be disabled (e.g. no language- or stdlib-features really depending on the borrow checker pass) - not that it's very useful in practice though.
> In addition to meeting the Open Source Definition, the following standards apply to new licenses:
> (...) The license does not have terms that structurally put the licensor in a more favored position than any licensee.
https://opensource.org/licenses/review-process
That's a funfact I learned from IP lawyer when discussing possibility of open-source but otherwise LLVM-extempt license. If there is extemption (even in LLM) such license is most likely OSI-incompatible.
In rust you don’t have a garbage collector and you don’t manually deallocate - if the compiler is not certain of who drops memory and when, what happens with those ambiguous drops ?
In other words, are the silenced errors guaranteed to be memory leaks/use after frees?
The borrow checker doesn't decide when things are dropped. It only checks reference uses and doesn't generate any code. This will work exactly the same as long as your program doesn't violate any borrowing rules.
No, I get that from an architectural perspective they are separate processes. The point is, unlike in other languages, the compiler is developed assuming the input has been borrow checked, right? So it is surprising to me that it doesn’t blow up somewhere when that invariant doesn’t hold.
> So it is surprising to me that it doesn’t blow up somewhere when that invariant doesn’t hold.
The final program may be broken in various manners because you don't respect the language's prescribed semantics, in about the same way they do in C and C++. From the compiler's perspective the borrow checker validates that rules it assumes are upheld are actually upheld.
mrustc already compiles rust code without having a borrow checker (well IIRC recent-ish versions of mrustc have some borrow checking bits, but for the most part it still assumes that somebody else has done all the borrow checking).
> The rust compiler thinks it knows better than you. It won't let you have two pointers to the same thing. It treats you like a mass of incompetence that can't be trusted with a pointer.
It does seem like satire. The very first example is:
fn main() {
let a = String::from("hello");
let b = a;
println!("{a}"); // Works! Prints: hello
}
This is not “I have correct code but Rust can’t tell it’s correct.” This is “wow, this code is intentionally outrageously wrong, obviously dereferences a pointer that is invalid, and happens to work anyway.”
I am wondering whether this would actually be a helpful compile option in upstream rustc for quick prototyping. I don't want prod code to use this, but if I want to try things out during development, this could substantially shorten the dev cycle.
After a while, you just don't write code that would cause substantial borrow-checker problems, even when prototyping. I'd say the slow compile times are much more of an impediment for a practicing Rust prototyper than the borrow checker.
Sometimes, you just need to know if an idea will even work or what it would look like. If you have to refactor half the codebase (true story for me once), it makes the change a much harder sell without showing some benefits. IE, it keeps you from discovering better optimizations because you have to pay the costs upfront.
Can't you usually just throw some quick referenced counted cells in there, to make the borrow checker happy enough for a prototype without refactoring the whole code base?
In Rust, it's a lot easier to refactor half the codebase than it would be in another language. Once you're done fighting the compiler, you're usually done! instead of NEVER being sure if you did enough testing.
Amazing, this is like the bizarro version of what I'd want. Like someone said 'hey, there's this kinda crappy language with a really cool feature, let's not make a great language with that feature, but instead take the crappy language and remove the cool feature which is the only thing keeping it from being trash'. Okay, sure, tagged unions, closures, and hygienic macros are nice; but there are plenty of other languages with the first two and when your syntax is atrocious even the most hygienic macro is going to look like something that crawled out of the sewer at R'lyeh.
I wish I could make the borrow checker give warnings not errors.
It would make exploration so much easier, so I don’t have to fight the borrow checker until I know how to build what I want.
To me it feels like rust is barely readable sometimes. When I read some rust cost, I am often incapable to guess what it does, so it does not feel intuitive.
I wish they made something simpler. At least C and C++ have a low barrier of entry and any beginner can write code.
I don't think the borrow checker forced rust to be such a complicated language.
There's a weird cognitive bias where somehow people justify "I compiled this Hello World C++ project " as "C++ is easy" and yet "I wasn't able to understand how this optimized linear algebra library works" gets classed as "Rust is hard".
In reality it matters what you already know, and whether you want to understand deeply or are just interested in enough surface understanding to write software. There's a reason C++ has an entire book about its many, many types of initialization for example.
Imo the worst thing about starting out with C++ (which is much better with Rust), is the lack of credible package management/build system that allows you to just install packages.
This used to be even more true previously than today. Nowadays, there's stuff like
vcpkg, and tons of resources, but I still wouldn't call it straightforward compared to something like nuget or cargo.
It tooke me more time to figure out CMake than entire other programming languages.
It does really help, in modern languages where they provide tools in the box and the ecosystem just accepts those as the default† tools, to have the default be that when you make a new project it just works, often by having it print "Hello, World!" or something else simple but definitive as proof we made a program.
† Default means just that, neither Rust's own compiler nor the Linux kernel need the cargo tooling, but these projects both have actual toolsmiths to maintain their build infrastructure and your toy program does not. There should be a default which Just Works at this small scale.
Yes, Rust has a pretty steep learning curve. If you're not writing very low level stuff and don't need to squeeze out every last bit of performance, there are many other, simpler languages to choose from.
I think we may safely assume that Rust's designers are smart people that have made every effort to keep Rust as simple as it can be, given its intended use.
> At least C and C++ have a low barrier of entry and any beginner can write code.
C/C++ is great at giving that false sense of competence. Then suddenly you're getting a segfault, and you'll never determine why with beginner knowledge, since the crash-line and the mistake-line aren't even in the same zipcode (and or same Git changeset).
Rust forces you to not "skip" knowledge steps. If you have a gap in your knowledge/understanding the compiler will call you out immediately. C/C++ will happily let your dangerously bad code compile and kinda-run, until it doesn't.
I'm not anti-C/C++, I've actually written tons. I love C in particular. But saying that they're beginner-friendly feels wrong, a lot of people quit the language because "random stuff" starts to go wrong, and they lack the knowledge to determine why.
Yep. I've heard it said that Rust forces you to experience all the pain up front. C will happily compile very broken code.
One of my formative memories learning C came after I wrote a function which accidentally returned a pointer to a variable on the stack. It took me about a week to track that bug down. I found it eventually - and then realised the compiler had been warning me about it the whole time. I'd just been ignoring the warnings "while I got my code working". Ugh. The rust borrow checker wouldn't let you even compile code like that.
If you're going to be working in a programming language for years or even decades, I think the extra complexity (and extra difficulty while learning) is an investment that will pay off. But I'd be very happy for rust to stay a niche language for systems software. C#, Go, Typescript and Swift seem like great choices for making webpages and apps.
I think the barrier to entry with Rust is lower than C++. Like was way lower... And I've been writing C++ for way long than Rust, so I'm probably a bit biased
I can just second that. Maybe someone (or some LLM) can write a nice superset of Rust that is more readable - so the barrier of entry drops significantly and we can all write better, more efficient and memory-safe code!
> To me it feels like rust is barely readable sometimes. When I read some rust cost, I am often incapable to guess what it does, so it does not feel intuitive.
I feel torn with this sentiment.
On one hand, I totally agree. Rust's "foreign" ideas (borrowck, lifetimes, match expressions, traits, etc) make it harder to learn because there's a bunch of new concepts that nobody has really worked with before. Some of this stuff - lifetimes and borrows especially - really demand a lot of imagination on behalf of the programmer to be able to understand what's actually going on. The amount of thinking I do per shipped line of code seems higher for rust than it does for languages like Go, Typescript and C#. And sometimes C.
On the other hand, I learned C about 30 years ago. Not only have I forgotten how hard it was to learn, but I had the brain of a teenager at the time. And now I'm in my (early) 40s. I'm scared that some of the struggle I went through learning rust came because my brain is old now, and I've forgotten what its like to be out of my depth with a programming language. Learning rust requires shaking up some old neurons. And that's really good for us, but it sucks.
In reality, I think its a bit of both. I've been using rust a lot for about 3-4 years now. Its gotten way easier. But I still prototype a fair bit of algorithmic code in typescript first because I find TS makes it easier to iterate. That implies rust is actually more complex. But, some people pick rust as their first language and it seems to work out fine? I'm not sure.
> I don't think the borrow checker forced rust to be such a complicated language.
Which parts of rust seem complicated? I've found a lot of the things I struggled with at first got a lot easier with familiarity. I love traits and match expressions. I love rust's implementation of generics. I love most things about cargo and the module system. But also, some parts of rust annoy me a lot more now, a few years in.
I disagree with your comment. I think the main source of complexity in rust comes from lifetimes - which are required by the borrow checker. For example, its not obvious when you need to put lifetimes in explicitly and when you can elide them. When does the borrow checker understand my code? (Eg, can you mutably borrow two different elements in an array at the same time?). I also still don't really understand Higher-Rank Trait Bounds.
I also still find Pin really confusing. In general I think async and Futures in rust have some big design flaws. It also really bothers me that there's a class of data types that the compiler can generate and use, which are impossible to name in the language. And some of the rules around derive and traits are annoying and silly. Eg derive(Clone) on a generic struct adds the constraint T: Clone, which is straight out wrong. And rust needs a better answer to the orphan rule.
But in general, if you take out the borrow checker, I find rust to be simpler and easier to read than most C++. There's no headers. No exceptions. No wild template nonsense. And there's generally way less weird magic going on. Eg, Foo(bar); could mean about 8 different things in C++. Rust isn't like that. Rust is simple enough you can just read the standard library, even as a beginner, and its great. C++'s STL is a disaster to read.
Rust is definitely more complex than C. But you do get some lovely features for that extra cognitive overhead. Whether or not thats worth it is up to you. In general - and I've been saying this for years - I feel like the language I really want is rust 2. I can't wait for someone to take rust's best ideas and refine them into a simpler language.
I feel exactly the same - C++ might be a much more complex and arcane language when you consider its entire feature set, and all the syntactic machinery (I figured out by looking at STL or Boost code, just how much of C++ I don't know or understand), you can choose to not engage with most of the language. Hell, even stuff like unique_ptr is optional when you're just starting out.
But with Rust, you have to understand almost all of the language very intimately to be a productive programmer, and Rust is not that great at hiding complexity, as in fairly innocious decisions often have far-reaching consequences down the line.
> you have to understand almost all of the language very intimately to be a productive programmer,
I've seen absolute Rust noobs write production code in Rust, I have no idea where did you get that notion from. Most of the apps I've written or I've worked with don't even need to use explicit lifetimes at all. If you don't need absolute performance with almost none memory allocations, it's honestly not rocket science. Even more so if you're writing web backends. Then the code doesn't really differ that much from Go.
I've shipped a lot of Rust software without the understanding or even attempting to learn a lot of the language. There is plenty of things in core libraries around traits that I have no idea how they work or really care.
Tangentially related: the opposite, Rust's borrow checker sans the compiler, is actually very useful. As far as I understand, the borrow checker is a significant part of the work of writing a Rust compiler. Therefore, having the official borrow checker available as a standalone program can make alternative compilers (e.g. for exotic hardware) feasible faster, because they won't need a borrow checker of their own from the get-go.
Why would this matter? The borrowck is (a) not needed during bring-up because as its name suggests it is merely a check, so going without it just means you can write nonsense and then unbounded undefined behaviour results, but (b) written entirely in Rust so you can just compile it with the rest of this "exotic hardware" Rust compiler you've built.
It’s technically possible to do, just very complicated and hard. Quite often, prohibitively so.
Still, the main idea is despite the input files are arbitrarily large, you don’t need an entire file in memory because displays aren’t remotely large enough to render a megabyte of text. Technically, you can only load a visible portion of the input file, and stream from/to disk when user scrolls. Furthermore, if you own the file format, you can design it in a way which allowing editing without overwriting the entire file: mark deleted portions without moving subsequent content, write inserts to the end of files, maybe organize the file as a B+ tree, etc.
That’s how software like Word 97 supported editing of documents much larger than available memory. As you can imagine, the complexity of such file format, and the software handling them, was overwhelming. Which is why software developers stopped doing things like that as soon as computers gained enough memory to keep entire documents, and instead serialize them into sane formats like zipped XMLs in case of modern MS office.
> What if you don't know ahead of time how big that monitor is that you are displaying stuff on?
Use a reasonable upper estimate?
> ad-hoc re-implementation of virtual memory?
If you rely on actual virtual memory instead of specially designed file format, saving large files will become prohibitively slow. On each save you have to stream the entire document from page file to actual memory, serialize the document, produce the entire file, then replace. And then when resuming editing after the save, you probably have to load the visible portion back from disk.
I have a feeling there will be some people here that will take this very seriously and will spend a lot of time criticizing this project in angry comment threads that go on for miles.
Honestly, I thought it was serious because I’ve seen people do things exactly like this, just in different languages.
By “this” I mean “spend all their time fighting against the language/framework because they don’t like it, rather than just picking a different language.”
There can be good reasons for choosing a language that you otherwise don't like.
Eg legacy software, or because your boss tells you, or because of legal requirements, or because of library availability etc.
Those are excellent reasons but then you shouldn’t fight the language, you should go with the language/framework conventions as much as possible. Trying to fight the language design will only lead to buggy, hard to understand code, so either suck it up or get a different job.
EDIT: That last sentence is a bit harsher than I intended. I’m trying to convey the importance of professionalism in our work and remembering the experience of working with people who couldn’t do this brought back some bad memories!
Certain people feel very emotional about the compilers and interpreters they use
You couldn't pay me to work with them
Don't worry, they probably wouldn't want to work with you either.
Some programmers think and care a lot about software correctness in a kind of mathematical way. Others just want to ship features and enjoy their lives. Both approaches are fine. They just don't necessarily mix super well.
Some people like to tell you that diverse teams work better. Years ago I worked with someone who had a PhD in psychometrics. She said that's kind of a lie. If you actually look at the research it shows something more interesting. She said the research shows that having a diverse set of backgrounds makes a team perform better. But having a diverse set of values makes a team perform worse. It makes sense. If one person on the team wants to vibe code and someone else wants to make every line of code perfect, you're all in for a bad time.
There is a third kind. Those who want to have a lot of fun by using their imagination to come up with interesting ways build something, but in rust, the borrow checker often won't have any of it.
In rust you have to learn and internalize lot of the non-intutive borrow checker reasoning to remain sane. If you remember to spend a fraction of that effort to remember the "unsafe" things you could end up doing in C, then I think most people would be fine.
But rust enforces it, which is good for a small fraction of all software that is being written. But "Rust for everything!?"..Give me a fucking break!
This can't possibly be guaranteed to work just by disabling the checker, can it? If Rust optimizes based on borrow-checker assumptions (which I understand it can and does) then wouldn't violating them be UB, unless you also mess with the compiler to disable those optimizations?
If you write correct Rust code it'll work, the borrowck is just that, a check, if the teacher doesn't check your homework where you wrote that 10 + 5 = 15 it's still correct. If you write incorrect code where you break Rust's borrowing rules it'll have unbounded Undefined Behaviour, unlike the actual Rust where that'd be an error this thing will just give you broken garbage, exactly like a C++ compiler.
Evidently millions of people want broken garbage, Herb Sutter even wrote a piece celebrating how many more C++ programmers and projects there were last year, churning out yet more broken garbage, it's a metaphor for 2025 I guess.
I have been using kde for years now without a single problem. Calling cpp garbage sounds wrong.
People don't want garbage. But in any case, they don't want straightjackets like the borrow checker.
Hence, they use GC'd languages like Go whenever they can.
Straightjackets can be very useful.
Haskell (and OCaml etc) give you both straightjackets and a garbage collector. Straightjackets and GC are very compatible.
Compared to C, which has neither straightjackets nor a GC (at least not by default).
>Straitjackets can be very useful.
Only if you’re insane.
Damn! This is the funniest HN comment that I have ever come across...
The meaning of straightjacket here is inherently subjective and not to be meant literally.
How dare you. C is a fine language.
Just don't accidentally step on any of these landmines and we'll all get along great.
> Straightjackets can be very useful.
Except Rust's straightjacket is so tight it obstructs blood circulation to the brain.
> Straightjackets and GC are very compatible.
Of course, if the straightjacket induces vertigo it should be taken off. Doctors say straightjackets should be used sparingly.
(Yes, I agree that Rust is missing an automatic GC.)
> This can't possibly be guaranteed to work just by disabling the checker, can it?
It works in the sense that the borrow checker stops bothering you and the compiler will compile your code. It will even work fine as long as you don't write code which invokes UB (which does include code which would not pass the borrow checker, as the borrow checker necessarily rejects valid programs in order to forbid all invalid programs).
> It will even work fine as long as you don't write code which invokes UB (which does include code which would not pass the borrow checker, as the borrow checker necessarily rejects valid programs in order to forbid all invalid programs).
To be clear, by "this" I meant "[allowing] code that would normally violate Rust's borrowing rules to compile and run successfully," which both of us seem to believe to be UB.
Yes. An analog would be uninitialized memory. The compiler is free to make optimizations that assume that uninitialized memory holds every value and no value simultaneously (because it is undefined behavior to ever read it).
In the following example, z is dereferenced one time and assigned to both x and y, but if z and x are aliased, then this is an invalid optimization.
https://rust.godbolt.org/z/Mc6fvTzPG> If Rust optimizes based on borrow-checker assumptions
This is a binary assumption that you can understand to evaluate to "true" in the absence of a borrow checker. If it is "false" it halts the compiler
What are protental issues with compiler, by just disabling borrow checker? If I recall correctly some compiler optimisations for rust can not be done in C/C++ because of restrictions implied by borrow checker.
Rust can set restricts to all pointers, because 1 mut xor many shared refs rule. Borrow checker empowers this. https://en.wikipedia.org/wiki/Restrict
The crazy part about this is that (auto) vectorization in Rust looks something like this: iter.chunks(32).map(vectorized)
Where the vectorized function checks if the chunk has length 32, if yes run the algorithm, else run the algorithm.
The compiler knows that the chunk has a fixed size at compile time in the first block, which means it can now attempt to vectorize the algorithm with a SIMD size of 32. The else block handles the scalar case, where the chunk is smaller than 32.
Without the borrow checker, how should memory be managed? Just never deallocate?
The borrow checker does not deal with ownership, which is what rust’s memory management leverages. The borrow checker validates that borrows (references) are valid aka that they don’t outlive their sources and that exclusive borrows don’t overlap.
The borrow checker does not influence codegen at all.
It would be the same as in any language with manual memory management, you'd simply get a dangling pointer access. The 'move-by-default' semantics of Rust just makes this a lot trickier than in a 'copy-by-default' language though.
It's actually interesting to me that the Rust borrow checker can 'simply' be disabled (e.g. no language- or stdlib-features really depending on the borrow checker pass) - not that it's very useful in practice though.
There are easier ways of making segfault than writing a custom compiler.
I’m not picturing how it works.
In rust you don’t have a garbage collector and you don’t manually deallocate - if the compiler is not certain of who drops memory and when, what happens with those ambiguous drops ?
In other words, are the silenced errors guaranteed to be memory leaks/use after frees?
The borrow checker doesn't decide when things are dropped. It only checks reference uses and doesn't generate any code. This will work exactly the same as long as your program doesn't violate any borrowing rules.
No, I get that from an architectural perspective they are separate processes. The point is, unlike in other languages, the compiler is developed assuming the input has been borrow checked, right? So it is surprising to me that it doesn’t blow up somewhere when that invariant doesn’t hold.
> So it is surprising to me that it doesn’t blow up somewhere when that invariant doesn’t hold.
The final program may be broken in various manners because you don't respect the language's prescribed semantics, in about the same way they do in C and C++. From the compiler's perspective the borrow checker validates that rules it assumes are upheld are actually upheld.
mrustc already compiles rust code without having a borrow checker (well IIRC recent-ish versions of mrustc have some borrow checking bits, but for the most part it still assumes that somebody else has done all the borrow checking).
I don't think so, I don't think Rust's borrow checker is free of false negatives.
Rust's concept of lifetime and scopes exists independently of the borrow checker
For everyone unaware, this repo is a meme:
https://www.reddit.com/r/rust/comments/1q0kvn1/corroded_upda...
As a follow on to the corroded meme crate:
https://github.com/buyukakyuz/corroded
> What Is This
> The rust compiler thinks it knows better than you. It won't let you have two pointers to the same thing. It treats you like a mass of incompetence that can't be trusted with a pointer.
> We fix that.
It does seem like satire. The very first example is:
This is not “I have correct code but Rust can’t tell it’s correct.” This is “wow, this code is intentionally outrageously wrong, obviously dereferences a pointer that is invalid, and happens to work anyway.”I am wondering whether this would actually be a helpful compile option in upstream rustc for quick prototyping. I don't want prod code to use this, but if I want to try things out during development, this could substantially shorten the dev cycle.
After a while, you just don't write code that would cause substantial borrow-checker problems, even when prototyping. I'd say the slow compile times are much more of an impediment for a practicing Rust prototyper than the borrow checker.
What the point, though? You will get compiling code, but later you would need to reachitecture code to avoid violating rust rules.
Sometimes, you just need to know if an idea will even work or what it would look like. If you have to refactor half the codebase (true story for me once), it makes the change a much harder sell without showing some benefits. IE, it keeps you from discovering better optimizations because you have to pay the costs upfront.
Can't you usually just throw some quick referenced counted cells in there, to make the borrow checker happy enough for a prototype without refactoring the whole code base?
In Rust, it's a lot easier to refactor half the codebase than it would be in another language. Once you're done fighting the compiler, you're usually done! instead of NEVER being sure if you did enough testing.
Should be named in rust we don't trust
This should be called trust, because it does view the developer as evil.
Love the "Note for LLMs" and the NSFW license.
It would be great if it only allowed multiple mutable borrows. That's the only one that always bugs me, for mostly innocuous stuff.
I don’t have a slightest idea why would anyone want this. Borrow checking is one of the greatest benefits of Rust.
It is funny.
Amazing, this is like the bizarro version of what I'd want. Like someone said 'hey, there's this kinda crappy language with a really cool feature, let's not make a great language with that feature, but instead take the crappy language and remove the cool feature which is the only thing keeping it from being trash'. Okay, sure, tagged unions, closures, and hygienic macros are nice; but there are plenty of other languages with the first two and when your syntax is atrocious even the most hygienic macro is going to look like something that crawled out of the sewer at R'lyeh.
Are the compile times noticeably faster?
Probably not, because it seems like it still checks for errors but just suppresses them.
Even so, the borrow checker repeatedly profiles as an insignificant part of compile times, so wouldn’t make a difference.
I wish I could make the borrow checker give warnings not errors. It would make exploration so much easier, so I don’t have to fight the borrow checker until I know how to build what I want.
Then you have code full of warnings and undefined behavior?
I think fighting the borrow checker is more like a rite of passage. Rust is not my favorite language but the borrow checker is great.
A motivation section in the readme seems like it is needed.
https://github.com/buyukakyuz/corroded/issues/11#issuecommen...
undefined behavior on steroids be like:
To me it feels like rust is barely readable sometimes. When I read some rust cost, I am often incapable to guess what it does, so it does not feel intuitive.
I wish they made something simpler. At least C and C++ have a low barrier of entry and any beginner can write code.
I don't think the borrow checker forced rust to be such a complicated language.
C++ doesn't have low barrier of entry, I almost quit programming as a teen because of C++.
There's a weird cognitive bias where somehow people justify "I compiled this Hello World C++ project " as "C++ is easy" and yet "I wasn't able to understand how this optimized linear algebra library works" gets classed as "Rust is hard".
In reality it matters what you already know, and whether you want to understand deeply or are just interested in enough surface understanding to write software. There's a reason C++ has an entire book about its many, many types of initialization for example.
Imo the worst thing about starting out with C++ (which is much better with Rust), is the lack of credible package management/build system that allows you to just install packages.
This used to be even more true previously than today. Nowadays, there's stuff like vcpkg, and tons of resources, but I still wouldn't call it straightforward compared to something like nuget or cargo.
It tooke me more time to figure out CMake than entire other programming languages.
It does really help, in modern languages where they provide tools in the box and the ecosystem just accepts those as the default† tools, to have the default be that when you make a new project it just works, often by having it print "Hello, World!" or something else simple but definitive as proof we made a program.
† Default means just that, neither Rust's own compiler nor the Linux kernel need the cargo tooling, but these projects both have actual toolsmiths to maintain their build infrastructure and your toy program does not. There should be a default which Just Works at this small scale.
Yes, Rust has a pretty steep learning curve. If you're not writing very low level stuff and don't need to squeeze out every last bit of performance, there are many other, simpler languages to choose from.
I think we may safely assume that Rust's designers are smart people that have made every effort to keep Rust as simple as it can be, given its intended use.
> At least C and C++ have a low barrier of entry and any beginner can write code.
C/C++ is great at giving that false sense of competence. Then suddenly you're getting a segfault, and you'll never determine why with beginner knowledge, since the crash-line and the mistake-line aren't even in the same zipcode (and or same Git changeset).
Rust forces you to not "skip" knowledge steps. If you have a gap in your knowledge/understanding the compiler will call you out immediately. C/C++ will happily let your dangerously bad code compile and kinda-run, until it doesn't.
I'm not anti-C/C++, I've actually written tons. I love C in particular. But saying that they're beginner-friendly feels wrong, a lot of people quit the language because "random stuff" starts to go wrong, and they lack the knowledge to determine why.
Yep. I've heard it said that Rust forces you to experience all the pain up front. C will happily compile very broken code.
One of my formative memories learning C came after I wrote a function which accidentally returned a pointer to a variable on the stack. It took me about a week to track that bug down. I found it eventually - and then realised the compiler had been warning me about it the whole time. I'd just been ignoring the warnings "while I got my code working". Ugh. The rust borrow checker wouldn't let you even compile code like that.
If you're going to be working in a programming language for years or even decades, I think the extra complexity (and extra difficulty while learning) is an investment that will pay off. But I'd be very happy for rust to stay a niche language for systems software. C#, Go, Typescript and Swift seem like great choices for making webpages and apps.
I think the barrier to entry with Rust is lower than C++. Like was way lower... And I've been writing C++ for way long than Rust, so I'm probably a bit biased
> To me it feels like rust is barely readable sometimes. [...] C++ have a low barrier of entry and any beginner can write code.
Here's rust code:
Here is the equivalent C++ for the vast majority of its life (any time before C++23, has MS even shipped C++23 support yet?): C++ initialisation alone is a more complex topic than pretty much any facet of Rust. And it's not hard to find C++ which is utterly inscrutable.I can just second that. Maybe someone (or some LLM) can write a nice superset of Rust that is more readable - so the barrier of entry drops significantly and we can all write better, more efficient and memory-safe code!
> To me it feels like rust is barely readable sometimes. When I read some rust cost, I am often incapable to guess what it does, so it does not feel intuitive.
I feel torn with this sentiment.
On one hand, I totally agree. Rust's "foreign" ideas (borrowck, lifetimes, match expressions, traits, etc) make it harder to learn because there's a bunch of new concepts that nobody has really worked with before. Some of this stuff - lifetimes and borrows especially - really demand a lot of imagination on behalf of the programmer to be able to understand what's actually going on. The amount of thinking I do per shipped line of code seems higher for rust than it does for languages like Go, Typescript and C#. And sometimes C.
On the other hand, I learned C about 30 years ago. Not only have I forgotten how hard it was to learn, but I had the brain of a teenager at the time. And now I'm in my (early) 40s. I'm scared that some of the struggle I went through learning rust came because my brain is old now, and I've forgotten what its like to be out of my depth with a programming language. Learning rust requires shaking up some old neurons. And that's really good for us, but it sucks.
In reality, I think its a bit of both. I've been using rust a lot for about 3-4 years now. Its gotten way easier. But I still prototype a fair bit of algorithmic code in typescript first because I find TS makes it easier to iterate. That implies rust is actually more complex. But, some people pick rust as their first language and it seems to work out fine? I'm not sure.
> I don't think the borrow checker forced rust to be such a complicated language.
Which parts of rust seem complicated? I've found a lot of the things I struggled with at first got a lot easier with familiarity. I love traits and match expressions. I love rust's implementation of generics. I love most things about cargo and the module system. But also, some parts of rust annoy me a lot more now, a few years in.
I disagree with your comment. I think the main source of complexity in rust comes from lifetimes - which are required by the borrow checker. For example, its not obvious when you need to put lifetimes in explicitly and when you can elide them. When does the borrow checker understand my code? (Eg, can you mutably borrow two different elements in an array at the same time?). I also still don't really understand Higher-Rank Trait Bounds.
I also still find Pin really confusing. In general I think async and Futures in rust have some big design flaws. It also really bothers me that there's a class of data types that the compiler can generate and use, which are impossible to name in the language. And some of the rules around derive and traits are annoying and silly. Eg derive(Clone) on a generic struct adds the constraint T: Clone, which is straight out wrong. And rust needs a better answer to the orphan rule.
But in general, if you take out the borrow checker, I find rust to be simpler and easier to read than most C++. There's no headers. No exceptions. No wild template nonsense. And there's generally way less weird magic going on. Eg, Foo(bar); could mean about 8 different things in C++. Rust isn't like that. Rust is simple enough you can just read the standard library, even as a beginner, and its great. C++'s STL is a disaster to read.
Rust is definitely more complex than C. But you do get some lovely features for that extra cognitive overhead. Whether or not thats worth it is up to you. In general - and I've been saying this for years - I feel like the language I really want is rust 2. I can't wait for someone to take rust's best ideas and refine them into a simpler language.
I feel exactly the same - C++ might be a much more complex and arcane language when you consider its entire feature set, and all the syntactic machinery (I figured out by looking at STL or Boost code, just how much of C++ I don't know or understand), you can choose to not engage with most of the language. Hell, even stuff like unique_ptr is optional when you're just starting out.
But with Rust, you have to understand almost all of the language very intimately to be a productive programmer, and Rust is not that great at hiding complexity, as in fairly innocious decisions often have far-reaching consequences down the line.
> you have to understand almost all of the language very intimately to be a productive programmer,
I've seen absolute Rust noobs write production code in Rust, I have no idea where did you get that notion from. Most of the apps I've written or I've worked with don't even need to use explicit lifetimes at all. If you don't need absolute performance with almost none memory allocations, it's honestly not rocket science. Even more so if you're writing web backends. Then the code doesn't really differ that much from Go.
I've shipped a lot of Rust software without the understanding or even attempting to learn a lot of the language. There is plenty of things in core libraries around traits that I have no idea how they work or really care.
Tangentially related: the opposite, Rust's borrow checker sans the compiler, is actually very useful. As far as I understand, the borrow checker is a significant part of the work of writing a Rust compiler. Therefore, having the official borrow checker available as a standalone program can make alternative compilers (e.g. for exotic hardware) feasible faster, because they won't need a borrow checker of their own from the get-go.
Why would this matter? The borrowck is (a) not needed during bring-up because as its name suggests it is merely a check, so going without it just means you can write nonsense and then unbounded undefined behaviour results, but (b) written entirely in Rust so you can just compile it with the rest of this "exotic hardware" Rust compiler you've built.
Yeah, you're right, I'm misremembering something here. Thanks for the correction.
I get your point, but still you haven't identified a use for the borrow checker sans the compiler.
C++ with extra steps?
Uh oh, this might look like a potentially memory-unsafe version of Rust...
Rust++ would be a nicer name then
Rust++? :)
Bust?
Rust- is you use C with ring buffers. If you think you need dynamic memory allocation your program is underspecified.
Avoiding dynamic allocation does not avoid memory unsafety in C.
How does "zero dynamic allocation" work in practice for something like a text editor IE. vscode or other apps that let users open arbitrary files?
It’s technically possible to do, just very complicated and hard. Quite often, prohibitively so.
Still, the main idea is despite the input files are arbitrarily large, you don’t need an entire file in memory because displays aren’t remotely large enough to render a megabyte of text. Technically, you can only load a visible portion of the input file, and stream from/to disk when user scrolls. Furthermore, if you own the file format, you can design it in a way which allowing editing without overwriting the entire file: mark deleted portions without moving subsequent content, write inserts to the end of files, maybe organize the file as a B+ tree, etc.
That’s how software like Word 97 supported editing of documents much larger than available memory. As you can imagine, the complexity of such file format, and the software handling them, was overwhelming. Which is why software developers stopped doing things like that as soon as computers gained enough memory to keep entire documents, and instead serialize them into sane formats like zipped XMLs in case of modern MS office.
What if you don't know ahead of time how big that monitor is that you are displaying stuff on?
In any case, what you are describing sounds like an ad-hoc re-implementation of virtual memory?
> What if you don't know ahead of time how big that monitor is that you are displaying stuff on?
Use a reasonable upper estimate?
> ad-hoc re-implementation of virtual memory?
If you rely on actual virtual memory instead of specially designed file format, saving large files will become prohibitively slow. On each save you have to stream the entire document from page file to actual memory, serialize the document, produce the entire file, then replace. And then when resuming editing after the save, you probably have to load the visible portion back from disk.
Just impose a maximum buffer size ;)
Instead of over specifying a program you can just use dynamic memory allocation
I'd prefer the opposite - borrow checker, but remove the useless "fn" and "let" keywords