Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit b3b368a

Browse files
committedJan 5, 2025
Auto merge of #135127 - Kobzol:rustc-dev-guide-sync, r=BoxyUwU
rustc-dev-guide subtree update This PR performs the first update of rustc-dev-guide code from its repository. r? `@BoxyUwU`
2 parents 3323bbe + 515d7eb commit b3b368a

20 files changed

+1249
-433
lines changed
 

‎src/doc/rustc-dev-guide/README.md

Lines changed: 18 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -70,46 +70,21 @@ $ ENABLE_LINKCHECK=1 mdbook serve
7070
We use `mdbook-toc` to auto-generate TOCs for long sections. You can invoke the preprocessor by
7171
including the `<!-- toc -->` marker at the place where you want the TOC.
7272

73-
## How to fix toolstate failures
74-
75-
> [!NOTE]
76-
> Currently, we do not track the rustc-dev-guide toolstate due to
77-
> [spurious failures](https://github.com/rust-lang/rust/pull/71731),
78-
> but we leave these instructions for when we do it again in the future.
79-
80-
1. You will get a ping from the toolstate commit. e.g. https://github.com/rust-lang-nursery/rust-toolstate/commit/8ffa0e4c30ac9ba8546b7046e5c4ccc2b96ebdd4
81-
82-
2. The commit contains a link to the PR that caused the breakage. e.g. https://github.com/rust-lang/rust/pull/64321
83-
84-
3. If you go to that PR's thread, there is a post from bors with a link to the CI status: https://github.com/rust-lang/rust/pull/64321#issuecomment-529763807
85-
86-
4. Follow the check-actions link to get to the Actions page for that build
87-
88-
5. There will be approximately 1 billion different jobs for the build. They are for different configurations and platforms. The rustc-dev-guide build only runs on the Linux x86_64-gnu-tools job. So click on that job in the list, which is about 60% down in the list.
89-
90-
6. Click the Run build step in the job to get the console log for the step.
91-
92-
7. Click on the log and Ctrl-f to get a search box in the log
93-
94-
8. Search for rustc-dev-guide. This gets you to the place where the links are checked. It is usually ~11K lines into the log.
95-
96-
9. Look at the links in the log near that point in the log
97-
98-
10. Fix those links in the rustc-dev-guide (by making a PR in the rustc-dev-guide repo)
99-
100-
11. Make a PR on the rust-lang/rust repo to update the rustc-dev-guide git submodule in src/docs/rustc-dev-guide.
101-
To make a PR, the following steps are useful.
102-
103-
```bash
104-
# Assuming you already cloned the rust-lang/rust repo and you're in the correct directory
105-
git submodule update --remote src/doc/rustc-dev-guide
106-
git add -u
107-
git commit -m "Update rustc-dev-guide"
108-
# Note that you can use -i, which is short for --incremental, in the following command
109-
./x test --incremental src/doc/rustc-dev-guide # This is optional and should succeed anyway
110-
# Open a PR in rust-lang/rust
111-
```
112-
113-
12. Wait for PR to merge
114-
115-
Voilà!
73+
## Synchronizing josh subtree with rustc
74+
75+
This repository is linked to `rust-lang/rust` as a [josh](https://josh-project.github.io/josh/intro.html) subtree. You can use the following commands to synchronize the subtree in both directions.
76+
77+
### Pull changes from `rust-lang/rust` into this repository
78+
1) Checkout a new branch that will be used to create a PR into `rust-lang/rustc-dev-guide`
79+
2) Run the pull command
80+
```
81+
$ cargo run --manifest-path josh-sync/Cargo.toml rustc-pull
82+
```
83+
3) Push the branch to your fork and create a PR into `rustc-dev-guide`
84+
85+
### Push changes from this repository into `rust-lang/rust`
86+
1) Run the push command to create a branch named `<branch-name>` in a `rustc` fork under the `<gh-username>` account
87+
```
88+
$ cargo run --manifest-path josh-sync/Cargo.toml rustc-push <branch-name> <gh-username>
89+
```
90+
2) Create a PR from `<branch-name>` into `rust-lang/rust`

‎src/doc/rustc-dev-guide/josh-sync/Cargo.lock

Lines changed: 430 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "josh-sync"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
anyhow = "1.0.95"
8+
clap = { version = "4.5.21", features = ["derive"] }
9+
directories = "5"
10+
xshell = "0.2.6"
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# Git josh sync
2+
This utility serves for syncing the josh git subtree to and from the rust-lang/rust repository.
3+
4+
See CLI help for usage.
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use clap::Parser;
2+
use crate::sync::GitSync;
3+
4+
mod sync;
5+
6+
#[derive(clap::Parser)]
7+
enum Args {
8+
/// Pull changes from the main `rustc` repository.
9+
/// This creates new commits that should be then merged into `rustc-dev-guide`.
10+
RustcPull,
11+
/// Push changes from `rustc-dev-guide` to the given `branch` of a `rustc` fork under the given
12+
/// GitHub `username`.
13+
/// The pushed branch should then be merged into the `rustc` repository.
14+
RustcPush {
15+
branch: String,
16+
github_username: String
17+
}
18+
}
19+
20+
fn main() -> anyhow::Result<()> {
21+
let args = Args::parse();
22+
let sync = GitSync::from_current_dir()?;
23+
match args {
24+
Args::RustcPull => {
25+
sync.rustc_pull(None)?;
26+
}
27+
Args::RustcPush { github_username, branch } => {
28+
sync.rustc_push(github_username, branch)?;
29+
}
30+
}
31+
Ok(())
32+
}
Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
use std::ops::Not;
2+
use std::path::PathBuf;
3+
use std::{env, net, process};
4+
use std::io::Write;
5+
use std::time::Duration;
6+
use anyhow::{anyhow, bail, Context};
7+
use xshell::{cmd, Shell};
8+
9+
/// Used for rustc syncs.
10+
const JOSH_FILTER: &str = ":/src/doc/rustc-dev-guide";
11+
const JOSH_PORT: u16 = 42042;
12+
const UPSTREAM_REPO: &str = "rust-lang/rust";
13+
14+
pub struct GitSync {
15+
dir: PathBuf,
16+
}
17+
18+
/// This code was adapted from the miri repository
19+
/// (https://github.com/rust-lang/miri/blob/6a68a79f38064c3bc30617cca4bdbfb2c336b140/miri-script/src/commands.rs#L236).
20+
impl GitSync {
21+
pub fn from_current_dir() -> anyhow::Result<Self> {
22+
Ok(Self {
23+
dir: std::env::current_dir()?
24+
})
25+
}
26+
27+
pub fn rustc_pull(&self, commit: Option<String>) -> anyhow::Result<()> {
28+
let sh = Shell::new()?;
29+
sh.change_dir(&self.dir);
30+
let commit = commit.map(Ok).unwrap_or_else(|| {
31+
let rust_repo_head =
32+
cmd!(sh, "git ls-remote https://github.com/{UPSTREAM_REPO}/ HEAD").read()?;
33+
rust_repo_head
34+
.split_whitespace()
35+
.next()
36+
.map(|front| front.trim().to_owned())
37+
.ok_or_else(|| anyhow!("Could not obtain Rust repo HEAD from remote."))
38+
})?;
39+
// Make sure the repo is clean.
40+
if cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty().not() {
41+
bail!("working directory must be clean before performing rustc pull");
42+
}
43+
// Make sure josh is running.
44+
let josh = Self::start_josh()?;
45+
let josh_url =
46+
format!("http://localhost:{JOSH_PORT}/{UPSTREAM_REPO}.git@{commit}{JOSH_FILTER}.git");
47+
48+
// Update rust-version file. As a separate commit, since making it part of
49+
// the merge has confused the heck out of josh in the past.
50+
// We pass `--no-verify` to avoid running git hooks.
51+
// We do this before the merge so that if there are merge conflicts, we have
52+
// the right rust-version file while resolving them.
53+
sh.write_file("rust-version", format!("{commit}\n"))?;
54+
const PREPARING_COMMIT_MESSAGE: &str = "Preparing for merge from rustc";
55+
cmd!(sh, "git commit rust-version --no-verify -m {PREPARING_COMMIT_MESSAGE}")
56+
.run()
57+
.context("FAILED to commit rust-version file, something went wrong")?;
58+
59+
// Fetch given rustc commit.
60+
cmd!(sh, "git fetch {josh_url}")
61+
.run()
62+
.inspect_err(|_| {
63+
// Try to un-do the previous `git commit`, to leave the repo in the state we found it.
64+
cmd!(sh, "git reset --hard HEAD^")
65+
.run()
66+
.expect("FAILED to clean up again after failed `git fetch`, sorry for that");
67+
})
68+
.context("FAILED to fetch new commits, something went wrong (committing the rust-version file has been undone)")?;
69+
70+
// This should not add any new root commits. So count those before and after merging.
71+
let num_roots = || -> anyhow::Result<u32> {
72+
Ok(cmd!(sh, "git rev-list HEAD --max-parents=0 --count")
73+
.read()
74+
.context("failed to determine the number of root commits")?
75+
.parse::<u32>()?)
76+
};
77+
let num_roots_before = num_roots()?;
78+
79+
// Merge the fetched commit.
80+
const MERGE_COMMIT_MESSAGE: &str = "Merge from rustc";
81+
cmd!(sh, "git merge FETCH_HEAD --no-verify --no-ff -m {MERGE_COMMIT_MESSAGE}")
82+
.run()
83+
.context("FAILED to merge new commits, something went wrong")?;
84+
85+
// Check that the number of roots did not increase.
86+
if num_roots()? != num_roots_before {
87+
bail!("Josh created a new root commit. This is probably not the history you want.");
88+
}
89+
90+
drop(josh);
91+
Ok(())
92+
}
93+
94+
pub fn rustc_push(&self, github_user: String, branch: String) -> anyhow::Result<()> {
95+
let sh = Shell::new()?;
96+
sh.change_dir(&self.dir);
97+
let base = sh.read_file("rust-version")?.trim().to_owned();
98+
// Make sure the repo is clean.
99+
if cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty().not() {
100+
bail!("working directory must be clean before running `rustc-push`");
101+
}
102+
// Make sure josh is running.
103+
let josh = Self::start_josh()?;
104+
let josh_url =
105+
format!("http://localhost:{JOSH_PORT}/{github_user}/rust.git{JOSH_FILTER}.git");
106+
107+
// Find a repo we can do our preparation in.
108+
if let Ok(rustc_git) = env::var("RUSTC_GIT") {
109+
// If rustc_git is `Some`, we'll use an existing fork for the branch updates.
110+
sh.change_dir(rustc_git);
111+
} else {
112+
// Otherwise, do this in the local repo.
113+
println!(
114+
"This will pull a copy of the rust-lang/rust history into this checkout, growing it by about 1GB."
115+
);
116+
print!(
117+
"To avoid that, abort now and set the `RUSTC_GIT` environment variable to an existing rustc checkout. Proceed? [y/N] "
118+
);
119+
std::io::stdout().flush()?;
120+
let mut answer = String::new();
121+
std::io::stdin().read_line(&mut answer)?;
122+
if answer.trim().to_lowercase() != "y" {
123+
std::process::exit(1);
124+
}
125+
};
126+
// Prepare the branch. Pushing works much better if we use as base exactly
127+
// the commit that we pulled from last time, so we use the `rust-version`
128+
// file to find out which commit that would be.
129+
println!("Preparing {github_user}/rust (base: {base})...");
130+
if cmd!(sh, "git fetch https://github.com/{github_user}/rust {branch}")
131+
.ignore_stderr()
132+
.read()
133+
.is_ok()
134+
{
135+
println!(
136+
"The branch '{branch}' seems to already exist in 'https://github.com/{github_user}/rust'. Please delete it and try again."
137+
);
138+
std::process::exit(1);
139+
}
140+
cmd!(sh, "git fetch https://github.com/{UPSTREAM_REPO} {base}").run()?;
141+
cmd!(sh, "git push https://github.com/{github_user}/rust {base}:refs/heads/{branch}")
142+
.ignore_stdout()
143+
.ignore_stderr() // silence the "create GitHub PR" message
144+
.run()?;
145+
println!();
146+
147+
// Do the actual push.
148+
sh.change_dir(&self.dir);
149+
println!("Pushing changes...");
150+
cmd!(sh, "git push {josh_url} HEAD:{branch}").run()?;
151+
println!();
152+
153+
// Do a round-trip check to make sure the push worked as expected.
154+
cmd!(sh, "git fetch {josh_url} {branch}").ignore_stderr().read()?;
155+
let head = cmd!(sh, "git rev-parse HEAD").read()?;
156+
let fetch_head = cmd!(sh, "git rev-parse FETCH_HEAD").read()?;
157+
if head != fetch_head {
158+
bail!(
159+
"Josh created a non-roundtrip push! Do NOT merge this into rustc!\n\
160+
Expected {head}, got {fetch_head}."
161+
);
162+
}
163+
println!(
164+
"Confirmed that the push round-trips back to rustc-dev-guide properly. Please create a rustc PR:"
165+
);
166+
println!(
167+
// Open PR with `subtree update` title to silence the `no-merges` triagebot check
168+
" https://github.com/{UPSTREAM_REPO}/compare/{github_user}:{branch}?quick_pull=1&title=Rustc+dev+guide+subtree+update&body=r?+@ghost"
169+
);
170+
171+
drop(josh);
172+
Ok(())
173+
}
174+
175+
fn start_josh() -> anyhow::Result<impl Drop> {
176+
// Determine cache directory.
177+
let local_dir = {
178+
let user_dirs =
179+
directories::ProjectDirs::from("org", "rust-lang", "rustc-dev-guide-josh").unwrap();
180+
user_dirs.cache_dir().to_owned()
181+
};
182+
183+
// Start josh, silencing its output.
184+
let mut cmd = process::Command::new("josh-proxy");
185+
cmd.arg("--local").arg(local_dir);
186+
cmd.arg("--remote").arg("https://github.com");
187+
cmd.arg("--port").arg(JOSH_PORT.to_string());
188+
cmd.arg("--no-background");
189+
cmd.stdout(process::Stdio::null());
190+
cmd.stderr(process::Stdio::null());
191+
let josh = cmd.spawn().context("failed to start josh-proxy, make sure it is installed")?;
192+
193+
// Create a wrapper that stops it on drop.
194+
struct Josh(process::Child);
195+
impl Drop for Josh {
196+
fn drop(&mut self) {
197+
#[cfg(unix)]
198+
{
199+
// Try to gracefully shut it down.
200+
process::Command::new("kill")
201+
.args(["-s", "INT", &self.0.id().to_string()])
202+
.output()
203+
.expect("failed to SIGINT josh-proxy");
204+
// Sadly there is no "wait with timeout"... so we just give it some time to finish.
205+
std::thread::sleep(Duration::from_millis(100));
206+
// Now hopefully it is gone.
207+
if self.0.try_wait().expect("failed to wait for josh-proxy").is_some() {
208+
return;
209+
}
210+
}
211+
// If that didn't work (or we're not on Unix), kill it hard.
212+
eprintln!(
213+
"I have to kill josh-proxy the hard way, let's hope this does not break anything."
214+
);
215+
self.0.kill().expect("failed to SIGKILL josh-proxy");
216+
}
217+
}
218+
219+
// Wait until the port is open. We try every 10ms until 1s passed.
220+
for _ in 0..100 {
221+
// This will generally fail immediately when the port is still closed.
222+
let josh_ready = net::TcpStream::connect_timeout(
223+
&net::SocketAddr::from(([127, 0, 0, 1], JOSH_PORT)),
224+
Duration::from_millis(1),
225+
);
226+
if josh_ready.is_ok() {
227+
return Ok(Josh(josh));
228+
}
229+
// Not ready yet.
230+
std::thread::sleep(Duration::from_millis(10));
231+
}
232+
bail!("Even after waiting for 1s, josh-proxy is still not available.")
233+
}
234+
}

‎src/doc/rustc-dev-guide/rust-version

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dcfa38fe234de9304169afc6638e81d0dd222c06

‎src/doc/rustc-dev-guide/src/SUMMARY.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,13 @@
134134

135135
- [Prologue](./part-4-intro.md)
136136
- [Generic parameter definitions](./generic_parameters_summary.md)
137-
- [Implementation nuances of early/late bound parameters](./early-late-bound-params/early-late-bound-implementation-nuances.md)
138-
- [Interactions with turbofishing](./early-late-bound-params/turbofishing-and-early-late-bound.md)
137+
- [`EarlyBinder` and instantiating parameters](./ty_module/early_binder.md)
138+
- [Binders and Higher ranked regions](./ty_module/binders.md)
139+
- [Instantiating binders](./ty_module/instantiating_binders.md)
140+
- [Early vs Late bound parameters](./early_late_parameters.md)
139141
- [The `ty` module: representing types](./ty.md)
140142
- [ADTs and Generic Arguments](./ty_module/generic_arguments.md)
141143
- [Parameter types/consts/regions](./ty_module/param_ty_const_regions.md)
142-
- [`EarlyBinder` and instantiating parameters](./ty_module/early_binder.md)
143-
- [`Binder` and Higher ranked regions](./ty_module/binders.md)
144-
- [Instantiating binders](./ty_module/instantiating_binders.md)
145144
- [`TypeFolder` and `TypeFoldable`](./ty-fold.md)
146145
- [Parameter Environments](./param_env/param_env_summary.md)
147146
- [What is it?](./param_env/param_env_what_is_it.md)

‎src/doc/rustc-dev-guide/src/early-late-bound-params/early-late-bound-implementation-nuances.md

Lines changed: 0 additions & 197 deletions
This file was deleted.

‎src/doc/rustc-dev-guide/src/early-late-bound-params/turbofishing-and-early-late-bound.md

Lines changed: 0 additions & 125 deletions
This file was deleted.

‎src/doc/rustc-dev-guide/src/early_late_parameters.md

Lines changed: 424 additions & 0 deletions
Large diffs are not rendered by default.

‎src/doc/rustc-dev-guide/src/external-repos.md

Lines changed: 26 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,24 @@
33
The `rust-lang/rust` git repository depends on several other repos in the `rust-lang` organization.
44
There are three main ways we use dependencies:
55
1. As a Cargo dependency through crates.io (e.g. `rustc-rayon`)
6-
2. As a git subtree (e.g. `clippy`)
6+
2. As a git (e.g. `clippy`) or a [josh] (e.g. `miri`) subtree
77
3. As a git submodule (e.g. `cargo`)
88

9-
As a general rule, use crates.io for libraries that could be useful for others in the ecosystem; use
10-
subtrees for tools that depend on compiler internals and need to be updated if there are breaking
11-
changes; and use submodules for tools that are independent of the compiler.
9+
As a general rule:
10+
- Use crates.io for libraries that could be useful for others in the ecosystem
11+
- Use subtrees for tools that depend on compiler internals and need to be updated if there are breaking
12+
changes
13+
- Use submodules for tools that are independent of the compiler
1214

13-
## External Dependencies (subtree)
15+
## External Dependencies (subtrees)
1416

15-
As a developer to this repository, you don't have to treat the following external projects
16-
differently from other crates that are directly in this repo:
17+
The following external projects are managed using some form of a `subtree`:
1718

18-
* [Clippy](https://github.com/rust-lang/rust-clippy)
19-
* [Miri]
19+
* [clippy](https://github.com/rust-lang/rust-clippy)
20+
* [miri](https://github.com/rust-lang/miri)
2021
* [rustfmt](https://github.com/rust-lang/rustfmt)
2122
* [rust-analyzer](https://github.com/rust-lang/rust-analyzer)
22-
23-
[Miri]: https://github.com/rust-lang/miri
23+
* [rustc_codegen_cranelift](https://github.com/rust-lang/rustc_codegen_cranelift)
2424

2525
In contrast to `submodule` dependencies
2626
(see below for those), the `subtree` dependencies are just regular files and directories which can
@@ -29,6 +29,20 @@ to these tools should be filed against the tools directly in their respective
2929
upstream repositories. The exception is that when rustc changes are required to
3030
implement a new tool feature or test, that should happen in one collective rustc PR.
3131

32+
`subtree` dependencies are currently managed by two distinct approaches:
33+
34+
* Using `git subtree`
35+
* `clippy` ([sync guide](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/sync.html#performing-the-sync-from-rust-langrust-to-clippy))
36+
* `rustfmt`
37+
* `rustc_codegen_cranelift` ([sync script](https://github.com/rust-lang/rustc_codegen_cranelift/blob/113af154d459e41b3dc2c5d7d878e3d3a8f33c69/scripts/rustup.sh#L7))
38+
* Using the [josh] tool
39+
* `miri` ([sync guide](https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#advanced-topic-syncing-with-the-rustc-repo))
40+
* `rust-analyzer` ([sync script](https://github.com/rust-lang/rust-analyzer/blob/2e13684be123eca7181aa48e043e185d8044a84a/xtask/src/release.rs#L147))
41+
42+
The [josh] tool is an alternative to git subtrees, which manages git history in a different way and scales better to larger repositories. Specific tooling is required to work with josh, you can check out the `miri` or `rust-analyzer` scripts linked above for inspiration. If you want to migrate a subtree from `git subtree` to josh, you can check out [this guide](https://hackmd.io/7pOuxnkdQDaL1Y1FQr65xg).
43+
44+
Below you can find a guide on how to perform push and pull synchronization with the main rustc repo using `git subtree`, although these instructions might differ repo from repo.
45+
3246
### Synchronizing a subtree
3347

3448
Periodically the changes made to subtree based dependencies need to be synchronized between this
@@ -84,7 +98,6 @@ Now you're done, the `src/tools/clippy` directory behaves as if Clippy were
8498
part of the rustc monorepo, so no one but you (or others that synchronize
8599
subtrees) actually needs to use `git subtree`.
86100

87-
88101
## External Dependencies (submodules)
89102

90103
Building Rust will also use external git repositories tracked using [git
@@ -111,3 +124,4 @@ the week leading up to the beta cut.
111124
[The Rust Reference]: https://github.com/rust-lang/reference/
112125
[toolstate website]: https://rust-lang-nursery.github.io/rust-toolstate/
113126
[Toolstate chapter]: https://forge.rust-lang.org/infra/toolstate.html
127+
[josh]: https://josh-project.github.io/josh/intro.html

‎src/doc/rustc-dev-guide/src/generic_parameters_summary.md

Lines changed: 1 addition & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -25,42 +25,4 @@ Interestingly, `ty::Generics` does not currently contain _every_ generic paramet
2525
[ch_representing_types]: ./ty.md
2626
[`ty::Generics`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Generics.html
2727
[`GenericParamDef`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/generics/struct.GenericParamDef.html
28-
29-
# Early vs Late bound parameters
30-
31-
32-
```rust
33-
fn foo<'a, T>(b: &'a T) -> &'a T { b }
34-
// ^^ ^early bound
35-
// ^^
36-
// ^^late bound
37-
```
38-
39-
Generally when referring to an item with generic parameters you must specify a list of generic arguments corresponding to the item's generic parameters. In some cases it is permitted to elide these arguments but still, implicitly, a set of arguments are provided (e.g. `Vec::default()` desugars to `Vec::<_>::default()`).
40-
41-
For functions this is not necessarily the case, for example if we take the function `foo` from the example above and write the following code:
42-
```rust
43-
fn main() {
44-
let f = foo::<_>;
45-
46-
let b = String::new();
47-
let c = String::new();
48-
49-
f(&b);
50-
drop(b);
51-
f(&c);
52-
}
53-
```
54-
55-
This code compiles perfectly fine even though there is no single lifetime that could possibly be specified in `foo::<_>` that would allow for both
56-
the `&b` and `&c` borrows to be used as arguments (note: the `drop(b)` line forces the `&b` borrow to be shorter than the `&c` borrow). This works because the `'a` lifetime is _late bound_.
57-
58-
A generic parameter being late bound means that when we write `foo::<_>` we do not actually provide an argument for that parameter, instead we wait until _calling_ the function to provide the generic argument. In the above example this means that we are doing something like `f::<'_>(&b);` and `f::<'_>(&c);` (although in practice we do not actually support turbofishing late bound parameters in this manner)
59-
60-
It may be helpful to think of "early bound parameter" or "late bound parameter" as meaning "early provided parameter" and "late provided parameter", i.e. we provide the argument to the parameter either early (when naming the function) or late (when calling it).
61-
62-
Late bound parameters on functions are tracked with a [`Binder`] when accessing the signature of the function, this can be done with the [`fn_sig`] query. For more information of binders see the [chapter on `Binder`s ][ch_binders].
63-
64-
[`Binder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/binder/struct.Binder.html
65-
[`fn_sig`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.fn_sig
66-
[ch_binders]: ./ty_module/binders.md
28+
[ch_binders]: ./ty_module/binders.md

‎src/doc/rustc-dev-guide/src/method-lookup.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ imported to use an inherent method, they are associated with the type
6767
itself (note that inherent impls can only be defined in the same
6868
crate as the type itself).
6969

70+
<!--
7071
FIXME: Inherent candidates are not always derived from impls. If you
7172
have a trait object, such as a value of type `Box<ToString>`, then the
7273
trait methods (`to_string()`, in this case) are inherently associated
@@ -76,7 +77,8 @@ to change: when DST's "impl Trait for Trait" is complete, trait object
7677
dispatch could be subsumed into trait matching, and the type parameter
7778
behavior should be reconsidered in light of where clauses.
7879
79-
TODO: Is this FIXME still accurate?
80+
Is this still accurate?
81+
-->
8082

8183
**Extension candidates** are derived from imported traits. If I have
8284
the trait `ToString` imported, and I call `to_string()` as a method,

‎src/doc/rustc-dev-guide/src/solve/normalization.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Normalization in the new solver
22

3+
> FIXME: Normalization has been changed significantly since this chapter was written.
4+
35
With the new solver we've made some fairly significant changes to normalization when compared
46
to the existing implementation.
57

@@ -52,12 +54,14 @@ before assigning the resulting rigid type to an inference variable. This is used
5254
This has to be used whenever we match on the value of some type, both inside
5355
and outside of the trait solver.
5456

57+
<!--
5558
FIXME: structure, maybe we should have an "alias handling" chapter instead as
5659
talking about normalization without explaining that doesn't make too much
5760
sense.
5861
5962
FIXME: it is likely that this will subtly change again by mostly moving structural
6063
normalization into `NormalizesTo`.
64+
-->
6165

6266
[structural_norm]: https://github.com/rust-lang/rust/blob/2627e9f3012a97d3136b3e11bf6bd0853c38a534/compiler/rustc_trait_selection/src/solve/alias_relate.rs#L140-L175
6367
[structural-relate]: https://github.com/rust-lang/rust/blob/a0569fa8f91b5271e92d2f73fd252de7d3d05b9c/compiler/rustc_trait_selection/src/solve/alias_relate.rs#L88-L107
@@ -72,11 +76,13 @@ possible. However, this only works for aliases referencing bound variables if th
7276
not ambiguous as we're unable to replace the alias with a corresponding inference
7377
variable without leaking universes.
7478

79+
<!--
7580
FIXME: we previously had to also be careful about instantiating the new inference
7681
variable with another normalizeable alias. Due to our recent changes to generalization,
7782
this should not be the case anymore. Equating an inference variable with an alias
7883
now always uses `AliasRelate` to fully normalize the alias before instantiating the
7984
inference variable: [source][generalize-no-alias]
85+
-->
8086

8187
[generalize-no-alias]: https://github.com/rust-lang/rust/blob/a0569fa8f91b5271e92d2f73fd252de7d3d05b9c/compiler/rustc_infer/src/infer/relate/generalize.rs#L353-L358
8288

‎src/doc/rustc-dev-guide/src/solve/opaque-types.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ Finally, we check whether the item bounds of the opaque hold for the expected ty
6060
[eq-prev]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L51-L59
6161
[insert-storage]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L68
6262
[item-bounds-ck]: https://github.com/rust-lang/rust/blob/384d26fc7e3bdd7687cc17b2662b091f6017ec2a/compiler/rustc_trait_selection/src/solve/normalizes_to/opaque_types.rs#L69-L74
63+
6364
[^1]: FIXME: this should ideally only result in a unique candidate given that we require the args to be placeholders and regions are always inference vars
6465
[^2]: FIXME: why do we check whether the expected type is rigid for this.
6566

@@ -101,6 +102,7 @@ The handling of member constraints does not change in the new solver. See the
101102

102103
FIXME: We need to continue to support calling methods on still unconstrained
103104
opaque types in their defining scope. It's unclear how to best do this.
105+
104106
```rust
105107
use std::future::Future;
106108
use futures::FutureExt;

‎src/doc/rustc-dev-guide/src/tests/compiletest.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,46 @@ $ COMPILETEST_FORCE_STAGE0=1 x test --stage 0 tests/run-make/<test-name>
441441

442442
Of course, some tests will not successfully *run* in this way.
443443

444+
#### Using rust-analyzer with `rmake.rs`
445+
446+
Like other test programs, the `rmake.rs` scripts used by run-make tests do not
447+
have rust-analyzer integration by default.
448+
449+
To work around this when working on a particular test, temporarily create a
450+
`Cargo.toml` file in the test's directory
451+
(e.g. `tests/run-make/sysroot-crates-are-unstable/Cargo.toml`)
452+
with these contents:
453+
454+
<div class="warning">
455+
Be careful not to add this `Cargo.toml` or its `Cargo.lock` to your actual PR!
456+
</div>
457+
458+
```toml
459+
# Convince cargo that this isn't part of an enclosing workspace.
460+
[workspace]
461+
462+
[package]
463+
name = "rmake"
464+
version = "0.1.0"
465+
edition = "2021"
466+
467+
[dependencies]
468+
run_make_support = { path = "../../../src/tools/run-make-support" }
469+
470+
[[bin]]
471+
name = "rmake"
472+
path = "rmake.rs"
473+
```
474+
475+
Then add a corresponding entry to `"rust-analyzer.linkedProjects"`
476+
(e.g. in `.vscode/settings.json`):
477+
478+
```json
479+
"rust-analyzer.linkedProjects": [
480+
"tests/run-make/sysroot-crates-are-unstable/Cargo.toml"
481+
],
482+
```
483+
444484
#### Using Makefiles (legacy)
445485

446486
<div class="warning">

‎src/doc/rustc-dev-guide/src/tests/directives.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
<!-- toc -->
44

5-
> **FIXME(jieyouxu)** completely revise this chapter.
5+
<!--
6+
FIXME(jieyouxu) completely revise this chapter.
7+
-->
68

79
Directives are special comments that tell compiletest how to build and interpret
810
a test. They must appear before the Rust source in the test. They may also
@@ -248,10 +250,11 @@ Consider writing the test as a proper incremental test instead.
248250
|-------------|--------------------------------------------------------------|------------------------------------------|---------------------------|
249251
| `doc-flags` | Flags passed to `rustdoc` when building the test or aux file | `rustdoc`, `js-doc-test`, `rustdoc-json` | Any valid `rustdoc` flags |
250252

251-
> **FIXME(rustdoc)**: what does `check-test-line-numbers-match` do?
252-
>
253-
> Asked in
254-
> <https://rust-lang.zulipchat.com/#narrow/stream/266220-t-rustdoc/topic/What.20is.20the.20.60check-test-line-numbers-match.60.20directive.3F>.
253+
<!--
254+
**FIXME(rustdoc)**: what does `check-test-line-numbers-match` do?
255+
Asked in
256+
<https://rust-lang.zulipchat.com/#narrow/stream/266220-t-rustdoc/topic/What.20is.20the.20.60check-test-line-numbers-match.60.20directive.3F>.
257+
-->
255258

256259
### Pretty printing
257260

‎src/doc/rustc-dev-guide/src/traits/chalk.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ stream and say hello!
1010
[Types team]: https://github.com/rust-lang/types-team
1111
[`#t-types`]: https://rust-lang.zulipchat.com/#narrow/stream/144729-t-types
1212

13-
The new-style trait solver is based on the work done in [chalk][chalk]. Chalk
13+
The new-style trait solver is based on the work done in [chalk]. Chalk
1414
recasts Rust's trait system explicitly in terms of logic programming. It does
1515
this by "lowering" Rust code into a kind of logic program we can then execute
1616
queries against.
@@ -30,7 +30,7 @@ You can read more about chalk itself in the
3030
## Ongoing work
3131
The design of the new-style trait solving happens in two places:
3232

33-
**chalk**. The [chalk][chalk] repository is where we experiment with new ideas
33+
**chalk**. The [chalk] repository is where we experiment with new ideas
3434
and designs for the trait system.
3535

3636
**rustc**. Once we are happy with the logical rules, we proceed to

‎src/doc/rustc-dev-guide/src/ty_module/early_binder.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@ fn bar(foo: Foo<u32, f32>) {
4747

4848
In the compiler the `instantiate` call for this is done in [`FieldDef::ty`] ([src][field_def_ty_src]), at some point during type checking `bar` we will wind up calling `FieldDef::ty(x, &[u32, f32])` in order to obtain the type of `foo.x`.
4949

50-
**Note on indices:** It is possible for the indices in `Param` to not match with what the `EarlyBinder` binds. For
51-
example, the index could be out of bounds or it could be the index of a lifetime when we were expecting a type.
52-
These sorts of errors would be caught earlier in the compiler when translating from a `rustc_hir::Ty` to a `ty::Ty`.
53-
If they occur later, that is a compiler bug.
50+
**Note on indices:** It is a bug if the index of a `Param` does not match what the `EarlyBinder` binds. For
51+
example, if the index is out of bounds or the index index of a lifetime corresponds to a type parameter.
52+
These sorts of errors are caught earlier in the compiler during name resolution where we disallow references
53+
to generics parameters introduced by items that should not be nameable by the inner item.
5454

5555
[`FieldDef::ty`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.FieldDef.html#method.ty
5656
[field_def_ty_src]: https://github.com/rust-lang/rust/blob/44d679b9021f03a79133021b94e6d23e9b55b3ab/compiler/rustc_middle/src/ty/mod.rs#L1421-L1426

0 commit comments

Comments
 (0)
Please sign in to comment.