-
I think the dependency situation is pretty rough, and very few folks want to admit it. An example I recently stumbled upon: the cargo-watch[0] crate.
At its core its a pretty simple app. I watches for file changes, and re-runs the compiler. The implementation is less than 1000 lines of code. But what happens if I vendor the dependencies? It turns out, the deps add up to almost 4 million lines of Rust code, spread across 8000+ files. For a simple file-watcher.
[0] https://crates.io/crates/cargo-watch
-
CodeRabbit
CodeRabbit: AI Code Reviews for Developers. Revolutionize your code reviews with AI. CodeRabbit offers PR summaries, code walkthroughs, 1-click suggestions, and AST-based analysis. Boost productivity and code quality across all major languages with each PR.
-
The article doesn't go into detail about the unstable features, that's not just a list of features that haven't been released yet. Some are experiments whose result will be "can't or shouldn't be done".
Some are things that will never be stable, because they're not a feature; as an example, https://github.com/rust-lang/rust/issues/90418
-
> Look at the dependency tree for a next
Looks ok to me: https://npmgraph.js.org/?q=next
Ironically, most of the dependencies are actually Rust crates used by swc and turbopack [1]. Try running cargo tree on either of those crates, it's enlightening to say the least. And of course, Node has a built in file watcher, and even the most popular third party package for file watching (Chokidar) has a single dependency [3].
[1] https://github.com/vercel/turborepo/blob/main/Cargo.toml
[2] https://github.com/swc-project/swc/blob/main/Cargo.toml
[3] https://npmgraph.js.org/?q=chokidar
-
Just look at the proposal to add an --only-dependencies flag to cargo-build.
https://github.com/rust-lang/cargo/issues/2644
Its a clusterfuck of people misdirecting the discussion, the maintainers completely missing the point, and in the end its still not even been allowed to start.
-
> Rust doesn't have syntax to mark a struct field as being in a borrowed state.
> ast_nodes: Vec<&'Self::source str>,
Oh, that would be neat to replace the https://github.com/tommie/incrstruct I wrote for two-phase initialization. Unlike Ouroboros and self_cell, it uses traits so the self-references can be recreated after a move. Whether it's a good idea, I don't know, but the magic Ouroboros applies to my struct feels wrong. But I say that as someone coming from C++.
> if let Some(x) = some_var && some_expr { }
Coming from Go, I was surprised that something like
if let Some(x) = some_var; expr(x) { }
-
-
That's what inevitably happens when you make transitive dependencies easy and you have a culture of "if there's a library for it you must use it!"
C/C++ are the only widely used languages without a popular npm-style package manager, and as a result most libraries are self-contained or have minimal, and often optional dependencies. efsw [1] is a 7000 lines (wc -l on the src directory) C++ FS watcher without dependencies.
The single-header libraries that are popular in the game programming space (stb_* [2], cgltf [3], etc) as well as of course Dear ImGui [4] have been some of the most pleasant ones I've ever worked with.
At this point I'm convinced that new package managers forbidding transitive dependencies would be an overall net gain. The biggest issue are large libraries that other ones justifiably depend on - OpenSSL, zlib, HTTP servers/clients, maybe even async runtimes. It's by no means an unsolvable problem, some replacements for transitive dependencies are:
1. Even without transitive dependencies, a library can still hard-depend on zlib, and just force the user to install it manually.
2. a library can provide generic compress/decompress callbacks that the user has to fill out
3. the compress/decompress functionality can be make standard, removing the need for a dependency
[1] https://github.com/SpartanJ/efsw
-
SaaSHub
SaaSHub - Software Alternatives and Reviews. SaaSHub helps you find the best software and product alternatives
-
[2] https://github.com/nothings/stb
-
-
-
inotify-tools
inotify-tools is a C library and a set of command-line programs providing a simple interface to inotify.
Note that entr doesn't recursively watch for file changes. It has a list of files it watches for changes, but this list isn't amended when new files are added. Fundamentally that's a fairly small subset of proper recursive file watching. A more comparable project in terms of just watching files is https://github.com/inotify-tools/inotify-tools.
-
Ah, I should have clarified that. Yes, if stack overflow resulted in a trap you are mostly okay, given that the caller is eventually able to recover from the trap. But imagine that the trap didn't happen because the page table wasn't configured, like in the kernel context. Now your program will venture into some unintended memory region, yikes!
But that was about the general language-based security, and you are correct that this particular case wouldn't matter much for Cargo. I only used this example in order to show that fully verifying language-based security is very hard in general. Even Coq, a well-known proof verifier with a solid type theory and implementation, suffered from some bug that allowed `false` to be proved [1]. It's just not feasible.
[1] https://github.com/clarus/falso
-
-
tokio
A runtime for writing reliable asynchronous applications with Rust. Provides I/O, networking, scheduling, timers, ...
-
-
> Sandboxing against malicious crates is an out-of-scope problem. You can't do this at the language level; you need some combination of a verifier and runtime sandbox. WebAssembly components are a much more likely solution here. But there's lots of interest in having capabilities for other reasons, for things like "what allocator should I use" or "what async runtime should I use" or "can I assume the platform is 64-bit" or similar. And we do want sandboxing of things like proc macros, not because of malice but to allow accurate caching that knows everything the proc macro depends on - with a sandbox, you know (for instance) exactly what files the proc macro read, so you can avoid re-running it if those files haven't changed.
We've had a lot of talk about sandboxing of proc-macros and build scripts. Of course, more declarative macros, delegating `-sys` crate logic to a shared library, and `cfg(version)` / `cfg(accessible)` will remove a lot of the need for user versions of these. However, that all ignores runtime. The more I think about it, the more cackle's "ACLs" [0] seem like the way to go as a way for extensible tracking of operations and auditing their use in your dependency tree, whether through a proc-macro, a build script, or runtime code.
I heard that `cargo-redpen` is developing into a tool to audit calls though I'm imagining something higher level like cackle.
[0]: https://github.com/cackle-rs/cackle
-
Every single JS future is boxed. Moreover, they aren't just boxed, they are often backed by a hashmap (which may or may not be optimised away by the JIT). Elaborate allocation-free async is not an apple-to-apples comparison, that's my point.
JS does support concurrent execution, Promise.all is an example. Without it, JS async would make little sense. The problem very much exists there, and try-catch is only a surface-level answer. As you can see here [1], the interaction of cancellation and async in JS is at least just as (or more) complex than in Rust.
By the way, multithreading has little to do with Pin. I presume you're thinking of Send bounds.
"To work at all" is very dismissive. It's complex, but very well abstracted, well defined, and robust, that complexity is essential. Again, look at [1], JS async is hardly less complex, but also much more vague and ill-defined.
[1]: https://github.com/whatwg/streams/issues/1255
-
turborepo
Discontinued Incremental bundler and build system optimized for JavaScript and TypeScript, written in Rust – including Turborepo and Turbopack. [Moved to: https://github.com/vercel/turbo]
> Look at the dependency tree for a next
Looks ok to me: https://npmgraph.js.org/?q=next
Ironically, most of the dependencies are actually Rust crates used by swc and turbopack [1]. Try running cargo tree on either of those crates, it's enlightening to say the least. And of course, Node has a built in file watcher, and even the most popular third party package for file watching (Chokidar) has a single dependency [3].
[1] https://github.com/vercel/turborepo/blob/main/Cargo.toml
[2] https://github.com/swc-project/swc/blob/main/Cargo.toml
[3] https://npmgraph.js.org/?q=chokidar
-
> Look at the dependency tree for a next
Looks ok to me: https://npmgraph.js.org/?q=next
Ironically, most of the dependencies are actually Rust crates used by swc and turbopack [1]. Try running cargo tree on either of those crates, it's enlightening to say the least. And of course, Node has a built in file watcher, and even the most popular third party package for file watching (Chokidar) has a single dependency [3].
[1] https://github.com/vercel/turborepo/blob/main/Cargo.toml
[2] https://github.com/swc-project/swc/blob/main/Cargo.toml
[3] https://npmgraph.js.org/?q=chokidar
-
I agree wholeheartedly (and I'm not surprised that you of all people often write raw futures!). I want to push back on the "async rust bad/failure/not ready" meme because
- it's perfectly possible to be a successful user of the async ecosystem as it is now while building great software;
- this two-tiered phenomenon is not unique to Rust, JS and Python struggle with it just as much (if not more due to less refined and messier design). As an example, [1] is elegant, but complex, and I'm less sure it's correct compared to a gnarly async Rust future, because the underlying async semantics are in flux.
Of course I'd love for the remaining snags (like AFIT) to go away, and simplified Pin story or better APIs would be great, but this negativity around async Rust is just wrong. It's a massive success already and should be celebrated.
[1]: https://github.com/florimondmanca/aiometer/blob/master/src/a...
-
SaaSHub
SaaSHub - Software Alternatives and Reviews. SaaSHub helps you find the best software and product alternatives