Rust 1.100

(blog.rust-lang.org)

814 points | by mbStavola 22 hours ago

41 comments

  • nirinor 22 hours ago
    Woohoo, that's a release! My personal favorites:

    - Stabilize never type

    - Stabilize custom allocators

    - Introduced minimum publish age configurations, also known as dependency cooldowns. When the relevant config is set, the resolver ignores versions published more recently than that, unless they are already in Cargo.lock. (RFC 3923) docs #17335

    - cargo-install: now uses the existing lockfile in the .crate tarball by default. --locked in cargo install becomes a no-op. #17388

    • nixpulvis 19 hours ago
      > cargo-install: now uses the existing lockfile in the .crate tarball by default. --locked in cargo install becomes a no-op. #17388

      Long time follower of this. Very grateful it's been implemented.

    • SOLAR_FIELDS 15 hours ago
      Dependency cooldowns receiving such a whiplash this year. Earlier everyone was advocating for them because of the supply chain attacks. Now, people are worried because you might miss 0 days if you use them.

      Nonetheless, the ability to set and configure it is a welcome feature.

      • woodruffw 14 hours ago
        You should do both: you should let normal updates cool down, and you should immediately patch security advisories.

        One of the biggest ergonomic problems with cooldowns is that many tools let the former goal obstruct the latter. Both should be part of the state machine of resolution itself, rather than things that get layered on.

        • kragen 4 hours ago
          Usually people advocate dependency cooldowns as a mitigation for supply-chain attacks, where you're depending on a module with a malicious maintainer, possibly a new one (perhaps one who stole the old maintainer's keys so they can pretend to be the old maintainer).

          In that situation, how do you distinguish between "normal updates" (that you should let cool down) and "security advisories"? If all the hypothetical malicious maintainer has to do to get you to update is to publish a security advisory for their own package, wouldn't they just do that? It might even be a real advisory about a real security hole that they introduced, but claiming more versions are affected than actually are affected.

          • woodruffw 3 hours ago
            It takes additional permissions, in general, to issue an advisory. And “supply chain” attacks in general tend to be used by smash-and-grab attackers, who don’t have time on their side. It’s not like a browser 0day where the attacker’s goal is to preserve their underlying exploit primitive for as long as possible.
            • kragen 1 hour ago
              Additional permissions?
        • jmvoodoo 4 hours ago
          Waiting for someone to hold back a vulnerability until they can compromise a package, then release vuln publicly for maximum impact.

          It’s only a matter of time.

        • ninkendo 4 hours ago
          How do you separate security advisories from regular updates? (If it’s just a box you check, it only means attackers will say “this is a security update” on the malicious package they upload.)

          The point of cooldowns is for when a crate author’s account is compromised and used to publish malicious code. Saying “security advisories bypass cooldowns” wouldn’t really help anything there.

          • woodruffw 3 hours ago
            > If it’s just a box you check, it only means attackers will say “this is a security update” on the malicious package they upload.

            It generally requires additional permissions, per the adjacent respond. And it introduces additional scrutiny on the release, which is the last thing an opportunistic attacker wants (the entire reason “supply chain” attacks are effective is because nobody gives any thought to upgrading their dependencies in the normal case).

        • PaoloBarbolini 9 hours ago
          There are many cases in which security advisories aren't published. But I guess an alternative could be to update using the cooldown, and then diff the dependencies that would get a newer version if the cooldown wasn't in place to check if they contain anything relevant for the particular application you're developing.
      • dns_snek 7 hours ago
        I haven't seen anyone advocate against cooldowns because those are completely different problems.

        How would removing cooldowns help you patch vulnerabilities? That would imply that your CI is configured to update dependencies, rebuild, and push them to production without human oversight?

        That's obviously not the way to go, you must have human oversight and if you do then your humans should be alerted when one of your dependencies patches a security issue. At that point you review it, override the cooldown, and push it to production.

      • zarzavat 13 hours ago
        You should use a cooldown. The effects of a supply chain attack are significantly worse than the effects of a 0 day. You can always make exceptions on a case-by-case basis.
      • saghm 14 hours ago
        Some of us were saying they didn't understand the endgame of everyone using cooldowns at the time. We mostly got told we were wrong though.
  • n_u 21 hours ago
    > Cargo now reports unused dependencies to users, e.g.

    > warning: unused dependency `tracing-subscriber` --> Cargo.toml:23:1 | 23 | tracing-subscriber.workspace = true | ^^^^^^^^^^^^^^^^^^ | = note: `cargo::unused_dependencies` is set to `warn` by default help: consider removing the dependency on `tracing-subscriber`

    Heck yes

    • minimaxir 20 hours ago
      I updated to 1.100 during a Claude session and it complained about new warnings, so I told it to fix them. It removed a large number of unused dependencies without issue.
      • saghm 14 hours ago
        My semi-controversial take is that the best way to use agents for Rust is to literally turn every possible lint and warning on in clippy and require that they're treated as blocking for the agent to fix before ever saying things are done. While a few of them might be overzealous and feel tedious to work around manually, there's no need to care about it being tedious for an agent!
        • skavi 8 hours ago
          clippy lints are not universally good advice. just off the dome, there are a few reasons you’d want to avoid boxing large variants.

          and with the pedantic set enabled, you quickly have bad clippy advice forcing a bunch of ugly expects in your code.

          the default set plus a selection of whatever you like from the rest works better.

      • minimaxir 14 hours ago
        I am legitimately confused why my parent comment is being mass downvoted: the point I was making is that this is change is more a perk for agent use with Rust since agents typically will resolve warnings by solving the issue (and therefore proactively remove redundant dependencies)
        • nightpool 9 hours ago
          I think most people (rightly or not) feel pretty negatively about the concept of a project having hundreds of unused dependencies. If you've lost track of your codebase to such an extent as that, you should probably expect a little bit of social pushback from people who pride themselves on understanding their code and being responsible for it. It's just a fundamentally different and in some ways upsetting mindset to the average programmer.
        • psnehanshu 9 hours ago
          How do you guys know when your comment is downvoted? I seem to be missing something in Hacker News.
          • steveklabnik 31 minutes ago
            Comments that go below one karma are made an increasingly light shade of grey.
          • dns_snek 7 hours ago
            You can see the number of points for your own comment right next to it. They start out at 1.
          • nexawave-ai 8 hours ago
            You must have a certain amount of Karma, then you'll be able to downvote comments. I dont know what that amount is though, I'm on 50 karma points and I dont have that feature enabled
            • latexr 5 hours ago
              > You must have a certain amount of Karma, then you'll be able to downvote comments

              That’s not what they’re asking, they want to know how people know their own comments were downvoted. The answer is that you can look at your own points in your own comments.

              > I dont know what that amount is though

              501.

        • MindSpunk 13 hours ago
          Confuses me too. Maybe they just stopped reading after the first sentence and assumed you were complaining about new warnings?
        • yuriks 13 hours ago
          fwiw my immediate reaction (I didn't downvote) to your comment was "no one asked".
          • minimaxir 13 hours ago
            My intent was to share a fun anecdote of an practical, unexpected impact of the change but I now see that agents + fun is still a tough sell on HN.
            • epage 12 hours ago
              I shared your anecdote with another Cargo team member who helped work on this feature. We appreciate seeing how what we made helped people!
    • jtwaleson 20 hours ago
      Does this remove the need for machete or shear?
      • epage 19 hours ago
        I believe so. The maintaner of cargo-udeps did most of the work as an effort to upstream it.

        The main limitation is in dev-dep detection since there isn't a way to exhaustively run everything that uses dev-deps yet. You can look at logging statements to get an approximation though.

  • ammar_az 21 hours ago
    This release is so big that multiple useful stabilized API aren't event mentioned in the blog post like:

    - bool::toggle() https://doc.rust-lang.org/stable/std/primitive.bool.html#met...

    - Box::map() https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#m...

    - str::trim_prefix(), str::trim_suffix, Path::trim_prefix()

    • nialv7 1 hour ago
      Box::map is cool, there are a bunch of crates filling this gap, guess I can ditch those now.
    • jacksontheel 18 hours ago
      I'm at a loss with the bool toggle method. Why would x = !x not be good enough?
      • stusmall 18 hours ago
        You can. Something like toggle is nice because it is very clear at a glance. That's a subjective style call.

        But under the hood it's all the same https://doc.rust-lang.org/stable/src/core/bool.rs.html#157-1...

        • brabel 9 hours ago
          My first thought was that this is useful when you need a lambda that does this, now you can use ::toggle
          • SkiFire13 4 hours ago
            You could do `bool::not` before, but this is clearer and doesn't require imports.
          • masklinn 6 hours ago
            Now I just need the integer types to gain in-place inc() and dec()

            I don’t know how to feel about toggle returning neither old nor new value tho.

        • rauli_ 18 hours ago
          For someone who has decades of experience from other programming languages this does not look clear to me at all but rather confusing. Calling an method can change value of variable of primitive type?
          • ninkendo 17 hours ago
            There’s nothing special about primitives, they’re just types like any other. A method taking `&mut self` can always modify self, on any type. But you can only call such methods if the value is mutable to begin with, so it’s not really that interesting.

            It’s only weird if you come from languages like Java where “primitives” are distinct from “objects”, which is a self-imposed limitation the language imposes.

            • Groxx 17 hours ago
              Or Go (also treats primitives rather specially) or roughly any language without extension methods (because primitives are at a minimum a pre-defined type). Which is quite a lot of languages really.

              Otherwise agreed, methods like this can be mutable in any language that doesn't heavily specialize primitives.

              • pjmlp 10 hours ago
                Eiffel or Smalltalk are two languages, among others I could chose from, where primitives and others types are differently implemented, yet unless you dive into the nitty gritty details, they look exactly the same to the developer as the compiler handles them exactly the same, and there are no extension methods to be seen.
                • kragen 4 hours ago
                  However, it would be impossible to implement a #toggle method in Smalltalk that behaves like this, because you're calling it on the singleton True (or False) object; Smalltalk local variables, like Lisp variables, are references to objects rather than objects themselves.

                  (You obviously know this, but it might be a surprise to many people reading this thread.)

                  • pjmlp 3 hours ago
                    Yes, but that is orthogonal how primitives and reference types get exposed to the developer.

                    Something like toggle is also impossible in languages that favour immutability and forward progress requires creating new variables, like several functional and logic languages.

          • stusmall 16 hours ago
            The big clue that'll jump out to any rust dev is the type signature:

            pub const fn toggle(&mut self)

            The "&mut" says that toggle takes a mutable reference to the instance it is called off of. This is also called a mutable borrow. You might think that would get buried in the program because you don't always check the type signature of every method you call, but there are a few reasons that muts really jump out in rust. The languages immutable by default nature is one and the other is that several IDE have features to specifically draw attention to mutable instances/references. It's a fairly common pattern in rust to have helper methods on a type that take a mutable reference or ownership of self.

            TL;DR: Rust's ownership model is very unique. Once it clicks its the cat's pajamas, but experience in other languages don't map well to this part of the language.

          • torginus 2 hours ago
            I think a major issue in all OOP languages is determining which operation mutates and which does not, and often having both operations, or even worse, if there's a third, static method. This is redundant and creates opportunity for code style divergence.

            An example would be having both `Vector3.Add` and `Vector3.AddToSelf` instance methods as well as third `Vector3::Add` which takes two Vector3s.

          • rtpg 16 hours ago
            C++ lets you do this kind of stuff as well.

            Primitive types and composite types having the same capabilities is a bit of a value statement for C++ and Rust IMO, and it's missing in a lot of languages downstream (IMO) of the "every variable is a reference to a slot/pointer" philosophy taken by most every managed language

            • tialaramex 14 hours ago
              C++ doesn't have methods/ "member functions" on the primitive types.

              One reason is that C++ doesn't know where to put them, for user defined class, struct or union types these "member functions" as their name suggests live inside the class/ struct/ union definition but for a primitive where would these live?

              In Rust they're just impl blocks, for example the method we're discussing here is:

                  impl bool {    
                      pub const fn toggle(&mut self) {
                          *self = !*self;
                      }
                  }
              • pjmlp 10 hours ago
                Only because Unified Call Syntax is yet to land into the language, after several failed attempts.
                • aw1621107 10 hours ago
                  And I think there's a decent chance that it never will, at least in the form it has been proposed in in the past (i.e., member function syntax being effectively turned into free function calls). P3027 "UFCS is a breaking change, of the absolutely worst kind" [0] argues quite strongly that that particular form of UFCS is basically completely broken.

                  [0]: https://isocpp.org/files/papers/P3027R0.html

                  • pjmlp 9 hours ago
                    As WG21 goes, it is a matter of advocacy, persistency, and getting the required votes in the room, at least if the process doesn't change even with how C++26 contracts turned out to be.
                    • aw1621107 8 hours ago
                      I mean, sure, but that's basically a tautology since that's how everything made it into the standard into the first place. Those are necessary but not sufficient conditions.
                      • tialaramex 7 hours ago
                        I'm with you on this and would point at std::hive as an example of the results.
                      • pjmlp 7 hours ago
                        Not really, in first place it was basically CFront 2.0, alongside C++ARM akin to the K&R C book, with last minute addition of HP STL implementation.

                        The only piece that wasn't really available and was made in a waterfall design approach was export templates, with the known outcome that no one other than EDG has even bothered implementing it.

                        Post C++98 is when we got into the "advocacy, persistency, and votes" strategy.

          • zdimension 17 hours ago
            When you call a method on something in Rust, the method gets passed that something (as a parameter called self). But the method gets to choose whether it's by move/copy or by reference. Here, toggle gets the bool passed by mutable reference.

            In effect, if x is a bool, doing x.toggle() is rewritten by the compiler as bool::toggle(&mut x), which can of course modify x.

          • saghm 14 hours ago
            Not quite; the method uses `&mut self`, so it actually operates on a mutable reference to the value that happens to be a primitive. If you declare a boolean without specifying the binding as mutable, you'd get a compiler error from trying to call this method. Moreover, if anything else had a reference to it at the same time, it would also cause a compiler error to call this method.

            This is definitely something that Rust does a bit different than most other languages, but it's not anything specific to this method, booleans, or particularly new to the language. Most people will learn about the common different ways of defining a method (via ownership, shared reference, or mutable reference) fairly early on in programming Rust.

          • crabmusket 15 hours ago
            I guess you're experiencing the feeling a mathematician gets when seeing a line like

            x = x + 1

          • scott_w 17 hours ago
            Why wouldn’t it be possible? The distinction in modern languages between primitive and not is an arbitrary one when it comes to stuff like this.
          • jason_oster 14 hours ago
            Think of having the method for AtomicBool, where you are forced to call methods for all value accesses. `atomic_bool.toggle(Ordering::SeqCst)` would read much better than `atomic_bool.fetch_xor(true, Ordering::SeqCst)`.
          • nicoburns 14 hours ago
            What may be surprising to you coming from other languages, is that primitive types in Rust have their own methods! So methods applying to primitives is not unusual at all in Rust.
          • throwaway2037 16 hours ago

                > decades of experience from other programming languages
            
            What languages?
            • adastra22 14 hours ago
              Most (not all) static & ahead-of-time compiled languages. C++ and Java come to mind. Method calls on built-in primitive types is more of a dynamic language thing (think: ruby, python) that got extended into compiled languages in recent memory.
          • worik 15 hours ago
            > Calling an method can change value of variable of primitive type?

            So long as the variable is mutable it's value can be changed

          • kibwen 16 hours ago
            In addition to what the sibling commenters have written, in order for this to compile, the variable would need to be declared as mutable.
        • dxxvi 16 hours ago
          Is x = !x faster than x.toggle() because from my naked eyes no function is called? Or does the compiler know that the function toggle should be replace with `!=`? If the compiler does know that, how is that knowledge implemented? Is there a table of special functions that should be replaced with something else? Or some more clever way?
          • tialaramex 14 hours ago
            Thanks to Matt Godbolt, we can ask Compiler Explorer!

            https://rust.godbolt.org/z/dPn3Y4r59

            The optimizer gives the exact same machine code for both functions, and so it just outputs a single function and gives it an alias.

            The compiler has a technique called "inlining" https://en.wikipedia.org/wiki/Inline_expansion

            The LLVM backend used by Rust is jokingly said to have a inlining heuristic of "yes" ie it will always try to inline everything because that's usually faster.

            • xiej 14 hours ago
              Unfortunately it's not inlined in debug/no optimization mode so that's rough.
              • saghm 14 hours ago
                I'll go out on a limb and hypothesize that there are going to be much larger difference between debug and release mode for any non-trivial code that the overhead of `toggle` in debug mode will quite literally never end up mattering to anyone in practice.
              • lanyard-textile 8 hours ago
                Why should it be? That's a feature of debug.
          • lern_too_spel 16 hours ago
            • kibwen 3 hours ago
              In this case the inline attribute probably isn't strictly necessary, because rustc heuristically inlines any functions that it deems trivial enough.
      • saghm 14 hours ago
        If you're dealing with something like an `Option<bool>` or `Vec<bool>`, it might be nice to avoid needing to do a more verbose dereference and assign:

            let mut vec = vec![false, false, false, false];
            vec[2].toggle();
            *vec[2] = !vec[2];
        
        "Good enough" is subjective, but I personally prefer the new way
      • viktorcode 7 hours ago
        When a similar thing was introduced to Swift it too raised a lot of heated discussions. Somehow, people became extremely passionate about this little extension.

        Fast forward to today. After years of using it I find it very good for readability. It became the default in codebases. Nobody complains anymore and absolutely no one is confused.

      • IshKebab 18 hours ago
        If you access the bool through a long path maybe.

          foo.bar().baz[expensive()].qux.toggle();
        • jacksontheel 18 hours ago
          Alright, I'm convinced, that makes a lot of sense.
          • Sharlin 9 hours ago
            You can of course also do

              long_path_bool ^= true;
            
            but that’s less obvious.
        • crabmusket 14 hours ago
          This gives me the same feeling as when I saw Rust's map Entry API

          https://doc.rust-lang.org/std/collections/hash_map/enum.Entr...

              let mut map: HashMap<&str, u32> = HashMap::new();
              map.entry("poneyland").or_insert(3);
              assert_eq!(map["poneyland"], 3);
          
          It's very ergonomic.
        • voxelghost 8 hours ago
          cant you just do

              foo.bar().baz[expensive()].qux ^= true;
          • IshKebab 8 hours ago
            Sure, but should you?
        • ammar_az 18 hours ago
          That's the main reason for me as well
      • thayne 14 hours ago
        If you have a (&mut) reference it would actually be x = !x. Also toggle is a function that can be passed to higher order functions without needing a lambda. For example, if you have a boolean in an option you can do opt.iter_mut().for_each(book::toggle). Or similar if you had a collection of booleans.
      • pasteleft 13 hours ago
        I think they made it to reduce closure usage.

          vec.map(|x| !x);
        
          vec.map(bool::toggle);
        • adwn 9 hours ago
          No, these aren't equivalent: the second line mutates the iterated-over values, while the first doesn't. And the first line returns an iterator over bool, while the second returns an iterator over ().
      • kibwen 18 hours ago
        Proposal here: https://github.com/rust-lang/libs-team/issues/820

        Looks like part of the motivation was for things with long names like `some_struct_a.some_field_b.some_subfield_c`, where needing to name the field twice would have pushed people to using `^= true` instead, which is a bit more roundabout to decipher and risks people forgetting the idiom and writing `^= false` by accident. Not necessarily the most useful API, but not unmotivated and harmless to add.

        • ammar_az 18 hours ago
          I think `toggle()` is also much better for readability as `^=true`
    • afdbcreid 21 hours ago
      They are mentioned in the blog post, under "Stabilized APIs".
    • pasteleft 13 hours ago
      Wow even slices support trim_prefix and trim_suffix
  • ashvardanian 22 minutes ago
    This is by far my most long-awaited Rust release! The kind of “memory safety” I fight with most in Systems Programming isn’t use-after-free, but keeping things running under memory starvation. Having standard containers abort on allocation failure always seemed wrong to me, especially in an ecosystem that got so many other things right!

    Huge thanks to everyone making this happen! I’ve only been on the consuming end so far, but hopefully I’ll find something useful to contribute myself. Pointer provenance might be a nice next challenge :)

  • jadbox 20 hours ago
    Is the compiler any faster now? Compiling takes forever. I'm also tired of always having to do "cargo clean" everyday to clear out 90gb of temp files.
    • epage 20 hours ago
      Faster compile and smaller build-dir can be at odds with each other.

      That said, this release includes some incremental improvements as well as the unused-dependency lint to help reduce wasted work within the ecosystem.

      Some changes that have been or are about to be merged for upcoming releases

      - We will be reducing the debug info generated for the `dev` profile which reduces build-dir size and speeds up builds. We've split off a `debug` profile for when that is needed.

      - Cargo will be deleting the directory rustc writes before each invocation, avoiding the leaking of debug files when split-debug is enabled (default on Mac)

      - rlibs for workspace members will no longer be copied from build-dir to target-dir which takes up extra space on systems without hardlinking or where we skip it (like Mac)

      - redundant information in rlibs and rmeta's is going to be de-duplicated

      Examples of further out changes

      - This release includes the foundational work to add a build-dir GC

      - Cross-workspace de-duplicating of build-dirs

      - Cross-workspace build-dir cache

      - Early cut off

      • iknowstuff 19 hours ago
        Also

        “Relink, don't rebuild” #790

        https://github.com/rust-lang/compiler-team/issues/790

        • epage 16 hours ago
          Note that this is a special form of early cut off (which was listed) where you are hashing a more specialized output file, rather than a broader one.
        • mohamedkoubaa 18 hours ago
          Ive always wondered why this wasn't an option from the beginning
          • epage 16 hours ago
            To do it right you need

            - stable id's even when the source changes

            - a separate output file dedicated to it so you hash that

            Those aren't free, taking extra work to implement and possibly slow down the compiler

      • pjmlp 19 hours ago
        Thanks for the list, looking forward to those improvements.
    • steveklabnik 20 hours ago
      Compiler speed is continually being worked on https://nnethercote.github.io/2026/11/04/how-to-speed-up-the...

      And the large target directories is also being worked on as well.

    • dabinat 7 hours ago
      I think the main reason Rust gets a bad reputation for compile times is that the compiler makes it very easy to shoot yourself in the foot. When I first started using Rust my compile times for release builds were around 7-8 mins. Then I tweaked some settings and split things up into smaller crates and got it to be under a minute, which was fine for me.

      cargo check would still take a long time though, until I realized that I had a build script that was triggering more often that it should, causing Rust to throw out a lot of its work and redo it. Once I fixed that, cargo check was near-instant.

      So as a Rust developer you can have decent compile times but only if you (and your dependencies) optimize for it. Hopefully at some point we’ll be able to stop having to think about it, but we’re not there yet.

      • mike1o1 1 hour ago
        Do you have an example of some of the compiler/setup changes you made, besides just splitting things into smaller crates, or was that all the organizational changes you made?
    • ytxm 1 hour ago
      Compiler usually isn't the problem, it's the link stage. Try "wild" linker (it's amazing) and try looser release-like build profiles
    • the8472 14 hours ago
      Yes, lots of optimization work has it made faster despite gaining new features.

      https://perf.rust-lang.org/dashboard.html

    • small_model 20 hours ago
      Yes this is why I switched to Go for backend, much faster compiling and performance isn't an issue for the application yes using 100GB+ is just bad tooling.
      • arl79 7 hours ago
        Not only is the compiler very slow, but maintaining the code is slower too. No single tool is right for everything. To me, Rust is definitely not a general-purpose language. It only makes sense for workloads where the ratio of execution time to dev/compile time is heavily skewed toward running the code.
        • kibwen 3 hours ago
          Nah, compared to other languages, the strictness of Rust makes maintaining codebases a joy. Like, I love Python, but maintaining a large Python codebase is a source of constant anxiety. The Rust compiler actually feels like it has your back.
    • eptcyka 19 hours ago
      On macOS there is a known bug where some temp files are always created anew, not reused, which slows down compilation and wastes more space than other platforms.
    • vlovich123 20 hours ago
      Any faster vs what baseline? They’ve constantly made improvements and Rust today is pretty darn quick, especially for incremental. There’s work to parallelize the front end which will help a little bit and you can always use the cranelift backend for debugging which is substantially faster than LLVM.

      They’re also doing work to reduce the amount of disk space usage (by clearing out unused articacts) and make it easier to maintain.

      • jtwaleson 20 hours ago
        Best to do some benchmarks for cranelift on your codebases and system. It used to be quite a lot faster, but for me the advantage has disappeared over the last year of Rust improvements.
    • barchar 18 hours ago
      try disabling at least some debug-info for your dependencies.

      use cargo's --timings option to identify the slow crates, then use measureme to figure where rustc is spending time.

      try fiddling with detached debug-info, dwp files can be smaller than their constituent dwo files.

      ensure really small "template wrappers" are inlined.

      lower the number of compilation-units you use.

      For incremental builds I have found it can _sometimes_ be effective to split out larger dependencies into a dynlib. You create a dylib crate that re-exports said dependencies and your executable depends on that. Ofc things like generics from the offending libraries will still end up in your executables; Though I think there is a way to mitigate this a little.

      This mostly helps with link-time, and saving space if you have a bunch of executables (using the argv[0] trick will help more, though).

    • kennykartman 19 hours ago
      You might be interested in this: https://news.ycombinator.com/item?id=50458849 - I didn't try it yet, though.
    • 0o777 20 hours ago
      All the big AI companies use Rust so this is probably something they should focus on improving.
      • panstromek 19 hours ago
        They do fund some of these efforts, yes.
    • benjiro29 18 hours ago
      Is the compiler any faster now?

      If your codebase is not some small project, its excruciating slow. Even if you try different linkers, and other compilers, nothing really make incremental compiles eat so much of your system. Even more so if you have multiple AI agents doing security and other checks.

      Switched to Go for several months, and the difference was very noticeable. Until you started to get there also 50k+ files that are interlinked. And let us not talk about Go and Rust their issues with insane amount of debug/cache buildup.

      Imaging if you have 4 to 6 agents running that, with each seeing the cache grow from 20, 30, 40 ... To the point that a 100/1000GB SSD grows to 800, 900GB usage. Often in barely a day.

      Seen my NVME drive its lifespan drop from 98% to 91% in barely a few month time. I dread looking at it again lol

      What was the solution? Going back to C ... Despite right now working on a 800k lines project, it compiles way faster the Go, and well, Rust will have pegged all 16 cores for a minute, for EACH agent trying to recompile on a small change.

      Memory safety? Instead of checking at compile time, and wasting my time, this has simply been moved to AI agents checking, making tools, checking, at night. So it does not disturb my own work.

      Its ironic, how both modern projects, end up being worse off. Best of all, the C project is way faster then the same project in Go and Rust. Yea, it was "fun" having AI transcompile them twice but the difference on actual large codebase, and not some micro benchmarks is not a joke. To the point that now all my projects have gone back to C...

      And yea, i expect some fast downvotes by our Rust friends because saying something negative about Rust always gets people downvoted here. No offence but Rust being linked to LLM and the whole checker was a benefit before AI came around. But now you can offload a lot of safety checks to the backend/offhours, instead of paying for it with every compile.

      • benjiro29 3 hours ago
        Thanks for proving my point. Every time there is some criticism of Rust, some people can not help downvoting because they associate their being with a programming language. Such odd behavior...
    • flykespice 15 hours ago
      What the hell are you doing to produce 90gb of temp files? Is that normal on rust land?
      • adastra22 14 hours ago
        It's large but not insane. I've got 20gb in a not-too-large repo.
        • a96 6 hours ago
          That is frankly insane IMO. 20 MB would be insane unless there's massive libraries or something. 20 GB is the size of a very fat graphical operating system.
          • flykespice 1 hour ago
            I think even Gradle produce much less cache files...
      • kstrauser 14 hours ago
        No. My target directory is 329GB at the moment. I wish mine were just 90GB.

        (And yet I’m perfectly happy running `cargo clean` periodically in exchange for all the Rust loveliness. Sure, I wish I didn’t need to. Sure, I hope it’ll get better. I can live with the temporary inconvenience though.

        Also, I’m developing in a tight auto-build-on-commit loop so I have a gazillion builds.)

        • soon_to_be_sb 12 hours ago
          Yea, I was thinking the same. 90gb is not that big. Last week I cleared 130gb out of the target dir.
        • simonask 8 hours ago
          These numbers are totally insane. I've never seen a Rust project with a build cache this large.

          Do you have 10 different versions of Tokio included in your project or something?

          The project I'm currently working on is quite large, and it's locally cross-compiled to 5 different arch/OS combinations, plus a debug build for the local machine. The build dir is 9.1 GB. I've seen it grow to somewhere around 20 GB, but only after a significant number of dependencies were updated, or the compiler version changed.

          A clean debug build of Bevy (a game engine, one of the largest Rust projects around) produces a target dir of around 13 GB. By the way, rebuilding Bevy on my machine takes about 1 minute.

          Now, these numbers are still much bigger than I would have preferred, but 329 GB? Get out of here.

        • flykespice 3 hours ago
          329gb?? That is larger than my entire SSD storage.

          It would be more believable if you told me you were making your own GTA VI

    • throwaway27448 20 hours ago
      I don't understand why people complain about this non-stop. If compilation time is such an issue use a different language. I can't say I've been bottlenecked by compilation in a very long time.
      • IshKebab 18 hours ago
        I don't think you can tell people not to complain about it - it is clearly very desirable to have faster compilation, like Zig or Go.

        But that said I do agree it is pretty fast these days. Significantly faster than C++ and people have tolerated that for decades.

        • throwaway27448 16 hours ago
          I didn't tell anyone to do anything. I just don't get why people complain—it's like they don't grasp the concept of tradeoffs.
    • amelius 20 hours ago
      There's really a paradox here. Rust claims to be a fast language, but compiling, even without optimizations on, takes ages ...
      • barchar 18 hours ago
        Rust encourages a kind of generic programming that can result in generating too much code.

        The compilation model is vastly, vastly, vastly better than languages like C++ and C, though, and it does compile much faster than an equivalent C++ build (doesn't count if you download precompiled binaries of your c++ dependencies)

        • cozzyd 16 hours ago
          But the lack of ABI stability means that's not a choice anyway, doesn't it?
          • SAI_Peregrinus 15 hours ago
            Rust can compile to dynamic libraries. If you don't use the C abi you have to compile anything that loads them with the same Rust compiler version and target triple. So you need to have some way to guarantee the correct compiler is being used, e.g. Nix or Bazel.
            • cozzyd 14 hours ago
              And possibly compilation options?
      • IshKebab 18 hours ago
        That's not a paradox, that's how it always works. Compiling to fast machine code requires more work and takes longer.

        Is Python a fast language because it barely takes any time to compile the code? No obviously not.

        • Matrixik 17 hours ago
          Looks like people extending rust never really focused on compile speed when designing features (from [1]):

          > If you could reinvent/change any aspect of Rust, what would you do alternatively?

          > A lot happened because we wanted to ship a useful thing with only so much time in the day, so some things were less deliberate than others. There’s an alternate version of Rust with significantly faster compiler times, because while we cared about compile times when designing we always prioritized other values more. We never asked ourselves how this feature or implementation impacted compiler analysis time and there are several spots where something slightly different would have much faster compiler times, which people do care about. But had we spent time on that, we would have neglected other things and not been any more successful.

          [1]: https://alexalejandre.com/interviews/interview-with-steve-kl...

        • amelius 18 hours ago
          You missed "without optimizations on".

          This is important, because most often during development you want fast compilation times more than you want fast code.

          • afdbcreid 17 hours ago
            That still isn't a paradox. Furthermore it still makes sense: a language designed to generate the fastest code has constructs that cannot be compiled quickly, even without optimizations.

            But some of it is implementation problems.

            • adastra22 14 hours ago
              Rust's compilation speed issues are not due to optimizations. There is some intrinsic slowness, but also some boneheaded decisions that are now baked in. E.g. the unit of compilation being the crate, not file/module, makes it so you hit some bad scaling laws. And the borrow checker is SLOW, and unavoidably so, but borrow checking could have been avoided with different lifetime rules. Etc.

              I say this as a full-time rust developer btw.

              • aw1621107 13 hours ago
                > And the borrow checker is SLOW, and unavoidably so

                IIRC for most codebases borrowck actually makes up a pretty small proportion of compilation time (e.g., see [0] for some admittedly rough estimates).

                > but borrow checking could have been avoided with different lifetime rules.

                I'm not sure you could entirely avoid borrow checking without a pretty significant change to what you're allowed to do with references.

                [0]: https://kobzol.github.io/rust/rustc/2024/03/15/rustc-what-ta...

              • afdbcreid 2 hours ago
                Rust is indeed not designed for quick compilation. Furthermore and unlike what you said, what makes it memory safe has pretty little to do with that. But what makes it fast definitely has to do with that, which is what I said.
      • kibwen 19 hours ago
        There's no paradox here. You can use any benchmark you like to prove that Rust is a fast language. The work that the compiler does is irrespective of the language that rustc is written in.
        • amelius 19 hours ago
          Yes, the benchmark is compiler compiling itself. From scratch and incrementally.
          • kibwen 18 hours ago
            Unfortunately, that isn't how any of this works.
      • saghm 14 hours ago
        Have you been similarly confused by how slow compiling can be for massive C++ projects for decades? I have trouble believing that you genuinely think that's what anyone means by saying Rut is fast.
        • pjmlp 10 hours ago
          In C++ case usually is the outcome of compiling everything from source, not using binary libraries for dependencies, binary caching, pre-compiled headers, incremental compilation and linking.

          Some of the items tend to be rather sub-optimal in UNIX based C++ compilers.

          Using Visual C++ or C++ Builder with pre-compiled headers, or modules nowadays, working only on the main application, with everything else compiled as DLLs, COM, or packages (C++ Builder specific), incremental compiler, incremental linking, hot code reloading, is rather fast for the typical compile-debug-fix workflow.

      • aw1621107 13 hours ago
        > Rust claims to be a fast language, but compiling, even without optimizations on, takes ages ...

        As usual, this begs the question of "compared to what"? "Fast" languages obviously don't have some magical ability to guarantee that every program written in them is Blazing Fast(tm); without further inspection one can come to any number of other equally plausible conclusions (e.g., the program is fast for what it does).

    • shevy-java 18 hours ago
      Well, the AI that slops out Rust code won't mind having to wait!
  • steveklabnik 21 hours ago
    A monumental release. Thanks to everyone who worked so hard on all of these long-term features that are finally landing.
    • caaqil 16 hours ago
      Plaudits to all involved, as the sermon goes.
      • steveklabnik 12 hours ago
        I know that's a meme but this actually is a really huge release.
  • levkk 17 hours ago
    DropGuard is nice. This is basically `defer` in Go I think.
    • Groxx 17 hours ago
      A defer that you can explicitly skip (via `dismiss()`) - I like it, that'd clean up a fair bit of "do this for safety unless successful" Go code that I've encountered. I've built similar things before, sometimes it helps a lot, and often that's in especially gnarly code which generally benefits from any clarity improvement.
    • aw1621107 16 hours ago
      Minus Go's defer being function-scoped, of course.

      (and what sibling comment mentioned)

  • esFran 5 hours ago
    I've been thinking for a while about learning a programming language other than SQL and Python. I'm weighing three candidates: C, C++ (modern C++, with smart pointers and so on) or Rust, and I can't make up my mind. C is ideal because it would get me into the Linux world and make me 100% portable. But the threat Rust poses on the security front is significant. C++ is a real dark horse: almost all high-performance libraries are written in C++, as are critical pieces of software such as 3D engines, drone controllers and robotics. But the threat from Rust is still felt.

    I have to choose: what would you recommend? I think C++ could be the perfect fit, but it keeps me out of Linux kernel development. With LLMs, is the safety advantage of Rust's borrow checker mitigated?

    • rswail 4 hours ago
      C is a simple language that is easy to understand but also easy to make classic mistakes like use-after-free and array boundaries.

      C++ is an extremely complex language with lots of features and libraries and mountains of code, but it's not necessarily easy to write or debug. Compiler warnings alone can be crazy, considering the templating feature is almost a compile-time turing complete language.

      Rust has some (to me) ugly syntax, but it tries to avoid the footguns of C++ while maintaining its commitment to removing the classic C problems in safe code. It also tries to maintain "zero cost abstractions" that are easier to program, but don't impact execution speed, primarily by having a much smarter compiler than C or C++.

      I'd learn Rust. C will be easy after that, and C++ may be unnecessary.

    • Buttons840 1 hour ago
      Learn whichever one makes you most excited right now.

      Don't worry, you can change your mind. If you end up learning a little of all 3, that's a good thing.

      The time you spend analyzing which you should learn would be better spent learning the worst possible pick of the 3.

      But don't feel too bad, I also procrastinate by analysis. Many of us do. :)

    • grougnax 5 hours ago
      [dead]
  • ComputerGuru 22 hours ago
    It would probably be better to wait for the official release blog post for submission to HN, no?
  • 129486799 32 minutes ago
    That is all very nice, but hardly anyone is writing original software in Rust. Most people use c2rust to steal C projects that are than unsafe Rust and 30% slower than the originals.

    It is really the most uncreative and morally corrupt community in existence.

  • pmichaud 22 hours ago
    Nice work... but I still yearn for a stable ABI!
    • JoshTriplett 21 hours ago
      The primary challenge in having a stable ABI is that we have generics. So, even if we never changed the calling conventions, an ABI is not as simple as exporting a symbol with the right name. We implement generics by providing MIR (our main intermediate representation) that gets compiled by the linking program for each instantiation of a generic.

      Swift handles this through the equivalent of Rust's `dyn`. We could have a stable ABI that's based entirely on `dyn`. Such an ABI would have some limitations, since there are traits `dyn` can't represent (anything that's generic over something other than the type that implements the trait, which is quite common), though we're working on some of those.

      Essentially, you wouldn't be able to have a `Vec<T>` in your ABI without either pinning down T or using something like `Vec<Box<dyn Trait>>`. Which is possible, but kind of awful.

      We're still planning to ship a stable ABI at some point, but that gives a flavor for some of the kinds of problems we'd need to solve in order for that stable ABI to be useful.

      (C++ typically handles generics by having types defined in header files, and those get compiled with the program consuming the library, which is effectively the same situation Rust is in. You could export symbols from a shared library for specific instantiation of a template, but people rarely do that.)

      • mamcx 20 hours ago
        I wonder why not make the ABI contract explicit, instead of do what C do that froze the lang.

        Similar to :

            #[rust_abi]
            struct MustConform
            fn must_conform
        
        So the user must write the shims instead of rust magically build it. This also mean that ABI changes become visible, and changes to rust not mean worries about ABI.
        • chiffaa 19 hours ago
          To my knowledge this is what crABI is all about
      • yrjrjjrjjtjjr 19 hours ago
        A generic could be seen as a pure (in the functional sense) program that is run at link time that takes various type information as input and outputs an implementation.
      • pjmlp 19 hours ago
        You are forgetting C++ has modules now, and extern templates, as implementations for common type parameters.
      • vaylian 6 hours ago
        Would it be possible to provide a first version of the ABI that deliberately excludes support for generics?
      • IshKebab 18 hours ago
        I would be happy with something better than the C ABI even if it doesn't support everything in Rust on day one.
        • barchar 18 hours ago
          I think there's some work on that, getting at least slice and trait object ABIs that you can use in DSO interfaces.
        • JoshTriplett 18 hours ago
          Same.
      • gspr 18 hours ago
        Thank you for your work, it's always interesting to read your take.

        Forgive the naive question on something that's probably been discussed many times over, but could there be a middle ground when it comes to a stable ABI and generics? Something where the person building the library for dynamic linking chooses which explicit monomorphizations they'd like to provide for each public generic function (and type), and the compiler stamps out all combinations of those concrete instances? Could the way these are named and stamped out be standardized so that this could be treated as a stable ABI for non-generics?

        It seems to me that it would at least cover distros: they could make a pass over all their Rust code and determine which monomorphizations are needed throughout the distro.

    • orlp 21 hours ago
      We have it: unsafe extern "C" { }.

      An actual stable native Rust ABI sounds like a forward compatibility nightmare.

      • Xirdus 21 hours ago
        An actual stable native Rust ABI is a prerequisite for distributing libraries as anything other than source code.
        • ChadNauseam 21 hours ago
          What is the advantage of doing so? Is it for cases where your source code is confidential but you want to sell access to your library?
          • cogman10 19 hours ago
            Operating systems.

            If there's a CVE in tokio, the OS could theoretically publish a patched version of tokio and all apps that depend on that end up using the fixed code.

            As it stands now, the OS needs to publish updated versions of all rust apps that depend on tokio.

            • afdbcreid 19 hours ago
              That's not how it works basically anywhere except in C/C++ apps on Linux.
              • cogman10 19 hours ago
                Yes and no.

                Yes, in that it's primarily a linux thing as MS has gone the route of saving off basically all dlls for all their OSes for backwards compatibility (though they still backpatch).

                No, in that other than Rust and Go (and maybe a few others that emit single binaries, zig?) this is how it works with OS distributed programming language packages. Python, ruby, java, perl, C#, the OS will for all of them control distribute and update the libs independent of the apps that use them.

                Also, C/C++ still make up a huge percentage of all apps in pretty much any OS.

                • the8472 15 hours ago
                  > prerequisite for distributing libraries as anything other than source code.

                  > Python, ruby, java, perl, C#, the OS will for all of them control distribute and update the libs independent of the apps that use them.

                  Those are all JIT'ed languages, so they're distributed in source or intermediate form, not as fixed-ABI-shared-libraries.

                  It's really just C where shared libs really work. Even C++ has wrinkles.

                  • cogman10 1 hour ago
                    > so they're distributed in source or intermediate form, not as fixed-ABI-shared-libraries.

                    I agree. These languages all have the benefit of what an ABI provides due to their nature. Go and Rust are outliers because they don't send out intermediate versions.

                    My point was more that the effect of being able to hot-patch applications on a system is what makes an ABI desirable, not that an ABI is necessary for that. For a language like rust, it's pretty necessary. Though it would be interesting if you could send out an intermediate compiled form of rust and do a JIT on that. WASM is pretty close to doing that, but rust doesn't support dynamic linking of modules (AFAIK).

                    > Even C++ has wrinkles.

                    Yeah, I somewhat hesitate to say C/C++ as being ABI stable as it's really just C and C++ uses that. Once you use any C++ features you quickly get into realms where things are ill defined. You end up needing gross things like COM in order to properly use C++ shared libs.

                • afdbcreid 18 hours ago
                  > No, in that other than Rust and Go (and maybe a few others that emit single binaries, zig?) this is how it works with OS distributed programming language packages.

                  Uhmm... No? E.g.:

                  - Python has long strongly recommended virtual environments.

                  - Not to talk about JavaScript which of course manage things per project by default.

                  - I don't remember what was the state of things in .NET Framework, but in modern .NET NuGet packages are distributed as DLLs with your app.

                  I don't know other ecosystems well but I believe they aren't different.

                  • cogman10 17 hours ago
                    > Uhmm... No?

                    Ummm... yes.

                    How software is maintained by an OS is different from how software is maintained by 3rd party developers.

                    - Python has long strongly recommended virtual environments.

                    Yes, if you are developing a private application. But if that application gets adopted by the OS then you can expect all it's dependencies to be sent to a place like `/usr/lib/python3/dist-packages`.

                    > Not to talk about JavaScript which of course manage things per project by default.

                    I didn't bring it up because it's one I'm not familiar with. I expect OS maintainers will do similar things with it that they do with python but I'm not 100% on that.

                    > I don't remember what was the state of things in .NET Framework, but in modern .NET NuGet packages are distributed as DLLs with your app.

                    And if your .net application ends up installed as an OS package you can expect those dlls to be stored in /usr/lib.

                    If you are doing C/C++, as a 3rd party app, you aren't putting the .so files or the .dll files in /usr/lib or C:\Windows\System32. You are storing them in the same directory as your application. But if the OS decides to distribute your app, you can expect your .so files to get put into /usr/lib and even System32 (very very rare for MS to do that, but it does happen when, for example, we are talking about drivers).

                    Edit: Re: node. Here's the debian guidelines for how dependencies ultimately get shredded and distributed. https://wiki.debian.org/Javascript/Nodejs/Manual?pow_referer...

                    • afdbcreid 16 hours ago
                      But that's the thing: almost nobody ships software via the OS today. Even on Linux software is often managed in other ways.
                      • cogman10 15 hours ago
                        Let me rewind this to the top of the thread.

                        > What is the advantage of doing so?

                        To which I responded

                        > Operating systems.

                        To which you said

                        > That's not how it works basically anywhere

                        I think we have reached the point in the thread where you concede that yes, there is somewhere where it's how it works and yes it does apply to languages that aren't C/C++.

                        So now you're shifting the goalposts and topic to

                        > almost nobody ships software via the OS today.

                        That was never something I was trying to debate. The topic was "why would you want ABI stability". And the answer is that if I wanted to rewrite coreutils in rust, then it'd be really useful to have synchronized crates with a stable ABI so I could potentially update those crates independent of the apps that depend on them.

                        • afdbcreid 15 hours ago
                          I agree that sometimes other languages are packaged this way as well, and maybe I was moving the goalposts. My original meaning was that only for C/C++ (on Linux) the recommended method of distribution is via the OS, while other languages have their own mediums (not requiring stable ABIs). So when they are packaged like that that's mostly because the OS itself or its services need them.
              • gspr 18 hours ago
                Well yes exactly, because essentially nothing else has a stable ABI.
              • Xirdus 19 hours ago
                Because only C/C++ apps have stable ABI. Everyone else would love to do it too but they're S.O.L.
                • afdbcreid 18 hours ago
                  That's not true. Scripting languages of course need no ABI. Managed languages like C# and Java often keep compatibility of the bytecode. Only AOT languages like Go and Rust cannot.
          • xigoi 17 hours ago
            Interoperating witt other languages without having to use C as a middleman?
            • saghm 13 hours ago
              I agree that using the C ABI for interop between arbitrary non-C languages feels weird, but it's not like that wasn't a thing long before Rust ever existed. If you truly want a modern ABI for languages that are not C, something like the WASM component model is probably the closest thing that exists today.
            • Xirdus 16 hours ago
              An unstable ABI is entirely sufficient for that, as long as you update both sides in tandem.
          • flykespice 15 hours ago
            Yep, and it also imposes a big security risk relying on a closed binary blob that could be injected anytime with a backdoor.

            Afaik, odin seems to get it right requiring libraries to be distributed source only.

          • xtajv 18 hours ago
            There is another thread complaining about compile times and tmp dir sizes.

            Stable ABI dramatically improves the problem space there (without necessarily having anything to do with business model).

        • SkiFire13 21 hours ago
          It's not a strict prerequisite, you can just require the library being distributed to use extern "C".
          • gspr 21 hours ago
            Well yes, but then your interface is a C ABI. That's fantastic if the side using my library is any language where C is the only common ground. When the application side is Rust though, it leaves a lot to be desired. It would be delicious to actually interface in a way that respects Rust!

            Hell, even if all exposed functions and types would need to be fully monomorphized at the interface, it would be a lot nicer to pass a `&'a [i64]` rather than a `const * int64_t` together with a `size_t n` and have to marshall the slice on both sides.

          • Xirdus 20 hours ago
            Or to put it another way, it is a strict prerequisite and Rust already meets it via extern "C".
        • wahern 21 hours ago
          Another year or three of insane memory and disk prices and people will come around.

          A stable Rust ABI would be nice for not just Rust, especially if they refine or extend (formally or de facto) the SysV ABI to optimize passing and returning of discriminants. That could then smooth the way for developing these features in C and C++, such as a primitive error-result type that saw some brief attention in both C and C++ WGs a couple of years ago. Doing it properly--absolute minimum cost, ABI stable, and cross-language--seemed to require too much orchestration across the ecosystem so enthusiasm and ambition seemed to peter out. The work required for a stable Rust ABI could provide the inertia to get that done.

        • afdbcreid 21 hours ago
          Rust will almost certainly never have a stable ABI by default, and libraries will continue to be compiled from source by default. It might one day have an opt-in stable ABI.
        • fallingbananna 21 hours ago
          If you can drop the "native" requirement, then Wasm is also a way.
        • redox99 21 hours ago
          Why would you want libraries in any other format?
          • eviks 21 hours ago
            Not to waste time and space?
    • iknowstuff 21 hours ago
      Follow or contribute to efforts on a minimal crABI:

      https://github.com/joshtriplett/rfcs/blob/crabi-v1/text/3470...

    • danhor 20 hours ago
      I don't think a stable ABI has enough advantages to be worth it. C++, IMHO, is a great examples of the downsides of a stable-enough ABI, where stability was never guaranteed, but is now so entrenched that it'll likely never be broken again (limiting the language & the usability in a bunch of ways).

      It might make sense to have a subset Swift-style stable ABI, but that's a huge engineering effort, has lots of overhead and is also likely not worth it IMHO.

    • stillpointlab 21 hours ago
      stable ABI sounds great, but anything/everything that reduces build times is what I really want
      • Narishma 18 hours ago
        A stable ABI would help with that.
    • Svoka 21 hours ago
      Why the yearning for prebuilt Rust libraries? Seems like a nightmare which does not need to happen.
      • gspr 20 hours ago
        Dynamic linking is useful. Not to everyone and not always, but it is.
        • kibwen 19 hours ago
          Rust supports dynamic linking. What a stable ABI provides is cross-toolchain dynamic linking.
      • Woshiwuja 21 hours ago
        [dead]
      • silon42 21 hours ago
        So, all Linux will be Gentoo?
        • Svoka 14 hours ago
          what? There is stable ABI. It's C's stable ABI. If you are reimplementing existing libraries like most of rust rewrites are, you already have ABI you have to follow.
  • ustad 21 hours ago
    “Never type” - Feel like I’m stupid for not having a clue what that means.
    • Xirdus 20 hours ago
      Mathematically, types are sets of possible values.

      Any type (like in TypeScript; Rust doesn't have one) is a set of every possible value; a supertype of all types. Every expression regardless of type can be assigned to a variable of type any.

      The opposite is the never type, which is an empty set; no value is of type never. Per set theory, an empty set is a subset of every set, which makes the never type a subtype of all types. An expression of type never can be assigned to every variable regardless of type.

      If never type has no values, then how can an expression have never type? Easy: it must never evaluate. Infinite loops, unconditional panics/exceptions, process exit/abort, etc. Also, generics - you can have Vec<!> that's always empty, Result<T,!> that can never be an error, etc.

      • rcxdude 19 hours ago
        Rust does have https://doc.rust-lang.org/std/any/trait.Any.html but it's not quite the same thing (for one thing, it's not actually all types).
      • afdbcreid 19 hours ago
        Also called top and bottom types, for this reason.
        • steveklabnik 19 hours ago
          Any is not a top type and ! is not a bottom type, actually. They are sort of similar from a lay perspective if you squint, though.
          • afdbcreid 18 hours ago
            Why not? I mean if you refer to Rust specifically, yes, because there is no subtyping except for lifetimes, only coercion (and `Any` also cannot contain any type). But in general, why not?
            • steveklabnik 18 hours ago
              I am speaking about Rust specifically, yes.
      • boston_clone 20 hours ago
        Comprehensive yet succinct, and appreciate you tying it to math - that helped solidify the idea.
    • anamexis 21 hours ago
    • pkulak 21 hours ago
      A few other langs have it too. It's just something to return when no return is actually possible. And then it can propagate, so it makes some nice things possible that weren't before.
      • igravious 20 hours ago
        Without looking up the Rust implementation I would hazard a guess that it is loose language to say "something to return when no return is actually possible" because if it is anything like the Bottom Type then there is no something that is being returned which is what this function signature indicates. Generally used for exception handling or intentional infinite loops (in both cases the function does not return from whence it came) … please correct me if I'm wrong here …
        • kibwen 19 hours ago
          Basic use cases like that have always been possible in Rust, either via defining your own enum with zero variants (`enum Foo {}`), or by using a function return type of `!` which was hardcoded to work for certain things, e.g. infinite loops. What this release does is generalizes it so that `!` can participate in types in general, and the coolest part is that pattern matching is aware of this, so for example if you have a `Result<u8, !>` where the error variant is impossible, a `match` over this would allow you to omit the impossible error arm, and furthermore because this enum now effectively only has a single variant, it would allow you to use the pleasant irrefutable destructuring assignment syntax `let Ok(foo) = blah();`.
          • afdbcreid 19 hours ago
            It has existed as a real type for a very long time (I believe in the beginning it really wasn't a real type but that's a long time ago), you just weren't allowed to name it. There was also an (unsupported) hack that allowed you to use it on stable.
    • saghm 13 hours ago
      It's the type of what you get back from a `panic!` (a value you never actually get back).
    • yccs27 19 hours ago
      If you have a variable x: ! in scope, your code can never be reached.
    • LoganDark 20 hours ago
      It's the type called "!", or the return value of diverging control flow, such as infinite loops, returns or function calls that panic or abort. It's an uninhabited type, meaning no values of it can actually exist, and that any code that would encounter such a value is unreachable.
    • NooneAtAll5 20 hours ago
      noreturn, basically
      • sixthDot 4 hours ago
        yeah aka the bottom type , but "never return" is inisde the type system (a bit like D handles that) while "noreturn" is an attribute. That's basically the two known possible ways of expressing that a call will never return.
  • mkl 18 hours ago
    > cargo install ignores the minimum publish age, for both the installed crate and its dependencies

    Why is that? It seems like that makes min-publish-age much less effective.

    • epage 15 hours ago
      This comes from usability and consistency.

      When we added the MSRV aware resolver, we decided to have it not affect `cargo install` because you could get an old version and not notice (especially with how noisy cargo is) when the right answer might be to upgrade.

      Somewhat similar for min-publish-age but also we had defined the parent table for these config fields to not affect install.

      The change to `--locked` made us feel a little better with this non-ideal circumstance.

    • GolDDranks 16 hours ago
      The fact that install now uses the lockfile by default, mitigates this, I think.
  • unvalley 19 minutes ago
    welcome min-publish-age
  • nbardy 13 hours ago
    Can anyone who knows Rust well explain why its so good for AI?

    It seems like the AI can really write safe types and fast, efficient code in rust that beats anything else.

    I've moved basically all my projects over to it. And I don't really know how it compares to other fast languages. My personal langue preference was always for readable languages like Clojure or Ruby, but at this point I'm not reading any code and just want performance.

    • hannofcart 12 hours ago
      Most of the reasons previously not to use Rust came down to the i) non-trivial learning curve, especially the ownership model, and ii) the (allegedly) overbearingly strict compiler that forces you to think through potential errors and solve them.

      With agentic programming, (i) is a non-issue since LLMs have a very good grasp of the language, and it's no skin of your back, the agent is sweating it out with the compiler, not you, and (ii) is likely something you actually want.

      I suspect it comes down to which other ecosystem you are coming from:

      Python -> Rust: massive performance gains, type safety, much better concurrency

      C++ -> Rust: much much better memory safety, much nicer compiler errors and warnings

      Java -> Rust: better memory utilisation, non-null-able types (though I think recent Java versions facilitate this), better performance

      But there are other language ecosystems where the gains become more subjective.

      For eg. Golang -> Rust, I'd argue better "correctness", especially when concurrency is involved, but it's less pronounced than some of the other paths I mentioned above.

      • heresie-dabord 9 hours ago
        > Golang -> Rust, I'd argue better "correctness", especially when concurrency is involved, but it's less pronounced than some of the other paths

        Tractable correctness is an underrated win at the scale of building enterprise solutions. But Rust also is a systems language, something that people had hoped from golang.

    • fluffiac 12 hours ago
      a well designed Rust project can leverage the type system to represent "weird states" in your program. what would otherwise be unstated rules or assumptions can be laid out cleanly as type invariants. a common example is `div(a, b) -> Option` where None is returned when b is zero. you can get really fancy with this, the blog post talks about a token struct that represents holding the GIL. doing this kind of thing can make certain logic errors more difficult to write and makes code self-documenting in some sense. going against the type system is flagged during compilation, which broadly contributes to rust code feeling like it "just works" when it compiles.

      if code fails to compile, rustc will produce a very high quality error message 90% of the time (they can get pretty gnarly when you're doing something super tricky, but they're still very workable for agents). tests are a first class feature, so agents are able to spot check new features on the same turn you ask it to implement something new. documentation is also first class, and lots of libraries have excellent docs (read https://docs.rs/pyo3/0.30.1/pyo3/marker/struct.Python.html). the whole toolchain gives agents a lot to work with.

      • estebank 11 hours ago
        > they can get pretty gnarly when you're doing something super tricky

        When that happens, please file a ticket. That's how the errors get good: we hear about when they aren't and then we fix them.

    • oconnor663 9 hours ago
      > It seems like the AI can really write safe types and fast, efficient code in rust that beats anything else.

      This is also true for humans! Rust/C/C++ are all about equally fast, but Rust is more productive for most people. The downside for humans is that Rust's learning curve is pretty steep, but that doesn't bother the LLMs.

      • simonask 7 hours ago
        You stumbled upon my pet peeve.

        Both C and C++ have a much steeper learning curve than many realize, just because the compilers let you get away with doing things that are fundamentally invalid (Undefined Behavior). Rust isn't actually much stricter, it just catches these problems at compile time.

        Anyone capable of writing actually correct, standard-conforming C and C++ is mostly able to first-try the equivalent Rust code in almost all cases, because they are already thinking the same way that Rust requires you to think.

        However, a significant portion of people who write both C and C++ don't realize that their code is full of UB - or worse, they don't care.

        From a language perspective, the only new restriction in Rust compared to C++ is that mutable borrows (references) cannot overlap. Good C++ programmers are already avoiding this at all cost, because it's a mess to keep track of. When you actually do need it, Rust gives you the tools to build a safe abstraction.

        EDIT: And to add, Rust is actually less restrictive in a few areas compared to C++. For example, Rust allows bitcasting between unrelated but compatible types (without going through char pointers).

      • Sharlin 8 hours ago
        To be fair, as far as I know even bleeding edge LLMs have problems with the borrow checker and resort to similar workarounds as newbie human Rust coders.
    • joevandyk 1 hour ago
      Any recommendations on good skills/rules/plugins for LLM rust projects?
    • IshKebab 1 hour ago
      Same reasons why it's so good for humans:

      * Very strong type system which helps catch bugs at compile time.

      * The type system lets you enforce invariants, e.g. see the type state pattern and "make invalid states unrepresentable"

      * The borrow checker encourages tree ownership which tends to be a less buggy structure than "anything can own anything" spaghetti you get in GC'd languages.

      These give it an "if it compiles it works" character, that some other languages also have (e.g. Haskell), but most don't.

      This was all well known before AI. I guess it's just more obvious to people that never tried Rust themselves.

    • adamnemecek 13 hours ago
      Types and zero cost avstractions.
  • fluffiac 21 hours ago
    yay never type!!

    when can we expect `Result::into_ok` and `Result::into_err` to land? the blog post includes the `infallible_unwrap` demo which is the exact functionality these two functions implement. i wonder why they didn't release these at the same time as never?

    • NobodyNada 21 hours ago
      Those were stabilized in https://github.com/rust-lang/rust/pull/161712, which just barely missed the cutoff date for 1.100 and is on the 1.101 release train.

      (As for why they weren't stabilized at the same time: because it's not worth adding more baggage to a major, difficult stabilization process; as that would just be more surface area that has to be reviewed and another source of potential issues or delays. Instead, the stabilization process for infallible_unwrap was started immediately after `!` was stabilized. That process includes a 2-week final comment period for community feedback which is why they landed in different releases.)

      • saghm 13 hours ago
        The six week release cadence means that stuff like this is not a huge deal, and it's honestly kind of insane how consistent it's been over what's now 100 minor releases over 11 years!
  • lukax 21 hours ago
    Awesome timing.

    I just spent last few days fixing arena leaks (Bumpalo doesn't call drop) and had to use allocator-api2 for Vec::new_in which is now available in stable Rust.

    https://github.com/bancek/rust-sass/pull/1

    • weinzierl 21 hours ago
      "Awesome timing."

      Wait for the timing of the next release. It will be a Christmas present.

  • wpollock 19 hours ago
    This is great news! Well done Rust team!

    As this release seems to include breaking changes, shouldn't the major version number have been bumped, as per semver?

    Has the Rust book(s) been updated to include the new APIs?

    • kibwen 14 hours ago
      Rust's three stability caveats are as follows:

      "We reserve the right to fix compiler bugs, patch safety holes, and change type inference in ways that may occasionally require new type annotations."

      https://blog.rust-lang.org/2014/10/30/Stability/#what-are-th...

      The breakage in question here falls under changes to type inference, which are allowed within reason when they're relatively minor, when steps have been taken to mitigate any breakage in the broader ecosystem, and when the compiler has emitted warnings regarding the imminent change during a grace period, all of which have been done here.

  • Panzerschrek 11 hours ago
    > global-min-publish-age = "3 days"

    It's not a proper solution. A malicious crate can just contain a time-based switching mechanism in order to be undetected some time (let's say a couple of months) in order to become widespread.

    • WillDaSilva 11 hours ago
      There exist companies who scan newly published crates (especially popular ones) for malicious code. Just because the code isn't active yet doesn't mean it won't be caught within a window like this. These measures provide real, albeit imperfect, security.
      • Panzerschrek 11 hours ago
        > There exist companies who scan newly published crates

        There is only one logical step left - make such scanning mandatory. Even better would be to perform proper audit with real humans involved. In order to cut down costs of such measures, there should be some limit on how often a package may be updated, let's say, once in a week.

    • nine_k 10 hours ago
      Isn't it the time between release for analysis and release for use? I suppose that finding malware only when it's activated isn't the only possible way, especially when the complete source code is available.
      • hmry 4 hours ago
        This is something I really appreciate about cargo/crates.io's source-only distribution, compared to e.g. npm or pip/PyPI.

        You always know that the package contents match the source code. And you can always add a dependency by just downloading its source code and putting it into a subdirectory. You don't have to go and set up a different build system for each library if you want to avoid the pre-built artifacts.

        • woodruffw 3 hours ago
          People have shipped binaries inside of crates on crates.io. It’s a strong (and good) community convention not to, but there’s nothing stopping it.
  • jokoon 2 hours ago
    is rust actually starting to to gain some territory over C++, or still not?
  • superlupo 9 hours ago
    Why not finally a 2.0 if there's a breaking change in it? Or is versioning merely covered by "yearly editions"?
    • looperhacks 8 hours ago
      Because rust 1.100.0 will still compile older code. To get the breaking changes, a crate has to opt into a newer edition. Older editions will still work fine. Apparently this has the added advantage that crates that use different editions can still work together, because the compiler understands all editions.
      • Felk 6 hours ago
        The release explicitly made a breaking change for _old_ editions regarding the `Infallible` type. Though they do explain that they consider the fallout of this to be minimal
    • IshKebab 4 hours ago
      It's a very minor breaking change. This happens all the time in large projects. E.g. when C++ or Python remove rarely used features. Python would be at version 10 by now if they followed strict backwards compatibility.
  • karavelov 22 hours ago
    Finally, "never" happened
    • JoshTriplett 21 hours ago
      And the running joke that the type is named after its stabilization date can finally be put to rest. :)
      • hbn 20 hours ago
        We got "never" in Rust before GTA6

        Two jokes that are expiring this month

    • jmyeet 21 hours ago
      One might call this the moment when nothing never occurs [1].

      [1]: https://www.youtube.com/watch?v=RFm9ClqlGuo

  • AndruLuvisi 16 hours ago
    I can't find any mention of become. Does rust have proper tail calls now?
  • Alien1Being 15 hours ago
    The elephant in the room question is:

    Is this good for AI vibecoding ?

    Human intelligibility and coherence does not seem to matter any more, for current software development.

    • soon_to_be_sb 11 hours ago
      >Human intelligibility and coherence does not seem to matter any more, for current software development.

      Only if your software is throwaway that no one uses.

  • uncivilized 16 hours ago
    The blog post says min-publish-age depends on the registry recording a pubtime. Why would pubtime not exist in the index?
    • epage 15 hours ago
      It was only added to the registry spec a few releases ago. We can't guarantee that a registry has updated to provide it.
      • uncivilized 13 hours ago
        Ah I see, but that means all new releases on crates.io will have that tag, correct?
        • epage 12 hours ago
          The crates.io index was updated to have pubtime populated for every version of every crate.
  • hobofan 21 hours ago
    Thanks to all the maintainers and contributors! That's one of the biggest releases in a long time!
    • fock 21 hours ago
      also humans contributing! Very cool!
  • einpoklum 18 hours ago
    Would you say that having 100 releases of the language more of a positive thing or a negative thing?

    For comparison, C has had, say, 4 versions, and C++ 7 had versions (depending on how you count). But - Java has had 27 main versions and probably more than a 100 if you count minor versions/updates.

    • estebank 15 hours ago
      They are completely different release processes, for different things. C and C++ are language specifications and Rust is a tool chain. Even comparing against another compiler tool chain like gcc it wouldn't be a 1 to 1 comparison. Rust having 100 minor releases is only a factor of the passage of time.

      Last time I checked between a quarter and a third had a patch release, and those are closer to a signal of "a minor release had a problem". When analysing those my conclusion and the time was "for the most part they were needed because some niche feature or platform had a regression that wasn't caught by the suite and a handful of regressions causes by enabling a new feature or updating llvm".

      Even Rust Editions are not a good point of comparison because they are also time based and only leveraged by things that would otherwise be breaking changes.

      What you could use for direct comparison is accepted Rust RFCs against accepted C++ proposals papers or the equivalent for other languages. Or merged Pull/Merge Request counts for the different tool chains. But that's not perfect either (Rust only supports one language, while GCC several, but it has a package manager, which GCC doesn't).

    • tialaramex 16 hours ago
      101 stable Rust minor releases, because 1.0 was a stable release, and many more micro releases incorporating merely urgent bug fixes with no other work.

      Even ignoring K&R C there is C89, C99, C11, C17, C23 and C2y is in progress. I don't see any way to squint at that and count four.

      • einpoklum 7 hours ago
        I forgot about C17, sorry. C2y is not released yet... so, 5 releases of C.
  • sawirricardo 15 hours ago
    i wish for small storage and short duration compilation times
  • badmonster0 7 hours ago
    excited for this
  • shevy-java 18 hours ago
    > The never type, spelled ! in code

    Is that the raven that says Ni?

    https://www.youtube.com/watch?v=bLiXjaPqSyY

  • AtreusS 6 hours ago
    [dead]
  • dharmasthan 11 hours ago
    [flagged]
  • joshsyn 10 hours ago
    [dead]
  • yoy0721 16 hours ago
    [flagged]
  • joshsyn 15 hours ago
    [dead]
  • theapiartist 22 hours ago
    [dead]
  • Surac 21 hours ago
    Still non ABI. Why is ist so hard? what is holding them back. Andy why does it need a unsave keyword? can't they marshal types like other languages?
    • kbolino 19 hours ago
      You can marshal values, but you can't marshal lifetimes, ownership, (lack of) thread-safety, (lack of) side-effects, etc. The ABI carries far less information than the Rust compiler relies on. Thus, any FFI call is inherently unsafe. It takes you, the programmer, with knowledge the compiler doesn't have and the architecture doesn't provide, to determine whether the code as you use it actually is safe or not.
    • galangalalgol 20 hours ago
      It is explained elsewhere, but a summary is that any language with generics is going to have any stable abi as a subset of the language. There is already a subset of the language that is a stable abi, it is the c abi. Expanding that subset has to be worth it in terms of what people actually want to export from a library. As I use generics fairly heavily I don't think I would use that expanded abi for anything.
    • adamch 21 hours ago
      because they change the binary layout sometimes, and the benefits have not yet been judged to be worth freezing it.
      • vablings 18 hours ago
        I mean they could also have a stable ABI for 2.0 and then and changes are breaking herein. Its kind of a choice problem
  • KolmogorovComp 21 hours ago
    I haven’t seen any blog on the topic but I fully believe in the age of coding agents and LLM backward compatibility is a bit less important than it has been in the past and should be relaxed in some cases to allow language to move faster.
    • raphlinus 20 hours ago
      I get your point but disagree strongly. One topic that's been on my mind a lot is durability. The culture of LLMs is that everything is transitory. Why bother keeping a vibe coded codebase around for more than a few weeks, when the next big model iteration will be able to vibe code it better?

      By contrast, free software in general, and Rust very much in particular, has cultural norms that things should last a while, rather than immediately being thrown away. I think that's worth preserving.

  • Sol- 18 hours ago
    Do language features still matter except insofar as they make the LLM verification loop better?
    • yodsanklai 17 hours ago
      You're downvoted but it's a very legitimate question. My main language at work is Rust, I had some expertise with the language (and deep interest for functional programming languages and type theory), but I almost don't read the code nowadays, I just skim though the functions and type definitions. I'm genuinely surprised that there are so many comments commenting the release. I thought most programmers wouldn't care anymore.
      • Sol- 7 hours ago
        Thanks, it was also a genuine question on my part and something I personally noticed recently with the Python 3.15 release notes - I used to enjoy reading them and cared, but it seems a bit moot to read them nowadays.

        So I wonder what programming languages should optimize for nowadays. Probably there's still something to be gained in developing Rust further, because its verifiable structure makes it mesh nicely with LLMs and helps them write code, but less so with more high level languages.

      • soon_to_be_sb 11 hours ago
        To prompt an LLM, you should understand the existing program.
    • wannabe44 11 hours ago
      Some people still read code.
  • grommz 20 hours ago
    [flagged]
  • fallingmeat 22 hours ago
    [flagged]
    • nazgulsenpai 21 hours ago
      once outlook broke we can't even share jensen memes