From 5fa6ede9d4d42c9b656fdcb67fb853958fcc4244 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 25 Jul 2024 15:39:27 -0700 Subject: [PATCH 01/19] Remove comment about bootstrap.py handling submodules bootstrap.py handling of submodules was removed in https://github.com/rust-lang/rust/pull/97513. --- src/bootstrap/src/core/build_steps/tool.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 087df2f8a88e2..66fcafb1c52ed 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1087,8 +1087,6 @@ macro_rules! tool_extended { // NOTE: tools need to be also added to `Builder::get_step_descriptions` in `builder.rs` // to make `./x.py build ` work. -// NOTE: Most submodule updates for tools are handled by bootstrap.py, since they're needed just to -// invoke Cargo to build bootstrap. See the comment there for more details. tool_extended!((self, builder), Cargofmt, "src/tools/rustfmt", "cargo-fmt", stable=true; CargoClippy, "src/tools/clippy", "cargo-clippy", stable=true; From 6642f8dcfcd44d7d4723c002b204e22b3255d70e Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 25 Jul 2024 16:10:54 -0700 Subject: [PATCH 02/19] Remove `pub` from update_existing_submodules This is not used anywhere outside this module. --- src/bootstrap/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 79bea50c626b2..e461105aba2bb 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -582,7 +582,7 @@ impl Build { /// If any submodule has been initialized already, sync it unconditionally. /// This avoids contributors checking in a submodule change by accident. - pub fn update_existing_submodules(&self) { + fn update_existing_submodules(&self) { // Avoid running git when there isn't a git checkout. if !self.config.submodules(self.rust_info()) { return; From 2c6222b3f290ebb9b818253e8f0dc6050348a859 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 25 Jul 2024 16:13:01 -0700 Subject: [PATCH 03/19] Clarify comment on update_existing_submodules This felt like an important point to me. --- src/bootstrap/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index e461105aba2bb..ab640bf39aaee 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -583,7 +583,8 @@ impl Build { /// If any submodule has been initialized already, sync it unconditionally. /// This avoids contributors checking in a submodule change by accident. fn update_existing_submodules(&self) { - // Avoid running git when there isn't a git checkout. + // Avoid running git when there isn't a git checkout, or the user has + // explicitly disabled submodules in `config.toml`. if !self.config.submodules(self.rust_info()) { return; } From 922fdd84627aa40237ca7adab07719fd98d4378b Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 25 Jul 2024 16:15:59 -0700 Subject: [PATCH 04/19] Remove argument from the submodules method The argument was not necessary, since it was only ever passed one value that exists in the config itself. --- src/bootstrap/src/core/config/config.rs | 7 +++++-- src/bootstrap/src/lib.rs | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index e32288e2caf67..3435225af7bd3 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -2404,8 +2404,11 @@ impl Config { .unwrap_or_else(|| SplitDebuginfo::default_for_platform(target)) } - pub fn submodules(&self, rust_info: &GitInfo) -> bool { - self.submodules.unwrap_or(rust_info.is_managed_git_subrepository()) + /// Returns whether or not submodules should be managed by bootstrap. + pub fn submodules(&self) -> bool { + // If not specified in config, the default is to only manage + // submodules if we're currently inside a git repository. + self.submodules.unwrap_or(self.rust_info.is_managed_git_subrepository()) } pub fn codegen_backends(&self, target: TargetSelection) -> &[String] { diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index ab640bf39aaee..e8f412d785d55 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -475,7 +475,7 @@ impl Build { /// /// `relative_path` should be relative to the root of the git repository, not an absolute path. pub(crate) fn update_submodule(&self, relative_path: &Path) { - if !self.config.submodules(self.rust_info()) { + if !self.config.submodules() { return; } @@ -585,7 +585,7 @@ impl Build { fn update_existing_submodules(&self) { // Avoid running git when there isn't a git checkout, or the user has // explicitly disabled submodules in `config.toml`. - if !self.config.submodules(self.rust_info()) { + if !self.config.submodules() { return; } let output = helpers::git(Some(&self.src)) @@ -609,7 +609,7 @@ impl Build { /// Updates the given submodule only if it's initialized already; nothing happens otherwise. pub fn update_existing_submodule(&self, submodule: &Path) { // Avoid running git when there isn't a git checkout. - if !self.config.submodules(self.rust_info()) { + if !self.config.submodules() { return; } From 6a449d97fe01a5c34f606b082d75d553b7cb3f80 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 25 Jul 2024 16:18:46 -0700 Subject: [PATCH 05/19] Remove outdated comment about update_submodule Although its origins were in bootstrap.py, that code in bootstrap.py no longer exists since it was removed. --- src/bootstrap/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index e8f412d785d55..0ce50ccaf3f68 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -470,7 +470,6 @@ impl Build { build } - // modified from `check_submodule` and `update_submodule` in bootstrap.py /// Given a path to the directory of a submodule, update it. /// /// `relative_path` should be relative to the root of the git repository, not an absolute path. From ee75f24945a4e7d614b25c89d70b3eb88dc20ccd Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 25 Jul 2024 16:26:21 -0700 Subject: [PATCH 06/19] Fix rustbook submodule update location I put this submodule update in the entirely wrong location. I put it in the `RustcBook` step (for generating src/doc/rustc), when it really should exist for all steps that use the `Rustbook` tool. --- src/bootstrap/src/core/build_steps/doc.rs | 6 ------ src/bootstrap/src/core/build_steps/tool.rs | 12 +++++++++++- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index d8204ea00f7b2..633e66afe598d 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -1172,12 +1172,6 @@ impl Step for RustcBook { /// in the "md-doc" directory in the build output directory. Then /// "rustbook" is used to convert it to HTML. fn run(self, builder: &Builder<'_>) { - // These submodules are required to be checked out to build rustbook - // because they have Cargo dependencies that are needed. - #[allow(clippy::single_element_loop)] // This will change soon. - for path in ["src/doc/book"] { - builder.update_submodule(Path::new(path)); - } let out_base = builder.md_doc_out(self.target).join("rustc"); t!(fs::create_dir_all(&out_base)); let out_listing = out_base.join("src/lints"); diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 66fcafb1c52ed..d5fd3301b9273 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -241,6 +241,7 @@ macro_rules! bootstrap_tool { $(,is_external_tool = $external:expr)* $(,is_unstable_tool = $unstable:expr)* $(,allow_features = $allow_features:expr)? + $(,submodules = $submodules:expr)? ; )+) => { #[derive(PartialEq, Eq, Clone)] @@ -287,6 +288,11 @@ macro_rules! bootstrap_tool { } fn run(self, builder: &Builder<'_>) -> PathBuf { + $( + for submodule in $submodules { + builder.update_submodule(Path::new(submodule)); + } + )* builder.ensure(ToolBuild { compiler: self.compiler, target: self.target, @@ -314,7 +320,7 @@ macro_rules! bootstrap_tool { } bootstrap_tool!( - Rustbook, "src/tools/rustbook", "rustbook"; + Rustbook, "src/tools/rustbook", "rustbook", submodules = SUBMODULES_FOR_RUSTBOOK; UnstableBookGen, "src/tools/unstable-book-gen", "unstable-book-gen"; Tidy, "src/tools/tidy", "tidy"; Linkchecker, "src/tools/linkchecker", "linkchecker"; @@ -340,6 +346,10 @@ bootstrap_tool!( WasmComponentLd, "src/tools/wasm-component-ld", "wasm-component-ld", is_unstable_tool = true, allow_features = "min_specialization"; ); +/// These are the submodules that are required for rustbook to work due to +/// depending on mdbook plugins. +pub static SUBMODULES_FOR_RUSTBOOK: &[&str] = &["src/doc/book"]; + #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct OptimizedDist { pub compiler: Compiler, From bbe9056c2a68495bf4139a358745d8ca4c398576 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 25 Jul 2024 16:36:09 -0700 Subject: [PATCH 07/19] Add require_and_update_submodule to ensure submodules exist This adds a new method `require_and_update_submodule` to replace `update_submodule`. This new method will generate an error if the submodule doesn't actually exist. This replaces some ad-hoc checks that were performing this function. This helps ensure that a good error message is always displayed. This also adds require_and_update_all_submodules which does this for all submodules. Ideally this should not have any change other than better error messages when submodules are missing. --- src/bootstrap/src/core/build_steps/check.rs | 4 +- src/bootstrap/src/core/build_steps/clippy.rs | 4 +- src/bootstrap/src/core/build_steps/compile.rs | 21 +++++---- src/bootstrap/src/core/build_steps/dist.rs | 7 +-- src/bootstrap/src/core/build_steps/doc.rs | 24 ++++------ src/bootstrap/src/core/build_steps/llvm.rs | 6 +-- src/bootstrap/src/core/build_steps/test.rs | 6 +-- src/bootstrap/src/core/build_steps/tool.rs | 10 ++-- src/bootstrap/src/core/build_steps/vendor.rs | 6 +-- src/bootstrap/src/core/builder/tests.rs | 2 +- src/bootstrap/src/lib.rs | 47 ++++++++++++++++++- 11 files changed, 87 insertions(+), 50 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index ed5b9edc86d64..5b720ffbc76fa 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -9,7 +9,7 @@ use crate::core::builder::{ }; use crate::core::config::TargetSelection; use crate::{Compiler, Mode, Subcommand}; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; pub fn cargo_subcommand(kind: Kind) -> &'static str { match kind { @@ -52,7 +52,7 @@ impl Step for Std { } fn run(self, builder: &Builder<'_>) { - builder.update_submodule(&Path::new("library").join("stdarch")); + builder.require_and_update_submodule("library/stdarch", None); let target = self.target; let compiler = builder.compiler(builder.top_stage, builder.config.build); diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index ee7fb368a8c27..add28f858efb7 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -1,7 +1,5 @@ //! Implementation of running clippy on the compiler, standard library and various tools. -use std::path::Path; - use crate::builder::Builder; use crate::builder::ShouldRun; use crate::core::builder; @@ -127,7 +125,7 @@ impl Step for Std { } fn run(self, builder: &Builder<'_>) { - builder.update_submodule(&Path::new("library").join("stdarch")); + builder.require_and_update_submodule("library/stdarch", None); let target = self.target; let compiler = builder.compiler(builder.top_stage, builder.config.build); diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 9bbebf9b87037..1efa3c8ada3a2 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -182,11 +182,14 @@ impl Step for Std { return; } - builder.update_submodule(&Path::new("library").join("stdarch")); + builder.require_and_update_submodule("library/stdarch", None); // Profiler information requires LLVM's compiler-rt if builder.config.profiler { - builder.update_submodule(Path::new("src/llvm-project")); + builder.require_and_update_submodule( + "src/llvm-project", + Some("The `build.profiler` config option requires compiler-rt sources."), + ); } let mut target_deps = builder.ensure(StartupObjects { compiler, target }); @@ -456,13 +459,15 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car // That's probably ok? At least, the difference wasn't enforced before. There's a comment in // the compiler_builtins build script that makes me nervous, though: // https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579 - builder.update_submodule(&Path::new("src").join("llvm-project")); + builder.require_and_update_submodule( + "src/llvm-project", + Some( + "need LLVM sources available to build `compiler-rt`, but they weren't present; \ + consider disabling `optimized-compiler-builtins`", + ), + ); let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt"); - if !compiler_builtins_root.exists() { - panic!( - "need LLVM sources available to build `compiler-rt`, but they weren't present; consider enabling `build.submodules = true` or disabling `optimized-compiler-builtins`" - ); - } + assert!(compiler_builtins_root.exists()); // Note that `libprofiler_builtins/build.rs` also computes this so if // you're changing something here please also change that. cargo.env("RUST_COMPILER_RT_ROOT", &compiler_builtins_root); diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 649bcdd873353..998f083b676ad 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -907,7 +907,7 @@ impl Step for Src { /// Creates the `rust-src` installer component fn run(self, builder: &Builder<'_>) -> GeneratedTarball { if !builder.config.dry_run() { - builder.update_submodule(Path::new("src/llvm-project")); + builder.require_and_update_submodule("src/llvm-project", None); } let tarball = Tarball::new_targetless(builder, "rust-src"); @@ -1022,10 +1022,7 @@ impl Step for PlainSourceTarball { // FIXME: This code looks _very_ similar to what we have in `src/core/build_steps/vendor.rs` // perhaps it should be removed in favor of making `dist` perform the `vendor` step? - // Ensure we have all submodules from src and other directories checked out. - for submodule in build_helper::util::parse_gitmodules(&builder.src) { - builder.update_submodule(Path::new(submodule)); - } + builder.require_and_update_all_submodules(); // Vendor all Cargo dependencies let mut cmd = command(&builder.initial_cargo); diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 633e66afe598d..079539388bd23 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -16,7 +16,7 @@ use crate::core::build_steps::tool::{self, prepare_tool_cargo, SourceType, Tool} use crate::core::builder::{self, crate_description}; use crate::core::builder::{Alias, Builder, Compiler, Kind, RunConfig, ShouldRun, Step}; use crate::core::config::{Config, TargetSelection}; -use crate::utils::helpers::{dir_is_empty, symlink_dir, t, up_to_date}; +use crate::utils::helpers::{symlink_dir, t, up_to_date}; use crate::Mode; macro_rules! submodule_helper { @@ -53,8 +53,8 @@ macro_rules! book { fn run(self, builder: &Builder<'_>) { $( - let path = Path::new(submodule_helper!( $path, submodule $( = $submodule )? )); - builder.update_submodule(&path); + let path = submodule_helper!( $path, submodule $( = $submodule )? ); + builder.require_and_update_submodule(path, None); )? builder.ensure(RustbookSrc { target: self.target, @@ -217,22 +217,14 @@ impl Step for TheBook { /// * Index page /// * Redirect pages fn run(self, builder: &Builder<'_>) { - let relative_path = Path::new("src").join("doc").join("book"); - builder.update_submodule(&relative_path); + builder.require_and_update_submodule("src/doc/book", None); let compiler = self.compiler; let target = self.target; - let absolute_path = builder.src.join(&relative_path); + let absolute_path = builder.src.join("src/doc/book"); let redirect_path = absolute_path.join("redirects"); - if !absolute_path.exists() - || !redirect_path.exists() - || dir_is_empty(&absolute_path) - || dir_is_empty(&redirect_path) - { - eprintln!("Please checkout submodule: {}", relative_path.display()); - crate::exit!(1); - } + // build book builder.ensure(RustbookSrc { target, @@ -932,8 +924,8 @@ macro_rules! tool_doc { let _ = source_type; // silence the "unused variable" warning let source_type = SourceType::Submodule; - let path = Path::new(submodule_helper!( $path, submodule $( = $submodule )? )); - builder.update_submodule(&path); + let path = submodule_helper!( $path, submodule $( = $submodule )? ); + builder.require_and_update_submodule(path, None); )? let stage = builder.top_stage; diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index f234b08f5e2ca..5d892275ad363 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -110,7 +110,7 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L } // Initialize the llvm submodule if not initialized already. - builder.update_submodule(&Path::new("src").join("llvm-project")); + builder.require_and_update_submodule("src/llvm-project", None); let root = "src/llvm-project/llvm"; let out_dir = builder.llvm_out(target); @@ -1197,7 +1197,7 @@ impl Step for CrtBeginEnd { /// Build crtbegin.o/crtend.o for musl target. fn run(self, builder: &Builder<'_>) -> Self::Output { - builder.update_submodule(Path::new("src/llvm-project")); + builder.require_and_update_submodule("src/llvm-project", None); let out_dir = builder.native_dir(self.target).join("crt"); @@ -1270,7 +1270,7 @@ impl Step for Libunwind { /// Build libunwind.a fn run(self, builder: &Builder<'_>) -> Self::Output { - builder.update_submodule(Path::new("src/llvm-project")); + builder.require_and_update_submodule("src/llvm-project", None); if builder.config.dry_run() { return PathBuf::new(); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index cc5931c68db1f..108b01de56108 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2398,8 +2398,8 @@ impl Step for RustcGuide { } fn run(self, builder: &Builder<'_>) { - let relative_path = Path::new("src").join("doc").join("rustc-dev-guide"); - builder.update_submodule(&relative_path); + let relative_path = "src/doc/rustc-dev-guide"; + builder.require_and_update_submodule(relative_path, None); let src = builder.src.join(relative_path); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook).delay_failure(); @@ -3009,7 +3009,7 @@ impl Step for Bootstrap { let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host); // Some tests require cargo submodule to be present. - builder.build.update_submodule(Path::new("src/tools/cargo")); + builder.build.require_and_update_submodule("src/tools/cargo", None); let mut check_bootstrap = command(builder.python()); check_bootstrap diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index d5fd3301b9273..bd0caef3963d7 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -1,6 +1,6 @@ use std::env; use std::fs; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use crate::core::build_steps::compile; use crate::core::build_steps::toolstate::ToolState; @@ -290,7 +290,7 @@ macro_rules! bootstrap_tool { fn run(self, builder: &Builder<'_>) -> PathBuf { $( for submodule in $submodules { - builder.update_submodule(Path::new(submodule)); + builder.require_and_update_submodule(submodule, None); } )* builder.ensure(ToolBuild { @@ -373,7 +373,7 @@ impl Step for OptimizedDist { fn run(self, builder: &Builder<'_>) -> PathBuf { // We need to ensure the rustc-perf submodule is initialized when building opt-dist since // the tool requires it to be in place to run. - builder.update_submodule(Path::new("src/tools/rustc-perf")); + builder.require_and_update_submodule("src/tools/rustc-perf", None); builder.ensure(ToolBuild { compiler: self.compiler, @@ -414,7 +414,7 @@ impl Step for RustcPerf { fn run(self, builder: &Builder<'_>) -> PathBuf { // We need to ensure the rustc-perf submodule is initialized. - builder.update_submodule(Path::new("src/tools/rustc-perf")); + builder.require_and_update_submodule("src/tools/rustc-perf", None); let tool = ToolBuild { compiler: self.compiler, @@ -715,7 +715,7 @@ impl Step for Cargo { } fn run(self, builder: &Builder<'_>) -> PathBuf { - builder.build.update_submodule(Path::new("src/tools/cargo")); + builder.build.require_and_update_submodule("src/tools/cargo", None); builder.ensure(ToolBuild { compiler: self.compiler, diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index e6b3cb320cf16..d6b0a9a44fc26 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -1,6 +1,6 @@ use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::utils::exec::command; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub(crate) struct Vendor { @@ -35,8 +35,8 @@ impl Step for Vendor { } // These submodules must be present for `x vendor` to work. - for path in ["src/tools/cargo", "src/doc/book"] { - builder.build.update_submodule(Path::new(path)); + for submodule in ["src/tools/cargo", "src/doc/book"] { + builder.build.require_and_update_submodule(submodule, None); } // Sync these paths by default. diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 97c9ece0036ea..922d02f2d8b1a 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -21,7 +21,7 @@ fn configure_with_args(cmd: &[String], host: &[&str], target: &[&str]) -> Config rust_codegen_backends: vec![], ..Config::parse(&["check".to_owned()]) }); - submodule_build.update_submodule(Path::new("src/doc/book")); + submodule_build.require_and_update_submodule("src/doc/book", None); config.submodules = Some(false); config.ninja_in_file = false; diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 0ce50ccaf3f68..6f736b6052bb5 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -473,7 +473,13 @@ impl Build { /// Given a path to the directory of a submodule, update it. /// /// `relative_path` should be relative to the root of the git repository, not an absolute path. - pub(crate) fn update_submodule(&self, relative_path: &Path) { + /// + /// This *does not* update the submodule if `config.toml` explicitly says + /// not to, or if we're not in a git repository (like a plain source + /// tarball). Typically [`Build::require_and_update_submodule`] should be + /// used instead to provide a nice error to the user if the submodule is + /// missing. + fn update_submodule(&self, relative_path: &Path) { if !self.config.submodules() { return; } @@ -579,6 +585,45 @@ impl Build { } } + /// Updates a submodule, and exits with a failure if submodule management + /// is disabled and the submodule does not exist. + /// + /// The given `err_hint` will be shown to the user if the submodule is not + /// checked out. + pub fn require_and_update_submodule(&self, submodule: &str, err_hint: Option<&str>) { + // When testing bootstrap itself, it is much faster to ignore + // submodules. Almost all Steps work fine without their submodules. + if cfg!(test) && !self.config.submodules() { + return; + } + let relative_path = Path::new(submodule); + self.update_submodule(relative_path); + let absolute_path = self.config.src.join(relative_path); + if dir_is_empty(&absolute_path) { + let maybe_enable = if !self.config.submodules() + && self.config.rust_info.is_managed_git_subrepository() + { + "\nConsider setting `build.submodules = true` or manually initializing the submodules." + } else { + "" + }; + let err_hint = err_hint.map_or_else(String::new, |e| format!("\n{e}")); + eprintln!( + "submodule {submodule} does not appear to be checked out, \ + but it is required for this step{maybe_enable}{err_hint}" + ); + exit!(1); + } + } + + /// Updates all submodules, and exits with an error if submodule + /// management is disabled and the submodule does not exist. + pub fn require_and_update_all_submodules(&self) { + for submodule in build_helper::util::parse_gitmodules(&self.src) { + self.require_and_update_submodule(submodule, None); + } + } + /// If any submodule has been initialized already, sync it unconditionally. /// This avoids contributors checking in a submodule change by accident. fn update_existing_submodules(&self) { From 18aa41958324ff1ba9e1dcb0c5d9c8f14bc0ae69 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 25 Jul 2024 16:36:57 -0700 Subject: [PATCH 08/19] Clarify comment about why bootstrap tests need src/doc/book --- src/bootstrap/src/core/builder/tests.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 922d02f2d8b1a..f9d6d5513705b 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -13,9 +13,12 @@ fn configure_with_args(cmd: &[String], host: &[&str], target: &[&str]) -> Config config.save_toolstates = None; config.dry_run = DryRun::SelfCheck; - // Ignore most submodules, since we don't need them for a dry run. - // But make sure to check out the `doc` and `rust-analyzer` submodules, since some steps need them - // just to know which commands to run. + // Ignore most submodules, since we don't need them for a dry run, and the + // tests run much faster without them. + // + // The src/doc/book submodule is needed because TheBook step tries to + // access files even during a dry-run (may want to consider just skipping + // that in a dry run). let submodule_build = Build::new(Config { // don't include LLVM, so CI doesn't require ninja/cmake to be installed rust_codegen_backends: vec![], From a20db06d5be876fbdaf1d4542d2974f2f76abba0 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 25 Jul 2024 17:10:08 -0700 Subject: [PATCH 09/19] Make sure submodules are checked out with `x test` If the submodule is not checked out, then these tests would fail. --- src/bootstrap/src/core/build_steps/test.rs | 24 +++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 108b01de56108..e2eef1baaf530 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2257,7 +2257,12 @@ impl BookTest { } macro_rules! test_book { - ($($name:ident, $path:expr, $book_name:expr, default=$default:expr;)+) => { + ($( + $name:ident, $path:expr, $book_name:expr, + default=$default:expr + $(,submodules = $submodules:expr)? + ; + )+) => { $( #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct $name { @@ -2280,6 +2285,11 @@ macro_rules! test_book { } fn run(self, builder: &Builder<'_>) { + $( + for submodule in $submodules { + builder.require_and_update_submodule(submodule, None); + } + )* builder.ensure(BookTest { compiler: self.compiler, path: PathBuf::from($path), @@ -2293,15 +2303,15 @@ macro_rules! test_book { } test_book!( - Nomicon, "src/doc/nomicon", "nomicon", default=false; - Reference, "src/doc/reference", "reference", default=false; + Nomicon, "src/doc/nomicon", "nomicon", default=false, submodules=["src/doc/nomicon"]; + Reference, "src/doc/reference", "reference", default=false, submodules=["src/doc/reference"]; RustdocBook, "src/doc/rustdoc", "rustdoc", default=true; RustcBook, "src/doc/rustc", "rustc", default=true; - RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false; - EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false; - TheBook, "src/doc/book", "book", default=false; + RustByExample, "src/doc/rust-by-example", "rust-by-example", default=false, submodules=["src/doc/rust-by-example"]; + EmbeddedBook, "src/doc/embedded-book", "embedded-book", default=false, submodules=["src/doc/embedded-book"]; + TheBook, "src/doc/book", "book", default=false, submodules=["src/doc/book"]; UnstableBook, "src/doc/unstable-book", "unstable-book", default=true; - EditionGuide, "src/doc/edition-guide", "edition-guide", default=false; + EditionGuide, "src/doc/edition-guide", "edition-guide", default=false, submodules=["src/doc/edition-guide"]; ); #[derive(Debug, Clone, PartialEq, Eq, Hash)] From 53ef052d455ba8bd9a4823c59696efb257aef2fa Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Thu, 25 Jul 2024 17:38:22 -0700 Subject: [PATCH 10/19] Integrate mdbook-spec for the reference. This updates the reference which is now using a new mdbook plugin. This requires a little extra work than a normal book because the plugin uses `rustdoc` to generate links to the standard library. It also ensures that the submodule is available for *any* command that uses rustbook, since it is now part of the rustbook workspace. --- src/bootstrap/src/core/build_steps/doc.rs | 72 +++++++++++++++++--- src/bootstrap/src/core/build_steps/tool.rs | 2 +- src/bootstrap/src/core/build_steps/vendor.rs | 3 +- src/doc/reference | 2 +- src/tools/rustbook/Cargo.lock | 21 ++++++ src/tools/rustbook/Cargo.toml | 1 + src/tools/rustbook/src/main.rs | 12 ++++ src/tools/tidy/src/deps.rs | 2 +- 8 files changed, 102 insertions(+), 13 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 079539388bd23..78e6e7af687ea 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -9,7 +9,7 @@ use std::io::{self, Write}; use std::path::{Path, PathBuf}; -use std::{fs, mem}; +use std::{env, fs, mem}; use crate::core::build_steps::compile; use crate::core::build_steps::tool::{self, prepare_tool_cargo, SourceType, Tool}; @@ -62,6 +62,7 @@ macro_rules! book { src: builder.src.join($path), parent: Some(self), languages: $lang.into(), + rustdoc: None, }) } } @@ -80,7 +81,6 @@ book!( EditionGuide, "src/doc/edition-guide", "edition-guide", &[], submodule; EmbeddedBook, "src/doc/embedded-book", "embedded-book", &[], submodule; Nomicon, "src/doc/nomicon", "nomicon", &[], submodule; - Reference, "src/doc/reference", "reference", &[], submodule; RustByExample, "src/doc/rust-by-example", "rust-by-example", &["ja"], submodule; RustdocBook, "src/doc/rustdoc", "rustdoc", &[]; StyleGuide, "src/doc/style-guide", "style-guide", &[]; @@ -112,6 +112,7 @@ impl Step for UnstableBook { src: builder.md_doc_out(self.target).join("unstable-book"), parent: Some(self), languages: vec![], + rustdoc: None, }) } } @@ -123,6 +124,7 @@ struct RustbookSrc { src: PathBuf, parent: Option

, languages: Vec<&'static str>, + rustdoc: Option, } impl Step for RustbookSrc

{ @@ -153,13 +155,18 @@ impl Step for RustbookSrc

{ builder.info(&format!("Rustbook ({target}) - {name}")); let _ = fs::remove_dir_all(&out); - builder - .tool_cmd(Tool::Rustbook) - .arg("build") - .arg(&src) - .arg("-d") - .arg(&out) - .run(builder); + let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook); + if let Some(mut rustdoc) = self.rustdoc { + rustdoc.pop(); + let old_path = env::var_os("PATH").unwrap_or_default(); + let new_path = + env::join_paths(std::iter::once(rustdoc).chain(env::split_paths(&old_path))) + .expect("could not add rustdoc to PATH"); + + rustbook_cmd.env("PATH", new_path); + } + + rustbook_cmd.arg("build").arg(&src).arg("-d").arg(&out).run(builder); for lang in &self.languages { let out = out.join(lang); @@ -232,6 +239,7 @@ impl Step for TheBook { src: absolute_path.clone(), parent: Some(self), languages: vec![], + rustdoc: None, }); // building older edition redirects @@ -244,6 +252,7 @@ impl Step for TheBook { // treat the other editions as not having a parent. parent: Option::::None, languages: vec![], + rustdoc: None, }); } @@ -1214,6 +1223,51 @@ impl Step for RustcBook { src: out_base, parent: Some(self), languages: vec![], + rustdoc: None, + }); + } +} + +#[derive(Ord, PartialOrd, Debug, Clone, Hash, PartialEq, Eq)] +pub struct Reference { + pub compiler: Compiler, + pub target: TargetSelection, +} + +impl Step for Reference { + type Output = (); + const DEFAULT: bool = true; + const ONLY_HOSTS: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + let builder = run.builder; + run.path("src/doc/reference").default_condition(builder.config.docs) + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(Reference { + compiler: run.builder.compiler(run.builder.top_stage, run.builder.config.build), + target: run.target, + }); + } + + /// Builds the reference book. + fn run(self, builder: &Builder<'_>) { + builder.require_and_update_submodule("src/doc/reference", None); + + // This is needed for generating links to the standard library using + // the mdbook-spec plugin. + builder.ensure(compile::Std::new(self.compiler, builder.config.build)); + let rustdoc = builder.rustdoc(self.compiler); + + // Run rustbook/mdbook to generate the HTML pages. + builder.ensure(RustbookSrc { + target: self.target, + name: "reference".to_owned(), + src: builder.src.join("src/doc/reference"), + parent: Some(self), + languages: vec![], + rustdoc: Some(rustdoc), }); } } diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index bd0caef3963d7..57447117b29b4 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -348,7 +348,7 @@ bootstrap_tool!( /// These are the submodules that are required for rustbook to work due to /// depending on mdbook plugins. -pub static SUBMODULES_FOR_RUSTBOOK: &[&str] = &["src/doc/book"]; +pub static SUBMODULES_FOR_RUSTBOOK: &[&str] = &["src/doc/book", "src/doc/reference"]; #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct OptimizedDist { diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index d6b0a9a44fc26..d5cd3c0832ac9 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -1,3 +1,4 @@ +use crate::core::build_steps::tool::SUBMODULES_FOR_RUSTBOOK; use crate::core::builder::{Builder, RunConfig, ShouldRun, Step}; use crate::utils::exec::command; use std::path::PathBuf; @@ -35,7 +36,7 @@ impl Step for Vendor { } // These submodules must be present for `x vendor` to work. - for submodule in ["src/tools/cargo", "src/doc/book"] { + for submodule in SUBMODULES_FOR_RUSTBOOK.iter().chain(["src/tools/cargo"].iter()) { builder.build.require_and_update_submodule(submodule, None); } diff --git a/src/doc/reference b/src/doc/reference index e2f0bdc403186..2e191814f163e 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit e2f0bdc4031866734661dcdb548184bde1450baf +Subproject commit 2e191814f163ee1e77e2d6094eee4dd78a289c5b diff --git a/src/tools/rustbook/Cargo.lock b/src/tools/rustbook/Cargo.lock index 75b89a162e9ec..df051ed447e51 100644 --- a/src/tools/rustbook/Cargo.lock +++ b/src/tools/rustbook/Cargo.lock @@ -661,6 +661,20 @@ dependencies = [ "textwrap", ] +[[package]] +name = "mdbook-spec" +version = "0.1.2" +dependencies = [ + "anyhow", + "mdbook", + "once_cell", + "pathdiff", + "regex", + "semver", + "serde_json", + "tempfile", +] + [[package]] name = "mdbook-trpl-listing" version = "0.1.0" @@ -794,6 +808,12 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "pathdiff" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8835116a5c179084a830efb3adc117ab007512b535bc1a21c991d3b32a6b44dd" + [[package]] name = "percent-encoding" version = "2.3.1" @@ -1079,6 +1099,7 @@ dependencies = [ "env_logger", "mdbook", "mdbook-i18n-helpers", + "mdbook-spec", "mdbook-trpl-listing", "mdbook-trpl-note", ] diff --git a/src/tools/rustbook/Cargo.toml b/src/tools/rustbook/Cargo.toml index 51ba58483c5ce..2c29a2848b7e5 100644 --- a/src/tools/rustbook/Cargo.toml +++ b/src/tools/rustbook/Cargo.toml @@ -12,6 +12,7 @@ env_logger = "0.11" mdbook-trpl-listing = { path = "../../doc/book/packages/mdbook-trpl-listing" } mdbook-trpl-note = { path = "../../doc/book/packages/mdbook-trpl-note" } mdbook-i18n-helpers = "0.3.3" +mdbook-spec = { path = "../../doc/reference/mdbook-spec"} [dependencies.mdbook] version = "0.4.37" diff --git a/src/tools/rustbook/src/main.rs b/src/tools/rustbook/src/main.rs index 31bba56addeb4..e94c2f5958ebe 100644 --- a/src/tools/rustbook/src/main.rs +++ b/src/tools/rustbook/src/main.rs @@ -9,6 +9,7 @@ use mdbook::errors::Result as Result3; use mdbook::MDBook; use mdbook_i18n_helpers::preprocessors::Gettext; +use mdbook_spec::Spec; use mdbook_trpl_listing::TrplListing; use mdbook_trpl_note::TrplNote; @@ -83,6 +84,13 @@ pub fn build(args: &ArgMatches) -> Result3<()> { book.config.build.build_dir = dest_dir.into(); } + // NOTE: Replacing preprocessors using this technique causes error + // messages to be displayed when the original preprocessor doesn't work + // (but it otherwise succeeds). + // + // This should probably be fixed in mdbook to remove the existing + // preprocessor, or this should modify the config and use + // MDBook::load_with_config. if book.config.get_preprocessor("trpl-note").is_some() { book.with_preprocessor(TrplNote); } @@ -91,6 +99,10 @@ pub fn build(args: &ArgMatches) -> Result3<()> { book.with_preprocessor(TrplListing); } + if book.config.get_preprocessor("spec").is_some() { + book.with_preprocessor(Spec::new()); + } + book.build()?; Ok(()) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 6d61e0dd3effd..d53e535a750f7 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -72,7 +72,7 @@ pub(crate) const WORKSPACES: &[(&str, ExceptionList, Option<(&[&str], &[&str])>, //("src/tools/miri/test-cargo-miri", &[], None), // FIXME uncomment once all deps are vendored //("src/tools/miri/test_dependencies", &[], None), // FIXME uncomment once all deps are vendored ("src/tools/rust-analyzer", EXCEPTIONS_RUST_ANALYZER, None, &[]), - ("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book"]), + ("src/tools/rustbook", EXCEPTIONS_RUSTBOOK, None, &["src/doc/book", "src/doc/reference"]), ("src/tools/rustc-perf", EXCEPTIONS_RUSTC_PERF, None, &["src/tools/rustc-perf"]), ("src/tools/x", &[], None, &[]), // tidy-alphabetical-end From 3abf0ba4fca59894b2b7fcafde347a3497c22e85 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Fri, 26 Jul 2024 23:47:09 -0700 Subject: [PATCH 11/19] rustdoc: use strategic ThinVec/Box to shrink `clean::ItemKind` --- src/librustdoc/clean/inline.rs | 15 ++-- src/librustdoc/clean/mod.rs | 69 ++++++++++--------- src/librustdoc/clean/types.rs | 24 ++++--- src/librustdoc/fold.rs | 2 +- src/librustdoc/html/format.rs | 2 +- src/librustdoc/html/render/mod.rs | 67 +++++++++++------- src/librustdoc/html/render/print_item.rs | 6 +- src/librustdoc/json/conversions.rs | 20 ++++-- .../passes/check_doc_test_visibility.rs | 2 +- src/librustdoc/visit.rs | 2 +- 10 files changed, 120 insertions(+), 89 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0024e246ef007..dbdc4a5ae7188 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -131,8 +131,8 @@ pub(crate) fn try_inline( Res::Def(DefKind::Const, did) => { record_extern_fqn(cx, did, ItemType::Constant); cx.with_param_env(did, |cx| { - let (generics, ty, ct) = build_const_item(cx, did); - clean::ConstantItem(generics, Box::new(ty), ct) + let ct = build_const_item(cx, did); + clean::ConstantItem(Box::new(ct)) }) } Res::Def(DefKind::Macro(kind), did) => { @@ -720,10 +720,7 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String { } } -fn build_const_item( - cx: &mut DocContext<'_>, - def_id: DefId, -) -> (clean::Generics, clean::Type, clean::Constant) { +fn build_const_item(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant { let mut generics = clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id)); clean::simplify::move_bounds_to_generic_parameters(&mut generics); @@ -733,17 +730,17 @@ fn build_const_item( None, None, ); - (generics, ty, clean::Constant { kind: clean::ConstantKind::Extern { def_id } }) + clean::Constant { generics, type_: ty, kind: clean::ConstantKind::Extern { def_id } } } fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static { clean::Static { - type_: clean_middle_ty( + type_: Box::new(clean_middle_ty( ty::Binder::dummy(cx.tcx.type_of(did).instantiate_identity()), cx, Some(did), None, - ), + )), mutability: if mutable { Mutability::Mut } else { Mutability::Not }, expr: None, } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 26011926cddda..aaefac32711f1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -287,23 +287,21 @@ fn clean_lifetime<'tcx>(lifetime: &hir::Lifetime, cx: &mut DocContext<'tcx>) -> pub(crate) fn clean_const<'tcx>( constant: &hir::ConstArg<'tcx>, _cx: &mut DocContext<'tcx>, -) -> Constant { +) -> ConstantKind { match &constant.kind { hir::ConstArgKind::Path(qpath) => { - Constant { kind: ConstantKind::Path { path: qpath_to_string(&qpath).into() } } - } - hir::ConstArgKind::Anon(anon) => { - Constant { kind: ConstantKind::Anonymous { body: anon.body } } + ConstantKind::Path { path: qpath_to_string(&qpath).into() } } + hir::ConstArgKind::Anon(anon) => ConstantKind::Anonymous { body: anon.body }, } } pub(crate) fn clean_middle_const<'tcx>( constant: ty::Binder<'tcx, ty::Const<'tcx>>, _cx: &mut DocContext<'tcx>, -) -> Constant { +) -> ConstantKind { // FIXME: instead of storing the stringified expression, store `self` directly instead. - Constant { kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() } } + ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() } } pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option { @@ -1230,14 +1228,11 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext let local_did = trait_item.owner_id.to_def_id(); cx.with_param_env(local_did, |cx| { let inner = match trait_item.kind { - hir::TraitItemKind::Const(ty, Some(default)) => { - let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); - AssocConstItem( - generics, - Box::new(clean_ty(ty, cx)), - ConstantKind::Local { def_id: local_did, body: default }, - ) - } + hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem(Box::new(Constant { + generics: enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)), + kind: ConstantKind::Local { def_id: local_did, body: default }, + type_: clean_ty(ty, cx), + })), hir::TraitItemKind::Const(ty, None) => { let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx)); TyAssocConstItem(generics, Box::new(clean_ty(ty, cx))) @@ -1282,11 +1277,11 @@ pub(crate) fn clean_impl_item<'tcx>( let local_did = impl_.owner_id.to_def_id(); cx.with_param_env(local_did, |cx| { let inner = match impl_.kind { - hir::ImplItemKind::Const(ty, expr) => { - let generics = clean_generics(impl_.generics, cx); - let default = ConstantKind::Local { def_id: local_did, body: expr }; - AssocConstItem(generics, Box::new(clean_ty(ty, cx)), default) - } + hir::ImplItemKind::Const(ty, expr) => AssocConstItem(Box::new(Constant { + generics: clean_generics(impl_.generics, cx), + kind: ConstantKind::Local { def_id: local_did, body: expr }, + type_: clean_ty(ty, cx), + })), hir::ImplItemKind::Fn(ref sig, body) => { let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body)); let defaultness = cx.tcx.defaultness(impl_.owner_id); @@ -1320,12 +1315,12 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( let tcx = cx.tcx; let kind = match assoc_item.kind { ty::AssocKind::Const => { - let ty = Box::new(clean_middle_ty( + let ty = clean_middle_ty( ty::Binder::dummy(tcx.type_of(assoc_item.def_id).instantiate_identity()), cx, Some(assoc_item.def_id), None, - )); + ); let mut generics = clean_ty_generics( cx, @@ -1339,9 +1334,13 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( ty::TraitContainer => tcx.defaultness(assoc_item.def_id).has_value(), }; if provided { - AssocConstItem(generics, ty, ConstantKind::Extern { def_id: assoc_item.def_id }) + AssocConstItem(Box::new(Constant { + generics, + kind: ConstantKind::Extern { def_id: assoc_item.def_id }, + type_: ty, + })) } else { - TyAssocConstItem(generics, ty) + TyAssocConstItem(generics, Box::new(ty)) } } ty::AssocKind::Fn => { @@ -1397,7 +1396,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>( { true } - (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => match &c.kind { + (GenericParamDefKind::Const { .. }, GenericArg::Const(c)) => match &**c { ConstantKind::TyConst { expr } => **expr == *param.name.as_str(), _ => false, }, @@ -2744,14 +2743,16 @@ fn clean_maybe_renamed_item<'tcx>( let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id())); cx.with_param_env(def_id, |cx| { let kind = match item.kind { - ItemKind::Static(ty, mutability, body_id) => { - StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) }) - } - ItemKind::Const(ty, generics, body_id) => ConstantItem( - clean_generics(generics, cx), - Box::new(clean_ty(ty, cx)), - Constant { kind: ConstantKind::Local { body: body_id, def_id } }, - ), + ItemKind::Static(ty, mutability, body_id) => StaticItem(Static { + type_: Box::new(clean_ty(ty, cx)), + mutability, + expr: Some(body_id), + }), + ItemKind::Const(ty, generics, body_id) => ConstantItem(Box::new(Constant { + generics: clean_generics(generics, cx), + type_: clean_ty(ty, cx), + kind: ConstantKind::Local { body: body_id, def_id }, + })), ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy { bounds: ty.bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(), generics: clean_generics(ty.generics, cx), @@ -3109,7 +3110,7 @@ fn clean_maybe_renamed_foreign_item<'tcx>( ForeignFunctionItem(Box::new(Function { decl, generics }), safety) } hir::ForeignItemKind::Static(ty, mutability, safety) => ForeignStaticItem( - Static { type_: clean_ty(ty, cx), mutability, expr: None }, + Static { type_: Box::new(clean_ty(ty, cx)), mutability, expr: None }, safety, ), hir::ForeignItemKind::Type => ForeignTypeItem, diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 3709953159686..92fe98130e859 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -852,9 +852,9 @@ pub(crate) enum ItemKind { PrimitiveItem(PrimitiveType), /// A required associated constant in a trait declaration. TyAssocConstItem(Generics, Box), - ConstantItem(Generics, Box, Constant), + ConstantItem(Box), /// An associated constant in a trait impl or a provided one in a trait declaration. - AssocConstItem(Generics, Box, ConstantKind), + AssocConstItem(Box), /// A required associated type in a trait declaration. /// /// The bounds may be non-empty if there is a `where` clause. @@ -888,7 +888,7 @@ impl ItemKind { | TypeAliasItem(_) | OpaqueTyItem(_) | StaticItem(_) - | ConstantItem(_, _, _) + | ConstantItem(_) | TraitAliasItem(_) | TyMethodItem(_) | MethodItem(_, _) @@ -922,7 +922,7 @@ impl ItemKind { | TypeAliasItem(_) | OpaqueTyItem(_) | StaticItem(_) - | ConstantItem(_, _, _) + | ConstantItem(_) | TraitAliasItem(_) | ForeignFunctionItem(_, _) | ForeignStaticItem(_, _) @@ -2050,7 +2050,7 @@ impl From for PrimitiveType { pub(crate) struct Struct { pub(crate) ctor_kind: Option, pub(crate) generics: Generics, - pub(crate) fields: Vec, + pub(crate) fields: ThinVec, } impl Struct { @@ -2076,7 +2076,7 @@ impl Union { /// only as a variant in an enum. #[derive(Clone, Debug)] pub(crate) struct VariantStruct { - pub(crate) fields: Vec, + pub(crate) fields: ThinVec, } impl VariantStruct { @@ -2110,7 +2110,7 @@ pub(crate) struct Variant { #[derive(Clone, Debug)] pub(crate) enum VariantKind { CLike, - Tuple(Vec), + Tuple(ThinVec), Struct(VariantStruct), } @@ -2246,7 +2246,7 @@ impl Path { pub(crate) enum GenericArg { Lifetime(Lifetime), Type(Type), - Const(Box), + Const(Box), Infer, } @@ -2359,20 +2359,22 @@ pub(crate) struct BareFunctionDecl { #[derive(Clone, Debug)] pub(crate) struct Static { - pub(crate) type_: Type, + pub(crate) type_: Box, pub(crate) mutability: Mutability, pub(crate) expr: Option, } #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub(crate) struct Constant { + pub(crate) generics: Generics, pub(crate) kind: ConstantKind, + pub(crate) type_: Type, } #[derive(Clone, PartialEq, Eq, Hash, Debug)] pub(crate) enum Term { Type(Type), - Constant(Constant), + Constant(ConstantKind), } impl Term { @@ -2594,7 +2596,7 @@ mod size_asserts { static_assert_size!(GenericParamDef, 40); static_assert_size!(Generics, 16); static_assert_size!(Item, 56); - static_assert_size!(ItemKind, 56); + static_assert_size!(ItemKind, 48); static_assert_size!(PathSegment, 40); static_assert_size!(Type, 32); // tidy-alphabetical-end diff --git a/src/librustdoc/fold.rs b/src/librustdoc/fold.rs index 346e9a4e113a5..beb7686e29c56 100644 --- a/src/librustdoc/fold.rs +++ b/src/librustdoc/fold.rs @@ -79,7 +79,7 @@ pub(crate) trait DocFolder: Sized { | FunctionItem(_) | OpaqueTyItem(_) | StaticItem(_) - | ConstantItem(_, _, _) + | ConstantItem(..) | TraitAliasItem(_) | TyMethodItem(_) | MethodItem(_, _) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 055781f7fed72..18ee04a2f4d5f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -375,7 +375,7 @@ impl clean::Lifetime { } } -impl clean::Constant { +impl clean::ConstantKind { pub(crate) fn print(&self, tcx: TyCtxt<'_>) -> impl Display + '_ { let expr = self.expr(tcx); display_fn( diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 5b9ef67109cf2..47712264e972d 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1090,22 +1090,26 @@ fn render_assoc_item( clean::MethodItem(m, _) => { assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode) } - kind @ (clean::TyAssocConstItem(generics, ty) | clean::AssocConstItem(generics, ty, _)) => { - assoc_const( - w, - item, - generics, - ty, - match kind { - clean::TyAssocConstItem(..) => None, - clean::AssocConstItem(.., default) => Some(default), - _ => unreachable!(), - }, - link, - if parent == ItemType::Trait { 4 } else { 0 }, - cx, - ) - } + clean::TyAssocConstItem(generics, ty) => assoc_const( + w, + item, + generics, + ty, + None, + link, + if parent == ItemType::Trait { 4 } else { 0 }, + cx, + ), + clean::AssocConstItem(ci) => assoc_const( + w, + item, + &ci.generics, + &ci.type_, + Some(&ci.kind), + link, + if parent == ItemType::Trait { 4 } else { 0 }, + cx, + ), clean::TyAssocTypeItem(ref generics, ref bounds) => assoc_type( w, item, @@ -1690,8 +1694,7 @@ fn render_impl( w.write_str(""); } } - kind @ (clean::TyAssocConstItem(generics, ty) - | clean::AssocConstItem(generics, ty, _)) => { + clean::TyAssocConstItem(generics, ty) => { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!(w, "

"); @@ -1706,11 +1709,29 @@ fn render_impl( item, generics, ty, - match kind { - clean::TyAssocConstItem(..) => None, - clean::AssocConstItem(.., default) => Some(default), - _ => unreachable!(), - }, + None, + link.anchor(if trait_.is_some() { &source_id } else { &id }), + 0, + cx, + ); + w.write_str("
"); + } + clean::AssocConstItem(ci) => { + let source_id = format!("{item_type}.{name}"); + let id = cx.derive_id(&source_id); + write!(w, "
"); + render_rightside(w, cx, item, render_mode); + if trait_.is_some() { + // Anchors are only used on trait impls. + write!(w, "ยง"); + } + w.write_str("

"); + assoc_const( + w, + item, + &ci.generics, + &ci.type_, + Some(&ci.kind), link.anchor(if trait_.is_some() { &source_id } else { &id }), 0, cx, diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index cf78a1d223c89..0cf62ccf6e7ff 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -267,7 +267,7 @@ pub(super) fn print_item(cx: &mut Context<'_>, item: &clean::Item, buf: &mut Buf clean::PrimitiveItem(_) => item_primitive(buf, cx, item), clean::StaticItem(ref i) => item_static(buf, cx, item, i, None), clean::ForeignStaticItem(ref i, safety) => item_static(buf, cx, item, i, Some(*safety)), - clean::ConstantItem(generics, ty, c) => item_constant(buf, cx, item, generics, ty, c), + clean::ConstantItem(ci) => item_constant(buf, cx, item, &ci.generics, &ci.type_, &ci.kind), clean::ForeignTypeItem => item_foreign_type(buf, cx, item), clean::KeywordItem => item_keyword(buf, cx, item), clean::OpaqueTyItem(ref e) => item_opaque_ty(buf, cx, item, e), @@ -1841,7 +1841,7 @@ fn item_constant( it: &clean::Item, generics: &clean::Generics, ty: &clean::Type, - c: &clean::Constant, + c: &clean::ConstantKind, ) { wrap_item(w, |w| { let tcx = cx.tcx(); @@ -1911,7 +1911,7 @@ fn item_fields( w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, - fields: &Vec, + fields: &[clean::Item], ctor_kind: Option, ) { let mut fields = fields diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 4ab0df3670859..a4731feb8de00 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -188,6 +188,16 @@ impl FromWithTcx for Constant { } } +impl FromWithTcx for Constant { + // FIXME(generic_const_items): Add support for generic const items. + fn from_tcx(constant: clean::ConstantKind, tcx: TyCtxt<'_>) -> Self { + let expr = constant.expr(tcx); + let value = constant.value(tcx); + let is_literal = constant.is_literal(tcx); + Constant { expr, value, is_literal } + } +} + impl FromWithTcx for TypeBinding { fn from_tcx(constraint: clean::AssocItemConstraint, tcx: TyCtxt<'_>) -> Self { TypeBinding { @@ -325,8 +335,8 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { TypeAliasItem(t) => ItemEnum::TypeAlias(t.into_tcx(tcx)), OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)), // FIXME(generic_const_items): Add support for generic free consts - ConstantItem(_generics, t, c) => { - ItemEnum::Constant { type_: (*t).into_tcx(tcx), const_: c.into_tcx(tcx) } + ConstantItem(ci) => { + ItemEnum::Constant { type_: ci.type_.into_tcx(tcx), const_: ci.kind.into_tcx(tcx) } } MacroItem(m) => ItemEnum::Macro(m.source), ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)), @@ -341,8 +351,8 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum { ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), default: None } } // FIXME(generic_const_items): Add support for generic associated consts. - AssocConstItem(_generics, ty, default) => { - ItemEnum::AssocConst { type_: (*ty).into_tcx(tcx), default: Some(default.expr(tcx)) } + AssocConstItem(ci) => { + ItemEnum::AssocConst { type_: ci.type_.into_tcx(tcx), default: Some(ci.kind.expr(tcx)) } } TyAssocTypeItem(g, b) => ItemEnum::AssocType { generics: g.into_tcx(tcx), @@ -829,7 +839,7 @@ impl FromWithTcx for OpaqueTy { impl FromWithTcx for Static { fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self { Static { - type_: stat.type_.into_tcx(tcx), + type_: (*stat.type_).into_tcx(tcx), mutable: stat.mutability == ast::Mutability::Mut, expr: stat .expr diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index 0437f5e5fd818..f97c417847359 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -62,7 +62,7 @@ pub(crate) fn should_have_doc_example(cx: &DocContext<'_>, item: &clean::Item) - | clean::AssocTypeItem(..) | clean::TypeAliasItem(_) | clean::StaticItem(_) - | clean::ConstantItem(_, _, _) + | clean::ConstantItem(..) | clean::ExternCrateItem { .. } | clean::ImportItem(_) | clean::PrimitiveItem(_) diff --git a/src/librustdoc/visit.rs b/src/librustdoc/visit.rs index b335dc5bd16b8..de836439be957 100644 --- a/src/librustdoc/visit.rs +++ b/src/librustdoc/visit.rs @@ -28,7 +28,7 @@ pub(crate) trait DocVisitor: Sized { | TypeAliasItem(_) | OpaqueTyItem(_) | StaticItem(_) - | ConstantItem(_, _, _) + | ConstantItem(..) | TraitAliasItem(_) | TyMethodItem(_) | MethodItem(_, _) From 5ebb821fa9f845e8edd854cbf15ace5dc36a61a4 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 27 Jul 2024 07:57:50 -0700 Subject: [PATCH 12/19] Fix mistake setting ONLY_HOSTS for Reference. This was a copy/paste mistake. --- src/bootstrap/src/core/build_steps/doc.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 78e6e7af687ea..1fbc78a94dfab 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -1237,7 +1237,6 @@ pub struct Reference { impl Step for Reference { type Output = (); const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { let builder = run.builder; From f76ab647d3b39581c3d29e5107c8d460f736989f Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 27 Jul 2024 07:59:37 -0700 Subject: [PATCH 13/19] Add more descriptions to why submodules are required. --- src/bootstrap/src/core/build_steps/compile.rs | 8 +++++--- src/bootstrap/src/core/build_steps/llvm.rs | 10 ++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 1efa3c8ada3a2..6bea163cdfe2a 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -188,7 +188,9 @@ impl Step for Std { if builder.config.profiler { builder.require_and_update_submodule( "src/llvm-project", - Some("The `build.profiler` config option requires compiler-rt sources."), + Some( + "The `build.profiler` config option requires `compiler-rt` sources from LLVM.", + ), ); } @@ -462,8 +464,8 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car builder.require_and_update_submodule( "src/llvm-project", Some( - "need LLVM sources available to build `compiler-rt`, but they weren't present; \ - consider disabling `optimized-compiler-builtins`", + "The `build.optimized-compiler-builtins` config option \ + requires `compiler-rt` sources from LLVM.", ), ); let compiler_builtins_root = builder.src.join("src/llvm-project/compiler-rt"); diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 5d892275ad363..f8a22b9748852 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1197,7 +1197,10 @@ impl Step for CrtBeginEnd { /// Build crtbegin.o/crtend.o for musl target. fn run(self, builder: &Builder<'_>) -> Self::Output { - builder.require_and_update_submodule("src/llvm-project", None); + builder.require_and_update_submodule( + "src/llvm-project", + Some("The LLVM sources are required for the CRT from `compiler-rt`."), + ); let out_dir = builder.native_dir(self.target).join("crt"); @@ -1270,7 +1273,10 @@ impl Step for Libunwind { /// Build libunwind.a fn run(self, builder: &Builder<'_>) -> Self::Output { - builder.require_and_update_submodule("src/llvm-project", None); + builder.require_and_update_submodule( + "src/llvm-project", + Some("The LLVM sources are required for libunwind."), + ); if builder.config.dry_run() { return PathBuf::new(); From 9b0115c7436e6367f11a2b93894a2345c90a60e0 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 27 Jul 2024 08:02:06 -0700 Subject: [PATCH 14/19] Consistently use a string to represent a submodule. This makes it easier to call these functions without needing to form a Path. --- src/bootstrap/src/core/build_steps/llvm.rs | 2 +- src/bootstrap/src/lib.rs | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index f8a22b9748852..cd64492164f87 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -89,7 +89,7 @@ impl LdFlags { /// if not). pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> LlvmBuildStatus { // If we have llvm submodule initialized already, sync it. - builder.update_existing_submodule(&Path::new("src").join("llvm-project")); + builder.update_existing_submodule("src/llvm-project"); builder.config.maybe_download_ci_llvm(); diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 6f736b6052bb5..431b04ae77462 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -441,7 +441,7 @@ impl Build { // Cargo.toml files. let rust_submodules = ["library/backtrace", "library/stdarch"]; for s in rust_submodules { - build.update_submodule(Path::new(s)); + build.update_submodule(s); } // Now, update all existing submodules. build.update_existing_submodules(); @@ -479,7 +479,7 @@ impl Build { /// tarball). Typically [`Build::require_and_update_submodule`] should be /// used instead to provide a nice error to the user if the submodule is /// missing. - fn update_submodule(&self, relative_path: &Path) { + fn update_submodule(&self, relative_path: &str) { if !self.config.submodules() { return; } @@ -527,7 +527,7 @@ impl Build { return; } - println!("Updating submodule {}", relative_path.display()); + println!("Updating submodule {relative_path}"); helpers::git(Some(&self.src)) .run_always() .args(["submodule", "-q", "sync"]) @@ -596,9 +596,8 @@ impl Build { if cfg!(test) && !self.config.submodules() { return; } - let relative_path = Path::new(submodule); - self.update_submodule(relative_path); - let absolute_path = self.config.src.join(relative_path); + self.update_submodule(submodule); + let absolute_path = self.config.src.join(submodule); if dir_is_empty(&absolute_path) { let maybe_enable = if !self.config.submodules() && self.config.rust_info.is_managed_git_subrepository() @@ -642,22 +641,23 @@ impl Build { for line in output.lines() { // Look for `submodule.$name.path = $path` // Sample output: `submodule.src/rust-installer.path src/tools/rust-installer` - let submodule = Path::new(line.split_once(' ').unwrap().1); + let submodule = line.split_once(' ').unwrap().1; + let path = Path::new(submodule); // Don't update the submodule unless it's already been cloned. - if GitInfo::new(false, submodule).is_managed_git_subrepository() { + if GitInfo::new(false, path).is_managed_git_subrepository() { self.update_submodule(submodule); } } } /// Updates the given submodule only if it's initialized already; nothing happens otherwise. - pub fn update_existing_submodule(&self, submodule: &Path) { + pub fn update_existing_submodule(&self, submodule: &str) { // Avoid running git when there isn't a git checkout. if !self.config.submodules() { return; } - if GitInfo::new(false, submodule).is_managed_git_subrepository() { + if GitInfo::new(false, Path::new(submodule)).is_managed_git_subrepository() { self.update_submodule(submodule); } } From 686e27ef49ab0d0d84e451311529283269d456e8 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 27 Jul 2024 08:04:46 -0700 Subject: [PATCH 15/19] Change the blanket submodule update for library submodules to be required These are required 100% of the time, but they are almost always required for any command that runs Cargo in the main workspace. Ideally, initializing these two standard library submodules would be lazy and only initialized when required (see https://github.com/rust-lang/rust/pull/82653). However, it would require updating these in almost every Step (anything that runs `cargo` in the main workspace). --- src/bootstrap/src/lib.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 431b04ae77462..68dfc89c5a1a4 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -441,7 +441,13 @@ impl Build { // Cargo.toml files. let rust_submodules = ["library/backtrace", "library/stdarch"]; for s in rust_submodules { - build.update_submodule(s); + build.require_and_update_submodule( + s, + Some( + "The submodule is required for the standard library \ + and the main Cargo workspace.", + ), + ); } // Now, update all existing submodules. build.update_existing_submodules(); From 78ee5d057baaa3a08e81c57828317126474c3ccf Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 27 Jul 2024 08:06:04 -0700 Subject: [PATCH 16/19] Change prebuilt_llvm_config to not be required. I misread this one. It is only checking if LLVM needs to be rebuilt. There is code below that handles the case where it is unable to compute the stamp if the source is missing. --- src/bootstrap/src/core/build_steps/llvm.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index cd64492164f87..b302e6eb632ad 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -110,7 +110,8 @@ pub fn prebuilt_llvm_config(builder: &Builder<'_>, target: TargetSelection) -> L } // Initialize the llvm submodule if not initialized already. - builder.require_and_update_submodule("src/llvm-project", None); + // If submodules are disabled, this does nothing. + builder.update_submodule("src/llvm-project"); let root = "src/llvm-project/llvm"; let out_dir = builder.llvm_out(target); From 0f387eb39b33d018eac138bdfc4f16d26e4207f1 Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 27 Jul 2024 08:06:20 -0700 Subject: [PATCH 17/19] Add clarifying documentation to require_and_update_submodule. --- src/bootstrap/src/lib.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 68dfc89c5a1a4..49df30022e34d 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -594,8 +594,11 @@ impl Build { /// Updates a submodule, and exits with a failure if submodule management /// is disabled and the submodule does not exist. /// + /// The given submodule name should be its path relative to the root of + /// the main repository. + /// /// The given `err_hint` will be shown to the user if the submodule is not - /// checked out. + /// checked out and submodule management is disabled. pub fn require_and_update_submodule(&self, submodule: &str, err_hint: Option<&str>) { // When testing bootstrap itself, it is much faster to ignore // submodules. Almost all Steps work fine without their submodules. From 1c98b8f9226d0e7a4e0ef42dd558de2857812f7a Mon Sep 17 00:00:00 2001 From: Eric Huss Date: Sat, 27 Jul 2024 08:07:53 -0700 Subject: [PATCH 18/19] Rename require_and_update_submodule to require_submodule Just trying to be a little less verbose here. --- src/bootstrap/src/core/build_steps/check.rs | 2 +- src/bootstrap/src/core/build_steps/clippy.rs | 2 +- src/bootstrap/src/core/build_steps/compile.rs | 6 +++--- src/bootstrap/src/core/build_steps/dist.rs | 2 +- src/bootstrap/src/core/build_steps/doc.rs | 8 ++++---- src/bootstrap/src/core/build_steps/llvm.rs | 4 ++-- src/bootstrap/src/core/build_steps/test.rs | 6 +++--- src/bootstrap/src/core/build_steps/tool.rs | 8 ++++---- src/bootstrap/src/core/build_steps/vendor.rs | 2 +- src/bootstrap/src/core/builder/tests.rs | 2 +- src/bootstrap/src/lib.rs | 8 ++++---- 11 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs index 5b720ffbc76fa..3e0bb2884cd7d 100644 --- a/src/bootstrap/src/core/build_steps/check.rs +++ b/src/bootstrap/src/core/build_steps/check.rs @@ -52,7 +52,7 @@ impl Step for Std { } fn run(self, builder: &Builder<'_>) { - builder.require_and_update_submodule("library/stdarch", None); + builder.require_submodule("library/stdarch", None); let target = self.target; let compiler = builder.compiler(builder.top_stage, builder.config.build); diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index add28f858efb7..68abf1e464a7a 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -125,7 +125,7 @@ impl Step for Std { } fn run(self, builder: &Builder<'_>) { - builder.require_and_update_submodule("library/stdarch", None); + builder.require_submodule("library/stdarch", None); let target = self.target; let compiler = builder.compiler(builder.top_stage, builder.config.build); diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 6bea163cdfe2a..5964905804632 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -182,11 +182,11 @@ impl Step for Std { return; } - builder.require_and_update_submodule("library/stdarch", None); + builder.require_submodule("library/stdarch", None); // Profiler information requires LLVM's compiler-rt if builder.config.profiler { - builder.require_and_update_submodule( + builder.require_submodule( "src/llvm-project", Some( "The `build.profiler` config option requires `compiler-rt` sources from LLVM.", @@ -461,7 +461,7 @@ pub fn std_cargo(builder: &Builder<'_>, target: TargetSelection, stage: u32, car // That's probably ok? At least, the difference wasn't enforced before. There's a comment in // the compiler_builtins build script that makes me nervous, though: // https://github.com/rust-lang/compiler-builtins/blob/31ee4544dbe47903ce771270d6e3bea8654e9e50/build.rs#L575-L579 - builder.require_and_update_submodule( + builder.require_submodule( "src/llvm-project", Some( "The `build.optimized-compiler-builtins` config option \ diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 998f083b676ad..4f4ef29c1d79c 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -907,7 +907,7 @@ impl Step for Src { /// Creates the `rust-src` installer component fn run(self, builder: &Builder<'_>) -> GeneratedTarball { if !builder.config.dry_run() { - builder.require_and_update_submodule("src/llvm-project", None); + builder.require_submodule("src/llvm-project", None); } let tarball = Tarball::new_targetless(builder, "rust-src"); diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 1fbc78a94dfab..bdd48fa644a8a 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -54,7 +54,7 @@ macro_rules! book { fn run(self, builder: &Builder<'_>) { $( let path = submodule_helper!( $path, submodule $( = $submodule )? ); - builder.require_and_update_submodule(path, None); + builder.require_submodule(path, None); )? builder.ensure(RustbookSrc { target: self.target, @@ -224,7 +224,7 @@ impl Step for TheBook { /// * Index page /// * Redirect pages fn run(self, builder: &Builder<'_>) { - builder.require_and_update_submodule("src/doc/book", None); + builder.require_submodule("src/doc/book", None); let compiler = self.compiler; let target = self.target; @@ -934,7 +934,7 @@ macro_rules! tool_doc { let source_type = SourceType::Submodule; let path = submodule_helper!( $path, submodule $( = $submodule )? ); - builder.require_and_update_submodule(path, None); + builder.require_submodule(path, None); )? let stage = builder.top_stage; @@ -1252,7 +1252,7 @@ impl Step for Reference { /// Builds the reference book. fn run(self, builder: &Builder<'_>) { - builder.require_and_update_submodule("src/doc/reference", None); + builder.require_submodule("src/doc/reference", None); // This is needed for generating links to the standard library using // the mdbook-spec plugin. diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index b302e6eb632ad..369e14df14b25 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1198,7 +1198,7 @@ impl Step for CrtBeginEnd { /// Build crtbegin.o/crtend.o for musl target. fn run(self, builder: &Builder<'_>) -> Self::Output { - builder.require_and_update_submodule( + builder.require_submodule( "src/llvm-project", Some("The LLVM sources are required for the CRT from `compiler-rt`."), ); @@ -1274,7 +1274,7 @@ impl Step for Libunwind { /// Build libunwind.a fn run(self, builder: &Builder<'_>) -> Self::Output { - builder.require_and_update_submodule( + builder.require_submodule( "src/llvm-project", Some("The LLVM sources are required for libunwind."), ); diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index e2eef1baaf530..daafb41e9d81e 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2287,7 +2287,7 @@ macro_rules! test_book { fn run(self, builder: &Builder<'_>) { $( for submodule in $submodules { - builder.require_and_update_submodule(submodule, None); + builder.require_submodule(submodule, None); } )* builder.ensure(BookTest { @@ -2409,7 +2409,7 @@ impl Step for RustcGuide { fn run(self, builder: &Builder<'_>) { let relative_path = "src/doc/rustc-dev-guide"; - builder.require_and_update_submodule(relative_path, None); + builder.require_submodule(relative_path, None); let src = builder.src.join(relative_path); let mut rustbook_cmd = builder.tool_cmd(Tool::Rustbook).delay_failure(); @@ -3019,7 +3019,7 @@ impl Step for Bootstrap { let _guard = builder.msg(Kind::Test, 0, "bootstrap", host, host); // Some tests require cargo submodule to be present. - builder.build.require_and_update_submodule("src/tools/cargo", None); + builder.build.require_submodule("src/tools/cargo", None); let mut check_bootstrap = command(builder.python()); check_bootstrap diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index 57447117b29b4..a0cb0b0dbb9ac 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -290,7 +290,7 @@ macro_rules! bootstrap_tool { fn run(self, builder: &Builder<'_>) -> PathBuf { $( for submodule in $submodules { - builder.require_and_update_submodule(submodule, None); + builder.require_submodule(submodule, None); } )* builder.ensure(ToolBuild { @@ -373,7 +373,7 @@ impl Step for OptimizedDist { fn run(self, builder: &Builder<'_>) -> PathBuf { // We need to ensure the rustc-perf submodule is initialized when building opt-dist since // the tool requires it to be in place to run. - builder.require_and_update_submodule("src/tools/rustc-perf", None); + builder.require_submodule("src/tools/rustc-perf", None); builder.ensure(ToolBuild { compiler: self.compiler, @@ -414,7 +414,7 @@ impl Step for RustcPerf { fn run(self, builder: &Builder<'_>) -> PathBuf { // We need to ensure the rustc-perf submodule is initialized. - builder.require_and_update_submodule("src/tools/rustc-perf", None); + builder.require_submodule("src/tools/rustc-perf", None); let tool = ToolBuild { compiler: self.compiler, @@ -715,7 +715,7 @@ impl Step for Cargo { } fn run(self, builder: &Builder<'_>) -> PathBuf { - builder.build.require_and_update_submodule("src/tools/cargo", None); + builder.build.require_submodule("src/tools/cargo", None); builder.ensure(ToolBuild { compiler: self.compiler, diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs index d5cd3c0832ac9..8732b30e94000 100644 --- a/src/bootstrap/src/core/build_steps/vendor.rs +++ b/src/bootstrap/src/core/build_steps/vendor.rs @@ -37,7 +37,7 @@ impl Step for Vendor { // These submodules must be present for `x vendor` to work. for submodule in SUBMODULES_FOR_RUSTBOOK.iter().chain(["src/tools/cargo"].iter()) { - builder.build.require_and_update_submodule(submodule, None); + builder.build.require_submodule(submodule, None); } // Sync these paths by default. diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index f9d6d5513705b..ccabcad243f7b 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -24,7 +24,7 @@ fn configure_with_args(cmd: &[String], host: &[&str], target: &[&str]) -> Config rust_codegen_backends: vec![], ..Config::parse(&["check".to_owned()]) }); - submodule_build.require_and_update_submodule("src/doc/book", None); + submodule_build.require_submodule("src/doc/book", None); config.submodules = Some(false); config.ninja_in_file = false; diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs index 49df30022e34d..d4303aab6d6b9 100644 --- a/src/bootstrap/src/lib.rs +++ b/src/bootstrap/src/lib.rs @@ -441,7 +441,7 @@ impl Build { // Cargo.toml files. let rust_submodules = ["library/backtrace", "library/stdarch"]; for s in rust_submodules { - build.require_and_update_submodule( + build.require_submodule( s, Some( "The submodule is required for the standard library \ @@ -482,7 +482,7 @@ impl Build { /// /// This *does not* update the submodule if `config.toml` explicitly says /// not to, or if we're not in a git repository (like a plain source - /// tarball). Typically [`Build::require_and_update_submodule`] should be + /// tarball). Typically [`Build::require_submodule`] should be /// used instead to provide a nice error to the user if the submodule is /// missing. fn update_submodule(&self, relative_path: &str) { @@ -599,7 +599,7 @@ impl Build { /// /// The given `err_hint` will be shown to the user if the submodule is not /// checked out and submodule management is disabled. - pub fn require_and_update_submodule(&self, submodule: &str, err_hint: Option<&str>) { + pub fn require_submodule(&self, submodule: &str, err_hint: Option<&str>) { // When testing bootstrap itself, it is much faster to ignore // submodules. Almost all Steps work fine without their submodules. if cfg!(test) && !self.config.submodules() { @@ -628,7 +628,7 @@ impl Build { /// management is disabled and the submodule does not exist. pub fn require_and_update_all_submodules(&self) { for submodule in build_helper::util::parse_gitmodules(&self.src) { - self.require_and_update_submodule(submodule, None); + self.require_submodule(submodule, None); } } From 6f662176e7cc5ff81642ca243f50c6b7ed86b8f8 Mon Sep 17 00:00:00 2001 From: Nilstrieb <48135649+Nilstrieb@users.noreply.github.com> Date: Sun, 2 Jun 2024 12:00:18 +0200 Subject: [PATCH 19/19] Add migration lint for 2024 prelude additions This adds the migration lint for the newly ambiguous methods `poll` and `into_future`. When these methods are used on types implementing the respective traits, it will be ambiguous in the future, which can lead to hard errors or behavior changes depending on the exact circumstances. --- .../src/method/prelude_edition_lints.rs | 17 +++++++- compiler/rustc_lint_defs/src/builtin.rs | 41 +++++++++++++++++++ .../future-poll-already-future.rs | 17 ++++++++ .../future-poll-async-block.e2021.fixed | 21 ++++++++++ .../future-poll-async-block.e2021.stderr | 16 ++++++++ .../future-poll-async-block.rs | 21 ++++++++++ .../future-poll-not-future-pinned.e2021.fixed | 21 ++++++++++ ...future-poll-not-future-pinned.e2021.stderr | 16 ++++++++ .../future-poll-not-future-pinned.rs | 21 ++++++++++ .../future-poll-not-future.rs | 15 +++++++ .../in_2024_compatibility.rs | 17 ++++++++ .../in_2024_compatibility.stderr | 17 ++++++++ .../into-future-adt.e2021.fixed | 29 +++++++++++++ .../into-future-adt.e2021.stderr | 16 ++++++++ .../prelude-migration/into-future-adt.rs | 29 +++++++++++++ .../into-future-already-into-future.rs | 24 +++++++++++ .../into-future-not-into-future.e2021.fixed | 23 +++++++++++ .../into-future-not-into-future.e2021.stderr | 16 ++++++++ .../into-future-not-into-future.rs | 23 +++++++++++ 19 files changed, 399 insertions(+), 1 deletion(-) create mode 100644 tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs create mode 100644 tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed create mode 100644 tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr create mode 100644 tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs create mode 100644 tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed create mode 100644 tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr create mode 100644 tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs create mode 100644 tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs create mode 100644 tests/ui/rust-2024/prelude-migration/in_2024_compatibility.rs create mode 100644 tests/ui/rust-2024/prelude-migration/in_2024_compatibility.stderr create mode 100644 tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed create mode 100644 tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr create mode 100644 tests/ui/rust-2024/prelude-migration/into-future-adt.rs create mode 100644 tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs create mode 100644 tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed create mode 100644 tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr create mode 100644 tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs index 3ee10f74d98a4..3a902390fcff9 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs @@ -9,7 +9,7 @@ use rustc_hir as hir; use rustc_lint::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER}; use rustc_middle::span_bug; use rustc_middle::ty::{self, Ty}; -use rustc_session::lint::builtin::RUST_2021_PRELUDE_COLLISIONS; +use rustc_session::lint::builtin::{RUST_2021_PRELUDE_COLLISIONS, RUST_2024_PRELUDE_COLLISIONS}; use rustc_span::symbol::kw::{Empty, Underscore}; use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; @@ -35,6 +35,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (prelude_or_array_lint, edition) = match segment.ident.name { // `try_into` was added to the prelude in Rust 2021. sym::try_into if !span.at_least_rust_2021() => (RUST_2021_PRELUDE_COLLISIONS, "2021"), + // `Future::poll` was added to the prelude in Rust 2024. + sym::poll + // We check that the self type is `Pin<&mut _>` to avoid false positives for this common name. + if !span.at_least_rust_2024() + && let ty::Adt(adt_def, args) = self_ty.kind() + && self.tcx.is_lang_item(adt_def.did(), hir::LangItem::Pin) + && let ty::Ref(_, _, ty::Mutability::Mut) = + args[0].as_type().unwrap().kind() => + { + (RUST_2024_PRELUDE_COLLISIONS, "2024") + } + // `IntoFuture::into_future` was added to the prelude in Rust 2024. + sym::into_future if !span.at_least_rust_2024() => { + (RUST_2024_PRELUDE_COLLISIONS, "2024") + } // `into_iter` wasn't added to the prelude, // but `[T; N].into_iter()` doesn't resolve to IntoIterator::into_iter // before Rust 2021, which results in the same problem. diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 2ade6964ca89e..a650d5b6a44ab 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -91,6 +91,7 @@ declare_lint_pass! { RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, RUST_2021_PRELUDE_COLLISIONS, RUST_2024_INCOMPATIBLE_PAT, + RUST_2024_PRELUDE_COLLISIONS, SELF_CONSTRUCTOR_FROM_OUTER_ITEM, SEMICOLON_IN_EXPRESSIONS_FROM_MACROS, SINGLE_USE_LIFETIMES, @@ -3750,6 +3751,46 @@ declare_lint! { }; } +declare_lint! { + /// The `rust_2024_prelude_collisions` lint detects the usage of trait methods which are ambiguous + /// with traits added to the prelude in future editions. + /// + /// ### Example + /// + /// ```rust,edition2021,compile_fail + /// #![deny(rust_2024_prelude_collisions)] + /// trait Meow { + /// fn poll(&self) {} + /// } + /// impl Meow for T {} + /// + /// fn main() { + /// core::pin::pin!(async {}).poll(); + /// // ^^^^^^ + /// // This call to try_into matches both Future::poll and Meow::poll as + /// // `Future` has been added to the Rust prelude in 2024 edition. + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Rust 2024, introduces two new additions to the standard library's prelude: + /// `Future` and `IntoFuture`. This results in an ambiguity as to which method/function + /// to call when an existing `poll`/`into_future` method is called via dot-call syntax or + /// a `poll`/`into_future` associated function is called directly on a type. + /// + pub RUST_2024_PRELUDE_COLLISIONS, + Allow, + "detects the usage of trait methods which are ambiguous with traits added to the \ + prelude in future editions", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::EditionError(Edition::Edition2024), + reference: "", + }; +} + declare_lint! { /// The `rust_2021_prefixes_incompatible_syntax` lint detects identifiers that will be parsed as a /// prefix instead in Rust 2021. diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs b/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs new file mode 100644 index 0000000000000..7bf5118c3402e --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/future-poll-already-future.rs @@ -0,0 +1,17 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +//@ check-pass + +#![deny(rust_2024_prelude_collisions)] + +use std::future::Future; + +fn main() { + core::pin::pin!(async {}).poll(&mut context()); +} + +fn context() -> core::task::Context<'static> { + loop {} +} diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed new file mode 100644 index 0000000000000..44850c8c45bbc --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.fixed @@ -0,0 +1,21 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2021] run-rustfix +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +//@[e2024] check-pass + +#![deny(rust_2024_prelude_collisions)] +trait Meow { + fn poll(&self, _ctx: &mut core::task::Context<'_>) {} +} +impl Meow for T {} +fn main() { + Meow::poll(&core::pin::pin!(async {}), &mut context()); + //[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024 + //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! +} + +fn context() -> core::task::Context<'static> { + loop {} +} diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr new file mode 100644 index 0000000000000..496b3197c3405 --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.e2021.stderr @@ -0,0 +1,16 @@ +error: trait method `poll` will become ambiguous in Rust 2024 + --> $DIR/future-poll-async-block.rs:14:5 + | +LL | core::pin::pin!(async {}).poll(&mut context()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(async {}), &mut context())` + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see +note: the lint level is defined here + --> $DIR/future-poll-async-block.rs:8:9 + | +LL | #![deny(rust_2024_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs new file mode 100644 index 0000000000000..614e4c786c533 --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/future-poll-async-block.rs @@ -0,0 +1,21 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2021] run-rustfix +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +//@[e2024] check-pass + +#![deny(rust_2024_prelude_collisions)] +trait Meow { + fn poll(&self, _ctx: &mut core::task::Context<'_>) {} +} +impl Meow for T {} +fn main() { + core::pin::pin!(async {}).poll(&mut context()); + //[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024 + //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! +} + +fn context() -> core::task::Context<'static> { + loop {} +} diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed new file mode 100644 index 0000000000000..c96d1dcecc219 --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.fixed @@ -0,0 +1,21 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2021] run-rustfix +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +//@[e2024] check-pass + +#![deny(rust_2024_prelude_collisions)] +trait Meow { + fn poll(&self) {} +} +impl Meow for T {} +fn main() { + // This is a deliberate false positive. + // While `()` does not implement `Future` and can therefore not be ambiguous, we + // do not check that in the lint, as that introduces additional complexities. + // Just checking whether the self type is `Pin<&mut _>` is enough. + Meow::poll(&core::pin::pin!(())); + //[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024 + //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! +} diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr new file mode 100644 index 0000000000000..020a00ccdec02 --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.e2021.stderr @@ -0,0 +1,16 @@ +error: trait method `poll` will become ambiguous in Rust 2024 + --> $DIR/future-poll-not-future-pinned.rs:18:5 + | +LL | core::pin::pin!(()).poll(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(()))` + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see +note: the lint level is defined here + --> $DIR/future-poll-not-future-pinned.rs:8:9 + | +LL | #![deny(rust_2024_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs new file mode 100644 index 0000000000000..21b170a5f1db0 --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future-pinned.rs @@ -0,0 +1,21 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2021] run-rustfix +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +//@[e2024] check-pass + +#![deny(rust_2024_prelude_collisions)] +trait Meow { + fn poll(&self) {} +} +impl Meow for T {} +fn main() { + // This is a deliberate false positive. + // While `()` does not implement `Future` and can therefore not be ambiguous, we + // do not check that in the lint, as that introduces additional complexities. + // Just checking whether the self type is `Pin<&mut _>` is enough. + core::pin::pin!(()).poll(); + //[e2021]~^ ERROR trait method `poll` will become ambiguous in Rust 2024 + //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! +} diff --git a/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs b/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs new file mode 100644 index 0000000000000..899b69ebfc246 --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/future-poll-not-future.rs @@ -0,0 +1,15 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +//@ check-pass + +#![deny(rust_2024_prelude_collisions)] +trait Meow { + fn poll(&self) {} +} +impl Meow for T {} +fn main() { + // As the self type here is not `Pin<&mut _>`, the lint does not fire. + ().poll(); +} diff --git a/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.rs b/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.rs new file mode 100644 index 0000000000000..b6a5d278720cf --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.rs @@ -0,0 +1,17 @@ +//@ edition: 2021 + +#![deny(rust_2024_compatibility)] + +trait Meow { + fn poll(&self, _ctx: &mut core::task::Context<'_>) {} +} +impl Meow for T {} +fn main() { + core::pin::pin!(async {}).poll(&mut context()); + //~^ ERROR trait method `poll` will become ambiguous in Rust 2024 + //~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! +} + +fn context() -> core::task::Context<'static> { + loop {} +} diff --git a/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.stderr b/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.stderr new file mode 100644 index 0000000000000..5865029d65de2 --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/in_2024_compatibility.stderr @@ -0,0 +1,17 @@ +error: trait method `poll` will become ambiguous in Rust 2024 + --> $DIR/in_2024_compatibility.rs:10:5 + | +LL | core::pin::pin!(async {}).poll(&mut context()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::poll(&core::pin::pin!(async {}), &mut context())` + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see +note: the lint level is defined here + --> $DIR/in_2024_compatibility.rs:3:9 + | +LL | #![deny(rust_2024_compatibility)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: `#[deny(rust_2024_prelude_collisions)]` implied by `#[deny(rust_2024_compatibility)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed new file mode 100644 index 0000000000000..0b0873eb23842 --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.fixed @@ -0,0 +1,29 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2021] run-rustfix +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +//@[e2024] check-pass + +#![deny(rust_2024_prelude_collisions)] +trait Meow { + fn into_future(&self) {} +} +impl Meow for Cat {} + +struct Cat; + +impl core::future::IntoFuture for Cat { + type Output = (); + type IntoFuture = core::future::Ready<()>; + + fn into_future(self) -> Self::IntoFuture { + core::future::ready(()) + } +} + +fn main() { + Meow::into_future(&Cat); + //[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024 + //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! +} diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr new file mode 100644 index 0000000000000..b74e80e2a4a08 --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.e2021.stderr @@ -0,0 +1,16 @@ +error: trait method `into_future` will become ambiguous in Rust 2024 + --> $DIR/into-future-adt.rs:26:5 + | +LL | Cat.into_future(); + | ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::into_future(&Cat)` + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see +note: the lint level is defined here + --> $DIR/into-future-adt.rs:8:9 + | +LL | #![deny(rust_2024_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/rust-2024/prelude-migration/into-future-adt.rs b/tests/ui/rust-2024/prelude-migration/into-future-adt.rs new file mode 100644 index 0000000000000..0db70930bc75b --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/into-future-adt.rs @@ -0,0 +1,29 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2021] run-rustfix +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +//@[e2024] check-pass + +#![deny(rust_2024_prelude_collisions)] +trait Meow { + fn into_future(&self) {} +} +impl Meow for Cat {} + +struct Cat; + +impl core::future::IntoFuture for Cat { + type Output = (); + type IntoFuture = core::future::Ready<()>; + + fn into_future(self) -> Self::IntoFuture { + core::future::ready(()) + } +} + +fn main() { + Cat.into_future(); + //[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024 + //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! +} diff --git a/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs b/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs new file mode 100644 index 0000000000000..6bc2ea317059e --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/into-future-already-into-future.rs @@ -0,0 +1,24 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +//@ check-pass + +#![deny(rust_2024_prelude_collisions)] + +use core::future::IntoFuture; + +struct Cat; + +impl IntoFuture for Cat { + type Output = (); + type IntoFuture = core::future::Ready<()>; + + fn into_future(self) -> Self::IntoFuture { + core::future::ready(()) + } +} + +fn main() { + let _ = Cat.into_future(); +} diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed new file mode 100644 index 0000000000000..a798014d93d3b --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.fixed @@ -0,0 +1,23 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2021] run-rustfix +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +//@[e2024] check-pass + +#![deny(rust_2024_prelude_collisions)] +trait Meow { + fn into_future(&self) {} +} +impl Meow for Cat {} + +struct Cat; + +fn main() { + // This is a false positive, but it should be rare enough to not matter, and checking whether + // it implements the trait can have other nontrivial consequences, so it was decided to accept + // this. + Meow::into_future(&Cat); + //[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024 + //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! +} diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr new file mode 100644 index 0000000000000..6ea4580ca72ed --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.e2021.stderr @@ -0,0 +1,16 @@ +error: trait method `into_future` will become ambiguous in Rust 2024 + --> $DIR/into-future-not-into-future.rs:20:5 + | +LL | Cat.into_future(); + | ^^^^^^^^^^^^^^^^^ help: disambiguate the associated function: `Meow::into_future(&Cat)` + | + = warning: this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! + = note: for more information, see +note: the lint level is defined here + --> $DIR/into-future-not-into-future.rs:8:9 + | +LL | #![deny(rust_2024_prelude_collisions)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs new file mode 100644 index 0000000000000..23e81cfe6b48d --- /dev/null +++ b/tests/ui/rust-2024/prelude-migration/into-future-not-into-future.rs @@ -0,0 +1,23 @@ +//@ revisions: e2021 e2024 +//@[e2021] edition: 2021 +//@[e2021] run-rustfix +//@[e2024] edition: 2024 +//@[e2024] compile-flags: -Zunstable-options +//@[e2024] check-pass + +#![deny(rust_2024_prelude_collisions)] +trait Meow { + fn into_future(&self) {} +} +impl Meow for Cat {} + +struct Cat; + +fn main() { + // This is a false positive, but it should be rare enough to not matter, and checking whether + // it implements the trait can have other nontrivial consequences, so it was decided to accept + // this. + Cat.into_future(); + //[e2021]~^ ERROR trait method `into_future` will become ambiguous in Rust 2024 + //[e2021]~| WARN this is accepted in the current edition (Rust 2021) but is a hard error in Rust 2024! +}