build-std: explicit dependencies#3875
Conversation
|
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. |
| [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). |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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?
| ### 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. |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Still not clear to me why they need to be in the index
There was a problem hiding this comment.
This was my understanding from @ehuss's earlier feedback but maybe I've misunderstood it?
| ### 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`. |
There was a problem hiding this comment.
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
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
I would also want no_std always added if you have
[dependencies]
core.builtin = true
std.builtin = true
std.optional = trueThere was a problem hiding this comment.
I would also want no_std always added if you have
Excuse me, isn't it break test-build especially if was defined like '#![cfg_attr(not(test), no_std)]`?
There was a problem hiding this comment.
No, the test-harness always pulls std in as a dependency, unconditional #![no_std] already works fine with #[test].
There was a problem hiding this comment.
I've made some changes in 829a404, suggesting that we pass -Zcrate-attr=no_std (or some equivalent), so that #![no_std] isn't required, but don't propose removing #![no_std] entirely (it is listed as a follow-up), as that's a bigger change under t-lang's purview and I don't think it makes sense to loop in another team to this RFC's approval just for that.
There was a problem hiding this comment.
Does this mean that stabilization of this feature is blocked on stabilization of -Zcrate-attr?
And I have no problem with #![no_std] still existing.
There was a problem hiding this comment.
We could do that, or we could introduce another flag specifically for this that's easier to stabilise. #138287 tracks -Zcrate-attr, which had a spur of activity last year with a new accepted RFC, so it probably isn't too hard to push that over the finish line.
|
@rfcbot fcp concern redundant-no-std See #3875 (comment) |
|
@rfcbot fcp resolve redundant-no-std |
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 withoutbuild-std-cratesbeing 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:
build-std="always"(build-std: always #3874)build-std="compatible"(RFC not opened yet)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