From 14be58acc903e4b6b7ec3cbff7756a18f5c06f99 Mon Sep 17 00:00:00 2001 From: David Rheinsberg Date: Mon, 24 Jul 2023 14:11:26 +0200 Subject: [PATCH 01/29] compiler: allow transmute of ZST arrays with generics Extend the `SizeSkeleton` evaluator to shortcut zero-sized arrays, thus considering `[T; 0]` to have a compile-time fixed-size of 0. The existing evaluator already deals with generic arrays under the feature-guard `transmute_const_generics`. However, it merely allows comparing fixed-size types with fixed-size types, and generic types with generic types. For generic types, it merely compares whether their arguments match (ordering them first). Even if their exact sizes are not known at compile time, it can ensure that they will eventually be the same. This patch extends this by shortcutting the size-evaluation of zero sized arrays and thus allowing size comparisons of `()` with `[T; 0]`, where one contains generics and the other does not. This code is guarded by `transmute_const_generics` (#109929), even though it is unclear whether it should be. However, this assumes that a separate stabilization PR is required to move this out of the feature guard. Initially reported in #98104. --- compiler/rustc_middle/src/ty/layout.rs | 7 ++++++- tests/ui/transmute/transmute-zst-generics.rs | 14 ++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/ui/transmute/transmute-zst-generics.rs diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 62805d1e8b5c..d981f52436e9 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -345,11 +345,16 @@ impl<'tcx> SizeSkeleton<'tcx> { ty::Array(inner, len) if len.ty() == tcx.types.usize && tcx.features().transmute_generic_consts => { + let len_eval = len.try_eval_target_usize(tcx, param_env); + if len_eval == Some(0) { + return Ok(SizeSkeleton::Known(Size::from_bytes(0))); + } + match SizeSkeleton::compute(inner, tcx, param_env)? { // This may succeed because the multiplication of two types may overflow // but a single size of a nested array will not. SizeSkeleton::Known(s) => { - if let Some(c) = len.try_eval_target_usize(tcx, param_env) { + if let Some(c) = len_eval { let size = s .bytes() .checked_mul(c) diff --git a/tests/ui/transmute/transmute-zst-generics.rs b/tests/ui/transmute/transmute-zst-generics.rs new file mode 100644 index 000000000000..469ad632d426 --- /dev/null +++ b/tests/ui/transmute/transmute-zst-generics.rs @@ -0,0 +1,14 @@ +// run-pass +// Transmuting to/from ZSTs that contain generics. + +#![feature(transmute_generic_consts)] + +unsafe fn cast_zst(from: ()) -> [T; 0] { + ::std::mem::transmute::<(), [T; 0]>(from) +} + +pub fn main() { + unsafe { + let _: [u32; 0] = cast_zst(()); + }; +} From 547f3cef6022980187da2744b3c6ed93368328bd Mon Sep 17 00:00:00 2001 From: Haydon Ryan Date: Mon, 11 Dec 2023 11:41:33 -0600 Subject: [PATCH 02/29] fixing error std::fs::read_to_string example documentation --- library/std/src/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 4310e1083038..ed630ef3dc7f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -283,11 +283,11 @@ pub fn read>(path: P) -> io::Result> { /// /// ```no_run /// use std::fs; -/// use std::net::SocketAddr; /// use std::error::Error; /// /// fn main() -> Result<(), Box> { -/// let foo: SocketAddr = fs::read_to_string("address.txt")?.parse()?; +/// let address: String = fs::read_to_string("address.txt")?; +/// println!("{}", address); /// Ok(()) /// } /// ``` From 6e9ca489f703f055d98bf7a513b2491dbec63983 Mon Sep 17 00:00:00 2001 From: Haydon Ryan Date: Mon, 11 Dec 2023 12:00:23 -0600 Subject: [PATCH 03/29] Updating fs::read example to remove SocketAddress --- library/std/src/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index ed630ef3dc7f..acc0f37a688a 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -242,10 +242,10 @@ pub struct DirBuilder { /// /// ```no_run /// use std::fs; -/// use std::net::SocketAddr; /// /// fn main() -> Result<(), Box> { -/// let foo: SocketAddr = String::from_utf8_lossy(&fs::read("address.txt")?).parse()?; +/// let address: String = String::from_utf8_lossy(&fs::read("address.txt")?).to_string(); +/// println!("{}", address); /// Ok(()) /// } /// ``` From a03d19ef63d342c408d7ec8208bda5b4eb0bacf5 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 14 Feb 2024 23:43:00 +0000 Subject: [PATCH 04/29] Allow targets to override default codegen backend --- compiler/rustc_driver_impl/src/lib.rs | 19 +++++- compiler/rustc_interface/src/interface.rs | 76 +++++++++++++++++++---- compiler/rustc_interface/src/tests.rs | 14 ++++- compiler/rustc_interface/src/util.rs | 47 +++++++------- compiler/rustc_session/src/config.rs | 2 +- compiler/rustc_session/src/session.rs | 9 +-- compiler/rustc_target/src/spec/mod.rs | 9 +++ 7 files changed, 130 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 60f11b1bdd49..bc485b052232 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -35,7 +35,7 @@ use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType}; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; -use rustc_session::{config, EarlyDiagCtxt, Session}; +use rustc_session::{config, filesearch, EarlyDiagCtxt, Session}; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::source_map::FileLoader; use rustc_span::symbol::sym; @@ -887,7 +887,13 @@ pub fn version_at_macro_invocation( let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); - get_codegen_backend(early_dcx, &None, backend_name).print_version(); + let opts = config::Options::default(); + let sysroot = opts.maybe_sysroot.clone().unwrap_or_else(|| { + filesearch::get_or_default_sysroot().expect("Failed finding sysroot") + }); + let target = config::build_target_config(early_dcx, &opts, None, &sysroot); + + get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_version(); } } @@ -1092,7 +1098,14 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) -> if cg_flags.iter().any(|x| *x == "passes=list") { let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); - get_codegen_backend(early_dcx, &None, backend_name).print_passes(); + + let opts = config::Options::default(); + let sysroot = opts.maybe_sysroot.clone().unwrap_or_else(|| { + filesearch::get_or_default_sysroot().expect("Failed finding sysroot") + }); + let target = config::build_target_config(early_dcx, &opts, None, &sysroot); + + get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_passes(); return true; } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 8a4705e0056e..f53b320f2e0f 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -16,7 +16,7 @@ use rustc_parse::maybe_new_parser_from_source_str; use rustc_query_impl::QueryCtxt; use rustc_query_system::query::print_query_stack; use rustc_session::config::{self, Cfg, CheckCfg, ExpectedValues, Input, OutFileName}; -use rustc_session::filesearch::sysroot_candidates; +use rustc_session::filesearch::{self, sysroot_candidates}; use rustc_session::parse::ParseSess; use rustc_session::{lint, CompilerIO, EarlyDiagCtxt, Session}; use rustc_span::source_map::FileLoader; @@ -336,14 +336,66 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let early_dcx = EarlyDiagCtxt::new(config.opts.error_format); - let codegen_backend = if let Some(make_codegen_backend) = config.make_codegen_backend { - make_codegen_backend(&config.opts) - } else { - util::get_codegen_backend( - &early_dcx, - &config.opts.maybe_sysroot, - config.opts.unstable_opts.codegen_backend.as_deref(), - ) + let sysroot = match &config.opts.maybe_sysroot { + Some(sysroot) => sysroot.clone(), + None => filesearch::get_or_default_sysroot().expect("Failed finding sysroot"), + }; + + let (codegen_backend, target_cfg) = match config.make_codegen_backend { + None => { + // Build a target without override, so that it can override the backend if needed + let target = + config::build_target_config(&early_dcx, &config.opts, None, &sysroot); + + let backend = util::get_codegen_backend( + &early_dcx, + &sysroot, + config.opts.unstable_opts.codegen_backend.as_deref(), + &target, + ); + + // target_override is documented to be called before init(), so this is okay + let target_override = backend.target_override(&config.opts); + + // Assert that we don't use target's override of the backend and + // backend's override of the target at the same time + if config.opts.unstable_opts.codegen_backend.is_none() + && target.default_codegen_backend.is_some() + && target_override.is_some() + { + rustc_middle::bug!( + "Codegen backend requested target override even though the target requested the backend" + ); + } + + // Re-build target with the (potential) override + let target = config::build_target_config( + &early_dcx, + &config.opts, + target_override, + &sysroot, + ); + + (backend, target) + } + Some(make_codegen_backend) => { + // N.B. `make_codegen_backend` takes precedence over `target.default_codegen_backend`, + // which is ignored in this case. + + let backend = make_codegen_backend(&config.opts); + + // target_override is documented to be called before init(), so this is okay + let target_override = backend.target_override(&config.opts); + + let target = config::build_target_config( + &early_dcx, + &config.opts, + target_override, + &sysroot, + ); + + (backend, target) + } }; let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); @@ -364,9 +416,6 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let mut locale_resources = Vec::from(config.locale_resources); locale_resources.push(codegen_backend.locale_resource()); - // target_override is documented to be called before init(), so this is okay - let target_override = codegen_backend.target_override(&config.opts); - let mut sess = rustc_session::build_session( early_dcx, config.opts, @@ -381,7 +430,8 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se locale_resources, config.lint_caps, config.file_loader, - target_override, + target_cfg, + sysroot, util::rustc_version_str().unwrap_or("unknown"), config.ice_file, config.using_internal_features, diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index bfc4fc07d4cc..b1d874d72046 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -37,6 +37,17 @@ fn mk_session(matches: getopts::Matches) -> (Session, Cfg) { output_file: None, temps_dir, }; + + let sysroot = match &sessopts.maybe_sysroot { + Some(sysroot) => sysroot.clone(), + None => { + rustc_session::filesearch::get_or_default_sysroot().expect("Failed finding sysroot") + } + }; + + let target_cfg = + rustc_session::config::build_target_config(&early_dcx, &sessopts, None, &sysroot); + let sess = build_session( early_dcx, sessopts, @@ -46,7 +57,8 @@ fn mk_session(matches: getopts::Matches) -> (Session, Cfg) { vec![], Default::default(), None, - None, + target_cfg, + sysroot, "", None, Arc::default(), diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 76b9e8de75fb..38c5157d4501 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -14,14 +14,15 @@ use rustc_session::{filesearch, output, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; use rustc_span::symbol::{sym, Symbol}; +use rustc_target::spec::Target; use session::EarlyDiagCtxt; -use std::env; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::mem; use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::OnceLock; use std::thread; +use std::{env, iter}; /// Function pointer type that constructs a new CodegenBackend. pub type MakeBackendFn = fn() -> Box; @@ -192,21 +193,25 @@ fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBacken /// A name of `None` indicates that the default backend should be used. pub fn get_codegen_backend( early_dcx: &EarlyDiagCtxt, - maybe_sysroot: &Option, + sysroot: &Path, backend_name: Option<&str>, + target: &Target, ) -> Box { static LOAD: OnceLock Box> = OnceLock::new(); let load = LOAD.get_or_init(|| { - let default_codegen_backend = option_env!("CFG_DEFAULT_CODEGEN_BACKEND").unwrap_or("llvm"); + let backend = backend_name + .or(target.default_codegen_backend.as_deref()) + .or(option_env!("CFG_DEFAULT_CODEGEN_BACKEND")) + .unwrap_or("llvm"); - match backend_name.unwrap_or(default_codegen_backend) { + match backend { filename if filename.contains('.') => { load_backend_from_dylib(early_dcx, filename.as_ref()) } #[cfg(feature = "llvm")] "llvm" => rustc_codegen_llvm::LlvmCodegenBackend::new, - backend_name => get_codegen_sysroot(early_dcx, maybe_sysroot, backend_name), + backend_name => get_codegen_sysroot(early_dcx, sysroot, backend_name), } }); @@ -240,7 +245,7 @@ fn get_rustc_path_inner(bin_path: &str) -> Option { fn get_codegen_sysroot( early_dcx: &EarlyDiagCtxt, - maybe_sysroot: &Option, + sysroot: &Path, backend_name: &str, ) -> MakeBackendFn { // For now we only allow this function to be called once as it'll dlopen a @@ -257,28 +262,28 @@ fn get_codegen_sysroot( let target = session::config::host_triple(); let sysroot_candidates = sysroot_candidates(); - let sysroot = maybe_sysroot - .iter() - .chain(sysroot_candidates.iter()) + let sysroot = iter::once(sysroot) + .chain(sysroot_candidates.iter().map(<_>::as_ref)) .map(|sysroot| { filesearch::make_target_lib_path(sysroot, target).with_file_name("codegen-backends") }) .find(|f| { info!("codegen backend candidate: {}", f.display()); f.exists() - }); - let sysroot = sysroot.unwrap_or_else(|| { - let candidates = sysroot_candidates - .iter() - .map(|p| p.display().to_string()) - .collect::>() - .join("\n* "); - let err = format!( - "failed to find a `codegen-backends` folder \ + }) + .unwrap_or_else(|| { + let candidates = sysroot_candidates + .iter() + .map(|p| p.display().to_string()) + .collect::>() + .join("\n* "); + let err = format!( + "failed to find a `codegen-backends` folder \ in the sysroot candidates:\n* {candidates}" - ); - early_dcx.early_fatal(err); - }); + ); + early_dcx.early_fatal(err); + }); + info!("probing {} for a codegen backend", sysroot.display()); let d = sysroot.read_dir().unwrap_or_else(|e| { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index d35f951e2aea..63bc902c813f 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1558,7 +1558,7 @@ pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg { user_cfg } -pub(super) fn build_target_config( +pub fn build_target_config( early_dcx: &EarlyDiagCtxt, opts: &Options, target_override: Option, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 25c20be8e627..2a8b507a227b 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1034,7 +1034,8 @@ pub fn build_session( fluent_resources: Vec<&'static str>, driver_lint_caps: FxHashMap, file_loader: Option>, - target_override: Option, + target_cfg: Target, + sysroot: PathBuf, cfg_version: &'static str, ice_file: Option, using_internal_features: Arc, @@ -1051,12 +1052,6 @@ pub fn build_session( let cap_lints_allow = sopts.lint_cap.is_some_and(|cap| cap == lint::Allow); let can_emit_warnings = !(warnings_allow || cap_lints_allow); - let sysroot = match &sopts.maybe_sysroot { - Some(sysroot) => sysroot.clone(), - None => filesearch::get_or_default_sysroot().expect("Failed finding sysroot"), - }; - - let target_cfg = config::build_target_config(&early_dcx, &sopts, target_override, &sysroot); let host_triple = TargetTriple::from_triple(config::host_triple()); let (host, target_warnings) = Target::search(&host_triple, &sysroot).unwrap_or_else(|e| { early_dcx.early_fatal(format!("Error loading host specification: {e}")) diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index d04bcb2d78aa..ec48930b20b9 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -2044,6 +2044,14 @@ pub struct TargetOptions { /// Default number of codegen units to use in debug mode pub default_codegen_units: Option, + /// Default codegen backend used for this target. Defaults to `None`. + /// + /// If `None`, then `CFG_DEFAULT_CODEGEN_BACKEND` environmental variable captured when + /// compiling `rustc` will be used instead (or llvm if it is not set). + /// + /// N.B. when *using* the compiler, backend can always be overriden with `-Zcodegen-backend`. + pub default_codegen_backend: Option>, + /// Whether to generate trap instructions in places where optimization would /// otherwise produce control flow that falls through into unrelated memory. pub trap_unreachable: bool, @@ -2350,6 +2358,7 @@ impl Default for TargetOptions { stack_probes: StackProbeType::None, min_global_align: None, default_codegen_units: None, + default_codegen_backend: None, trap_unreachable: true, requires_lto: false, singlethread: false, From 5441523f0727639040fdd134abff1e298d88733e Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Thu, 15 Feb 2024 00:03:34 +0000 Subject: [PATCH 05/29] Refactor out a repeating pattern with `get_or_default_sysroot` --- compiler/rustc_driver_impl/src/lib.rs | 8 ++------ compiler/rustc_interface/src/interface.rs | 5 +---- compiler/rustc_interface/src/tests.rs | 9 ++------- compiler/rustc_session/src/config.rs | 16 ++++------------ compiler/rustc_session/src/filesearch.rs | 6 ++++++ 5 files changed, 15 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index bc485b052232..0920505d86e3 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -888,9 +888,7 @@ pub fn version_at_macro_invocation( let debug_flags = matches.opt_strs("Z"); let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); let opts = config::Options::default(); - let sysroot = opts.maybe_sysroot.clone().unwrap_or_else(|| { - filesearch::get_or_default_sysroot().expect("Failed finding sysroot") - }); + let sysroot = filesearch::materialize_sysroot(opts.maybe_sysroot.clone()); let target = config::build_target_config(early_dcx, &opts, None, &sysroot); get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_version(); @@ -1100,9 +1098,7 @@ pub fn describe_flag_categories(early_dcx: &EarlyDiagCtxt, matches: &Matches) -> let backend_name = debug_flags.iter().find_map(|x| x.strip_prefix("codegen-backend=")); let opts = config::Options::default(); - let sysroot = opts.maybe_sysroot.clone().unwrap_or_else(|| { - filesearch::get_or_default_sysroot().expect("Failed finding sysroot") - }); + let sysroot = filesearch::materialize_sysroot(opts.maybe_sysroot.clone()); let target = config::build_target_config(early_dcx, &opts, None, &sysroot); get_codegen_backend(early_dcx, &sysroot, backend_name, &target).print_passes(); diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index f53b320f2e0f..a45762b2ce77 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -336,10 +336,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let early_dcx = EarlyDiagCtxt::new(config.opts.error_format); - let sysroot = match &config.opts.maybe_sysroot { - Some(sysroot) => sysroot.clone(), - None => filesearch::get_or_default_sysroot().expect("Failed finding sysroot"), - }; + let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone()); let (codegen_backend, target_cfg) = match config.make_codegen_backend { None => { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index b1d874d72046..0651950b967b 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -13,7 +13,7 @@ use rustc_session::config::{ use rustc_session::lint::Level; use rustc_session::search_paths::SearchPath; use rustc_session::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; -use rustc_session::{build_session, getopts, CompilerIO, EarlyDiagCtxt, Session}; +use rustc_session::{build_session, filesearch, getopts, CompilerIO, EarlyDiagCtxt, Session}; use rustc_span::edition::{Edition, DEFAULT_EDITION}; use rustc_span::symbol::sym; use rustc_span::{FileName, SourceFileHashAlgorithm}; @@ -38,12 +38,7 @@ fn mk_session(matches: getopts::Matches) -> (Session, Cfg) { temps_dir, }; - let sysroot = match &sessopts.maybe_sysroot { - Some(sysroot) => sysroot.clone(), - None => { - rustc_session::filesearch::get_or_default_sysroot().expect("Failed finding sysroot") - } - }; + let sysroot = filesearch::materialize_sysroot(sessopts.maybe_sysroot.clone()); let target_cfg = rustc_session::config::build_target_config(&early_dcx, &sessopts, None, &sysroot); diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 63bc902c813f..2ad959d38329 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -6,7 +6,7 @@ pub use crate::options::*; use crate::errors::FileWriteFail; use crate::search_paths::SearchPath; use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind}; -use crate::{lint, HashStableContext}; +use crate::{filesearch, lint, HashStableContext}; use crate::{EarlyDiagCtxt, Session}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey}; @@ -2856,16 +2856,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M let logical_env = parse_logical_env(early_dcx, matches); - // Try to find a directory containing the Rust `src`, for more details see - // the doc comment on the `real_rust_source_base_dir` field. - let tmp_buf; - let sysroot = match &sysroot_opt { - Some(s) => s, - None => { - tmp_buf = crate::filesearch::get_or_default_sysroot().expect("Failed finding sysroot"); - &tmp_buf - } - }; + let sysroot = filesearch::materialize_sysroot(sysroot_opt); + let real_rust_source_base_dir = { // This is the location used by the `rust-src` `rustup` component. let mut candidate = sysroot.join("lib/rustlib/src/rust"); @@ -2909,7 +2901,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M describe_lints, output_types, search_paths, - maybe_sysroot: sysroot_opt, + maybe_sysroot: Some(sysroot), target_triple, test, incremental, diff --git a/compiler/rustc_session/src/filesearch.rs b/compiler/rustc_session/src/filesearch.rs index 6e459ac45d35..668acc0f7615 100644 --- a/compiler/rustc_session/src/filesearch.rs +++ b/compiler/rustc_session/src/filesearch.rs @@ -194,6 +194,12 @@ pub fn sysroot_candidates() -> SmallVec<[PathBuf; 2]> { return sysroot_candidates; } +/// Returns the provided sysroot or calls [`get_or_default_sysroot`] if it's none. +/// Panics if [`get_or_default_sysroot`] returns an error. +pub fn materialize_sysroot(maybe_sysroot: Option) -> PathBuf { + maybe_sysroot.unwrap_or_else(|| get_or_default_sysroot().expect("Failed finding sysroot")) +} + /// This function checks if sysroot is found using env::args().next(), and if it /// is not found, finds sysroot from current rustc_driver dll. pub fn get_or_default_sysroot() -> Result { From 9539feb2f73b1e9370e28a6dcdaf0fe51bc65465 Mon Sep 17 00:00:00 2001 From: Haydon Ryan Date: Thu, 15 Feb 2024 08:20:15 -0600 Subject: [PATCH 06/29] Update library/std/src/fs.rs Co-authored-by: Mara Bos --- library/std/src/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index acc0f37a688a..29b61a8d1d0b 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -286,8 +286,8 @@ pub fn read>(path: P) -> io::Result> { /// use std::error::Error; /// /// fn main() -> Result<(), Box> { -/// let address: String = fs::read_to_string("address.txt")?; -/// println!("{}", address); +/// let message: String = fs::read_to_string("message.txt")?; +/// println!("{}", message); /// Ok(()) /// } /// ``` From b5e1ca39180e9997efef14d3b7d06a3ddff72b59 Mon Sep 17 00:00:00 2001 From: Haydon Ryan Date: Thu, 15 Feb 2024 08:20:45 -0600 Subject: [PATCH 07/29] Update library/std/src/fs.rs Co-authored-by: Mara Bos --- library/std/src/fs.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 29b61a8d1d0b..5bcd92b63df9 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -244,8 +244,8 @@ pub struct DirBuilder { /// use std::fs; /// /// fn main() -> Result<(), Box> { -/// let address: String = String::from_utf8_lossy(&fs::read("address.txt")?).to_string(); -/// println!("{}", address); +/// let data: Vec = fs::read("image.jpg")?; +/// assert_eq!(data[0..3], [0xFF, 0xD8, 0xFF]); /// Ok(()) /// } /// ``` From 6d115f5d9a05380b983dd53d747150c8afbd48d8 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Sun, 18 Feb 2024 19:26:45 +0000 Subject: [PATCH 08/29] Refactor out another repeating pattern --- compiler/rustc_interface/src/interface.rs | 26 ++++++----------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index a45762b2ce77..9783327efd3d 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -338,7 +338,7 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se let sysroot = filesearch::materialize_sysroot(config.opts.maybe_sysroot.clone()); - let (codegen_backend, target_cfg) = match config.make_codegen_backend { + let (codegen_backend, target_override) = match config.make_codegen_backend { None => { // Build a target without override, so that it can override the backend if needed let target = @@ -365,36 +365,24 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se ); } - // Re-build target with the (potential) override - let target = config::build_target_config( - &early_dcx, - &config.opts, - target_override, - &sysroot, - ); - - (backend, target) + (backend, target_override) } Some(make_codegen_backend) => { // N.B. `make_codegen_backend` takes precedence over `target.default_codegen_backend`, // which is ignored in this case. - let backend = make_codegen_backend(&config.opts); // target_override is documented to be called before init(), so this is okay let target_override = backend.target_override(&config.opts); - let target = config::build_target_config( - &early_dcx, - &config.opts, - target_override, - &sysroot, - ); - - (backend, target) + (backend, target_override) } }; + // Re-build target with the (potential) override + let target_cfg = + config::build_target_config(&early_dcx, &config.opts, target_override, &sysroot); + let temps_dir = config.opts.unstable_opts.temps_dir.as_deref().map(PathBuf::from); let bundle = match rustc_errors::fluent_bundle( From f27a22c24a51ba734e4eb25c499320d819ebe236 Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 30 Jan 2024 15:58:08 +0000 Subject: [PATCH 09/29] try_with_capacity for RawVec --- library/alloc/src/raw_vec.rs | 36 +++++++++++++++++------------- library/alloc/src/raw_vec/tests.rs | 7 +++--- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index dd8d6f6c7e63..2d86fa377f16 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -17,7 +17,6 @@ use crate::collections::TryReserveErrorKind::*; #[cfg(test)] mod tests; -#[cfg(not(no_global_oom_handling))] enum AllocInit { /// The contents of the new memory are uninitialized. Uninitialized, @@ -93,6 +92,8 @@ impl RawVec { /// zero-sized. Note that if `T` is zero-sized this means you will /// *not* get a `RawVec` with the requested capacity. /// + /// Non-fallible version of `try_with_capacity` + /// /// # Panics /// /// Panics if the requested capacity exceeds `isize::MAX` bytes. @@ -104,7 +105,7 @@ impl RawVec { #[must_use] #[inline] pub fn with_capacity(capacity: usize) -> Self { - Self::with_capacity_in(capacity, Global) + handle_reserve(Self::try_allocate_in(capacity, AllocInit::Uninitialized, Global)) } /// Like `with_capacity`, but guarantees the buffer is zeroed. @@ -142,7 +143,7 @@ impl RawVec { #[cfg(not(no_global_oom_handling))] #[inline] pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { - Self::allocate_in(capacity, AllocInit::Uninitialized, alloc) + handle_reserve(Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc)) } /// Like `with_capacity_zeroed`, but parameterized over the choice @@ -150,7 +151,7 @@ impl RawVec { #[cfg(not(no_global_oom_handling))] #[inline] pub fn with_capacity_zeroed_in(capacity: usize, alloc: A) -> Self { - Self::allocate_in(capacity, AllocInit::Zeroed, alloc) + handle_reserve(Self::try_allocate_in(capacity, AllocInit::Zeroed, alloc)) } /// Converts the entire buffer into `Box<[MaybeUninit]>` with the specified `len`. @@ -179,35 +180,40 @@ impl RawVec { } } - #[cfg(not(no_global_oom_handling))] - fn allocate_in(capacity: usize, init: AllocInit, alloc: A) -> Self { + fn try_allocate_in( + capacity: usize, + init: AllocInit, + alloc: A, + ) -> Result { // Don't allocate here because `Drop` will not deallocate when `capacity` is 0. + if T::IS_ZST || capacity == 0 { - Self::new_in(alloc) + Ok(Self::new_in(alloc)) } else { // We avoid `unwrap_or_else` here because it bloats the amount of // LLVM IR generated. let layout = match Layout::array::(capacity) { Ok(layout) => layout, - Err(_) => capacity_overflow(), + Err(_) => return Err(CapacityOverflow.into()), }; - match alloc_guard(layout.size()) { - Ok(_) => {} - Err(_) => capacity_overflow(), + + if let Err(err) = alloc_guard(layout.size()) { + return Err(err); } + let result = match init { AllocInit::Uninitialized => alloc.allocate(layout), AllocInit::Zeroed => alloc.allocate_zeroed(layout), }; let ptr = match result { Ok(ptr) => ptr, - Err(_) => handle_alloc_error(layout), + Err(_) => return Err(AllocError { layout, non_exhaustive: () }.into()), }; // Allocators currently return a `NonNull<[u8]>` whose length // matches the size requested. If that ever changes, the capacity // here should change to `ptr.len() / mem::size_of::()`. - Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc } + Ok(Self { ptr: Unique::from(ptr.cast()), cap: unsafe { Cap(capacity) }, alloc }) } } @@ -537,11 +543,11 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for RawVec { // Central function for reserve error handling. #[cfg(not(no_global_oom_handling))] #[inline] -fn handle_reserve(result: Result<(), TryReserveError>) { +fn handle_reserve(result: Result) -> T { match result.map_err(|e| e.kind()) { + Ok(res) => res, Err(CapacityOverflow) => capacity_overflow(), Err(AllocError { layout, .. }) => handle_alloc_error(layout), - Ok(()) => { /* yay */ } } } diff --git a/library/alloc/src/raw_vec/tests.rs b/library/alloc/src/raw_vec/tests.rs index f8cada01c030..4194be530612 100644 --- a/library/alloc/src/raw_vec/tests.rs +++ b/library/alloc/src/raw_vec/tests.rs @@ -105,13 +105,14 @@ fn zst() { let v: RawVec = RawVec::with_capacity_in(100, Global); zst_sanity(&v); - let v: RawVec = RawVec::allocate_in(0, AllocInit::Uninitialized, Global); + let v: RawVec = RawVec::try_allocate_in(0, AllocInit::Uninitialized, Global).unwrap(); zst_sanity(&v); - let v: RawVec = RawVec::allocate_in(100, AllocInit::Uninitialized, Global); + let v: RawVec = RawVec::try_allocate_in(100, AllocInit::Uninitialized, Global).unwrap(); zst_sanity(&v); - let mut v: RawVec = RawVec::allocate_in(usize::MAX, AllocInit::Uninitialized, Global); + let mut v: RawVec = + RawVec::try_allocate_in(usize::MAX, AllocInit::Uninitialized, Global).unwrap(); zst_sanity(&v); // Check all these operations work as expected with zero-sized elements. From 78fb977d6b600865b7887245d24f6dca22a0099a Mon Sep 17 00:00:00 2001 From: Kornel Date: Tue, 30 Jan 2024 16:08:57 +0000 Subject: [PATCH 10/29] try_with_capacity for Vec, VecDeque, String #91913 --- .../alloc/src/collections/vec_deque/mod.rs | 24 +++++++++++++ library/alloc/src/lib.rs | 1 + library/alloc/src/raw_vec.rs | 9 +++++ library/alloc/src/string.rs | 13 +++++++ library/alloc/src/vec/mod.rs | 34 ++++++++++++++++++ library/alloc/tests/lib.rs | 1 + library/alloc/tests/string.rs | 11 ++++++ library/alloc/tests/vec.rs | 12 +++++++ library/alloc/tests/vec_deque.rs | 11 ++++++ tests/codegen/vec-with-capacity.rs | 35 +++++++++++++++++++ tests/ui/suggestions/deref-path-method.stderr | 4 +-- tests/ui/ufcs/bad-builder.stderr | 4 +-- 12 files changed, 155 insertions(+), 4 deletions(-) create mode 100644 tests/codegen/vec-with-capacity.rs diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index c35bab5ef665..41adc2e79dc7 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -559,6 +559,30 @@ impl VecDeque { pub fn with_capacity(capacity: usize) -> VecDeque { Self::with_capacity_in(capacity, Global) } + + /// Creates an empty deque with space for at least `capacity` elements. + /// + /// # Errors + /// + /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, + /// or if the allocator reports allocation failure. + /// + /// # Examples + /// + /// ``` + /// # #![feature(try_with_capacity)] + /// # #[allow(unused)] + /// # fn example() -> Result<(), std::collections::TryReserveError> { + /// use std::collections::VecDeque; + /// + /// let deque: VecDeque = VecDeque::try_with_capacity(10)?; + /// # Ok(()) } + /// ``` + #[inline] + #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity(capacity: usize) -> Result, TryReserveError> { + Ok(VecDeque { head: 0, len: 0, buf: RawVec::try_with_capacity_in(capacity, Global)? }) + } } impl VecDeque { diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 28695ade5bf5..ca504b05a968 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -163,6 +163,7 @@ #![feature(trusted_len)] #![feature(trusted_random_access)] #![feature(try_trait_v2)] +#![feature(try_with_capacity)] #![feature(tuple_trait)] #![feature(unchecked_math)] #![feature(unicode_internals)] diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index 2d86fa377f16..c5cf12209d90 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -20,6 +20,7 @@ mod tests; enum AllocInit { /// The contents of the new memory are uninitialized. Uninitialized, + #[cfg(not(no_global_oom_handling))] /// The new memory is guaranteed to be zeroed. Zeroed, } @@ -146,6 +147,13 @@ impl RawVec { handle_reserve(Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc)) } + /// Like `try_with_capacity`, but parameterized over the choice of + /// allocator for the returned `RawVec`. + #[inline] + pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result { + Self::try_allocate_in(capacity, AllocInit::Uninitialized, alloc) + } + /// Like `with_capacity_zeroed`, but parameterized over the choice /// of allocator for the returned `RawVec`. #[cfg(not(no_global_oom_handling))] @@ -203,6 +211,7 @@ impl RawVec { let result = match init { AllocInit::Uninitialized => alloc.allocate(layout), + #[cfg(not(no_global_oom_handling))] AllocInit::Zeroed => alloc.allocate_zeroed(layout), }; let ptr = match result { diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index 98ded7f6cdf5..c4dcff1b1c49 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -492,6 +492,19 @@ impl String { String { vec: Vec::with_capacity(capacity) } } + /// Creates a new empty `String` with at least the specified capacity. + /// + /// # Errors + /// + /// Returns [`Err`] if the capacity exceeds `isize::MAX` bytes, + /// or if the memory allocator reports failure. + /// + #[inline] + #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity(capacity: usize) -> Result { + Ok(String { vec: Vec::try_with_capacity(capacity)? }) + } + // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is // required for this method definition, is not available. Since we don't // require this method for testing purposes, I'll just stub it diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 7bd19875584a..4b8b095c752f 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -481,6 +481,22 @@ impl Vec { Self::with_capacity_in(capacity, Global) } + /// Constructs a new, empty `Vec` with at least the specified capacity. + /// + /// The vector will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// + /// # Errors + /// + /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, + /// or if the allocator reports allocation failure. + #[inline] + #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity(capacity: usize) -> Result { + Self::try_with_capacity_in(capacity, Global) + } + /// Creates a `Vec` directly from a pointer, a length, and a capacity. /// /// # Safety @@ -672,6 +688,24 @@ impl Vec { Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } } + /// Constructs a new, empty `Vec` with at least the specified capacity + /// with the provided allocator. + /// + /// The vector will be able to hold at least `capacity` elements without + /// reallocating. This method is allowed to allocate for more elements than + /// `capacity`. If `capacity` is 0, the vector will not allocate. + /// + /// # Errors + /// + /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, + /// or if the allocator reports allocation failure. + #[inline] + #[unstable(feature = "allocator_api", issue = "32838")] + // #[unstable(feature = "try_with_capacity", issue = "91913")] + pub fn try_with_capacity_in(capacity: usize, alloc: A) -> Result { + Ok(Vec { buf: RawVec::try_with_capacity_in(capacity, alloc)?, len: 0 }) + } + /// Creates a `Vec` directly from a pointer, a length, a capacity, /// and an allocator. /// diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs index c4e89a58a05a..e4e1a02fd832 100644 --- a/library/alloc/tests/lib.rs +++ b/library/alloc/tests/lib.rs @@ -20,6 +20,7 @@ #![feature(pattern)] #![feature(trusted_len)] #![feature(try_reserve_kind)] +#![feature(try_with_capacity)] #![feature(unboxed_closures)] #![feature(associated_type_bounds)] #![feature(binary_heap_into_iter_sorted)] diff --git a/library/alloc/tests/string.rs b/library/alloc/tests/string.rs index 711e4eef2e72..e20ceae87b0d 100644 --- a/library/alloc/tests/string.rs +++ b/library/alloc/tests/string.rs @@ -723,6 +723,17 @@ fn test_reserve_exact() { assert!(s.capacity() >= 33) } +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_with_capacity() { + let string = String::try_with_capacity(1000).unwrap(); + assert_eq!(0, string.len()); + assert!(string.capacity() >= 1000 && string.capacity() <= isize::MAX as usize); + + assert!(String::try_with_capacity(usize::MAX).is_err()); +} + #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs index 15ee4d652052..aa95b4e97708 100644 --- a/library/alloc/tests/vec.rs +++ b/library/alloc/tests/vec.rs @@ -1694,6 +1694,18 @@ fn test_reserve_exact() { assert!(v.capacity() >= 33) } +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_with_capacity() { + let mut vec: Vec = Vec::try_with_capacity(5).unwrap(); + assert_eq!(0, vec.len()); + assert!(vec.capacity() >= 5 && vec.capacity() <= isize::MAX as usize / 4); + assert!(vec.spare_capacity_mut().len() >= 5); + + assert!(Vec::::try_with_capacity(isize::MAX as usize + 1).is_err()); +} + #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc diff --git a/library/alloc/tests/vec_deque.rs b/library/alloc/tests/vec_deque.rs index eda2f8bb812b..cea5de4dd598 100644 --- a/library/alloc/tests/vec_deque.rs +++ b/library/alloc/tests/vec_deque.rs @@ -1182,6 +1182,17 @@ fn test_reserve_exact_2() { assert!(v.capacity() >= 33) } +#[test] +#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM +#[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc +fn test_try_with_capacity() { + let vec: VecDeque = VecDeque::try_with_capacity(5).unwrap(); + assert_eq!(0, vec.len()); + assert!(vec.capacity() >= 5 && vec.capacity() <= isize::MAX as usize / 4); + + assert!(VecDeque::::try_with_capacity(isize::MAX as usize + 1).is_err()); +} + #[test] #[cfg_attr(miri, ignore)] // Miri does not support signalling OOM #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc diff --git a/tests/codegen/vec-with-capacity.rs b/tests/codegen/vec-with-capacity.rs new file mode 100644 index 000000000000..47051f2eef89 --- /dev/null +++ b/tests/codegen/vec-with-capacity.rs @@ -0,0 +1,35 @@ +//@ compile-flags: -O +//@ ignore-debug +// (with debug assertions turned on, `assert_unchecked` generates a real assertion) + +#![crate_type = "lib"] +#![feature(try_with_capacity)] + +// CHECK-LABEL: @with_capacity_does_not_grow1 +#[no_mangle] +pub fn with_capacity_does_not_grow1() -> Vec { + let v = Vec::with_capacity(1234); + // CHECK: call {{.*}}__rust_alloc( + // CHECK-NOT: call {{.*}}__rust_realloc + // CHECK-NOT: call {{.*}}capacity_overflow + // CHECK-NOT: call {{.*}}finish_grow + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: memcpy + // CHECK-NOT: memset + v +} + +// CHECK-LABEL: @try_with_capacity_does_not_grow2 +#[no_mangle] +pub fn try_with_capacity_does_not_grow2() -> Option>> { + let v = Vec::try_with_capacity(1234).ok()?; + // CHECK: call {{.*}}__rust_alloc( + // CHECK-NOT: call {{.*}}__rust_realloc + // CHECK-NOT: call {{.*}}capacity_overflow + // CHECK-NOT: call {{.*}}finish_grow + // CHECK-NOT: call {{.*}}handle_alloc_error + // CHECK-NOT: call {{.*}}reserve + // CHECK-NOT: memcpy + // CHECK-NOT: memset + Some(v) +} diff --git a/tests/ui/suggestions/deref-path-method.stderr b/tests/ui/suggestions/deref-path-method.stderr index a2b68fa966fc..b27d9aef0661 100644 --- a/tests/ui/suggestions/deref-path-method.stderr +++ b/tests/ui/suggestions/deref-path-method.stderr @@ -7,9 +7,9 @@ LL | Vec::contains(&vec, &0); note: if you're trying to build a new `Vec<_, _>` consider using one of the following associated functions: Vec::::new Vec::::with_capacity + Vec::::try_with_capacity Vec::::from_raw_parts - Vec::::new_in - and 2 others + and 4 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: the function `contains` is implemented on `[_]` | diff --git a/tests/ui/ufcs/bad-builder.stderr b/tests/ui/ufcs/bad-builder.stderr index e1c5e45b3ebb..9cfeb7a5d09d 100644 --- a/tests/ui/ufcs/bad-builder.stderr +++ b/tests/ui/ufcs/bad-builder.stderr @@ -7,9 +7,9 @@ LL | Vec::::mew() note: if you're trying to build a new `Vec` consider using one of the following associated functions: Vec::::new Vec::::with_capacity + Vec::::try_with_capacity Vec::::from_raw_parts - Vec::::new_in - and 2 others + and 4 others --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL help: there is an associated function `new` with a similar name | From 784e6a1e080e5ba18e5c246e744e2d20525d1c3d Mon Sep 17 00:00:00 2001 From: Kornel Date: Wed, 31 Jan 2024 15:23:52 +0000 Subject: [PATCH 11/29] Move capacity_overflow function to make ui tests change less Code changes in raw_vec require blessing UI tests every time --- library/alloc/src/raw_vec.rs | 18 +++++++++--------- tests/ui/hygiene/panic-location.run.stderr | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index c5cf12209d90..5e37de18c954 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -17,6 +17,15 @@ use crate::collections::TryReserveErrorKind::*; #[cfg(test)] mod tests; +// One central function responsible for reporting capacity overflows. This'll +// ensure that the code generation related to these panics is minimal as there's +// only one location which panics rather than a bunch throughout the module. +#[cfg(not(no_global_oom_handling))] +#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] +fn capacity_overflow() -> ! { + panic!("capacity overflow"); +} + enum AllocInit { /// The contents of the new memory are uninitialized. Uninitialized, @@ -576,12 +585,3 @@ fn alloc_guard(alloc_size: usize) -> Result<(), TryReserveError> { Ok(()) } } - -// One central function responsible for reporting capacity overflows. This'll -// ensure that the code generation related to these panics is minimal as there's -// only one location which panics rather than a bunch throughout the module. -#[cfg(not(no_global_oom_handling))] -#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never))] -fn capacity_overflow() -> ! { - panic!("capacity overflow"); -} diff --git a/tests/ui/hygiene/panic-location.run.stderr b/tests/ui/hygiene/panic-location.run.stderr index 5c552411da7f..ec0ce18c3dfa 100644 --- a/tests/ui/hygiene/panic-location.run.stderr +++ b/tests/ui/hygiene/panic-location.run.stderr @@ -1,3 +1,3 @@ -thread 'main' panicked at library/alloc/src/raw_vec.rs:571:5: +thread 'main' panicked at library/alloc/src/raw_vec.rs:26:5: capacity overflow note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace From 2149c45e03bc8c89cd74e859e23abc3dd9fad2c1 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 14 Feb 2024 14:49:16 +0000 Subject: [PATCH 12/29] Bubble up the TyCtxtFeed --- compiler/rustc_resolve/src/def_collector.rs | 18 ++++++++++-------- compiler/rustc_resolve/src/lib.rs | 9 +++++---- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 12bf462a6fdf..bb3b902c0de6 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -38,14 +38,16 @@ impl<'a, 'b, 'tcx> DefCollector<'a, 'b, 'tcx> { "create_def(node_id={:?}, def_kind={:?}, parent_def={:?})", node_id, def_kind, parent_def ); - self.resolver.create_def( - parent_def, - node_id, - name, - def_kind, - self.expansion.to_expn_id(), - span.with_parent(None), - ) + self.resolver + .create_def( + parent_def, + node_id, + name, + def_kind, + self.expansion.to_expn_id(), + span.with_parent(None), + ) + .def_id() } fn with_parent(&mut self, parent_def: LocalDefId, f: F) { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 0434ff171934..c234d9acdf42 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -52,7 +52,7 @@ use rustc_middle::metadata::ModChild; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::query::Providers; use rustc_middle::span_bug; -use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt}; +use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt, TyCtxtFeed}; use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; @@ -1251,7 +1251,7 @@ impl<'tcx> Resolver<'_, 'tcx> { def_kind: DefKind, expn_id: ExpnId, span: Span, - ) -> LocalDefId { + ) -> TyCtxtFeed<'tcx, LocalDefId> { let data = def_kind.def_path_data(name); assert!( !self.node_id_to_def_id.contains_key(&node_id), @@ -1262,7 +1262,8 @@ impl<'tcx> Resolver<'_, 'tcx> { ); // FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()` - let def_id = self.tcx.create_def(parent, name, def_kind).def_id(); + let feed = self.tcx.create_def(parent, name, def_kind); + let def_id = feed.def_id(); // Create the definition. if expn_id != ExpnId::root() { @@ -1283,7 +1284,7 @@ impl<'tcx> Resolver<'_, 'tcx> { } assert_eq!(self.def_id_to_node_id.push(node_id), def_id); - def_id + feed } fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize { From 31d0a644be5c1b5bf73625fb363e53d7519bd84f Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 14 Feb 2024 15:13:09 +0000 Subject: [PATCH 13/29] Keep `TyCtxtFeed` around longer in the resolver --- compiler/rustc_middle/src/ty/context.rs | 35 +++++++++++++++++++++++++ compiler/rustc_middle/src/ty/mod.rs | 3 ++- 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b2a7f5599b64..760392e83378 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -74,6 +74,7 @@ use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; use std::iter; +use std::marker::PhantomData; use std::mem; use std::ops::{Bound, Deref}; @@ -519,6 +520,23 @@ pub struct TyCtxtFeed<'tcx, KEY: Copy> { key: KEY, } +/// The same as `TyCtxtFeed`, but does not contain a `TyCtxt`. +/// Use this to pass around when you have a `TyCtxt` elsewhere. +/// Just an optimization to save space and not store hundreds of +/// `TyCtxtFeed` in the resolver. +#[derive(Copy, Clone)] +pub struct Feed<'tcx, KEY: Copy> { + _tcx: PhantomData>, + // Do not allow direct access, as downstream code must not mutate this field. + key: KEY, +} + +impl fmt::Debug for Feed<'_, T> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.key.fmt(f) + } +} + impl<'tcx> TyCtxt<'tcx> { pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> { TyCtxtFeed { tcx: self, key: () } @@ -544,6 +562,23 @@ impl<'tcx, KEY: Copy> TyCtxtFeed<'tcx, KEY> { pub fn key(&self) -> KEY { self.key } + + #[inline(always)] + pub fn downgrade(self) -> Feed<'tcx, KEY> { + Feed { _tcx: PhantomData, key: self.key } + } +} + +impl<'tcx, KEY: Copy> Feed<'tcx, KEY> { + #[inline(always)] + pub fn key(&self) -> KEY { + self.key + } + + #[inline(always)] + pub fn upgrade(self, tcx: TyCtxt<'tcx>) -> TyCtxtFeed<'tcx, KEY> { + TyCtxtFeed { tcx, key: self.key } + } } impl<'tcx> TyCtxtFeed<'tcx, LocalDefId> { diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index f005a2405044..77444b74ccdb 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -85,7 +85,8 @@ pub use self::consts::{ Const, ConstData, ConstInt, ConstKind, Expr, ScalarInt, UnevaluatedConst, ValTree, }; pub use self::context::{ - tls, CtxtInterners, DeducedParamAttrs, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, TyCtxtFeed, + tls, CtxtInterners, DeducedParamAttrs, Feed, FreeRegionInfo, GlobalCtxt, Lift, TyCtxt, + TyCtxtFeed, }; pub use self::instance::{Instance, InstanceDef, ShortInstance, UnusedGenericParams}; pub use self::list::List; From 3b9dfd3f09270a439ac9a7a3081eadacacb2674b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 14 Feb 2024 15:21:04 +0000 Subject: [PATCH 14/29] Preserve the `Feed` in local tables --- compiler/rustc_resolve/src/lib.rs | 32 ++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index c234d9acdf42..241749762e3c 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -53,7 +53,7 @@ use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt, TyCtxtFeed}; -use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs}; +use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, Feed}; use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; use rustc_session::lint::LintBuffer; @@ -1115,7 +1115,7 @@ pub struct Resolver<'a, 'tcx> { next_node_id: NodeId, - node_id_to_def_id: NodeMap, + node_id_to_def_id: NodeMap>, def_id_to_node_id: IndexVec, /// Indices of unnamed struct or variant fields with unresolved attributes. @@ -1231,11 +1231,19 @@ impl<'a, 'tcx> AsMut> for Resolver<'a, 'tcx> { impl<'tcx> Resolver<'_, 'tcx> { fn opt_local_def_id(&self, node: NodeId) -> Option { - self.node_id_to_def_id.get(&node).copied() + self.opt_feed(node).map(|f| f.key()) } fn local_def_id(&self, node: NodeId) -> LocalDefId { - self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) + self.feed(node).key() + } + + fn opt_feed(&self, node: NodeId) -> Option> { + self.node_id_to_def_id.get(&node).copied() + } + + fn feed(&self, node: NodeId) -> Feed<'tcx, LocalDefId> { + self.opt_feed(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) } fn local_def_kind(&self, node: NodeId) -> DefKind { @@ -1258,7 +1266,7 @@ impl<'tcx> Resolver<'_, 'tcx> { "adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}", node_id, data, - self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id]), + self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id].key()), ); // FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()` @@ -1280,7 +1288,7 @@ impl<'tcx> Resolver<'_, 'tcx> { // we don't need a mapping from `NodeId` to `LocalDefId`. if node_id != ast::DUMMY_NODE_ID { debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); - self.node_id_to_def_id.insert(node_id, def_id); + self.node_id_to_def_id.insert(node_id, feed.downgrade()); } assert_eq!(self.def_id_to_node_id.push(node_id), def_id); @@ -1332,7 +1340,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut def_id_to_node_id = IndexVec::default(); assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID); let mut node_id_to_def_id = NodeMap::default(); - node_id_to_def_id.insert(CRATE_NODE_ID, CRATE_DEF_ID); + let crate_feed = tcx.feed_local_def_id(CRATE_DEF_ID).downgrade(); + node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed); let mut invocation_parents = FxHashMap::default(); invocation_parents.insert(LocalExpnId::ROOT, (CRATE_DEF_ID, ImplTraitContext::Existential)); @@ -1548,7 +1557,8 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { self.tcx.feed_local_crate().stripped_cfg_items(self.tcx.arena.alloc_from_iter( self.stripped_cfg_items.into_iter().filter_map(|item| { - let parent_module = self.node_id_to_def_id.get(&item.parent_module)?.to_def_id(); + let parent_module = + self.node_id_to_def_id.get(&item.parent_module)?.key().to_def_id(); Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg }) }), )); @@ -1577,7 +1587,11 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { lifetimes_res_map: self.lifetimes_res_map, extra_lifetime_params_map: self.extra_lifetime_params_map, next_node_id: self.next_node_id, - node_id_to_def_id: self.node_id_to_def_id, + node_id_to_def_id: self + .node_id_to_def_id + .into_items() + .map(|(k, f)| (k, f.key())) + .collect(), def_id_to_node_id: self.def_id_to_node_id, trait_map: self.trait_map, lifetime_elision_allowed: self.lifetime_elision_allowed, From 30f2ec2895430d87d6e3a34ea290a9d344472452 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 14 Feb 2024 15:28:40 +0000 Subject: [PATCH 15/29] Eliminate all non-CRATE_DEF_ID uses of `feed_def_id` --- .../rustc_resolve/src/build_reduced_graph.rs | 56 +++++++++++-------- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 9 +-- 3 files changed, 39 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 1c4aeefcbcfd..dd18ab7d9d23 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -25,6 +25,7 @@ use rustc_hir::def::{self, *}; use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_ID}; use rustc_metadata::creader::LoadedMacro; use rustc_middle::metadata::ModChild; +use rustc_middle::ty::Feed; use rustc_middle::{bug, ty}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; @@ -407,7 +408,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Top level use tree reuses the item's id and list stems reuse their parent // use tree's ids, so in both cases their visibilities are already filled. if nested && !list_stem { - self.r.feed_visibility(self.r.local_def_id(id), vis); + self.r.feed_visibility(self.r.feed(id), vis); } let mut prefix_iter = parent_prefix @@ -632,7 +633,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { &mut self, fields: &[ast::FieldDef], ident: Ident, - def_id: LocalDefId, + feed: Feed<'tcx, LocalDefId>, adt_res: Res, adt_vis: ty::Visibility, adt_span: Span, @@ -643,7 +644,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Define a name in the type namespace if it is not anonymous. self.r.define(parent, ident, TypeNS, (adt_res, adt_vis, adt_span, expansion)); - self.r.feed_visibility(def_id, adt_vis); + self.r.feed_visibility(feed, adt_vis); + let def_id = feed.key(); // Record field names for error reporting. self.insert_field_def_ids(def_id, fields); @@ -653,14 +655,15 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { match &field.ty.kind { ast::TyKind::AnonStruct(id, nested_fields) | ast::TyKind::AnonUnion(id, nested_fields) => { - let local_def_id = self.r.local_def_id(*id); + let feed = self.r.feed(*id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); let def_kind = self.r.tcx.def_kind(local_def_id); let res = Res::Def(def_kind, def_id); self.build_reduced_graph_for_struct_variant( &nested_fields, Ident::empty(), - local_def_id, + feed, res, // Anonymous adts inherit visibility from their parent adts. adt_vis, @@ -680,12 +683,13 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let ident = item.ident; let sp = item.span; let vis = self.resolve_visibility(&item.vis); - let local_def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); let def_kind = self.r.tcx.def_kind(def_id); let res = Res::Def(def_kind, def_id); - self.r.feed_visibility(local_def_id, vis); + self.r.feed_visibility(feed, vis); match item.kind { ItemKind::Use(ref use_tree) => { @@ -762,7 +766,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, - local_def_id, + feed, res, vis, sp, @@ -795,10 +799,11 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { } ret_fields.push(field_vis.to_def_id()); } - let ctor_def_id = self.r.local_def_id(ctor_node_id); + let feed = self.r.feed(ctor_node_id); + let ctor_def_id = feed.key(); let ctor_res = self.res(ctor_def_id); self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion)); - self.r.feed_visibility(ctor_def_id, ctor_vis); + self.r.feed_visibility(feed, ctor_vis); // We need the field visibility spans also for the constructor for E0603. self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata.fields()); @@ -812,7 +817,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.build_reduced_graph_for_struct_variant( vdata.fields(), ident, - local_def_id, + feed, res, vis, sp, @@ -919,7 +924,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { /// Constructs the reduced graph for one foreign item. fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) { - let local_def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); let ns = match item.kind { ForeignItemKind::Fn(..) => ValueNS, @@ -931,7 +937,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { let expansion = self.parent_scope.expansion; let vis = self.resolve_visibility(&item.vis); self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion)); - self.r.feed_visibility(local_def_id, vis); + self.r.feed_visibility(feed, vis); } fn build_reduced_graph_for_block(&mut self, block: &Block) { @@ -1218,7 +1224,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScopeRef<'a> { let parent_scope = self.parent_scope; let expansion = parent_scope.expansion; - let def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let def_id = feed.key(); let (res, ident, span, macro_rules) = match &item.kind { ItemKind::MacroDef(def) => (self.res(def_id), item.ident, item.span, def.macro_rules), ItemKind::Fn(..) => match self.proc_macro_stub(item) { @@ -1269,7 +1276,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.r.check_reserved_macro_name(ident, res); self.insert_unused_macro(ident, def_id, item.id); } - self.r.feed_visibility(def_id, vis); + self.r.feed_visibility(feed, vis); let scope = self.r.arenas.alloc_macro_rules_scope(MacroRulesScope::Binding( self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding { parent_macro_rules_scope: parent_scope.macro_rules, @@ -1293,7 +1300,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.insert_unused_macro(ident, def_id, item.id); } self.r.define(module, ident, MacroNS, (res, vis, span, expansion)); - self.r.feed_visibility(def_id, vis); + self.r.feed_visibility(feed, vis); self.parent_scope.macro_rules } } @@ -1385,7 +1392,8 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { } let vis = self.resolve_visibility(&item.vis); - let local_def_id = self.r.local_def_id(item.id); + let feed = self.r.feed(item.id); + let local_def_id = feed.key(); let def_id = local_def_id.to_def_id(); if !(ctxt == AssocCtxt::Impl @@ -1395,7 +1403,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Trait impl item visibility is inherited from its trait when not specified // explicitly. In that case we cannot determine it here in early resolve, // so we leave a hole in the visibility table to be filled later. - self.r.feed_visibility(local_def_id, vis); + self.r.feed_visibility(feed, vis); } if ctxt == AssocCtxt::Trait { @@ -1469,7 +1477,7 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { self.visit_invoc(sf.id); } else { let vis = self.resolve_visibility(&sf.vis); - self.r.feed_visibility(self.r.local_def_id(sf.id), vis); + self.r.feed_visibility(self.r.feed(sf.id), vis); visit::walk_field_def(self, sf); } } @@ -1487,10 +1495,11 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { let ident = variant.ident; // Define a name in the type namespace. - let def_id = self.r.local_def_id(variant.id); + let feed = self.r.feed(variant.id); + let def_id = feed.key(); let vis = self.resolve_visibility(&variant.vis); self.r.define(parent, ident, TypeNS, (self.res(def_id), vis, variant.span, expn_id)); - self.r.feed_visibility(def_id, vis); + self.r.feed_visibility(feed, vis); // If the variant is marked as non_exhaustive then lower the visibility to within the crate. let ctor_vis = @@ -1502,10 +1511,11 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> { // Define a constructor name in the value namespace. if let Some(ctor_node_id) = variant.data.ctor_node_id() { - let ctor_def_id = self.r.local_def_id(ctor_node_id); + let feed = self.r.feed(ctor_node_id); + let ctor_def_id = feed.key(); let ctor_res = self.res(ctor_def_id); self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id)); - self.r.feed_visibility(ctor_def_id, ctor_vis); + self.r.feed_visibility(feed, ctor_vis); } // Record field names for error reporting. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 85db8ba8618e..8cf5917a71c3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3117,7 +3117,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { ); rustc_middle::ty::Visibility::Public }; - this.r.feed_visibility(this.r.local_def_id(id), vis); + this.r.feed_visibility(this.r.feed(id), vis); }; let Some(binding) = binding else { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 241749762e3c..b8ea110d1c00 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1492,7 +1492,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let root_parent_scope = ParentScope::module(graph_root, &resolver); resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope); - resolver.feed_visibility(CRATE_DEF_ID, ty::Visibility::Public); + resolver.feed_visibility(crate_feed, ty::Visibility::Public); resolver } @@ -1540,9 +1540,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { Default::default() } - fn feed_visibility(&mut self, def_id: LocalDefId, vis: ty::Visibility) { - self.tcx.feed_local_def_id(def_id).visibility(vis.to_def_id()); - self.visibilities_for_hashing.push((def_id, vis)); + fn feed_visibility(&mut self, feed: Feed<'tcx, LocalDefId>, vis: ty::Visibility) { + let feed = feed.upgrade(self.tcx); + feed.visibility(vis.to_def_id()); + self.visibilities_for_hashing.push((feed.def_id(), vis)); } pub fn into_outputs(self) -> ResolverOutputs { From 5a0c46a22c8264203bb37c5cb27d25810a412283 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 14 Feb 2024 15:44:01 +0000 Subject: [PATCH 16/29] Get rid of `feed_local_def_id` --- compiler/rustc_interface/src/queries.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 9 +++++---- compiler/rustc_resolve/src/lib.rs | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 86858bfe41d8..f58a2380d2a6 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -173,7 +173,7 @@ impl<'tcx> Queries<'tcx> { feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); feed.output_filenames(Arc::new(outputs)); - let feed = tcx.feed_local_def_id(CRATE_DEF_ID); + let feed = tcx.feed_local_crate_def_id(); feed.def_kind(DefKind::Mod); }); Ok(qcx) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 760392e83378..f6bd5fc6788d 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -60,7 +60,7 @@ use rustc_session::config::CrateType; use rustc_session::cstore::{CrateStoreDyn, Untracked}; use rustc_session::lint::Lint; use rustc_session::{Limit, MetadataKind, Session}; -use rustc_span::def_id::{DefPathHash, StableCrateId}; +use rustc_span::def_id::{DefPathHash, StableCrateId, CRATE_DEF_ID}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use rustc_target::abi::{FieldIdx, Layout, LayoutS, TargetDataLayout, VariantIdx}; @@ -544,8 +544,9 @@ impl<'tcx> TyCtxt<'tcx> { pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> { TyCtxtFeed { tcx: self, key: LOCAL_CRATE } } - pub fn feed_local_def_id(self, key: LocalDefId) -> TyCtxtFeed<'tcx, LocalDefId> { - TyCtxtFeed { tcx: self, key } + + pub fn feed_local_crate_def_id(self) -> TyCtxtFeed<'tcx, LocalDefId> { + TyCtxtFeed { tcx: self, key: CRATE_DEF_ID } } /// In order to break cycles involving `AnonConst`, we need to set the expected type by side @@ -1123,7 +1124,7 @@ impl<'tcx> TyCtxt<'tcx> { // needs to be re-evaluated. self.dep_graph.read_index(DepNodeIndex::FOREVER_RED_NODE); - let feed = self.feed_local_def_id(def_id); + let feed = TyCtxtFeed { tcx: self, key: def_id }; feed.def_kind(def_kind); // Unique types created for closures participate in type privacy checking. // They have visibilities inherited from the module they are defined in. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b8ea110d1c00..25f17e67f462 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1340,7 +1340,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut def_id_to_node_id = IndexVec::default(); assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID); let mut node_id_to_def_id = NodeMap::default(); - let crate_feed = tcx.feed_local_def_id(CRATE_DEF_ID).downgrade(); + let crate_feed = tcx.feed_local_crate_def_id().downgrade(); node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed); let mut invocation_parents = FxHashMap::default(); From 890dd586503fe3a212fc3dc346ea7f0196ca8c29 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 19 Feb 2024 12:02:10 +0000 Subject: [PATCH 17/29] Prevent leaking `Feed`s into query results --- compiler/rustc_middle/src/ty/context.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index f6bd5fc6788d..032d973dcc79 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -520,6 +520,10 @@ pub struct TyCtxtFeed<'tcx, KEY: Copy> { key: KEY, } +/// Never return a `Feed` from a query. Only queries that create a `DefId` are +/// allowed to feed queries for that `DefId`. +impl !HashStable for TyCtxtFeed<'_, KEY> {} + /// The same as `TyCtxtFeed`, but does not contain a `TyCtxt`. /// Use this to pass around when you have a `TyCtxt` elsewhere. /// Just an optimization to save space and not store hundreds of @@ -531,6 +535,10 @@ pub struct Feed<'tcx, KEY: Copy> { key: KEY, } +/// Never return a `Feed` from a query. Only queries that create a `DefId` are +/// allowed to feed queries for that `DefId`. +impl !HashStable for Feed<'_, KEY> {} + impl fmt::Debug for Feed<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.key.fmt(f) From 3845be6b376f405671850dd37c92864aac7b07c2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 19 Feb 2024 16:07:48 +0000 Subject: [PATCH 18/29] Prevent feeding `CRATE_DEF_ID` queries outside the resolver --- compiler/rustc_interface/src/queries.rs | 12 +++--------- compiler/rustc_middle/src/ty/context.rs | 12 ++++++++++-- compiler/rustc_resolve/src/lib.rs | 7 +++++-- 3 files changed, 18 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index f58a2380d2a6..b7ede5e25937 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -8,8 +8,7 @@ use rustc_codegen_ssa::CodegenResults; use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{AppendOnlyIndexVec, FreezeLock, OnceLock, WorkerLocal}; -use rustc_hir::def::DefKind; -use rustc_hir::def_id::{StableCrateId, CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_hir::def_id::{StableCrateId, LOCAL_CRATE}; use rustc_hir::definitions::Definitions; use rustc_incremental::setup_dep_graph; use rustc_metadata::creader::CStore; @@ -144,10 +143,8 @@ impl<'tcx> Queries<'tcx> { stable_crate_id, )) as _); let definitions = FreezeLock::new(Definitions::new(stable_crate_id)); - let source_span = AppendOnlyIndexVec::new(); - let _id = source_span.push(krate.spans.inner_span); - debug_assert_eq!(_id, CRATE_DEF_ID); - let untracked = Untracked { cstore, source_span, definitions }; + let untracked = + Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions }; let qcx = passes::create_global_ctxt( self.compiler, @@ -172,9 +169,6 @@ impl<'tcx> Queries<'tcx> { ))); feed.crate_for_resolver(tcx.arena.alloc(Steal::new((krate, pre_configured_attrs)))); feed.output_filenames(Arc::new(outputs)); - - let feed = tcx.feed_local_crate_def_id(); - feed.def_kind(DefKind::Mod); }); Ok(qcx) }) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 032d973dcc79..b568364517fc 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -545,6 +545,10 @@ impl fmt::Debug for Feed<'_, T> { } } +/// Some workarounds to use cases that cannot use `create_def`. +/// Do not add new ways to create `TyCtxtFeed` without consulting +/// with T-compiler and making an analysis about why your addition +/// does not cause incremental compilation issues. impl<'tcx> TyCtxt<'tcx> { pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> { TyCtxtFeed { tcx: self, key: () } @@ -553,8 +557,12 @@ impl<'tcx> TyCtxt<'tcx> { TyCtxtFeed { tcx: self, key: LOCAL_CRATE } } - pub fn feed_local_crate_def_id(self) -> TyCtxtFeed<'tcx, LocalDefId> { - TyCtxtFeed { tcx: self, key: CRATE_DEF_ID } + /// Only used in the resolver to register the `CRATE_DEF_ID` `DefId` and feed + /// some queries for it. It will panic if used twice. + pub fn create_local_crate_def_id(self, span: Span) -> TyCtxtFeed<'tcx, LocalDefId> { + let key = self.untracked().source_span.push(span); + assert_eq!(key, CRATE_DEF_ID); + TyCtxtFeed { tcx: self, key } } /// In order to break cycles involving `AnonConst`, we need to set the expected type by side diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 25f17e67f462..4135ae405c32 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -53,7 +53,7 @@ use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::query::Providers; use rustc_middle::span_bug; use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt, TyCtxtFeed}; -use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs, Feed}; +use rustc_middle::ty::{Feed, ResolverGlobalCtxt, ResolverOutputs}; use rustc_query_system::ich::StableHashingContext; use rustc_session::lint::builtin::PRIVATE_MACRO_USE; use rustc_session::lint::LintBuffer; @@ -1340,7 +1340,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let mut def_id_to_node_id = IndexVec::default(); assert_eq!(def_id_to_node_id.push(CRATE_NODE_ID), CRATE_DEF_ID); let mut node_id_to_def_id = NodeMap::default(); - let crate_feed = tcx.feed_local_crate_def_id().downgrade(); + let crate_feed = tcx.create_local_crate_def_id(crate_span); + + crate_feed.def_kind(DefKind::Mod); + let crate_feed = crate_feed.downgrade(); node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed); let mut invocation_parents = FxHashMap::default(); From c696d4c3238ed71f0acedad7c402924fb0bdde32 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 19 Feb 2024 16:58:18 +0000 Subject: [PATCH 19/29] Remove a use of feed_local_crate and make it fail if used within queries --- compiler/rustc_interface/src/passes.rs | 2 ++ compiler/rustc_middle/src/query/mod.rs | 1 - compiler/rustc_middle/src/ty/context.rs | 6 ++++++ compiler/rustc_middle/src/ty/mod.rs | 2 ++ compiler/rustc_resolve/src/lib.rs | 18 +++++++++++------- 5 files changed, 21 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 661401687593..eba707a4938d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -608,6 +608,8 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { providers.analysis = analysis; providers.hir_crate = rustc_ast_lowering::lower_to_hir; providers.resolver_for_lowering = resolver_for_lowering; + providers.stripped_cfg_items = + |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal()); providers.early_lint_checks = early_lint_checks; proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index e87bc581e6ea..ef0ac52d7935 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -2230,7 +2230,6 @@ rustc_queries! { /// Should not be called for the local crate before the resolver outputs are created, as it /// is only fed there. query stripped_cfg_items(cnum: CrateNum) -> &'tcx [StrippedCfgItem] { - feedable desc { "getting cfg-ed out item names" } separate_provide_extern } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b568364517fc..adb00bcd9bf1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -550,10 +550,16 @@ impl fmt::Debug for Feed<'_, T> { /// with T-compiler and making an analysis about why your addition /// does not cause incremental compilation issues. impl<'tcx> TyCtxt<'tcx> { + /// Can only be fed before queries are run, and is thus exempt from any + /// incremental issues. Do not use except for the initial query feeding. pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> { TyCtxtFeed { tcx: self, key: () } } + + /// Can only be fed before queries are run, and is thus exempt from any + /// incremental issues. Do not use except for the initial query feeding. pub fn feed_local_crate(self) -> TyCtxtFeed<'tcx, CrateNum> { + self.dep_graph.assert_ignored(); TyCtxtFeed { tcx: self, key: LOCAL_CRATE } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 77444b74ccdb..aa572b80a019 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -31,6 +31,7 @@ pub use assoc::*; pub use generic_args::*; pub use generics::*; use rustc_ast as ast; +use rustc_ast::expand::StrippedCfgItem; use rustc_ast::node_id::NodeMap; pub use rustc_ast_ir::{Movability, Mutability}; use rustc_attr as attr; @@ -189,6 +190,7 @@ pub struct ResolverGlobalCtxt { pub doc_link_resolutions: FxHashMap, pub doc_link_traits_in_scope: FxHashMap>, pub all_macro_rules: FxHashMap>, + pub stripped_cfg_items: Steal>, } /// Resolutions that should only be used for lowering. diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 4135ae405c32..35e1147b11d3 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1559,13 +1559,16 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { let confused_type_with_std_module = self.confused_type_with_std_module; let effective_visibilities = self.effective_visibilities; - self.tcx.feed_local_crate().stripped_cfg_items(self.tcx.arena.alloc_from_iter( - self.stripped_cfg_items.into_iter().filter_map(|item| { - let parent_module = - self.node_id_to_def_id.get(&item.parent_module)?.key().to_def_id(); - Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg }) - }), - )); + let stripped_cfg_items = Steal::new( + self.stripped_cfg_items + .into_iter() + .filter_map(|item| { + let parent_module = + self.node_id_to_def_id.get(&item.parent_module)?.key().to_def_id(); + Some(StrippedCfgItem { parent_module, name: item.name, cfg: item.cfg }) + }) + .collect(), + ); let global_ctxt = ResolverGlobalCtxt { expn_that_defined, @@ -1582,6 +1585,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { doc_link_resolutions: self.doc_link_resolutions, doc_link_traits_in_scope: self.doc_link_traits_in_scope, all_macro_rules: self.all_macro_rules, + stripped_cfg_items, }; let ast_lowering = ty::ResolverAstLowering { legacy_const_generic_args: self.legacy_const_generic_args, From ef00fae46d6bf05b1ea7c5447410f0cdf8dc2267 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 19 Feb 2024 17:25:01 +0000 Subject: [PATCH 20/29] Avoid using feed_unit_query from within queries --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_driver_impl/src/lib.rs | 2 +- compiler/rustc_driver_impl/src/pretty.rs | 4 ++-- compiler/rustc_interface/src/passes.rs | 16 ++++++++-------- compiler/rustc_middle/src/query/mod.rs | 3 +-- compiler/rustc_middle/src/ty/context.rs | 7 ++++++- compiler/rustc_passes/src/debugger_visualizer.rs | 2 +- compiler/rustc_passes/src/lang_items.rs | 2 +- tests/ui/panics/default-backtrace-ice.stderr | 2 +- 9 files changed, 22 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 087d240b0d50..ac9150182cc7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -427,7 +427,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> hir::Crate<'_> { tcx.ensure_with_value().early_lint_checks(()); tcx.ensure_with_value().debugger_visualizers(LOCAL_CRATE); tcx.ensure_with_value().get_lang_items(()); - let (mut resolver, krate) = tcx.resolver_for_lowering(()).steal(); + let (mut resolver, krate) = tcx.resolver_for_lowering().steal(); let ast_index = index_crate(&resolver.node_id_to_def_id, &krate); let mut owners = IndexVec::from_fn_n( diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 410e7eba30a9..7b9d3296bb22 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -417,7 +417,7 @@ fn run_compiler( } // Make sure name resolution and macro expansion is run. - queries.global_ctxt()?.enter(|tcx| tcx.resolver_for_lowering(())); + queries.global_ctxt()?.enter(|tcx| tcx.resolver_for_lowering()); if callbacks.after_expansion(compiler, queries) == Compilation::Stop { return early_exit(); diff --git a/compiler/rustc_driver_impl/src/pretty.rs b/compiler/rustc_driver_impl/src/pretty.rs index ff5ffd2454a1..787168e66758 100644 --- a/compiler/rustc_driver_impl/src/pretty.rs +++ b/compiler/rustc_driver_impl/src/pretty.rs @@ -229,7 +229,7 @@ impl<'tcx> PrintExtra<'tcx> { { match self { PrintExtra::AfterParsing { krate, .. } => f(krate), - PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering(()).borrow().1), + PrintExtra::NeedsAstMap { tcx } => f(&tcx.resolver_for_lowering().borrow().1), } } @@ -281,7 +281,7 @@ pub fn print<'tcx>(sess: &Session, ppm: PpMode, ex: PrintExtra<'tcx>) { } AstTreeExpanded => { debug!("pretty-printing expanded AST"); - format!("{:#?}", ex.tcx().resolver_for_lowering(()).borrow().1) + format!("{:#?}", ex.tcx().resolver_for_lowering().borrow().1) } Hir(s) => { debug!("pretty printing HIR {:?}", s); diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index eba707a4938d..2417c2af4a8d 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -280,7 +280,7 @@ fn configure_and_expand( fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { let sess = tcx.sess; - let (resolver, krate) = &*tcx.resolver_for_lowering(()).borrow(); + let (resolver, krate) = &*tcx.resolver_for_lowering().borrow(); let mut lint_buffer = resolver.lint_buffer.steal(); if sess.opts.unstable_opts.input_stats { @@ -531,10 +531,10 @@ fn write_out_deps(tcx: TyCtxt<'_>, outputs: &OutputFilenames, out_filenames: &[P } } -fn resolver_for_lowering<'tcx>( +fn resolver_for_lowering_raw<'tcx>( tcx: TyCtxt<'tcx>, (): (), -) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { +) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc)>, &'tcx ty::ResolverGlobalCtxt) { let arenas = Resolver::arenas(); let _ = tcx.registered_tools(()); // Uses `crate_for_resolver`. let (krate, pre_configured_attrs) = tcx.crate_for_resolver(()).steal(); @@ -549,16 +549,15 @@ fn resolver_for_lowering<'tcx>( ast_lowering: untracked_resolver_for_lowering, } = resolver.into_outputs(); - let feed = tcx.feed_unit_query(); - feed.resolutions(tcx.arena.alloc(untracked_resolutions)); - tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))) + let resolutions = tcx.arena.alloc(untracked_resolutions); + (tcx.arena.alloc(Steal::new((untracked_resolver_for_lowering, Lrc::new(krate)))), resolutions) } pub(crate) fn write_dep_info(tcx: TyCtxt<'_>) { // Make sure name resolution and macro expansion is run for // the side-effect of providing a complete set of all // accessed files and env vars. - let _ = tcx.resolver_for_lowering(()); + let _ = tcx.resolver_for_lowering(); let sess = tcx.sess; let _timer = sess.timer("write_dep_info"); @@ -607,9 +606,10 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { let providers = &mut Providers::default(); providers.analysis = analysis; providers.hir_crate = rustc_ast_lowering::lower_to_hir; - providers.resolver_for_lowering = resolver_for_lowering; + providers.resolver_for_lowering_raw = resolver_for_lowering_raw; providers.stripped_cfg_items = |tcx, _| tcx.arena.alloc_from_iter(tcx.resolutions(()).stripped_cfg_items.steal()); + providers.resolutions = |tcx, ()| tcx.resolver_for_lowering_raw(()).1; providers.early_lint_checks = early_lint_checks; proc_macro_decls::provide(providers); rustc_const_eval::provide(providers); diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index ef0ac52d7935..aa29556f9242 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -125,12 +125,11 @@ rustc_queries! { } query resolutions(_: ()) -> &'tcx ty::ResolverGlobalCtxt { - feedable no_hash desc { "getting the resolver outputs" } } - query resolver_for_lowering(_: ()) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { + query resolver_for_lowering_raw(_: ()) -> (&'tcx Steal<(ty::ResolverAstLowering, Lrc)>, &'tcx ty::ResolverGlobalCtxt) { eval_always no_hash desc { "getting the resolver for lowering" } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index adb00bcd9bf1..90fc142fd161 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -39,7 +39,7 @@ use rustc_data_structures::profiling::SelfProfilerRef; use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::steal::Steal; -use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, WorkerLocal}; +use rustc_data_structures::sync::{self, FreezeReadGuard, Lock, Lrc, WorkerLocal}; #[cfg(parallel_compiler)] use rustc_data_structures::sync::{DynSend, DynSync}; use rustc_data_structures::unord::UnordSet; @@ -553,6 +553,7 @@ impl<'tcx> TyCtxt<'tcx> { /// Can only be fed before queries are run, and is thus exempt from any /// incremental issues. Do not use except for the initial query feeding. pub fn feed_unit_query(self) -> TyCtxtFeed<'tcx, ()> { + self.dep_graph.assert_ignored(); TyCtxtFeed { tcx: self, key: () } } @@ -2383,6 +2384,10 @@ impl<'tcx> TyCtxt<'tcx> { self.resolutions(()).module_children.get(&def_id).map_or(&[], |v| &v[..]) } + pub fn resolver_for_lowering(self) -> &'tcx Steal<(ty::ResolverAstLowering, Lrc)> { + self.resolver_for_lowering_raw(()).0 + } + /// Given an `impl_id`, return the trait it implements. /// Return `None` if this is an inherent impl. pub fn impl_trait_ref( diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 4bfe6be54937..96893e585491 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -87,7 +87,7 @@ impl<'ast> rustc_ast::visit::Visitor<'ast> for DebuggerVisualizerCollector<'_> { /// Traverses and collects the debugger visualizers for a specific crate. fn debugger_visualizers(tcx: TyCtxt<'_>, _: LocalCrate) -> Vec { - let resolver_and_krate = tcx.resolver_for_lowering(()).borrow(); + let resolver_and_krate = tcx.resolver_for_lowering().borrow(); let krate = &*resolver_and_krate.1; let mut visitor = DebuggerVisualizerCollector { sess: tcx.sess, visualizers: Vec::new() }; diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index d3e3e183845e..d1368267224a 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -243,7 +243,7 @@ impl<'ast, 'tcx> LanguageItemCollector<'ast, 'tcx> { /// Traverses and collects all the lang items in all crates. fn get_lang_items(tcx: TyCtxt<'_>, (): ()) -> LanguageItems { - let resolver = tcx.resolver_for_lowering(()).borrow(); + let resolver = tcx.resolver_for_lowering().borrow(); let (resolver, krate) = &*resolver; // Initialize the collector. diff --git a/tests/ui/panics/default-backtrace-ice.stderr b/tests/ui/panics/default-backtrace-ice.stderr index 9d27cb22ae94..82b61e43f449 100644 --- a/tests/ui/panics/default-backtrace-ice.stderr +++ b/tests/ui/panics/default-backtrace-ice.stderr @@ -21,5 +21,5 @@ error: the compiler unexpectedly panicked. this is a bug. query stack during panic: -#0 [resolver_for_lowering] getting the resolver for lowering +#0 [resolver_for_lowering_raw] getting the resolver for lowering end of query stack From 0a0074980fb7802ac621ceac92bf98bdc640bd78 Mon Sep 17 00:00:00 2001 From: Andrew Wock Date: Sun, 18 Feb 2024 18:06:16 -0500 Subject: [PATCH 21/29] Implement MaybeUninit::fill{,_with,_from} ACP: rust-lang/libs-team#156 Signed-off-by: Andrew Wock --- library/core/src/mem/maybe_uninit.rs | 202 +++++++++++++++++++++++-- library/core/tests/lib.rs | 1 + library/core/tests/mem.rs | 217 ++++++++++++++++++++++++++- 3 files changed, 398 insertions(+), 22 deletions(-) diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index c19b5791562c..026e21586d40 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -1125,22 +1125,6 @@ impl MaybeUninit { // unlike copy_from_slice this does not call clone_from_slice on the slice // this is because `MaybeUninit` does not implement Clone. - struct Guard<'a, T> { - slice: &'a mut [MaybeUninit], - initialized: usize, - } - - impl<'a, T> Drop for Guard<'a, T> { - fn drop(&mut self) { - let initialized_part = &mut self.slice[..self.initialized]; - // SAFETY: this raw slice will contain only initialized objects - // that's why, it is allowed to drop it. - unsafe { - crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part)); - } - } - } - assert_eq!(this.len(), src.len(), "destination and source slices have different lengths"); // NOTE: We need to explicitly slice them to the same length // for bounds checking to be elided, and the optimizer will @@ -1162,6 +1146,151 @@ impl MaybeUninit { unsafe { MaybeUninit::slice_assume_init_mut(this) } } + /// Fills `this` with elements by cloning `value`, returning a mutable reference to the now + /// initialized contents of `this`. + /// Any previously initialized elements will not be dropped. + /// + /// This is similar to [`slice::fill`]. + /// + /// # Panics + /// + /// This function will panic if any call to `Clone` panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Fill an uninit vec with 1. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::uninit(); 10]; + /// let initialized = MaybeUninit::fill(buf.as_mut_slice(), 1); + /// assert_eq!(initialized, &mut [1; 10]); + /// ``` + #[doc(alias = "memset")] + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn fill<'a>(this: &'a mut [MaybeUninit], value: T) -> &'a mut [T] + where + T: Clone, + { + SpecFill::spec_fill(this, value); + // SAFETY: Valid elements have just been filled into `this` so it is initialized + unsafe { MaybeUninit::slice_assume_init_mut(this) } + } + + /// Fills `this` with elements returned by calling a closure repeatedly. + /// + /// This method uses a closure to create new values. If you'd rather `Clone` a given value, use + /// [`MaybeUninit::fill`]. If you want to use the `Default` trait to generate values, you can + /// pass [`Default::default`] as the argument. + /// + /// # Panics + /// + /// This function will panic if any call to the provided closure panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Fill an uninit vec with the default value. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::::uninit(); 10]; + /// let initialized = MaybeUninit::fill_with(buf.as_mut_slice(), Default::default); + /// assert_eq!(initialized, &mut [0; 10]); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn fill_with<'a, F>(this: &'a mut [MaybeUninit], mut f: F) -> &'a mut [T] + where + F: FnMut() -> T, + { + let mut guard = Guard { slice: this, initialized: 0 }; + + for element in guard.slice.iter_mut() { + element.write(f()); + guard.initialized += 1; + } + + super::forget(guard); + + // SAFETY: Valid elements have just been written into `this` so it is initialized + unsafe { MaybeUninit::slice_assume_init_mut(this) } + } + + /// Fills `this` with elements yielded by an iterator until either all elements have been + /// initialized or the iterator is empty. + /// + /// Returns two slices. The first slice contains the initialized portion of the original slice. + /// The second slice is the still-uninitialized remainder of the original slice. + /// + /// # Panics + /// + /// This function panics if the iterator's `next` function panics. + /// + /// If such a panic occurs, any elements previously initialized during this operation will be + /// dropped. + /// + /// # Examples + /// + /// Fill an uninit vec with a cycling iterator. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::uninit(); 5]; + /// + /// let iter = [1, 2, 3].into_iter().cycle(); + /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); + /// + /// assert_eq!(initialized, &mut [1, 2, 3, 1, 2]); + /// assert_eq!(0, remainder.len()); + /// ``` + /// + /// Fill an uninit vec, but not completely. + /// ``` + /// #![feature(maybe_uninit_fill)] + /// use std::mem::MaybeUninit; + /// + /// let mut buf = vec![MaybeUninit::uninit(); 5]; + /// let iter = [1, 2]; + /// let (initialized, remainder) = MaybeUninit::fill_from(&mut buf, iter); + /// + /// assert_eq!(initialized, &mut [1, 2]); + /// assert_eq!(remainder.len(), 3); + /// ``` + #[unstable(feature = "maybe_uninit_fill", issue = "117428")] + pub fn fill_from<'a, I>( + this: &'a mut [MaybeUninit], + it: I, + ) -> (&'a mut [T], &'a mut [MaybeUninit]) + where + I: IntoIterator, + { + let iter = it.into_iter(); + let mut guard = Guard { slice: this, initialized: 0 }; + + for (element, val) in guard.slice.iter_mut().zip(iter) { + element.write(val); + guard.initialized += 1; + } + + let initialized_len = guard.initialized; + super::forget(guard); + + // SAFETY: guard.initialized <= this.len() + let (initted, remainder) = unsafe { this.split_at_mut_unchecked(initialized_len) }; + + // SAFETY: Valid elements have just been written into `init`, so that portion + // of `this` is initialized. + (unsafe { MaybeUninit::slice_assume_init_mut(initted) }, remainder) + } + /// Returns the contents of this `MaybeUninit` as a slice of potentially uninitialized bytes. /// /// Note that even if the contents of a `MaybeUninit` have been initialized, the value may still @@ -1315,3 +1444,44 @@ impl [MaybeUninit; N] { unsafe { intrinsics::transmute_unchecked(self) } } } + +struct Guard<'a, T> { + slice: &'a mut [MaybeUninit], + initialized: usize, +} + +impl<'a, T> Drop for Guard<'a, T> { + fn drop(&mut self) { + let initialized_part = &mut self.slice[..self.initialized]; + // SAFETY: this raw sub-slice will contain only initialized objects. + unsafe { + crate::ptr::drop_in_place(MaybeUninit::slice_assume_init_mut(initialized_part)); + } + } +} + +trait SpecFill { + fn spec_fill(&mut self, value: T); +} + +impl SpecFill for [MaybeUninit] { + default fn spec_fill(&mut self, value: T) { + let mut guard = Guard { slice: self, initialized: 0 }; + + if let Some((last, elems)) = guard.slice.split_last_mut() { + for el in elems { + el.write(value.clone()); + guard.initialized += 1; + } + + last.write(value); + } + super::forget(guard); + } +} + +impl SpecFill for [MaybeUninit] { + fn spec_fill(&mut self, value: T) { + self.fill(MaybeUninit::new(value)); + } +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index fa0e9a979d06..c5a7e87c4aa4 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -54,6 +54,7 @@ #![feature(slice_from_ptr_range)] #![feature(slice_split_once)] #![feature(split_as_slice)] +#![feature(maybe_uninit_fill)] #![feature(maybe_uninit_uninit_array)] #![feature(maybe_uninit_write_slice)] #![feature(maybe_uninit_uninit_array_transpose)] diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index 0f7fde747690..e388800f400d 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -308,21 +308,226 @@ fn uninit_write_slice_cloned_mid_panic() { } } +#[derive(Clone)] +struct Bomb; + +impl Drop for Bomb { + fn drop(&mut self) { + panic!("dropped a bomb! kaboom!") + } +} + #[test] fn uninit_write_slice_cloned_no_drop() { - #[derive(Clone)] - struct Bomb; + let mut dst = [MaybeUninit::uninit()]; + let src = [Bomb]; + + MaybeUninit::clone_from_slice(&mut dst, &src); + + forget(src); +} + +#[test] +fn uninit_fill() { + let mut dst = [MaybeUninit::new(255); 64]; + let expect = [0; 64]; + + assert_eq!(MaybeUninit::fill(&mut dst, 0), &expect); +} + +#[cfg(panic = "unwind")] +struct CloneUntilPanic { + limit: usize, + rc: Rc<()>, +} - impl Drop for Bomb { - fn drop(&mut self) { - panic!("dropped a bomb! kaboom") +#[cfg(panic = "unwind")] +impl Clone for CloneUntilPanic { + fn clone(&self) -> Self { + if Rc::strong_count(&self.rc) >= self.limit { + panic!("expected panic on clone"); } + Self { limit: self.limit, rc: self.rc.clone() } } +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_clone_panic_drop() { + use std::panic; + + let rc = Rc::new(()); + + let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; + + let src = CloneUntilPanic { limit: 3, rc: rc.clone() }; + let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { + MaybeUninit::fill(&mut dst, src); + })); + + match err { + Ok(_) => unreachable!(), + Err(payload) => { + payload + .downcast::<&'static str>() + .and_then(|s| if *s == "expected panic on clone" { Ok(s) } else { Err(s) }) + .unwrap_or_else(|p| panic::resume_unwind(p)); + assert_eq!(Rc::strong_count(&rc), 1) + } + } +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_clone_no_drop_clones() { + let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; + + MaybeUninit::fill(&mut dst, Bomb); +} + +#[test] +fn uninit_fill_with() { + let mut dst = [MaybeUninit::new(255); 64]; + let expect = [0; 64]; + + assert_eq!(MaybeUninit::fill_with(&mut dst, || 0), &expect); +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_with_mid_panic() { + use std::panic; + + let rc = Rc::new(()); + + let mut dst = [MaybeUninit::uninit(), MaybeUninit::uninit(), MaybeUninit::uninit()]; + + let src = CloneUntilPanic { limit: 3, rc: rc.clone() }; + let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { + MaybeUninit::fill_with(&mut dst, || src.clone()); + })); + + drop(src); + + match err { + Ok(_) => unreachable!(), + Err(payload) => { + payload + .downcast::<&'static str>() + .and_then(|s| if *s == "expected panic on clone" { Ok(s) } else { Err(s) }) + .unwrap_or_else(|p| panic::resume_unwind(p)); + assert_eq!(Rc::strong_count(&rc), 1) + } + } +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_with_no_drop() { + let mut dst = [MaybeUninit::uninit()]; + let src = Bomb; + + MaybeUninit::fill_with(&mut dst, || src.clone()); + + forget(src); +} + +#[test] +fn uninit_fill_from() { + let mut dst = [MaybeUninit::new(255); 64]; + let src = [0; 64]; + + let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + assert_eq!(initted, &src); + assert_eq!(remainder.len(), 0); +} + +#[test] +fn uninit_fill_from_partial() { + let mut dst = [MaybeUninit::new(255); 64]; + let src = [0; 48]; + + let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + assert_eq!(initted, &src); + assert_eq!(remainder.len(), 16); +} + +#[test] +fn uninit_over_fill() { + let mut dst = [MaybeUninit::new(255); 64]; + let src = [0; 72]; + + let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + assert_eq!(initted, &src[0..64]); + assert_eq!(remainder.len(), 0); +} + +#[test] +fn uninit_empty_fill() { + let mut dst = [MaybeUninit::new(255); 64]; + let src = [0; 0]; + + let (initted, remainder) = MaybeUninit::fill_from(&mut dst, src.into_iter()); + assert_eq!(initted, &src[0..0]); + assert_eq!(remainder.len(), 64); +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_from_mid_panic() { + use std::panic; + + struct IterUntilPanic { + limit: usize, + rc: Rc<()>, + } + + impl Iterator for IterUntilPanic { + type Item = Rc<()>; + fn next(&mut self) -> Option { + if Rc::strong_count(&self.rc) >= self.limit { + panic!("expected panic on next"); + } + Some(self.rc.clone()) + } + } + + let rc = Rc::new(()); + + let mut dst = [ + MaybeUninit::uninit(), + MaybeUninit::uninit(), + MaybeUninit::uninit(), + MaybeUninit::uninit(), + ]; + + let src = IterUntilPanic { limit: 3, rc: rc.clone() }; + + let err = panic::catch_unwind(panic::AssertUnwindSafe(|| { + MaybeUninit::fill_from(&mut dst, src); + })); + + match err { + Ok(_) => unreachable!(), + Err(payload) => { + payload + .downcast::<&'static str>() + .and_then(|s| if *s == "expected panic on next" { Ok(s) } else { Err(s) }) + .unwrap_or_else(|p| panic::resume_unwind(p)); + + assert_eq!(Rc::strong_count(&rc), 1) + } + } +} + +#[test] +#[cfg(panic = "unwind")] +fn uninit_fill_from_no_drop() { let mut dst = [MaybeUninit::uninit()]; let src = [Bomb]; - MaybeUninit::clone_from_slice(&mut dst, &src); + MaybeUninit::fill_from(&mut dst, src.iter()); forget(src); } From b69607cecfca1315643a305fe44363b6e0ac74c6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 6 Mar 2024 16:33:17 +0100 Subject: [PATCH 22/29] Add missing background color for top-level rust documentation page and increase contrast by setting text color to black --- src/doc/rust.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rust.css b/src/doc/rust.css index e0bf64c33bcf..bd2e0b945187 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -5,12 +5,13 @@ body { margin: 0 auto; padding: 0 15px; font-size: 18px; - color: #333; + color: #000; line-height: 1.428571429; -webkit-box-sizing: unset; -moz-box-sizing: unset; box-sizing: unset; + background: #fff; } @media (min-width: 768px) { body { @@ -39,7 +40,6 @@ h4, h5, h6 { padding: 5px 10px; } h5, h6 { - color: black; text-decoration: underline; } From 9da004ea1997ac0eedbb882fa52960417725bd48 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Mon, 10 Jul 2023 01:28:23 -0700 Subject: [PATCH 23/29] Dynamically size sigaltstk in std On modern Linux with Intel AMX and 1KiB matrices, Arm SVE with potentially 2KiB vectors, and RISCV Vectors with up to 16KiB vectors, we must handle dynamic signal stack sizes. We can do so unconditionally by using getauxval, but assuming it may return 0 as an answer, thus falling back to the old constant if needed. --- .../std/src/sys/pal/unix/stack_overflow.rs | 50 +++++++++++++++---- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow.rs index 923637cbaf26..78a599077c75 100644 --- a/library/std/src/sys/pal/unix/stack_overflow.rs +++ b/library/std/src/sys/pal/unix/stack_overflow.rs @@ -51,7 +51,7 @@ mod imp { #[cfg(all(target_os = "linux", target_env = "gnu"))] use libc::{mmap64, munmap}; use libc::{sigaction, sighandler_t, SA_ONSTACK, SA_SIGINFO, SIGBUS, SIG_DFL}; - use libc::{sigaltstack, SIGSTKSZ, SS_DISABLE}; + use libc::{sigaltstack, SS_DISABLE}; use libc::{MAP_ANON, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SIGSEGV}; use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering}; @@ -130,7 +130,7 @@ mod imp { drop_handler(MAIN_ALTSTACK.load(Ordering::Relaxed)); } - unsafe fn get_stackp() -> *mut libc::c_void { + unsafe fn get_stack() -> libc::stack_t { // OpenBSD requires this flag for stack mapping // otherwise the said mapping will fail as a no-op on most systems // and has a different meaning on FreeBSD @@ -148,20 +148,28 @@ mod imp { target_os = "dragonfly", )))] let flags = MAP_PRIVATE | MAP_ANON; - let stackp = - mmap64(ptr::null_mut(), SIGSTKSZ + page_size(), PROT_READ | PROT_WRITE, flags, -1, 0); + + let sigstack_size = sigstack_size(); + let page_size = page_size(); + + let stackp = mmap64( + ptr::null_mut(), + sigstack_size + page_size, + PROT_READ | PROT_WRITE, + flags, + -1, + 0, + ); if stackp == MAP_FAILED { panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); } - let guard_result = libc::mprotect(stackp, page_size(), PROT_NONE); + let guard_result = libc::mprotect(stackp, page_size, PROT_NONE); if guard_result != 0 { panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error()); } - stackp.add(page_size()) - } + let stackp = stackp.add(page_size); - unsafe fn get_stack() -> libc::stack_t { - libc::stack_t { ss_sp: get_stackp(), ss_flags: 0, ss_size: SIGSTKSZ } + libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size } } pub unsafe fn make_handler() -> Handler { @@ -182,6 +190,8 @@ mod imp { pub unsafe fn drop_handler(data: *mut libc::c_void) { if !data.is_null() { + let sigstack_size = sigstack_size(); + let page_size = page_size(); let stack = libc::stack_t { ss_sp: ptr::null_mut(), ss_flags: SS_DISABLE, @@ -189,14 +199,32 @@ mod imp { // UNIX2003 which returns ENOMEM when disabling a stack while // passing ss_size smaller than MINSIGSTKSZ. According to POSIX // both ss_sp and ss_size should be ignored in this case. - ss_size: SIGSTKSZ, + ss_size: sigstack_size, }; sigaltstack(&stack, ptr::null_mut()); // We know from `get_stackp` that the alternate stack we installed is part of a mapping // that started one page earlier, so walk back a page and unmap from there. - munmap(data.sub(page_size()), SIGSTKSZ + page_size()); + munmap(data.sub(page_size), sigstack_size + page_size); } } + + /// Modern kernels on modern hardware can have dynamic signal stack sizes. + #[cfg(any(target_os = "linux", target_os = "android"))] + fn sigstack_size() -> usize { + // FIXME: reuse const from libc when available? + const AT_MINSIGSTKSZ: crate::ffi::c_ulong = 51; + let dynamic_sigstksz = unsafe { libc::getauxval(AT_MINSIGSTKSZ) }; + // If getauxval couldn't find the entry, it returns 0, + // so take the higher of the "constant" and auxval. + // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ + libc::SIGSTKSZ.max(dynamic_sigstksz as _) + } + + /// Not all OS support hardware where this is needed. + #[cfg(not(any(target_os = "linux", target_os = "android")))] + fn sigstack_size() -> usize { + libc::SIGSTKSZ + } } #[cfg(not(any( From 8e45d0fe495358bbb2415f1c0eec92d28b50c743 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Wed, 6 Mar 2024 21:59:03 +0000 Subject: [PATCH 24/29] Cancel parsing ever made during recovery --- compiler/rustc_parse/src/parser/stmt.rs | 16 ++++++++++------ .../recover-colon-instead-of-eq-in-local.rs | 7 +++++++ .../recover-colon-instead-of-eq-in-local.stderr | 12 ++++++++++-- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 54854cd2da99..ea9c78ca34c0 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -787,13 +787,17 @@ impl<'a> Parser<'a> { let suggest_eq = if self.token.kind == token::Dot && let _ = self.bump() && let mut snapshot = self.create_snapshot_for_diagnostic() - && let Ok(_) = snapshot.parse_dot_suffix_expr( - colon_sp, - self.mk_expr_err( + && let Ok(_) = snapshot + .parse_dot_suffix_expr( colon_sp, - self.dcx().delayed_bug("error during `:` -> `=` recovery"), - ), - ) { + self.mk_expr_err( + colon_sp, + self.dcx() + .delayed_bug("error during `:` -> `=` recovery"), + ), + ) + .map_err(Diag::cancel) + { true } else if let Some(op) = self.check_assoc_op() && op.node.can_continue_expr_unambiguously() diff --git a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs index ed4de58cd23c..521eb6a818b0 100644 --- a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs +++ b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.rs @@ -1,3 +1,10 @@ +#![allow(unused)] + +fn test_122112() { + // Make sure we don't ICE if parsing in recovery fails + let _: std::env::temp_dir().join(&self, push: Box); //~ ERROR expected one of +} + fn main() { let _: std::env::temp_dir().join("foo"); //~ ERROR expected one of } diff --git a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr index d03f3ae02830..15c27bb9451b 100644 --- a/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr +++ b/tests/ui/parser/recover/recover-colon-instead-of-eq-in-local.stderr @@ -1,5 +1,13 @@ error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.` - --> $DIR/recover-colon-instead-of-eq-in-local.rs:2:32 + --> $DIR/recover-colon-instead-of-eq-in-local.rs:5:32 + | +LL | let _: std::env::temp_dir().join(&self, push: Box); + | - ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=` + | | + | while parsing the type for `_` + +error: expected one of `!`, `+`, `->`, `::`, `;`, or `=`, found `.` + --> $DIR/recover-colon-instead-of-eq-in-local.rs:9:32 | LL | let _: std::env::temp_dir().join("foo"); | - ^ expected one of `!`, `+`, `->`, `::`, `;`, or `=` @@ -7,5 +15,5 @@ LL | let _: std::env::temp_dir().join("foo"); | while parsing the type for `_` | help: use `=` if you meant to assign -error: aborting due to 1 previous error +error: aborting due to 2 previous errors From ee1c691befd416221354b3595fd109a7d480ec01 Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 6 Mar 2024 20:34:31 +0000 Subject: [PATCH 25/29] Make `x t miri` respect `MIRI_TEMP` --- src/tools/miri/tests/compiletest.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs index 9f4677245651..db0768848fd3 100644 --- a/src/tools/miri/tests/compiletest.rs +++ b/src/tools/miri/tests/compiletest.rs @@ -81,8 +81,10 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) -> // Add a test env var to do environment communication tests. program.envs.push(("MIRI_ENV_VAR_TEST".into(), Some("0".into()))); + // Let the tests know where to store temp files (they might run for a different target, which can make this hard to find). - program.envs.push(("MIRI_TEMP".into(), Some(env::temp_dir().into()))); + let miri_temp = env::var_os("MIRI_TEMP").unwrap_or_else(|| env::temp_dir().into()); + program.envs.push(("MIRI_TEMP".into(), Some(miri_temp))); let mut config = Config { target: Some(target.to_owned()), From 9891d6a33737117dcc93c620c0bb027aa26a246e Mon Sep 17 00:00:00 2001 From: Maybe Waffle Date: Wed, 6 Mar 2024 20:34:50 +0000 Subject: [PATCH 26/29] Add advice for failing `shims/fs.rs` miri test --- src/tools/miri/tests/pass/shims/fs.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 6ba39c1f563f..304a178dc340 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -1,6 +1,10 @@ //@ignore-target-windows: File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation +// If this test is failing for you locally, you can try +// 1. Deleting the files `/tmp/miri_*` +// 2. Setting `MIRI_TEMP` or `TMPDIR` to a different directory, without the `miri_*` files + #![feature(io_error_more)] #![feature(io_error_uncategorized)] From 52bc7ce837a0c5a386b084f37f371fa85fc2ba99 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Wed, 6 Mar 2024 16:45:43 -0500 Subject: [PATCH 27/29] Make not finding core a fatal error --- compiler/rustc_metadata/src/locator.rs | 22 +++++++++++++++---- tests/ui/crate-loading/missing-std.stderr | 4 +--- tests/ui/issues/issue-37131.stderr | 4 +--- .../issue-49851/compiler-builtins-error.rs | 2 -- .../compiler-builtins-error.stderr | 12 +--------- 5 files changed, 21 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 90e68a6b5b91..dcccace12b00 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -1077,7 +1077,7 @@ impl CrateError { crate_rejections, }); } else { - dcx.emit_err(errors::CannotFindCrate { + let error = errors::CannotFindCrate { span, crate_name, add_info, @@ -1091,11 +1091,18 @@ impl CrateError { profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: locator.triple, is_ui_testing: sess.opts.unstable_opts.ui_testing, - }); + }; + // The diagnostic for missing core is very good, but it is followed by a lot of + // other diagnostics that do not add information. + if missing_core { + dcx.emit_fatal(error); + } else { + dcx.emit_err(error); + } } } CrateError::NotFound(crate_name) => { - dcx.emit_err(errors::CannotFindCrate { + let error = errors::CannotFindCrate { span, crate_name, add_info: String::new(), @@ -1105,7 +1112,14 @@ impl CrateError { profiler_runtime: Symbol::intern(&sess.opts.unstable_opts.profiler_runtime), locator_triple: sess.opts.target_triple.clone(), is_ui_testing: sess.opts.unstable_opts.ui_testing, - }); + }; + // The diagnostic for missing core is very good, but it is followed by a lot of + // other diagnostics that do not add information. + if missing_core { + dcx.emit_fatal(error); + } else { + dcx.emit_err(error); + } } } } diff --git a/tests/ui/crate-loading/missing-std.stderr b/tests/ui/crate-loading/missing-std.stderr index 70bcae1e0edd..3eb6c2946d35 100644 --- a/tests/ui/crate-loading/missing-std.stderr +++ b/tests/ui/crate-loading/missing-std.stderr @@ -8,8 +8,6 @@ LL | extern crate core; = help: consider downloading the target with `rustup target add x86_64-unknown-uefi` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error: requires `sized` lang_item - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/issues/issue-37131.stderr b/tests/ui/issues/issue-37131.stderr index 9ecae3e7a2b2..588696f35418 100644 --- a/tests/ui/issues/issue-37131.stderr +++ b/tests/ui/issues/issue-37131.stderr @@ -4,8 +4,6 @@ error[E0463]: can't find crate for `std` = help: consider downloading the target with `rustup target add thumbv6m-none-eabi` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error: requires `sized` lang_item - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.rs b/tests/ui/issues/issue-49851/compiler-builtins-error.rs index 3b62cc73f93d..db45d040f791 100644 --- a/tests/ui/issues/issue-49851/compiler-builtins-error.rs +++ b/tests/ui/issues/issue-49851/compiler-builtins-error.rs @@ -1,5 +1,4 @@ //~ ERROR can't find crate for `core` -//~^ ERROR can't find crate for `compiler_builtins` //@ compile-flags: --target thumbv7em-none-eabihf //@ needs-llvm-components: arm @@ -8,6 +7,5 @@ #![no_std] extern crate cortex_m; -//~^ ERROR can't find crate for `cortex_m` fn main() {} diff --git a/tests/ui/issues/issue-49851/compiler-builtins-error.stderr b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr index fcfa2bf119cf..1cd65a1b68c8 100644 --- a/tests/ui/issues/issue-49851/compiler-builtins-error.stderr +++ b/tests/ui/issues/issue-49851/compiler-builtins-error.stderr @@ -4,16 +4,6 @@ error[E0463]: can't find crate for `core` = help: consider downloading the target with `rustup target add thumbv7em-none-eabihf` = help: consider building the standard library from source with `cargo build -Zbuild-std` -error[E0463]: can't find crate for `compiler_builtins` - -error[E0463]: can't find crate for `cortex_m` - --> $DIR/compiler-builtins-error.rs:10:1 - | -LL | extern crate cortex_m; - | ^^^^^^^^^^^^^^^^^^^^^^ can't find crate - -error: requires `sized` lang_item - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0463`. From bf9782dd9d14268d0c72ac13b24fa35c6a2e5a57 Mon Sep 17 00:00:00 2001 From: Jubilee Young Date: Wed, 6 Mar 2024 20:14:12 -0800 Subject: [PATCH 28/29] Fix tidy --bless on Windows --- src/tools/tidy/src/ui_tests.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index a9c5be913ba1..1a53637ad42f 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -190,7 +190,11 @@ pub fn check(path: &Path, bless: bool, bad: &mut bool) { let blessed_issues_path = tidy_src.join("issues_blessed.txt"); let mut blessed_issues_txt = fs::File::create(&blessed_issues_path).unwrap(); blessed_issues_txt.write(issues_txt_header.as_bytes()).unwrap(); - for filename in allowed_issue_names.difference(&remaining_issue_names) { + // If we changed paths to use the OS separator, reassert Unix chauvinism for blessing. + for filename in allowed_issue_names + .difference(&remaining_issue_names) + .map(|s| s.replace(std::path::MAIN_SEPARATOR_STR, "/")) + { write!(blessed_issues_txt, "\"{filename}\",\n").unwrap(); } write!(blessed_issues_txt, "]\n").unwrap(); From 1a2bc1102d9502a5058585f6422a974323a884a7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 6 Mar 2024 20:21:00 +0100 Subject: [PATCH 29/29] =?UTF-8?q?Rust=20is=20a=20proper=20name:=20rust=20?= =?UTF-8?q?=E2=86=92=20Rust?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/alloc/src/raw_vec.rs | 2 +- library/core/src/arch.rs | 8 ++++---- library/core/src/macros/mod.rs | 2 +- library/core/src/ptr/alignment.rs | 2 +- library/core/src/slice/mod.rs | 2 +- library/core/src/sync/exclusive.rs | 2 +- library/std/src/ffi/os_str.rs | 8 ++++---- library/std/src/lib.rs | 2 +- library/std/src/sys/pal/hermit/time.rs | 2 +- library/std/src/time.rs | 10 +++++----- library/test/src/formatters/terse.rs | 2 +- library/test/src/types.rs | 2 +- 12 files changed, 22 insertions(+), 22 deletions(-) diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec.rs index dd8d6f6c7e63..4d9694d4beba 100644 --- a/library/alloc/src/raw_vec.rs +++ b/library/alloc/src/raw_vec.rs @@ -259,7 +259,7 @@ impl RawVec { } else { // We could use Layout::array here which ensures the absence of isize and usize overflows // and could hypothetically handle differences between stride and size, but this memory - // has already been allocated so we know it can't overflow and currently rust does not + // has already been allocated so we know it can't overflow and currently Rust does not // support such types. So we can do better by skipping some checks and avoid an unwrap. const { assert!(mem::size_of::() % mem::align_of::() == 0) }; unsafe { diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 8817ec0777b6..31d6bc36fc8b 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -6,10 +6,10 @@ pub use crate::core_arch::arch::*; /// Inline assembly. /// -/// Refer to [rust by example] for a usage guide and the [reference] for +/// Refer to [Rust By Example] for a usage guide and the [reference] for /// detailed information about the syntax and available options. /// -/// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html #[stable(feature = "asm", since = "1.59.0")] #[rustc_builtin_macro] @@ -19,10 +19,10 @@ pub macro asm("assembly template", $(operands,)* $(options($(option),*))?) { /// Module-level inline assembly. /// -/// Refer to [rust by example] for a usage guide and the [reference] for +/// Refer to [Rust By Example] for a usage guide and the [reference] for /// detailed information about the syntax and available options. /// -/// [rust by example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html +/// [Rust By Example]: https://doc.rust-lang.org/nightly/rust-by-example/unsafe/asm.html /// [reference]: https://doc.rust-lang.org/nightly/reference/inline-assembly.html #[stable(feature = "global_asm", since = "1.59.0")] #[rustc_builtin_macro] diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs index 643968c35e84..0ee7e190e3d4 100644 --- a/library/core/src/macros/mod.rs +++ b/library/core/src/macros/mod.rs @@ -1481,7 +1481,7 @@ pub(crate) mod builtin { /// script](https://doc.rust-lang.org/cargo/reference/build-scripts.html#outputs-of-the-build-script). /// /// When using the `include` macro to include stretches of documentation, remember that the - /// included file still needs to be a valid rust syntax. It is also possible to + /// included file still needs to be a valid Rust syntax. It is also possible to /// use the [`include_str`] macro as `#![doc = include_str!("...")]` (at the module level) or /// `#[doc = include_str!("...")]` (at the item level) to include documentation from a plain /// text or markdown file. diff --git a/library/core/src/ptr/alignment.rs b/library/core/src/ptr/alignment.rs index 3eea065eef64..3508b0c7f238 100644 --- a/library/core/src/ptr/alignment.rs +++ b/library/core/src/ptr/alignment.rs @@ -3,7 +3,7 @@ use crate::num::NonZero; use crate::{cmp, fmt, hash, mem, num}; /// A type storing a `usize` which is a power of two, and thus -/// represents a possible alignment in the rust abstract machine. +/// represents a possible alignment in the Rust abstract machine. /// /// Note that particularly large alignments, while representable in this type, /// are likely not to be supported by actual allocators and linkers. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index aaedbed0d550..643b7971a662 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -23,7 +23,7 @@ use crate::slice; issue = "none", reason = "exposed from core to be reused in std; use the memchr crate" )] -/// Pure rust memchr implementation, taken from rust-memchr +/// Pure Rust memchr implementation, taken from rust-memchr pub mod memchr; #[unstable( diff --git a/library/core/src/sync/exclusive.rs b/library/core/src/sync/exclusive.rs index fa02dd52e002..e8170c13ed26 100644 --- a/library/core/src/sync/exclusive.rs +++ b/library/core/src/sync/exclusive.rs @@ -19,7 +19,7 @@ use core::task::{Context, Poll}; /// /// Certain constructs like [`Future`]s can only be used with _exclusive_ access, /// and are often `Send` but not `Sync`, so `Exclusive` can be used as hint to the -/// rust compiler that something is `Sync` in practice. +/// Rust compiler that something is `Sync` in practice. /// /// ## Examples /// Using a non-`Sync` future prevents the wrapping struct from being `Sync` diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index e44da8e637e9..8927e9a47fa8 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -157,7 +157,7 @@ impl OsString { /// # Safety /// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of - /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same rust version + /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version /// built for the same target platform. For example, reconstructing an `OsString` from bytes sent /// over the network or stored in a file will likely violate these safety rules. /// @@ -213,7 +213,7 @@ impl OsString { /// ASCII. /// /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should - /// be treated as opaque and only comparable within the same rust version built for the same + /// be treated as opaque and only comparable within the same Rust version built for the same /// target platform. For example, sending the bytes over the network or storing it in a file /// will likely result in incompatible data. See [`OsString`] for more encoding details /// and [`std::ffi`] for platform-specific, specified conversions. @@ -747,7 +747,7 @@ impl OsStr { /// # Safety /// /// As the encoding is unspecified, callers must pass in bytes that originated as a mixture of - /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same rust version + /// validated UTF-8 and bytes from [`OsStr::as_encoded_bytes`] from within the same Rust version /// built for the same target platform. For example, reconstructing an `OsStr` from bytes sent /// over the network or stored in a file will likely violate these safety rules. /// @@ -955,7 +955,7 @@ impl OsStr { /// ASCII. /// /// Note: As the encoding is unspecified, any sub-slice of bytes that is not valid UTF-8 should - /// be treated as opaque and only comparable within the same rust version built for the same + /// be treated as opaque and only comparable within the same Rust version built for the same /// target platform. For example, sending the slice over the network or storing it in a file /// will likely result in incompatible byte slices. See [`OsString`] for more encoding details /// and [`std::ffi`] for platform-specific, specified conversions. diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 288cce3aa085..55a5292a4a41 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -84,7 +84,7 @@ //! //! # Contributing changes to the documentation //! -//! Check out the rust contribution guidelines [here]( +//! Check out the Rust contribution guidelines [here]( //! https://rustc-dev-guide.rust-lang.org/contributing.html#writing-documentation). //! The source for this documentation can be found on //! [GitHub](https://github.com/rust-lang/rust). diff --git a/library/std/src/sys/pal/hermit/time.rs b/library/std/src/sys/pal/hermit/time.rs index f289dafd8bc5..319b835a7687 100644 --- a/library/std/src/sys/pal/hermit/time.rs +++ b/library/std/src/sys/pal/hermit/time.rs @@ -179,7 +179,7 @@ impl Sub for Instant { /// /// # Panics /// - /// Previous rust versions panicked when `other` was later than `self`. Currently this + /// Previous Rust versions panicked when `other` was later than `self`. Currently this /// method saturates. Future versions may reintroduce the panic in some circumstances. /// See [Monotonicity]. /// diff --git a/library/std/src/time.rs b/library/std/src/time.rs index 91c010ef2b5e..6f1a354d28a8 100644 --- a/library/std/src/time.rs +++ b/library/std/src/time.rs @@ -59,7 +59,7 @@ pub use core::time::TryFromFloatSecsError; /// experience time dilation (slow down or speed up), but it will never go /// backwards. /// As part of this non-guarantee it is also not specified whether system suspends count as -/// elapsed time or not. The behavior varies across platforms and rust versions. +/// elapsed time or not. The behavior varies across platforms and Rust versions. /// /// Instants are opaque types that can only be compared to one another. There is /// no method to get "the number of seconds" from an instant. Instead, it only @@ -142,7 +142,7 @@ pub use core::time::TryFromFloatSecsError; /// where monotonicity is violated, or `Instant`s are subtracted in the wrong order. /// /// This workaround obscures programming errors where earlier and later instants are accidentally -/// swapped. For this reason future rust versions may reintroduce panics. +/// swapped. For this reason future Rust versions may reintroduce panics. /// /// [tier 1]: https://doc.rust-lang.org/rustc/platform-support.html /// [`duration_since`]: Instant::duration_since @@ -290,7 +290,7 @@ impl Instant { /// /// # Panics /// - /// Previous rust versions panicked when `earlier` was later than `self`. Currently this + /// Previous Rust versions panicked when `earlier` was later than `self`. Currently this /// method saturates. Future versions may reintroduce the panic in some circumstances. /// See [Monotonicity]. /// @@ -365,7 +365,7 @@ impl Instant { /// /// # Panics /// - /// Previous rust versions panicked when the current time was earlier than self. Currently this + /// Previous Rust versions panicked when the current time was earlier than self. Currently this /// method returns a Duration of zero in that case. Future versions may reintroduce the panic. /// See [Monotonicity]. /// @@ -450,7 +450,7 @@ impl Sub for Instant { /// /// # Panics /// - /// Previous rust versions panicked when `other` was later than `self`. Currently this + /// Previous Rust versions panicked when `other` was later than `self`. Currently this /// method saturates. Future versions may reintroduce the panic in some circumstances. /// See [Monotonicity]. /// diff --git a/library/test/src/formatters/terse.rs b/library/test/src/formatters/terse.rs index 22c28e4954ef..875c66e5fa32 100644 --- a/library/test/src/formatters/terse.rs +++ b/library/test/src/formatters/terse.rs @@ -84,7 +84,7 @@ impl TerseFormatter { if self.test_column % QUIET_MODE_MAX_COLUMN == QUIET_MODE_MAX_COLUMN - 1 { // We insert a new line regularly in order to flush the // screen when dealing with line-buffered output (e.g., piping to - // `stamp` in the rust CI). + // `stamp` in the Rust CI). self.write_progress()?; } diff --git a/library/test/src/types.rs b/library/test/src/types.rs index 1a8ae889c8c1..6a7035a8e291 100644 --- a/library/test/src/types.rs +++ b/library/test/src/types.rs @@ -13,7 +13,7 @@ pub use NamePadding::*; pub use TestFn::*; pub use TestName::*; -/// Type of the test according to the [rust book](https://doc.rust-lang.org/cargo/guide/tests.html) +/// Type of the test according to the [Rust book](https://doc.rust-lang.org/cargo/guide/tests.html) /// conventions. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum TestType {