Skip to content

Conversation

@davidtwco
Copy link
Member

@davidtwco davidtwco commented Oct 31, 2025

Allow users to add explicit dependencies on standard library crates in the Cargo.toml. This enables Cargo to determine which standard library crates are required by the crate graph without build-std-crates being set and for different crates to require different standard library crates.

This RFC is is part of the build-std project goal and a series of build-std RFCs:

  1. build-std context (build-std: context #3873)
  2. build-std="always" (build-std: always #3874)
  3. Explicit standard library dependencies (this RFC)
  4. build-std="compatible" (RFC not opened yet)
  5. build-std="match-profile" (RFC not opened yet)

There is also a Zulip channel where you can ask questions about any of the build-std RFCs. This series of RFCs was drafted over many months with the help of stakeholders from many Rust project teams, we thank them for their help!

There are some details that have been noted as being worth mentioning in any eventual tracking issues:

FCP

Rendered

@davidtwco davidtwco added T-cargo Relevant to the Cargo team, which will review and decide on the RFC. T-crates-io Relevant to the crates.io team, which will review and decide on the RFC. labels Oct 31, 2025
@Turbo87 Turbo87 moved this to For next meeting in crates.io team meetings Oct 31, 2025
Comment on lines 100 to 102
> When adding an explicit dependency, users > may need to adjust their code
> (removing extraneous `extern crate` statements > or root-relative paths,
> like `::std` - this will likely only be the case on the 2015 edition).
Copy link
Contributor

Choose a reason for hiding this comment

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

Looks like there was a word-wrapping issue.

Suggested change
> When adding an explicit dependency, users > may need to adjust their code
> (removing extraneous `extern crate` statements > or root-relative paths,
> like `::std` - this will likely only be the case on the 2015 edition).
> When adding an explicit dependency, users may need to adjust their code
> (removing extraneous `extern crate` statements or root-relative paths,
> like `::std` - this will likely only be the case on the 2015 edition).

Copy link
Member Author

Choose a reason for hiding this comment

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

Fixed in bbb4c6a

@ehuss
Copy link
Contributor

ehuss commented Jan 6, 2026

Thanks everyone! I think we're at a stage where we can start a proposal for FCP.

@rfcbot fcp merge cargo,crates-io

@rust-rfcbot
Copy link
Collaborator

rust-rfcbot commented Jan 6, 2026

Team member @ehuss has proposed to merge this. The next step is review by the rest of the tagged team members:

Concerns:

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rust-rfcbot rust-rfcbot added proposed-final-comment-period Currently awaiting signoff of all team members in order to enter the final comment period. disposition-merge This RFC is in PFCP or FCP with a disposition to merge it. labels Jan 6, 2026
Comment on lines +107 to +110
[build-std-always][rfcs#3874-standard-library-crate-stability]). Any explicit
standard library dependency present in any dependency table will disable the
implicit dependencies (e.g. an explicit `builtin` or `path` dependency from
`std` will disable the implicit dependencies).
Copy link
Contributor

Choose a reason for hiding this comment

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

This makes it sound like we need to scan [*dependencies] and [target.*.*dependencies] to know whether implicit deps are used but I thought it was more local than that.

Copy link
Member Author

Choose a reason for hiding this comment

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

I didn't think it would make sense for the implicit dependencies to exist on a per-table basis. If [dependencies] had a alloc = {..} and you add a [target.aarch64-linux.dependencies] table, because you don't specify alloc in that again, you get implicit std? That seemed more unintuitive to me than implicit dependencies being a global property of the manifest. Unless there's some alternative way that this could work that I've not thought of?

Comment on lines 934 to 938
### Why add standard library crates to Cargo's index?
[rationale-cargo-index]: #why-add-standard-library-crates-to-cargos-index

When Cargo builds the dependency graph, it is driven by the index (not
`Cargo.toml`), so builtin dependencies need to be included in the index.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this about adding them to the index (as top-level packages), which isn't needed, or adding dependencies on the standard library to the index format?

Copy link
Member Author

Choose a reason for hiding this comment

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

Just the latter, clarified in 81298d9

Copy link
Contributor

Choose a reason for hiding this comment

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

Still not clear to me why they need to be in the index

Comment on lines +1086 to +1113
### Replace `#![no_std]` as the source-of-truth for whether a crate depends on `std`
[future-replace-no_std]: #replace-no_std-as-the-source-of-truth-for-whether-a-crate-depends-on-std

Crates can currently use the crate attribute `#![no_std]` to indicate a lack of
dependency on `std`. Introducing `build-std.crates` from [RFC #3874][rfcs#3874]
or explicit dependencies would add a second way for the user to indicate a lack
of dependency on the standard library. It could therefore be desirable to
deprecate `#![no_std]` so that there remains only a single way to express a
dependency on the standard library.

`#![no_std]` serves two purposes - it stops the compiler from adding `std` to
the extern prelude and it prevents the user from depending on anything from
`std` accidentally. rustc's default behaviour of loading `std` when not
explicitly provided the crate via an `--extern` flag should be preserved for
backwards-compatibility with existing direct invocations of rustc.

Initially, if a crate has the `#![no_std]` attribute and has implicit
dependencies on the standard library in its `Cargo.toml`, a lint could be
emitted to suggest that their Cargo dependencies are adjusted.

Eventually, `#![no_std]` could instead become a compiler flag which would
indicate to the compiler that `std` should not be loaded by default and that
`core`'s prelude should be used instead. Cargo would use this flag when driving
rustc, providing explicit paths to the newly-built or pre-built standard library
crates, just as with any other dependency.

In addition, uses of the `#![no_std]` attribute could be migrated to denying a
lint which would prevent use of items from `std`.
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this saying that if I only depend on core.builtin = true then I still have to put in #![no_std]? If so, that seems wrong to me

Copy link
Member Author

Choose a reason for hiding this comment

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

I agree that I'd prefer if that wasn't necessary.

Migrating away from #![no_std] is a bit tricky just because it exists in crates today and we'd need those crates to continue to compile with rustc if Cargo isn't being used.

I investigated whether rustc could lazily load the standard library and discard the loaded crate if it wasn't used, so that not using std was sufficient for making a crate no_std (and then interpret #![no_std] to a lint to enforce this, which would be useful anyway, and is a relatively easy migration to implement over an edition). It isn't possible, so we need some explicit indication of whether a crate is no_std or not. #![no_std] does that and we have it already, but a compiler flag would be nicer now that Cargo would know when to pass it. Cargo could pass -Zcrate-attr=no_std if there was only core.builtin=true, but that doesn't help too much with the not-using-Cargo case. We've also never had a "replace this line of code with a flag" migration before, which is why I've left this to a future possibility.

It's not a perfect part of the proposal, but it works today and leaves the door open to improvements later.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would like to see -Zcrater-attr=no_std (or some other solution with the same ends) be part of this if it is core-only or alloc-only in Cargo.toml and would need a strong justification for why we shouldn't.

For non-Cargo use cases, there is some other build system that can do similar.

In terms of migration, the user is already changing their Cargo.toml for this, having them remove #![no_std] at the same time does not seem like a big deal.

@ehuss ehuss moved this from RFC needs review to FCP merge in Cargo status tracker Jan 13, 2026
@epage
Copy link
Contributor

epage commented Jan 20, 2026

@rfcbot fcp concern redundant-no-std

See #3875 (comment)

@Turbo87 Turbo87 moved this from For next meeting to Backlog in crates.io team meetings Jan 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

disposition-merge This RFC is in PFCP or FCP with a disposition to merge it. proposed-final-comment-period Currently awaiting signoff of all team members in order to enter the final comment period. T-cargo Relevant to the Cargo team, which will review and decide on the RFC. T-crates-io Relevant to the crates.io team, which will review and decide on the RFC.

Projects

Status: FCP merge

Development

Successfully merging this pull request may close these issues.