6 ms·
I really like Rust but there are some quite frustrating core paper cuts that I wish would get more attention: 1. Self-referencing structs. Especially where you
by IshKebab 1y ago
I really like Rust but there are some quite frustrating core paper cuts that I wish would get more attention:
1. Self-referencing structs. Especially where you want to have something like a source file and the parsed AST in the same struct. You can't easily do that at the moment. It would be nice if there was something like an offset reference that made it work. Or something else...
2. The orphan rule. I get it, but it's still annoying. We can do better than newtype wrappers (which sometimes have to be nested 2 or 3 levels deep!).
3. The fact that for reasonable compile time you need to split projects into lots of small crates. Again, I understand the reasons, but the result sucks and we can definitely do better. As I understand it this is because crates are compiled as one compilation unit, and they have to be because circular dependencies are allowed. While that is true, I expect most code doesn't actually have circular dependencies so why not make those opt-in? Or even automatically split items/files within a crate into separate compilation units based on the dependency graph?
There's probably more; this is just what I can remember off the top of my head.
Hopefully that's constructive criticism. Rust is still my favourite programming language by far.
- selfmodruntime 1y agoHuge agree with the orphan rule. We should be able to disable this in application crates, or do away with it when we can prove certain hygiene, like proc macros.
- nicoburns 1y agoTotally agree with 1 and 2. Would add 4: partial self borrows (ability for methods to only part of their struct). For 3, I think the low hanging fruit is probably better support for just using multiple crates (support for publishing them as one package for example).
- Ygg2 1y agoWeakening the orphan rule would probably wreck too many crates. It's one of those changes that sounds great on paper but is a nightmare in practice.
- SkiFire13 1y ago> The orphan rule. I get it, but it's still annoying. We can do better than newtype wrappers By that do you mean that there are better alternatives that Rust could adopt or that we need such alternatives (but they could not exist)?
- estebank 1y agoOne option would be to ignore the orphan rule withing workspaces.
- kibwen 1y agoOr let them be ignored within the root crate when building a binary, since the main concern with orphans is that libraries deep in your dependency tree become accidentally incompatible, which isn't a problem if orphans arise in the root of a binary crate, since by definition you control its source.
- SkiFire13 1y agoI know it sounds simple, but AFAIK it's not actually so easy to implement, see e.g. https://internals.rust-lang.org/t/allow-disabling-orphan-rules-for-applications/22172/4 https://internals.rust-lang.org/t/allow-disabling-orphan-rul...
- kibwen 1y ago> As I understand it this is because crates are compiled as one compilation unit, and they have to be because circular dependencies are allowed Rust allows circular dependencies between modules within a single compilation unit, but crates can't be circular dependencies. > I expect most code doesn't actually have circular dependencies Not true, most code does have benign circular dependencies, though it's not common to realize this. For example, consider any module that contains a `test` submodule, that's a circular dependency, because the `test` submodule imports items from the parent (it has to, because it wants to test them), but also the parent can refer to the submodule, because that's how modules and submodules fundamentally work. To eliminate the circular dependency you would need to have all test functions within every compilation unit defined within the root of the crate (not in a submodule off of the root; literally defined in the root namespace itself).
- IshKebab 1y ago> Rust allows circular dependencies between modules within a single compilation unit, but crates can't be circular dependencies. Yes, that's what I was saying. > that's a circular dependency, because the `test` submodule imports items from the parent This isn't a circular dependency because the parent doesn't import anything from the test module. It would mean your compilation unit might have to be a subset of a module, but I think that's fine?
- kibwen 1y agoGenerally the way that you would implement a restriction against circular dependencies is to prevent children from importing from their parents, full stop. The more elaborate analysis that you propose would work, technically, but it would only work for tests (if items can't be reached from the crate root, that's another way of saying that the code in question is dead and unreachable; tests only get around this because the test runner is a weird alternative entry point). You'd still be unable to, for example, have a submodule that defines a trait, and then a sibling submodule that defines a type that imports that trait; you'd need to move either the trait or the type to a shared root. To illustrate, this means that anything in the stdlib that implements std::iter::Iterator would need to be defined in a submodule of std::iter (or vice versa). And then repeat that process for every other trait: std::convert::From, std::ops::Drop, std::io::Read...