diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 51d262a881b8c..2beb5e0ab5d20 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -414,7 +414,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { let typeck_root_def_id = self.infcx.tcx.typeck_root_def_id(self.mir_def.did.to_def_id()); - // If this is is a 'root' body (not a closure/generator/inline const), then + // If this is a 'root' body (not a closure/generator/inline const), then // there are no extern regions, so the local regions start at the same // position as the (empty) sub-list of extern regions let first_local_index = if self.mir_def.did.to_def_id() == typeck_root_def_id { diff --git a/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs index 913b589afcc87..3c08b6fa3894d 100644 --- a/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs +++ b/compiler/rustc_codegen_cranelift/build_system/rustc_info.rs @@ -65,7 +65,7 @@ pub(crate) fn get_file_name(crate_name: &str, crate_type: &str) -> String { } /// Similar to `get_file_name`, but converts any dashes (`-`) in the `crate_name` to -/// underscores (`_`). This is specially made for the the rustc and cargo wrappers +/// underscores (`_`). This is specially made for the rustc and cargo wrappers /// which have a dash in the name, and that is not allowed in a crate name. pub(crate) fn get_wrapper_file_name(crate_name: &str, crate_type: &str) -> String { let crate_name = crate_name.replace('-', "_"); diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs index 96e25d3a8d4c9..e5ad31eb9484a 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs @@ -193,7 +193,7 @@ pub(super) fn from_casted_value<'tcx>( kind: StackSlotKind::ExplicitSlot, // FIXME Don't force the size to a multiple of 16 bytes once Cranelift gets a way to // specify stack slot alignment. - // Stack slot size may be bigger for for example `[u8; 3]` which is packed into an `i32`. + // Stack slot size may be bigger for example `[u8; 3]` which is packed into an `i32`. // It may also be smaller for example when the type is a wrapper around an integer with a // larger alignment than the integer. size: (std::cmp::max(abi_param_size, layout_size) + 15) / 16 * 16, diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index cef7bf1e8034d..a49cc7f8d662d 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -32,8 +32,8 @@ pub const THIN_LTO_KEYS_INCR_COMP_FILE_NAME: &str = "thin-lto-past-keys.bin"; pub fn crate_type_allows_lto(crate_type: CrateType) -> bool { match crate_type { - CrateType::Executable | CrateType::Staticlib | CrateType::Cdylib => true, - CrateType::Dylib | CrateType::Rlib | CrateType::ProcMacro => false, + CrateType::Executable | CrateType::Dylib | CrateType::Staticlib | CrateType::Cdylib => true, + CrateType::Rlib | CrateType::ProcMacro => false, } } @@ -73,17 +73,6 @@ fn prepare_lto( // with either fat or thin LTO let mut upstream_modules = Vec::new(); if cgcx.lto != Lto::ThinLocal { - if cgcx.opts.cg.prefer_dynamic { - diag_handler - .struct_err("cannot prefer dynamic linking when performing LTO") - .note( - "only 'staticlib', 'bin', and 'cdylib' outputs are \ - supported with LTO", - ) - .emit(); - return Err(FatalError); - } - // Make sure we actually can run LTO for crate_type in cgcx.crate_types.iter() { if !crate_type_allows_lto(*crate_type) { @@ -92,9 +81,25 @@ fn prepare_lto( static library outputs", ); return Err(e); + } else if *crate_type == CrateType::Dylib { + if !cgcx.opts.unstable_opts.dylib_lto { + return Err(diag_handler + .fatal("lto cannot be used for `dylib` crate type without `-Zdylib-lto`")); + } } } + if cgcx.opts.cg.prefer_dynamic && !cgcx.opts.unstable_opts.dylib_lto { + diag_handler + .struct_err("cannot prefer dynamic linking when performing LTO") + .note( + "only 'staticlib', 'bin', and 'cdylib' outputs are \ + supported with LTO", + ) + .emit(); + return Err(FatalError); + } + for &(cnum, ref path) in cgcx.each_linked_rlib_for_lto.iter() { let exported_symbols = cgcx.exported_symbols.as_ref().expect("needs exported symbols for LTO"); diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index db526746fa70a..11053a8f6c452 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -537,7 +537,7 @@ pub(crate) fn link( mut modules: Vec>, ) -> Result, FatalError> { use super::lto::{Linker, ModuleBuffer}; - // Sort the modules by name to ensure to ensure deterministic behavior. + // Sort the modules by name to ensure deterministic behavior. modules.sort_by(|a, b| a.name.cmp(&b.name)); let (first, elements) = modules.split_first().expect("Bug! modules must contain at least one module."); diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 0d1df6fb1acd9..433f043209e53 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -129,7 +129,7 @@ impl CoverageMapGenerator { // LLVM Coverage Mapping Format version 6 (zero-based encoded as 5) // requires setting the first filename to the compilation directory. // Since rustc generates coverage maps with relative paths, the - // compilation directory can be combined with the the relative paths + // compilation directory can be combined with the relative paths // to get absolute paths, if needed. let working_dir = tcx .sess diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 95e72184ff037..9cb706e5e7037 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -11,7 +11,7 @@ use rustc_metadata::find_native_static_library; use rustc_metadata::fs::{emit_metadata, METADATA_FILENAME}; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::SymbolExportKind; -use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Strip}; +use rustc_session::config::{self, CFGuard, CrateType, DebugInfo, LdImpl, Lto, Strip}; use rustc_session::config::{OutputFilenames, OutputType, PrintRequest, SplitDwarfKind}; use rustc_session::cstore::DllImport; use rustc_session::output::{check_file_is_writeable, invalid_output_for_target, out_filename}; @@ -39,6 +39,7 @@ use cc::windows_registry; use regex::Regex; use tempfile::Builder as TempFileBuilder; +use itertools::Itertools; use std::borrow::Borrow; use std::cell::OnceCell; use std::collections::BTreeSet; @@ -208,11 +209,26 @@ pub fn link_binary<'a>( } pub fn each_linked_rlib( + sess: &Session, info: &CrateInfo, f: &mut dyn FnMut(CrateNum, &Path), ) -> Result<(), errors::LinkRlibError> { let crates = info.used_crates.iter(); let mut fmts = None; + + let lto_active = matches!(sess.lto(), Lto::Fat | Lto::Thin); + if lto_active { + for combination in info.dependency_formats.iter().combinations(2) { + let (ty1, list1) = combination[0]; + let (ty2, list2) = combination[1]; + if list1 != list2 { + return Err(format!( + "{ty1:?} and {ty2:?} do not have equivalent dependency formats (`{list1:?}` vs `{list2:?}`)" + )); + } + } + } + for (ty, list) in info.dependency_formats.iter() { match ty { CrateType::Executable @@ -222,6 +238,10 @@ pub fn each_linked_rlib( fmts = Some(list); break; } + CrateType::Dylib if lto_active => { + fmts = Some(list); + break; + } _ => {} } } @@ -490,7 +510,7 @@ fn link_staticlib<'a>( )?; let mut all_native_libs = vec![]; - let res = each_linked_rlib(&codegen_results.crate_info, &mut |cnum, path| { + let res = each_linked_rlib(sess, &codegen_results.crate_info, &mut |cnum, path| { let name = codegen_results.crate_info.crate_name[&cnum]; let native_libs = &codegen_results.crate_info.native_libraries[&cnum]; diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index 8d7e2c5cf3939..7f97261054cf3 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -13,7 +13,7 @@ use rustc_middle::ty::query::{ExternProviders, Providers}; use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::Instance; use rustc_middle::ty::{self, SymbolName, TyCtxt}; -use rustc_session::config::CrateType; +use rustc_session::config::{CrateType, OomStrategy}; use rustc_target::spec::SanitizerSet; pub fn threshold(tcx: TyCtxt<'_>) -> SymbolExportLevel { @@ -206,6 +206,15 @@ fn exported_symbols_provider_local<'tcx>( }, )); } + + symbols.push(( + ExportedSymbol::NoDefId(SymbolName::new(tcx, OomStrategy::SYMBOL)), + SymbolExportInfo { + level: SymbolExportLevel::Rust, + kind: SymbolExportKind::Text, + used: false, + }, + )); } if tcx.sess.instrument_coverage() || tcx.sess.opts.cg.profile_generate.enabled() { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index a292bfce31eb8..d0ac016b02e15 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -999,6 +999,14 @@ fn start_executing_work( let coordinator_send = tx_to_llvm_workers; let sess = tcx.sess; + let mut each_linked_rlib_for_lto = Vec::new(); + drop(link::each_linked_rlib(sess, crate_info, &mut |cnum, path| { + if link::ignored_for_lto(sess, crate_info, cnum) { + return; + } + each_linked_rlib_for_lto.push((cnum, path.to_path_buf())); + })); + // Compute the set of symbols we need to retain when doing LTO (if we need to) let exported_symbols = { let mut exported_symbols = FxHashMap::default(); @@ -1020,7 +1028,7 @@ fn start_executing_work( } Lto::Fat | Lto::Thin => { exported_symbols.insert(LOCAL_CRATE, copy_symbols(LOCAL_CRATE)); - for &cnum in tcx.crates(()).iter() { + for &(cnum, ref _path) in &each_linked_rlib_for_lto { exported_symbols.insert(cnum, copy_symbols(cnum)); } Some(Arc::new(exported_symbols)) @@ -1040,14 +1048,6 @@ fn start_executing_work( }) .expect("failed to spawn helper thread"); - let mut each_linked_rlib_for_lto = Vec::new(); - drop(link::each_linked_rlib(crate_info, &mut |cnum, path| { - if link::ignored_for_lto(sess, crate_info, cnum) { - return; - } - each_linked_rlib_for_lto.push((cnum, path.to_path_buf())); - })); - let ol = if tcx.sess.opts.unstable_opts.no_codegen || !tcx.sess.opts.output_types.should_codegen() { // If we know that we won’t be doing codegen, create target machines without optimisation. diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 136bfbeaad2f0..4977a5d6bbf05 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -64,7 +64,7 @@ pub struct ConstEvalErr<'tcx> { impl<'tcx> ConstEvalErr<'tcx> { /// Turn an interpreter error into something to report to the user. /// As a side-effect, if RUSTC_CTFE_BACKTRACE is set, this prints the backtrace. - /// Should be called only if the error is actually going to to be reported! + /// Should be called only if the error is actually going to be reported! pub fn new<'mir, M: Machine<'mir, 'tcx>>( ecx: &InterpCx<'mir, 'tcx, M>, error: InterpErrorInfo<'tcx>, diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index ed155fbfef087..e5e015c1e1802 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -794,7 +794,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { todo.extend(static_roots); while let Some(id) = todo.pop() { if reachable.insert(id) { - // This is a new allocation, add the allocation it points to to `todo`. + // This is a new allocation, add the allocation it points to `todo`. if let Some((_, alloc)) = self.memory.alloc_map.get(id) { todo.extend( alloc.provenance().values().filter_map(|prov| prov.get_alloc_id()), diff --git a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs index 3d91bcade59a4..e8efbd09a2c38 100644 --- a/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs +++ b/compiler/rustc_data_structures/src/graph/vec_graph/mod.rs @@ -29,8 +29,8 @@ impl VecGraph { // Store the *target* of each edge into `edge_targets`. let edge_targets: Vec = edge_pairs.iter().map(|&(_, target)| target).collect(); - // Create the *edge starts* array. We are iterating over over - // the (sorted) edge pairs. We maintain the invariant that the + // Create the *edge starts* array. We are iterating over the + // (sorted) edge pairs. We maintain the invariant that the // length of the `node_starts` array is enough to store the // current source node -- so when we see that the source node // for an edge is greater than the current length, we grow the diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index c2add852a0679..59f434b941e78 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -327,7 +327,7 @@ impl InvocationKind { fn placeholder_visibility(&self) -> Option { // HACK: For unnamed fields placeholders should have the same visibility as the actual // fields because for tuple structs/variants resolve determines visibilities of their - // constructor using these field visibilities before attributes on them are are expanded. + // constructor using these field visibilities before attributes on them are expanded. // The assumption is that the attribute expansion cannot change field visibilities, // and it holds because only inert attributes are supported in this position. match self { diff --git a/compiler/rustc_hir_analysis/src/check/fallback.rs b/compiler/rustc_hir_analysis/src/check/fallback.rs index 4059b3403b19f..474d5651bbe2f 100644 --- a/compiler/rustc_hir_analysis/src/check/fallback.rs +++ b/compiler/rustc_hir_analysis/src/check/fallback.rs @@ -72,7 +72,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // // - Unconstrained ints are replaced with `i32`. // - // - Unconstrained floats are replaced with with `f64`. + // - Unconstrained floats are replaced with `f64`. // // - Non-numerics may get replaced with `()` or `!`, depending on // how they were categorized by `calculate_diverging_fallback` diff --git a/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_build.rs b/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_build.rs index 016f4056bd903..122ad7009cb49 100644 --- a/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_build.rs +++ b/compiler/rustc_hir_analysis/src/check/generator_interior/drop_ranges/cfg_build.rs @@ -210,7 +210,7 @@ impl<'a, 'tcx> DropRangeVisitor<'a, 'tcx> { } /// For an expression with an uninhabited return type (e.g. a function that returns !), - /// this adds a self edge to to the CFG to model the fact that the function does not + /// this adds a self edge to the CFG to model the fact that the function does not /// return. fn handle_uninhabited_return(&mut self, expr: &Expr<'tcx>) { let ty = self.typeck_results.expr_ty(expr); diff --git a/compiler/rustc_hir_analysis/src/check/upvar.rs b/compiler/rustc_hir_analysis/src/check/upvar.rs index 4f49564169173..4dea40829f622 100644 --- a/compiler/rustc_hir_analysis/src/check/upvar.rs +++ b/compiler/rustc_hir_analysis/src/check/upvar.rs @@ -352,7 +352,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// and that the path can be captured with required capture kind (depending on use in closure, /// move closure etc.) /// - /// Returns the set of of adjusted information along with the inferred closure kind and span + /// Returns the set of adjusted information along with the inferred closure kind and span /// associated with the closure kind inference. /// /// Note that we *always* infer a minimal kind, even if diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 03e076bf5ec89..c634a57b0b534 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -58,6 +58,37 @@ impl<'tcx> InherentOverlapChecker<'tcx> { == item2.ident(self.tcx).normalize_to_macros_2_0() } + fn check_for_duplicate_items_in_impl(&self, impl_: DefId) { + let impl_items = self.tcx.associated_items(impl_); + + let mut seen_items = FxHashMap::default(); + for impl_item in impl_items.in_definition_order() { + let span = self.tcx.def_span(impl_item.def_id); + let ident = impl_item.ident(self.tcx); + + let norm_ident = ident.normalize_to_macros_2_0(); + match seen_items.entry(norm_ident) { + Entry::Occupied(entry) => { + let former = entry.get(); + let mut err = struct_span_err!( + self.tcx.sess, + span, + E0592, + "duplicate definitions with name `{}`", + ident, + ); + err.span_label(span, format!("duplicate definitions for `{}`", ident)); + err.span_label(*former, format!("other definition for `{}`", ident)); + + err.emit(); + } + Entry::Vacant(entry) => { + entry.insert(span); + } + } + } + } + fn check_for_common_items_in_impls( &self, impl1: DefId, @@ -133,12 +164,6 @@ impl<'tcx> InherentOverlapChecker<'tcx> { let impls = self.tcx.inherent_impls(id.def_id); - // If there is only one inherent impl block, - // there is nothing to overlap check it with - if impls.len() <= 1 { - return; - } - let overlap_mode = OverlapMode::get(self.tcx, id.def_id.to_def_id()); let impls_items = impls @@ -152,6 +177,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> { const ALLOCATING_ALGO_THRESHOLD: usize = 500; if impls.len() < ALLOCATING_ALGO_THRESHOLD { for (i, &(&impl1_def_id, impl_items1)) in impls_items.iter().enumerate() { + self.check_for_duplicate_items_in_impl(impl1_def_id); + for &(&impl2_def_id, impl_items2) in &impls_items[(i + 1)..] { if self.impls_have_common_items(impl_items1, impl_items2) { self.check_for_overlapping_inherent_impls( @@ -290,6 +317,8 @@ impl<'tcx> InherentOverlapChecker<'tcx> { impl_blocks.sort_unstable(); for (i, &impl1_items_idx) in impl_blocks.iter().enumerate() { let &(&impl1_def_id, impl_items1) = &impls_items[impl1_items_idx]; + self.check_for_duplicate_items_in_impl(impl1_def_id); + for &impl2_items_idx in impl_blocks[(i + 1)..].iter() { let &(&impl2_def_id, impl_items2) = &impls_items[impl2_items_idx]; if self.impls_have_common_items(impl_items1, impl_items2) { diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index 69155a422b062..a84257b939c52 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -11,7 +11,7 @@ use crate::constrained_generic_params as cgp; use min_specialization::check_min_specialization; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_errors::struct_span_err; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; @@ -19,8 +19,6 @@ use rustc_middle::ty::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitable}; use rustc_span::{Span, Symbol}; -use std::collections::hash_map::Entry::{Occupied, Vacant}; - mod min_specialization; /// Checks that all the type/lifetime parameters on an impl also @@ -59,7 +57,6 @@ fn check_mod_impl_wf(tcx: TyCtxt<'_>, module_def_id: LocalDefId) { for id in module.items() { if matches!(tcx.def_kind(id.def_id), DefKind::Impl) { enforce_impl_params_are_constrained(tcx, id.def_id.def_id); - enforce_impl_items_are_distinct(tcx, id.def_id.def_id); if min_specialization { check_min_specialization(tcx, id.def_id.def_id); } @@ -194,38 +191,3 @@ fn report_unused_parameter(tcx: TyCtxt<'_>, span: Span, kind: &str, name: Symbol } err.emit(); } - -/// Enforce that we do not have two items in an impl with the same name. -fn enforce_impl_items_are_distinct(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) { - if tcx.impl_trait_ref(impl_def_id).is_some() { - return; - } - let mut seen_type_items = FxHashMap::default(); - let mut seen_value_items = FxHashMap::default(); - for &impl_item_ref in tcx.associated_item_def_ids(impl_def_id) { - let impl_item = tcx.associated_item(impl_item_ref); - let seen_items = match impl_item.kind { - ty::AssocKind::Type => &mut seen_type_items, - _ => &mut seen_value_items, - }; - let span = tcx.def_span(impl_item_ref); - let ident = impl_item.ident(tcx); - match seen_items.entry(ident.normalize_to_macros_2_0()) { - Occupied(entry) => { - let mut err = struct_span_err!( - tcx.sess, - span, - E0201, - "duplicate definitions with name `{}`:", - ident - ); - err.span_label(*entry.get(), format!("previous definition of `{}` here", ident)); - err.span_label(span, "duplicate definition"); - err.emit(); - } - Vacant(entry) => { - entry.insert(span); - } - } - } -} diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 5a5e9db81a243..167ef2791040a 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1150,8 +1150,8 @@ impl<'tcx> InferCtxt<'tcx> { /// Return the universe that the region `r` was created in. For /// most regions (e.g., `'static`, named regions from the user, /// etc) this is the root universe U0. For inference variables or - /// placeholders, however, it will return the universe which which - /// they are associated. + /// placeholders, however, it will return the universe which they + /// are associated. pub fn universe_of_region(&self, r: ty::Region<'tcx>) -> ty::UniverseIndex { self.inner.borrow_mut().unwrap_region_constraints().universe(r) } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 949bd02ad6839..a697f8071b4b3 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -276,59 +276,6 @@ pub struct Config { pub registry: Registry, } -pub fn create_compiler_and_run(config: Config, f: impl FnOnce(&Compiler) -> R) -> R { - crate::callbacks::setup_callbacks(); - - let registry = &config.registry; - let (mut sess, codegen_backend) = util::create_session( - config.opts, - config.crate_cfg, - config.crate_check_cfg, - config.diagnostic_output, - config.file_loader, - config.input_path.clone(), - config.lint_caps, - config.make_codegen_backend, - registry.clone(), - ); - - if let Some(parse_sess_created) = config.parse_sess_created { - parse_sess_created( - &mut Lrc::get_mut(&mut sess) - .expect("create_session() should never share the returned session") - .parse_sess, - ); - } - - let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o)); - - let compiler = Compiler { - sess, - codegen_backend, - input: config.input, - input_path: config.input_path, - output_dir: config.output_dir, - output_file: config.output_file, - temps_dir, - register_lints: config.register_lints, - override_queries: config.override_queries, - }; - - rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || { - let r = { - let _sess_abort_error = OnDrop(|| { - compiler.sess.finish_diagnostics(registry); - }); - - f(&compiler) - }; - - let prof = compiler.sess.prof.clone(); - prof.generic_activity("drop_compiler").run(move || drop(compiler)); - r - }) -} - // JUSTIFICATION: before session exists, only config #[allow(rustc::bad_opt_access)] pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Send) -> R { @@ -336,7 +283,54 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se util::run_in_thread_pool_with_globals( config.opts.edition, config.opts.unstable_opts.threads, - || create_compiler_and_run(config, f), + || { + crate::callbacks::setup_callbacks(); + + let registry = &config.registry; + let (mut sess, codegen_backend) = util::create_session( + config.opts, + config.crate_cfg, + config.crate_check_cfg, + config.diagnostic_output, + config.file_loader, + config.input_path.clone(), + config.lint_caps, + config.make_codegen_backend, + registry.clone(), + ); + + if let Some(parse_sess_created) = config.parse_sess_created { + parse_sess_created(&mut sess.parse_sess); + } + + let temps_dir = sess.opts.unstable_opts.temps_dir.as_ref().map(|o| PathBuf::from(&o)); + + let compiler = Compiler { + sess: Lrc::new(sess), + codegen_backend: Lrc::new(codegen_backend), + input: config.input, + input_path: config.input_path, + output_dir: config.output_dir, + output_file: config.output_file, + temps_dir, + register_lints: config.register_lints, + override_queries: config.override_queries, + }; + + rustc_span::with_source_map(compiler.sess.parse_sess.clone_source_map(), move || { + let r = { + let _sess_abort_error = OnDrop(|| { + compiler.sess.finish_diagnostics(registry); + }); + + f(&compiler) + }; + + let prof = compiler.sess.prof.clone(); + prof.generic_activity("drop_compiler").run(move || drop(compiler)); + r + }) + }, ) } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index d64cdcdbaa9db..932ba59e94d92 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -657,6 +657,7 @@ fn test_unstable_options_tracking_hash() { untracked!(dump_mir_dir, String::from("abc")); untracked!(dump_mir_exclude_pass_number, true); untracked!(dump_mir_graphviz, true); + untracked!(dylib_lto, true); untracked!(emit_stack_sizes, true); untracked!(future_incompat_test, true); untracked!(hir_stats, true); diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index f7e70d355cf86..1bbfb9a415699 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -5,7 +5,6 @@ use rustc_codegen_ssa::traits::CodegenBackend; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[cfg(parallel_compiler)] use rustc_data_structures::jobserver; -use rustc_data_structures::sync::Lrc; use rustc_errors::registry::Registry; #[cfg(parallel_compiler)] use rustc_middle::ty::tls; @@ -73,7 +72,7 @@ pub fn create_session( Box Box + Send>, >, descriptions: Registry, -) -> (Lrc, Lrc>) { +) -> (Session, Box) { let codegen_backend = if let Some(make_codegen_backend) = make_codegen_backend { make_codegen_backend(&sopts) } else { @@ -121,7 +120,7 @@ pub fn create_session( sess.parse_sess.config = cfg; sess.parse_sess.check_config = check_cfg; - (Lrc::new(sess), Lrc::new(codegen_backend)) + (sess, codegen_backend) } const STACK_SIZE: usize = 8 * 1024 * 1024; @@ -132,33 +131,31 @@ fn get_stack_size() -> Option { env::var_os("RUST_MIN_STACK").is_none().then_some(STACK_SIZE) } -/// Like a `thread::Builder::spawn` followed by a `join()`, but avoids the need -/// for `'static` bounds. #[cfg(not(parallel_compiler))] -fn scoped_thread R + Send, R: Send>(cfg: thread::Builder, f: F) -> R { - // SAFETY: join() is called immediately, so any closure captures are still - // alive. - match unsafe { cfg.spawn_unchecked(f) }.unwrap().join() { - Ok(v) => v, - Err(e) => panic::resume_unwind(e), - } -} - -#[cfg(not(parallel_compiler))] -pub fn run_in_thread_pool_with_globals R + Send, R: Send>( +pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( edition: Edition, _threads: usize, f: F, ) -> R { - let mut cfg = thread::Builder::new().name("rustc".to_string()); - - if let Some(size) = get_stack_size() { - cfg = cfg.stack_size(size); - } + // The thread pool is a single thread in the non-parallel compiler. + thread::scope(|s| { + let mut builder = thread::Builder::new().name("rustc".to_string()); + if let Some(size) = get_stack_size() { + builder = builder.stack_size(size); + } - let main_handler = move || rustc_span::create_session_globals_then(edition, f); + // `unwrap` is ok here because `spawn_scoped` only panics if the thread + // name contains null bytes. + let r = builder + .spawn_scoped(s, move || rustc_span::create_session_globals_then(edition, f)) + .unwrap() + .join(); - scoped_thread(cfg, main_handler) + match r { + Ok(v) => v, + Err(e) => panic::resume_unwind(e), + } + }) } /// Creates a new thread and forwards information in thread locals to it. @@ -177,7 +174,7 @@ unsafe fn handle_deadlock() { } #[cfg(parallel_compiler)] -pub fn run_in_thread_pool_with_globals R + Send, R: Send>( +pub(crate) fn run_in_thread_pool_with_globals R + Send, R: Send>( edition: Edition, threads: usize, f: F, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index f28cfbd8b4c46..886e25f2d788b 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -3310,7 +3310,7 @@ declare_lint! { /// explicitly. /// /// To access a library from a binary target within the same crate, - /// use `your_crate_name::` as the path path instead of `lib::`: + /// use `your_crate_name::` as the path instead of `lib::`: /// /// ```rust,compile_fail /// // bar/src/lib.rs diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 4e30aa5eaba8a..8390d80a458cf 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3937,7 +3937,7 @@ declare_lint! { /// /// The compiler disables the automatic implementation if an explicit one /// exists for given type constructor. The exact rules governing this - /// are currently unsound and quite subtle and and will be modified in the future. + /// are currently unsound, quite subtle, and will be modified in the future. /// This change will cause the automatic implementation to be disabled in more /// cases, potentially breaking some code. pub SUSPICIOUS_AUTO_TRAIT_IMPLS, diff --git a/compiler/rustc_middle/src/mir/interpret/pointer.rs b/compiler/rustc_middle/src/mir/interpret/pointer.rs index 95e52e391d8f8..23c2ce6474c5a 100644 --- a/compiler/rustc_middle/src/mir/interpret/pointer.rs +++ b/compiler/rustc_middle/src/mir/interpret/pointer.rs @@ -43,7 +43,7 @@ pub trait PointerArithmetic: HasDataLayout { let val = val as i64; // Now wrap-around into the machine_isize range. if val > self.machine_isize_max() { - // This can only happen the the ptr size is < 64, so we know max_usize_plus_1 fits into + // This can only happen if the ptr size is < 64, so we know max_usize_plus_1 fits into // i64. debug_assert!(self.pointer_size().bits() < 64); let max_usize_plus_1 = 1u128 << self.pointer_size().bits(); diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index e4234442faef5..ce4a46e362d80 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -13,8 +13,7 @@ //! //! There are three groups of traits involved in each traversal. //! - `TypeFoldable`. This is implemented once for many types, including: -//! - Types of interest, for which the the methods delegate to the -//! folder. +//! - Types of interest, for which the methods delegate to the folder. //! - All other types, including generic containers like `Vec` and `Option`. //! It defines a "skeleton" of how they should be folded. //! - `TypeSuperFoldable`. This is implemented only for each type of interest, diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 713f9067a85e2..f73d062ba30a6 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -958,7 +958,7 @@ impl<'tcx> Ty<'tcx> { } } - /// Checks if `ty` has has a significant drop. + /// Checks if `ty` has a significant drop. /// /// Note that this method can return false even if `ty` has a destructor /// attached; even if that is the case then the adt has been marked with diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs index 44efb93a53bfc..6e1991b527fe3 100644 --- a/compiler/rustc_middle/src/ty/visit.rs +++ b/compiler/rustc_middle/src/ty/visit.rs @@ -10,8 +10,7 @@ //! //! There are three groups of traits involved in each traversal. //! - `TypeVisitable`. This is implemented once for many types, including: -//! - Types of interest, for which the the methods delegate to the -//! visitor. +//! - Types of interest, for which the methods delegate to the visitor. //! - All other types, including generic containers like `Vec` and `Option`. //! It defines a "skeleton" of how they should be visited. //! - `TypeSuperVisitable`. This is implemented only for each type of interest, diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index ec709a1db513e..5984c800d8381 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -370,8 +370,12 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { // Check if the let source is while, for there is no alternative place to put a prefix, // and we shouldn't lint. + // For let guards inside a match, prefixes might use bindings of the match pattern, + // so can't always be moved out. + // FIXME: Add checking whether the bindings are actually used in the prefix, + // and lint if they are not. let let_source = let_source_parent(self.tcx, top, None); - if !matches!(let_source, LetSource::WhileLet) { + if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) { // Emit the lint let prefix = &chain_refutabilities[..until]; lint_affix(prefix, "leading", "outside of the construct"); @@ -1151,10 +1155,14 @@ fn let_source_parent(tcx: TyCtxt<'_>, parent: HirId, pat_id: Option) -> L let parent_parent = hir.get_parent_node(parent); let parent_parent_node = hir.get(parent_parent); - if let hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(_), span, .. }) = - parent_parent_node - { - return LetSource::LetElse(*span); + match parent_parent_node { + hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(_), span, .. }) => { + return LetSource::LetElse(*span); + } + hir::Node::Arm(hir::Arm { guard: Some(hir::Guard::If(_)), .. }) => { + return LetSource::IfLetGuard; + } + _ => {} } let parent_parent_parent = hir.get_parent_node(parent_parent); diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index f127907284425..8dc9976eaea8a 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -885,7 +885,7 @@ fn is_useful<'p, 'tcx>( // that has the potential to trigger the `non_exhaustive_omitted_patterns` lint. // To understand the workings checkout `Constructor::split` and `SplitWildcard::new/into_ctors` if is_non_exhaustive_and_wild - // We check that the match has a wildcard pattern and that that wildcard is useful, + // We check that the match has a wildcard pattern and that wildcard is useful, // meaning there are variants that are covered by the wildcard. Without the check // for `witness_preference` the lint would trigger on `if let NonExhaustiveEnum::A = foo {}` && usefulness.is_useful() && matches!(witness_preference, RealArm) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f57bd9cec1920..828b7d2f2f7be 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2232,7 +2232,7 @@ impl<'a> Parser<'a> { /// /// When encountering code like `foo::< bar + 3 >` or `foo::< bar - baz >` we suggest /// `foo::<{ bar + 3 }>` and `foo::<{ bar - baz }>`, respectively. We only provide a suggestion - /// if we think that that the resulting expression would be well formed. + /// if we think that the resulting expression would be well formed. pub fn recover_const_arg( &mut self, start: Span, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 73fb89bbc385e..dab8ae4777952 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -268,7 +268,7 @@ impl CheckAttrVisitor<'_> { } // FIXME(#65833): We permit associated consts to have an `#[inline]` attribute with // just a lint, because we previously erroneously allowed it and some crates used it - // accidentally, to to be compatible with crates depending on them, we can't throw an + // accidentally, to be compatible with crates depending on them, we can't throw an // error here. Target::AssocConst => { self.tcx.emit_spanned_lint( @@ -376,7 +376,7 @@ impl CheckAttrVisitor<'_> { | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true, // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[allow_internal_unstable]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "naked"); @@ -456,7 +456,7 @@ impl CheckAttrVisitor<'_> { Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => true, // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[track_caller]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { for attr in attrs { @@ -485,7 +485,7 @@ impl CheckAttrVisitor<'_> { Target::Struct | Target::Enum | Target::Variant => true, // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[non_exhaustive]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "non_exhaustive"); @@ -507,7 +507,7 @@ impl CheckAttrVisitor<'_> { Target::Trait => true, // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[marker]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "marker"); @@ -566,7 +566,7 @@ impl CheckAttrVisitor<'_> { } // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[target_feature]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "target_feature"); @@ -1205,7 +1205,7 @@ impl CheckAttrVisitor<'_> { Target::Fn | Target::Method(..) | Target::ForeignFn | Target::Closure => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[cold]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "cold"); @@ -1247,7 +1247,7 @@ impl CheckAttrVisitor<'_> { Target::ForeignFn | Target::ForeignStatic => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[link_name]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "link_name"); @@ -1281,7 +1281,7 @@ impl CheckAttrVisitor<'_> { Target::ExternCrate => true, // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[no_link]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_link"); @@ -1311,7 +1311,7 @@ impl CheckAttrVisitor<'_> { Target::Method(..) if self.is_impl_item(hir_id) => true, // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[export_name]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "export_name"); @@ -1503,7 +1503,7 @@ impl CheckAttrVisitor<'_> { Target::Static | Target::Fn | Target::Method(..) => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[link_section]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "link_section"); @@ -1528,7 +1528,7 @@ impl CheckAttrVisitor<'_> { Target::Method(..) if self.is_impl_item(hir_id) => {} // FIXME(#80564): We permit struct fields, match arms and macro defs to have an // `#[no_mangle]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "no_mangle"); @@ -1782,7 +1782,7 @@ impl CheckAttrVisitor<'_> { Target::MacroDef => true, // FIXME(#80564): We permit struct fields and match arms to have an // `#[allow_internal_unstable]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm => { self.inline_attr_str_error_without_macro_def( @@ -1877,7 +1877,7 @@ impl CheckAttrVisitor<'_> { } // FIXME(#80564): We permit struct fields and match arms to have an // `#[allow_internal_unstable]` attribute with just a lint, because we previously - // erroneously allowed it and some crates used it accidentally, to to be compatible + // erroneously allowed it and some crates used it accidentally, to be compatible // with crates depending on them, we can't throw an error here. Target::Field | Target::Arm | Target::MacroDef => { self.inline_attr_str_error_with_macro_def(hir_id, attr, "allow_internal_unstable"); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 971cd62831d47..1c1976af5054c 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2060,7 +2060,7 @@ struct Finalize { /// Span of the whole path or some its characteristic fragment. /// E.g. span of `b` in `foo::{a, b, c}`, or full span for regular paths. path_span: Span, - /// Span of the path start, suitable for prepending something to to it. + /// Span of the path start, suitable for prepending something to it. /// E.g. span of `foo` in `foo::{a, b, c}`, or full span for regular paths. root_span: Span, /// Whether to report privacy errors or silently return "no resolution" for them, diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 102df3a4d7ead..3f234a47a3d86 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -186,7 +186,7 @@ top_level_options!( /// Remap source path prefixes in all output (messages, object files, debug, etc.). remap_path_prefix: Vec<(PathBuf, PathBuf)> [TRACKED_NO_CRATE_HASH], /// Base directory containing the `src/` for the Rust standard library, and - /// potentially `rustc` as well, if we can can find it. Right now it's always + /// potentially `rustc` as well, if we can find it. Right now it's always /// `$sysroot/lib/rustlib/src/rust` (i.e. the `rustup` `rust-src` component). /// /// This directory is what the virtual `/rustc/$hash` is translated back to, @@ -1295,6 +1295,8 @@ options! { an additional `.html` file showing the computed coverage spans."), dwarf_version: Option = (None, parse_opt_number, [TRACKED], "version of DWARF debug information to emit (default: 2 or 4, depending on platform)"), + dylib_lto: bool = (false, parse_bool, [UNTRACKED], + "enables LTO for dylib crate type"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emit a section containing stack size metadata (default: no)"), emit_thin_lto: bool = (true, parse_bool, [TRACKED], diff --git a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs index aa65a72ab646a..6aa031c8378e6 100644 --- a/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs +++ b/compiler/rustc_symbol_mangling/src/typeid/typeid_itanium_cxx_abi.rs @@ -540,7 +540,7 @@ fn encode_ty<'tcx>( let mut s = String::new(); let def_id = adt_def.0.did; if options.contains(EncodeTyOptions::GENERALIZE_REPR_C) && adt_def.repr().c() { - // For for cross-language CFI support, the encoding must be compatible at the FFI + // For cross-language CFI support, the encoding must be compatible at the FFI // boundary. For instance: // // struct type1 {}; diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index 9fe7da3f29ec1..9e5f0e4d158b2 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -47,7 +47,7 @@ pub enum PassMode { /// Pass the argument indirectly via a hidden pointer. /// The `extra_attrs` value, if any, is for the extra data (vtable or length) /// which indicates that it refers to an unsized rvalue. - /// `on_stack` defines that the the value should be passed at a fixed + /// `on_stack` defines that the value should be passed at a fixed /// stack offset in accordance to the ABI rather than passed using a /// pointer. This corresponds to the `byval` LLVM argument attribute. Indirect { attrs: ArgAttributes, extra_attrs: Option, on_stack: bool }, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 7fc5c2ed0eae7..7715874743192 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -193,7 +193,7 @@ fn overlap_within_probe<'cx, 'tcx>( } } - // We disable the leak when when creating the `snapshot` by using + // We disable the leak when creating the `snapshot` by using // `infcx.probe_maybe_disable_leak_check`. if infcx.leak_check(true, snapshot).is_err() { debug!("overlap: leak check failed"); diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 8ea3d0fc917c2..b06f24ddf2e24 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -101,7 +101,7 @@ impl<'tcx> ConstUnifyCtxt<'tcx> { a_uv == b_uv } // FIXME(generic_const_exprs): We may want to either actually try - // to evaluate `a_ct` and `b_ct` if they are are fully concrete or something like + // to evaluate `a_ct` and `b_ct` if they are fully concrete or something like // this, for now we just return false here. _ => false, } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index fda6a2236b195..4431cf9f4436b 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -2937,19 +2937,15 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> { ObligationCauseCode::BinOp { rhs_span: Some(span), is_lit, .. } if *is_lit => span, _ => return, }; - match ( - trait_ref.skip_binder().self_ty().kind(), - trait_ref.skip_binder().substs.type_at(1).kind(), - ) { - (ty::Float(_), ty::Infer(InferTy::IntVar(_))) => { - err.span_suggestion_verbose( - rhs_span.shrink_to_hi(), - "consider using a floating-point literal by writing it with `.0`", - ".0", - Applicability::MaybeIncorrect, - ); - } - _ => {} + if let ty::Float(_) = trait_ref.skip_binder().self_ty().kind() + && let ty::Infer(InferTy::IntVar(_)) = trait_ref.skip_binder().substs.type_at(1).kind() + { + err.span_suggestion_verbose( + rhs_span.shrink_to_hi(), + "consider using a floating-point literal by writing it with `.0`", + ".0", + Applicability::MaybeIncorrect, + ); } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index cd1e9a97731ee..1ca9a1c1994f8 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -566,7 +566,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { .unwrap_or_else(|| ty.super_fold_with(self).into()) }; // For cases like #95134 we would like to catch overflows early - // otherwise they slip away away and cause ICE. + // otherwise they slip away and cause ICE. let recursion_limit = self.tcx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) // HACK: Don't overflow when running cargo doc see #100991 diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index ba987c6f76314..d390a30815307 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -264,7 +264,7 @@ fn adt_consider_insignificant_dtor<'tcx>( if is_marked_insig { // In some cases like `std::collections::HashMap` where the struct is a wrapper around // a type that is a Drop type, and the wrapped type (eg: `hashbrown::HashMap`) lies - // outside stdlib, we might choose to still annotate the the wrapper (std HashMap) with + // outside stdlib, we might choose to still annotate the wrapper (std HashMap) with // `rustc_insignificant_dtor`, even if the type itself doesn't have a `Drop` impl. Some(DtorType::Insignificant) } else if adt_def.destructor(tcx).is_some() { diff --git a/config.toml.example b/config.toml.example index 1f5747456e957..a46813e4d7a3b 100644 --- a/config.toml.example +++ b/config.toml.example @@ -638,6 +638,11 @@ changelog-seen = 2 # If an explicit setting is given, it will be used for all parts of the codebase. #new-symbol-mangling = true|false (see comment) +# Select LTO mode that will be used for compiling rustc. By default, thin local LTO +# (LTO within a single crate) is used (like for any Rust crate). You can also select +# "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib. +#lto = "thin-local" + # ============================================================================= # Options for specific targets # diff --git a/library/alloc/src/collections/linked_list.rs b/library/alloc/src/collections/linked_list.rs index 6480fcaf93d4e..f2f5dffc25d3a 100644 --- a/library/alloc/src/collections/linked_list.rs +++ b/library/alloc/src/collections/linked_list.rs @@ -1613,7 +1613,7 @@ impl<'a, T> CursorMut<'a, T> { None } else { // We can't point to the node that we pop. Copying the behavior of - // `remove_current`, we move on the the next node in the sequence. + // `remove_current`, we move on to the next node in the sequence. // If the list is of length 1 then we end pointing to the "ghost" // node at index 0, which is expected. if self.list.head == self.current { diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs index f6e6732b0e391..789a87968d154 100644 --- a/library/core/src/iter/traits/iterator.rs +++ b/library/core/src/iter/traits/iterator.rs @@ -692,7 +692,7 @@ pub trait Iterator { /// assert_eq!(it.next(), Some(NotClone(99))); // The separator. /// assert_eq!(it.next(), Some(NotClone(1))); // The next element from `v`. /// assert_eq!(it.next(), Some(NotClone(99))); // The separator. - /// assert_eq!(it.next(), Some(NotClone(2))); // The last element from from `v`. + /// assert_eq!(it.next(), Some(NotClone(2))); // The last element from `v`. /// assert_eq!(it.next(), None); // The iterator is finished. /// ``` /// diff --git a/library/core/src/mem/maybe_uninit.rs b/library/core/src/mem/maybe_uninit.rs index 2490c07679dd0..e2ae39fbab335 100644 --- a/library/core/src/mem/maybe_uninit.rs +++ b/library/core/src/mem/maybe_uninit.rs @@ -647,7 +647,7 @@ impl MaybeUninit { /// implements the [`Copy`] trait or not. When using multiple copies of the /// data (by calling `assume_init_read` multiple times, or first calling /// `assume_init_read` and then [`assume_init`]), it is your responsibility - /// to ensure that that data may indeed be duplicated. + /// to ensure that data may indeed be duplicated. /// /// [inv]: #initialization-invariant /// [`assume_init`]: MaybeUninit::assume_init diff --git a/library/core/src/num/dec2flt/lemire.rs b/library/core/src/num/dec2flt/lemire.rs index b8b0a1d3d7e2e..9f7594460a1d5 100644 --- a/library/core/src/num/dec2flt/lemire.rs +++ b/library/core/src/num/dec2flt/lemire.rs @@ -76,7 +76,7 @@ pub fn compute_float(q: i64, mut w: u64) -> BiasedFp { return BiasedFp { f: mantissa, e: power2 }; } // Need to handle rounding ties. Normally, we need to round up, - // but if we fall right in between and and we have an even basis, we + // but if we fall right in between and we have an even basis, we // need to round down. // // This will only occur if: diff --git a/library/core/src/num/int_log10.rs b/library/core/src/num/int_log10.rs index cc26c04a5d42a..80472528f6c3a 100644 --- a/library/core/src/num/int_log10.rs +++ b/library/core/src/num/int_log10.rs @@ -1,5 +1,5 @@ /// These functions compute the integer logarithm of their type, assuming -/// that someone has already checked that the the value is strictly positive. +/// that someone has already checked that the value is strictly positive. // 0 < val <= u8::MAX #[inline] diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index ff3b7bc2c9047..b413a85fee340 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -652,7 +652,6 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(2), Some(1));")] #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_rem(0), None);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_rem(-1), None);")] @@ -704,7 +703,6 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".checked_neg(), Some(-5));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_neg(), None);")] /// ``` @@ -820,7 +818,6 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #[doc = concat!("assert_eq!((-5", stringify!($SelfT), ").checked_abs(), Some(5));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.checked_abs(), None);")] /// ``` @@ -1026,7 +1023,6 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #[doc = concat!("assert_eq!(10", stringify!($SelfT), ".saturating_mul(12), 120);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.saturating_mul(10), ", stringify!($SelfT), "::MAX);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_mul(10), ", stringify!($SelfT), "::MIN);")] @@ -1085,7 +1081,6 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #[doc = concat!("assert_eq!((-4", stringify!($SelfT), ").saturating_pow(3), -64);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(2), ", stringify!($SelfT), "::MAX);")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_pow(3), ", stringify!($SelfT), "::MIN);")] @@ -1498,7 +1493,6 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (", stringify!($SelfT), "::MIN, true));")] /// ``` @@ -1593,7 +1587,6 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));")] /// ``` @@ -1703,7 +1696,6 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_div(2), (2, false));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_div(-1), (", stringify!($SelfT), "::MIN, true));")] /// ``` @@ -1766,7 +1758,6 @@ macro_rules! int_impl { /// Basic usage: /// /// ``` - /// #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_rem(2), (1, false));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.overflowing_rem(-1), (0, true));")] /// ``` diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index d921ff9ba1026..b177e5e390028 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -1456,7 +1456,6 @@ macro_rules! uint_impl { /// Basic usage /// /// ``` - /// #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_add(2), (7, false));")] #[doc = concat!("assert_eq!(", stringify!($SelfT), "::MAX.overflowing_add(1), (0, true));")] /// ``` @@ -1551,7 +1550,6 @@ macro_rules! uint_impl { /// Basic usage /// /// ``` - /// #[doc = concat!("assert_eq!(5", stringify!($SelfT), ".overflowing_sub(2), (3, false));")] #[doc = concat!("assert_eq!(0", stringify!($SelfT), ".overflowing_sub(1), (", stringify!($SelfT), "::MAX, true));")] /// ``` diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs index d898108be580f..67e59460d74b0 100644 --- a/library/core/src/ptr/const_ptr.rs +++ b/library/core/src/ptr/const_ptr.rs @@ -694,7 +694,7 @@ impl *const T { /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// /// This computes the same value that [`offset_from`](#method.offset_from) - /// would compute, but with the added precondition that that the offset is + /// would compute, but with the added precondition that the offset is /// guaranteed to be non-negative. This method is equivalent to /// `usize::from(self.offset_from(origin)).unwrap_unchecked()`, /// but it provides slightly more information to the optimizer, which can diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs index 543ab826c4eb9..bbcc7c699e036 100644 --- a/library/core/src/ptr/mut_ptr.rs +++ b/library/core/src/ptr/mut_ptr.rs @@ -867,7 +867,7 @@ impl *mut T { /// units of T: the distance in bytes is divided by `mem::size_of::()`. /// /// This computes the same value that [`offset_from`](#method.offset_from) - /// would compute, but with the added precondition that that the offset is + /// would compute, but with the added precondition that the offset is /// guaranteed to be non-negative. This method is equivalent to /// `usize::from(self.offset_from(origin)).unwrap_unchecked()`, /// but it provides slightly more information to the optimizer, which can diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs index 6c70517d965b2..cdc47e17938dc 100644 --- a/library/core/src/sync/atomic.rs +++ b/library/core/src/sync/atomic.rs @@ -1642,8 +1642,8 @@ impl AtomicPtr { /// and the argument `val`, and stores a pointer with provenance of the /// current pointer and the resulting address. /// - /// This is equivalent equivalent to using [`map_addr`] to atomically - /// perform `ptr = ptr.map_addr(|a| a | val)`. This can be used in tagged + /// This is equivalent to using [`map_addr`] to atomically perform + /// `ptr = ptr.map_addr(|a| a | val)`. This can be used in tagged /// pointer schemes to atomically set tag bits. /// /// **Caveat**: This operation returns the previous value. To compute the @@ -1693,8 +1693,8 @@ impl AtomicPtr { /// pointer, and the argument `val`, and stores a pointer with provenance of /// the current pointer and the resulting address. /// - /// This is equivalent equivalent to using [`map_addr`] to atomically - /// perform `ptr = ptr.map_addr(|a| a & val)`. This can be used in tagged + /// This is equivalent to using [`map_addr`] to atomically perform + /// `ptr = ptr.map_addr(|a| a & val)`. This can be used in tagged /// pointer schemes to atomically unset tag bits. /// /// **Caveat**: This operation returns the previous value. To compute the @@ -1743,8 +1743,8 @@ impl AtomicPtr { /// pointer, and the argument `val`, and stores a pointer with provenance of /// the current pointer and the resulting address. /// - /// This is equivalent equivalent to using [`map_addr`] to atomically - /// perform `ptr = ptr.map_addr(|a| a ^ val)`. This can be used in tagged + /// This is equivalent to using [`map_addr`] to atomically perform + /// `ptr = ptr.map_addr(|a| a ^ val)`. This can be used in tagged /// pointer schemes to atomically toggle tag bits. /// /// **Caveat**: This operation returns the previous value. To compute the diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs index 49580cdcc481a..c79e909e41db8 100644 --- a/library/core/tests/num/mod.rs +++ b/library/core/tests/num/mod.rs @@ -172,7 +172,7 @@ fn test_can_not_overflow() { // Calcutate the string length for the smallest overflowing number: let max_len_string = format_radix(num, base as u128); - // Ensure that that string length is deemed to potentially overflow: + // Ensure that string length is deemed to potentially overflow: assert!(can_overflow::<$t>(base, &max_len_string)); } )*) diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs index 34b57c37635cb..9cb74f951dd37 100644 --- a/library/std/src/backtrace.rs +++ b/library/std/src/backtrace.rs @@ -325,8 +325,7 @@ impl Backtrace { // Capture a backtrace which start just before the function addressed by // `ip` fn create(ip: usize) -> Backtrace { - // SAFETY: We don't attempt to lock this reentrantly. - let _lock = unsafe { lock() }; + let _lock = lock(); let mut frames = Vec::new(); let mut actual_start = None; unsafe { @@ -469,8 +468,7 @@ impl Capture { // Use the global backtrace lock to synchronize this as it's a // requirement of the `backtrace` crate, and then actually resolve // everything. - // SAFETY: We don't attempt to lock this reentrantly. - let _lock = unsafe { lock() }; + let _lock = lock(); for frame in self.frames.iter_mut() { let symbols = &mut frame.symbols; let frame = match &frame.frame { diff --git a/library/std/src/os/fd/owned.rs b/library/std/src/os/fd/owned.rs index 9875c389d8aaf..9d758320cfcc6 100644 --- a/library/std/src/os/fd/owned.rs +++ b/library/std/src/os/fd/owned.rs @@ -6,6 +6,7 @@ use super::raw::{AsRawFd, FromRawFd, IntoRawFd, RawFd}; use crate::fmt; use crate::fs; +use crate::io; use crate::marker::PhantomData; use crate::mem::forget; #[cfg(not(any(target_arch = "wasm32", target_env = "sgx")))] @@ -385,3 +386,54 @@ impl AsFd for Box { (**self).as_fd() } } + +#[stable(feature = "io_safety", since = "1.63.0")] +impl AsFd for io::Stdin { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(0) } + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl<'a> AsFd for io::StdinLock<'a> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + // SAFETY: user code should not close stdin out from under the standard library + unsafe { BorrowedFd::borrow_raw(0) } + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl AsFd for io::Stdout { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(1) } + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl<'a> AsFd for io::StdoutLock<'a> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + // SAFETY: user code should not close stdout out from under the standard library + unsafe { BorrowedFd::borrow_raw(1) } + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl AsFd for io::Stderr { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + unsafe { BorrowedFd::borrow_raw(2) } + } +} + +#[stable(feature = "io_safety", since = "1.63.0")] +impl<'a> AsFd for io::StderrLock<'a> { + #[inline] + fn as_fd(&self) -> BorrowedFd<'_> { + // SAFETY: user code should not close stderr out from under the standard library + unsafe { BorrowedFd::borrow_raw(2) } + } +} diff --git a/library/std/src/process.rs b/library/std/src/process.rs index e08ea8f9a5fc9..b8249a027ad99 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1629,7 +1629,7 @@ impl ExitStatusError { /// /// This is exactly like [`code()`](Self::code), except that it returns a `NonZeroI32`. /// - /// Plain `code`, returning a plain integer, is provided because is is often more convenient. + /// Plain `code`, returning a plain integer, is provided because it is often more convenient. /// The returned value from `code()` is indeed also nonzero; use `code_nonzero()` when you want /// a type-level guarantee of nonzeroness. /// diff --git a/library/std/src/sys/hermit/args.rs b/library/std/src/sys/hermit/args.rs index 1c7e1dd8d5778..afcae6c90ee02 100644 --- a/library/std/src/sys/hermit/args.rs +++ b/library/std/src/sys/hermit/args.rs @@ -1,20 +1,37 @@ -use crate::ffi::OsString; +use crate::ffi::{c_char, CStr, OsString}; use crate::fmt; +use crate::os::unix::ffi::OsStringExt; +use crate::ptr; +use crate::sync::atomic::{ + AtomicIsize, AtomicPtr, + Ordering::{Acquire, Relaxed, Release}, +}; use crate::vec; +static ARGC: AtomicIsize = AtomicIsize::new(0); +static ARGV: AtomicPtr<*const u8> = AtomicPtr::new(ptr::null_mut()); + /// One-time global initialization. pub unsafe fn init(argc: isize, argv: *const *const u8) { - imp::init(argc, argv) -} - -/// One-time global cleanup. -pub unsafe fn cleanup() { - imp::cleanup() + ARGC.store(argc, Relaxed); + // Use release ordering here to broadcast writes by the OS. + ARGV.store(argv as *mut *const u8, Release); } /// Returns the command line arguments pub fn args() -> Args { - imp::args() + // Synchronize with the store above. + let argv = ARGV.load(Acquire); + // If argv has not been initialized yet, do not return any arguments. + let argc = if argv.is_null() { 0 } else { ARGC.load(Relaxed) }; + let args: Vec = (0..argc) + .map(|i| unsafe { + let cstr = CStr::from_ptr(*argv.offset(i) as *const c_char); + OsStringExt::from_vec(cstr.to_bytes().to_vec()) + }) + .collect(); + + Args { iter: args.into_iter() } } pub struct Args { @@ -51,44 +68,3 @@ impl DoubleEndedIterator for Args { self.iter.next_back() } } - -mod imp { - use super::Args; - use crate::ffi::{CStr, OsString}; - use crate::os::unix::ffi::OsStringExt; - use crate::ptr; - - use crate::sys_common::mutex::StaticMutex; - - static mut ARGC: isize = 0; - static mut ARGV: *const *const u8 = ptr::null(); - static LOCK: StaticMutex = StaticMutex::new(); - - pub unsafe fn init(argc: isize, argv: *const *const u8) { - let _guard = LOCK.lock(); - ARGC = argc; - ARGV = argv; - } - - pub unsafe fn cleanup() { - let _guard = LOCK.lock(); - ARGC = 0; - ARGV = ptr::null(); - } - - pub fn args() -> Args { - Args { iter: clone().into_iter() } - } - - fn clone() -> Vec { - unsafe { - let _guard = LOCK.lock(); - (0..ARGC) - .map(|i| { - let cstr = CStr::from_ptr(*ARGV.offset(i) as *const i8); - OsStringExt::from_vec(cstr.to_bytes().to_vec()) - }) - .collect() - } - } -} diff --git a/library/std/src/sys/hermit/mod.rs b/library/std/src/sys/hermit/mod.rs index 827d82900eae4..e6534df8938eb 100644 --- a/library/std/src/sys/hermit/mod.rs +++ b/library/std/src/sys/hermit/mod.rs @@ -106,9 +106,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, _sigpipe: u8) { // SAFETY: must be called only once during runtime cleanup. // NOTE: this is not guaranteed to run, for example when the program aborts. -pub unsafe fn cleanup() { - args::cleanup(); -} +pub unsafe fn cleanup() {} #[cfg(not(test))] #[no_mangle] diff --git a/library/std/src/sys/unix/process/process_fuchsia.rs b/library/std/src/sys/unix/process/process_fuchsia.rs index 73f5d3a618bad..66ea3db2015a4 100644 --- a/library/std/src/sys/unix/process/process_fuchsia.rs +++ b/library/std/src/sys/unix/process/process_fuchsia.rs @@ -287,7 +287,7 @@ impl ExitStatus { // SuS and POSIX) say a wait status is, but Fuchsia apparently uses a u64, so it won't // necessarily fit. // - // It seems to me that that the right answer would be to provide std::os::fuchsia with its + // It seems to me that the right answer would be to provide std::os::fuchsia with its // own ExitStatusExt, rather that trying to provide a not very convincing imitation of // Unix. Ie, std::os::unix::process:ExitStatusExt ought not to exist on Fuchsia. But // fixing this up that is beyond the scope of my efforts now. diff --git a/library/std/src/sys/unix/stdio.rs b/library/std/src/sys/unix/stdio.rs index 329f9433dba0e..b3626c564e86a 100644 --- a/library/std/src/sys/unix/stdio.rs +++ b/library/std/src/sys/unix/stdio.rs @@ -1,6 +1,6 @@ use crate::io::{self, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; -use crate::os::unix::io::{AsFd, BorrowedFd, FromRawFd}; +use crate::os::unix::io::FromRawFd; use crate::sys::fd::FileDesc; pub struct Stdin(()); @@ -91,51 +91,3 @@ pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE; pub fn panic_output() -> Option { Some(Stderr::new()) } - -#[stable(feature = "io_safety", since = "1.63.0")] -impl AsFd for io::Stdin { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw(libc::STDIN_FILENO) } - } -} - -#[stable(feature = "io_safety", since = "1.63.0")] -impl<'a> AsFd for io::StdinLock<'a> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw(libc::STDIN_FILENO) } - } -} - -#[stable(feature = "io_safety", since = "1.63.0")] -impl AsFd for io::Stdout { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw(libc::STDOUT_FILENO) } - } -} - -#[stable(feature = "io_safety", since = "1.63.0")] -impl<'a> AsFd for io::StdoutLock<'a> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw(libc::STDOUT_FILENO) } - } -} - -#[stable(feature = "io_safety", since = "1.63.0")] -impl AsFd for io::Stderr { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw(libc::STDERR_FILENO) } - } -} - -#[stable(feature = "io_safety", since = "1.63.0")] -impl<'a> AsFd for io::StderrLock<'a> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw(libc::STDERR_FILENO) } - } -} diff --git a/library/std/src/sys/unix/thread_local_dtor.rs b/library/std/src/sys/unix/thread_local_dtor.rs index 6e8be2a91de00..d7fd2130f7cce 100644 --- a/library/std/src/sys/unix/thread_local_dtor.rs +++ b/library/std/src/sys/unix/thread_local_dtor.rs @@ -17,6 +17,7 @@ target_os = "redox", target_os = "emscripten" ))] +#[cfg_attr(target_family = "wasm", allow(unused))] // might remain unused depending on target details (e.g. wasm32-unknown-emscripten) pub unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern "C" fn(*mut u8)) { use crate::mem; use crate::sys_common::thread_local_dtor::register_dtor_fallback; diff --git a/library/std/src/sys/unsupported/thread_local_dtor.rs b/library/std/src/sys/unsupported/thread_local_dtor.rs index 85d660983029c..84660ea588156 100644 --- a/library/std/src/sys/unsupported/thread_local_dtor.rs +++ b/library/std/src/sys/unsupported/thread_local_dtor.rs @@ -1,5 +1,6 @@ #![unstable(feature = "thread_local_internals", issue = "none")] +#[cfg_attr(target_family = "wasm", allow(unused))] // unused on wasm32-unknown-unknown pub unsafe fn register_dtor(_t: *mut u8, _dtor: unsafe extern "C" fn(*mut u8)) { // FIXME: right now there is no concept of "thread exit", but this is likely // going to show up at some point in the form of an exported symbol that the diff --git a/library/std/src/sys/wasi/stdio.rs b/library/std/src/sys/wasi/stdio.rs index bf045c7841f63..4cc0e4ed5a45a 100644 --- a/library/std/src/sys/wasi/stdio.rs +++ b/library/std/src/sys/wasi/stdio.rs @@ -4,7 +4,7 @@ use super::fd::WasiFd; use crate::io::{self, IoSlice, IoSliceMut}; use crate::mem::ManuallyDrop; use crate::os::raw; -use crate::os::wasi::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd}; +use crate::os::wasi::io::{AsRawFd, FromRawFd}; pub struct Stdin; pub struct Stdout; @@ -23,22 +23,6 @@ impl AsRawFd for Stdin { } } -impl AsFd for Stdin { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw(0) } - } -} - -#[stable(feature = "io_safety", since = "1.63.0")] -impl<'a> AsFd for io::StdinLock<'a> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - // SAFETY: user code should not close stdin out from under the standard library - unsafe { BorrowedFd::borrow_raw(0) } - } -} - impl io::Read for Stdin { fn read(&mut self, data: &mut [u8]) -> io::Result { self.read_vectored(&mut [IoSliceMut::new(data)]) @@ -67,22 +51,6 @@ impl AsRawFd for Stdout { } } -impl AsFd for Stdout { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw(1) } - } -} - -#[stable(feature = "io_safety", since = "1.63.0")] -impl<'a> AsFd for io::StdoutLock<'a> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - // SAFETY: user code should not close stdout out from under the standard library - unsafe { BorrowedFd::borrow_raw(1) } - } -} - impl io::Write for Stdout { fn write(&mut self, data: &[u8]) -> io::Result { self.write_vectored(&[IoSlice::new(data)]) @@ -114,22 +82,6 @@ impl AsRawFd for Stderr { } } -impl AsFd for Stderr { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - unsafe { BorrowedFd::borrow_raw(2) } - } -} - -#[stable(feature = "io_safety", since = "1.63.0")] -impl<'a> AsFd for io::StderrLock<'a> { - #[inline] - fn as_fd(&self) -> BorrowedFd<'_> { - // SAFETY: user code should not close stderr out from under the standard library - unsafe { BorrowedFd::borrow_raw(2) } - } -} - impl io::Write for Stderr { fn write(&mut self, data: &[u8]) -> io::Result { self.write_vectored(&[IoSlice::new(data)]) diff --git a/library/std/src/sys/windows/process.rs b/library/std/src/sys/windows/process.rs index 02d5af4719ae8..9cbb4ef19e9b7 100644 --- a/library/std/src/sys/windows/process.rs +++ b/library/std/src/sys/windows/process.rs @@ -16,6 +16,7 @@ use crate::os::windows::ffi::{OsStrExt, OsStringExt}; use crate::os::windows::io::{AsHandle, AsRawHandle, BorrowedHandle, FromRawHandle, IntoRawHandle}; use crate::path::{Path, PathBuf}; use crate::ptr; +use crate::sync::Mutex; use crate::sys::args::{self, Arg}; use crate::sys::c; use crate::sys::c::NonZeroDWORD; @@ -25,7 +26,6 @@ use crate::sys::handle::Handle; use crate::sys::path; use crate::sys::pipe::{self, AnonPipe}; use crate::sys::stdio; -use crate::sys_common::mutex::StaticMutex; use crate::sys_common::process::{CommandEnv, CommandEnvs}; use crate::sys_common::IntoInner; @@ -301,9 +301,9 @@ impl Command { // // For more information, msdn also has an article about this race: // https://support.microsoft.com/kb/315939 - static CREATE_PROCESS_LOCK: StaticMutex = StaticMutex::new(); + static CREATE_PROCESS_LOCK: Mutex<()> = Mutex::new(()); - let _guard = unsafe { CREATE_PROCESS_LOCK.lock() }; + let _guard = CREATE_PROCESS_LOCK.lock(); let mut pipes = StdioPipes { stdin: None, stdout: None, stderr: None }; let null = Stdio::Null; diff --git a/library/std/src/sys_common/backtrace.rs b/library/std/src/sys_common/backtrace.rs index 31164afdc7b54..8807077cb4927 100644 --- a/library/std/src/sys_common/backtrace.rs +++ b/library/std/src/sys_common/backtrace.rs @@ -7,15 +7,14 @@ use crate::fmt; use crate::io; use crate::io::prelude::*; use crate::path::{self, Path, PathBuf}; -use crate::sys_common::mutex::StaticMutex; +use crate::sync::{Mutex, PoisonError}; /// Max number of frames to print. const MAX_NB_FRAMES: usize = 100; -// SAFETY: Don't attempt to lock this reentrantly. -pub unsafe fn lock() -> impl Drop { - static LOCK: StaticMutex = StaticMutex::new(); - LOCK.lock() +pub fn lock() -> impl Drop { + static LOCK: Mutex<()> = Mutex::new(()); + LOCK.lock().unwrap_or_else(PoisonError::into_inner) } /// Prints the current backtrace. diff --git a/library/std/src/sys_common/mutex.rs b/library/std/src/sys_common/mutex.rs index 7b9f7ef548785..98046f20f896a 100644 --- a/library/std/src/sys_common/mutex.rs +++ b/library/std/src/sys_common/mutex.rs @@ -1,49 +1,5 @@ use crate::sys::locks as imp; -/// An OS-based mutual exclusion lock, meant for use in static variables. -/// -/// This mutex has a const constructor ([`StaticMutex::new`]), does not -/// implement `Drop` to cleanup resources, and causes UB when used reentrantly. -/// -/// This mutex does not implement poisoning. -/// -/// This is a wrapper around `imp::Mutex` that does *not* call `init()` and -/// `destroy()`. -pub struct StaticMutex(imp::Mutex); - -unsafe impl Sync for StaticMutex {} - -impl StaticMutex { - /// Creates a new mutex for use. - #[inline] - pub const fn new() -> Self { - Self(imp::Mutex::new()) - } - - /// Calls raw_lock() and then returns an RAII guard to guarantee the mutex - /// will be unlocked. - /// - /// It is undefined behaviour to call this function while locked by the - /// same thread. - #[inline] - pub unsafe fn lock(&'static self) -> StaticMutexGuard { - self.0.lock(); - StaticMutexGuard(&self.0) - } -} - -#[must_use] -pub struct StaticMutexGuard(&'static imp::Mutex); - -impl Drop for StaticMutexGuard { - #[inline] - fn drop(&mut self) { - unsafe { - self.0.unlock(); - } - } -} - /// An OS-based mutual exclusion lock. /// /// This mutex cleans up its resources in its `Drop` implementation, may safely diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index ffd17dc99093a..5d267891bb0ed 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -901,7 +901,7 @@ pub mod statik { } #[doc(hidden)] -#[cfg(target_thread_local)] +#[cfg(all(target_thread_local, not(all(target_family = "wasm", not(target_feature = "atomics"))),))] pub mod fast { use super::lazy::LazyKeyInner; use crate::cell::Cell; @@ -1037,7 +1037,10 @@ pub mod fast { } #[doc(hidden)] -#[cfg(not(target_thread_local))] +#[cfg(all( + not(target_thread_local), + not(all(target_family = "wasm", not(target_feature = "atomics"))), +))] pub mod os { use super::lazy::LazyKeyInner; use crate::cell::Cell; diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index 55110c44b6e98..05023df1bb24b 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -150,6 +150,8 @@ #![stable(feature = "rust1", since = "1.0.0")] #![deny(unsafe_op_in_unsafe_fn)] +// Under `test`, `__FastLocalKeyInner` seems unused. +#![cfg_attr(test, allow(dead_code))] #[cfg(all(test, not(target_os = "emscripten")))] mod tests; @@ -192,32 +194,40 @@ pub use scoped::{scope, Scope, ScopedJoinHandle}; #[stable(feature = "rust1", since = "1.0.0")] pub use self::local::{AccessError, LocalKey}; -// Select the type used by the thread_local! macro to access TLS keys. There -// are three types: "static", "fast", "OS". The "OS" thread local key +// Provide the type used by the thread_local! macro to access TLS keys. This +// needs to be kept in sync with the macro itself (in `local.rs`). +// There are three types: "static", "fast", "OS". The "OS" thread local key // type is accessed via platform-specific API calls and is slow, while the "fast" // key type is accessed via code generated via LLVM, where TLS keys are set up // by the elf linker. "static" is for single-threaded platforms where a global // static is sufficient. #[unstable(feature = "libstd_thread_internals", issue = "none")] -#[cfg(target_thread_local)] #[cfg(not(test))] +#[cfg(all( + target_thread_local, + not(all(target_family = "wasm", not(target_feature = "atomics"))), +))] #[doc(hidden)] pub use self::local::fast::Key as __FastLocalKeyInner; -#[unstable(feature = "libstd_thread_internals", issue = "none")] -#[cfg(target_thread_local)] -#[cfg(test)] // when building for tests, use real std's key -pub use realstd::thread::__FastLocalKeyInner; +// when building for tests, use real std's type #[unstable(feature = "libstd_thread_internals", issue = "none")] -#[cfg(target_thread_local)] #[cfg(test)] -pub use self::local::fast::Key as __FastLocalKeyInnerUnused; // we import this anyway to silence 'unused' warnings +#[cfg(all( + target_thread_local, + not(all(target_family = "wasm", not(target_feature = "atomics"))), +))] +pub use realstd::thread::__FastLocalKeyInner; #[unstable(feature = "libstd_thread_internals", issue = "none")] +#[cfg(all( + not(target_thread_local), + not(all(target_family = "wasm", not(target_feature = "atomics"))), +))] #[doc(hidden)] -#[cfg(not(target_thread_local))] pub use self::local::os::Key as __OsLocalKeyInner; + #[unstable(feature = "libstd_thread_internals", issue = "none")] #[cfg(all(target_family = "wasm", not(target_feature = "atomics")))] #[doc(hidden)] @@ -1118,24 +1128,21 @@ impl ThreadId { } } } else { - use crate::sys_common::mutex::StaticMutex; + use crate::sync::{Mutex, PoisonError}; - // It is UB to attempt to acquire this mutex reentrantly! - static GUARD: StaticMutex = StaticMutex::new(); - static mut COUNTER: u64 = 0; + static COUNTER: Mutex = Mutex::new(0); - unsafe { - let guard = GUARD.lock(); + let mut counter = COUNTER.lock().unwrap_or_else(PoisonError::into_inner); + let Some(id) = counter.checked_add(1) else { + // in case the panic handler ends up calling `ThreadId::new()`, + // avoid reentrant lock acquire. + drop(counter); + exhausted(); + }; - let Some(id) = COUNTER.checked_add(1) else { - drop(guard); // in case the panic handler ends up calling `ThreadId::new()`, avoid reentrant lock acquire. - exhausted(); - }; - - COUNTER = id; - drop(guard); - ThreadId(NonZeroU64::new(id).unwrap()) - } + *counter = id; + drop(counter); + ThreadId(NonZeroU64::new(id).unwrap()) } } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index 4967bf50b48a1..9cc119d3301ac 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -21,7 +21,7 @@ use serde::Deserialize; use crate::builder::Cargo; use crate::builder::{Builder, Kind, RunConfig, ShouldRun, Step}; use crate::cache::{Interned, INTERNER}; -use crate::config::{LlvmLibunwind, TargetSelection}; +use crate::config::{LlvmLibunwind, RustcLto, TargetSelection}; use crate::dist; use crate::native; use crate::tool::SourceType; @@ -464,7 +464,7 @@ fn copy_sanitizers( builder.copy(&runtime.path, &dst); if target == "x86_64-apple-darwin" || target == "aarch64-apple-darwin" { - // Update the library’s install name to reflect that it has has been renamed. + // Update the library’s install name to reflect that it has been renamed. apple_darwin_update_library_name(&dst, &format!("@rpath/{}", &runtime.name)); // Upon renaming the install name, the code signature of the file will invalidate, // so we will sign it again. @@ -701,6 +701,28 @@ impl Step for Rustc { )); } + // cfg(bootstrap): remove if condition once the bootstrap compiler supports dylib LTO + if compiler.stage != 0 { + match builder.config.rust_lto { + RustcLto::Thin | RustcLto::Fat => { + // Since using LTO for optimizing dylibs is currently experimental, + // we need to pass -Zdylib-lto. + cargo.rustflag("-Zdylib-lto"); + // Cargo by default passes `-Cembed-bitcode=no` and doesn't pass `-Clto` when + // compiling dylibs (and their dependencies), even when LTO is enabled for the + // crate. Therefore, we need to override `-Clto` and `-Cembed-bitcode` here. + let lto_type = match builder.config.rust_lto { + RustcLto::Thin => "thin", + RustcLto::Fat => "fat", + _ => unreachable!(), + }; + cargo.rustflag(&format!("-Clto={}", lto_type)); + cargo.rustflag("-Cembed-bitcode=yes"); + } + RustcLto::ThinLocal => { /* Do nothing, this is the default */ } + } + } + builder.info(&format!( "Building stage{} compiler artifacts ({} -> {})", compiler.stage, &compiler.host, target diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index 635823b958b18..a8c403675d821 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -158,6 +158,7 @@ pub struct Config { pub rust_new_symbol_mangling: Option, pub rust_profile_use: Option, pub rust_profile_generate: Option, + pub rust_lto: RustcLto, pub llvm_profile_use: Option, pub llvm_profile_generate: bool, pub llvm_libunwind_default: Option, @@ -319,6 +320,28 @@ impl SplitDebuginfo { } } +/// LTO mode used for compiling rustc itself. +#[derive(Default, Clone)] +pub enum RustcLto { + #[default] + ThinLocal, + Thin, + Fat, +} + +impl std::str::FromStr for RustcLto { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "thin-local" => Ok(RustcLto::ThinLocal), + "thin" => Ok(RustcLto::Thin), + "fat" => Ok(RustcLto::Fat), + _ => Err(format!("Invalid value for rustc LTO: {}", s)), + } + } +} + #[derive(Copy, Clone, Default, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct TargetSelection { pub triple: Interned, @@ -726,6 +749,7 @@ define_config! { profile_use: Option = "profile-use", // ignored; this is set from an env var set by bootstrap.py download_rustc: Option = "download-rustc", + lto: Option = "lto", } } @@ -1173,6 +1197,12 @@ impl Config { config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use); config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate); config.download_rustc_commit = download_ci_rustc_commit(&config, rust.download_rustc); + + config.rust_lto = rust + .lto + .as_deref() + .map(|value| RustcLto::from_str(value).unwrap()) + .unwrap_or_default(); } else { config.rust_profile_use = flags.rust_profile_use; config.rust_profile_generate = flags.rust_profile_generate; diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index b960239807af8..423aba06ccaff 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -78,7 +78,8 @@ ENV RUST_CONFIGURE_ARGS \ --set llvm.thin-lto=true \ --set llvm.ninja=false \ --set rust.jemalloc \ - --set rust.use-lld=true + --set rust.use-lld=true \ + --set rust.lto=thin ENV SCRIPT ../src/ci/pgo.sh python3 ../x.py dist \ --host $HOSTS --target $HOSTS \ --include-default-paths \ diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh index cf00c285b0a63..3e1f39eaab5a4 100755 --- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh +++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/checktools.sh @@ -4,7 +4,7 @@ set -eu X_PY="$1" -# Try to test all the tools and store the build/test success in the TOOLSTATE_FILE +# Try to test the toolstate-tracked tools and store the build/test success in the TOOLSTATE_FILE. set +e python3 "$X_PY" test --stage 2 --no-fail-fast \ @@ -19,6 +19,8 @@ set -e # debugging: print out the saved toolstates cat /tmp/toolstate/toolstates.json + +# Test remaining tools that must pass. python3 "$X_PY" test --stage 2 check-tools python3 "$X_PY" test --stage 2 src/tools/clippy python3 "$X_PY" test --stage 2 src/tools/rustfmt diff --git a/src/doc/unstable-book/src/compiler-flags/dylib-lto.md b/src/doc/unstable-book/src/compiler-flags/dylib-lto.md new file mode 100644 index 0000000000000..f69ea334f5a3a --- /dev/null +++ b/src/doc/unstable-book/src/compiler-flags/dylib-lto.md @@ -0,0 +1,4 @@ +## `dylib-lto` + +This option enables using LTO for the `dylib` crate type. This is currently only used for compiling +`rustc` itself (more specifically, the `librustc_driver` dylib). diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 7f82dfbd3d6ff..5f674ed7441ba 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1514,7 +1514,7 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> T // as we currently do not supply the parent generics to anonymous constants // but do allow `ConstKind::Param`. // - // `const_eval_poly` tries to to first substitute generic parameters which + // `const_eval_poly` tries to first substitute generic parameters which // results in an ICE while manually constructing the constant and using `eval` // does nothing for `ConstKind::Param`. let ct = ty::Const::from_anon_const(cx.tcx, def_id); diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index f4ec60735a8dd..d9160e8abd4e3 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -18,7 +18,6 @@ use rustc_session::{lint, DiagnosticOutput, Session}; use rustc_span::edition::Edition; use rustc_span::source_map::SourceMap; use rustc_span::symbol::sym; -use rustc_span::Symbol; use rustc_span::{BytePos, FileName, Pos, Span, DUMMY_SP}; use rustc_target::spec::TargetTriple; use tempfile::Builder as TempFileBuilder; @@ -125,7 +124,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { let opts = scrape_test_config(crate_attrs); let enable_per_target_ignores = options.enable_per_target_ignores; let mut collector = Collector::new( - tcx.crate_name(LOCAL_CRATE), + tcx.crate_name(LOCAL_CRATE).to_string(), options, false, opts, @@ -909,7 +908,7 @@ pub(crate) struct Collector { rustdoc_options: RustdocOptions, use_headers: bool, enable_per_target_ignores: bool, - crate_name: Symbol, + crate_name: String, opts: GlobalTestOptions, position: Span, source_map: Option>, @@ -921,7 +920,7 @@ pub(crate) struct Collector { impl Collector { pub(crate) fn new( - crate_name: Symbol, + crate_name: String, rustdoc_options: RustdocOptions, use_headers: bool, opts: GlobalTestOptions, @@ -984,7 +983,7 @@ impl Tester for Collector { fn add_test(&mut self, test: String, config: LangString, line: usize) { let filename = self.get_filename(); let name = self.generate_name(line, &filename); - let crate_name = self.crate_name.to_string(); + let crate_name = self.crate_name.clone(); let opts = self.opts.clone(); let edition = config.edition.unwrap_or(self.rustdoc_options.edition); let rustdoc_options = self.rustdoc_options.clone(); diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 943a074366e8e..7d00002d05bee 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -612,7 +612,7 @@ fn generate_macro_def_id_path( }; if path.len() < 2 { // The minimum we can have is the crate name followed by the macro name. If shorter, then - // it means that that `relative` was empty, which is an error. + // it means that `relative` was empty, which is an error. debug!("macro path cannot be empty!"); return Err(HrefError::NotInExternalCache); } diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css index 5958b389c9f4c..7989c52177495 100644 --- a/src/librustdoc/html/static/css/rustdoc.css +++ b/src/librustdoc/html/static/css/rustdoc.css @@ -808,9 +808,6 @@ table, height: 34px; margin-top: 4px; } -.search-container > * { - height: 100%; -} .search-results-title { margin-top: 0; white-space: nowrap; @@ -1089,8 +1086,55 @@ so that we can apply CSS-filters to change the arrow color in themes */ color: var(--right-side-color); } +pre.rust { + tab-size: 4; + -moz-tab-size: 4; +} + +/* Code highlighting */ +pre.rust .kw { + color: var(--code-highlight-kw-color); +} +pre.rust .kw-2 { + color: var(--code-highlight-kw-2-color); +} +pre.rust .lifetime { + color: var(--code-highlight-lifetime-color); +} +pre.rust .prelude-ty { + color: var(--code-highlight-prelude-color); +} +pre.rust .prelude-val { + color: var(--code-highlight-prelude-val-color); +} +pre.rust .string { + color: var(--code-highlight-string-color); +} +pre.rust .number { + color: var(--code-highlight-number-color); +} +pre.rust .bool-val { + color: var(--code-highlight-literal-color); +} +pre.rust .self { + color: var(--code-highlight-self-color); +} +pre.rust .attribute { + color: var(--code-highlight-attribute-color); +} +pre.rust .macro, +pre.rust .macro-nonterminal { + color: var(--code-highlight-macro-color); +} pre.rust .question-mark { font-weight: bold; + color: var(--code-highlight-question-mark-color); +} +pre.rust .comment { + color: var(--code-highlight-comment-color); +} +pre.rust .doccomment { + color: var(--code-highlight-doc-comment-color); } .example-wrap.compile_fail, @@ -1296,11 +1340,6 @@ h3.variant { font-size: 1.25rem; } -pre.rust { - tab-size: 4; - -moz-tab-size: 4; -} - .search-failed { text-align: center; margin-top: 20px; diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css index fc7713b98857b..ee74f81926ac6 100644 --- a/src/librustdoc/html/static/css/themes/ayu.css +++ b/src/librustdoc/html/static/css/themes/ayu.css @@ -41,6 +41,20 @@ Original by Dempfi (https://github.com/dempfi/ayu) --stab-background-color: #314559; --stab-code-color: #e6e1cf; --search-color: #fff; + --code-highlight-kw-color: #ff7733; + --code-highlight-kw-2-color: #ff7733; + --code-highlight-lifetime-color: #ff7733; + --code-highlight-prelude-color: #69f2df; + --code-highlight-prelude-val-color: #ff7733; + --code-highlight-number-color: #b8cc52; + --code-highlight-string-color: #b8cc52; + --code-highlight-literal-color: #ff7733; + --code-highlight-attribute-color: #e6e1cf; + --code-highlight-self-color: #36a3d9; + --code-highlight-macro-color: #a37acc; + --code-highlight-question-mark-color: #ff9011; + --code-highlight-comment-color: #788797; + --code-highlight-doc-comment-color: #a1ac88; } .slider { @@ -124,9 +138,6 @@ pre, .rustdoc.source .example-wrap { .content .item-info::before { color: #ccc; } -pre.rust .comment { color: #788797; } -pre.rust .doccomment { color: #a1ac88; } - .sidebar h2 a, .sidebar h3 a { color: white; @@ -161,23 +172,6 @@ details.rustdoc-toggle > summary::before { .src-line-numbers :target { background-color: transparent; } -/* Code highlighting */ -pre.rust .number, pre.rust .string { color: #b8cc52; } -pre.rust .kw, pre.rust .kw-2, pre.rust .prelude-ty, -pre.rust .bool-val, pre.rust .prelude-val, -pre.rust .lifetime { color: #ff7733; } -pre.rust .macro, pre.rust .macro-nonterminal { color: #a37acc; } -pre.rust .question-mark { - color: #ff9011; -} -pre.rust .self { - color: #36a3d9; - font-style: italic; -} -pre.rust .attribute { - color: #e6e1cf; -} - pre.example-line-numbers { color: #5c67736e; border: none; diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css index ee2a9ec8a0bee..06baceca01d3b 100644 --- a/src/librustdoc/html/static/css/themes/dark.css +++ b/src/librustdoc/html/static/css/themes/dark.css @@ -36,6 +36,20 @@ --stab-background-color: #314559; --stab-code-color: #e6e1cf; --search-color: #111; + --code-highlight-kw-color: #ab8ac1; + --code-highlight-kw-2-color: #769acb; + --code-highlight-lifetime-color: #d97f26; + --code-highlight-prelude-color: #769acb; + --code-highlight-prelude-val-color: #ee6868; + --code-highlight-number-color: #83a300; + --code-highlight-string-color: #83a300; + --code-highlight-literal-color: #ee6868; + --code-highlight-attribute-color: #ee6868; + --code-highlight-self-color: #ee6868; + --code-highlight-macro-color: #3e999f; + --code-highlight-question-mark-color: #ff9011; + --code-highlight-comment-color: #8d8d8b; + --code-highlight-doc-comment-color: #8ca375; } .slider { @@ -62,9 +76,6 @@ input:focus + .slider { .content .item-info::before { color: #ccc; } -pre.rust .comment { color: #8d8d8b; } -pre.rust .doccomment { color: #8ca375; } - body.source .example-wrap pre.rust a { background: #333; } @@ -86,18 +97,6 @@ details.rustdoc-toggle > summary::before { .src-line-numbers :target { background-color: transparent; } -/* Code highlighting */ -pre.rust .kw { color: #ab8ac1; } -pre.rust .kw-2, pre.rust .prelude-ty { color: #769acb; } -pre.rust .number, pre.rust .string { color: #83a300; } -pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val, -pre.rust .attribute { color: #ee6868; } -pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; } -pre.rust .lifetime { color: #d97f26; } -pre.rust .question-mark { - color: #ff9011; -} - pre.example-line-numbers { border-color: #4a4949; } diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css index 7287d5b62123b..058974c078c8d 100644 --- a/src/librustdoc/html/static/css/themes/light.css +++ b/src/librustdoc/html/static/css/themes/light.css @@ -36,6 +36,20 @@ --stab-background-color: #fff5d6; --stab-code-color: #000; --search-color: #000; + --code-highlight-kw-color: #8959a8; + --code-highlight-kw-2-color: #4271ae; + --code-highlight-lifetime-color: #b76514; + --code-highlight-prelude-color: #4271ae; + --code-highlight-prelude-val-color: #c82829; + --code-highlight-number-color: #718c00; + --code-highlight-string-color: #718c00; + --code-highlight-literal-color: #c82829; + --code-highlight-attribute-color: #c82829; + --code-highlight-self-color: #c82829; + --code-highlight-macro-color: #3e999f; + --code-highlight-question-mark-color: #ff9011; + --code-highlight-comment-color: #8e908c; + --code-highlight-doc-comment-color: #4d4d4c; } .slider { @@ -78,20 +92,6 @@ body.source .example-wrap pre.rust a { .src-line-numbers :target { background-color: transparent; } -/* Code highlighting */ -pre.rust .kw { color: #8959A8; } -pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; } -pre.rust .number, pre.rust .string { color: #718C00; } -pre.rust .self, pre.rust .bool-val, pre.rust .prelude-val, -pre.rust .attribute { color: #C82829; } -pre.rust .comment { color: #8E908C; } -pre.rust .doccomment { color: #4D4D4C; } -pre.rust .macro, pre.rust .macro-nonterminal { color: #3E999F; } -pre.rust .lifetime { color: #B76514; } -pre.rust .question-mark { - color: #ff9011; -} - pre.example-line-numbers { border-color: #c7c7c7; } diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index ef01b854e5a69..7e0cc668d7b59 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -674,39 +674,6 @@ fn usage(argv0: &str) { /// A result type used by several functions under `main()`. type MainResult = Result<(), ErrorGuaranteed>; -fn main_args(at_args: &[String]) -> MainResult { - let args = rustc_driver::args::arg_expand_all(at_args); - - let mut options = getopts::Options::new(); - for option in opts() { - (option.apply)(&mut options); - } - let matches = match options.parse(&args[1..]) { - Ok(m) => m, - Err(err) => { - early_error(ErrorOutputType::default(), &err.to_string()); - } - }; - - // Note that we discard any distinction between different non-zero exit - // codes from `from_matches` here. - let options = match config::Options::from_matches(&matches, args) { - Ok(opts) => opts, - Err(code) => { - return if code == 0 { - Ok(()) - } else { - Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) - }; - } - }; - rustc_interface::util::run_in_thread_pool_with_globals( - options.edition, - 1, // this runs single-threaded, even in a parallel compiler - move || main_options(options), - ) -} - fn wrap_return(diag: &rustc_errors::Handler, res: Result<(), String>) -> MainResult { match res { Ok(()) => Ok(()), @@ -737,7 +704,33 @@ fn run_renderer<'tcx, T: formats::FormatRenderer<'tcx>>( } } -fn main_options(options: config::Options) -> MainResult { +fn main_args(at_args: &[String]) -> MainResult { + let args = rustc_driver::args::arg_expand_all(at_args); + + let mut options = getopts::Options::new(); + for option in opts() { + (option.apply)(&mut options); + } + let matches = match options.parse(&args[1..]) { + Ok(m) => m, + Err(err) => { + early_error(ErrorOutputType::default(), &err.to_string()); + } + }; + + // Note that we discard any distinction between different non-zero exit + // codes from `from_matches` here. + let options = match config::Options::from_matches(&matches, args) { + Ok(opts) => opts, + Err(code) => { + return if code == 0 { + Ok(()) + } else { + Err(ErrorGuaranteed::unchecked_claim_error_was_emitted()) + }; + } + }; + let diag = core::new_handler( options.error_format, None, @@ -749,9 +742,12 @@ fn main_options(options: config::Options) -> MainResult { (true, true) => return wrap_return(&diag, markdown::test(options)), (true, false) => return doctest::run(options), (false, true) => { + // Session globals are required for symbol interning. return wrap_return( &diag, - markdown::render(&options.input, options.render_options, options.edition), + rustc_span::create_session_globals_then(options.edition, || { + markdown::render(&options.input, options.render_options, options.edition) + }), ); } (false, false) => {} @@ -777,9 +773,10 @@ fn main_options(options: config::Options) -> MainResult { let render_options = options.render_options.clone(); let scrape_examples_options = options.scrape_examples_options.clone(); let document_private = options.render_options.document_private; + let config = core::create_config(options); - interface::create_compiler_and_run(config, |compiler| { + interface::run_compiler(config, |compiler| { let sess = compiler.session(); if sess.opts.describe_lints { diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 0b557ef244e94..eb64ac455dc4c 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -5,7 +5,6 @@ use std::path::Path; use rustc_span::edition::Edition; use rustc_span::source_map::DUMMY_SP; -use rustc_span::Symbol; use crate::config::{Options, RenderOptions}; use crate::doctest::{Collector, GlobalTestOptions}; @@ -36,6 +35,8 @@ fn extract_leading_metadata(s: &str) -> (Vec<&str>, &str) { /// Render `input` (e.g., "foo.md") into an HTML file in `output` /// (e.g., output = "bar" => "bar/foo.html"). +/// +/// Requires session globals to be available, for symbol interning. pub(crate) fn render>( input: P, options: RenderOptions, @@ -133,7 +134,7 @@ pub(crate) fn test(options: Options) -> Result<(), String> { let mut opts = GlobalTestOptions::default(); opts.no_crate_inject = true; let mut collector = Collector::new( - Symbol::intern(&options.input.display().to_string()), + options.input.display().to_string(), options.clone(), true, opts, diff --git a/src/test/codegen/vec-in-place.rs b/src/test/codegen/vec-in-place.rs index 62139aa9bebde..5df3669056d0f 100644 --- a/src/test/codegen/vec-in-place.rs +++ b/src/test/codegen/vec-in-place.rs @@ -17,7 +17,7 @@ pub struct Foo { // Going from an aggregate struct to another type currently requires Copy to // enable the TrustedRandomAccess specialization. Without it optimizations do not yet -// reliably recognize the loops as noop for for repr(C) or non-Copy structs. +// reliably recognize the loops as noop for repr(C) or non-Copy structs. #[derive(Copy, Clone)] pub struct Bar { a: u64, diff --git a/src/test/rustdoc-gui/highlight-colors.goml b/src/test/rustdoc-gui/highlight-colors.goml new file mode 100644 index 0000000000000..dd01dbf6148d2 --- /dev/null +++ b/src/test/rustdoc-gui/highlight-colors.goml @@ -0,0 +1,57 @@ +// This test checks the highlight colors in the source code pages. +goto: "file://" + |DOC_PATH| + "/src/test_docs/lib.rs.html" +show-text: true + +local-storage: {"rustdoc-theme": "ayu", "rustdoc-use-system-theme": "false"} +reload: + +assert-css: ("pre.rust .kw", {"color": "rgb(255, 119, 51)"}, ALL) +assert-css: ("pre.rust .kw-2", {"color": "rgb(255, 119, 51)"}, ALL) +assert-css: ("pre.rust .prelude-ty", {"color": "rgb(105, 242, 223)"}, ALL) +assert-css: ("pre.rust .prelude-val", {"color": "rgb(255, 119, 51)"}, ALL) +assert-css: ("pre.rust .lifetime", {"color": "rgb(255, 119, 51)"}, ALL) +assert-css: ("pre.rust .number", {"color": "rgb(184, 204, 82)"}, ALL) +assert-css: ("pre.rust .string", {"color": "rgb(184, 204, 82)"}, ALL) +assert-css: ("pre.rust .bool-val", {"color": "rgb(255, 119, 51)"}, ALL) +assert-css: ("pre.rust .self", {"color": "rgb(54, 163, 217)"}, ALL) +assert-css: ("pre.rust .attribute", {"color": "rgb(230, 225, 207)"}, ALL) +assert-css: ("pre.rust .macro", {"color": "rgb(163, 122, 204)"}, ALL) +assert-css: ("pre.rust .question-mark", {"color": "rgb(255, 144, 17)"}, ALL) +assert-css: ("pre.rust .comment", {"color": "rgb(120, 135, 151)"}, ALL) +assert-css: ("pre.rust .doccomment", {"color": "rgb(161, 172, 136)"}, ALL) + +local-storage: {"rustdoc-theme": "dark"} +reload: + +assert-css: ("pre.rust .kw", {"color": "rgb(171, 138, 193)"}, ALL) +assert-css: ("pre.rust .kw-2", {"color": "rgb(118, 154, 203)"}, ALL) +assert-css: ("pre.rust .prelude-ty", {"color": "rgb(118, 154, 203)"}, ALL) +assert-css: ("pre.rust .prelude-val", {"color": "rgb(238, 104, 104)"}, ALL) +assert-css: ("pre.rust .lifetime", {"color": "rgb(217, 127, 38)"}, ALL) +assert-css: ("pre.rust .number", {"color": "rgb(131, 163, 0)"}, ALL) +assert-css: ("pre.rust .string", {"color": "rgb(131, 163, 0)"}, ALL) +assert-css: ("pre.rust .bool-val", {"color": "rgb(238, 104, 104)"}, ALL) +assert-css: ("pre.rust .self", {"color": "rgb(238, 104, 104)"}, ALL) +assert-css: ("pre.rust .attribute", {"color": "rgb(238, 104, 104)"}, ALL) +assert-css: ("pre.rust .macro", {"color": "rgb(62, 153, 159)"}, ALL) +assert-css: ("pre.rust .question-mark", {"color": "rgb(255, 144, 17)"}, ALL) +assert-css: ("pre.rust .comment", {"color": "rgb(141, 141, 139)"}, ALL) +assert-css: ("pre.rust .doccomment", {"color": "rgb(140, 163, 117)"}, ALL) + +local-storage: {"rustdoc-theme": "light"} +reload: + +assert-css: ("pre.rust .kw", {"color": "rgb(137, 89, 168)"}, ALL) +assert-css: ("pre.rust .kw-2", {"color": "rgb(66, 113, 174)"}, ALL) +assert-css: ("pre.rust .prelude-ty", {"color": "rgb(66, 113, 174)"}, ALL) +assert-css: ("pre.rust .prelude-val", {"color": "rgb(200, 40, 41)"}, ALL) +assert-css: ("pre.rust .lifetime", {"color": "rgb(183, 101, 20)"}, ALL) +assert-css: ("pre.rust .number", {"color": "rgb(113, 140, 0)"}, ALL) +assert-css: ("pre.rust .string", {"color": "rgb(113, 140, 0)"}, ALL) +assert-css: ("pre.rust .bool-val", {"color": "rgb(200, 40, 41)"}, ALL) +assert-css: ("pre.rust .self", {"color": "rgb(200, 40, 41)"}, ALL) +assert-css: ("pre.rust .attribute", {"color": "rgb(200, 40, 41)"}, ALL) +assert-css: ("pre.rust .macro", {"color": "rgb(62, 153, 159)"}, ALL) +assert-css: ("pre.rust .question-mark", {"color": "rgb(255, 144, 17)"}, ALL) +assert-css: ("pre.rust .comment", {"color": "rgb(142, 144, 140)"}, ALL) +assert-css: ("pre.rust .doccomment", {"color": "rgb(77, 77, 76)"}, ALL) diff --git a/src/test/rustdoc-gui/src/test_docs/lib.rs b/src/test/rustdoc-gui/src/test_docs/lib.rs index 33c74e3a331cd..cc0efe7231a43 100644 --- a/src/test/rustdoc-gui/src/test_docs/lib.rs +++ b/src/test/rustdoc-gui/src/test_docs/lib.rs @@ -363,9 +363,24 @@ pub trait TraitWithNoDocblocks { pub struct TypeWithNoDocblocks; +impl TypeWithNoDocblocks { + fn x() -> Option { + Some(Self) + } + fn y() -> Option { + // code comment + let t = Self::x()?; + Some(0) + } +} + impl TypeWithNoDocblocks { pub fn first_fn(&self) {} - pub fn second_fn(&self) {} + pub fn second_fn<'a>(&'a self) { + let x = 12; + let y = "a"; + let z = false; + } } pub unsafe fn unsafe_fn() {} diff --git a/src/test/rustdoc-ui/z-help.stdout b/src/test/rustdoc-ui/z-help.stdout index dbf3a8f00ee6d..46f11d2e5d1eb 100644 --- a/src/test/rustdoc-ui/z-help.stdout +++ b/src/test/rustdoc-ui/z-help.stdout @@ -36,6 +36,7 @@ -Z dump-mir-graphviz=val -- in addition to `.mir` files, create graphviz `.dot` files (and with `-Z instrument-coverage`, also create a `.dot` file for the MIR-derived coverage graph) (default: no) -Z dump-mir-spanview=val -- in addition to `.mir` files, create `.html` files to view spans for all `statement`s (including terminators), only `terminator` spans, or computed `block` spans (one span encompassing a block's terminator and all statements). If `-Z instrument-coverage` is also enabled, create an additional `.html` file showing the computed coverage spans. -Z dwarf-version=val -- version of DWARF debug information to emit (default: 2 or 4, depending on platform) + -Z dylib-lto=val -- enables LTO for dylib crate type -Z emit-stack-sizes=val -- emit a section containing stack size metadata (default: no) -Z emit-thin-lto=val -- emit the bc module with thin LTO info (default: yes) -Z export-executable-symbols=val -- export symbols from executables, as if they were dynamic libraries diff --git a/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr index f4efd131248ce..0b96a6bd7c009 100644 --- a/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr +++ b/src/test/ui/associated-item/associated-item-duplicate-names-2.stderr @@ -1,11 +1,11 @@ -error[E0201]: duplicate definitions with name `bar`: +error[E0592]: duplicate definitions with name `bar` --> $DIR/associated-item-duplicate-names-2.rs:5:5 | LL | const bar: bool = true; - | --------------- previous definition of `bar` here + | --------------- other definition for `bar` LL | fn bar() {} - | ^^^^^^^^ duplicate definition + | ^^^^^^^^ duplicate definitions for `bar` error: aborting due to previous error -For more information about this error, try `rustc --explain E0201`. +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/impl-duplicate-methods.rs b/src/test/ui/associated-item/impl-duplicate-methods.rs similarity index 57% rename from src/test/ui/impl-duplicate-methods.rs rename to src/test/ui/associated-item/impl-duplicate-methods.rs index adb09d7f56e93..328d54d5ac411 100644 --- a/src/test/ui/impl-duplicate-methods.rs +++ b/src/test/ui/associated-item/impl-duplicate-methods.rs @@ -3,7 +3,7 @@ struct Foo; impl Foo { fn orange(&self) {} fn orange(&self) {} - //~^ ERROR duplicate definition + //~^ ERROR duplicate definitions with name `orange` [E0592] } fn main() {} diff --git a/src/test/ui/associated-item/impl-duplicate-methods.stderr b/src/test/ui/associated-item/impl-duplicate-methods.stderr new file mode 100644 index 0000000000000..6f753845ac85a --- /dev/null +++ b/src/test/ui/associated-item/impl-duplicate-methods.stderr @@ -0,0 +1,11 @@ +error[E0592]: duplicate definitions with name `orange` + --> $DIR/impl-duplicate-methods.rs:5:5 + | +LL | fn orange(&self) {} + | ---------------- other definition for `orange` +LL | fn orange(&self) {} + | ^^^^^^^^^^^^^^^^ duplicate definitions for `orange` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/issues/issue-17718-static-move.rs b/src/test/ui/borrowck/issue-17718-static-move.rs similarity index 100% rename from src/test/ui/issues/issue-17718-static-move.rs rename to src/test/ui/borrowck/issue-17718-static-move.rs diff --git a/src/test/ui/issues/issue-17718-static-move.stderr b/src/test/ui/borrowck/issue-17718-static-move.stderr similarity index 100% rename from src/test/ui/issues/issue-17718-static-move.stderr rename to src/test/ui/borrowck/issue-17718-static-move.stderr diff --git a/src/test/ui/issues/issue-17718-constants-not-static.rs b/src/test/ui/consts/issue-17718-constants-not-static.rs similarity index 100% rename from src/test/ui/issues/issue-17718-constants-not-static.rs rename to src/test/ui/consts/issue-17718-constants-not-static.rs diff --git a/src/test/ui/issues/issue-17718-constants-not-static.stderr b/src/test/ui/consts/issue-17718-constants-not-static.stderr similarity index 100% rename from src/test/ui/issues/issue-17718-constants-not-static.stderr rename to src/test/ui/consts/issue-17718-constants-not-static.stderr diff --git a/src/test/ui/issues/issue-17718-const-destructors.rs b/src/test/ui/drop/issue-17718-const-destructors.rs similarity index 100% rename from src/test/ui/issues/issue-17718-const-destructors.rs rename to src/test/ui/drop/issue-17718-const-destructors.rs diff --git a/src/test/ui/issues/issue-48962.rs b/src/test/ui/drop/issue-48962.rs similarity index 100% rename from src/test/ui/issues/issue-48962.rs rename to src/test/ui/drop/issue-48962.rs diff --git a/src/test/ui/error-codes/E0201.rs b/src/test/ui/error-codes/E0201.rs index adefd4bcd4600..04b37091b2f16 100644 --- a/src/test/ui/error-codes/E0201.rs +++ b/src/test/ui/error-codes/E0201.rs @@ -2,7 +2,7 @@ struct Foo(u8); impl Foo { fn bar(&self) -> bool { self.0 > 5 } - fn bar() {} //~ ERROR E0201 + fn bar() {} //~ ERROR E0592 } trait Baz { diff --git a/src/test/ui/error-codes/E0201.stderr b/src/test/ui/error-codes/E0201.stderr index f72145a82447b..608ff69177694 100644 --- a/src/test/ui/error-codes/E0201.stderr +++ b/src/test/ui/error-codes/E0201.stderr @@ -21,14 +21,15 @@ LL | type Quux = u32; LL | type Quux = u32; | ^^^^^^^^^^^^^^^^ duplicate definition -error[E0201]: duplicate definitions with name `bar`: +error[E0592]: duplicate definitions with name `bar` --> $DIR/E0201.rs:5:5 | LL | fn bar(&self) -> bool { self.0 > 5 } - | --------------------- previous definition of `bar` here + | --------------------- other definition for `bar` LL | fn bar() {} - | ^^^^^^^^ duplicate definition + | ^^^^^^^^ duplicate definitions for `bar` error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0201`. +Some errors have detailed explanations: E0201, E0592. +For more information about an error, try `rustc --explain E0201`. diff --git a/src/test/ui/impl-duplicate-methods.stderr b/src/test/ui/impl-duplicate-methods.stderr deleted file mode 100644 index c19702a5bf0cf..0000000000000 --- a/src/test/ui/impl-duplicate-methods.stderr +++ /dev/null @@ -1,11 +0,0 @@ -error[E0201]: duplicate definitions with name `orange`: - --> $DIR/impl-duplicate-methods.rs:5:5 - | -LL | fn orange(&self) {} - | ---------------- previous definition of `orange` here -LL | fn orange(&self) {} - | ^^^^^^^^^^^^^^^^ duplicate definition - -error: aborting due to previous error - -For more information about this error, try `rustc --explain E0201`. diff --git a/src/test/ui/issues/issue-4265.stderr b/src/test/ui/issues/issue-4265.stderr index 27e83d4957493..8c7303f3c3c51 100644 --- a/src/test/ui/issues/issue-4265.stderr +++ b/src/test/ui/issues/issue-4265.stderr @@ -1,12 +1,12 @@ -error[E0201]: duplicate definitions with name `bar`: +error[E0592]: duplicate definitions with name `bar` --> $DIR/issue-4265.rs:10:5 | LL | fn bar() { - | -------- previous definition of `bar` here + | -------- other definition for `bar` ... LL | fn bar() { - | ^^^^^^^^ duplicate definition + | ^^^^^^^^ duplicate definitions for `bar` error: aborting due to previous error -For more information about this error, try `rustc --explain E0201`. +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/issues/issue-77993-1.rs b/src/test/ui/issues/issue-77993-1.rs deleted file mode 100644 index 515b3bc09f076..0000000000000 --- a/src/test/ui/issues/issue-77993-1.rs +++ /dev/null @@ -1,12 +0,0 @@ -#[derive(Clone)] -struct InGroup { - it: It, - //~^ ERROR cannot find type `It` in this scope - f: F, -} -fn dates_in_year() -> impl Clone { - InGroup { f: |d| d } - //~^ ERROR missing field `it` in initializer of `InGroup<_>` -} - -fn main() {} diff --git a/src/test/ui/issues/issue-77993-1.stderr b/src/test/ui/issues/issue-77993-1.stderr deleted file mode 100644 index 3dc78ba6f8563..0000000000000 --- a/src/test/ui/issues/issue-77993-1.stderr +++ /dev/null @@ -1,16 +0,0 @@ -error[E0412]: cannot find type `It` in this scope - --> $DIR/issue-77993-1.rs:3:9 - | -LL | it: It, - | ^^ not found in this scope - -error[E0063]: missing field `it` in initializer of `InGroup<_>` - --> $DIR/issue-77993-1.rs:8:5 - | -LL | InGroup { f: |d| d } - | ^^^^^^^ missing `it` - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0063, E0412. -For more information about an error, try `rustc --explain E0063`. diff --git a/src/test/ui/let-else/let-else-then-diverge.rs b/src/test/ui/let-else/let-else-then-diverge.rs index 1c8f7d758e8a6..1a75310c94ff5 100644 --- a/src/test/ui/let-else/let-else-then-diverge.rs +++ b/src/test/ui/let-else/let-else-then-diverge.rs @@ -1,8 +1,6 @@ -// -// popped up in in #94012, where an alternative desugaring was +// popped up in #94012, where an alternative desugaring was // causing unreachable code errors - #![deny(unused_variables)] #![deny(unreachable_code)] diff --git a/src/test/ui/let-else/let-else-then-diverge.stderr b/src/test/ui/let-else/let-else-then-diverge.stderr index ceb61029d3863..470a11d4769bc 100644 --- a/src/test/ui/let-else/let-else-then-diverge.stderr +++ b/src/test/ui/let-else/let-else-then-diverge.stderr @@ -1,11 +1,11 @@ error: unused variable: `x` - --> $DIR/let-else-then-diverge.rs:11:13 + --> $DIR/let-else-then-diverge.rs:9:13 | LL | let x = 5; | ^ help: if this is intentional, prefix it with an underscore: `_x` | note: the lint level is defined here - --> $DIR/let-else-then-diverge.rs:6:9 + --> $DIR/let-else-then-diverge.rs:4:9 | LL | #![deny(unused_variables)] | ^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/methods/method-macro-backtrace.stderr b/src/test/ui/methods/method-macro-backtrace.stderr index 7ae00835c965d..dd616c4a5e75d 100644 --- a/src/test/ui/methods/method-macro-backtrace.stderr +++ b/src/test/ui/methods/method-macro-backtrace.stderr @@ -1,11 +1,11 @@ -error[E0201]: duplicate definitions with name `bar`: +error[E0592]: duplicate definitions with name `bar` --> $DIR/method-macro-backtrace.rs:22:5 | LL | fn bar(&self) { } - | ------------- previous definition of `bar` here + | ------------- other definition for `bar` LL | fn bar(&self) { } - | ^^^^^^^^^^^^^ duplicate definition + | ^^^^^^^^^^^^^ duplicate definitions for `bar` error: aborting due to previous error -For more information about this error, try `rustc --explain E0201`. +For more information about this error, try `rustc --explain E0592`. diff --git a/src/test/ui/issues/issue-5500-1.rs b/src/test/ui/never_type/issue-5500-1.rs similarity index 100% rename from src/test/ui/issues/issue-5500-1.rs rename to src/test/ui/never_type/issue-5500-1.rs diff --git a/src/test/ui/issues/issue-17718-parse-const.rs b/src/test/ui/parser/issue-17718-parse-const.rs similarity index 100% rename from src/test/ui/issues/issue-17718-parse-const.rs rename to src/test/ui/parser/issue-17718-parse-const.rs diff --git a/src/test/ui/issues/issue-17718-patterns.rs b/src/test/ui/pattern/issue-17718-patterns.rs similarity index 100% rename from src/test/ui/issues/issue-17718-patterns.rs rename to src/test/ui/pattern/issue-17718-patterns.rs diff --git a/src/test/ui/issues/issue-17718-patterns.stderr b/src/test/ui/pattern/issue-17718-patterns.stderr similarity index 100% rename from src/test/ui/issues/issue-17718-patterns.stderr rename to src/test/ui/pattern/issue-17718-patterns.stderr diff --git a/src/test/ui/issues/auxiliary/issue-17718-const-privacy.rs b/src/test/ui/privacy/auxiliary/issue-17718-const-privacy.rs similarity index 100% rename from src/test/ui/issues/auxiliary/issue-17718-const-privacy.rs rename to src/test/ui/privacy/auxiliary/issue-17718-const-privacy.rs diff --git a/src/test/ui/issues/issue-17718-const-privacy.rs b/src/test/ui/privacy/issue-17718-const-privacy.rs similarity index 100% rename from src/test/ui/issues/issue-17718-const-privacy.rs rename to src/test/ui/privacy/issue-17718-const-privacy.rs diff --git a/src/test/ui/issues/issue-17718-const-privacy.stderr b/src/test/ui/privacy/issue-17718-const-privacy.stderr similarity index 100% rename from src/test/ui/issues/issue-17718-const-privacy.stderr rename to src/test/ui/privacy/issue-17718-const-privacy.stderr diff --git a/src/test/ui/proc-macro/call-deprecated.rs b/src/test/ui/proc-macro/call-deprecated.rs index b92cc23638ae1..cb634671bd4fa 100644 --- a/src/test/ui/proc-macro/call-deprecated.rs +++ b/src/test/ui/proc-macro/call-deprecated.rs @@ -5,7 +5,7 @@ extern crate call_deprecated; // These first two `#[allow(deprecated)]` attributes // do nothing, since the AST nodes for `First` and `Second` -// haven't been been assigned a `NodeId`. +// haven't been assigned a `NodeId`. // See #63221 for a discussion about how we should // handle the interaction of 'inert' attributes and // proc-macro attributes. diff --git a/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr b/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr index 2570c36b8108e..be4a523155825 100644 --- a/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr +++ b/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.disallowed.stderr @@ -75,26 +75,26 @@ LL | if let first = &opt && let None = Some(1) {} = note: this pattern will always match = help: consider moving it outside of the construct -error: irrefutable `let` patterns +error: irrefutable `if let` guard patterns --> $DIR/irrefutable-lets.rs:44:28 | LL | Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {}, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: these patterns will always match, so the `let` is useless - = help: consider removing `let` + = note: these patterns will always match, so the guard is useless + = help: consider removing the guard and adding a `let` inside the match arm -error: leading irrefutable pattern in let chain - --> $DIR/irrefutable-lets.rs:50:28 +error: trailing irrefutable patterns in let chain + --> $DIR/irrefutable-lets.rs:59:16 | -LL | Some(ref first) if let Range { start: local_start, end: _ } = first - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | && let v = local_end && let w = v => {}, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: this pattern will always match - = help: consider moving it outside of the construct + = note: these patterns will always match + = help: consider moving them into the body error: irrefutable `while let` patterns - --> $DIR/irrefutable-lets.rs:59:11 + --> $DIR/irrefutable-lets.rs:68:11 | LL | while let first = &opt && let (a, b) = (1, 2) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -103,7 +103,7 @@ LL | while let first = &opt && let (a, b) = (1, 2) {} = help: consider instead using a `loop { ... }` with a `let` inside it error: trailing irrefutable patterns in let chain - --> $DIR/irrefutable-lets.rs:62:40 + --> $DIR/irrefutable-lets.rs:71:40 | LL | while let Some(ref first) = opt && let second = first && let _third = second {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs b/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs index 3d1626e8ffb9a..9afb6853b3627 100644 --- a/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs +++ b/src/test/ui/rfc-2497-if-let-chains/irrefutable-lets.rs @@ -42,18 +42,27 @@ fn main() { match opt { Some(ref first) if let second = first && let _third = second && let v = 4 + 4 => {}, - //[disallowed]~^ ERROR irrefutable `let` patterns + //[disallowed]~^ ERROR irrefutable `if let` guard patterns _ => {} } + // No error about leading irrefutable patterns: the expr on the rhs might + // use the bindings created by the match. match opt { Some(ref first) if let Range { start: local_start, end: _ } = first - //[disallowed]~^ ERROR leading irrefutable pattern in let chain && let None = local_start => {}, _ => {} } - // No error, despite the prefix being irrefutable + match opt { + Some(ref first) if let Range { start: Some(_), end: local_end } = first + && let v = local_end && let w = v => {}, + //[disallowed]~^ ERROR trailing irrefutable patterns in let chain + _ => {} + } + + // No error, despite the prefix being irrefutable: moving out could change the behaviour, + // due to possible side effects of the operation. while let first = &opt && let Some(ref second) = first && let None = second.start {} while let first = &opt && let (a, b) = (1, 2) {} diff --git a/src/test/ui/issues/issue-17718-static-sync.rs b/src/test/ui/statics/issue-17718-static-sync.rs similarity index 100% rename from src/test/ui/issues/issue-17718-static-sync.rs rename to src/test/ui/statics/issue-17718-static-sync.rs diff --git a/src/test/ui/issues/issue-17718-static-sync.stderr b/src/test/ui/statics/issue-17718-static-sync.stderr similarity index 100% rename from src/test/ui/issues/issue-17718-static-sync.stderr rename to src/test/ui/statics/issue-17718-static-sync.stderr diff --git a/src/test/ui/issues/issue-17718-static-unsafe-interior.rs b/src/test/ui/statics/issue-17718-static-unsafe-interior.rs similarity index 100% rename from src/test/ui/issues/issue-17718-static-unsafe-interior.rs rename to src/test/ui/statics/issue-17718-static-unsafe-interior.rs diff --git a/src/test/ui/threads-sendsync/issue-43733-2.rs b/src/test/ui/threads-sendsync/issue-43733-2.rs index 21ea8e9a20982..32baeec4359c1 100644 --- a/src/test/ui/threads-sendsync/issue-43733-2.rs +++ b/src/test/ui/threads-sendsync/issue-43733-2.rs @@ -1,5 +1,5 @@ +// ignore-wasm32 // dont-check-compiler-stderr - #![feature(cfg_target_thread_local, thread_local_internals)] // On platforms *without* `#[thread_local]`, use diff --git a/src/test/ui/threads-sendsync/issue-43733.rs b/src/test/ui/threads-sendsync/issue-43733.rs index 0ac6f588fb1d9..935e02944b97f 100644 --- a/src/test/ui/threads-sendsync/issue-43733.rs +++ b/src/test/ui/threads-sendsync/issue-43733.rs @@ -1,8 +1,8 @@ +// ignore-wasm32 // revisions: mir thir // [thir]compile-flags: -Z thir-unsafeck // normalize-stderr-test: "__FastLocalKeyInner::::get" -> "$$LOCALKEYINNER::::get" // normalize-stderr-test: "__OsLocalKeyInner::::get" -> "$$LOCALKEYINNER::::get" - #![feature(thread_local)] #![feature(cfg_target_thread_local, thread_local_internals)] diff --git a/src/test/ui/traits/issue-102989.rs b/src/test/ui/traits/issue-102989.rs new file mode 100644 index 0000000000000..cb1e3271d26e8 --- /dev/null +++ b/src/test/ui/traits/issue-102989.rs @@ -0,0 +1,19 @@ +//~ ERROR can't find crate for `profiler_builtins` +// compile-flags: -Cinstrument-coverage +// normalize-stderr-test "loaded from .*libcore-.*.rlib" -> "loaded from SYSROOT/libcore-*.rlib" + +#![no_core] +#![feature(no_core, lang_items)] +#[lang="sized"] +trait Sized { } //~ ERROR found duplicate lang item `sized` + +fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + //~^ ERROR `self` parameter is only allowed in associated functions + //~| ERROR cannot find type `Struct` in this scope + //~| ERROR mismatched types + let x = x << 1; + //~^ ERROR the size for values of type `{integer}` cannot be known at compilation time + //~| ERROR cannot find value `x` in this scope +} + +fn main() {} diff --git a/src/test/ui/traits/issue-102989.stderr b/src/test/ui/traits/issue-102989.stderr new file mode 100644 index 0000000000000..efea2251a13f8 --- /dev/null +++ b/src/test/ui/traits/issue-102989.stderr @@ -0,0 +1,72 @@ +error: `self` parameter is only allowed in associated functions + --> $DIR/issue-102989.rs:10:15 + | +LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ^^^^ not semantically valid as function parameter + | + = note: associated functions are those in `impl` or `trait` definitions + +error[E0412]: cannot find type `Struct` in this scope + --> $DIR/issue-102989.rs:10:22 + | +LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ^^^^^^ not found in this scope + +error[E0425]: cannot find value `x` in this scope + --> $DIR/issue-102989.rs:14:13 + | +LL | let x = x << 1; + | ^ help: a local variable with a similar name exists: `f` + +error: `profiler_builtins` crate (required by compiler options) is not compatible with crate attribute `#![no_core]` + +error[E0463]: can't find crate for `profiler_builtins` + | + = note: the compiler may have been built without the profiler runtime + +error[E0152]: found duplicate lang item `sized` + --> $DIR/issue-102989.rs:8:1 + | +LL | trait Sized { } + | ^^^^^^^^^^^ + | + = note: the lang item is first defined in crate `core`. + = note: first definition in `core` loaded from SYSROOT/libcore-*.rlib + = note: second definition in the local crate (`issue_102989`) + +error: `#[panic_handler]` function required, but not found + +error: language item required, but not found: `eh_personality` + | + = note: this can occur when a binary crate with `#![no_std]` is compiled for a target where `eh_personality` is defined in the standard library + = help: you may be able to compile for a target that doesn't need `eh_personality`, specify a target with `--target` or in `.cargo/config` + +error[E0277]: the size for values of type `{integer}` cannot be known at compilation time + --> $DIR/issue-102989.rs:14:15 + | +LL | let x = x << 1; + | ^^ doesn't have a size known at compile-time + | + = help: the trait `core::marker::Sized` is not implemented for `{integer}` + +error[E0308]: mismatched types + --> $DIR/issue-102989.rs:10:42 + | +LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ---------- ^^^^ expected `&u32`, found `()` + | | + | implicitly returns `()` as its body has no tail or `return` expression + | +note: consider returning one of these bindings + --> $DIR/issue-102989.rs:10:30 + | +LL | fn ref_Struct(self: &Struct, f: &u32) -> &u32 { + | ^ +... +LL | let x = x << 1; + | ^ + +error: aborting due to 10 previous errors + +Some errors have detailed explanations: E0152, E0277, E0308, E0412, E0425, E0463. +For more information about an error, try `rustc --explain E0152`. diff --git a/src/tools/tidy/src/ui_tests.rs b/src/tools/tidy/src/ui_tests.rs index 052abfdab5dd3..3815259c9aac9 100644 --- a/src/tools/tidy/src/ui_tests.rs +++ b/src/tools/tidy/src/ui_tests.rs @@ -7,8 +7,8 @@ use std::path::Path; const ENTRY_LIMIT: usize = 1000; // FIXME: The following limits should be reduced eventually. -const ROOT_ENTRY_LIMIT: usize = 950; -const ISSUES_ENTRY_LIMIT: usize = 2141; +const ROOT_ENTRY_LIMIT: usize = 948; +const ISSUES_ENTRY_LIMIT: usize = 2126; fn check_entries(path: &Path, bad: &mut bool) { let dirs = walkdir::WalkDir::new(&path.join("test/ui"))