90 comments

[ 2.8 ms ] story [ 139 ms ] thread
All of these choices seem reasonable except letting an ORM be a sticking point.

Is there an institutional issue with SQL knowledge or is it exceedingly complex database?

As someone who finds ORMs more trouble than they're worth I really struggle with that point, particularly if it's SQLite.

And while Go's testing framework is really nice, I've never had much issue doing unit testing in Rust. I'm assuming the problem was more with the testing + the tauri framework than Rust itself.

I feel similarly. I think people just tend to be put off by SQL and the programmer answer of 'just another abstraction' takes over.

It's not good, but it's not bad enough to justify ORM complexity. Then again I've worked in places where no one knew what an index was so maybe they make sense in such environments.

Just wishing there was no mismatch between idiomatic SQL schemas and idiomatic programming data structures (join (join (join ....

Working directly with SQL does feel a bit like peppering your modern codebase with COBOL.

The impedance mismatch comes as a result of needing workarounds for database implementations that exhibit high query latency in order to see the execution finish in a reasonable amount of time. It is not fundamental. You can avoid the mismatch by using a DBMS that provides low-latency queries, like SQLite.
To be clear, and I assume you know this, network connectivity is probably a small part of typical query latency. Large joins, sorts, etc, would tend to dominate. Maybe for huge result sets bandwidth might factor in a again but so would the sorts.
(comment deleted)
ORMs are a tool that can be abused, but eventually you need something that loads data from your database and places it into an in-memory object. Given how repetitive the SQL and mapping code is, why wouldn't you use a tool to automate that, even if you're an SQL expert?
I think there are a lot of database libraries across a lot of languages that let you jam data directly into an object.

The only thing I think (some) ORMs do really well is migration management. But you can also devise your own patterns for this easily enough that it's not worth it.

The SQL and mapping code is very simple. Getting an ORM to generate queries as efficient as hand written SQL requires substantial ORM study, experimentation, and ongoing tweaks. I've seen too many junior programmers write simplistic code that creates a massive number of database queries because they didn't understand how the ORM works. That rarely happens with handcoded SQL because how the code interacts with the database is transparent.
But in most applications only a small subset of queries need to be efficient.
I completely disagree but of course we probably have not worked on the same sorts of applications so we have no common ground.
You can use both though. Keep the ORM for the easy stuff to save yourself the boilerplate, and drop down to raw SQL when needed or when it's easier than figuring out how to do the same with the ORM.
But then you're still having to fully understand the ORM so you're not saving yourself any work.

I'm always amazed at how much I can do in a single SQL query and how much extra code is required to accomplish the same when using an ORM. But then I once wrote a SQL compiler and runtime system so I'm quite adept at SQL.

Specifically in Golang, an issue I encountered writing SQL queries is when you expect the response will contain null fields. Specifically in Go, at least with the stdlib database/sql client, there's a lot of boilerplate code you need to add to make raw queries without an ORM to map to a sql.NullT object (where T is the Golang equivalent type for the column), then check for each row if the sql.NullT object is "valid" and then copy the column values for each row over to a new struct after doing each sequential null check. An ORM might have saved me about 50 lines of code for just this one query that I'm looking at, just in handling null types alone.
IMO the best value of the ORM is not in the object relational mapping part, but in type synchronization between the DB and a client. Thus there's a wave of recent enthusiasm for ORM-lite solutions.
Very much agree with this. I really like how sqlx (on rust) does it. You just write normal SQL queries, and it will check and validate the types against your db. Best of both worlds.
I can't find an equivalent for Go. https://github.com/sqlc-dev/sqlc and https://github.com/sqlc-dev/sqlc look nice, but they are doing codegen, definitely not as sleek as Rust sqlx.

I guess it's a good example of how powerful Rust is. The "magic" that sqlx does at compile time gets really difficult if not impossible to do without macros.

Of course you could create a separate parser/builder, and codegen works as well, but definitely not as convenient and flexible.

Diesel (also in Rust world) has pretty good mappings to SQL.

There are derives involved, of course, so that probably counts as macros.

You've pasted the same link twice, I think
I've found a happy medium, where I use sql-migrate to build the database, and go-jet to generate the table/model structures for use in go, and go-jet's syntax is reasonably close to SQL that it's easy enough for expression.

caveat: I'm an ex-DBA so I'm comfortable with building complex tables, relationships and queries. Less familiar folks might struggle building the tables, relationships, and doing joins, ctes etc.

from my experience working for a globally distributed django shop, orm mapping/type synchronization are both small fry compared to query building

this now 400+ headcount company would not exist if query builders did not exist

The big draw of ORMs is (was?) the idea of database independence which is a fools errand unless you're a vendor pushing some kind of application which needs some kind of relational database.

If working in-house or building something bespoke, an ORM provides negative value. The only possible upside I can think of is that it offers an opportunity to capture databases access events or... no, that's it. In exchange for this dubious capability, ORMs end up sacrificing the full generality of SQL for simple CRUD statements. On top of that, if ORM migrations are in play then database maintenance becomes bifurcated because, like on the CRUD side, ORMs can only provide crippled imitations of DML.

Avoid.

No, the big draw of an ORM is you can map objects to your database relations. That's why it's an object-relation-mapping. When working with Postgres I think of database rows as instances of a class in my app's native language. I think of queries for the table as static methods, queries for rows as instance methods. Going with raw SQL queries means you not only lose good intellisense on query methods as well as composability, but for a non-trivial app you'll end up implementing much of what an ORM will give to you anyway.

It's the power of an ACID RDBMS with the level of integration of DAOs written in whatever language you want.

Maybe we're coming at this from different ends? I've always adopted the position that the database is the source of truth, not the ORM data model. I've always maintained that mirroring the database schema in an ORM data model is an anti pattern. And I don't like exposing tables to client code under any circumstances -- a view for queries is an absolute minimum and for updates I prefer to implement those through stored procs.

There's nothing stopping anyone from writing their own DAO layer with bespoke SQL statements and allowing intellisense to index the API over the top of that.

> There's nothing stopping anyone from writing their own DAO layer with bespoke SQL statements and allowing intellisense to index the API over the top of that.

That sounds like a homebrew ORM. It could end up being better than any out-of-the-box solution. Or you could make a spaghetti code mess. But I’d rather spend my time elsewhere.

In my opinion the bespoke app code is the center of everything. The database is on the periphery and should conform to my needs as a software engineer building a user facing product. I need to live in reality, though, and understand the database accessed through an ORM is a leaky abstraction. But for many common use cases (find by ID, update a field for a row, etc) I can forget that it’s Postgres under the hood.

I know SQL well enough, understand how to craft a decent schema, how to keep the database happy as tables grow in size. But the main job is writing web app code, not operating as a DBA.

I operate on the principle that the center of the app can be determined by finding where most of the bullshit is. For an app where you’ve got some tables and indexes, the database is too idyllic to be the center of bullshit. Your app code probably has 1000x more bugs and spaghetti to it.

I think it’s a false dichotomy that people against ORMs put out that the user of an ORM doesn’t know SQL well enough or sql is better than an ORM.

An ORMs super power is in easily composable queries. Something no easily don’t with SQL strings because of name conflicts and other issues. ORMs provide incredible benefits when it comes to sub queries and IN statements for instance.

ORMs are not a replacement for SQL strings or knowing SQL. Knowing SQL is sometimes a prerequisite for using some advanced features of an ORM to begin with.

Maybe it comes from people using crappy libs or perhaps some people just like something to feel superior about, but I’ll keep using my humble ORM. So many incredible benefits of ORMs and zero restrictions on just using raw SQL with them anyways.

It's more that "composing queries" in SQL is "CREATE VIEW" (and/or stored procedures/functions). It means you need some way to manage views.
The property of composable queries is not unique to (or dare I say even characteristic of) ORMs, which are primarily concerned with mapping between tables or relations (in the relational algebra sense), and in-memory objects.

It's the modelling of SQL as an AST that gives you that composability, and this does not require an ORM; see for instance arel (even though this was later absorbed into Rails' ActiveRecord ORM as an implementation detail...). [0]

[0] https://github.com/brynary/arel

If I’m not mistaken, you’re describing a SQL query builder, not an ORM
ORMs are not an either/or decision. You can use an ORM, save yourself time with the usual repetitive "CRUD", result set mapping, etc. and then drop down to SQL if you require something complex (like reporting.)

On the other hand, I've worked at companies where they built their own barely functional ORM. It was total garbage. The original developer did not understand prepared statements, so you can imagine how well that worked out. We'd regularly hit SQL errors in production because a quoted string came through.

Back in my Java days a long time ago, I too preferred just writing prepared statements and then copying the data to my POJOs. Until I thought about it and decided to use reflection to do the heavy lifting after modifying the code every sprint to deal with new requirements. Then I added the ability for my POJOs to be annotated so I could define the table and columns it belonged to. It didn't hit me until near the end that I had reinvented Hibernate without all of the rest of its features.
(comment deleted)
> It didn't hit me until near the end that I had reinvented Hibernate without all of the rest of its features.

This is pretty much the life cycle of the “ORMs suck” crowd. The hangups are similar to “XML sucks” — conflating a poor ORM framework or XML-based format with the concept of ORMs or XML in general.

ORMs are a very useful abstraction, and even if you think you aren’t using an ORM, you probably are — just a bespoke one.

I wasn't in the "ORMs suck" mindset, but rather I just didn't want to take the time to integrate it since it was "just a small little project for a few people". But as word got around, more people got interested in it and wanted their own fields and data added. It was a case where premature optimizing would have been a good idea.
ORMs manifest when the language doesn't have native query constructs.

C# (LINQ) or F# (Query Expressions) come to mind. Sadly not much else.

ORMs are worth it for `includes` and wrapping up nested objects. SQL support for associations in a result set could use some work.
I feel like the majority of the people who complain about orms, haven't taken the time to learn the orm. Often times, there is a DSL you need to learn, but for simple database relations and joins not using an ORM is a waste of time and resources.

orms are often opinionated and tables that are setup with an ORM may not be compatible with other ORMS. This is the only real downside. If you have a large legacy application that needs to be migrated to a new framework that uses different conventions for index names, table names, ect, then you are in for a bad time.

Django's orm is probably one of the best out there. Django also has orm manager classes you can extend with abstractions around orm functions or raw queries.

For complex queries, like with CTE's, complex joins, recrusive queries, index optimizations, there is no way around custom queries but any good ORM has an api around these raw queries that can hopefully also map to objects in your applications.

I've used a few ORMs. I've even designed a commercial ORM, many years ago.

My personal experience is that the more they try to abstract away raw queries, the least useful they are. YMMV

Java would have been a better option.
Why? Ultimately we're talking about a web app with a thin wrapper desktop client that hopefully has an API between the two.

Does Java have a killer framework for this? Something that builds super fast, creates a small executable that doesn't gobble memory like crazy?

That's what devs in this space care about, not the language (as I think this post indicates).

If they cared they would not use Java, but also not ship a Web application in disguise.
That ship has long sailed. I personally don't care what's underneath the hood if the app works well.
Mostly they don't. Web widgets exist for about 30 years now, while fake desktop apps shipping a browser go back to Windows 95 Active Desktop and Mozzilla's XUL.

Want to do Web, target the browser.

Want to do native, target OS SDKs.

Look for all the complaints about Slack ... it mostly just works for me. And it's one of the heaviest Electron apps out there.
> a small executable that doesn't gobble memory like crazy

Whilst I don't contest about the executable size does really golang gc is more efficient than Java's?

Given the latter has a much more mature platform I would assume their gc would be the best at maximizing memory efficiency, even beating golang.

Java’s GCs are much better than Go’s, but they optimize for throughput over memory usage. Nonetheless, they would probably be more than fine for the job here.

As for executable size, JVM byte code is much more dense than executables.

(comment deleted)
"We decided to use Wails (no link) instead of Tauri (link)." Wails developers: okay...
Under the heading of Type Safety:

Golang and Rust both offer type safety, but Golang is statically typed and uses a garbage collector to manage memory (as mentioned earlier).

Why would they word it that way? Is Rust any less statically typed than Go?

Super weird phrasing, particularly since Rust's type safety is far more sophisticated than Go's.
In my experience the reverse is true. There are points in Go where you resign yourself to passing around interface{}/any, just because generics can't (yet) do everything you might want. In doing so, you revert to dynamic typing again, albeit in specific circumstances.
It happens often. Basically every go project past a certain size.
that's a sign they're doing it wrong ;) Seriously though, I see this a lot with (ex)java programmers
No it's not. It's not java programmers who are wrong, it's you and golang that is wrong. You clearly don't know what you're talking about. I hate smug golang programmers who think they're gods gift to programming because they think they're so good at go when they don't realize how broken go is as a modern language. Honestly it's only the golang programmers who have this attitude.

Golang (and java) by nature has a bad type system that's fundamentally incompatible with popular data structures used in the web.

Json a very popular web data structure cannot be represented properly as a type in golang.

The standard way of dealing with a dynamic json data structure in golang is to resort to interfaces and type assertions or assuming it's some struct. There is a similar problem in java. This isn't some "wrong" thing in go as you wrongly state. It's standard practice. You are suppose to use interfaces for this purpose in go. It's standard and by design. If you haven't then you haven't worked on something sufficiently big enough such that the input parameters include json of an unknown structure. Basically you only worked in web apps where inputs aren't complex like trees which is a valid structure that can be represented in json.

Rust gets around this by something called sum types allowing you to stay type safe without ever resorting to breaking out of the type system when dealing with any json type. Typed python also has sum types which let's you easily get around this problem.

What are you talking about? Even the standard library is littered with `any` and reflection. Look at how JSON serialization works.
Based on the rest of the post, I would expect that's just a typo.
Yeah, that’s just wrong on both accounts. Rust is of course statically typed as well and GC has almost nothing to do with the type system.
I think I might be the only one on the planet that tries to avoid tooling like this that's tied to a subscription. If it's a local app and there aren't any ongoing operating costs, tolerating subscriptions for stuff like this seems insane to me. I'll happily buy an upgrade when HTTP changes versions.

If you were a plumber, would you rent your pipe fitting tools forever just to have the manufacturer frequently changing the way they work to justify the subscription model? The software development industry has gone crazy.

I'll never in my life pay $30 / year for something like this, but I wouldn't hesitate to buy a perpetual license for $150 upfront if it were useful to me.

I have Java projects that are 10+ years old and I can check out the repo, install IntelliJ IDEA v7 (perpetual), install all my other tooling that had perpetual licenses, and have everything "just work". It's so frustrating to try that in modern times where there's no hope in hell a project that's been idle for 5 years is serviceable without a bunch of tweaking due to the rolling release, subscription software everyone's been suckered into using.

The software industry is going backwards IMO.

/rant

> I think I might be the only one on the planet that tries to avoid tooling like this that's tied to a subscription.

It's really unfortunate that things have moved this way, but I'm with you that a desktop client is the thing that feels most alien in this model.

> I think I might be the only one on the planet that tries to avoid tooling like this that's tied to a subscription

I think it depends on the app. If it's something that I use frequently I want a subscription. Otherwise, not. The reason for that, is that I look at subscriptions as something I have to be convinced to continuously pay every month. That gives me a lot of power to just disconnect at a later time, and this means that those apps tend to listen to user feedback more often than other apps.

> If it's something that I use frequently I want a subscription. Otherwise, not. The reason for that, is that I look at subscriptions as something I have to be convinced to continuously pay every month.

I don't agree. I'm fine with the economic idea of a subscription in terms of creating recurring revenue for developers and think a loyalty discount is a good way to convince people to keep paying, especially for tools that are used moderately to frequently. I want the latest and greatest version of the software I depend on and I don't mind paying for it, but I want to be able to stop paying at any moment and have the only downside be a loss of loyalty discount.

On the workflow / risk side, cancelling a subscription is, by design, intended to be punitive. As soon as you stop paying, the vendor revokes access to your tooling and you're workflow is disrupted. The intent is for it to damage your businesses and processes enough that cancelling becomes extremely painful.

Even the Jetbrains model that everyone seems to love is a total sham because cancelling is designed to damage your development process by forcing you to roll back to a year old version of the software.

> I'll never in my life pay $30 / year for something like this, but I wouldn't hesitate to buy a perpetual license for $150 upfront if it were useful to me.

I felt the same way for a long time, but then I realized that I was paying so much to upgrade my “perpetual license” software to the new version every year or 2 that it might as well have been subscription software

I do prefer subscription software that lets me use old versions that were available when my subscription was still active, though. JetBrains is a good example of this.

On the other hand, I now have several old 32-bit x86 Mac programs that I can’t run because the OS moved on. The Windows situation is much better and I have some extremely old engineering tools that still work just fine.

> JetBrains is a good example of this.

JetBrains is an example of a subscription designed to damage your development process if you cancel. Rolling back to a year old IDE isn't reasonable. You should get the current version and all previous versions. Once a version is 5 years old they should release patches that strip out licensing / activation.

> I realized that I was paying so much to upgrade my “perpetual license” software to the new version every year or 2

I have no problem with a subscription in terms of the cost. It's cancellation causing the loss of access to tools that I depend on that's the issue for me. JetBrains is the only subscription I pay for because if a project idles for a year then I'm at least into the territory where I can go back and work on it with the original tooling even if I've cancelled my subscription.

I don't particularly like JetBrains' model, but it's half tolerable. They charge $289, $231, $173 for the 1st, 2nd, 3rd year on personal licenses for all products. IMO, make the 1st year $347 and then $173 after that and give a perpetual license for the current version. Updating every 3rd year and being 2 years out of date by the time you update would only save $100 per year over a 9 year cycle and isn't worth the hassle for anyone that actually uses the software regularly. However, having access to the current version of everything if I suddenly need to cancel tomorrow has a lot of value for me.

(comment deleted)
I've been looking at Rust and Go and I understand their point. Rust is amazing but can be really challenging. It's easy to start building something, then followed by a long period of lots of frustration and wondering if I can ever get it to work, then once it finally works it's usually very solid.

Skill issue for sure, I would love to spend more time learning and practicing, but that's not always great when you need to get stuff done.

In Go it is really easy to just build the things I need, fast enough, safe enough. I expect it's somewhat the reverse of Rust, very productive and easy until it's not, but it will take you quite far! It's maybe more like Python, but with decent types, and a lot faster.

I think both are pretty awesome for different purposes, I would also expect that once you get to a decent level of Rust experience it probably gets a lot more productive, but it takes a while to get there.

Bikeshedding over language selection for a tool ultimately built to support a PHP framework in 2023 is... an interesting irony.
Yeah, I came looking for the comment to say the should have built this in PHP.
I came here to make that comment
I would have loved to see the performance comparison between Rust and Golang for the desktop app. Historically, GC language based desktops (Java,C#,Electron) are laggy, less performant or consume a large amount of memory compared to the native versions (which were often non-GC languages like C/C++/Objective-C etc.). Pretty much the only reason people power through the native versions, even though they are a pain to code, is due to much snappier performance and smaller memory footprint. I would have guessed Rust would have fallen into the native category and it would have been an interesting comparison.
Meh, even the traditionally non-gc languages ones have used reference counting (gobject, Objective-C MRC) or even GC (gcnew C++/CLI)

I admit that STW GC pauses sicken me, so I avoid them on principle.

> Understanding ownership transfer and management can be one of the most confusing and complex aspects of Rust. It is crucial to consider the program's execution flow and manage mutable and immutable variables in memory to avoid getting lost in the code. Mastering this, along with working with threads, was one of the most time-consuming tasks for the team.

I want to add that "ownership" isn't new. When working with systems languages without a GC, ownership was always there, you just kept track of it mentally, rust may be the first to make you aware of it by enforcing it at the compiler level, essentially making you aware that you are doing something stupid.

Adopting rust's ownership model was truly "zero cost" coming from a C/C++ background as we were already doing it.

We were doing it so well that we had to come up with memory safe languages :-)
Precisely true, but from a PHP background, I assume there's not much to prepare you for this.
What a harsh choice of colors to use, my eyes hurt after a few seconds of trying to read it
If you're developing a gui app in Go and trying to minimize dependencies, I found Gio in particular to be great. It linked to barely anything when I tried it a while back.
I have been watching a Twitch streamer Tsoding for a while now. Recently he ported a very simple chat client (like a hello, world! chat app) from Go to Rust [1]. Some impressions I have:

* I was surprised how naturally and easily porting the Go code to Rust was. I have been writing Go and I have been happy with it (to my surprise actually). And I have a stereotype in my head that Rust is more cumbersome. But in some cases, the Rust code was much more ergonomic than the Go code.

* Rust appears to be a quagmire of TIMTOWTDI (There Is More Than One Way To Do It). Just looking at the Rust docs for the standard library is a bit stress inducing. In some way Rust reminds me of the old Perl hacker culture which many love but I did not. When I first read the zen of Python stuff, and the idea that there should be one obvious way to do things I knew where my own heart lay.

* Rust is like the Dark Souls of programming. In the linked video there is a moment where the creator is audibly relieved. He did some mutable borrowing stuff across threads and he was deep in a rabbit hole of making the compiler happy. Finally he got it all to compile but he admits he wondered if he was going to find a dead-end. But there is something addictive about that kind of stress - I know it myself. You feel like you accomplished something when you come out the other side. It is some kind of dopamine inducing validation of your ability as a programmer. I think this is a very negative trait in the context of tools used to complete work.

* After implementing large blocks of functionality and getting the code to compile, it "just worked" as Rust programmers like to brag about.

My impression is still that Rust is over engineered. I have a lot of reasons to feel that way, but a recent one is a video from the CopenhagenRustCommunity where Jon Gjengset did a presentation on using `impl` traits in place of generics. It really feels to me that the ergonomics that I praised in my first point are a deal with the devil. I get the impression that maintaining this facade of "easy" is creating some demons under the covers. And things like `impl` trait and some of the decisions around it are layering on top to try to hide those demons. I don't want to call out this feature too hard since I'm just a tourist here and real Rust guys will probably have more useful opinions on it. But whenever I dig deep into Rust you end up with things like "Pin" or whatever and the guys behind it are almost apologetic. They recognize these are weird annoying things but in some sense earlier decisions are forcing them to do the best they can.

All that being said, I'm probably going to finally give Rust a decent try. I've been writing a small personal project in C and I think porting it to Rust is worth the time.

1. https://www.youtube.com/watch?v=BbIEuNscn_E&ab_channel=Tsodi...

2. https://www.youtube.com/watch?v=CWiz_RtA1Hw&t=2234s&ab_chann...

The best advice I can give is: go for it, and if you get stuck or feel like something in Rust is more difficult than it should be, reach out for help. Once in a while you may really be hitting an unpolished piece of the language, but in most cases I find that expert advice can clear up a lot of pain and make things much more ergonomic across the board. Having the proper types and lifetimes at API boundaries, for example, can make a big difference, and folks new to Rust don't often have the right intuition for some of that stuff.
Rust makes tradeoffs explicit, which means you often have to make decisions you don’t have to worry about in other languages. I suspect this is where your perception of its being over-engineered may be coming from.

Traits are mostly well-trodden ground, being rather like typeclasses in Haskell. The ability to use them for both generic bounds and dynamic dispatch is lovely, but a source of confusion if you’re new to the language.

In my experience lifetime management is the biggest hurdle when you’re getting started. I’ll admit that five years into learning rust, with half of that working with it professionally, I still sometimes get lifetime errors that I don’t understand. However, I have gotten much better at them over time (name your lifetimes well! it’s a lot more helpful for understanding for a lifetime to be named ‘frobnicator than ‘a, IMO).

Anyway, only thing for it is to give it a shot! The feeling of easy performance wins and strong type safety is hard to give up once you’re used to it.

> I still sometimes get lifetime errors that I don’t understand.

I'd like to remind people that errors you don't understand are bugs and I'd encourage you all to file a ticket when encountering any: https://github.com/rust-lang/rust/issues/new?assignees=&labe...

Thanks, esteban! I’ll try to keep this in mind. It happens much less often these days, and it’s always hard to disambiguate my own ignorance from the quality of the error message :)
I think you missed the point of Jon's talk, it was in large to highlight some deficiencies that currently exist in the language but are actively being worked on.

As he mentioned the current situation with return position impl trait + 'a was surprising even to some of the core rustc developers so it's not like they intended for it to be like that.

A few remarks.

> You feel like you accomplished something when you come out the other side. It is some kind of dopamine inducing validation of your ability as a programmer. I think this is a very negative trait in the context of tools used to complete work.

It is an interesting point. I have regularly claimed that you need to be heroic to program applications with weakly or dynamically-typed languages, because regularly, everything is going to come crashing down on you, and you will need large doses of heroism to debug through stuff that a strongly, statically typed language would have caught earlier.

Reading what you write makes sense, though, because it is true that you sometimes need to sacrifice live chicken to the compiler gods. So it could very well be that you are trading late heroism for earlier heroism.

> My impression is still that Rust is over engineered. [...]

Having worked on a few compilers and SpiderMonkey, I believe that I can tell you that most, if not all, languages are over engineered. Rust likes making choices explicit, while Go, Python or JavaScript try harder (with various levels of success) to hide this over engineering into the runtime.

That being said, yes, the Rust team has made a few choices they're not happy with and is trying to harmonize back the language.

Golang's compile times << Rust's compile times
I can't wait for the next entry of their blog: "Why we moved from golang to Rust"
Very interesting, will have to take note about this and be inspired to use the same tech stack.
Those build times are sus. These days I find Rust cold builds to be marginally slower than Go, but everything else is even.