> The fact that it knows to look for lib.rs or main.rs in src and then recursively find all my other modules without me needing to specify targets or anything like that is a killer feature on its own IMO.
In the interest of pedantry, locating source files relative to the crate root is a language-level Rust feature, not something specific to Cargo. You can pass any single Rust source file directly to rustc (bypassing Cargo altogether) and it will treat it as a crate root and locate additional files as needed based on the normal lookup rules.
Interesting, I didn't realize this! I know that a "crate" is specifically the unit of compilation for rustc, but I assumed there was some magic in cargo that glued the modules together into a single AST rather than it being in rustc itself.
That being said, I'd argue that the fact that this happens so transparently that people don't really need to know this to use Cargo correctly is somewhat the point I was making. Compared to something like cmake, the amount of effort to use it is at least an order of magnitude lower.
The module system in Rust is incredibly confusing for a beginner.
The standard module in Rust is basically a Rust source file (<module_name>.rs) with the name of the module or a directory <module_name> with a mod.rs file inside (<module_name>/mod.rs). However, that alone doesn't make it a module. The root source file (lib.rs or main.rs) must declare that <module_name>.rs is actually a module in the preamble via mod <module_name>;
Thus it works "backwards" in comparison to C style #include. mod doesn't include a module into the current file/module, it includes the module into the current project directory tree, which means you will never need a second mod <module_name>.rs declaration again.
I wouldn't exactly say that the way C/C++ headers work is particularly intuitive for beginners either; having spent several years as a TA in a course in college where students were writing C for the first time (after having used mostly Java beforehand), I've seen plenty of times where students have trouble figuring out how to properly split things between headers and "regular" source files, have trouble figuring out how to properly specify which sources to link together in their makefiles, and have to learn how to either avoid accidentally including the same thing twice transitively or use one of the various workarounds that mitigates it.
You might argue that all of these are solvable problems, but I'd argue that learning how to properly declare a module in Rust is overall a lot simpler than learning how to deal with all of the analogous problems in C/C++. For people who have never used C/C++ or Rust before, you could just as easily say that they work backwards in comparison to Rust, and in a vaccuum, I think the way Rust does it would be far more intuitive to someone who had familiarity with neither and were presented both at the same time.
As a thought experiment: if you had a group of people who didn't know either Rust or C/C++, and you split them in half, and taught half of them Rust first and C second and did the reverse for the other half, how many of the people in each group would you expect to consider the configuration of Rust builds to be more confusing than the configuration of C builds? I'd be willing to bet that you'd have a far more people in the group that you taught C first who considered Rust builds to be more intuitive than people in the other group who thought that C builds were more intuitive, and that it would be strong evidence that the build system for Rust is overall much easier to understand.
In the interest of pedantry, locating source files relative to the crate root is a language-level Rust feature, not something specific to Cargo. You can pass any single Rust source file directly to rustc (bypassing Cargo altogether) and it will treat it as a crate root and locate additional files as needed based on the normal lookup rules.