From 7cee1b4aebf4ac1a9779fa352c249dcd263a6427 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Thu, 24 Feb 2022 22:37:53 +0000 Subject: [PATCH 01/15] ARM: Only allow using d16-d31 with asm! when supported by the target Support can be determined by checking for the "d32" LLVM feature. --- compiler/rustc_codegen_ssa/src/target_features.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_target/src/asm/arm.rs | 5 ++++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 77166c89735e4..14045ad7ff524 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -36,6 +36,7 @@ const ARM_ALLOWED_FEATURES: &[(&str, Option)] = &[ // #[target_feature]. ("thumb-mode", Some(sym::arm_target_feature)), ("thumb2", Some(sym::arm_target_feature)), + ("d32", Some(sym::arm_target_feature)), ]; const AARCH64_ALLOWED_FEATURES: &[(&str, Option)] = &[ diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 6767593bbc51a..9d452131fa6ac 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -539,6 +539,7 @@ symbols! { custom_inner_attributes, custom_test_frameworks, d, + d32, dbg_macro, dead_code, dealloc, diff --git a/compiler/rustc_target/src/asm/arm.rs b/compiler/rustc_target/src/asm/arm.rs index 88f2d3f80d2c3..aaa632333db38 100644 --- a/compiler/rustc_target/src/asm/arm.rs +++ b/compiler/rustc_target/src/asm/arm.rs @@ -50,9 +50,12 @@ impl ArmInlineAsmRegClass { match self { Self::reg => types! { _: I8, I16, I32, F32; }, Self::sreg | Self::sreg_low16 => types! { vfp2: I32, F32; }, - Self::dreg | Self::dreg_low16 | Self::dreg_low8 => types! { + Self::dreg_low16 | Self::dreg_low8 => types! { vfp2: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2); }, + Self::dreg => types! { + d32: I64, F64, VecI8(8), VecI16(4), VecI32(2), VecI64(1), VecF32(2); + }, Self::qreg | Self::qreg_low8 | Self::qreg_low4 => types! { neon: VecI8(16), VecI16(8), VecI32(4), VecI64(2), VecF32(4); }, From 2d854f9c340df887e30896f49270ae81feb3e227 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Wed, 2 Mar 2022 15:22:32 +0100 Subject: [PATCH 02/15] Remove num_cpus dependency from bootstrap, build-manifest and rustc_session --- Cargo.lock | 3 --- compiler/rustc_session/Cargo.toml | 1 - compiler/rustc_session/src/options.rs | 2 +- src/bootstrap/Cargo.toml | 1 - src/bootstrap/config.rs | 2 +- src/bootstrap/flags.rs | 2 +- src/bootstrap/lib.rs | 4 +++- src/tools/build-manifest/Cargo.toml | 1 - src/tools/build-manifest/src/main.rs | 2 +- 9 files changed, 7 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f0c6e371c38be..716f4d7501467 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -221,7 +221,6 @@ dependencies = [ "getopts", "ignore", "libc", - "num_cpus", "once_cell", "opener", "pretty_assertions", @@ -249,7 +248,6 @@ dependencies = [ "anyhow", "flate2", "hex 0.4.2", - "num_cpus", "rayon", "serde", "serde_json", @@ -4241,7 +4239,6 @@ name = "rustc_session" version = "0.0.0" dependencies = [ "getopts", - "num_cpus", "rustc_ast", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_session/Cargo.toml b/compiler/rustc_session/Cargo.toml index 37cfc4a0dc3c2..6b1eaa4d399d9 100644 --- a/compiler/rustc_session/Cargo.toml +++ b/compiler/rustc_session/Cargo.toml @@ -15,6 +15,5 @@ rustc_serialize = { path = "../rustc_serialize" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_span = { path = "../rustc_span" } rustc_fs_util = { path = "../rustc_fs_util" } -num_cpus = "1.0" rustc_ast = { path = "../rustc_ast" } rustc_lint_defs = { path = "../rustc_lint_defs" } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index c2b13346cd6c9..43123d30ad5c6 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -551,7 +551,7 @@ mod parse { crate fn parse_threads(slot: &mut usize, v: Option<&str>) -> bool { match v.and_then(|s| s.parse().ok()) { Some(0) => { - *slot = ::num_cpus::get(); + *slot = std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get); true } Some(i) => { diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml index 592a137e379de..02efc08cc791f 100644 --- a/src/bootstrap/Cargo.toml +++ b/src/bootstrap/Cargo.toml @@ -37,7 +37,6 @@ test = false build_helper = { path = "../build_helper" } cmake = "0.1.38" filetime = "0.2" -num_cpus = "1.0" getopts = "0.2.19" cc = "1.0.69" libc = "0.2" diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs index d6f77fe6cd6d0..ce76ccd57551d 100644 --- a/src/bootstrap/config.rs +++ b/src/bootstrap/config.rs @@ -1187,7 +1187,7 @@ fn set(field: &mut T, val: Option) { fn threads_from_config(v: u32) -> u32 { match v { - 0 => num_cpus::get() as u32, + 0 => std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32, n => n, } } diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index 9180c5f03af68..74528f2752f5f 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -208,7 +208,7 @@ To learn more about a subcommand, run `./x.py -h`", let j_msg = format!( "number of jobs to run in parallel; \ defaults to {} (this host's logical CPU count)", - num_cpus::get() + std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) ); opts.optopt("j", "jobs", &j_msg, "JOBS"); opts.optflag("h", "help", "print this help message"); diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 86339c8d7f88d..6a58de40181c2 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -917,7 +917,9 @@ impl Build { /// Returns the number of parallel jobs that have been configured for this /// build. fn jobs(&self) -> u32 { - self.config.jobs.unwrap_or_else(|| num_cpus::get() as u32) + self.config.jobs.unwrap_or_else(|| { + std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) as u32 + }) } fn debuginfo_map_to(&self, which: GitRepo) -> Option { diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index c022d3aa0acd7..c437bde5ae69a 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -13,4 +13,3 @@ tar = "0.4.29" sha2 = "0.10.1" rayon = "1.5.1" hex = "0.4.2" -num_cpus = "1.13.0" diff --git a/src/tools/build-manifest/src/main.rs b/src/tools/build-manifest/src/main.rs index 8a62146abfc4e..378efeb644375 100644 --- a/src/tools/build-manifest/src/main.rs +++ b/src/tools/build-manifest/src/main.rs @@ -208,7 +208,7 @@ fn main() { let num_threads = if let Some(num) = env::var_os("BUILD_MANIFEST_NUM_THREADS") { num.to_str().unwrap().parse().expect("invalid number for BUILD_MANIFEST_NUM_THREADS") } else { - num_cpus::get() + std::thread::available_parallelism().map_or(1, std::num::NonZeroUsize::get) }; rayon::ThreadPoolBuilder::new() .num_threads(num_threads) From 78e7d9b0500e85032db995758531a1a59b568ad1 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Tue, 1 Mar 2022 17:03:13 +0000 Subject: [PATCH 03/15] Re-enable debuginfo tests that have been ignored Most of these tests either ran perfectly once enabled or only needed a small amount of tweaking to get passing or used ignore-test when ignore-lldb would have been more appropriate. With this change we go from 64 ignored tests to 50. --- src/test/debuginfo/basic-types-globals-metadata.rs | 3 +-- src/test/debuginfo/c-style-enum.rs | 1 - src/test/debuginfo/cross-crate-spans.rs | 1 - src/test/debuginfo/destructured-for-loop-variable.rs | 4 ---- src/test/debuginfo/function-arg-initialization.rs | 2 +- src/test/debuginfo/lexical-scopes-in-block-expression.rs | 1 - src/test/debuginfo/limited-debuginfo.rs | 1 - src/test/debuginfo/method-on-enum.rs | 2 +- src/test/debuginfo/simple-struct.rs | 1 - src/test/debuginfo/simple-tuple.rs | 1 - src/test/debuginfo/union-smoke.rs | 1 - src/test/debuginfo/vec.rs | 1 - 12 files changed, 3 insertions(+), 16 deletions(-) diff --git a/src/test/debuginfo/basic-types-globals-metadata.rs b/src/test/debuginfo/basic-types-globals-metadata.rs index 3934d3c7a685e..30e4b882076af 100644 --- a/src/test/debuginfo/basic-types-globals-metadata.rs +++ b/src/test/debuginfo/basic-types-globals-metadata.rs @@ -1,5 +1,4 @@ // min-lldb-version: 310 -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // compile-flags:-g // gdb-command:run @@ -11,7 +10,7 @@ // gdb-check:type = isize // gdbg-command:whatis 'basic_types_globals_metadata::C' // gdbr-command:whatis basic_types_globals_metadata::C -// gdb-check:type = char +// gdb-check:type = char32_t // gdbg-command:whatis 'basic_types_globals_metadata::I8' // gdbr-command:whatis basic_types_globals_metadata::I8 // gdb-check:type = i8 diff --git a/src/test/debuginfo/c-style-enum.rs b/src/test/debuginfo/c-style-enum.rs index dce34fc0dcf5e..86079e45b2727 100644 --- a/src/test/debuginfo/c-style-enum.rs +++ b/src/test/debuginfo/c-style-enum.rs @@ -1,5 +1,4 @@ // ignore-aarch64 -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // min-lldb-version: 310 // compile-flags:-g diff --git a/src/test/debuginfo/cross-crate-spans.rs b/src/test/debuginfo/cross-crate-spans.rs index 7c58e1db23f35..57077f4aa802f 100644 --- a/src/test/debuginfo/cross-crate-spans.rs +++ b/src/test/debuginfo/cross-crate-spans.rs @@ -5,7 +5,6 @@ // This fails on lldb 6.0.1 on x86-64 Fedora 28; so mark it macOS-only // for now. -// only-macos // aux-build:cross_crate_spans.rs extern crate cross_crate_spans; diff --git a/src/test/debuginfo/destructured-for-loop-variable.rs b/src/test/debuginfo/destructured-for-loop-variable.rs index 15cb88ef25d5b..eb821a580564a 100644 --- a/src/test/debuginfo/destructured-for-loop-variable.rs +++ b/src/test/debuginfo/destructured-for-loop-variable.rs @@ -1,9 +1,5 @@ // min-lldb-version: 310 -// This fails on lldb 6.0.1 on x86-64 Fedora 28; so mark it macOS-only -// for now. -// only-macos - // compile-flags:-g // === GDB TESTS =================================================================================== diff --git a/src/test/debuginfo/function-arg-initialization.rs b/src/test/debuginfo/function-arg-initialization.rs index dea1339517b46..ad432d2e7d370 100644 --- a/src/test/debuginfo/function-arg-initialization.rs +++ b/src/test/debuginfo/function-arg-initialization.rs @@ -1,4 +1,4 @@ -// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 +// ignore-lldb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // min-lldb-version: 310 // This test case checks if function arguments already have the correct value diff --git a/src/test/debuginfo/lexical-scopes-in-block-expression.rs b/src/test/debuginfo/lexical-scopes-in-block-expression.rs index 72621ffc74267..fee4ac7bd2f6d 100644 --- a/src/test/debuginfo/lexical-scopes-in-block-expression.rs +++ b/src/test/debuginfo/lexical-scopes-in-block-expression.rs @@ -1,5 +1,4 @@ // min-lldb-version: 310 -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // compile-flags:-g diff --git a/src/test/debuginfo/limited-debuginfo.rs b/src/test/debuginfo/limited-debuginfo.rs index bd381cd0e22d3..bf03ac3dd29e9 100644 --- a/src/test/debuginfo/limited-debuginfo.rs +++ b/src/test/debuginfo/limited-debuginfo.rs @@ -1,5 +1,4 @@ // ignore-lldb -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // compile-flags:-C debuginfo=1 diff --git a/src/test/debuginfo/method-on-enum.rs b/src/test/debuginfo/method-on-enum.rs index aaa9bd9d6f97a..e746895797820 100644 --- a/src/test/debuginfo/method-on-enum.rs +++ b/src/test/debuginfo/method-on-enum.rs @@ -1,5 +1,5 @@ // min-lldb-version: 310 -// ignore-test // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 +// ignore-lldb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // compile-flags:-g diff --git a/src/test/debuginfo/simple-struct.rs b/src/test/debuginfo/simple-struct.rs index aa3cf023a718d..fc2b1f64221d1 100644 --- a/src/test/debuginfo/simple-struct.rs +++ b/src/test/debuginfo/simple-struct.rs @@ -1,5 +1,4 @@ // min-lldb-version: 310 -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // compile-flags:-g diff --git a/src/test/debuginfo/simple-tuple.rs b/src/test/debuginfo/simple-tuple.rs index 0807cfedce01d..b89a51437b3ba 100644 --- a/src/test/debuginfo/simple-tuple.rs +++ b/src/test/debuginfo/simple-tuple.rs @@ -1,5 +1,4 @@ // min-lldb-version: 310 -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // compile-flags:-g diff --git a/src/test/debuginfo/union-smoke.rs b/src/test/debuginfo/union-smoke.rs index 4d4b6cc96fb57..5d1cd03ad3e8c 100644 --- a/src/test/debuginfo/union-smoke.rs +++ b/src/test/debuginfo/union-smoke.rs @@ -1,5 +1,4 @@ // min-lldb-version: 310 -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // ignore-gdb-version: 7.11.90 - 7.12.9 diff --git a/src/test/debuginfo/vec.rs b/src/test/debuginfo/vec.rs index 895661816b864..9bead21fe5f88 100644 --- a/src/test/debuginfo/vec.rs +++ b/src/test/debuginfo/vec.rs @@ -1,5 +1,4 @@ // min-lldb-version: 310 -// ignore-gdb // Test temporarily ignored due to debuginfo tests being disabled, see PR 47155 // compile-flags:-g From 926bf1a3718fc408b2d75a7536b7a2ed3d2d070b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Thu, 3 Mar 2022 00:00:00 +0000 Subject: [PATCH 04/15] Pass LLVM string attributes as string slices --- compiler/rustc_codegen_llvm/src/abi.rs | 3 +- compiler/rustc_codegen_llvm/src/attributes.rs | 52 ++++++++----------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 5 +- compiler/rustc_codegen_llvm/src/llvm/mod.rs | 24 +++++++-- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 6 --- 5 files changed, 47 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index f8f6956c47e4d..b14a4f28c756c 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -561,8 +561,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if self.conv == Conv::CCmseNonSecureCall { // This will probably get ignored on all targets but those supporting the TrustZone-M // extension (thumbv8m targets). - let cmse_nonsecure_call = - llvm::CreateAttrString(bx.cx.llcx, cstr::cstr!("cmse_nonsecure_call")); + let cmse_nonsecure_call = llvm::CreateAttrString(bx.cx.llcx, "cmse_nonsecure_call"); attributes::apply_to_callsite( callsite, llvm::AttributePlace::Function, diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index e382af8880b8d..6fd836946ffb4 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -1,10 +1,6 @@ //! Set and unset common attributes on LLVM values. -use std::ffi::CString; - -use cstr::cstr; use rustc_codegen_ssa::traits::*; -use rustc_data_structures::small_c_str::SmallCStr; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::ty::{self, TyCtxt}; @@ -103,11 +99,11 @@ pub fn frame_pointer_type_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attr fp = FramePointer::Always; } let attr_value = match fp { - FramePointer::Always => cstr!("all"), - FramePointer::NonLeaf => cstr!("non-leaf"), + FramePointer::Always => "all", + FramePointer::NonLeaf => "non-leaf", FramePointer::MayOmit => return None, }; - Some(llvm::CreateAttrStringValue(cx.llcx, cstr!("frame-pointer"), attr_value)) + Some(llvm::CreateAttrStringValue(cx.llcx, "frame-pointer", attr_value)) } /// Tell LLVM what instrument function to insert. @@ -119,11 +115,11 @@ fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribu // The function name varies on platforms. // See test/CodeGen/mcount.c in clang. - let mcount_name = CString::new(cx.sess().target.mcount.as_str().as_bytes()).unwrap(); + let mcount_name = cx.sess().target.mcount.as_str(); Some(llvm::CreateAttrStringValue( cx.llcx, - cstr!("instrument-function-entry-inlined"), + "instrument-function-entry-inlined", &mcount_name, )) } else { @@ -159,20 +155,20 @@ fn probestack_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { StackProbeType::None => return None, // Request LLVM to generate the probes inline. If the given LLVM version does not support // this, no probe is generated at all (even if the attribute is specified). - StackProbeType::Inline => cstr!("inline-asm"), + StackProbeType::Inline => "inline-asm", // Flag our internal `__rust_probestack` function as the stack probe symbol. // This is defined in the `compiler-builtins` crate for each architecture. - StackProbeType::Call => cstr!("__rust_probestack"), + StackProbeType::Call => "__rust_probestack", // Pick from the two above based on the LLVM version. StackProbeType::InlineOrCall { min_llvm_version_for_inline } => { if llvm_util::get_version() < min_llvm_version_for_inline { - cstr!("__rust_probestack") + "__rust_probestack" } else { - cstr!("inline-asm") + "inline-asm" } } }; - Some(llvm::CreateAttrStringValue(cx.llcx, cstr!("probe-stack"), attr_value)) + Some(llvm::CreateAttrStringValue(cx.llcx, "probe-stack", attr_value)) } fn stackprotector_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { @@ -187,15 +183,13 @@ fn stackprotector_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { } pub fn target_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> &'ll Attribute { - let target_cpu = SmallCStr::new(llvm_util::target_cpu(cx.tcx.sess)); - llvm::CreateAttrStringValue(cx.llcx, cstr!("target-cpu"), target_cpu.as_c_str()) + let target_cpu = llvm_util::target_cpu(cx.tcx.sess); + llvm::CreateAttrStringValue(cx.llcx, "target-cpu", target_cpu) } pub fn tune_cpu_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> Option<&'ll Attribute> { - llvm_util::tune_cpu(cx.tcx.sess).map(|tune| { - let tune_cpu = SmallCStr::new(tune); - llvm::CreateAttrStringValue(cx.llcx, cstr!("tune-cpu"), tune_cpu.as_c_str()) - }) + llvm_util::tune_cpu(cx.tcx.sess) + .map(|tune_cpu| llvm::CreateAttrStringValue(cx.llcx, "tune-cpu", tune_cpu)) } /// Get the `NonLazyBind` LLVM attribute, @@ -280,7 +274,7 @@ pub fn from_fn_attrs<'ll, 'tcx>( } if cx.sess().opts.debugging_opts.profile_sample_use.is_some() { - to_add.push(llvm::CreateAttrString(cx.llcx, cstr!("use-sample-profile"))); + to_add.push(llvm::CreateAttrString(cx.llcx, "use-sample-profile")); } // FIXME: none of these three functions interact with source level attributes. @@ -310,7 +304,7 @@ pub fn from_fn_attrs<'ll, 'tcx>( attributes::apply_to_llfn(llfn, AttributePlace::ReturnValue, &[no_alias]); } if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::CMSE_NONSECURE_ENTRY) { - to_add.push(llvm::CreateAttrString(cx.llcx, cstr!("cmse_nonsecure_entry"))); + to_add.push(llvm::CreateAttrString(cx.llcx, "cmse_nonsecure_entry")); } if let Some(align) = codegen_fn_attrs.alignment { llvm::set_alignment(llfn, align as usize); @@ -363,12 +357,12 @@ pub fn from_fn_attrs<'ll, 'tcx>( // If this function is an import from the environment but the wasm // import has a specific module/name, apply them here. if let Some(module) = wasm_import_module(cx.tcx, instance.def_id()) { - to_add.push(llvm::CreateAttrStringValue(cx.llcx, cstr!("wasm-import-module"), &module)); + to_add.push(llvm::CreateAttrStringValue(cx.llcx, "wasm-import-module", &module)); let name = codegen_fn_attrs.link_name.unwrap_or_else(|| cx.tcx.item_name(instance.def_id())); - let name = CString::new(name.as_str()).unwrap(); - to_add.push(llvm::CreateAttrStringValue(cx.llcx, cstr!("wasm-import-name"), &name)); + let name = name.as_str(); + to_add.push(llvm::CreateAttrStringValue(cx.llcx, "wasm-import-name", name)); } // The `"wasm"` abi on wasm targets automatically enables the @@ -388,13 +382,13 @@ pub fn from_fn_attrs<'ll, 'tcx>( let val = global_features .chain(function_features.iter().map(|s| &s[..])) .intersperse(",") - .collect::(); - to_add.push(llvm::CreateAttrStringValue(cx.llcx, cstr!("target-features"), &val)); + .collect::(); + to_add.push(llvm::CreateAttrStringValue(cx.llcx, "target-features", &val)); } attributes::apply_to_llfn(llfn, Function, &to_add); } -fn wasm_import_module(tcx: TyCtxt<'_>, id: DefId) -> Option { - tcx.wasm_import_module_map(id.krate).get(&id).map(|s| CString::new(&s[..]).unwrap()) +fn wasm_import_module(tcx: TyCtxt<'_>, id: DefId) -> Option<&String> { + tcx.wasm_import_module_map(id.krate).get(&id) } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 4a8894983b98d..6c944b9e4868e 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1175,11 +1175,12 @@ extern "C" { // Operations on attributes pub fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute; - pub fn LLVMRustCreateAttrString(C: &Context, Name: *const c_char) -> &Attribute; - pub fn LLVMRustCreateAttrStringValue( + pub fn LLVMCreateStringAttribute( C: &Context, Name: *const c_char, + NameLen: c_uint, Value: *const c_char, + ValueLen: c_uint, ) -> &Attribute; pub fn LLVMRustCreateAlignmentAttr(C: &Context, bytes: u64) -> &Attribute; pub fn LLVMRustCreateDereferenceableAttr(C: &Context, bytes: u64) -> &Attribute; diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 4892b8d4a84c6..48fbc1de8ee44 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -47,12 +47,28 @@ pub fn AddCallSiteAttributes<'ll>( } } -pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &CStr, value: &CStr) -> &'ll Attribute { - unsafe { LLVMRustCreateAttrStringValue(llcx, attr.as_ptr(), value.as_ptr()) } +pub fn CreateAttrStringValue<'ll>(llcx: &'ll Context, attr: &str, value: &str) -> &'ll Attribute { + unsafe { + LLVMCreateStringAttribute( + llcx, + attr.as_ptr().cast(), + attr.len().try_into().unwrap(), + value.as_ptr().cast(), + value.len().try_into().unwrap(), + ) + } } -pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &CStr) -> &'ll Attribute { - unsafe { LLVMRustCreateAttrStringValue(llcx, attr.as_ptr(), std::ptr::null()) } +pub fn CreateAttrString<'ll>(llcx: &'ll Context, attr: &str) -> &'ll Attribute { + unsafe { + LLVMCreateStringAttribute( + llcx, + attr.as_ptr().cast(), + attr.len().try_into().unwrap(), + std::ptr::null(), + 0, + ) + } } pub fn CreateAlignmentAttr(llcx: &Context, bytes: u64) -> &Attribute { diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 919fe7cac5ce3..ef6c9ef6627d5 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -267,12 +267,6 @@ extern "C" LLVMAttributeRef LLVMRustCreateAttrNoValue(LLVMContextRef C, return wrap(Attribute::get(*unwrap(C), fromRust(RustAttr))); } -extern "C" LLVMAttributeRef LLVMRustCreateAttrStringValue(LLVMContextRef C, - const char *Name, - const char *Value) { - return wrap(Attribute::get(*unwrap(C), StringRef(Name), StringRef(Value))); -} - extern "C" LLVMAttributeRef LLVMRustCreateAlignmentAttr(LLVMContextRef C, uint64_t Bytes) { return wrap(Attribute::getWithAlignment(*unwrap(C), llvm::Align(Bytes))); From bac5523ea0025988361a092c1f0e7f4eb90f6ad7 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Sun, 9 Jan 2022 19:39:02 +0100 Subject: [PATCH 05/15] Use cgroup quotas for calculating `available_parallelism` Manually tested via ``` // spawn a new cgroup scope for the current user $ sudo systemd-run -p CPUQuota="300%" --uid=$(id -u) -tdS // quota.rs #![feature(available_parallelism)] fn main() { println!("{:?}", std::thread::available_parallelism()); // prints Ok(3) } ``` Caveats * cgroup v1 is ignored * funky mountpoints (containing spaces, newlines or control chars) for cgroupfs will not be handled correctly since that would require unescaping /proc/self/mountinfo The escaping behavior of procfs seems to be undocumented. systemd and docker default to `/sys/fs/cgroup` so it should be fine for most systems. * quota will be ignored when `sched_getaffinity` doesn't work * assumes procfs is mounted under `/proc` and cgroupfs mounted and readable somewhere in the directory tree --- library/std/src/sys/unix/thread.rs | 71 ++++++++++++++++++++++++++++-- 1 file changed, 68 insertions(+), 3 deletions(-) diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index cf8cf5ad49f73..933210e1ff02e 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -279,10 +279,15 @@ pub fn available_parallelism() -> io::Result { ))] { #[cfg(any(target_os = "android", target_os = "linux"))] { + let quota = cgroup2_quota().unwrap_or(usize::MAX).max(1); let mut set: libc::cpu_set_t = unsafe { mem::zeroed() }; - if unsafe { libc::sched_getaffinity(0, mem::size_of::(), &mut set) } == 0 { - let count = unsafe { libc::CPU_COUNT(&set) }; - return Ok(unsafe { NonZeroUsize::new_unchecked(count as usize) }); + unsafe { + if libc::sched_getaffinity(0, mem::size_of::(), &mut set) == 0 { + let count = libc::CPU_COUNT(&set) as usize; + let count = count.min(quota); + // SAFETY: affinity mask can't be empty and the quota gets clamped to a minimum of 1 + return Ok(NonZeroUsize::new_unchecked(count)); + } } } match unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) } { @@ -368,6 +373,66 @@ pub fn available_parallelism() -> io::Result { } } +#[cfg(any(target_os = "android", target_os = "linux"))] +fn cgroup2_quota() -> Option { + use crate::ffi::OsString; + use crate::fs::{read, read_to_string, File}; + use crate::io::{BufRead, BufReader}; + use crate::os::unix::ffi::OsStringExt; + use crate::path::PathBuf; + + // find cgroup2 fs + let cgroups_mount = BufReader::new(File::open("/proc/self/mountinfo").ok()?) + .split(b'\n') + .map_while(Result::ok) + .filter_map(|line| { + let fields: Vec<_> = line.split(|&c| c == b' ').collect(); + let suffix_at = fields.iter().position(|f| f == b"-")?; + let fs_type = fields[suffix_at + 1]; + if fs_type == b"cgroup2" { Some(fields[4].to_owned()) } else { None } + }) + .next()?; + + let cgroups_mount = PathBuf::from(OsString::from_vec(cgroups_mount)); + + // find our place in the hierarchy + let cgroup_path = read("/proc/self/cgroup") + .ok()? + .split(|&c| c == b'\n') + .filter_map(|line| { + let mut fields = line.splitn(3, |&c| c == b':'); + // expect cgroupv2 which has an empty 2nd field + if fields.nth(1) != Some(b"") { + return None; + } + let path = fields.last()?; + // skip leading slash + Some(path[1..].to_owned()) + }) + .next()?; + let cgroup_path = PathBuf::from(OsString::from_vec(cgroup_path)); + + // walk hierarchy and take the minimum quota + cgroup_path + .ancestors() + .filter_map(|level| { + let cgroup_path = cgroups_mount.join(level); + let quota = match read_to_string(cgroup_path.join("cpu.max")) { + Ok(quota) => quota, + _ => return None, + }; + let quota = quota.lines().next()?; + let mut quota = quota.split(' '); + let limit = quota.next()?; + let period = quota.next()?; + match (limit.parse::(), period.parse::()) { + (Ok(limit), Ok(period)) => Some(limit / period), + _ => None, + } + }) + .min() +} + #[cfg(all( not(target_os = "linux"), not(target_os = "freebsd"), From af6d2ed24557694ff7d32bf2a29a6cd5aaade859 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 3 Mar 2022 00:35:47 +0100 Subject: [PATCH 06/15] hardcode /sys/fs/cgroup instead of doing a lookup via mountinfo this avoids parsing mountinfo which can be huge on some systems and something might be emulating cgroup fs for sandboxing reasons which means it wouldn't show up as mountpoint additionally the new implementation operates on a single pathbuffer, reducing allocations --- library/std/src/sys/unix/thread.rs | 120 ++++++++++++++++------------- 1 file changed, 67 insertions(+), 53 deletions(-) diff --git a/library/std/src/sys/unix/thread.rs b/library/std/src/sys/unix/thread.rs index 933210e1ff02e..ff01ce2733329 100644 --- a/library/std/src/sys/unix/thread.rs +++ b/library/std/src/sys/unix/thread.rs @@ -279,7 +279,7 @@ pub fn available_parallelism() -> io::Result { ))] { #[cfg(any(target_os = "android", target_os = "linux"))] { - let quota = cgroup2_quota().unwrap_or(usize::MAX).max(1); + let quota = cgroup2_quota().max(1); let mut set: libc::cpu_set_t = unsafe { mem::zeroed() }; unsafe { if libc::sched_getaffinity(0, mem::size_of::(), &mut set) == 0 { @@ -373,64 +373,78 @@ pub fn available_parallelism() -> io::Result { } } +/// Returns cgroup CPU quota in core-equivalents, rounded down, or usize::MAX if the quota cannot +/// be determined or is not set. #[cfg(any(target_os = "android", target_os = "linux"))] -fn cgroup2_quota() -> Option { +fn cgroup2_quota() -> usize { use crate::ffi::OsString; - use crate::fs::{read, read_to_string, File}; - use crate::io::{BufRead, BufReader}; + use crate::fs::{try_exists, File}; + use crate::io::Read; use crate::os::unix::ffi::OsStringExt; use crate::path::PathBuf; - // find cgroup2 fs - let cgroups_mount = BufReader::new(File::open("/proc/self/mountinfo").ok()?) - .split(b'\n') - .map_while(Result::ok) - .filter_map(|line| { - let fields: Vec<_> = line.split(|&c| c == b' ').collect(); - let suffix_at = fields.iter().position(|f| f == b"-")?; - let fs_type = fields[suffix_at + 1]; - if fs_type == b"cgroup2" { Some(fields[4].to_owned()) } else { None } - }) - .next()?; - - let cgroups_mount = PathBuf::from(OsString::from_vec(cgroups_mount)); - - // find our place in the hierarchy - let cgroup_path = read("/proc/self/cgroup") - .ok()? - .split(|&c| c == b'\n') - .filter_map(|line| { - let mut fields = line.splitn(3, |&c| c == b':'); - // expect cgroupv2 which has an empty 2nd field - if fields.nth(1) != Some(b"") { - return None; - } - let path = fields.last()?; - // skip leading slash - Some(path[1..].to_owned()) - }) - .next()?; - let cgroup_path = PathBuf::from(OsString::from_vec(cgroup_path)); - - // walk hierarchy and take the minimum quota - cgroup_path - .ancestors() - .filter_map(|level| { - let cgroup_path = cgroups_mount.join(level); - let quota = match read_to_string(cgroup_path.join("cpu.max")) { - Ok(quota) => quota, - _ => return None, - }; - let quota = quota.lines().next()?; - let mut quota = quota.split(' '); - let limit = quota.next()?; - let period = quota.next()?; - match (limit.parse::(), period.parse::()) { - (Ok(limit), Ok(period)) => Some(limit / period), - _ => None, + let mut quota = usize::MAX; + + let _: Option<()> = try { + let mut buf = Vec::with_capacity(128); + // find our place in the cgroup hierarchy + File::open("/proc/self/cgroup").ok()?.read_to_end(&mut buf).ok()?; + let cgroup_path = buf + .split(|&c| c == b'\n') + .filter_map(|line| { + let mut fields = line.splitn(3, |&c| c == b':'); + // expect cgroupv2 which has an empty 2nd field + if fields.nth(1) != Some(b"") { + return None; + } + let path = fields.last()?; + // skip leading slash + Some(path[1..].to_owned()) + }) + .next()?; + let cgroup_path = PathBuf::from(OsString::from_vec(cgroup_path)); + + let mut path = PathBuf::with_capacity(128); + let mut read_buf = String::with_capacity(20); + + let cgroup_mount = "/sys/fs/cgroup"; + + path.push(cgroup_mount); + path.push(&cgroup_path); + + path.push("cgroup.controllers"); + + // skip if we're not looking at cgroup2 + if matches!(try_exists(&path), Err(_) | Ok(false)) { + return usize::MAX; + }; + + path.pop(); + + while path.starts_with(cgroup_mount) { + path.push("cpu.max"); + + read_buf.clear(); + + if File::open(&path).and_then(|mut f| f.read_to_string(&mut read_buf)).is_ok() { + let raw_quota = read_buf.lines().next()?; + let mut raw_quota = raw_quota.split(' '); + let limit = raw_quota.next()?; + let period = raw_quota.next()?; + match (limit.parse::(), period.parse::()) { + (Ok(limit), Ok(period)) => { + quota = quota.min(limit / period); + } + _ => {} + } } - }) - .min() + + path.pop(); // pop filename + path.pop(); // pop dir + } + }; + + quota } #[cfg(all( From e18abbf2ac544ef744c5aa95df434b2c81c066a2 Mon Sep 17 00:00:00 2001 From: The 8472 Date: Thu, 3 Mar 2022 00:36:23 +0100 Subject: [PATCH 07/15] update available_parallelism docs since cgroups and sched_getaffinity are now taken into account --- library/std/src/thread/mod.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/library/std/src/thread/mod.rs b/library/std/src/thread/mod.rs index beb606099341e..09d1e714ab6dd 100644 --- a/library/std/src/thread/mod.rs +++ b/library/std/src/thread/mod.rs @@ -1524,7 +1524,10 @@ fn _assert_sync_and_send() { /// /// On Linux: /// - It may overcount the amount of parallelism available when limited by a -/// process-wide affinity mask, or when affected by cgroup limits. +/// process-wide affinity mask or cgroup quotas and cgroup2 fs or `sched_getaffinity()` can't be +/// queried, e.g. due to sandboxing. +/// - It may undercount the amount of parallelism if the current thread's affinity mask +/// does not reflect the process' cpuset, e.g. due to pinned threads. /// /// On all targets: /// - It may overcount the amount of parallelism available when running in a VM From 37c1eb0a470e0fb18db8a230181d6e1c600bde60 Mon Sep 17 00:00:00 2001 From: Axel Viala Date: Thu, 3 Mar 2022 11:25:01 +0100 Subject: [PATCH 08/15] Doc: Fix use of quote instead of backstick in Adapter::map. --- library/core/src/iter/adapters/map.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/iter/adapters/map.rs b/library/core/src/iter/adapters/map.rs index b2ed82508dd29..d2077a63e150a 100644 --- a/library/core/src/iter/adapters/map.rs +++ b/library/core/src/iter/adapters/map.rs @@ -38,7 +38,7 @@ use crate::ops::Try; /// } /// ``` /// -/// This will print "('a', 1), ('b', 2), ('c', 3)". +/// This will print `('a', 1), ('b', 2), ('c', 3)`. /// /// Now consider this twist where we add a call to `rev`. This version will /// print `('c', 1), ('b', 2), ('a', 3)`. Note that the letters are reversed, From 11c565f14b03fe06e3149ebb83e546a627a6b649 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Mar 2022 11:00:50 +1100 Subject: [PATCH 09/15] Improve if/else formatting in macro_parser.rs. To avoid the strange style where comments force `else` onto its own line. The commit also removes several else-after-return constructs, which can be hard to read. --- compiler/rustc_expand/src/mbe/macro_parser.rs | 60 +++++++++---------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index dd82add08dd98..596fee21cdd71 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -505,25 +505,23 @@ fn inner_parse_loop<'root, 'tt>( item.idx += 1; next_items.push(item); } - } - // We don't need a separator. Move the "dot" back to the beginning of the matcher - // and try to match again UNLESS we are only allowed to have _one_ repetition. - else if item.seq_op != Some(mbe::KleeneOp::ZeroOrOne) { + } else if item.seq_op != Some(mbe::KleeneOp::ZeroOrOne) { + // We don't need a separator. Move the "dot" back to the beginning of the + // matcher and try to match again UNLESS we are only allowed to have _one_ + // repetition. item.match_cur = item.match_lo; item.idx = 0; cur_items.push(item); } - } - // If we are not in a repetition, then being at the end of a matcher means that we have - // reached the potential end of the input. - else { + } else { + // If we are not in a repetition, then being at the end of a matcher means that we + // have reached the potential end of the input. eof_items.push(item); } - } - // We are in the middle of a matcher. - else { - // Look at what token in the matcher we are trying to match the current token (`token`) - // against. Depending on that, we may generate new items. + } else { + // We are in the middle of a matcher. Look at what token in the matcher we are trying + // to match the current token (`token`) against. Depending on that, we may generate new + // items. match item.top_elts.get_tt(idx) { // Need to descend into a sequence TokenTree::Sequence(sp, seq) => { @@ -666,17 +664,14 @@ pub(super) fn parse_tt( // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise, // either the parse is ambiguous (which should never happen) or there is a syntax error. if parser.token == token::Eof { - if eof_items.len() == 1 { + return if eof_items.len() == 1 { let matches = eof_items[0].matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap()); - return nameize(parser.sess, ms, matches); + nameize(parser.sess, ms, matches) } else if eof_items.len() > 1 { - return Error( - parser.token.span, - "ambiguity: multiple successful parses".to_string(), - ); + Error(parser.token.span, "ambiguity: multiple successful parses".to_string()) } else { - return Failure( + Failure( Token::new( token::Eof, if parser.token.span.is_dummy() { @@ -686,8 +681,8 @@ pub(super) fn parse_tt( }, ), "missing tokens in macro arguments", - ); - } + ) + }; } // Performance hack: eof_items may share matchers via Rc with other things that we want // to modify. Dropping eof_items now may drop these refcounts to 1, preventing an @@ -699,9 +694,10 @@ pub(super) fn parse_tt( if bb_items.is_empty() && next_items.is_empty() { return Failure(parser.token.clone(), "no rules expected this token in macro call"); } - // Another possibility is that we need to call out to parse some rust nonterminal - // (black-box) parser. However, if there is not EXACTLY ONE of these, something is wrong. - else if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 { + + if (!bb_items.is_empty() && !next_items.is_empty()) || bb_items.len() > 1 { + // We need to call out to parse some rust nonterminal (black-box) parser. But something + // is wrong, because there is not EXACTLY ONE of these. let nts = bb_items .iter() .map(|item| match item.top_elts.get_tt(item.idx) { @@ -723,15 +719,15 @@ pub(super) fn parse_tt( ), ); } - // Dump all possible `next_items` into `cur_items` for the next iteration. - else if !next_items.is_empty() { - // Now process the next token + + if !next_items.is_empty() { + // Dump all possible `next_items` into `cur_items` for the next iteration. Then process + // the next token. cur_items.extend(next_items.drain(..)); parser.to_mut().bump(); - } - // Finally, we have the case where we need to call the black-box parser to get some - // nonterminal. - else { + } else { + // Finally, we have the case where we need to call the black-box parser to get some + // nonterminal. assert_eq!(bb_items.len(), 1); let mut item = bb_items.pop().unwrap(); From b9fabc3f9cce1e29cd54f1809b4ac8dc3c52980f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Mar 2022 11:02:43 +1100 Subject: [PATCH 10/15] Add a static size assertion for `MatcherPos`. --- compiler/rustc_expand/src/mbe/macro_parser.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 596fee21cdd71..577e2c823ba84 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -207,6 +207,10 @@ struct MatcherPos<'root, 'tt> { stack: SmallVec<[MatcherTtFrame<'tt>; 1]>, } +// This type is used a lot. Make sure it doesn't unintentionally get bigger. +#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] +rustc_data_structures::static_assert_size!(MatcherPos<'_, '_>, 192); + impl<'root, 'tt> MatcherPos<'root, 'tt> { /// Adds `m` as a named match for the `idx`-th metavar. fn push_match(&mut self, idx: usize, m: NamedMatch) { From 643ba50004996b474c073e58d70fdbc9f797a8bd Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Mar 2022 11:04:04 +1100 Subject: [PATCH 11/15] Introduce `MatcherPosRepetition`. There are three `Option` fields in `MatcherPos` that are only used in tandem. This commit combines them, making the code slightly easier to read. (It also makes clear that the `sep` field arguably should have been `Option>`!) --- compiler/rustc_expand/src/mbe/macro_parser.rs | 50 ++++++++++--------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 577e2c823ba84..aff0c8a96642a 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -184,17 +184,8 @@ struct MatcherPos<'root, 'tt> { /// in this matcher. match_hi: usize, - // The following fields are used if we are matching a repetition. If we aren't, they should be - // `None`. - /// The KleeneOp of this sequence if we are in a repetition. - seq_op: Option, - - /// The separator if we are in a repetition. - sep: Option, - - /// The "parent" matcher position if we are in a repetition. That is, the matcher position just - /// before we enter the sequence. - up: Option>, + /// This field is only used if we are matching a repetition. + repetition: Option>, /// Specifically used to "unzip" token trees. By "unzip", we mean to unwrap the delimiters from /// a delimited token tree (e.g., something wrapped in `(` `)`) or to get the contents of a doc @@ -219,6 +210,19 @@ impl<'root, 'tt> MatcherPos<'root, 'tt> { } } +#[derive(Clone)] +struct MatcherPosRepetition<'root, 'tt> { + /// The KleeneOp of this sequence. + seq_op: mbe::KleeneOp, + + /// The separator. + sep: Option, + + /// The "parent" matcher position. That is, the matcher position just before we enter the + /// sequence. + up: MatcherPosHandle<'root, 'tt>, +} + // Lots of MatcherPos instances are created at runtime. Allocating them on the // heap is slow. Furthermore, using SmallVec to allocate them all // on the stack is also slow, because MatcherPos is quite a large type and @@ -326,10 +330,8 @@ fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree]) -> MatcherPos<'root, 't // Haven't descended into any delimiters, so empty stack stack: smallvec![], - // Haven't descended into any sequences, so both of these are `None`. - seq_op: None, - sep: None, - up: None, + // Haven't descended into any sequences, so this is `None`. + repetition: None, } } @@ -476,7 +478,7 @@ fn inner_parse_loop<'root, 'tt>( // We are repeating iff there is a parent. If the matcher is inside of a repetition, // then we could be at the end of a sequence or at the beginning of the next // repetition. - if item.up.is_some() { + if let Some(repetition) = &item.repetition { // At this point, regardless of whether there is a separator, we should add all // matches from the complete repetition of the sequence to the shared, top-level // `matches` list (actually, `up.matches`, which could itself not be the top-level, @@ -487,7 +489,7 @@ fn inner_parse_loop<'root, 'tt>( // NOTE: removing the condition `idx == len` allows trailing separators. if idx == len { // Get the `up` matcher - let mut new_pos = item.up.clone().unwrap(); + let mut new_pos = repetition.up.clone(); // Add matches from this repetition to the `matches` of `up` for idx in item.match_lo..item.match_hi { @@ -502,14 +504,14 @@ fn inner_parse_loop<'root, 'tt>( } // Check if we need a separator. - if idx == len && item.sep.is_some() { + if idx == len && repetition.sep.is_some() { // We have a separator, and it is the current token. We can advance past the // separator token. - if item.sep.as_ref().map_or(false, |sep| token_name_eq(token, sep)) { + if repetition.sep.as_ref().map_or(false, |sep| token_name_eq(token, sep)) { item.idx += 1; next_items.push(item); } - } else if item.seq_op != Some(mbe::KleeneOp::ZeroOrOne) { + } else if repetition.seq_op != mbe::KleeneOp::ZeroOrOne { // We don't need a separator. Move the "dot" back to the beginning of the // matcher and try to match again UNLESS we are only allowed to have _one_ // repetition. @@ -548,14 +550,16 @@ fn inner_parse_loop<'root, 'tt>( let matches = create_matches(item.matches.len()); cur_items.push(MatcherPosHandle::Box(Box::new(MatcherPos { stack: smallvec![], - sep: seq.separator.clone(), - seq_op: Some(seq.kleene.op), idx: 0, matches, match_lo: item.match_cur, match_cur: item.match_cur, match_hi: item.match_cur + seq.num_captures, - up: Some(item), + repetition: Some(MatcherPosRepetition { + up: item, + sep: seq.separator.clone(), + seq_op: seq.kleene.op, + }), top_elts: Tt(TokenTree::Sequence(sp, seq)), }))); } From e5f3fd625022c22f0f415e9c11ca84e1f2be5771 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Mar 2022 11:10:21 +1100 Subject: [PATCH 12/15] Use a better return type for `inner_parse_loop`. Because `inner_parse_loop` has only one way to not succeed, not three. --- compiler/rustc_expand/src/mbe/macro_parser.rs | 60 +++++++++++-------- 1 file changed, 35 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index aff0c8a96642a..69f293b241c77 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -266,6 +266,12 @@ impl<'root, 'tt> DerefMut for MatcherPosHandle<'root, 'tt> { } } +enum EofItems<'root, 'tt> { + None, + One(MatcherPosHandle<'root, 'tt>), + Multiple, +} + /// Represents the possible results of an attempted parse. crate enum ParseResult { /// Parsed successfully. @@ -449,10 +455,10 @@ fn inner_parse_loop<'root, 'tt>( sess: &ParseSess, cur_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, next_items: &mut Vec>, - eof_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, bb_items: &mut SmallVec<[MatcherPosHandle<'root, 'tt>; 1]>, + eof_items: &mut EofItems<'root, 'tt>, token: &Token, -) -> ParseResult<()> { +) -> Result<(), (rustc_span::Span, String)> { // Pop items from `cur_items` until it is empty. while let Some(mut item) = cur_items.pop() { // When unzipped trees end, remove them. This corresponds to backtracking out of a @@ -522,7 +528,10 @@ fn inner_parse_loop<'root, 'tt>( } else { // If we are not in a repetition, then being at the end of a matcher means that we // have reached the potential end of the input. - eof_items.push(item); + *eof_items = match eof_items { + EofItems::None => EofItems::One(item), + EofItems::One(_) | EofItems::Multiple => EofItems::Multiple, + } } } else { // We are in the middle of a matcher. Look at what token in the matcher we are trying @@ -567,7 +576,7 @@ fn inner_parse_loop<'root, 'tt>( // We need to match a metavar (but the identifier is invalid)... this is an error TokenTree::MetaVarDecl(span, _, None) => { if sess.missing_fragment_specifiers.borrow_mut().remove(&span).is_some() { - return Error(span, "missing fragment specifier".to_string()); + return Err((span, "missing fragment specifier".to_string())); } } @@ -615,7 +624,7 @@ fn inner_parse_loop<'root, 'tt>( } // Yay a successful parse (so far)! - Success(()) + Ok(()) } /// Use the given sequence of token trees (`ms`) as a matcher. Match the token @@ -638,12 +647,13 @@ pub(super) fn parse_tt( let mut next_items = Vec::new(); loop { + assert!(next_items.is_empty()); + // Matcher positions black-box parsed by parser.rs (`parser`) let mut bb_items = SmallVec::new(); // Matcher positions that would be valid if the macro invocation was over now - let mut eof_items = SmallVec::new(); - assert!(next_items.is_empty()); + let mut eof_items = EofItems::None; // Process `cur_items` until either we have finished the input or we need to get some // parsing from the black-box parser done. The result is that `next_items` will contain a @@ -652,34 +662,34 @@ pub(super) fn parse_tt( parser.sess, &mut cur_items, &mut next_items, - &mut eof_items, &mut bb_items, + &mut eof_items, &parser.token, ) { - Success(_) => {} - Failure(token, msg) => return Failure(token, msg), - Error(sp, msg) => return Error(sp, msg), - ErrorReported => return ErrorReported, + Ok(()) => {} + Err((sp, msg)) => return Error(sp, msg), } // inner parse loop handled all cur_items, so it's empty assert!(cur_items.is_empty()); - // We need to do some post processing after the `inner_parser_loop`. + // We need to do some post processing after the `inner_parse_loop`. // // Error messages here could be improved with links to original rules. // If we reached the EOF, check that there is EXACTLY ONE possible matcher. Otherwise, // either the parse is ambiguous (which should never happen) or there is a syntax error. if parser.token == token::Eof { - return if eof_items.len() == 1 { - let matches = - eof_items[0].matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap()); - nameize(parser.sess, ms, matches) - } else if eof_items.len() > 1 { - Error(parser.token.span, "ambiguity: multiple successful parses".to_string()) - } else { - Failure( + return match eof_items { + EofItems::One(mut eof_item) => { + let matches = + eof_item.matches.iter_mut().map(|dv| Lrc::make_mut(dv).pop().unwrap()); + nameize(parser.sess, ms, matches) + } + EofItems::Multiple => { + Error(parser.token.span, "ambiguity: multiple successful parses".to_string()) + } + EofItems::None => Failure( Token::new( token::Eof, if parser.token.span.is_dummy() { @@ -689,12 +699,12 @@ pub(super) fn parse_tt( }, ), "missing tokens in macro arguments", - ) + ), }; } - // Performance hack: eof_items may share matchers via Rc with other things that we want - // to modify. Dropping eof_items now may drop these refcounts to 1, preventing an - // unnecessary implicit clone later in Rc::make_mut. + // Performance hack: `eof_items` may share matchers via `Rc` with other things that we want + // to modify. Dropping `eof_items` now may drop these refcounts to 1, preventing an + // unnecessary implicit clone later in `Rc::make_mut`. drop(eof_items); // If there are no possible next positions AND we aren't waiting for the black-box parser, From 97eb1b4669b893bf01cbc362e82ee10cfe8aff1c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 3 Mar 2022 12:14:27 +1100 Subject: [PATCH 13/15] Change `initial_matcher_pos()` into `MatcherPos::new()`. --- compiler/rustc_expand/src/mbe/macro_parser.rs | 58 +++++++++---------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 69f293b241c77..81e30a8a742ce 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -154,7 +154,7 @@ type NamedMatchVec = SmallVec<[NamedMatch; 4]>; /// lifetime. By separating `'tt` from `'root`, we can show that. #[derive(Clone)] struct MatcherPos<'root, 'tt> { - /// The token or sequence of tokens that make up the matcher + /// The token or sequence of tokens that make up the matcher. `elts` is short for "elements". top_elts: TokenTreeOrTokenTreeSlice<'tt>, /// The position of the "dot" in this matcher @@ -203,6 +203,33 @@ struct MatcherPos<'root, 'tt> { rustc_data_structures::static_assert_size!(MatcherPos<'_, '_>, 192); impl<'root, 'tt> MatcherPos<'root, 'tt> { + /// Generates the top-level matcher position in which the "dot" is before the first token of + /// the matcher `ms`. + fn new(ms: &'tt [TokenTree]) -> Self { + let match_idx_hi = count_names(ms); + MatcherPos { + // Start with the top level matcher given to us. + top_elts: TtSeq(ms), + + // The "dot" is before the first token of the matcher. + idx: 0, + + // Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in + // `top_elts`. `match_lo` for `top_elts` is 0 and `match_hi` is `match_idx_hi`. + // `match_cur` is 0 since we haven't actually matched anything yet. + matches: create_matches(match_idx_hi), + match_lo: 0, + match_cur: 0, + match_hi: match_idx_hi, + + // Haven't descended into any delimiters, so this is empty. + stack: smallvec![], + + // Haven't descended into any sequences, so this is `None`. + repetition: None, + } + } + /// Adds `m` as a named match for the `idx`-th metavar. fn push_match(&mut self, idx: usize, m: NamedMatch) { let matches = Lrc::make_mut(&mut self.matches[idx]); @@ -314,33 +341,6 @@ fn create_matches(len: usize) -> Box<[Lrc]> { .into_boxed_slice() } -/// Generates the top-level matcher position in which the "dot" is before the first token of the -/// matcher `ms`. -fn initial_matcher_pos<'root, 'tt>(ms: &'tt [TokenTree]) -> MatcherPos<'root, 'tt> { - let match_idx_hi = count_names(ms); - let matches = create_matches(match_idx_hi); - MatcherPos { - // Start with the top level matcher given to us - top_elts: TtSeq(ms), // "elts" is an abbr. for "elements" - // The "dot" is before the first token of the matcher - idx: 0, - - // Initialize `matches` to a bunch of empty `Vec`s -- one for each metavar in `top_elts`. - // `match_lo` for `top_elts` is 0 and `match_hi` is `matches.len()`. `match_cur` is 0 since - // we haven't actually matched anything yet. - matches, - match_lo: 0, - match_cur: 0, - match_hi: match_idx_hi, - - // Haven't descended into any delimiters, so empty stack - stack: smallvec![], - - // Haven't descended into any sequences, so this is `None`. - repetition: None, - } -} - /// `NamedMatch` is a pattern-match result for a single `token::MATCH_NONTERMINAL`: /// so it is associated with a single ident in a parse, and all /// `MatchedNonterminal`s in the `NamedMatch` have the same non-terminal type @@ -642,7 +642,7 @@ pub(super) fn parse_tt( // // This MatcherPos instance is allocated on the stack. All others -- and // there are frequently *no* others! -- are allocated on the heap. - let mut initial = initial_matcher_pos(ms); + let mut initial = MatcherPos::new(ms); let mut cur_items = smallvec![MatcherPosHandle::Ref(&mut initial)]; let mut next_items = Vec::new(); From 516488484ebcf83759d94bc11608971bb6331d5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lo=C3=AFc=20BRANSTETT?= Date: Thu, 3 Mar 2022 11:52:09 +0100 Subject: [PATCH 14/15] Fix invalid lint_node_id being put on a removed stmt --- compiler/rustc_expand/src/expand.rs | 4 ++-- src/test/ui/check-cfg/stmt-no-ice.rs | 10 ++++++++++ src/test/ui/check-cfg/stmt-no-ice.stderr | 10 ++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/check-cfg/stmt-no-ice.rs create mode 100644 src/test/ui/check-cfg/stmt-no-ice.stderr diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 1b97618050939..4af376b983c94 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1841,7 +1841,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.flat_map_node(node) } - fn flat_map_stmt(&mut self, mut node: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { + fn flat_map_stmt(&mut self, node: ast::Stmt) -> SmallVec<[ast::Stmt; 1]> { // FIXME: invocations in semicolon-less expressions positions are expanded as expressions, // changing that requires some compatibility measures. if node.is_expr() { @@ -1863,7 +1863,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> { self.cx.current_expansion.is_trailing_mac = false; res } - _ => assign_id!(self, &mut node.id, || noop_flat_map_stmt(node, self)), + _ => noop_flat_map_stmt(node, self), }; } diff --git a/src/test/ui/check-cfg/stmt-no-ice.rs b/src/test/ui/check-cfg/stmt-no-ice.rs new file mode 100644 index 0000000000000..cf76487ed46fb --- /dev/null +++ b/src/test/ui/check-cfg/stmt-no-ice.rs @@ -0,0 +1,10 @@ +// This test checks that there is no ICE with this code +// +// check-pass +// compile-flags:--check-cfg=names() -Z unstable-options + +fn main() { + #[cfg(crossbeam_loom)] + //~^ WARNING unexpected `cfg` condition name + {} +} diff --git a/src/test/ui/check-cfg/stmt-no-ice.stderr b/src/test/ui/check-cfg/stmt-no-ice.stderr new file mode 100644 index 0000000000000..da65b596911d2 --- /dev/null +++ b/src/test/ui/check-cfg/stmt-no-ice.stderr @@ -0,0 +1,10 @@ +warning: unexpected `cfg` condition name + --> $DIR/stmt-no-ice.rs:7:11 + | +LL | #[cfg(crossbeam_loom)] + | ^^^^^^^^^^^^^^ + | + = note: `#[warn(unexpected_cfgs)]` on by default + +warning: 1 warning emitted + From 00fffdddd22cdd796cf4261cdbbf830bee7e4f7b Mon Sep 17 00:00:00 2001 From: cuishuang Date: Thu, 3 Mar 2022 19:47:23 +0800 Subject: [PATCH 15/15] all: fix some typos Signed-off-by: cuishuang --- RELEASES.md | 2 +- compiler/rustc_codegen_gcc/src/builder.rs | 2 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 10 +++++----- compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs | 2 +- compiler/rustc_const_eval/src/interpret/operand.rs | 2 +- compiler/rustc_driver/src/lib.rs | 2 +- compiler/rustc_error_codes/src/error_codes/E0772.md | 2 +- compiler/rustc_expand/src/mbe/transcribe.rs | 2 +- compiler/rustc_expand/src/proc_macro_server.rs | 2 +- compiler/rustc_incremental/src/persist/load.rs | 2 +- .../src/infer/error_reporting/need_type_info.rs | 2 +- .../nice_region_error/mismatched_static_lifetime.rs | 2 +- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 971a63b240f3e..08040f4815836 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1060,7 +1060,7 @@ Version 1.52.1 (2021-05-10) This release disables incremental compilation, unless the user has explicitly opted in via the newly added RUSTC_FORCE_INCREMENTAL=1 environment variable. -This is due to the widespread, and frequently occuring, breakage encountered by +This is due to the widespread, and frequently occurring, breakage encountered by Rust users due to newly enabled incremental verification in 1.52.0. Notably, Rust users **should** upgrade to 1.52.0 or 1.52.1: the bugs that are detected by newly added incremental verification are still present in past stable versions, diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 974e59b65ec91..be3f6a12706f8 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -1064,7 +1064,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let val_type = value.get_type(); match (type_is_pointer(val_type), type_is_pointer(dest_ty)) { (false, true) => { - // NOTE: Projecting a field of a pointer type will attemp a cast from a signed char to + // NOTE: Projecting a field of a pointer type will attempt a cast from a signed char to // a pointer, which is not supported by gccjit. return self.cx.context.new_cast(None, self.inttoptr(value, val_type.make_pointer()), dest_ty); }, diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 3b06587061d9d..e9d13a4ebaf8c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -369,12 +369,12 @@ pub fn target_cpu(sess: &Session) -> &str { /// The list of LLVM features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, /// `--target` and similar). pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec { - // Features that come earlier are overriden by conflicting features later in the string. + // Features that come earlier are overridden by conflicting features later in the string. // Typically we'll want more explicit settings to override the implicit ones, so: // - // * Features from -Ctarget-cpu=*; are overriden by [^1] - // * Features implied by --target; are overriden by - // * Features from -Ctarget-feature; are overriden by + // * Features from -Ctarget-cpu=*; are overridden by [^1] + // * Features implied by --target; are overridden by + // * Features from -Ctarget-feature; are overridden by // * function specific features. // // [^1]: target-cpu=native is handled here, other target-cpu values are handled implicitly @@ -383,7 +383,7 @@ pub(crate) fn global_llvm_features(sess: &Session, diagnostics: bool) -> Vec> InterpCx<'mir, 'tcx, M> { let val = self.subst_from_current_frame_and_normalize_erasing_regions(constant.literal)?; // This can still fail: - // * During ConstProp, with `TooGeneric` or since the `requried_consts` were not all + // * During ConstProp, with `TooGeneric` or since the `required_consts` were not all // checked yet. // * During CTFE, since promoteds in `const`/`static` initializer bodies can fail. diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs index b36ce63dda756..43c9e9296b90a 100644 --- a/compiler/rustc_driver/src/lib.rs +++ b/compiler/rustc_driver/src/lib.rs @@ -1228,7 +1228,7 @@ pub fn report_ice(info: &panic::PanicInfo<'_>, bug_report_url: &str) { /// /// A custom rustc driver can skip calling this to set up a custom ICE hook. pub fn install_ice_hook() { - // If the user has not explicitly overriden "RUST_BACKTRACE", then produce + // If the user has not explicitly overridden "RUST_BACKTRACE", then produce // full backtraces. When a compiler ICE happens, we want to gather // as much information as possible to present in the issue opened // by the user. Compiler developers and other rustc users can diff --git a/compiler/rustc_error_codes/src/error_codes/E0772.md b/compiler/rustc_error_codes/src/error_codes/E0772.md index 262e52351ef01..3b73abaf776c2 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0772.md +++ b/compiler/rustc_error_codes/src/error_codes/E0772.md @@ -45,7 +45,7 @@ trait object's internal data to be accessed safely from any trait methods. This rule also goes for any lifetime any struct made into a trait object may have. In the implementation for `dyn Person`, the `'2` lifetime representing the -internal data was ommitted, meaning that the compiler inferred the lifetime +internal data was omitted, meaning that the compiler inferred the lifetime `'static`. As a result, the implementation's `is_cool` is inferred by the compiler to look like this: diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 01a7f7266172c..6844162ca43bb 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -233,7 +233,7 @@ pub(super) fn transcribe<'a>( } else { // Other variables are emitted into the output stream as groups with // `Delimiter::None` to maintain parsing priorities. - // `Interpolated` is currenty used for such groups in rustc parser. + // `Interpolated` is currently used for such groups in rustc parser. marker.visit_span(&mut sp); TokenTree::token(token::Interpolated(nt.clone()), sp) }; diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 869cada400f0f..0aef5982cff50 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -847,7 +847,7 @@ impl server::Span for Rustc<'_, '_> { /// the `quote` proc-macro. This will save the span of /// "hello" into the metadata of `my_proc_macro`. As a result, /// the body of `my_proc_macro` (after expansion) will end - /// up containg a call that looks like this: + /// up containing a call that looks like this: /// `proc_macro::Ident::new("hello", proc_macro::Span::recover_proc_macro_span(0))` /// /// where `0` is the id returned by this function. diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 870c3f8068245..908a936142475 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -27,7 +27,7 @@ pub enum LoadResult { }, /// The file either didn't exist or was produced by an incompatible compiler version. DataOutOfDate, - /// An error occured. + /// An error occurred. Error { #[allow(missing_docs)] message: String, diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs index 8ff0eed71ed03..70ea3de5dd49b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs @@ -935,7 +935,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { /// performing that replacement, we'll turn all remaining infer type params to use their name from /// their definition, and replace all the `[type error]`s back to being infer so they display in /// the output as `_`. If we didn't go through `[type error]`, we would either show all type params -/// by their name *or* `_`, neither of which is desireable: we want to show all types that we could +/// by their name *or* `_`, neither of which is desirable: we want to show all types that we could /// infer as `_` to reduce verbosity and avoid telling the user about unnecessary type annotations. struct ResolvedTypeParamEraser<'tcx> { tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs index e0420291aa3f5..4710eae6189a5 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs @@ -58,7 +58,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { bug!("Node not an impl."); }; - // Next, let's figure out the set of trait objects with implict static bounds + // Next, let's figure out the set of trait objects with implicit static bounds let ty = self.tcx().type_of(*impl_def_id); let mut v = super::static_impl_trait::TraitObjectVisitor(FxHashSet::default()); v.visit_ty(ty);