Skip to content

WIP: Builtin/opaque dependencies#16675

Draft
adamgemmell wants to merge 3 commits intorust-lang:masterfrom
adamgemmell:dev/adagem01/opaque
Draft

WIP: Builtin/opaque dependencies#16675
adamgemmell wants to merge 3 commits intorust-lang:masterfrom
adamgemmell:dev/adagem01/opaque

Conversation

@adamgemmell
Copy link

@adamgemmell adamgemmell commented Feb 25, 2026

This WIP PR intends to evaluate an approach to rust-lang/rfcs#3875 by adding support for builtin and opaque dependencies and lets the current -Zbuild-std implementation use them. I'm working on this now as it's a fairly wide-reaching change and was worried that some necessary changes might invalidate other work on the build-std RFCs.

A builtin dependency is one which Cargo innately knows how to find, such as one included with the toolchain. The RFC above adds a new builtin package source for standard library dependencies. An opaque dependency isn't yet fully agreed upon, but is a possible future feature that "hides" transitive dependencies from the main resolve in order to reduce rebuilds.

This PR does this by:

  1. injecting a default set of builtin dependencies to every package in dep_cache (which every call to activate in the resolver goes through), which are identified as opaque.
  2. The registry, when queried for a package satisfying one of these dependencies, returns a dummy Summary representing a builtin package. This package has no dependencies, because the dependency injected is opaque. This allows the resolve to succeed as normal without modifying the resolver itself. The intended behaviour, though untested, is to make use of all the patching/replacement logic already in the registry query.
  3. Instead of the current -Zbuild-std unit generation step which attaches UnitDeps to each root of the std resolve, the main unit generation loop replaces the dummy Summarys with roots from the separate std resolve.

This PR mostly works end to end for various packages I've tried, though some (like tokio) fail right now, maybe because it's a workspace. Removing the hardcoded hacks will be needed to check what tests break. -Zbuild-std-features still works as I haven't touched the main std resolve and take Units from that.

What would be great is some feedback on whether this approach seems sustainable or risks breaking too many things. Do you have any thoughts at this stage @ehuss @epage?

@rustbot rustbot added A-cli Area: Command-line interface, option parsing, etc. A-crate-dependencies Area: [dependencies] of any kind A-dependency-resolution Area: dependency resolution and the resolver A-lockfile Area: Cargo.lock issues A-registries Area: registries Command-fix Command-metadata Command-package Command-tree Command-update labels Feb 25, 2026
@davidtwco
Copy link
Member

davidtwco commented Feb 26, 2026

We aren't expecting that this will land prior to those RFCs being approved (unless Cargo want it to), the intent with this is just to get some feedback on the general direction for the implementation, we're happy to adjust as much or as little as required :) @adamgemmell will also be away for a couple of weeks starting next week, so we might not respond to feedback immediately.

/// A directory-based registry.
Directory,
/// Package sources distributed with the rust toolchain
Builtin,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will impact the unique identifier for the packages from this source in cargo's json output when compiling, cargo metadata, cargo <cmd> -p, etc

.url
.to_file_path()
.expect("builtin sources should not be remote");
Ok(Box::new(PathSource::new(&path, self, gctx)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will using a PathSsource directly like this work?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This particularly could have interesting design questions

None
} else {
Some(builtins.iter())
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is for implicit builtins. Is there a reason you chose to do this here?

}
}

pub fn new_injected_builtin(name: InternedString) -> Dependency {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what do you see as the role of this compared to the other news?

)
})?;

if dep.is_opaque() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to find a way to ask the source for the opaque variant of the summary. The tricky thing will be that we need to work with both variants.

// Injecting builtins earlier (somewhere with access to RustcTargetData) is needed instead of this
let home = std::env::var("HOME").expect("HOME is set");
let path = format!(
"file://{home}/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The URL in source ids is public facing. I think we'll need something more generic and then a new Source

);
if name == "compiler_builtins" {
Self::from_url(&format!(
"builtin+{path}compiler-builtins/compiler-builtins"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why the special case?

has_dev_units,
crate::core::resolver::features::ForceAllTargets::No,
dry_run,
true,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not really a fan of bool constants being used in parameter lists. Makes it a lot harder to figure what what is going on here

keep_previous: Option<Keep<'_>>,
specs: &[PackageIdSpec],
register_patches: bool,
inject_builtins: bool,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do we need to tunnel this through? Not thrilled with this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-cli Area: Command-line interface, option parsing, etc. A-crate-dependencies Area: [dependencies] of any kind A-dependency-resolution Area: dependency resolution and the resolver A-lockfile Area: Cargo.lock issues A-registries Area: registries Command-fix Command-metadata Command-package Command-tree Command-update

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants