Skip to content

[WIP] Add an Inside Rust blog post for stage 0 std redesign #1582

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from

Conversation

jieyouxu
Copy link
Member

@jieyouxu jieyouxu commented Apr 17, 2025

Tip

There are intentionally a lot of WIP intermediate commits for review purposes, I will rebase once the content is ready.

Accompanying blog post for:

r? @onur-ozkan (and @Mark-Simulacrum)
cc @rust-lang/bootstrap (significant stage 0 bootstrap changes)

Rendered

@jieyouxu
Copy link
Member Author

jieyouxu commented Apr 17, 2025

Hi @senekor, do you know what this zola failure is? Or am I missing sth in the front-matter?

Run zola build
Building site...
Checking all internal links with anchors.
> Successfully checked 254 internal link(s) with anchors.
-> Creating 600 pages (0 orphan) and 2 sections
Error: Failed to build the site
Error: Failed to render 'feed.xml'
Error: Reason: Filter call 'nth' failed
Error: Reason: Filter `nth` received an incorrect type for arg `n`: got `-2` but expected a usize
Error: Process completed with exit code 1.

I guess I'm missing a path = ""...? Or what am I supposed to put there?

@senekor
Copy link
Contributor

senekor commented Apr 17, 2025

Yes, the path key is required. The format has to be "YYYY/MM/DD/whatever-you-want".

I'll try to improve the templates so they produce better error messages in this case.

@senekor
Copy link
Contributor

senekor commented Apr 17, 2025

Oh if it's an inside-rust post, that should be in the path as well. So: "inside-rust/YYYY/MM/DD/whatever".

If the date of publication is not yet known, it's recommended to use the placeholder "9999/12/31" as the date, CI will prevent that from being published accidentally.

I can definitely improve docs/guidance/tooling/error msgs here.

@@ -0,0 +1,54 @@
+++
path = "inside-rust/9999/12/31/redesigning-stage-0-std"
Copy link
Member Author

Choose a reason for hiding this comment

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

FIXME(jieyouxu): update this date when we're ready

Copy link
Member

@onur-ozkan onur-ozkan left a comment

Choose a reason for hiding this comment

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

Great work!

Just two suggestions in addition to my minor notes:

  1. It'd be helpful to mention the implementation PR.

  2. Consider showing the staging diagram to illustrate how things looked before and how they look now (the updated version is in the implementation PR).

@jieyouxu
Copy link
Member Author

It'd be helpful to mention the rust-lang/rust#119899.

I have no idea how I didn't include that when I even remember telling myself not to forget that lmao

@jieyouxu jieyouxu force-pushed the stage0-std-redesign branch from c8bc2d5 to 222f4fe Compare April 17, 2025 08:35
@jieyouxu
Copy link
Member Author

jieyouxu commented Apr 17, 2025

Changes since last review (in round 2 222f4fe):

  • Added a comparison diagram showing difference before/after the redesign.
  • Addressed nits.
  • Actually link to the stage 0 redesign PR itself.

Copy link
Member Author

Choose a reason for hiding this comment

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

TODO: having someone on t-libs and someone on t-compiler skim it and sign off that it makes sense


### Caveat: `libtest` changes

See the *Recommended config: have `compiletest` instead depend on precompiled stage 0 libtest* section below.
Copy link
Member Author

Choose a reason for hiding this comment

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

FIXME(jieyouxu) [COMPILETEST_STAGE0 1/2]: drop this if we remove the compiletest force stage0 hack

Copy link
Member Author

Choose a reason for hiding this comment

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

Dropped, but blocked on removing the hack

Comment on lines 52 to 56
## Recommended config: have `compiletest` instead depend on precompiled stage 0 libtest

`compiletest` currently depends on in-tree libtest. For workflows that involve building the compiler, this can cause `compiletest` rebuilds if stage 1 library is rebuilt as a consequence of compiler changes. If you don't intend to change libtest, you can [specify `build.compiletest-use-stage0-libtest = true` to instead have `compiletest` depend on precompiled stage 0 libtest](https://github.com/rust-lang/rust/pull/139386). That way, compiler test iterations can avoid rebuilding `compiletest` unnecessarily. This is already the default unless the `dist` profile is used.

Note that some CI jobs have `build.compiletest-use-stage0-libtest = true` set while others have `build.compiletest-use-stage0-libtest = false`, meaning that libtest programmatic API changes can require adding `cfg(bootstrap)`/`cfg(not(bootstrap))` to `compiletest`'s libtest API use sites. However, in practice we expect this to be very rare.
Copy link
Member Author

Choose a reason for hiding this comment

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

FIXME(jieyouxu) [COMPILETEST_STAGE0 3/3]: drop this once we drop the hack

Copy link
Member Author

Choose a reason for hiding this comment

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

Dropped, but blocked on removing the hack

team_url = "https://www.rust-lang.org/governance/teams/infra#team-bootstrap"
+++

# Redesigning stage 0 std
Copy link
Member

Choose a reason for hiding this comment

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

I would maybe change the title to be something like "Redesigning stage 0 during compiler bootstrapping" (i.e. give a little bit more of a hint at who will be affected, for those not familiar with what "stage 0" is)

Copy link
Member Author

@jieyouxu jieyouxu Apr 29, 2025

Choose a reason for hiding this comment

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

I might rename this to sth like "Redesigning the stage 0 compiler bootstrap sequence", not sure if that makes more sense?

Copy link
Contributor

Choose a reason for hiding this comment

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

Btw the heading should be removed, the title attribute in the frontmatter is authoritative. Otherwise it creates this:
image

Copy link
Contributor

Choose a reason for hiding this comment

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

I might rename this to sth like "Redesigning the stage 0 compiler bootstrap sequence", not sure if that makes more sense?

I agree to find a less dense title. Another (more verbose) proposal:

Redesigning rustc initial bootstrap stage to compile the standard library

or something like that. Titles are hard 😅


## Summary

We are reworking how the stage 0 bootstrap sequence works (the sequence used to build a stage 1 compiler).
Copy link
Member

Choose a reason for hiding this comment

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

Similarly, I would put a little bit of a lead up here on why this change is desired (which I think will naturally require a little bit of background to flow well).

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, previously the motivation was up front, I'll need to balance it a bit.


## What does this mean for a typical compiler workflow?

- If unstable library features are being dogfooded, some additional `cfg(bootstrap)` usages may now be needed in compiler sources.
Copy link
Member

Choose a reason for hiding this comment

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

I think this would really benefit from some example(s). For example, what would this look like for e.g. a new trait solving feature that requires some core lang items?

(Aside, not the right place for this, but this effectively means that such features actually will need to a stage 2 compiler to be built to properly test them, right?)


## Why are we making this change?

The previous stage 0 bootstrapping sequence was a source of endless confusion for compiler, library and bootstrap contributors alike, because std had to support being built by *both* a previous beta rustc and in-tree rustc, with `cfg(bootstrap)` in std sources necessary to distinguish between them. By adjusting the stage 0 bootstrap sequence to instead use a precompiled stage 0 std instead of building the in-tree std, we hope to:
Copy link
Member

Choose a reason for hiding this comment

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

Said above, a very brief summary of this could be put at the beginning.


The previous stage 0 bootstrapping sequence was a source of endless confusion for compiler, library and bootstrap contributors alike, because std had to support being built by *both* a previous beta rustc and in-tree rustc, with `cfg(bootstrap)` in std sources necessary to distinguish between them. By adjusting the stage 0 bootstrap sequence to instead use a precompiled stage 0 std instead of building the in-tree std, we hope to:

1. Simplify library development workflow to no longer need `cfg(bootstrap)`, and
Copy link
Member

Choose a reason for hiding this comment

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

Also an aside and shouldn't really be discussed here, but I personally think cfg(bootstrap) in library code is likely easier to maintain and reason about than cfg(bootstrap) in compiler code.

Though, perhaps I'm wrong, in which case I think this blog post can do better at convincing me this isn't the case.

Copy link
Member

Choose a reason for hiding this comment

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

It may be easier, but it's much more common. Instances of cfg(bootstrap) should be really rare, while in the library it's incredibly common, especially for larger refactors that were simply not done previously because it's so bad

Copy link
Member

@BoxyUwU BoxyUwU left a comment

Choose a reason for hiding this comment

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

Some random thoughts.

In general I feel like this post doesn't do too much to explain why the new system is a clearer/simpler mental model. And I think that does a bit of a disservice to all of the (great) explanation of what that actually means in terms of changes to building the compiler/library.

It's almost like the post frames this as an arbitrary change in what depends on what because it just so happens to make std's life simpler. When, as far as I can tell, the new system is just generally more coherent and how you would expect things to work.

E.g. generally when a rust crate is built by compiler X it also depends on the standard library built and shipped with/by X. With the previous bootstrapping setup the compiler was actually depending on some weird frankenstein std that was built by the beta compiler but wasn't shipped with it.

Similarly the inconsistency between "build the stage0 compiler" and "build the stage0 std library" was weird and has now been resolved (stage0 compiler is beta compiler, stage0 library was a weird frankenstein std but is now the beta std), but doesn't really seem to be mentioned anywhere in this post.

I think it would be a lot easier to understand what has changed if the post started with the motivation and talked about the shift in mental model to something that's generally more coherent. It's hard to fully understand what has changed without talking about how the change fits in with the wider "heres how things normally work".

Generally that's what my review comments are trying to get at I think 🤔 Small changes that would help build the right mental model for readers- but realistically it should probably be all together in one upfront paragraph for the motivation.

Comment on lines +17 to +19
- Before: a stage 0 (beta by default) compiler is used to build the in-tree std, which in turn is used to build the stage 1 compiler.
- After: a stage 0 (beta by default) compiler and a precompiled stage 0 std is instead used to build the stage 1 compiler.

Copy link
Member

Choose a reason for hiding this comment

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

I wonder if this could do with a short summary with less of the... I hesitate to say jargon, but something like:

Suggested change
- Before: a stage 0 (beta by default) compiler is used to build the in-tree std, which in turn is used to build the stage 1 compiler.
- After: a stage 0 (beta by default) compiler and a precompiled stage 0 std is instead used to build the stage 1 compiler.
- Before: a stage 0 (beta by default) compiler is used to build the in-tree std, which in turn is used to build the stage 1 compiler.
- After: a stage 0 (beta by default) compiler and a precompiled stage 0 std is instead used to build the stage 1 compiler.
In other words, in the typical workflow, the stage1 compiler now depends on beta std instead of the in-tree std (built by the beta compiler).

Generally I find the current "before/after" description to be a little bit hard to parse 🤔

Comment on lines +22 to +26
Notably, this means that after [redesign stage 0 std #119899](https://github.com/rust-lang/rust/pull/119899) PR lands:

- `./x {build,test,check} library --stage 0` becomes no-op, as stage 0 std is no longer the built in-tree std, and the minimum supported stage to build std is now `1`.
- Consequently, default (test, check, bench) stage values in the library profile are no longer `0`, but instead defaults to `1`.
- Some additional `cfg(bootstrap)` usages may be needed in the compiler sources for dogfooding unstable library features.
Copy link
Member

Choose a reason for hiding this comment

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

I'm not sure how you'd fit in but I wonder if it'd be helpful to say something like "stage0 now always refers to things from the beta toolchain (unless otherwise customized)".

Copy link
Contributor

Choose a reason for hiding this comment

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

"If unstable library features are being dogfooded"

dogfooding = technical lingo, which might be ok if we assume a specific target audience. Could it be reworded to be less technical?

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 can use "experimenting with unstable library features", sure.

This internal blog post is targeted towards people (compiler/library contributors) who'd already be exposed to terms like "dogfooding", but "experimenting" is less opaque, so sure.


We are reworking how the stage 0 bootstrap sequence works (the sequence used to build a stage 1 compiler).

- Before: a stage 0 (beta by default) compiler is used to build the in-tree std, which in turn is used to build the stage 1 compiler.
Copy link
Member

@BoxyUwU BoxyUwU Apr 29, 2025

Choose a reason for hiding this comment

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

I also think that having to clarify that stage0 is "technically not always the beta compiler" makes things a bit harder to understand 🤔 Almost every contributor is going to have stage0 being the beta compiler so even if its not necessarily true I do wonder if it would make sense to lie a bit with a footnote the first time and then just ignore it from then on:

Suggested change
- Before: a stage 0 (beta by default) compiler is used to build the in-tree std, which in turn is used to build the stage 1 compiler.
- Before: the beta compiler[^1] is used to build the in-tree std, which in turn is used to build the stage 1 compiler.
[^1]: In practice, rarely, the stage0 compiler can be something other than the beta compiler. This doesn't matter too much for the purpose of this change though, so we've taken the liberty of conflating the two to make it easier to explain the change to bootstrapping.

Although maybe this actually doesn't matter too much if you have a motivation section upfront discussing mental models so that there's already a nice intuition built for "stage0 == beta mostly sort of"


| Invocation | Before stage 0 std redesign | After stage 0 std redesign |
|--------------------------------------------|-------------------------------------------------------------|----------------------------------------------------------|
| `./x check library` | Checks in-tree library | Check/build/tests stage 1 library |
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
| `./x check library` | Checks in-tree library | Check/build/tests stage 1 library |
| `./x check library` | Checks in-tree library | Check stage 1 library |

or does x check library actually build and test it?

Copy link
Member Author

@jieyouxu jieyouxu Apr 29, 2025

Choose a reason for hiding this comment

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

No, that's a mistake from moving things around, good catch

| Invocation | Before stage 0 std redesign | After stage 0 std redesign |
|--------------------------------------------|-------------------------------------------------------------|----------------------------------------------------------|
| `./x check library` | Checks in-tree library | Check/build/tests stage 1 library |
| `./x {build,test} library` | Builds in-tree library, builds/tests stage 1 library | Check/build/tests stage 1 library |
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
| `./x {build,test} library` | Builds in-tree library, builds/tests stage 1 library | Check/build/tests stage 1 library |
| `./x {build,test} library` | Builds in-tree library, builds/tests stage 1 library | build/tests stage 1 library |

Notably, this means that after [redesign stage 0 std #119899](https://github.com/rust-lang/rust/pull/119899) PR lands:

- `./x {build,test,check} library --stage 0` becomes no-op, as stage 0 std is no longer the built in-tree std, and the minimum supported stage to build std is now `1`.
- Consequently, default (test, check, bench) stage values in the library profile are no longer `0`, but instead defaults to `1`.

Choose a reason for hiding this comment

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

Suggested change
- Consequently, default (test, check, bench) stage values in the library profile are no longer `0`, but instead defaults to `1`.
- Consequently, default (test, check, bench) stage values in the library profile are no longer `0`, but instead default to `1`.


## Why are we making this change?

The previous stage 0 bootstrapping sequence was a source of endless confusion for compiler, library and bootstrap contributors alike, because std had to support being built by *both* a previous beta rustc and in-tree rustc, with `cfg(bootstrap)` in std sources necessary to distinguish between them. By adjusting the stage 0 bootstrap sequence to instead use a precompiled stage 0 std instead of building the in-tree std, we hope to:
Copy link
Member

Choose a reason for hiding this comment

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

I have an alternative description of the motivation that I think more accurately captures the effect on combined compiler/library changes. Feel free to merge and integrate or so whatever with it that you want:

The compiler and standard library are tightly coupled. Intrinsics and lang items form a broad interface between the two, and whenever it is changed, both sides need to adjust. But the standard library supports being compiled with two different compilers, the in-tree compiler and the stage0 (beta) compiler. This means that all such changes require cfg(bootstrap) to support both compilers, which results in a lot of churn of anyone wanting to improve things that touch this area.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yeah, I think that's a way better motivation summary. I'll need to think about how to reword this section.

|--------------------------------------------|-------------------------------------------------------------|----------------------------------------------------------|
| `./x check library` | Checks in-tree library | Check/build/tests stage 1 library |
| `./x {build,test} library` | Builds in-tree library, builds/tests stage 1 library | Check/build/tests stage 1 library |
| `./x {check,build,test} library --stage 0` | Checks/builds/tests in-tree library | No-op in case of build, checks/tests precompiled library |

Choose a reason for hiding this comment

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

What does it mean to check the precompiled library?

Copy link
Member Author

@jieyouxu jieyouxu Apr 30, 2025

Choose a reason for hiding this comment

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

It's a no-op (arguably not exactly that, it's "does nothing"/"unsupported"?), I'll reword that

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants