Rust 1.90 makes LLD the Linux x86-64 default
Rust 1.90 changes the linker default for x86_64-unknown-linux-gnu and adds workspace publishing. Both changes move established build work into the standard toolchain with specific compatibility and failure contracts.
An incremental compilation can rebuild little Rust code and still spend substantial time linking the executable. Improving type checking alone cannot remove that final step. Rust 1.90 changes the default linker on its common GNU Linux x86-64 target, making a faster implementation available without requiring each project to maintain its own opt-in configuration.
Released on September 18, Rust 1.90 selects LLD for x86_64-unknown-linux-gnu. It also adds native workspace publishing in Cargo. These are changes to the work around compilation, where a toolchain can reduce repeated project-specific setup while retaining explicit limits on compatibility and recovery.
I value improvements that make the ordinary development path useful without requiring every repository to rediscover the same configuration. Rust's language semantics are a large part of its appeal, but build iteration and release behavior determine how practical that appeal becomes in daily engineering.
Linking remains after incremental compilation
The September 1 explanation from the compiler performance working group distinguishes link time from the rest of compilation. A binary or shared library needs its compiled pieces combined into a final artifact. Reusing compilation results does not eliminate the work required to produce that artifact.
The article reports a ripgrep debug-build example in which linking took roughly half the total time. Its incremental rebuild comparison reduced linking time sevenfold and total compilation time by about forty percent. Those numbers describe the cited example, not a general speedup promised for every Rust project.
The important implication is the relationship between the two phases. As incremental compilation reduces the changed source that needs processing, linking can occupy a larger share of the remaining wait. A linker improvement can therefore help the small edit-and-rebuild cycle as well as a large clean build.
Debug information also affects the amount of material the linker processes. The release specifically calls out large binaries and binaries containing substantial debug information as cases likely to benefit. This explains why a development build can spend significant time linking even when the program is not using expensive optimized code generation.
The toolchain already packages the linker
The working group's explanation says rustup-distributed toolchains already ship LLD for targets that use it. Rust names the packaged executable rust-lld to avoid colliding with an independently installed LLD. Selecting it as a default for another target builds on distribution machinery that already exists.
This matters for reproducibility of setup. A project does not need to assume that the developer installed a matching linker independently merely to receive the new default. The toolchain's packaged component participates in the build, while the target and explicit configuration still determine which path is selected.
The default change is target-specific. It should not be summarized as switching every Linux target or every Rust build to LLD. The announcement names x86_64-unknown-linux-gnu, and other targets have their own toolchain requirements and existing linker choices.
The project's preparation also predates the stable release. The working group describes enabling the default on nightly in May 2024 and testing through CI, Crater, and performance infrastructure. Stable adoption follows that exposure rather than introducing the implementation to all users without an earlier testing period.
Compatibility includes linker behavior
The release expects LLD to work as a replacement in the vast majority of cases, but the working group explicitly rejects a claim of bug-for-bug compatibility with GNU ld. A program can depend on a linker's extensions, accepted scripts, or incidental behavior even when the Rust source is unchanged. The documented opt-out is target-scoped:
[target.x86_64-unknown-linux-gnu]
rustflags = ["-Clinker-features=-lld"]
This belongs in .cargo/config.toml. It disables the LLD linker feature for that target and restores use of the system default linker under the described configuration. A scoped setting also makes the reason for differing build behavior visible where the project records target policy.
An explicit fallback is useful evidence when investigating a new link failure. It can distinguish a changed linker path from an unrelated source change. That does not make permanent fallback the only resolution. A crate relying on a behavioral difference may need corrected link arguments or an upstream linker issue.
The working group also notes that parallelism contributes to the gains. That resource use can matter on constrained build machines or in projects already near hardware limits. Faster elapsed time and the amount of concurrent work are related measurements, not interchangeable ones.
Cargo can publish a dependency graph
Rust 1.90 adds cargo publish --workspace, ordering crate publication according to dependencies between workspace members. Previously, external tools or manual sequencing supplied that operation. Native integration lets Cargo consider the selected packages together during verification.
The versioned Cargo publish documentation describes publishing as packaging, verification, upload, and waiting for index availability. A workspace operation coordinates those steps across packages. It does not turn a registry into a transactional database for the entire workspace.
That distinction matters for dependent crates. A package build inside a checkout can use a local path dependency. A published package needs to work under the dependency information available to registry consumers. Verification of the to-be-published set needs to account for that different environment.
The release says the native operation builds the selected crates as though they were published, including in dry runs. This provides a way to examine the combined release before uploading it. It can catch a mismatch between a workspace's local build relationships and the package relationships the registry will expose.
Dry runs verify without committing uploads
A dry run checks the release set under packaging rules before any registry upload. Cargo exposes that check through the same workspace selection used for publication:
cargo publish --workspace --dry-run
The documentation defines --dry-run as performing checks without upload. That gives a maintainer a concrete artifact-oriented review point, rather than treating a successful development build as proof that the packages are publishable.
Package selection remains a separate part of the command. The versioned documentation describes selecting individual packages and excluding members from a workspace publish. A workspace can contain support crates that are not intended for a registry, so the selected release set should reflect its package policy.
No command can infer the intended public versioning policy from dependency order alone. Ordering establishes which package needs to be available first. The manifests still determine version requirements and publication restrictions. Native sequencing reduces repeated release code without replacing the meaning of those declarations.
Publication can finish only partly
The release announcement explicitly says workspace publishing is not atomic. Network or server failures can leave some crates published and others unpublished. A single command invocation represents a coordinated workflow, not a guarantee that every remote effect commits together.
The Cargo documentation also distinguishes an upload from the client's subsequent wait for index visibility. That wait can time out without undoing the upload. A caller therefore cannot infer from a late timeout that nothing happened remotely.
I consider these failure contracts essential to the feature. A release tool needs to explain completed effects as well as successful intent. Dependency ordering and preflight verification help make a workspace release coherent, while the registry's individual uploads remain observable operations that can succeed or fail separately.
Support tiers describe testing commitments
The release also demotes Intel macOS, x86_64-apple-darwin, to Tier 2 with host tools. Its announcement explains that compiler and standard-library builds remain distributed. This changed guarantee concerns automated testing, not immediate removal of the target or its development tools.
That distinction matters when interpreting a platform-support label. A target can continue building and remain usable while no longer receiving the same required test coverage. For maintainers of cross-platform crates, the practical question is which platforms have execution evidence in their own release process. Availability of a compiler is only one part of that evidence, and a support tier records a particular commitment by the Rust Project.
Defaults and orchestration have different responsibilities
The linker change selects an implementation for an existing build phase. Workspace publishing coordinates an existing set of remote operations. Both improve the standard toolchain, but their guarantees differ. Linker compatibility concerns the resulting artifact, while publication recovery concerns which remote packages already exist.
Rust 1.90 makes those distinctions explicit through a target-specific fallback and a documented non-atomic release workflow. A project can receive faster ordinary linking while retaining a way to isolate compatibility differences. A workspace can verify and order its release set while preserving the individual upload outcomes needed for recovery after a partial publication.