authorbors <bors@rust-lang.org> 2025-03-05 02:43:15 UTC
committerbors <bors@rust-lang.org> 2025-03-05 02:43:15 UTC
logac951d379913c667a1fb73a0830e81d65d2007cf
tree0e95d4d9055ab7295908f998b9d5efb7890b4988
parent08db600e8e276b548e986abe7239c2a85d2f425f
parent7ba7cc835ec18876b8133c4f051abfd5bfebb0aa

Auto merge of #138021 - workingjubilee:rollup-brhnycu, r=workingjubilee

Rollup of 6 pull requests Successful merges: - #137077 (Postprocess bootstrap metrics into GitHub job summary) - #137373 (Compile run-make-support and run-make tests with the bootstrap compiler) - #137634 (Update `compiler-builtins` to 0.1.149) - #137667 (Add `dist::Gcc` build step) - #137722 (`librustdoc`: 2024 edition! 🎊) - #137947 (Do not install rustup on Rust for Linux job) r? `@ghost` `@rustbot` modify labels: rollup

46 files changed, 765 insertions(+), 793 deletions(-)

.github/workflows/ci.yml+17
......@@ -182,6 +182,13 @@ jobs:
182182 - name: show the current environment
183183 run: src/ci/scripts/dump-environment.sh
184184
185 # Pre-build citool before the following step uninstalls rustup
186 # Build is into the build directory, to avoid modifying sources
187 - name: build citool
188 run: |
189 cd src/ci/citool
190 CARGO_TARGET_DIR=../../../build/citool cargo build
191
185192 - name: run the build
186193 # Redirect stderr to stdout to avoid reordering the two streams in the GHA logs.
187194 run: src/ci/scripts/run-build-from-ci.sh 2>&1
......@@ -218,6 +225,16 @@ jobs:
218225 # erroring about invalid credentials instead.
219226 if: github.event_name == 'push' || env.DEPLOY == '1' || env.DEPLOY_ALT == '1'
220227
228 - name: postprocess metrics into the summary
229 run: |
230 if [ -f build/metrics.json ]; then
231 ./build/citool/debug/citool postprocess-metrics build/metrics.json ${GITHUB_STEP_SUMMARY}
232 elif [ -f obj/build/metrics.json ]; then
233 ./build/citool/debug/citool postprocess-metrics obj/build/metrics.json ${GITHUB_STEP_SUMMARY}
234 else
235 echo "No metrics.json found"
236 fi
237
221238 - name: upload job metrics to DataDog
222239 if: needs.calculate_matrix.outputs.run_type != 'pr'
223240 env:
compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch+2-2
......@@ -16,8 +16,8 @@ index 7165c3e48af..968552ad435 100644
1616
1717 [dependencies]
1818 core = { path = "../core", public = true }
19-compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] }
20+compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std', 'no-f16-f128'] }
19-compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std'] }
20+compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std', 'no-f16-f128'] }
2121
2222 [dev-dependencies]
2323 rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
compiler/rustc_data_structures/src/captures.rs deleted-8
......@@ -1,8 +0,0 @@
1/// "Signaling" trait used in impl trait to tag lifetimes that you may
2/// need to capture but don't really need for other reasons.
3/// Basically a workaround; see [this comment] for details.
4///
5/// [this comment]: https://github.com/rust-lang/rust/issues/34511#issuecomment-373423999
6pub trait Captures<'a> {}
7
8impl<'a, T: ?Sized> Captures<'a> for T {}
compiler/rustc_data_structures/src/lib.rs-1
......@@ -48,7 +48,6 @@ pub use rustc_index::static_assert_size;
4848pub mod aligned;
4949pub mod base_n;
5050pub mod binary_search_util;
51pub mod captures;
5251pub mod fingerprint;
5352pub mod flat_map_in_place;
5453pub mod flock;
library/Cargo.lock+2-2
......@@ -61,9 +61,9 @@ dependencies = [
6161
6262[[package]]
6363name = "compiler_builtins"
64version = "0.1.148"
64version = "0.1.150"
6565source = "registry+https://github.com/rust-lang/crates.io-index"
66checksum = "26137996631d90d2727b905b480fdcf8c4479fdbce7afd7f8e3796d689b33cc2"
66checksum = "5c42734e0ccf0d9f953165770593a75306f0b24dda1aa03f115c70748726dbca"
6767dependencies = [
6868 "cc",
6969 "rustc-std-workspace-core",
library/alloc/Cargo.toml+1-1
......@@ -12,7 +12,7 @@ edition = "2021"
1212
1313[dependencies]
1414core = { path = "../core", public = true }
15compiler_builtins = { version = "=0.1.148", features = ['rustc-dep-of-std'] }
15compiler_builtins = { version = "=0.1.150", features = ['rustc-dep-of-std'] }
1616
1717[dev-dependencies]
1818rand = { version = "0.9.0", default-features = false, features = ["alloc"] }
library/std/Cargo.toml+1-1
......@@ -18,7 +18,7 @@ cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
1818panic_unwind = { path = "../panic_unwind", optional = true }
1919panic_abort = { path = "../panic_abort" }
2020core = { path = "../core", public = true }
21compiler_builtins = { version = "=0.1.148" }
21compiler_builtins = { version = "=0.1.150" }
2222unwind = { path = "../unwind" }
2323hashbrown = { version = "0.15", default-features = false, features = [
2424 'rustc-dep-of-std',
src/bootstrap/src/core/build_steps/dist.rs+27
......@@ -2464,3 +2464,30 @@ impl Step for ReproducibleArtifacts {
24642464 if added_anything { Some(tarball.generate()) } else { None }
24652465 }
24662466}
2467
2468/// Tarball containing a prebuilt version of the libgccjit library,
2469/// needed as a dependency for the GCC codegen backend (similarly to the LLVM
2470/// backend needing a prebuilt libLLVM).
2471#[derive(Clone, Debug, Eq, Hash, PartialEq)]
2472pub struct Gcc {
2473 pub target: TargetSelection,
2474}
2475
2476impl Step for Gcc {
2477 type Output = GeneratedTarball;
2478
2479 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
2480 run.alias("gcc")
2481 }
2482
2483 fn make_run(run: RunConfig<'_>) {
2484 run.builder.ensure(Gcc { target: run.target });
2485 }
2486
2487 fn run(self, builder: &Builder<'_>) -> Self::Output {
2488 let tarball = Tarball::new(builder, "gcc", &self.target.triple);
2489 let output = builder.ensure(super::gcc::Gcc { target: self.target });
2490 tarball.add_file(output.libgccjit, ".", 0o644);
2491 tarball.generate()
2492 }
2493}
src/bootstrap/src/core/build_steps/test.rs+9-87
......@@ -1242,59 +1242,6 @@ macro_rules! test {
12421242 };
12431243}
12441244
1245#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
1246pub struct RunMakeSupport {
1247 pub compiler: Compiler,
1248 pub target: TargetSelection,
1249}
1250
1251impl Step for RunMakeSupport {
1252 type Output = PathBuf;
1253 const DEFAULT: bool = true;
1254
1255 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1256 run.never()
1257 }
1258
1259 fn make_run(run: RunConfig<'_>) {
1260 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1261 run.builder.ensure(RunMakeSupport { compiler, target: run.build_triple() });
1262 }
1263
1264 /// Builds run-make-support and returns the path to the resulting rlib.
1265 fn run(self, builder: &Builder<'_>) -> PathBuf {
1266 builder.ensure(compile::Std::new(self.compiler, self.target));
1267
1268 let cargo = tool::prepare_tool_cargo(
1269 builder,
1270 self.compiler,
1271 Mode::ToolStd,
1272 self.target,
1273 Kind::Build,
1274 "src/tools/run-make-support",
1275 SourceType::InTree,
1276 &[],
1277 );
1278
1279 let _guard = builder.msg_tool(
1280 Kind::Build,
1281 Mode::ToolStd,
1282 "run-make-support",
1283 self.compiler.stage,
1284 &self.compiler.host,
1285 &self.target,
1286 );
1287 cargo.into_cmd().run(builder);
1288
1289 let lib_name = "librun_make_support.rlib";
1290 let lib = builder.tools_dir(self.compiler).join(lib_name);
1291
1292 let cargo_out = builder.cargo_out(self.compiler, Mode::ToolStd, self.target).join(lib_name);
1293 builder.copy_link(&cargo_out, &lib);
1294 lib
1295 }
1296}
1297
12981245/// Runs `cargo test` on the `src/tools/run-make-support` crate.
12991246/// That crate is used by run-make tests.
13001247#[derive(Debug, Clone, PartialEq, Eq, Hash)]
......@@ -1446,40 +1393,7 @@ test!(Pretty {
14461393 only_hosts: true,
14471394});
14481395
1449/// Special-handling is needed for `run-make`, so don't use `test!` for defining `RunMake`
1450/// tests.
1451#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1452pub struct RunMake {
1453 pub compiler: Compiler,
1454 pub target: TargetSelection,
1455}
1456
1457impl Step for RunMake {
1458 type Output = ();
1459 const DEFAULT: bool = true;
1460 const ONLY_HOSTS: bool = false;
1461
1462 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1463 run.suite_path("tests/run-make")
1464 }
1465
1466 fn make_run(run: RunConfig<'_>) {
1467 let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1468 run.builder.ensure(RunMakeSupport { compiler, target: run.build_triple() });
1469 run.builder.ensure(RunMake { compiler, target: run.target });
1470 }
1471
1472 fn run(self, builder: &Builder<'_>) {
1473 builder.ensure(Compiletest {
1474 compiler: self.compiler,
1475 target: self.target,
1476 mode: "run-make",
1477 suite: "run-make",
1478 path: "tests/run-make",
1479 compare_mode: None,
1480 });
1481 }
1482}
1396test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make", default: true });
14831397
14841398test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly", default: true });
14851399
......@@ -1722,6 +1636,9 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
17221636 host: target,
17231637 });
17241638 }
1639 if suite == "run-make" {
1640 builder.tool_exe(Tool::RunMakeSupport);
1641 }
17251642
17261643 // Also provide `rust_test_helpers` for the host.
17271644 builder.ensure(TestHelpers { target: compiler.host });
......@@ -1774,6 +1691,11 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
17741691 };
17751692
17761693 cmd.arg("--cargo-path").arg(cargo_path);
1694
1695 // We need to pass the compiler that was used to compile run-make-support,
1696 // because we have to use the same compiler to compile rmake.rs recipes.
1697 let stage0_rustc_path = builder.compiler(0, compiler.host);
1698 cmd.arg("--stage0-rustc-path").arg(builder.rustc(stage0_rustc_path));
17771699 }
17781700
17791701 // Avoid depending on rustdoc when we don't need it.
src/bootstrap/src/core/build_steps/tool.rs+38-43
......@@ -34,6 +34,12 @@ pub enum SourceType {
3434 Submodule,
3535}
3636
37#[derive(Debug, Clone, Hash, PartialEq, Eq)]
38pub enum ToolArtifactKind {
39 Binary,
40 Library,
41}
42
3743#[derive(Debug, Clone, Hash, PartialEq, Eq)]
3844struct ToolBuild {
3945 compiler: Compiler,
......@@ -47,6 +53,8 @@ struct ToolBuild {
4753 allow_features: &'static str,
4854 /// Additional arguments to pass to the `cargo` invocation.
4955 cargo_args: Vec<String>,
56 /// Whether the tool builds a binary or a library.
57 artifact_kind: ToolArtifactKind,
5058}
5159
5260impl Builder<'_> {
......@@ -79,7 +87,7 @@ impl Builder<'_> {
7987/// for using this type as `type Output = ToolBuildResult;`
8088#[derive(Clone)]
8189pub struct ToolBuildResult {
82 /// Executable path of the corresponding tool that was built.
90 /// Artifact path of the corresponding tool that was built.
8391 pub tool_path: PathBuf,
8492 /// Compiler used to build the tool. For non-`ToolRustc` tools this is equal to `target_compiler`.
8593 /// For `ToolRustc` this is one stage before of the `target_compiler`.
......@@ -179,8 +187,14 @@ impl Step for ToolBuild {
179187 if tool == "tidy" {
180188 tool = "rust-tidy";
181189 }
182 let tool_path =
183 copy_link_tool_bin(builder, self.compiler, self.target, self.mode, tool);
190 let tool_path = match self.artifact_kind {
191 ToolArtifactKind::Binary => {
192 copy_link_tool_bin(builder, self.compiler, self.target, self.mode, tool)
193 }
194 ToolArtifactKind::Library => builder
195 .cargo_out(self.compiler, self.mode, self.target)
196 .join(format!("lib{tool}.rlib")),
197 };
184198
185199 ToolBuildResult { tool_path, build_compiler: self.compiler, target_compiler }
186200 }
......@@ -330,6 +344,7 @@ macro_rules! bootstrap_tool {
330344 $(,is_unstable_tool = $unstable:expr)*
331345 $(,allow_features = $allow_features:expr)?
332346 $(,submodules = $submodules:expr)?
347 $(,artifact_kind = $artifact_kind:expr)?
333348 ;
334349 )+) => {
335350 #[derive(PartialEq, Eq, Clone)]
......@@ -389,6 +404,7 @@ macro_rules! bootstrap_tool {
389404 builder.require_submodule(submodule, None);
390405 }
391406 )*
407
392408 builder.ensure(ToolBuild {
393409 compiler: self.compiler,
394410 target: self.target,
......@@ -407,7 +423,12 @@ macro_rules! bootstrap_tool {
407423 },
408424 extra_features: vec![],
409425 allow_features: concat!($($allow_features)*),
410 cargo_args: vec![]
426 cargo_args: vec![],
427 artifact_kind: if false $(|| $artifact_kind == ToolArtifactKind::Library)* {
428 ToolArtifactKind::Library
429 } else {
430 ToolArtifactKind::Binary
431 }
411432 })
412433 }
413434 }
......@@ -445,51 +466,14 @@ bootstrap_tool!(
445466 WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization";
446467 UnicodeTableGenerator, "src/tools/unicode-table-generator", "unicode-table-generator";
447468 FeaturesStatusDump, "src/tools/features-status-dump", "features-status-dump";
469 OptimizedDist, "src/tools/opt-dist", "opt-dist", submodules = &["src/tools/rustc-perf"];
470 RunMakeSupport, "src/tools/run-make-support", "run_make_support", artifact_kind = ToolArtifactKind::Library;
448471);
449472
450473/// These are the submodules that are required for rustbook to work due to
451474/// depending on mdbook plugins.
452475pub static SUBMODULES_FOR_RUSTBOOK: &[&str] = &["src/doc/book", "src/doc/reference"];
453476
454#[derive(Debug, Clone, Hash, PartialEq, Eq)]
455pub struct OptimizedDist {
456 pub compiler: Compiler,
457 pub target: TargetSelection,
458}
459
460impl Step for OptimizedDist {
461 type Output = ToolBuildResult;
462
463 fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
464 run.path("src/tools/opt-dist")
465 }
466
467 fn make_run(run: RunConfig<'_>) {
468 run.builder.ensure(OptimizedDist {
469 compiler: run.builder.compiler(0, run.builder.config.build),
470 target: run.target,
471 });
472 }
473
474 fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
475 // We need to ensure the rustc-perf submodule is initialized when building opt-dist since
476 // the tool requires it to be in place to run.
477 builder.require_submodule("src/tools/rustc-perf", None);
478
479 builder.ensure(ToolBuild {
480 compiler: self.compiler,
481 target: self.target,
482 tool: "opt-dist",
483 mode: Mode::ToolBootstrap,
484 path: "src/tools/opt-dist",
485 source_type: SourceType::InTree,
486 extra_features: Vec::new(),
487 allow_features: "",
488 cargo_args: Vec::new(),
489 })
490 }
491}
492
493477/// The [rustc-perf](https://github.com/rust-lang/rustc-perf) benchmark suite, which is added
494478/// as a submodule at `src/tools/rustc-perf`.
495479#[derive(Debug, Clone, Hash, PartialEq, Eq)]
......@@ -529,6 +513,7 @@ impl Step for RustcPerf {
529513 // Only build the collector package, which is used for benchmarking through
530514 // a CLI.
531515 cargo_args: vec!["-p".to_string(), "collector".to_string()],
516 artifact_kind: ToolArtifactKind::Binary,
532517 };
533518 let res = builder.ensure(tool.clone());
534519 // We also need to symlink the `rustc-fake` binary to the corresponding directory,
......@@ -586,6 +571,7 @@ impl Step for ErrorIndex {
586571 extra_features: Vec::new(),
587572 allow_features: "",
588573 cargo_args: Vec::new(),
574 artifact_kind: ToolArtifactKind::Binary,
589575 })
590576 }
591577}
......@@ -621,6 +607,7 @@ impl Step for RemoteTestServer {
621607 extra_features: Vec::new(),
622608 allow_features: "",
623609 cargo_args: Vec::new(),
610 artifact_kind: ToolArtifactKind::Binary,
624611 })
625612 }
626613}
......@@ -725,6 +712,7 @@ impl Step for Rustdoc {
725712 extra_features,
726713 allow_features: "",
727714 cargo_args: Vec::new(),
715 artifact_kind: ToolArtifactKind::Binary,
728716 });
729717
730718 // don't create a stage0-sysroot/bin directory.
......@@ -779,6 +767,7 @@ impl Step for Cargo {
779767 extra_features: Vec::new(),
780768 allow_features: "",
781769 cargo_args: Vec::new(),
770 artifact_kind: ToolArtifactKind::Binary,
782771 })
783772 }
784773}
......@@ -827,6 +816,7 @@ impl Step for LldWrapper {
827816 extra_features: Vec::new(),
828817 allow_features: "",
829818 cargo_args: Vec::new(),
819 artifact_kind: ToolArtifactKind::Binary,
830820 });
831821
832822 let libdir_bin = builder.sysroot_target_bindir(self.target_compiler, target);
......@@ -887,6 +877,7 @@ impl Step for RustAnalyzer {
887877 source_type: SourceType::InTree,
888878 allow_features: RustAnalyzer::ALLOW_FEATURES,
889879 cargo_args: Vec::new(),
880 artifact_kind: ToolArtifactKind::Binary,
890881 })
891882 }
892883}
......@@ -931,6 +922,7 @@ impl Step for RustAnalyzerProcMacroSrv {
931922 source_type: SourceType::InTree,
932923 allow_features: RustAnalyzer::ALLOW_FEATURES,
933924 cargo_args: Vec::new(),
925 artifact_kind: ToolArtifactKind::Binary,
934926 });
935927
936928 // Copy `rust-analyzer-proc-macro-srv` to `<sysroot>/libexec/`
......@@ -985,6 +977,7 @@ impl Step for LlvmBitcodeLinker {
985977 extra_features: self.extra_features,
986978 allow_features: "",
987979 cargo_args: Vec::new(),
980 artifact_kind: ToolArtifactKind::Binary,
988981 });
989982
990983 if tool_result.target_compiler.stage > 0 {
......@@ -1164,6 +1157,7 @@ fn run_tool_build_step(
11641157 source_type: SourceType::InTree,
11651158 allow_features: "",
11661159 cargo_args: vec![],
1160 artifact_kind: ToolArtifactKind::Binary,
11671161 });
11681162
11691163 // FIXME: This should just be an if-let-chain, but those are unstable.
......@@ -1242,6 +1236,7 @@ impl Step for TestFloatParse {
12421236 extra_features: Vec::new(),
12431237 allow_features: "",
12441238 cargo_args: Vec::new(),
1239 artifact_kind: ToolArtifactKind::Binary,
12451240 })
12461241 }
12471242}
src/bootstrap/src/core/builder/mod.rs+1
......@@ -1072,6 +1072,7 @@ impl<'a> Builder<'a> {
10721072 dist::PlainSourceTarball,
10731073 dist::BuildManifest,
10741074 dist::ReproducibleArtifacts,
1075 dist::Gcc
10751076 ),
10761077 Kind::Install => describe!(
10771078 install::Docs,
src/bootstrap/src/utils/metrics.rs+8
......@@ -200,6 +200,14 @@ impl BuildMetrics {
200200 }
201201 };
202202 invocations.push(JsonInvocation {
203 // The command-line invocation with which bootstrap was invoked.
204 // Skip the first argument, as it is a potentially long absolute
205 // path that is not interesting.
206 cmdline: std::env::args_os()
207 .skip(1)
208 .map(|arg| arg.to_string_lossy().to_string())
209 .collect::<Vec<_>>()
210 .join(" "),
203211 start_time: state
204212 .invocation_start
205213 .duration_since(SystemTime::UNIX_EPOCH)
src/build_helper/src/metrics.rs+88
......@@ -1,3 +1,5 @@
1use std::time::Duration;
2
13use serde_derive::{Deserialize, Serialize};
24
35#[derive(Serialize, Deserialize)]
......@@ -12,6 +14,8 @@ pub struct JsonRoot {
1214#[derive(Serialize, Deserialize)]
1315#[serde(rename_all = "snake_case")]
1416pub struct JsonInvocation {
17 // Remembers the command-line invocation with which bootstrap was invoked.
18 pub cmdline: String,
1519 // Unix timestamp in seconds
1620 //
1721 // This is necessary to easily correlate this invocation with logs or other data.
......@@ -98,3 +102,87 @@ fn null_as_f64_nan<'de, D: serde::Deserializer<'de>>(d: D) -> Result<f64, D::Err
98102 use serde::Deserialize as _;
99103 Option::<f64>::deserialize(d).map(|f| f.unwrap_or(f64::NAN))
100104}
105
106/// Represents a single bootstrap step, with the accumulated duration of all its children.
107#[derive(Clone, Debug)]
108pub struct BuildStep {
109 pub r#type: String,
110 pub children: Vec<BuildStep>,
111 pub duration: Duration,
112}
113
114impl BuildStep {
115 /// Create a `BuildStep` representing a single invocation of bootstrap.
116 /// The most important thing is that the build step aggregates the
117 /// durations of all children, so that it can be easily accessed.
118 pub fn from_invocation(invocation: &JsonInvocation) -> Self {
119 fn parse(node: &JsonNode) -> Option<BuildStep> {
120 match node {
121 JsonNode::RustbuildStep {
122 type_: kind,
123 children,
124 duration_excluding_children_sec,
125 ..
126 } => {
127 let children: Vec<_> = children.into_iter().filter_map(parse).collect();
128 let children_duration = children.iter().map(|c| c.duration).sum::<Duration>();
129 Some(BuildStep {
130 r#type: kind.to_string(),
131 children,
132 duration: children_duration
133 + Duration::from_secs_f64(*duration_excluding_children_sec),
134 })
135 }
136 JsonNode::TestSuite(_) => None,
137 }
138 }
139
140 let duration = Duration::from_secs_f64(invocation.duration_including_children_sec);
141 let children: Vec<_> = invocation.children.iter().filter_map(parse).collect();
142 Self { r#type: "total".to_string(), children, duration }
143 }
144
145 pub fn find_all_by_type(&self, r#type: &str) -> Vec<&Self> {
146 let mut result = Vec::new();
147 self.find_by_type(r#type, &mut result);
148 result
149 }
150
151 fn find_by_type<'a>(&'a self, r#type: &str, result: &mut Vec<&'a Self>) {
152 if self.r#type == r#type {
153 result.push(self);
154 }
155 for child in &self.children {
156 child.find_by_type(r#type, result);
157 }
158 }
159}
160
161/// Writes build steps into a nice indented table.
162pub fn format_build_steps(root: &BuildStep) -> String {
163 use std::fmt::Write;
164
165 let mut substeps: Vec<(u32, &BuildStep)> = Vec::new();
166
167 fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) {
168 substeps.push((level, step));
169 for child in &step.children {
170 visit(child, level + 1, substeps);
171 }
172 }
173
174 visit(root, 0, &mut substeps);
175
176 let mut output = String::new();
177 for (level, step) in substeps {
178 let label = format!(
179 "{}{}",
180 ".".repeat(level as usize),
181 // Bootstrap steps can be generic and thus contain angle brackets (<...>).
182 // However, Markdown interprets these as HTML, so we need to escap ethem.
183 step.r#type.replace('<', "&lt;").replace('>', "&gt;")
184 );
185 writeln!(output, "{label:.<65}{:>8.2}s", step.duration.as_secs_f64()).unwrap();
186 }
187 output
188}
src/ci/citool/Cargo.lock+9
......@@ -58,11 +58,20 @@ version = "1.0.95"
5858source = "registry+https://github.com/rust-lang/crates.io-index"
5959checksum = "34ac096ce696dc2fcabef30516bb13c0a68a11d30131d3df6f04711467681b04"
6060
61[[package]]
62name = "build_helper"
63version = "0.1.0"
64dependencies = [
65 "serde",
66 "serde_derive",
67]
68
6169[[package]]
6270name = "citool"
6371version = "0.1.0"
6472dependencies = [
6573 "anyhow",
74 "build_helper",
6675 "clap",
6776 "insta",
6877 "serde",
src/ci/citool/Cargo.toml+2
......@@ -10,6 +10,8 @@ serde = { version = "1", features = ["derive"] }
1010serde_yaml = "0.9"
1111serde_json = "1"
1212
13build_helper = { path = "../../build_helper" }
14
1315[dev-dependencies]
1416insta = "1"
1517
src/ci/citool/src/main.rs+15
......@@ -1,3 +1,5 @@
1mod metrics;
2
13use std::collections::BTreeMap;
24use std::path::{Path, PathBuf};
35use std::process::Command;
......@@ -6,6 +8,8 @@ use anyhow::Context;
68use clap::Parser;
79use serde_yaml::Value;
810
11use crate::metrics::postprocess_metrics;
12
913const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/..");
1014const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker");
1115const JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../github-actions/jobs.yml");
......@@ -338,6 +342,14 @@ enum Args {
338342 #[clap(long = "type", default_value = "auto")]
339343 job_type: JobType,
340344 },
345 /// Postprocess the metrics.json file generated by bootstrap.
346 PostprocessMetrics {
347 /// Path to the metrics.json file
348 metrics_path: PathBuf,
349 /// Path to a file where the postprocessed metrics summary will be stored.
350 /// Usually, this will be GITHUB_STEP_SUMMARY on CI.
351 summary_path: PathBuf,
352 },
341353}
342354
343355#[derive(clap::ValueEnum, Clone)]
......@@ -369,6 +381,9 @@ fn main() -> anyhow::Result<()> {
369381 Args::RunJobLocally { job_type, name } => {
370382 run_workflow_locally(load_db(default_jobs_file)?, job_type, name)?
371383 }
384 Args::PostprocessMetrics { metrics_path, summary_path } => {
385 postprocess_metrics(&metrics_path, &summary_path)?;
386 }
372387 }
373388
374389 Ok(())
src/ci/citool/src/metrics.rs created+164
......@@ -0,0 +1,164 @@
1use std::collections::BTreeMap;
2use std::fs::File;
3use std::io::Write;
4use std::path::Path;
5
6use anyhow::Context;
7use build_helper::metrics::{
8 BuildStep, JsonNode, JsonRoot, TestOutcome, TestSuite, TestSuiteMetadata, format_build_steps,
9};
10
11pub fn postprocess_metrics(metrics_path: &Path, summary_path: &Path) -> anyhow::Result<()> {
12 let metrics = load_metrics(metrics_path)?;
13
14 let mut file = File::options()
15 .append(true)
16 .create(true)
17 .open(summary_path)
18 .with_context(|| format!("Cannot open summary file at {summary_path:?}"))?;
19
20 if !metrics.invocations.is_empty() {
21 writeln!(file, "# Bootstrap steps")?;
22 record_bootstrap_step_durations(&metrics, &mut file)?;
23 record_test_suites(&metrics, &mut file)?;
24 }
25
26 Ok(())
27}
28
29fn record_bootstrap_step_durations(metrics: &JsonRoot, file: &mut File) -> anyhow::Result<()> {
30 for invocation in &metrics.invocations {
31 let step = BuildStep::from_invocation(invocation);
32 let table = format_build_steps(&step);
33 eprintln!("Step `{}`\n{table}\n", invocation.cmdline);
34 writeln!(
35 file,
36 r"<details>
37<summary>{}</summary>
38<pre><code>{table}</code></pre>
39</details>
40",
41 invocation.cmdline
42 )?;
43 }
44 eprintln!("Recorded {} bootstrap invocation(s)", metrics.invocations.len());
45
46 Ok(())
47}
48
49fn record_test_suites(metrics: &JsonRoot, file: &mut File) -> anyhow::Result<()> {
50 let suites = get_test_suites(&metrics);
51
52 if !suites.is_empty() {
53 let aggregated = aggregate_test_suites(&suites);
54 let table = render_table(aggregated);
55 writeln!(file, "\n# Test results\n")?;
56 writeln!(file, "{table}")?;
57 } else {
58 eprintln!("No test suites found in metrics");
59 }
60
61 Ok(())
62}
63
64fn render_table(suites: BTreeMap<String, TestSuiteRecord>) -> String {
65 use std::fmt::Write;
66
67 let mut table = "| Test suite | Passed ✅ | Ignored 🚫 | Failed ❌ |\n".to_string();
68 writeln!(table, "|:------|------:|------:|------:|").unwrap();
69
70 fn write_row(
71 buffer: &mut String,
72 name: &str,
73 record: &TestSuiteRecord,
74 surround: &str,
75 ) -> std::fmt::Result {
76 let TestSuiteRecord { passed, ignored, failed } = record;
77 let total = (record.passed + record.ignored + record.failed) as f64;
78 let passed_pct = ((*passed as f64) / total) * 100.0;
79 let ignored_pct = ((*ignored as f64) / total) * 100.0;
80 let failed_pct = ((*failed as f64) / total) * 100.0;
81
82 write!(buffer, "| {surround}{name}{surround} |")?;
83 write!(buffer, " {surround}{passed} ({passed_pct:.0}%){surround} |")?;
84 write!(buffer, " {surround}{ignored} ({ignored_pct:.0}%){surround} |")?;
85 writeln!(buffer, " {surround}{failed} ({failed_pct:.0}%){surround} |")?;
86
87 Ok(())
88 }
89
90 let mut total = TestSuiteRecord::default();
91 for (name, record) in suites {
92 write_row(&mut table, &name, &record, "").unwrap();
93 total.passed += record.passed;
94 total.ignored += record.ignored;
95 total.failed += record.failed;
96 }
97 write_row(&mut table, "Total", &total, "**").unwrap();
98 table
99}
100
101#[derive(Default)]
102struct TestSuiteRecord {
103 passed: u64,
104 ignored: u64,
105 failed: u64,
106}
107
108fn aggregate_test_suites(suites: &[&TestSuite]) -> BTreeMap<String, TestSuiteRecord> {
109 let mut records: BTreeMap<String, TestSuiteRecord> = BTreeMap::new();
110 for suite in suites {
111 let name = match &suite.metadata {
112 TestSuiteMetadata::CargoPackage { crates, stage, .. } => {
113 format!("{} (stage {stage})", crates.join(", "))
114 }
115 TestSuiteMetadata::Compiletest { suite, stage, .. } => {
116 format!("{suite} (stage {stage})")
117 }
118 };
119 let record = records.entry(name).or_default();
120 for test in &suite.tests {
121 match test.outcome {
122 TestOutcome::Passed => {
123 record.passed += 1;
124 }
125 TestOutcome::Failed => {
126 record.failed += 1;
127 }
128 TestOutcome::Ignored { .. } => {
129 record.ignored += 1;
130 }
131 }
132 }
133 }
134 records
135}
136
137fn get_test_suites(metrics: &JsonRoot) -> Vec<&TestSuite> {
138 fn visit_test_suites<'a>(nodes: &'a [JsonNode], suites: &mut Vec<&'a TestSuite>) {
139 for node in nodes {
140 match node {
141 JsonNode::RustbuildStep { children, .. } => {
142 visit_test_suites(&children, suites);
143 }
144 JsonNode::TestSuite(suite) => {
145 suites.push(&suite);
146 }
147 }
148 }
149 }
150
151 let mut suites = vec![];
152 for invocation in &metrics.invocations {
153 visit_test_suites(&invocation.children, &mut suites);
154 }
155 suites
156}
157
158fn load_metrics(path: &Path) -> anyhow::Result<JsonRoot> {
159 let metrics = std::fs::read_to_string(path)
160 .with_context(|| format!("Cannot read JSON metrics from {path:?}"))?;
161 let metrics: JsonRoot = serde_json::from_str(&metrics)
162 .with_context(|| format!("Cannot deserialize JSON metrics from {path:?}"))?;
163 Ok(metrics)
164}
src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile+1-1
......@@ -101,7 +101,7 @@ ENV SCRIPT python3 ../x.py build --set rust.debug=true opt-dist && \
101101 ./build/$HOSTS/stage0-tools-bin/opt-dist linux-ci -- python3 ../x.py dist \
102102 --host $HOSTS --target $HOSTS \
103103 --include-default-paths \
104 build-manifest bootstrap
104 build-manifest bootstrap gcc
105105ENV CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_LINKER=clang
106106
107107# This is the only builder which will create source tarballs
src/ci/docker/scripts/rfl-build.sh+8-10
......@@ -8,16 +8,10 @@ LINUX_VERSION=v6.14-rc3
88../x.py build --stage 2 library rustdoc clippy rustfmt
99../x.py build --stage 0 cargo
1010
11# Install rustup so that we can use the built toolchain easily, and also
12# install bindgen in an easy way.
13curl --proto '=https' --tlsv1.2 -sSf -o rustup.sh https://sh.rustup.rs
14sh rustup.sh -y --default-toolchain none
11BUILD_DIR=$(realpath ./build/x86_64-unknown-linux-gnu)
1512
16source /cargo/env
17
18BUILD_DIR=$(realpath ./build)
19rustup toolchain link local "${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage2
20rustup default local
13# Provide path to rustc, rustdoc, clippy-driver and rustfmt to RfL
14export PATH=${PATH}:${BUILD_DIR}/stage2/bin
2115
2216mkdir -p rfl
2317cd rfl
......@@ -33,10 +27,14 @@ git -C linux fetch --depth 1 origin ${LINUX_VERSION}
3327git -C linux checkout FETCH_HEAD
3428
3529# Install bindgen
36"${BUILD_DIR}"/x86_64-unknown-linux-gnu/stage0/bin/cargo install \
30"${BUILD_DIR}"/stage0/bin/cargo install \
3731 --version $(linux/scripts/min-tool-version.sh bindgen) \
32 --root ${BUILD_DIR}/bindgen \
3833 bindgen-cli
3934
35# Provide path to bindgen to RfL
36export PATH=${PATH}:${BUILD_DIR}/bindgen/bin
37
4038# Configure Rust for Linux
4139cat <<EOF > linux/kernel/configs/rfl-for-rust-ci.config
4240# CONFIG_WERROR is not set
src/ci/github-actions/jobs.yml+2-3
......@@ -271,9 +271,8 @@ auto:
271271
272272 # Tests integration with Rust for Linux.
273273 # Builds stage 1 compiler and tries to compile a few RfL examples with it.
274 # FIXME: fix rustup 1.28 issue
275 # - name: x86_64-rust-for-linux
276 # <<: *job-linux-4c
274 - name: x86_64-rust-for-linux
275 <<: *job-linux-4c
277276
278277 - name: x86_64-gnu
279278 <<: *job-linux-4c
src/librustdoc/Cargo.toml+1-1
......@@ -1,7 +1,7 @@
11[package]
22name = "rustdoc"
33version = "0.0.0"
4edition = "2021"
4edition = "2024"
55build = "build.rs"
66
77[lib]
src/librustdoc/clean/cfg.rs+2-2
......@@ -48,12 +48,12 @@ impl Cfg {
4848 exclude: &FxHashSet<Cfg>,
4949 ) -> Result<Option<Cfg>, InvalidCfgError> {
5050 match nested_cfg {
51 MetaItemInner::MetaItem(ref cfg) => Cfg::parse_without(cfg, exclude),
51 MetaItemInner::MetaItem(cfg) => Cfg::parse_without(cfg, exclude),
5252 MetaItemInner::Lit(MetaItemLit { kind: LitKind::Bool(b), .. }) => match *b {
5353 true => Ok(Some(Cfg::True)),
5454 false => Ok(Some(Cfg::False)),
5555 },
56 MetaItemInner::Lit(ref lit) => {
56 MetaItemInner::Lit(lit) => {
5757 Err(InvalidCfgError { msg: "unexpected literal", span: lit.span })
5858 }
5959 }
src/librustdoc/clean/mod.rs+2-2
......@@ -741,7 +741,7 @@ pub(crate) fn clean_generics<'tcx>(
741741 for p in gens.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
742742 let mut p = clean_generic_param(cx, Some(gens), p);
743743 match &mut p.kind {
744 GenericParamDefKind::Lifetime { ref mut outlives } => {
744 GenericParamDefKind::Lifetime { outlives } => {
745745 if let Some(region_pred) = region_predicates.get_mut(&Lifetime(p.name)) {
746746 // We merge bounds in the `where` clause.
747747 for outlive in outlives.drain(..) {
......@@ -2688,7 +2688,7 @@ fn filter_doc_attr_ident(ident: Symbol, is_inline: bool) -> bool {
26882688/// Before calling this function, make sure `normal` is a `#[doc]` attribute.
26892689fn filter_doc_attr(args: &mut hir::AttrArgs, is_inline: bool) {
26902690 match args {
2691 hir::AttrArgs::Delimited(ref mut args) => {
2691 hir::AttrArgs::Delimited(args) => {
26922692 let tokens = filter_tokens_from_list(&args.tokens, |token| {
26932693 !matches!(
26942694 token,
src/librustdoc/clean/types.rs+4-4
......@@ -502,7 +502,7 @@ impl Item {
502502 let Some(links) = cx.cache().intra_doc_links.get(&self.item_id) else { return vec![] };
503503 links
504504 .iter()
505 .filter_map(|ItemLink { link: s, link_text, page_id: id, ref fragment }| {
505 .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| {
506506 debug!(?id);
507507 if let Ok((mut href, ..)) = href(*id, cx) {
508508 debug!(?href);
......@@ -1150,7 +1150,7 @@ pub(crate) struct Attributes {
11501150}
11511151
11521152impl Attributes {
1153 pub(crate) fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::MetaItemInner> + '_ {
1153 pub(crate) fn lists(&self, name: Symbol) -> impl Iterator<Item = ast::MetaItemInner> {
11541154 hir_attr_lists(&self.other_attrs[..], name)
11551155 }
11561156
......@@ -1864,7 +1864,7 @@ impl PrimitiveType {
18641864 .copied()
18651865 }
18661866
1867 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> + '_ {
1867 pub(crate) fn all_impls(tcx: TyCtxt<'_>) -> impl Iterator<Item = DefId> {
18681868 Self::simplified_types()
18691869 .values()
18701870 .flatten()
......@@ -2259,7 +2259,7 @@ impl GenericArgs {
22592259 GenericArgs::Parenthesized { inputs, output } => inputs.is_empty() && output.is_none(),
22602260 }
22612261 }
2262 pub(crate) fn constraints<'a>(&'a self) -> Box<dyn Iterator<Item = AssocItemConstraint> + 'a> {
2262 pub(crate) fn constraints(&self) -> Box<dyn Iterator<Item = AssocItemConstraint> + '_> {
22632263 match self {
22642264 GenericArgs::AngleBracketed { constraints, .. } => {
22652265 Box::new(constraints.iter().cloned())
src/librustdoc/clean/utils.rs+7-6
......@@ -60,7 +60,7 @@ pub(crate) fn krate(cx: &mut DocContext<'_>) -> Crate {
6060 let primitives = local_crate.primitives(cx.tcx);
6161 let keywords = local_crate.keywords(cx.tcx);
6262 {
63 let ItemKind::ModuleItem(ref mut m) = &mut module.inner.kind else { unreachable!() };
63 let ItemKind::ModuleItem(m) = &mut module.inner.kind else { unreachable!() };
6464 m.items.extend(primitives.iter().map(|&(def_id, prim)| {
6565 Item::from_def_id_and_parts(
6666 def_id,
......@@ -302,7 +302,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
302302 use rustc_hir::*;
303303 debug!("trying to get a name from pattern: {p:?}");
304304
305 Symbol::intern(&match p.kind {
305 Symbol::intern(&match &p.kind {
306306 // FIXME(never_patterns): does this make sense?
307307 PatKind::Wild
308308 | PatKind::Err(_)
......@@ -313,8 +313,9 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
313313 }
314314 PatKind::Binding(_, _, ident, _) => return ident.name,
315315 PatKind::Box(p) | PatKind::Ref(p, _) | PatKind::Guard(p, _) => return name_from_pat(p),
316 PatKind::TupleStruct(ref p, ..)
317 | PatKind::Expr(PatExpr { kind: PatExprKind::Path(ref p), .. }) => qpath_to_string(p),
316 PatKind::TupleStruct(p, ..) | PatKind::Expr(PatExpr { kind: PatExprKind::Path(p), .. }) => {
317 qpath_to_string(p)
318 }
318319 PatKind::Or(pats) => {
319320 fmt::from_fn(|f| pats.iter().map(|p| name_from_pat(p)).joined(" | ", f)).to_string()
320321 }
......@@ -329,7 +330,7 @@ pub(crate) fn name_from_pat(p: &hir::Pat<'_>) -> Symbol {
329330 return Symbol::intern("()");
330331 }
331332 PatKind::Slice(begin, mid, end) => {
332 fn print_pat<'a>(pat: &'a Pat<'a>, wild: bool) -> impl Display + 'a {
333 fn print_pat(pat: &Pat<'_>, wild: bool) -> impl Display {
333334 fmt::from_fn(move |f| {
334335 if wild {
335336 f.write_str("..")?;
......@@ -493,7 +494,7 @@ pub(crate) fn resolve_type(cx: &mut DocContext<'_>, path: Path) -> Type {
493494pub(crate) fn synthesize_auto_trait_and_blanket_impls(
494495 cx: &mut DocContext<'_>,
495496 item_def_id: DefId,
496) -> impl Iterator<Item = Item> {
497) -> impl Iterator<Item = Item> + use<> {
497498 let auto_impls = cx
498499 .sess()
499500 .prof
src/librustdoc/html/format.rs+46-100
......@@ -15,7 +15,6 @@ use std::iter::{self, once};
1515use itertools::Either;
1616use rustc_abi::ExternAbi;
1717use rustc_attr_parsing::{ConstStability, StabilityLevel, StableSince};
18use rustc_data_structures::captures::Captures;
1918use rustc_data_structures::fx::FxHashSet;
2019use rustc_hir as hir;
2120use rustc_hir::def::DefKind;
......@@ -41,10 +40,10 @@ pub(crate) fn write_str(s: &mut String, f: fmt::Arguments<'_>) {
4140 s.write_fmt(f).unwrap();
4241}
4342
44pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>(
45 bounds: &'a [clean::GenericBound],
46 cx: &'a Context<'tcx>,
47) -> impl Display + 'a + Captures<'tcx> {
43pub(crate) fn print_generic_bounds(
44 bounds: &[clean::GenericBound],
45 cx: &Context<'_>,
46) -> impl Display {
4847 fmt::from_fn(move |f| {
4948 let mut bounds_dup = FxHashSet::default();
5049
......@@ -57,10 +56,7 @@ pub(crate) fn print_generic_bounds<'a, 'tcx: 'a>(
5756}
5857
5958impl clean::GenericParamDef {
60 pub(crate) fn print<'a, 'tcx: 'a>(
61 &'a self,
62 cx: &'a Context<'tcx>,
63 ) -> impl Display + 'a + Captures<'tcx> {
59 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
6460 fmt::from_fn(move |f| match &self.kind {
6561 clean::GenericParamDefKind::Lifetime { outlives } => {
6662 write!(f, "{}", self.name)?;
......@@ -80,7 +76,7 @@ impl clean::GenericParamDef {
8076 print_generic_bounds(bounds, cx).fmt(f)?;
8177 }
8278
83 if let Some(ref ty) = default {
79 if let Some(ty) = default {
8480 f.write_str(" = ")?;
8581 ty.print(cx).fmt(f)?;
8682 }
......@@ -107,10 +103,7 @@ impl clean::GenericParamDef {
107103}
108104
109105impl clean::Generics {
110 pub(crate) fn print<'a, 'tcx: 'a>(
111 &'a self,
112 cx: &'a Context<'tcx>,
113 ) -> impl Display + 'a + Captures<'tcx> {
106 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
114107 fmt::from_fn(move |f| {
115108 let mut real_params = self.params.iter().filter(|p| !p.is_synthetic_param()).peekable();
116109 if real_params.peek().is_none() {
......@@ -134,10 +127,7 @@ pub(crate) enum Ending {
134127 NoNewline,
135128}
136129
137fn print_where_predicate<'a, 'tcx: 'a>(
138 predicate: &'a clean::WherePredicate,
139 cx: &'a Context<'tcx>,
140) -> impl Display + 'a + Captures<'tcx> {
130fn print_where_predicate(predicate: &clean::WherePredicate, cx: &Context<'_>) -> impl Display {
141131 fmt::from_fn(move |f| {
142132 match predicate {
143133 clean::WherePredicate::BoundPredicate { ty, bounds, bound_params } => {
......@@ -173,12 +163,12 @@ fn print_where_predicate<'a, 'tcx: 'a>(
173163/// * The Generics from which to emit a where-clause.
174164/// * The number of spaces to indent each line with.
175165/// * Whether the where-clause needs to add a comma and newline after the last bound.
176pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
177 gens: &'a clean::Generics,
178 cx: &'a Context<'tcx>,
166pub(crate) fn print_where_clause(
167 gens: &clean::Generics,
168 cx: &Context<'_>,
179169 indent: usize,
180170 ending: Ending,
181) -> Option<impl Display + 'a + Captures<'tcx>> {
171) -> Option<impl Display> {
182172 if gens.where_predicates.is_empty() {
183173 return None;
184174 }
......@@ -250,13 +240,13 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
250240}
251241
252242impl clean::Lifetime {
253 pub(crate) fn print(&self) -> impl Display + '_ {
243 pub(crate) fn print(&self) -> impl Display {
254244 self.0.as_str()
255245 }
256246}
257247
258248impl clean::ConstantKind {
259 pub(crate) fn print(&self, tcx: TyCtxt<'_>) -> impl Display + '_ {
249 pub(crate) fn print(&self, tcx: TyCtxt<'_>) -> impl Display {
260250 let expr = self.expr(tcx);
261251 fmt::from_fn(move |f| {
262252 if f.alternate() { f.write_str(&expr) } else { write!(f, "{}", Escape(&expr)) }
......@@ -265,7 +255,7 @@ impl clean::ConstantKind {
265255}
266256
267257impl clean::PolyTrait {
268 fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> {
258 fn print(&self, cx: &Context<'_>) -> impl Display {
269259 fmt::from_fn(move |f| {
270260 print_higher_ranked_params_with_space(&self.generic_params, cx, "for").fmt(f)?;
271261 self.trait_.print(cx).fmt(f)
......@@ -274,10 +264,7 @@ impl clean::PolyTrait {
274264}
275265
276266impl clean::GenericBound {
277 pub(crate) fn print<'a, 'tcx: 'a>(
278 &'a self,
279 cx: &'a Context<'tcx>,
280 ) -> impl Display + 'a + Captures<'tcx> {
267 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
281268 fmt::from_fn(move |f| match self {
282269 clean::GenericBound::Outlives(lt) => write!(f, "{}", lt.print()),
283270 clean::GenericBound::TraitBound(ty, modifiers) => {
......@@ -304,7 +291,7 @@ impl clean::GenericBound {
304291}
305292
306293impl clean::GenericArgs {
307 fn print<'a, 'tcx: 'a>(&'a self, cx: &'a Context<'tcx>) -> impl Display + 'a + Captures<'tcx> {
294 fn print(&self, cx: &Context<'_>) -> impl Display {
308295 fmt::from_fn(move |f| {
309296 match self {
310297 clean::GenericArgs::AngleBracketed { args, constraints } => {
......@@ -809,11 +796,11 @@ fn primitive_link_fragment(
809796 Ok(())
810797}
811798
812fn tybounds<'a, 'tcx: 'a>(
813 bounds: &'a [clean::PolyTrait],
814 lt: &'a Option<clean::Lifetime>,
815 cx: &'a Context<'tcx>,
816) -> impl Display + 'a + Captures<'tcx> {
799fn tybounds(
800 bounds: &[clean::PolyTrait],
801 lt: &Option<clean::Lifetime>,
802 cx: &Context<'_>,
803) -> impl Display {
817804 fmt::from_fn(move |f| {
818805 bounds.iter().map(|bound| bound.print(cx)).joined(" + ", f)?;
819806 if let Some(lt) = lt {
......@@ -825,11 +812,11 @@ fn tybounds<'a, 'tcx: 'a>(
825812 })
826813}
827814
828fn print_higher_ranked_params_with_space<'a, 'tcx: 'a>(
829 params: &'a [clean::GenericParamDef],
830 cx: &'a Context<'tcx>,
815fn print_higher_ranked_params_with_space(
816 params: &[clean::GenericParamDef],
817 cx: &Context<'_>,
831818 keyword: &'static str,
832) -> impl Display + 'a + Captures<'tcx> {
819) -> impl Display {
833820 fmt::from_fn(move |f| {
834821 if !params.is_empty() {
835822 f.write_str(keyword)?;
......@@ -841,11 +828,7 @@ fn print_higher_ranked_params_with_space<'a, 'tcx: 'a>(
841828 })
842829}
843830
844pub(crate) fn anchor<'a: 'cx, 'cx>(
845 did: DefId,
846 text: Symbol,
847 cx: &'cx Context<'a>,
848) -> impl Display + Captures<'a> + 'cx {
831pub(crate) fn anchor(did: DefId, text: Symbol, cx: &Context<'_>) -> impl Display {
849832 fmt::from_fn(move |f| {
850833 let parts = href(did, cx);
851834 if let Ok((url, short_ty, fqp)) = parts {
......@@ -1121,29 +1104,19 @@ fn fmt_type(
11211104}
11221105
11231106impl clean::Type {
1124 pub(crate) fn print<'b, 'a: 'b, 'tcx: 'a>(
1125 &'a self,
1126 cx: &'a Context<'tcx>,
1127 ) -> impl Display + 'b + Captures<'tcx> {
1107 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
11281108 fmt::from_fn(move |f| fmt_type(self, f, false, cx))
11291109 }
11301110}
11311111
11321112impl clean::Path {
1133 pub(crate) fn print<'b, 'a: 'b, 'tcx: 'a>(
1134 &'a self,
1135 cx: &'a Context<'tcx>,
1136 ) -> impl Display + 'b + Captures<'tcx> {
1113 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
11371114 fmt::from_fn(move |f| resolved_path(f, self.def_id(), self, false, false, cx))
11381115 }
11391116}
11401117
11411118impl clean::Impl {
1142 pub(crate) fn print<'a, 'tcx: 'a>(
1143 &'a self,
1144 use_absolute: bool,
1145 cx: &'a Context<'tcx>,
1146 ) -> impl Display + 'a + Captures<'tcx> {
1119 pub(crate) fn print(&self, use_absolute: bool, cx: &Context<'_>) -> impl Display {
11471120 fmt::from_fn(move |f| {
11481121 f.write_str("impl")?;
11491122 self.generics.print(cx).fmt(f)?;
......@@ -1182,12 +1155,12 @@ impl clean::Impl {
11821155 print_where_clause(&self.generics, cx, 0, Ending::Newline).maybe_display().fmt(f)
11831156 })
11841157 }
1185 fn print_type<'a, 'tcx: 'a>(
1158 fn print_type(
11861159 &self,
11871160 type_: &clean::Type,
11881161 f: &mut fmt::Formatter<'_>,
11891162 use_absolute: bool,
1190 cx: &'a Context<'tcx>,
1163 cx: &Context<'_>,
11911164 ) -> Result<(), fmt::Error> {
11921165 if let clean::Type::Tuple(types) = type_
11931166 && let [clean::Type::Generic(name)] = &types[..]
......@@ -1258,10 +1231,7 @@ impl clean::Impl {
12581231}
12591232
12601233impl clean::Arguments {
1261 pub(crate) fn print<'a, 'tcx: 'a>(
1262 &'a self,
1263 cx: &'a Context<'tcx>,
1264 ) -> impl Display + 'a + Captures<'tcx> {
1234 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
12651235 fmt::from_fn(move |f| {
12661236 self.values
12671237 .iter()
......@@ -1301,10 +1271,7 @@ impl Display for Indent {
13011271}
13021272
13031273impl clean::FnDecl {
1304 pub(crate) fn print<'b, 'a: 'b, 'tcx: 'a>(
1305 &'a self,
1306 cx: &'a Context<'tcx>,
1307 ) -> impl Display + 'b + Captures<'tcx> {
1274 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
13081275 fmt::from_fn(move |f| {
13091276 let ellipsis = if self.c_variadic { ", ..." } else { "" };
13101277 if f.alternate() {
......@@ -1333,12 +1300,12 @@ impl clean::FnDecl {
13331300 /// are preserved.
13341301 /// * `indent`: The number of spaces to indent each successive line with, if line-wrapping is
13351302 /// necessary.
1336 pub(crate) fn full_print<'a, 'tcx: 'a>(
1337 &'a self,
1303 pub(crate) fn full_print(
1304 &self,
13381305 header_len: usize,
13391306 indent: usize,
1340 cx: &'a Context<'tcx>,
1341 ) -> impl Display + 'a + Captures<'tcx> {
1307 cx: &Context<'_>,
1308 ) -> impl Display {
13421309 fmt::from_fn(move |f| {
13431310 // First, generate the text form of the declaration, with no line wrapping, and count the bytes.
13441311 let mut counter = WriteCounter(0);
......@@ -1420,10 +1387,7 @@ impl clean::FnDecl {
14201387 self.print_output(cx).fmt(f)
14211388 }
14221389
1423 fn print_output<'a, 'tcx: 'a>(
1424 &'a self,
1425 cx: &'a Context<'tcx>,
1426 ) -> impl Display + 'a + Captures<'tcx> {
1390 fn print_output(&self, cx: &Context<'_>) -> impl Display {
14271391 fmt::from_fn(move |f| match &self.output {
14281392 clean::Tuple(tys) if tys.is_empty() => Ok(()),
14291393 ty if f.alternate() => {
......@@ -1434,10 +1398,7 @@ impl clean::FnDecl {
14341398 }
14351399}
14361400
1437pub(crate) fn visibility_print_with_space<'a, 'tcx: 'a>(
1438 item: &clean::Item,
1439 cx: &'a Context<'tcx>,
1440) -> impl Display + 'a + Captures<'tcx> {
1401pub(crate) fn visibility_print_with_space(item: &clean::Item, cx: &Context<'_>) -> impl Display {
14411402 use std::fmt::Write as _;
14421403 let vis: Cow<'static, str> = match item.visibility(cx.tcx()) {
14431404 None => "".into(),
......@@ -1546,10 +1507,7 @@ pub(crate) fn print_constness_with_space(
15461507}
15471508
15481509impl clean::Import {
1549 pub(crate) fn print<'a, 'tcx: 'a>(
1550 &'a self,
1551 cx: &'a Context<'tcx>,
1552 ) -> impl Display + 'a + Captures<'tcx> {
1510 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
15531511 fmt::from_fn(move |f| match self.kind {
15541512 clean::ImportKind::Simple(name) => {
15551513 if name == self.source.path.last() {
......@@ -1570,10 +1528,7 @@ impl clean::Import {
15701528}
15711529
15721530impl clean::ImportSource {
1573 pub(crate) fn print<'a, 'tcx: 'a>(
1574 &'a self,
1575 cx: &'a Context<'tcx>,
1576 ) -> impl Display + 'a + Captures<'tcx> {
1531 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
15771532 fmt::from_fn(move |f| match self.did {
15781533 Some(did) => resolved_path(f, did, &self.path, true, false, cx),
15791534 _ => {
......@@ -1593,10 +1548,7 @@ impl clean::ImportSource {
15931548}
15941549
15951550impl clean::AssocItemConstraint {
1596 pub(crate) fn print<'a, 'tcx: 'a>(
1597 &'a self,
1598 cx: &'a Context<'tcx>,
1599 ) -> impl Display + 'a + Captures<'tcx> {
1551 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
16001552 fmt::from_fn(move |f| {
16011553 f.write_str(self.assoc.name.as_str())?;
16021554 self.assoc.args.print(cx).fmt(f)?;
......@@ -1627,15 +1579,12 @@ pub(crate) fn print_abi_with_space(abi: ExternAbi) -> impl Display {
16271579 })
16281580}
16291581
1630pub(crate) fn print_default_space<'a>(v: bool) -> &'a str {
1582pub(crate) fn print_default_space(v: bool) -> &'static str {
16311583 if v { "default " } else { "" }
16321584}
16331585
16341586impl clean::GenericArg {
1635 pub(crate) fn print<'a, 'tcx: 'a>(
1636 &'a self,
1637 cx: &'a Context<'tcx>,
1638 ) -> impl Display + 'a + Captures<'tcx> {
1587 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
16391588 fmt::from_fn(move |f| match self {
16401589 clean::GenericArg::Lifetime(lt) => lt.print().fmt(f),
16411590 clean::GenericArg::Type(ty) => ty.print(cx).fmt(f),
......@@ -1646,10 +1595,7 @@ impl clean::GenericArg {
16461595}
16471596
16481597impl clean::Term {
1649 pub(crate) fn print<'a, 'tcx: 'a>(
1650 &'a self,
1651 cx: &'a Context<'tcx>,
1652 ) -> impl Display + 'a + Captures<'tcx> {
1598 pub(crate) fn print(&self, cx: &Context<'_>) -> impl Display {
16531599 fmt::from_fn(move |f| match self {
16541600 clean::Term::Type(ty) => ty.print(cx).fmt(f),
16551601 clean::Term::Constant(ct) => ct.print(cx.tcx()).fmt(f),
src/librustdoc/html/render/mod.rs+102-107
......@@ -47,7 +47,6 @@ use rinja::Template;
4747use rustc_attr_parsing::{
4848 ConstStability, DeprecatedSince, Deprecation, RustcVersion, StabilityLevel, StableSince,
4949};
50use rustc_data_structures::captures::Captures;
5150use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
5251use rustc_hir::Mutability;
5352use rustc_hir::def_id::{DefId, DefIdSet};
......@@ -82,7 +81,7 @@ use crate::html::{highlight, sources};
8281use crate::scrape_examples::{CallData, CallLocation};
8382use crate::{DOC_RUST_LANG_ORG_VERSION, try_none};
8483
85pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display + '_ {
84pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display {
8685 fmt::from_fn(move |f| {
8786 if !v.ends_with('/') && !v.is_empty() { write!(f, "{v}/") } else { f.write_str(v) }
8887 })
......@@ -310,7 +309,7 @@ impl ItemEntry {
310309}
311310
312311impl ItemEntry {
313 pub(crate) fn print(&self) -> impl fmt::Display + '_ {
312 pub(crate) fn print(&self) -> impl fmt::Display {
314313 fmt::from_fn(move |f| write!(f, "<a href=\"{}\">{}</a>", self.url, Escape(&self.name)))
315314 }
316315}
......@@ -505,12 +504,12 @@ fn scrape_examples_help(shared: &SharedContext<'_>) -> String {
505504 )
506505}
507506
508fn document<'a, 'cx: 'a>(
509 cx: &'a Context<'cx>,
510 item: &'a clean::Item,
511 parent: Option<&'a clean::Item>,
507fn document(
508 cx: &Context<'_>,
509 item: &clean::Item,
510 parent: Option<&clean::Item>,
512511 heading_offset: HeadingOffset,
513) -> impl fmt::Display + 'a + Captures<'cx> {
512) -> impl fmt::Display {
514513 if let Some(ref name) = item.name {
515514 info!("Documenting {name}");
516515 }
......@@ -526,12 +525,12 @@ fn document<'a, 'cx: 'a>(
526525}
527526
528527/// Render md_text as markdown.
529fn render_markdown<'a, 'cx: 'a>(
530 cx: &'a Context<'cx>,
531 md_text: &'a str,
528fn render_markdown(
529 cx: &Context<'_>,
530 md_text: &str,
532531 links: Vec<RenderedLink>,
533532 heading_offset: HeadingOffset,
534) -> impl fmt::Display + 'a + Captures<'cx> {
533) -> impl fmt::Display {
535534 fmt::from_fn(move |f| {
536535 write!(
537536 f,
......@@ -552,13 +551,13 @@ fn render_markdown<'a, 'cx: 'a>(
552551
553552/// Writes a documentation block containing only the first paragraph of the documentation. If the
554553/// docs are longer, a "Read more" link is appended to the end.
555fn document_short<'a, 'cx: 'a>(
556 item: &'a clean::Item,
557 cx: &'a Context<'cx>,
558 link: AssocItemLink<'a>,
559 parent: &'a clean::Item,
554fn document_short(
555 item: &clean::Item,
556 cx: &Context<'_>,
557 link: AssocItemLink<'_>,
558 parent: &clean::Item,
560559 show_def_docs: bool,
561) -> impl fmt::Display + 'a + Captures<'cx> {
560) -> impl fmt::Display {
562561 fmt::from_fn(move |f| {
563562 document_item_info(cx, item, Some(parent)).render_into(f).unwrap();
564563 if !show_def_docs {
......@@ -595,28 +594,28 @@ fn document_short<'a, 'cx: 'a>(
595594 })
596595}
597596
598fn document_full_collapsible<'a, 'cx: 'a>(
599 item: &'a clean::Item,
600 cx: &'a Context<'cx>,
597fn document_full_collapsible(
598 item: &clean::Item,
599 cx: &Context<'_>,
601600 heading_offset: HeadingOffset,
602) -> impl fmt::Display + 'a + Captures<'cx> {
601) -> impl fmt::Display {
603602 document_full_inner(item, cx, true, heading_offset)
604603}
605604
606fn document_full<'a, 'cx: 'a>(
607 item: &'a clean::Item,
608 cx: &'a Context<'cx>,
605fn document_full(
606 item: &clean::Item,
607 cx: &Context<'_>,
609608 heading_offset: HeadingOffset,
610) -> impl fmt::Display + 'a + Captures<'cx> {
609) -> impl fmt::Display {
611610 document_full_inner(item, cx, false, heading_offset)
612611}
613612
614fn document_full_inner<'a, 'cx: 'a>(
615 item: &'a clean::Item,
616 cx: &'a Context<'cx>,
613fn document_full_inner(
614 item: &clean::Item,
615 cx: &Context<'_>,
617616 is_collapsible: bool,
618617 heading_offset: HeadingOffset,
619) -> impl fmt::Display + 'a + Captures<'cx> {
618) -> impl fmt::Display {
620619 fmt::from_fn(move |f| {
621620 if let Some(s) = item.opt_doc_value() {
622621 debug!("Doc block: =====\n{s}\n=====");
......@@ -797,11 +796,11 @@ pub(crate) fn render_impls(
797796}
798797
799798/// Build a (possibly empty) `href` attribute (a key-value pair) for the given associated item.
800fn assoc_href_attr<'a, 'tcx>(
799fn assoc_href_attr(
801800 it: &clean::Item,
802 link: AssocItemLink<'a>,
803 cx: &Context<'tcx>,
804) -> Option<impl fmt::Display + 'a + Captures<'tcx>> {
801 link: AssocItemLink<'_>,
802 cx: &Context<'_>,
803) -> Option<impl fmt::Display> {
805804 let name = it.name.unwrap();
806805 let item_type = it.type_();
807806
......@@ -812,7 +811,7 @@ fn assoc_href_attr<'a, 'tcx>(
812811 }
813812
814813 let href = match link {
815 AssocItemLink::Anchor(Some(ref id)) => Href::AnchorId(id),
814 AssocItemLink::Anchor(Some(id)) => Href::AnchorId(id),
816815 AssocItemLink::Anchor(None) => Href::Anchor(item_type),
817816 AssocItemLink::GotoSource(did, provided_methods) => {
818817 // We're creating a link from the implementation of an associated item to its
......@@ -877,15 +876,15 @@ enum AssocConstValue<'a> {
877876 None,
878877}
879878
880fn assoc_const<'a, 'tcx>(
881 it: &'a clean::Item,
882 generics: &'a clean::Generics,
883 ty: &'a clean::Type,
884 value: AssocConstValue<'a>,
885 link: AssocItemLink<'a>,
879fn assoc_const(
880 it: &clean::Item,
881 generics: &clean::Generics,
882 ty: &clean::Type,
883 value: AssocConstValue<'_>,
884 link: AssocItemLink<'_>,
886885 indent: usize,
887 cx: &'a Context<'tcx>,
888) -> impl fmt::Display + 'a + Captures<'tcx> {
886 cx: &Context<'_>,
887) -> impl fmt::Display {
889888 let tcx = cx.tcx();
890889 fmt::from_fn(move |w| {
891890 write!(
......@@ -917,15 +916,15 @@ fn assoc_const<'a, 'tcx>(
917916 })
918917}
919918
920fn assoc_type<'a, 'tcx>(
921 it: &'a clean::Item,
922 generics: &'a clean::Generics,
923 bounds: &'a [clean::GenericBound],
924 default: Option<&'a clean::Type>,
925 link: AssocItemLink<'a>,
919fn assoc_type(
920 it: &clean::Item,
921 generics: &clean::Generics,
922 bounds: &[clean::GenericBound],
923 default: Option<&clean::Type>,
924 link: AssocItemLink<'_>,
926925 indent: usize,
927 cx: &'a Context<'tcx>,
928) -> impl fmt::Display + 'a + Captures<'tcx> {
926 cx: &Context<'_>,
927) -> impl fmt::Display {
929928 fmt::from_fn(move |w| {
930929 write!(
931930 w,
......@@ -947,15 +946,15 @@ fn assoc_type<'a, 'tcx>(
947946 })
948947}
949948
950fn assoc_method<'a, 'tcx>(
951 meth: &'a clean::Item,
952 g: &'a clean::Generics,
953 d: &'a clean::FnDecl,
954 link: AssocItemLink<'a>,
949fn assoc_method(
950 meth: &clean::Item,
951 g: &clean::Generics,
952 d: &clean::FnDecl,
953 link: AssocItemLink<'_>,
955954 parent: ItemType,
956 cx: &'a Context<'tcx>,
955 cx: &Context<'_>,
957956 render_mode: RenderMode,
958) -> impl fmt::Display + 'a + Captures<'tcx> {
957) -> impl fmt::Display {
959958 let tcx = cx.tcx();
960959 let header = meth.fn_header(tcx).expect("Trying to get header from a non-function item");
961960 let name = meth.name.as_ref().unwrap();
......@@ -1031,7 +1030,7 @@ fn render_stability_since_raw_with_extra(
10311030 stable_version: Option<StableSince>,
10321031 const_stability: Option<ConstStability>,
10331032 extra_class: &str,
1034) -> Option<impl fmt::Display + '_> {
1033) -> Option<impl fmt::Display> {
10351034 let mut title = String::new();
10361035 let mut stability = String::new();
10371036
......@@ -1102,13 +1101,13 @@ fn render_stability_since_raw(
11021101 render_stability_since_raw_with_extra(ver, const_stability, "")
11031102}
11041103
1105fn render_assoc_item<'a, 'tcx>(
1106 item: &'a clean::Item,
1107 link: AssocItemLink<'a>,
1104fn render_assoc_item(
1105 item: &clean::Item,
1106 link: AssocItemLink<'_>,
11081107 parent: ItemType,
1109 cx: &'a Context<'tcx>,
1108 cx: &Context<'_>,
11101109 render_mode: RenderMode,
1111) -> impl fmt::Display + 'a + Captures<'tcx> {
1110) -> impl fmt::Display {
11121111 fmt::from_fn(move |f| match &item.kind {
11131112 clean::StrippedItem(..) => Ok(()),
11141113 clean::RequiredMethodItem(m) | clean::MethodItem(m, _) => {
......@@ -1144,7 +1143,7 @@ fn render_assoc_item<'a, 'tcx>(
11441143 cx,
11451144 )
11461145 .fmt(f),
1147 clean::RequiredAssocTypeItem(ref generics, ref bounds) => assoc_type(
1146 clean::RequiredAssocTypeItem(generics, bounds) => assoc_type(
11481147 item,
11491148 generics,
11501149 bounds,
......@@ -1154,7 +1153,7 @@ fn render_assoc_item<'a, 'tcx>(
11541153 cx,
11551154 )
11561155 .fmt(f),
1157 clean::AssocTypeItem(ref ty, ref bounds) => assoc_type(
1156 clean::AssocTypeItem(ty, bounds) => assoc_type(
11581157 item,
11591158 &ty.generics,
11601159 bounds,
......@@ -1170,11 +1169,7 @@ fn render_assoc_item<'a, 'tcx>(
11701169
11711170// When an attribute is rendered inside a `<pre>` tag, it is formatted using
11721171// a whitespace prefix and newline.
1173fn render_attributes_in_pre<'a, 'tcx: 'a>(
1174 it: &'a clean::Item,
1175 prefix: &'a str,
1176 cx: &'a Context<'tcx>,
1177) -> impl fmt::Display + Captures<'a> + Captures<'tcx> {
1172fn render_attributes_in_pre(it: &clean::Item, prefix: &str, cx: &Context<'_>) -> impl fmt::Display {
11781173 fmt::from_fn(move |f| {
11791174 for a in it.attributes(cx.tcx(), cx.cache(), false) {
11801175 writeln!(f, "{prefix}{a}")?;
......@@ -1206,12 +1201,12 @@ impl<'a> AssocItemLink<'a> {
12061201 }
12071202}
12081203
1209pub fn write_section_heading<'a>(
1210 title: &'a str,
1211 id: &'a str,
1212 extra_class: Option<&'a str>,
1213 extra: impl fmt::Display + 'a,
1214) -> impl fmt::Display + 'a {
1204pub fn write_section_heading(
1205 title: &str,
1206 id: &str,
1207 extra_class: Option<&str>,
1208 extra: impl fmt::Display,
1209) -> impl fmt::Display {
12151210 fmt::from_fn(move |w| {
12161211 let (extra_class, whitespace) = match extra_class {
12171212 Some(extra) => (extra, " "),
......@@ -1227,7 +1222,7 @@ pub fn write_section_heading<'a>(
12271222 })
12281223}
12291224
1230fn write_impl_section_heading<'a>(title: &'a str, id: &'a str) -> impl fmt::Display + 'a {
1225fn write_impl_section_heading(title: &str, id: &str) -> impl fmt::Display {
12311226 write_section_heading(title, id, None, "")
12321227}
12331228
......@@ -1276,12 +1271,12 @@ pub(crate) fn render_all_impls(
12761271 }
12771272}
12781273
1279fn render_assoc_items<'a, 'cx: 'a>(
1280 cx: &'a Context<'cx>,
1281 containing_item: &'a clean::Item,
1274fn render_assoc_items(
1275 cx: &Context<'_>,
1276 containing_item: &clean::Item,
12821277 it: DefId,
1283 what: AssocItemRender<'a>,
1284) -> impl fmt::Display + 'a + Captures<'cx> {
1278 what: AssocItemRender<'_>,
1279) -> impl fmt::Display {
12851280 fmt::from_fn(move |f| {
12861281 let mut derefs = DefIdSet::default();
12871282 derefs.insert(it);
......@@ -1466,10 +1461,10 @@ fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) ->
14661461 }
14671462}
14681463
1469pub(crate) fn notable_traits_button<'a, 'tcx>(
1470 ty: &'a clean::Type,
1471 cx: &'a Context<'tcx>,
1472) -> Option<impl fmt::Display + 'a + Captures<'tcx>> {
1464pub(crate) fn notable_traits_button(
1465 ty: &clean::Type,
1466 cx: &Context<'_>,
1467) -> Option<impl fmt::Display> {
14731468 let mut has_notable_trait = false;
14741469
14751470 if ty.is_unit() {
......@@ -1623,16 +1618,16 @@ struct ImplRenderingParameters {
16231618 toggle_open_by_default: bool,
16241619}
16251620
1626fn render_impl<'a, 'tcx>(
1627 cx: &'a Context<'tcx>,
1628 i: &'a Impl,
1629 parent: &'a clean::Item,
1630 link: AssocItemLink<'a>,
1621fn render_impl(
1622 cx: &Context<'_>,
1623 i: &Impl,
1624 parent: &clean::Item,
1625 link: AssocItemLink<'_>,
16311626 render_mode: RenderMode,
16321627 use_absolute: Option<bool>,
1633 aliases: &'a [String],
1628 aliases: &[String],
16341629 rendering_params: ImplRenderingParameters,
1635) -> impl fmt::Display + 'a + Captures<'tcx> {
1630) -> impl fmt::Display {
16361631 fmt::from_fn(move |w| {
16371632 let cache = &cx.shared.cache;
16381633 let traits = &cache.traits;
......@@ -1780,7 +1775,7 @@ fn render_impl<'a, 'tcx>(
17801775 );
17811776 }
17821777 }
1783 clean::RequiredAssocConstItem(ref generics, ref ty) => {
1778 clean::RequiredAssocConstItem(generics, ty) => {
17841779 let source_id = format!("{item_type}.{name}");
17851780 let id = cx.derive_id(&source_id);
17861781 write_str(
......@@ -1847,7 +1842,7 @@ fn render_impl<'a, 'tcx>(
18471842 ),
18481843 );
18491844 }
1850 clean::RequiredAssocTypeItem(ref generics, ref bounds) => {
1845 clean::RequiredAssocTypeItem(generics, bounds) => {
18511846 let source_id = format!("{item_type}.{name}");
18521847 let id = cx.derive_id(&source_id);
18531848 write_str(
......@@ -2135,11 +2130,11 @@ fn render_impl<'a, 'tcx>(
21352130
21362131// Render the items that appear on the right side of methods, impls, and
21372132// associated types. For example "1.0.0 (const: 1.39.0) · source".
2138fn render_rightside<'a, 'tcx>(
2139 cx: &'a Context<'tcx>,
2140 item: &'a clean::Item,
2133fn render_rightside(
2134 cx: &Context<'_>,
2135 item: &clean::Item,
21412136 render_mode: RenderMode,
2142) -> impl fmt::Display + 'a + Captures<'tcx> {
2137) -> impl fmt::Display {
21432138 let tcx = cx.tcx();
21442139
21452140 fmt::from_fn(move |w| {
......@@ -2174,17 +2169,17 @@ fn render_rightside<'a, 'tcx>(
21742169 })
21752170}
21762171
2177pub(crate) fn render_impl_summary<'a, 'tcx>(
2178 cx: &'a Context<'tcx>,
2179 i: &'a Impl,
2180 parent: &'a clean::Item,
2172pub(crate) fn render_impl_summary(
2173 cx: &Context<'_>,
2174 i: &Impl,
2175 parent: &clean::Item,
21812176 show_def_docs: bool,
21822177 use_absolute: Option<bool>,
21832178 // This argument is used to reference same type with different paths to avoid duplication
21842179 // in documentation pages for trait with automatic implementations like "Send" and "Sync".
2185 aliases: &'a [String],
2186 doc: Option<&'a str>,
2187) -> impl fmt::Display + 'a + Captures<'tcx> {
2180 aliases: &[String],
2181 doc: Option<&str>,
2182) -> impl fmt::Display {
21882183 fmt::from_fn(move |w| {
21892184 let inner_impl = i.inner_impl();
21902185 let id = cx.derive_id(get_id_for_impl(cx.tcx(), i.impl_item.item_id));
src/librustdoc/html/render/print_item.rs+120-207
......@@ -4,7 +4,6 @@ use std::fmt::{Display, Write as _};
44
55use rinja::Template;
66use rustc_abi::VariantIdx;
7use rustc_data_structures::captures::Captures;
87use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
98use rustc_hir as hir;
109use rustc_hir::def::CtorKind;
......@@ -92,44 +91,32 @@ macro_rules! item_template {
9291macro_rules! item_template_methods {
9392 () => {};
9493 (document $($rest:tt)*) => {
95 fn document<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
96 fmt::from_fn(move |f| {
97 let (item, cx) = self.item_and_cx();
98 let v = document(cx, item, None, HeadingOffset::H2);
99 write!(f, "{v}")
100 })
94 fn document(&self) -> impl fmt::Display {
95 let (item, cx) = self.item_and_cx();
96 document(cx, item, None, HeadingOffset::H2)
10197 }
10298 item_template_methods!($($rest)*);
10399 };
104100 (document_type_layout $($rest:tt)*) => {
105 fn document_type_layout<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
106 fmt::from_fn(move |f| {
107 let (item, cx) = self.item_and_cx();
108 let def_id = item.item_id.expect_def_id();
109 let v = document_type_layout(cx, def_id);
110 write!(f, "{v}")
111 })
101 fn document_type_layout(&self) -> impl fmt::Display {
102 let (item, cx) = self.item_and_cx();
103 let def_id = item.item_id.expect_def_id();
104 document_type_layout(cx, def_id)
112105 }
113106 item_template_methods!($($rest)*);
114107 };
115108 (render_attributes_in_pre $($rest:tt)*) => {
116 fn render_attributes_in_pre<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
117 fmt::from_fn(move |f| {
118 let (item, cx) = self.item_and_cx();
119 let v = render_attributes_in_pre(item, "", cx);
120 write!(f, "{v}")
121 })
109 fn render_attributes_in_pre(&self) -> impl fmt::Display {
110 let (item, cx) = self.item_and_cx();
111 render_attributes_in_pre(item, "", cx)
122112 }
123113 item_template_methods!($($rest)*);
124114 };
125115 (render_assoc_items $($rest:tt)*) => {
126 fn render_assoc_items<'b>(&'b self) -> impl fmt::Display + Captures<'a> + 'b + Captures<'cx> {
127 fmt::from_fn(move |f| {
128 let (item, cx) = self.item_and_cx();
129 let def_id = item.item_id.expect_def_id();
130 let v = render_assoc_items(cx, item, def_id, AssocItemRender::All);
131 write!(f, "{v}")
132 })
116 fn render_assoc_items(&self) -> impl fmt::Display {
117 let (item, cx) = self.item_and_cx();
118 let def_id = item.item_id.expect_def_id();
119 render_assoc_items(cx, item, def_id, AssocItemRender::All)
133120 }
134121 item_template_methods!($($rest)*);
135122 };
......@@ -162,10 +149,7 @@ struct ItemVars<'a> {
162149 src_href: Option<&'a str>,
163150}
164151
165pub(super) fn print_item<'a, 'tcx>(
166 cx: &'a Context<'tcx>,
167 item: &'a clean::Item,
168) -> impl fmt::Display + 'a + Captures<'tcx> {
152pub(super) fn print_item(cx: &Context<'_>, item: &clean::Item) -> impl fmt::Display {
169153 debug_assert!(!item.is_stripped());
170154
171155 fmt::from_fn(|buf| {
......@@ -241,30 +225,30 @@ pub(super) fn print_item<'a, 'tcx>(
241225 item_vars.render_into(buf).unwrap();
242226
243227 match &item.kind {
244 clean::ModuleItem(ref m) => {
228 clean::ModuleItem(m) => {
245229 write!(buf, "{}", item_module(cx, item, &m.items))
246230 }
247 clean::FunctionItem(ref f) | clean::ForeignFunctionItem(ref f, _) => {
231 clean::FunctionItem(f) | clean::ForeignFunctionItem(f, _) => {
248232 write!(buf, "{}", item_function(cx, item, f))
249233 }
250 clean::TraitItem(ref t) => write!(buf, "{}", item_trait(cx, item, t)),
251 clean::StructItem(ref s) => {
234 clean::TraitItem(t) => write!(buf, "{}", item_trait(cx, item, t)),
235 clean::StructItem(s) => {
252236 write!(buf, "{}", item_struct(cx, item, s))
253237 }
254 clean::UnionItem(ref s) => write!(buf, "{}", item_union(cx, item, s)),
255 clean::EnumItem(ref e) => write!(buf, "{}", item_enum(cx, item, e)),
256 clean::TypeAliasItem(ref t) => {
238 clean::UnionItem(s) => write!(buf, "{}", item_union(cx, item, s)),
239 clean::EnumItem(e) => write!(buf, "{}", item_enum(cx, item, e)),
240 clean::TypeAliasItem(t) => {
257241 write!(buf, "{}", item_type_alias(cx, item, t))
258242 }
259 clean::MacroItem(ref m) => write!(buf, "{}", item_macro(cx, item, m)),
260 clean::ProcMacroItem(ref m) => {
243 clean::MacroItem(m) => write!(buf, "{}", item_macro(cx, item, m)),
244 clean::ProcMacroItem(m) => {
261245 write!(buf, "{}", item_proc_macro(cx, item, m))
262246 }
263247 clean::PrimitiveItem(_) => write!(buf, "{}", item_primitive(cx, item)),
264 clean::StaticItem(ref i) => {
248 clean::StaticItem(i) => {
265249 write!(buf, "{}", item_static(cx, item, i, None))
266250 }
267 clean::ForeignStaticItem(ref i, safety) => {
251 clean::ForeignStaticItem(i, safety) => {
268252 write!(buf, "{}", item_static(cx, item, i, Some(*safety)))
269253 }
270254 clean::ConstantItem(ci) => {
......@@ -274,7 +258,7 @@ pub(super) fn print_item<'a, 'tcx>(
274258 write!(buf, "{}", item_foreign_type(cx, item))
275259 }
276260 clean::KeywordItem => write!(buf, "{}", item_keyword(cx, item)),
277 clean::TraitAliasItem(ref ta) => {
261 clean::TraitAliasItem(ta) => {
278262 write!(buf, "{}", item_trait_alias(cx, item, ta))
279263 }
280264 _ => {
......@@ -321,11 +305,7 @@ trait ItemTemplate<'a, 'cx: 'a>: rinja::Template + Display {
321305 fn item_and_cx(&self) -> (&'a clean::Item, &'a Context<'cx>);
322306}
323307
324fn item_module<'a, 'tcx>(
325 cx: &'a Context<'tcx>,
326 item: &'a clean::Item,
327 items: &'a [clean::Item],
328) -> impl fmt::Display + 'a + Captures<'tcx> {
308fn item_module(cx: &Context<'_>, item: &clean::Item, items: &[clean::Item]) -> impl fmt::Display {
329309 fmt::from_fn(|w| {
330310 write!(w, "{}", document(cx, item, None, HeadingOffset::H2))?;
331311
......@@ -541,14 +521,14 @@ fn item_module<'a, 'tcx>(
541521
542522/// Render the stability, deprecation and portability tags that are displayed in the item's summary
543523/// at the module level.
544fn extra_info_tags<'a, 'tcx: 'a>(
545 tcx: TyCtxt<'tcx>,
546 item: &'a clean::Item,
547 parent: &'a clean::Item,
524fn extra_info_tags(
525 tcx: TyCtxt<'_>,
526 item: &clean::Item,
527 parent: &clean::Item,
548528 import_def_id: Option<DefId>,
549) -> impl Display + 'a + Captures<'tcx> {
529) -> impl Display {
550530 fmt::from_fn(move |f| {
551 fn tag_html<'a>(class: &'a str, title: &'a str, contents: &'a str) -> impl Display + 'a {
531 fn tag_html(class: &str, title: &str, contents: &str) -> impl Display {
552532 fmt::from_fn(move |f| {
553533 write!(
554534 f,
......@@ -597,11 +577,7 @@ fn extra_info_tags<'a, 'tcx: 'a>(
597577 })
598578}
599579
600fn item_function<'a, 'tcx>(
601 cx: &'a Context<'tcx>,
602 it: &'a clean::Item,
603 f: &'a clean::Function,
604) -> impl fmt::Display + 'a + Captures<'tcx> {
580fn item_function(cx: &Context<'_>, it: &clean::Item, f: &clean::Function) -> impl fmt::Display {
605581 fmt::from_fn(|w| {
606582 let tcx = cx.tcx();
607583 let header = it.fn_header(tcx).expect("printing a function which isn't a function");
......@@ -657,11 +633,7 @@ fn item_function<'a, 'tcx>(
657633 })
658634}
659635
660fn item_trait<'a, 'tcx>(
661 cx: &'a Context<'tcx>,
662 it: &'a clean::Item,
663 t: &'a clean::Trait,
664) -> impl fmt::Display + 'a + Captures<'tcx> {
636fn item_trait(cx: &Context<'_>, it: &clean::Item, t: &clean::Trait) -> impl fmt::Display {
665637 fmt::from_fn(|w| {
666638 let tcx = cx.tcx();
667639 let bounds = bounds(&t.bounds, false, cx);
......@@ -831,11 +803,7 @@ fn item_trait<'a, 'tcx>(
831803 // Trait documentation
832804 write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
833805
834 fn trait_item<'a, 'tcx>(
835 cx: &'a Context<'tcx>,
836 m: &'a clean::Item,
837 t: &'a clean::Item,
838 ) -> impl fmt::Display + 'a + Captures<'tcx> {
806 fn trait_item(cx: &Context<'_>, m: &clean::Item, t: &clean::Item) -> impl fmt::Display {
839807 fmt::from_fn(|w| {
840808 let name = m.name.unwrap();
841809 info!("Documenting {name} on {ty_name:?}", ty_name = t.name);
......@@ -1021,7 +989,7 @@ fn item_trait<'a, 'tcx>(
1021989 extern_crates.insert(did.krate);
1022990 }
1023991 match implementor.inner_impl().for_.without_borrowed_ref() {
1024 clean::Type::Path { ref path } if !path.is_assoc_ty() => {
992 clean::Type::Path { path } if !path.is_assoc_ty() => {
1025993 let did = path.def_id();
1026994 let &mut (prev_did, ref mut has_duplicates) =
1027995 implementor_dups.entry(path.last()).or_insert((did, false));
......@@ -1254,11 +1222,11 @@ fn item_trait<'a, 'tcx>(
12541222 })
12551223}
12561224
1257fn item_trait_alias<'a, 'tcx>(
1258 cx: &'a Context<'tcx>,
1259 it: &'a clean::Item,
1260 t: &'a clean::TraitAlias,
1261) -> impl fmt::Display + 'a + Captures<'tcx> {
1225fn item_trait_alias(
1226 cx: &Context<'_>,
1227 it: &clean::Item,
1228 t: &clean::TraitAlias,
1229) -> impl fmt::Display {
12621230 fmt::from_fn(|w| {
12631231 wrap_item(w, |w| {
12641232 write!(
......@@ -1285,11 +1253,7 @@ fn item_trait_alias<'a, 'tcx>(
12851253 })
12861254}
12871255
1288fn item_type_alias<'a, 'tcx>(
1289 cx: &'a Context<'tcx>,
1290 it: &'a clean::Item,
1291 t: &'a clean::TypeAlias,
1292) -> impl fmt::Display + 'a + Captures<'tcx> {
1256fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> impl fmt::Display {
12931257 fmt::from_fn(|w| {
12941258 wrap_item(w, |w| {
12951259 write!(
......@@ -1499,11 +1463,7 @@ fn item_type_alias<'a, 'tcx>(
14991463 })
15001464}
15011465
1502fn item_union<'a, 'tcx>(
1503 cx: &'a Context<'tcx>,
1504 it: &'a clean::Item,
1505 s: &'a clean::Union,
1506) -> impl fmt::Display + 'a + Captures<'tcx> {
1466fn item_union(cx: &Context<'_>, it: &clean::Item, s: &clean::Union) -> impl fmt::Display {
15071467 item_template!(
15081468 #[template(path = "item_union.html")]
15091469 struct ItemUnion<'a, 'cx> {
......@@ -1515,35 +1475,20 @@ fn item_union<'a, 'tcx>(
15151475 );
15161476
15171477 impl<'a, 'cx: 'a> ItemUnion<'a, 'cx> {
1518 fn render_union<'b>(&'b self) -> impl Display + Captures<'a> + 'b + Captures<'cx> {
1519 fmt::from_fn(move |f| {
1520 let v = render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx);
1521 write!(f, "{v}")
1522 })
1478 fn render_union(&self) -> impl Display {
1479 render_union(self.it, Some(&self.s.generics), &self.s.fields, self.cx)
15231480 }
15241481
1525 fn document_field<'b>(
1526 &'b self,
1527 field: &'a clean::Item,
1528 ) -> impl Display + Captures<'a> + 'b + Captures<'cx> {
1529 fmt::from_fn(move |f| {
1530 let v = document(self.cx, field, Some(self.it), HeadingOffset::H3);
1531 write!(f, "{v}")
1532 })
1482 fn document_field(&self, field: &'a clean::Item) -> impl Display {
1483 document(self.cx, field, Some(self.it), HeadingOffset::H3)
15331484 }
15341485
15351486 fn stability_field(&self, field: &clean::Item) -> Option<String> {
15361487 field.stability_class(self.cx.tcx())
15371488 }
15381489
1539 fn print_ty<'b>(
1540 &'b self,
1541 ty: &'a clean::Type,
1542 ) -> impl Display + Captures<'a> + 'b + Captures<'cx> {
1543 fmt::from_fn(move |f| {
1544 let v = ty.print(self.cx);
1545 write!(f, "{v}")
1546 })
1490 fn print_ty(&self, ty: &'a clean::Type) -> impl Display {
1491 ty.print(self.cx)
15471492 }
15481493
15491494 fn fields_iter(
......@@ -1566,10 +1511,7 @@ fn item_union<'a, 'tcx>(
15661511 })
15671512}
15681513
1569fn print_tuple_struct_fields<'a, 'cx: 'a>(
1570 cx: &'a Context<'cx>,
1571 s: &'a [clean::Item],
1572) -> impl Display + 'a + Captures<'cx> {
1514fn print_tuple_struct_fields(cx: &Context<'_>, s: &[clean::Item]) -> impl Display {
15731515 fmt::from_fn(|f| {
15741516 if !s.is_empty()
15751517 && s.iter().all(|field| {
......@@ -1591,11 +1533,7 @@ fn print_tuple_struct_fields<'a, 'cx: 'a>(
15911533 })
15921534}
15931535
1594fn item_enum<'a, 'tcx>(
1595 cx: &'a Context<'tcx>,
1596 it: &'a clean::Item,
1597 e: &'a clean::Enum,
1598) -> impl fmt::Display + 'a + Captures<'tcx> {
1536fn item_enum(cx: &Context<'_>, it: &clean::Item, e: &clean::Enum) -> impl fmt::Display {
15991537 fmt::from_fn(|w| {
16001538 let count_variants = e.variants().count();
16011539 wrap_item(w, |w| {
......@@ -1658,14 +1596,14 @@ fn should_show_enum_discriminant(
16581596 repr.c() || repr.int.is_some()
16591597}
16601598
1661fn display_c_like_variant<'a, 'tcx>(
1662 cx: &'a Context<'tcx>,
1663 item: &'a clean::Item,
1664 variant: &'a clean::Variant,
1599fn display_c_like_variant(
1600 cx: &Context<'_>,
1601 item: &clean::Item,
1602 variant: &clean::Variant,
16651603 index: VariantIdx,
16661604 should_show_enum_discriminant: bool,
16671605 enum_def_id: DefId,
1668) -> impl fmt::Display + 'a + Captures<'tcx> {
1606) -> impl fmt::Display {
16691607 fmt::from_fn(move |w| {
16701608 let name = item.name.unwrap();
16711609 if let Some(ref value) = variant.discriminant {
......@@ -1685,15 +1623,15 @@ fn display_c_like_variant<'a, 'tcx>(
16851623 })
16861624}
16871625
1688fn render_enum_fields<'a, 'tcx>(
1689 cx: &'a Context<'tcx>,
1690 g: Option<&'a clean::Generics>,
1691 variants: &'a IndexVec<VariantIdx, clean::Item>,
1626fn render_enum_fields(
1627 cx: &Context<'_>,
1628 g: Option<&clean::Generics>,
1629 variants: &IndexVec<VariantIdx, clean::Item>,
16921630 count_variants: usize,
16931631 has_stripped_entries: bool,
16941632 is_non_exhaustive: bool,
16951633 enum_def_id: DefId,
1696) -> impl fmt::Display + 'a + Captures<'tcx> {
1634) -> impl fmt::Display {
16971635 fmt::from_fn(move |w| {
16981636 let should_show_enum_discriminant =
16991637 should_show_enum_discriminant(cx, enum_def_id, variants);
......@@ -1764,12 +1702,12 @@ fn render_enum_fields<'a, 'tcx>(
17641702 })
17651703}
17661704
1767fn item_variants<'a, 'tcx>(
1768 cx: &'a Context<'tcx>,
1769 it: &'a clean::Item,
1770 variants: &'a IndexVec<VariantIdx, clean::Item>,
1705fn item_variants(
1706 cx: &Context<'_>,
1707 it: &clean::Item,
1708 variants: &IndexVec<VariantIdx, clean::Item>,
17711709 enum_def_id: DefId,
1772) -> impl fmt::Display + 'a + Captures<'tcx> {
1710) -> impl fmt::Display {
17731711 fmt::from_fn(move |w| {
17741712 let tcx = cx.tcx();
17751713 write!(
......@@ -1895,11 +1833,7 @@ fn item_variants<'a, 'tcx>(
18951833 })
18961834}
18971835
1898fn item_macro<'a, 'tcx>(
1899 cx: &'a Context<'tcx>,
1900 it: &'a clean::Item,
1901 t: &'a clean::Macro,
1902) -> impl fmt::Display + 'a + Captures<'tcx> {
1836fn item_macro(cx: &Context<'_>, it: &clean::Item, t: &clean::Macro) -> impl fmt::Display {
19031837 fmt::from_fn(|w| {
19041838 wrap_item(w, |w| {
19051839 // FIXME: Also print `#[doc(hidden)]` for `macro_rules!` if it `is_doc_hidden`.
......@@ -1912,11 +1846,7 @@ fn item_macro<'a, 'tcx>(
19121846 })
19131847}
19141848
1915fn item_proc_macro<'a, 'tcx>(
1916 cx: &'a Context<'tcx>,
1917 it: &'a clean::Item,
1918 m: &'a clean::ProcMacro,
1919) -> impl fmt::Display + 'a + Captures<'tcx> {
1849fn item_proc_macro(cx: &Context<'_>, it: &clean::Item, m: &clean::ProcMacro) -> impl fmt::Display {
19201850 fmt::from_fn(|w| {
19211851 wrap_item(w, |w| {
19221852 let name = it.name.expect("proc-macros always have names");
......@@ -1947,10 +1877,7 @@ fn item_proc_macro<'a, 'tcx>(
19471877 })
19481878}
19491879
1950fn item_primitive<'a, 'tcx>(
1951 cx: &'a Context<'tcx>,
1952 it: &'a clean::Item,
1953) -> impl fmt::Display + 'a + Captures<'tcx> {
1880fn item_primitive(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
19541881 fmt::from_fn(|w| {
19551882 let def_id = it.item_id.expect_def_id();
19561883 write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?;
......@@ -1968,13 +1895,13 @@ fn item_primitive<'a, 'tcx>(
19681895 })
19691896}
19701897
1971fn item_constant<'a, 'tcx>(
1972 cx: &'a Context<'tcx>,
1973 it: &'a clean::Item,
1974 generics: &'a clean::Generics,
1975 ty: &'a clean::Type,
1976 c: &'a clean::ConstantKind,
1977) -> impl fmt::Display + 'a + Captures<'tcx> {
1898fn item_constant(
1899 cx: &Context<'_>,
1900 it: &clean::Item,
1901 generics: &clean::Generics,
1902 ty: &clean::Type,
1903 c: &clean::ConstantKind,
1904) -> impl fmt::Display {
19781905 fmt::from_fn(|w| {
19791906 wrap_item(w, |w| {
19801907 let tcx = cx.tcx();
......@@ -2028,11 +1955,7 @@ fn item_constant<'a, 'tcx>(
20281955 })
20291956}
20301957
2031fn item_struct<'a, 'tcx>(
2032 cx: &'a Context<'tcx>,
2033 it: &'a clean::Item,
2034 s: &'a clean::Struct,
2035) -> impl fmt::Display + 'a + Captures<'tcx> {
1958fn item_struct(cx: &Context<'_>, it: &clean::Item, s: &clean::Struct) -> impl fmt::Display {
20361959 fmt::from_fn(|w| {
20371960 wrap_item(w, |w| {
20381961 render_attributes_in_code(w, it, cx);
......@@ -2056,12 +1979,12 @@ fn item_struct<'a, 'tcx>(
20561979 })
20571980}
20581981
2059fn item_fields<'a, 'tcx>(
2060 cx: &'a Context<'tcx>,
2061 it: &'a clean::Item,
2062 fields: &'a [clean::Item],
1982fn item_fields(
1983 cx: &Context<'_>,
1984 it: &clean::Item,
1985 fields: &[clean::Item],
20631986 ctor_kind: Option<CtorKind>,
2064) -> impl fmt::Display + 'a + Captures<'tcx> {
1987) -> impl fmt::Display {
20651988 fmt::from_fn(move |w| {
20661989 let mut fields = fields
20671990 .iter()
......@@ -2111,12 +2034,12 @@ fn item_fields<'a, 'tcx>(
21112034 })
21122035}
21132036
2114fn item_static<'a, 'tcx>(
2115 cx: &'a Context<'tcx>,
2116 it: &'a clean::Item,
2117 s: &'a clean::Static,
2037fn item_static(
2038 cx: &Context<'_>,
2039 it: &clean::Item,
2040 s: &clean::Static,
21182041 safety: Option<hir::Safety>,
2119) -> impl fmt::Display + 'a + Captures<'tcx> {
2042) -> impl fmt::Display {
21202043 fmt::from_fn(move |w| {
21212044 wrap_item(w, |w| {
21222045 render_attributes_in_code(w, it, cx);
......@@ -2135,10 +2058,7 @@ fn item_static<'a, 'tcx>(
21352058 })
21362059}
21372060
2138fn item_foreign_type<'a, 'tcx>(
2139 cx: &'a Context<'tcx>,
2140 it: &'a clean::Item,
2141) -> impl fmt::Display + 'a + Captures<'tcx> {
2061fn item_foreign_type(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
21422062 fmt::from_fn(|w| {
21432063 wrap_item(w, |w| {
21442064 w.write_str("extern {\n")?;
......@@ -2155,10 +2075,7 @@ fn item_foreign_type<'a, 'tcx>(
21552075 })
21562076}
21572077
2158fn item_keyword<'a, 'tcx>(
2159 cx: &'a Context<'tcx>,
2160 it: &'a clean::Item,
2161) -> impl fmt::Display + 'a + Captures<'tcx> {
2078fn item_keyword(cx: &Context<'_>, it: &clean::Item) -> impl fmt::Display {
21622079 document(cx, it, None, HeadingOffset::H2)
21632080}
21642081
......@@ -2268,18 +2185,14 @@ pub(super) fn full_path(cx: &Context<'_>, item: &clean::Item) -> String {
22682185 s
22692186}
22702187
2271pub(super) fn item_path(ty: ItemType, name: &str) -> impl Display + '_ {
2188pub(super) fn item_path(ty: ItemType, name: &str) -> impl Display {
22722189 fmt::from_fn(move |f| match ty {
22732190 ItemType::Module => write!(f, "{}index.html", ensure_trailing_slash(name)),
22742191 _ => write!(f, "{ty}.{name}.html"),
22752192 })
22762193}
22772194
2278fn bounds<'a, 'tcx>(
2279 bounds: &'a [clean::GenericBound],
2280 trait_alias: bool,
2281 cx: &'a Context<'tcx>,
2282) -> impl Display + 'a + Captures<'tcx> {
2195fn bounds(bounds: &[clean::GenericBound], trait_alias: bool, cx: &Context<'_>) -> impl Display {
22832196 (!bounds.is_empty())
22842197 .then_some(fmt::from_fn(move |f| {
22852198 let has_lots_of_bounds = bounds.len() > 2;
......@@ -2329,13 +2242,13 @@ impl Ord for ImplString {
23292242 }
23302243}
23312244
2332fn render_implementor<'a, 'tcx>(
2333 cx: &'a Context<'tcx>,
2334 implementor: &'a Impl,
2335 trait_: &'a clean::Item,
2336 implementor_dups: &'a FxHashMap<Symbol, (DefId, bool)>,
2337 aliases: &'a [String],
2338) -> impl fmt::Display + 'a + Captures<'tcx> {
2245fn render_implementor(
2246 cx: &Context<'_>,
2247 implementor: &Impl,
2248 trait_: &clean::Item,
2249 implementor_dups: &FxHashMap<Symbol, (DefId, bool)>,
2250 aliases: &[String],
2251) -> impl fmt::Display {
23392252 // If there's already another implementor that has the same abridged name, use the
23402253 // full path, for example in `std::iter::ExactSizeIterator`
23412254 let use_absolute = match implementor.inner_impl().for_ {
......@@ -2364,12 +2277,12 @@ fn render_implementor<'a, 'tcx>(
23642277 )
23652278}
23662279
2367fn render_union<'a, 'cx: 'a>(
2368 it: &'a clean::Item,
2369 g: Option<&'a clean::Generics>,
2370 fields: &'a [clean::Item],
2371 cx: &'a Context<'cx>,
2372) -> impl Display + 'a + Captures<'cx> {
2280fn render_union(
2281 it: &clean::Item,
2282 g: Option<&clean::Generics>,
2283 fields: &[clean::Item],
2284 cx: &Context<'_>,
2285) -> impl Display {
23732286 fmt::from_fn(move |mut f| {
23742287 write!(f, "{}union {}", visibility_print_with_space(it, cx), it.name.unwrap(),)?;
23752288
......@@ -2421,15 +2334,15 @@ fn render_union<'a, 'cx: 'a>(
24212334 })
24222335}
24232336
2424fn render_struct<'a, 'tcx>(
2425 it: &'a clean::Item,
2426 g: Option<&'a clean::Generics>,
2337fn render_struct(
2338 it: &clean::Item,
2339 g: Option<&clean::Generics>,
24272340 ty: Option<CtorKind>,
2428 fields: &'a [clean::Item],
2429 tab: &'a str,
2341 fields: &[clean::Item],
2342 tab: &str,
24302343 structhead: bool,
2431 cx: &'a Context<'tcx>,
2432) -> impl fmt::Display + 'a + Captures<'tcx> {
2344 cx: &Context<'_>,
2345) -> impl fmt::Display {
24332346 fmt::from_fn(move |w| {
24342347 write!(
24352348 w,
......@@ -2457,15 +2370,15 @@ fn render_struct<'a, 'tcx>(
24572370 })
24582371}
24592372
2460fn render_struct_fields<'a, 'tcx>(
2461 g: Option<&'a clean::Generics>,
2373fn render_struct_fields(
2374 g: Option<&clean::Generics>,
24622375 ty: Option<CtorKind>,
2463 fields: &'a [clean::Item],
2464 tab: &'a str,
2376 fields: &[clean::Item],
2377 tab: &str,
24652378 structhead: bool,
24662379 has_stripped_entries: bool,
2467 cx: &'a Context<'tcx>,
2468) -> impl fmt::Display + 'a + Captures<'tcx> {
2380 cx: &Context<'_>,
2381) -> impl fmt::Display {
24692382 fmt::from_fn(move |w| {
24702383 match ty {
24712384 None => {
......@@ -2581,7 +2494,7 @@ fn document_non_exhaustive_header(item: &clean::Item) -> &str {
25812494 if item.is_non_exhaustive() { " (Non-exhaustive)" } else { "" }
25822495}
25832496
2584fn document_non_exhaustive(item: &clean::Item) -> impl Display + '_ {
2497fn document_non_exhaustive(item: &clean::Item) -> impl Display {
25852498 fmt::from_fn(|f| {
25862499 if item.is_non_exhaustive() {
25872500 write!(
src/librustdoc/html/render/type_layout.rs+1-5
......@@ -2,7 +2,6 @@ use std::fmt;
22
33use rinja::Template;
44use rustc_abi::{Primitive, TagEncoding, Variants};
5use rustc_data_structures::captures::Captures;
65use rustc_hir::def_id::DefId;
76use rustc_middle::span_bug;
87use rustc_middle::ty::layout::LayoutError;
......@@ -26,10 +25,7 @@ struct TypeLayoutSize {
2625 size: u64,
2726}
2827
29pub(crate) fn document_type_layout<'a, 'cx: 'a>(
30 cx: &'a Context<'cx>,
31 ty_def_id: DefId,
32) -> impl fmt::Display + 'a + Captures<'cx> {
28pub(crate) fn document_type_layout(cx: &Context<'_>, ty_def_id: DefId) -> impl fmt::Display {
3329 fmt::from_fn(move |f| {
3430 if !cx.shared.show_type_layout {
3531 return Ok(());
src/librustdoc/html/sources.rs+1-1
......@@ -333,7 +333,7 @@ pub(crate) fn print_src(
333333 source_context: &SourceContext<'_>,
334334) {
335335 let mut lines = s.lines().count();
336 let line_info = if let SourceContext::Embedded(ref info) = source_context {
336 let line_info = if let SourceContext::Embedded(info) = source_context {
337337 highlight::LineInfo::new_scraped(lines as u32, info.offset as u32)
338338 } else {
339339 highlight::LineInfo::new(lines as u32)
src/librustdoc/lib.rs+1-1
......@@ -147,7 +147,7 @@ pub fn main() {
147147
148148 #[cfg(target_os = "macos")]
149149 {
150 extern "C" {
150 unsafe extern "C" {
151151 fn _rjem_je_zone_register();
152152 }
153153
src/librustdoc/passes/collect_intra_doc_links.rs+1-1
......@@ -58,7 +58,7 @@ fn filter_assoc_items_by_name_and_namespace(
5858 assoc_items_of: DefId,
5959 ident: Ident,
6060 ns: Namespace,
61) -> impl Iterator<Item = &ty::AssocItem> + '_ {
61) -> impl Iterator<Item = &ty::AssocItem> {
6262 tcx.associated_items(assoc_items_of).filter_by_name_unhygienic(ident.name).filter(move |item| {
6363 item.kind.namespace() == ns && tcx.hygienic_eq(ident, item.ident(tcx), assoc_items_of)
6464 })
src/tools/compiletest/src/common.rs+3
......@@ -190,6 +190,9 @@ pub struct Config {
190190 /// The cargo executable.
191191 pub cargo_path: Option<PathBuf>,
192192
193 /// Rustc executable used to compile run-make recipes.
194 pub stage0_rustc_path: Option<PathBuf>,
195
193196 /// The rustdoc executable.
194197 pub rustdoc_path: Option<PathBuf>,
195198
src/tools/compiletest/src/lib.rs+7
......@@ -54,6 +54,12 @@ pub fn parse_config(args: Vec<String>) -> Config {
5454 .reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
5555 .reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
5656 .optopt("", "cargo-path", "path to cargo to use for compiling", "PATH")
57 .optopt(
58 "",
59 "stage0-rustc-path",
60 "path to rustc to use for compiling run-make recipes",
61 "PATH",
62 )
5763 .optopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH")
5864 .optopt("", "coverage-dump-path", "path to coverage-dump to use in tests", "PATH")
5965 .reqopt("", "python", "path to python to use for doc tests", "PATH")
......@@ -320,6 +326,7 @@ pub fn parse_config(args: Vec<String>) -> Config {
320326 run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
321327 rustc_path: opt_path(matches, "rustc-path"),
322328 cargo_path: matches.opt_str("cargo-path").map(PathBuf::from),
329 stage0_rustc_path: matches.opt_str("stage0-rustc-path").map(PathBuf::from),
323330 rustdoc_path: matches.opt_str("rustdoc-path").map(PathBuf::from),
324331 coverage_dump_path: matches.opt_str("coverage-dump-path").map(PathBuf::from),
325332 python: matches.opt_str("python").unwrap(),
src/tools/compiletest/src/runtest/run_make.rs+41-78
......@@ -173,7 +173,8 @@ impl TestCx<'_> {
173173 fn run_rmake_v2_test(&self) {
174174 // For `run-make` V2, we need to perform 2 steps to build and run a `run-make` V2 recipe
175175 // (`rmake.rs`) to run the actual tests. The support library is already built as a tool rust
176 // library and is available under `build/$TARGET/stageN-tools-bin/librun_make_support.rlib`.
176 // library and is available under
177 // `build/$HOST/stage0-bootstrap-tools/$TARGET/release/librun_make_support.rlib`.
177178 //
178179 // 1. We need to build the recipe `rmake.rs` as a binary and link in the `run_make_support`
179180 // library.
......@@ -224,25 +225,21 @@ impl TestCx<'_> {
224225 //
225226 // ```
226227 // build/<target_triple>/
227 // ├── stageN-tools-bin/
228 // │ └── librun_make_support.rlib // <- support rlib itself
229 // ├── stageN-tools/
230 // │ ├── release/deps/ // <- deps of deps
231 // │ └── <host_triple>/release/deps/ // <- deps
228 // ├── stage0-bootstrap-tools/
229 // │ ├── <host_triple>/release/librun_make_support.rlib // <- support rlib itself
230 // │ ├── <host_triple>/release/deps/ // <- deps
231 // │ └── release/deps/ // <- deps of deps
232232 // ```
233233 //
234234 // FIXME(jieyouxu): there almost certainly is a better way to do this (specifically how the
235 // support lib and its deps are organized, can't we copy them to the tools-bin dir as
236 // well?), but this seems to work for now.
235 // support lib and its deps are organized), but this seems to work for now.
237236
238 let stage_number = self.config.stage;
237 let tools_bin = host_build_root.join("stage0-bootstrap-tools");
238 let support_host_path = tools_bin.join(&self.config.host).join("release");
239 let support_lib_path = support_host_path.join("librun_make_support.rlib");
239240
240 let stage_tools_bin = host_build_root.join(format!("stage{stage_number}-tools-bin"));
241 let support_lib_path = stage_tools_bin.join("librun_make_support.rlib");
242
243 let stage_tools = host_build_root.join(format!("stage{stage_number}-tools"));
244 let support_lib_deps = stage_tools.join(&self.config.host).join("release").join("deps");
245 let support_lib_deps_deps = stage_tools.join("release").join("deps");
241 let support_lib_deps = support_host_path.join("deps");
242 let support_lib_deps_deps = tools_bin.join("release").join("deps");
246243
247244 // To compile the recipe with rustc, we need to provide suitable dynamic library search
248245 // paths to rustc. This includes both:
......@@ -253,12 +250,6 @@ impl TestCx<'_> {
253250 let base_dylib_search_paths =
254251 Vec::from_iter(env::split_paths(&env::var(dylib_env_var()).unwrap()));
255252
256 let host_dylib_search_paths = {
257 let mut paths = vec![self.config.compile_lib_path.clone()];
258 paths.extend(base_dylib_search_paths.iter().cloned());
259 paths
260 };
261
262253 // Calculate the paths of the recipe binary. As previously discussed, this is placed at
263254 // `<base_dir>/<bin_name>` with `bin_name` being `rmake` or `rmake.exe` depending on
264255 // platform.
......@@ -268,7 +259,15 @@ impl TestCx<'_> {
268259 p
269260 };
270261
271 let mut rustc = Command::new(&self.config.rustc_path);
262 // run-make-support and run-make tests are compiled using the stage0 compiler
263 // If the stage is 0, then the compiler that we test (either bootstrap or an explicitly
264 // set compiler) is the one that actually compiled run-make-support.
265 let stage0_rustc = self
266 .config
267 .stage0_rustc_path
268 .as_ref()
269 .expect("stage0 rustc is required to run run-make tests");
270 let mut rustc = Command::new(&stage0_rustc);
272271 rustc
273272 .arg("-o")
274273 .arg(&recipe_bin)
......@@ -282,35 +281,12 @@ impl TestCx<'_> {
282281 .arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
283282 .arg("--edition=2021")
284283 .arg(&self.testpaths.file.join("rmake.rs"))
285 .arg("-Cprefer-dynamic")
286 // Provide necessary library search paths for rustc.
287 .env(dylib_env_var(), &env::join_paths(host_dylib_search_paths).unwrap());
284 .arg("-Cprefer-dynamic");
288285
289286 // In test code we want to be very pedantic about values being silently discarded that are
290287 // annotated with `#[must_use]`.
291288 rustc.arg("-Dunused_must_use");
292289
293 // > `cg_clif` uses `COMPILETEST_FORCE_STAGE0=1 ./x.py test --stage 0` for running the rustc
294 // > test suite. With the introduction of rmake.rs this broke. `librun_make_support.rlib` is
295 // > compiled using the bootstrap rustc wrapper which sets `--sysroot
296 // > build/aarch64-unknown-linux-gnu/stage0-sysroot`, but then compiletest will compile
297 // > `rmake.rs` using the sysroot of the bootstrap compiler causing it to not find the
298 // > `libstd.rlib` against which `librun_make_support.rlib` is compiled.
299 //
300 // The gist here is that we have to pass the proper stage0 sysroot if we want
301 //
302 // ```
303 // $ COMPILETEST_FORCE_STAGE0=1 ./x test run-make --stage 0
304 // ```
305 //
306 // to work correctly.
307 //
308 // See <https://github.com/rust-lang/rust/pull/122248> for more background.
309 let stage0_sysroot = host_build_root.join("stage0-sysroot");
310 if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
311 rustc.arg("--sysroot").arg(&stage0_sysroot);
312 }
313
314290 // Now run rustc to build the recipe.
315291 let res = self.run_command_to_procres(&mut rustc);
316292 if !res.status.success() {
......@@ -320,35 +296,24 @@ impl TestCx<'_> {
320296 // To actually run the recipe, we have to provide the recipe with a bunch of information
321297 // provided through env vars.
322298
323 // Compute stage-specific standard library paths.
324 let stage_std_path = host_build_root.join(format!("stage{stage_number}")).join("lib");
325
326299 // Compute dynamic library search paths for recipes.
300 // These dylib directories are needed to **execute the recipe**.
327301 let recipe_dylib_search_paths = {
328302 let mut paths = base_dylib_search_paths.clone();
329
330 // For stage 0, we need to explicitly include the stage0-sysroot libstd dylib.
331 // See <https://github.com/rust-lang/rust/issues/135373>.
332 if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
333 paths.push(
334 stage0_sysroot.join("lib").join("rustlib").join(&self.config.host).join("lib"),
335 );
336 }
337
338 paths.push(support_lib_path.parent().unwrap().to_path_buf());
339 paths.push(stage_std_path.join("rustlib").join(&self.config.host).join("lib"));
340 paths
341 };
342
343 // Compute runtime library search paths for recipes. This is target-specific.
344 let target_runtime_dylib_search_paths = {
345 let mut paths = vec![rmake_out_dir.clone()];
346 paths.extend(base_dylib_search_paths.iter().cloned());
303 paths.push(
304 stage0_rustc
305 .parent()
306 .unwrap()
307 .parent()
308 .unwrap()
309 .join("lib")
310 .join("rustlib")
311 .join(&self.config.host)
312 .join("lib"),
313 );
347314 paths
348315 };
349316
350 // FIXME(jieyouxu): please rename `TARGET_RPATH_ENV`, `HOST_RPATH_DIR` and
351 // `TARGET_RPATH_DIR`, it is **extremely** confusing!
352317 let mut cmd = Command::new(&recipe_bin);
353318 cmd.current_dir(&rmake_out_dir)
354319 .stdout(Stdio::piped())
......@@ -357,9 +322,14 @@ impl TestCx<'_> {
357322 // example, this could be `LD_LIBRARY_PATH` on some linux distros but `PATH` on Windows.
358323 .env("LD_LIB_PATH_ENVVAR", dylib_env_var())
359324 // Provide the dylib search paths.
325 // This is required to run the **recipe** itself.
360326 .env(dylib_env_var(), &env::join_paths(recipe_dylib_search_paths).unwrap())
361 // Provide runtime dylib search paths.
362 .env("TARGET_RPATH_ENV", &env::join_paths(target_runtime_dylib_search_paths).unwrap())
327 // Provide the directory to libraries that are needed to run the *compiler* invoked
328 // by the recipe.
329 .env("HOST_RUSTC_DYLIB_PATH", &self.config.compile_lib_path)
330 // Provide the directory to libraries that might be needed to run binaries created
331 // by a compiler invoked by the recipe.
332 .env("TARGET_EXE_DYLIB_PATH", &self.config.run_lib_path)
363333 // Provide the target.
364334 .env("TARGET", &self.config.target)
365335 // Some tests unfortunately still need Python, so provide path to a Python interpreter.
......@@ -370,13 +340,6 @@ impl TestCx<'_> {
370340 .env("BUILD_ROOT", &host_build_root)
371341 // Provide path to stage-corresponding rustc.
372342 .env("RUSTC", &self.config.rustc_path)
373 // Provide the directory to libraries that are needed to run the *compiler*. This is not
374 // to be confused with `TARGET_RPATH_ENV` or `TARGET_RPATH_DIR`. This is needed if the
375 // recipe wants to invoke rustc.
376 .env("HOST_RPATH_DIR", &self.config.compile_lib_path)
377 // Provide the directory to libraries that might be needed to run compiled binaries
378 // (further compiled by the recipe!).
379 .env("TARGET_RPATH_DIR", &self.config.run_lib_path)
380343 // Provide which LLVM components are available (e.g. which LLVM components are provided
381344 // through a specific CI runner).
382345 .env("LLVM_COMPONENTS", &self.config.llvm_components);
src/tools/opt-dist/src/main.rs+1
......@@ -389,6 +389,7 @@ fn main() -> anyhow::Result<()> {
389389 "clippy",
390390 "miri",
391391 "rustfmt",
392 "gcc",
392393 ] {
393394 build_args.extend(["--skip".to_string(), target.to_string()]);
394395 }
src/tools/opt-dist/src/metrics.rs+3-70
......@@ -1,33 +1,10 @@
11use std::time::Duration;
22
3use build_helper::metrics::{JsonNode, JsonRoot};
3use build_helper::metrics::{BuildStep, JsonRoot, format_build_steps};
44use camino::Utf8Path;
55
66use crate::timer::TimerSection;
77
8#[derive(Clone, Debug)]
9pub struct BuildStep {
10 r#type: String,
11 children: Vec<BuildStep>,
12 duration: Duration,
13}
14
15impl BuildStep {
16 pub fn find_all_by_type(&self, r#type: &str) -> Vec<&BuildStep> {
17 let mut result = Vec::new();
18 self.find_by_type(r#type, &mut result);
19 result
20 }
21 fn find_by_type<'a>(&'a self, r#type: &str, result: &mut Vec<&'a BuildStep>) {
22 if self.r#type == r#type {
23 result.push(self);
24 }
25 for child in &self.children {
26 child.find_by_type(r#type, result);
27 }
28 }
29}
30
318/// Loads the metrics of the most recent bootstrap execution from a metrics.json file.
329pub fn load_metrics(path: &Utf8Path) -> anyhow::Result<BuildStep> {
3310 let content = std::fs::read(path.as_std_path())?;
......@@ -37,30 +14,7 @@ pub fn load_metrics(path: &Utf8Path) -> anyhow::Result<BuildStep> {
3714 .pop()
3815 .ok_or_else(|| anyhow::anyhow!("No bootstrap invocation found in metrics file"))?;
3916
40 fn parse(node: JsonNode) -> Option<BuildStep> {
41 match node {
42 JsonNode::RustbuildStep {
43 type_: kind,
44 children,
45 duration_excluding_children_sec,
46 ..
47 } => {
48 let children: Vec<_> = children.into_iter().filter_map(parse).collect();
49 let children_duration = children.iter().map(|c| c.duration).sum::<Duration>();
50 Some(BuildStep {
51 r#type: kind.to_string(),
52 children,
53 duration: children_duration
54 + Duration::from_secs_f64(duration_excluding_children_sec),
55 })
56 }
57 JsonNode::TestSuite(_) => None,
58 }
59 }
60
61 let duration = Duration::from_secs_f64(invocation.duration_including_children_sec);
62 let children: Vec<_> = invocation.children.into_iter().filter_map(parse).collect();
63 Ok(BuildStep { r#type: "root".to_string(), children, duration })
17 Ok(BuildStep::from_invocation(&invocation))
6418}
6519
6620/// Logs the individual metrics in a table and add Rustc and LLVM durations to the passed
......@@ -82,27 +36,6 @@ pub fn record_metrics(metrics: &BuildStep, timer: &mut TimerSection) {
8236 timer.add_duration("Rustc", rustc_duration);
8337 }
8438
85 log_metrics(metrics);
86}
87
88fn log_metrics(metrics: &BuildStep) {
89 use std::fmt::Write;
90
91 let mut substeps: Vec<(u32, &BuildStep)> = Vec::new();
92
93 fn visit<'a>(step: &'a BuildStep, level: u32, substeps: &mut Vec<(u32, &'a BuildStep)>) {
94 substeps.push((level, step));
95 for child in &step.children {
96 visit(child, level + 1, substeps);
97 }
98 }
99
100 visit(metrics, 0, &mut substeps);
101
102 let mut output = String::new();
103 for (level, step) in substeps {
104 let label = format!("{}{}", ".".repeat(level as usize), step.r#type);
105 writeln!(output, "{label:<65}{:>8.2}s", step.duration.as_secs_f64()).unwrap();
106 }
39 let output = format_build_steps(metrics);
10740 log::info!("Build step durations\n{output}");
10841}
src/tools/run-make-support/src/external_deps/rustc.rs+4-4
......@@ -5,7 +5,7 @@ use std::str::FromStr as _;
55use crate::command::Command;
66use crate::env::env_var;
77use crate::path_helpers::cwd;
8use crate::util::set_host_rpath;
8use crate::util::set_host_compiler_dylib_path;
99use crate::{is_aix, is_darwin, is_msvc, is_windows, uname};
1010
1111/// Construct a new `rustc` invocation. This will automatically set the library
......@@ -15,8 +15,8 @@ pub fn rustc() -> Rustc {
1515 Rustc::new()
1616}
1717
18/// Construct a plain `rustc` invocation with no flags set. Note that [`set_host_rpath`]
19/// still presets the environment variable `HOST_RPATH_DIR` by default.
18/// Construct a plain `rustc` invocation with no flags set. Note that [`set_host_compiler_dylib_path`]
19/// still presets the environment variable `HOST_RUSTC_DYLIB_PATH` by default.
2020#[track_caller]
2121pub fn bare_rustc() -> Rustc {
2222 Rustc::bare()
......@@ -44,7 +44,7 @@ pub fn rustc_path() -> String {
4444#[track_caller]
4545fn setup_common() -> Command {
4646 let mut cmd = Command::new(rustc_path());
47 set_host_rpath(&mut cmd);
47 set_host_compiler_dylib_path(&mut cmd);
4848 cmd
4949}
5050
src/tools/run-make-support/src/external_deps/rustdoc.rs+5-19
......@@ -2,16 +2,10 @@ use std::ffi::OsStr;
22use std::path::Path;
33
44use crate::command::Command;
5use crate::env::{env_var, env_var_os};
6use crate::util::set_host_rpath;
5use crate::env::env_var;
6use crate::util::set_host_compiler_dylib_path;
77
8/// Construct a plain `rustdoc` invocation with no flags set.
9#[track_caller]
10pub fn bare_rustdoc() -> Rustdoc {
11 Rustdoc::bare()
12}
13
14/// Construct a new `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
8/// Construct a new `rustdoc` invocation.
159#[track_caller]
1610pub fn rustdoc() -> Rustdoc {
1711 Rustdoc::new()
......@@ -29,23 +23,15 @@ crate::macros::impl_common_helpers!(Rustdoc);
2923fn setup_common() -> Command {
3024 let rustdoc = env_var("RUSTDOC");
3125 let mut cmd = Command::new(rustdoc);
32 set_host_rpath(&mut cmd);
26 set_host_compiler_dylib_path(&mut cmd);
3327 cmd
3428}
3529
3630impl Rustdoc {
3731 /// Construct a bare `rustdoc` invocation.
3832 #[track_caller]
39 pub fn bare() -> Self {
40 let cmd = setup_common();
41 Self { cmd }
42 }
43
44 /// Construct a `rustdoc` invocation with `-L $(TARGET_RPATH_DIR)` set.
45 #[track_caller]
4633 pub fn new() -> Self {
47 let mut cmd = setup_common();
48 cmd.arg("-L").arg(env_var_os("TARGET_RPATH_DIR"));
34 let cmd = setup_common();
4935 Self { cmd }
5036 }
5137
src/tools/run-make-support/src/lib.rs+1-1
......@@ -67,7 +67,7 @@ pub use llvm::{
6767};
6868pub use python::python_command;
6969pub use rustc::{aux_build, bare_rustc, rustc, rustc_path, Rustc};
70pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
70pub use rustdoc::{rustdoc, Rustdoc};
7171
7272/// [`diff`][mod@diff] is implemented in terms of the [similar] library.
7373///
src/tools/run-make-support/src/run.rs+5-14
......@@ -1,10 +1,10 @@
11use std::ffi::OsStr;
2use std::path::{Path, PathBuf};
2use std::path::PathBuf;
33use std::{env, panic};
44
55use crate::command::{Command, CompletedProcess};
6use crate::util::{handle_failed_output, set_host_rpath};
7use crate::{cwd, env_var, is_windows};
6use crate::util::handle_failed_output;
7use crate::{cwd, env_var};
88
99#[track_caller]
1010fn run_common(name: &str, args: Option<&[&str]>) -> Command {
......@@ -18,10 +18,11 @@ fn run_common(name: &str, args: Option<&[&str]>) -> Command {
1818 cmd.arg(arg);
1919 }
2020 }
21
2122 cmd.env(&ld_lib_path_envvar, {
2223 let mut paths = vec![];
2324 paths.push(cwd());
24 for p in env::split_paths(&env_var("TARGET_RPATH_ENV")) {
25 for p in env::split_paths(&env_var("TARGET_EXE_DYLIB_PATH")) {
2526 paths.push(p.to_path_buf());
2627 }
2728 for p in env::split_paths(&env_var(&ld_lib_path_envvar)) {
......@@ -31,15 +32,6 @@ fn run_common(name: &str, args: Option<&[&str]>) -> Command {
3132 });
3233 cmd.env("LC_ALL", "C"); // force english locale
3334
34 if is_windows() {
35 let mut paths = vec![];
36 for p in env::split_paths(&std::env::var("PATH").unwrap_or(String::new())) {
37 paths.push(p.to_path_buf());
38 }
39 paths.push(Path::new(&env_var("TARGET_RPATH_DIR")).to_path_buf());
40 cmd.env("PATH", env::join_paths(paths.iter()).unwrap());
41 }
42
4335 cmd
4436}
4537
......@@ -84,7 +76,6 @@ pub fn run_fail(name: &str) -> CompletedProcess {
8476#[track_caller]
8577pub fn cmd<S: AsRef<OsStr>>(program: S) -> Command {
8678 let mut command = Command::new(program);
87 set_host_rpath(&mut command);
8879 command.env("LC_ALL", "C"); // force english locale
8980 command
9081}
src/tools/run-make-support/src/util.rs+3-3
......@@ -24,13 +24,13 @@ pub(crate) fn handle_failed_output(
2424 std::process::exit(1)
2525}
2626
27/// Set the runtime library path as needed for running the host rustc/rustdoc/etc.
28pub(crate) fn set_host_rpath(cmd: &mut Command) {
27/// Set the runtime library paths as needed for running the host compilers (rustc/rustdoc/etc).
28pub(crate) fn set_host_compiler_dylib_path(cmd: &mut Command) {
2929 let ld_lib_path_envvar = env_var("LD_LIB_PATH_ENVVAR");
3030 cmd.env(&ld_lib_path_envvar, {
3131 let mut paths = vec![];
3232 paths.push(cwd());
33 paths.push(PathBuf::from(env_var("HOST_RPATH_DIR")));
33 paths.push(PathBuf::from(env_var("HOST_RUSTC_DYLIB_PATH")));
3434 for p in std::env::split_paths(&env_var(&ld_lib_path_envvar)) {
3535 paths.push(p.to_path_buf());
3636 }
src/tools/rustdoc/Cargo.toml+1-1
......@@ -1,7 +1,7 @@
11[package]
22name = "rustdoc-tool"
33version = "0.0.0"
4edition = "2021"
4edition = "2024"
55
66# Cargo adds a number of paths to the dylib search path on windows, which results in
77# the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
tests/run-make/a-b-a-linker-guard/rmake.rs+4-3
......@@ -1,7 +1,8 @@
1// ignore-tidy-linelength
1// Test that if we build `b` against a version of `a` that has
2// one set of types, it will not run with a dylib that has a different set of types.
23
3// Test that if we build `b` against a version of `a` that has one set of types, it will not run
4// with a dylib that has a different set of types.
4//@ ignore-cross-compile
5// Reason: the compiled binary is executed
56
67use run_make_support::{run, run_fail, rustc};
78
tests/run-make/rustdoc-default-output/rmake.rs+2-2
......@@ -3,10 +3,10 @@
33// ensures the output of rustdoc's help menu is as expected.
44// See https://github.com/rust-lang/rust/issues/88756
55
6use run_make_support::{bare_rustdoc, diff};
6use run_make_support::{diff, rustdoc};
77
88fn main() {
9 let out = bare_rustdoc().run().stdout_utf8();
9 let out = rustdoc().run().stdout_utf8();
1010 diff()
1111 .expected_file("output-default.stdout")
1212 .actual_text("actual", out)
tests/run-make/version-verbose-commit-hash/rmake.rs+2-2
......@@ -5,13 +5,13 @@
55
66//@ needs-git-hash
77
8use run_make_support::{bare_rustc, bare_rustdoc, regex};
8use run_make_support::{bare_rustc, regex, rustdoc};
99
1010fn main() {
1111 let out_rustc =
1212 bare_rustc().arg("--version").arg("--verbose").run().stdout_utf8().to_lowercase();
1313 let out_rustdoc =
14 bare_rustdoc().arg("--version").arg("--verbose").run().stdout_utf8().to_lowercase();
14 rustdoc().arg("--version").arg("--verbose").run().stdout_utf8().to_lowercase();
1515 let re =
1616 regex::Regex::new(r#"commit-hash: [0-9a-f]{40}\ncommit-date: [0-9]{4}-[0-9]{2}-[0-9]{2}"#)
1717 .unwrap();