Rust 1.34 gives private crates a registry workflow
Cargo can combine crates.io dependencies with a named alternative registry. Rust 1.34 also stabilizes fallible conversions, making failed representation changes part of a typed result.
Private code does not stop needing package versions merely because it cannot be published on crates.io. Git and path dependencies provide ways to share that code, but the Rust team describes a gap for organizations managing many internal crates. Rust 1.34 gives Cargo a named alternative-registry workflow that can coexist with the public registry.
The April 11 announcement identifies this as the release's largest change. It also stabilizes TryFrom and TryInto, extends documentation-test support for ? and changes the safety status of a Unix process callback. These are distinct changes, with alternative registries addressing the distribution model around a Rust program.
I tend to judge a systems language partly by how directly it can express the requirements around its code. Internal distribution is one of those requirements. A registry should provide versioned dependencies without requiring an organization to publish proprietary source to the public service.
A local name identifies the registry
The release shows registry configuration in .cargo/config, either under the user's home directory or relative to a package directory. This file maps a chosen name to the location of a registry index. The manifest can then use that name without repeating the index URL in each dependency declaration.
For example, the configuration can define an internal registry. This URL names the index, rather than a particular crate archive.
[registries]
internal = { index = "https://registry.example.com/git/index" }
The package's Cargo.toml then selects it for a particular dependency. The registry name must correspond to the configured entry.
[dependencies]
internal-protocol = { version = "1.0", registry = "internal" }
This separates the package's source selection from the environment's location mapping. A build environment must know what internal means. Merely copying the dependency declaration to an environment without the registry configuration does not supply the missing index location.
The alternative registries RFC explains the motivation for this indirection. Defining registry locations in configuration avoids repeating them throughout project manifests. It also separates location and credential concerns from the manifest's dependency declarations. The released syntax in the announcement is the relevant authority for the examples here, since an RFC can contain earlier forms of the design.
An index and a download service have separate jobs
The RFC describes a registry index stored in a Git repository. The index contains metadata about crate versions and their dependencies. Its top-level configuration points to a location from which Cargo can download crate archives. A full publishing API is a further service, rather than the same thing as the index itself.
This distinction helps explain what an alternative registry must provide. Version resolution needs the crate metadata, while obtaining the selected package needs its archive. Running a private source repository alone does not automatically create a compatible registry index with the required metadata.
The design also distinguishes an alternative registry from source replacement. A mirror must serve the same contents, including matching checksums, as the source being mirrored. An independent registry can publish its own crates. Routing a request to another location and selecting a different package source therefore have different meanings.
For publishing, the release provides cargo login --registry=internal followed by cargo publish --registry=internal. Authentication is stored through Cargo's credentials mechanism. The registry selection on the publish command makes the destination explicit instead of assuming that every package belongs on crates.io.
Public crates cannot require a private registry
Cargo can build software that depends on crates from both crates.io and an alternative registry. The announcement also specifies the opposite boundary, crates published on crates.io cannot depend on external registries. Mixing sources in a private application does not establish that the same manifest can be published as a public crate.
The RFC explains the availability reason. Crates.io cannot make guarantees about another registry's continued availability. A public package whose dependency can be obtained only from an unrelated registry would transfer that availability problem to its users. The restriction preserves a more contained dependency model for published public crates.
The design acknowledges that multiple public registries could fragment the ecosystem. Its stated motivation is that the value of supporting private registries outweighs that potential drawback. The release gives organizations the mechanism, while the existing public-registry boundary remains part of the workflow.
I find the coexistence useful because private distribution should not require duplicating every public dependency into a separate naming system. Cargo can select an internal source for one crate and retain public dependencies elsewhere. The distinction remains visible in the manifest and registry configuration.
Failed conversions receive a standard trait contract
TryFrom and TryInto address a separate source-level boundary. Some representation changes can fail, such as converting a slice into an array of a specific length. An infallible conversion contract cannot express that failure honestly, so the new traits return a result that carries an error.
The release's example combines a checked slice-to-array conversion with u32::from_be_bytes. The latter requires a fixed-size byte array. try_into() can perform the length-sensitive conversion, and ? can propagate the failure in a function with a suitable result type.
The announcement also introduces Infallible for conversions that cannot fail. A blanket implementation connects existing From implementations to the fallible conversion traits. Generic code can therefore use the fallible interface without requiring every underlying conversion to invent an error condition. The release gives conversion from u8 to u32 as an example where the destination can represent the source value without failure. A shared trait vocabulary covers that case while still permitting genuinely fallible conversions to report their own errors.
This makes the relationship between representations explicit. A successful result establishes that the requested conversion was possible, while the error explains that the input did not meet its requirements. It is a useful complement to the registry work, although the two mechanisms operate at entirely different levels.
The release also deprecates the safe before_exec callback in favor of unsafe pre_exec on Unix-like systems. Its explanation concerns invariants after a fork, when resources can be duplicated into the child. That change illustrates why a systems API must state its actual obligations even when doing so makes the caller's responsibilities more visible.