From 82336c13115e1e8d567f6ffbdffdf9e2a0c3f955 Mon Sep 17 00:00:00 2001 From: Jan-Mirko Otter Date: Mon, 1 May 2023 10:59:37 +0000 Subject: [PATCH 01/23] wasm target feature: exception handling --- compiler/rustc_codegen_ssa/src/target_features.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index c5976a65411fd..bb2a45dcc68d1 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -282,6 +282,7 @@ const WASM_ALLOWED_FEATURES: &[(&str, Option)] = &[ // tidy-alphabetical-start ("atomics", Some(sym::wasm_target_feature)), ("bulk-memory", Some(sym::wasm_target_feature)), + ("exception-handling", Some(sym::wasm_target_feature)), ("multivalue", Some(sym::wasm_target_feature)), ("mutable-globals", Some(sym::wasm_target_feature)), ("nontrapping-fptoint", Some(sym::wasm_target_feature)), From 00ce5e8fcab0b6c64c12e3fee9c67cc155034692 Mon Sep 17 00:00:00 2001 From: Jan-Mirko Otter Date: Mon, 1 May 2023 19:22:54 +0000 Subject: [PATCH 02/23] add wasm eh intrinsics --- compiler/rustc_codegen_llvm/src/context.rs | 4 ++++ compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 + compiler/rustc_codegen_llvm/src/type_.rs | 4 ++++ 3 files changed, 9 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index e8a7afcc632c2..f5ea3b654263a 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -662,6 +662,10 @@ impl<'ll> CodegenCx<'ll, '_> { let t_f32 = self.type_f32(); let t_f64 = self.type_f64(); let t_metadata = self.type_metadata(); + let t_token = self.type_token(); + + ifn!("llvm.wasm.get.exception", fn(t_token) -> i8p); + ifn!("llvm.wasm.get.ehselector", fn(t_token) -> t_i32); ifn!("llvm.wasm.trunc.unsigned.i32.f32", fn(t_f32) -> t_i32); ifn!("llvm.wasm.trunc.unsigned.i32.f64", fn(t_f64) -> t_i32); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 6ef3418cc5f77..5c1657268b74c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1071,6 +1071,7 @@ extern "C" { // Operations on other types pub fn LLVMVoidTypeInContext(C: &Context) -> &Type; + pub fn LLVMTokenTypeInContext(C: &Context) -> &Type; pub fn LLVMMetadataTypeInContext(C: &Context) -> &Type; // Operations on all values diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 4ffa2b9c6a39d..7e672a8dc3362 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -52,6 +52,10 @@ impl<'ll> CodegenCx<'ll, '_> { unsafe { llvm::LLVMVoidTypeInContext(self.llcx) } } + pub(crate) fn type_token(&self) -> &'ll Type { + unsafe { llvm::LLVMTokenTypeInContext(self.llcx) } + } + pub(crate) fn type_metadata(&self) -> &'ll Type { unsafe { llvm::LLVMMetadataTypeInContext(self.llcx) } } From 35cdb28c846dd327801bbcfd274385e3e353b21a Mon Sep 17 00:00:00 2001 From: Jan-Mirko Otter Date: Sun, 7 May 2023 11:02:17 +0200 Subject: [PATCH 03/23] add comment --- compiler/rustc_codegen_ssa/src/mir/block.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index e0cb26d3ba866..b0a9aec3694b3 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -1587,6 +1587,15 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // } catch (...) { // bar(); // } + // + // which creates an IR snippet like + // + // cs_terminate: + // %cs = catchswitch within none [%cp_terminate] unwind to caller + // cp_terminate: + // %cp = catchpad within %cs [null, i32 64, null] + // ... + llbb = Bx::append_block(self.cx, self.llfn, "cs_terminate"); let cp_llbb = Bx::append_block(self.cx, self.llfn, "cp_terminate"); From 82730b452147a3137a732f7f7dc6b7cb2e14f4f9 Mon Sep 17 00:00:00 2001 From: Jan-Mirko Otter Date: Mon, 1 May 2023 19:24:21 +0000 Subject: [PATCH 04/23] wasm exception handling --- compiler/rustc_codegen_llvm/src/context.rs | 19 +++-- compiler/rustc_codegen_llvm/src/intrinsic.rs | 78 +++++++++++++++++++- compiler/rustc_codegen_ssa/src/base.rs | 14 ++++ compiler/rustc_codegen_ssa/src/mir/block.rs | 17 +++-- compiler/rustc_codegen_ssa/src/mir/mod.rs | 3 +- 5 files changed, 117 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index f5ea3b654263a..7cb7506a7c3d3 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -8,7 +8,7 @@ use crate::llvm_util; use crate::type_::Type; use crate::value::Value; -use rustc_codegen_ssa::base::wants_msvc_seh; +use rustc_codegen_ssa::base::{wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::traits::*; use rustc_data_structures::base_n; use rustc_data_structures::fx::FxHashMap; @@ -532,19 +532,24 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { if let Some(llpersonality) = self.eh_personality.get() { return llpersonality; } + + let name = if wants_msvc_seh(self.sess()) { + Some("__CxxFrameHandler3") + } else if wants_wasm_eh(self.sess()) { + Some("__gxx_wasm_personality_v0") + } else { + None + }; + let tcx = self.tcx; let llfn = match tcx.lang_items().eh_personality() { - Some(def_id) if !wants_msvc_seh(self.sess()) => self.get_fn_addr( + Some(def_id) if name.is_none() => self.get_fn_addr( ty::Instance::resolve(tcx, ty::ParamEnv::reveal_all(), def_id, ty::List::empty()) .unwrap() .unwrap(), ), _ => { - let name = if wants_msvc_seh(self.sess()) { - "__CxxFrameHandler3" - } else { - "rust_eh_personality" - }; + let name = name.unwrap_or("rust_eh_personality"); if let Some(llfn) = self.get_declared_value(name) { llfn } else { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 4e28034a8507b..883bb1eb8d060 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -7,7 +7,7 @@ use crate::type_of::LayoutLlvmExt; use crate::va_arg::emit_va_arg; use crate::value::Value; -use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh}; +use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization}; use rustc_codegen_ssa::mir::operand::OperandRef; @@ -452,6 +452,8 @@ fn try_intrinsic<'ll>( bx.store(bx.const_i32(0), dest, ret_align); } else if wants_msvc_seh(bx.sess()) { codegen_msvc_try(bx, try_func, data, catch_func, dest); + } else if wants_wasm_eh(bx.sess()) { + codegen_wasm_try(bx, try_func, data, catch_func, dest); } else if bx.sess().target.os == "emscripten" { codegen_emcc_try(bx, try_func, data, catch_func, dest); } else { @@ -610,6 +612,80 @@ fn codegen_msvc_try<'ll>( bx.store(ret, dest, i32_align); } +// WASM's definition of the `rust_try` function. +fn codegen_wasm_try<'ll>( + bx: &mut Builder<'_, 'll, '_>, + try_func: &'ll Value, + data: &'ll Value, + catch_func: &'ll Value, + dest: &'ll Value, +) { + let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| { + bx.set_personality_fn(bx.eh_personality()); + + let normal = bx.append_sibling_block("normal"); + let catchswitch = bx.append_sibling_block("catchswitch"); + let catchpad = bx.append_sibling_block("catchpad"); + let caught = bx.append_sibling_block("caught"); + + let try_func = llvm::get_param(bx.llfn(), 0); + let data = llvm::get_param(bx.llfn(), 1); + let catch_func = llvm::get_param(bx.llfn(), 2); + + // We're generating an IR snippet that looks like: + // + // declare i32 @rust_try(%try_func, %data, %catch_func) { + // %slot = alloca i8* + // invoke %try_func(%data) to label %normal unwind label %catchswitch + // + // normal: + // ret i32 0 + // + // catchswitch: + // %cs = catchswitch within none [%catchpad_rust] unwind to caller + // + // catchpad: + // %tok = catchpad within %cs [null] + // %ptr = call @llvm.wasm.get.exception(token %tok) + // %sel = call @llvm.wasm.get.ehselector(token %tok) + // call %catch_func(%data, %ptr) + // catchret from %tok to label %caught + // + // caught: + // ret i32 1 + // } + // + let try_func_ty = bx.type_func(&[bx.type_i8p()], bx.type_void()); + bx.invoke(try_func_ty, None, None, try_func, &[data], normal, catchswitch, None); + + bx.switch_to_block(normal); + bx.ret(bx.const_i32(0)); + + bx.switch_to_block(catchswitch); + let cs = bx.catch_switch(None, None, &[catchpad]); + + bx.switch_to_block(catchpad); + let null = bx.const_null(bx.type_i8p()); + let funclet = bx.catch_pad(cs, &[null]); + + let ptr = bx.call_intrinsic("llvm.wasm.get.exception", &[funclet.cleanuppad()]); + let _sel = bx.call_intrinsic("llvm.wasm.get.ehselector", &[funclet.cleanuppad()]); + + let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void()); + bx.call(catch_ty, None, None, catch_func, &[data, ptr], Some(&funclet)); + bx.catch_ret(&funclet, caught); + + bx.switch_to_block(caught); + bx.ret(bx.const_i32(1)); + }); + + // Note that no invoke is used here because by definition this function + // can't panic (that's what it's catching). + let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None); + let i32_align = bx.tcx().data_layout.i32_align.abi; + bx.store(ret, dest, i32_align); +} + // Definition of the standard `try` function for Rust using the GNU-like model // of exceptions (e.g., the normal semantics of LLVM's `landingpad` and `invoke` // instructions). diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index dc4a28c866ff3..d847220e2fad3 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -357,6 +357,13 @@ pub fn cast_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } +// Returns `true` if this session's target will use native wasm +// exceptions. This means that the VM does the unwinding for +// us +pub fn wants_wasm_eh(sess: &Session) -> bool { + sess.target.is_like_wasm && sess.target.os != "emscripten" +} + /// Returns `true` if this session's target will use SEH-based unwinding. /// /// This is only true for MSVC targets, and even then the 64-bit MSVC target @@ -366,6 +373,13 @@ pub fn wants_msvc_seh(sess: &Session) -> bool { sess.target.is_like_msvc } +/// Returns `true` if this session's target requires the new exception +/// handling LLVM IR instructions (catchpad / cleanuppad / ... instead +/// of landingpad) +pub fn wants_new_eh_instructions(sess: &Session) -> bool { + wants_wasm_eh(sess) || wants_msvc_seh(sess) +} + pub fn memcpy_ty<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( bx: &mut Bx, dst: Bx::Value, diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index b0a9aec3694b3..1481dba98a272 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -79,8 +79,8 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { lltarget = fx.landing_pad_for(target); } if is_cleanupret { - // MSVC cross-funclet jump - need a trampoline - debug_assert!(base::wants_msvc_seh(fx.cx.tcx().sess)); + // Cross-funclet jump - need a trampoline + debug_assert!(base::wants_new_eh_instructions(fx.cx.tcx().sess)); debug!("llbb_with_cleanup: creating cleanup trampoline for {:?}", target); let name = &format!("{:?}_cleanup_trampoline_{:?}", self.bb, target); let trampoline_llbb = Bx::append_block(fx.cx, fx.llfn, name); @@ -177,9 +177,16 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { mir::UnwindAction::Continue => None, mir::UnwindAction::Unreachable => None, mir::UnwindAction::Terminate => { - if fx.mir[self.bb].is_cleanup && base::wants_msvc_seh(fx.cx.tcx().sess) { - // SEH will abort automatically if an exception tries to + if fx.mir[self.bb].is_cleanup && base::wants_new_eh_instructions(fx.cx.tcx().sess) { + // MSVC SEH will abort automatically if an exception tries to // propagate out from cleanup. + + // FIXME(@mirkootter): For wasm, we currently do not support terminate during + // cleanup, because this requires a few more changes: The current code + // caches the `terminate_block` for each function; funclet based code - however - + // requires a different terminate_block for each funclet + // Until this is implemented, we just do not unwind inside cleanup blocks + None } else { Some(fx.terminate_block()) @@ -1528,7 +1535,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // FIXME(eddyb) rename this to `eh_pad_for_uncached`. fn landing_pad_for_uncached(&mut self, bb: mir::BasicBlock) -> Bx::BasicBlock { let llbb = self.llbb(bb); - if base::wants_msvc_seh(self.cx.sess()) { + if base::wants_new_eh_instructions(self.cx.sess()) { let cleanup_bb = Bx::append_block(self.cx, self.llfn, &format!("funclet_{:?}", bb)); let mut cleanup_bx = Bx::build(self.cx, cleanup_bb); let funclet = cleanup_bx.cleanup_pad(None, &[]); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 2809ec2deb550..136da3e639880 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -169,7 +169,8 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( start_bx.set_personality_fn(cx.eh_personality()); } - let cleanup_kinds = base::wants_msvc_seh(cx.tcx().sess).then(|| analyze::cleanup_kinds(&mir)); + let cleanup_kinds = + base::wants_new_eh_instructions(cx.tcx().sess).then(|| analyze::cleanup_kinds(&mir)); let cached_llbbs: IndexVec> = mir.basic_blocks From 12ad6622add9246e37ba22f5c3f1f0d212806559 Mon Sep 17 00:00:00 2001 From: Jan-Mirko Otter Date: Mon, 22 May 2023 00:28:44 +0200 Subject: [PATCH 05/23] add comment regarding `__gxx_wasm_personality_v0` --- compiler/rustc_codegen_llvm/src/context.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 7cb7506a7c3d3..287a22bc9a6c5 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -536,6 +536,10 @@ impl<'ll, 'tcx> MiscMethods<'tcx> for CodegenCx<'ll, 'tcx> { let name = if wants_msvc_seh(self.sess()) { Some("__CxxFrameHandler3") } else if wants_wasm_eh(self.sess()) { + // LLVM specifically tests for the name of the personality function + // There is no need for this function to exist anywhere, it will + // not be called. However, its name has to be "__gxx_wasm_personality_v0" + // for native wasm exceptions. Some("__gxx_wasm_personality_v0") } else { None From 744ec64c93937de87a1c74eb2eef265795d9a9d4 Mon Sep 17 00:00:00 2001 From: Jan-Mirko Otter Date: Mon, 22 May 2023 11:19:28 +0200 Subject: [PATCH 06/23] fix comment (review change) Co-authored-by: bjorn3 <17426603+bjorn3@users.noreply.github.com> --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 883bb1eb8d060..31bafa8781480 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -642,7 +642,7 @@ fn codegen_wasm_try<'ll>( // ret i32 0 // // catchswitch: - // %cs = catchswitch within none [%catchpad_rust] unwind to caller + // %cs = catchswitch within none [%catchpad] unwind to caller // // catchpad: // %tok = catchpad within %cs [null] From 8af8a95a64cd765273aae3f4dc0aa50faab148c9 Mon Sep 17 00:00:00 2001 From: He1pa <18012015693@163.com> Date: Wed, 21 Jun 2023 19:01:53 +0800 Subject: [PATCH 07/23] Migrate some rustc_builtin_macros to SessionDiagnostic --- compiler/rustc_builtin_macros/messages.ftl | 25 ++++++ compiler/rustc_builtin_macros/src/asm.rs | 12 +-- .../rustc_builtin_macros/src/cmdline_attrs.rs | 5 +- compiler/rustc_builtin_macros/src/concat.rs | 2 +- .../rustc_builtin_macros/src/concat_bytes.rs | 2 +- compiler/rustc_builtin_macros/src/errors.rs | 88 +++++++++++++++++++ .../src/global_allocator.rs | 3 +- .../src/proc_macro_harness.rs | 14 ++- compiler/rustc_builtin_macros/src/test.rs | 7 +- .../rustc_builtin_macros/src/test_harness.rs | 5 +- .../rustc_builtin_macros/src/trace_macros.rs | 3 +- 11 files changed, 134 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index f00cd39cbc82a..68349449f55cf 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -1,4 +1,5 @@ builtin_macros_alloc_error_must_be_fn = alloc_error_handler must be a function +builtin_macros_alloc_must_statics = allocators must be statics builtin_macros_asm_clobber_abi = clobber_abi builtin_macros_asm_clobber_no_reg = asm with `clobber_abi` must specify explicit registers for outputs @@ -56,6 +57,9 @@ builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `e .label = not applicable here .label2 = not a `struct`, `enum` or `union` +builtin_macros_bench_sig = functions used as benches must have signature `fn(&mut Bencher) -> impl Termination` + + builtin_macros_cannot_derive_union = this trait cannot be derived for unions builtin_macros_cfg_accessible_has_args = `cfg_accessible` path cannot accept arguments @@ -84,6 +88,7 @@ builtin_macros_concat_bytes_non_u8 = numeric literal is not a `u8` builtin_macros_concat_bytes_oob = numeric literal is out of bounds builtin_macros_concat_bytestr = cannot concatenate a byte string literal +builtin_macros_concat_c_str_lit = cannot concatenate a C string literal builtin_macros_concat_idents_ident_args = `concat_idents!()` requires ident args @@ -111,6 +116,10 @@ builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern +builtin_macros_expected_register_class_or_explict_register = expected register class or explicit register + +builtin_macros_export_macro_rules = cannot export macro_rules! macros from a `proc-macro` crate type currently + builtin_macros_format_duplicate_arg = duplicate argument named `{$ident}` .label1 = previously here .label2 = duplicate argument @@ -158,6 +167,8 @@ builtin_macros_format_unused_args = multiple unused formatting arguments builtin_macros_global_asm_clobber_abi = `clobber_abi` cannot be used with `global_asm!` +builtin_macros_invalid_crate_attribute = invalid crate attribute + builtin_macros_multiple_default_attrs = multiple `#[default]` attributes .note = only one `#[default]` attribute is needed .label = `#[default]` used here @@ -177,6 +188,8 @@ builtin_macros_no_default_variant = no default declared .help = make a unit variant default by placing `#[default]` above it .suggestion = make `{$ident}` default +builtin_macros_non_abi = at least one abi must be provided as an argument to `clobber_abi` + builtin_macros_non_exhaustive_default = default variant must be exhaustive .label = declared `#[non_exhaustive]` here .help = consider a manual implementation of `Default` @@ -184,12 +197,20 @@ builtin_macros_non_exhaustive_default = default variant must be exhaustive builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants .help = consider a manual implementation of `Default` +builtin_macros_proc_macro = `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` + builtin_macros_requires_cfg_pattern = macro requires a cfg-pattern as an argument .label = cfg-pattern required +builtin_macros_should_panic = functions using `#[should_panic]` must return `()` + builtin_macros_sugg = consider using a positional formatting argument instead +builtin_macros_test_arg_non_lifetime = functions used as tests can not have any non-lifetime generic parameters + +builtin_macros_test_args = functions used as tests can not have any arguments + builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests .label = `{$kind}` because of this @@ -198,6 +219,10 @@ builtin_macros_test_case_non_item = `#[test_case]` attribute is only allowed on builtin_macros_test_runner_invalid = `test_runner` argument must be a path builtin_macros_test_runner_nargs = `#![test_runner(..)]` accepts exactly 1 argument +builtin_macros_tests_not_support = building tests with panic=abort is not supported without `-Zpanic_abort_tests` + +builtin_macros_trace_macros = trace_macros! accepts only `true` or `false` + builtin_macros_unexpected_lit = expected path to a trait, found literal .label = not a trait .str_lit = try using `#[derive({$sym})]` diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 9734fc2b36d94..5dcbb42ca846b 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -371,11 +371,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a, p.expect(&token::OpenDelim(Delimiter::Parenthesis))?; if p.eat(&token::CloseDelim(Delimiter::Parenthesis)) { - let err = p.sess.span_diagnostic.struct_span_err( - p.token.span, - "at least one abi must be provided as an argument to `clobber_abi`", - ); - return Err(err); + return Err(p.sess.span_diagnostic.create_err(errors::NonABI { span: p.token.span })); } let mut new_abis = Vec::new(); @@ -428,9 +424,9 @@ fn parse_reg<'a>( ast::InlineAsmRegOrRegClass::Reg(symbol) } _ => { - return Err( - p.struct_span_err(p.token.span, "expected register class or explicit register") - ); + return Err(p.sess.create_err(errors::ExpectedRegisterClassOrExplictRegister { + span: p.token.span, + })); } }; p.bump(); diff --git a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs index 2b6fcc169be06..7b75d7d84e4fc 100644 --- a/compiler/rustc_builtin_macros/src/cmdline_attrs.rs +++ b/compiler/rustc_builtin_macros/src/cmdline_attrs.rs @@ -1,5 +1,6 @@ //! Attributes injected into the crate root from command line using `-Z crate-attr`. +use crate::errors; use rustc_ast::attr::mk_attr; use rustc_ast::token; use rustc_ast::{self as ast, AttrItem, AttrStyle}; @@ -24,7 +25,9 @@ pub fn inject(krate: &mut ast::Crate, parse_sess: &ParseSess, attrs: &[String]) }; let end_span = parser.token.span; if parser.token != token::Eof { - parse_sess.span_diagnostic.span_err(start_span.to(end_span), "invalid crate attribute"); + parse_sess + .span_diagnostic + .emit_err(errors::InvalidCrateAttr { span: start_span.to(end_span) }); continue; } diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index 50e88ae2eeede..9695fb4fee13f 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -33,7 +33,7 @@ pub fn expand_concat( accumulator.push_str(&b.to_string()); } Ok(ast::LitKind::CStr(..)) => { - cx.span_err(e.span, "cannot concatenate a C string literal"); + cx.emit_err(errors::ConcatCStrLit{ span: e.span}); has_errors = true; } Ok(ast::LitKind::Byte(..) | ast::LitKind::ByteStr(..)) => { diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 5ef35af0a059a..6a1586f071c45 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -21,7 +21,7 @@ fn invalid_type_err( Ok(ast::LitKind::CStr(_, _)) => { // FIXME(c_str_literals): should concatenation of C string literals // include the null bytes in the end? - cx.span_err(span, "cannot concatenate C string literals"); + cx.emit_err(errors::ConcatCStrLit { span: span }); } Ok(ast::LitKind::Char(_)) => { let sugg = diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index f1ab279dababf..c3beb5da86e62 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -87,6 +87,83 @@ pub(crate) struct ConcatBytestr { pub(crate) span: Span, } +#[derive(Diagnostic)] +#[diag(builtin_macros_concat_c_str_lit)] +pub(crate) struct ConcatCStrLit { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_export_macro_rules)] +pub(crate) struct ExportMacroRules { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_proc_macro)] +pub(crate) struct ProcMacro { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_invalid_crate_attribute)] +pub(crate) struct InvalidCrateAttr { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_non_abi)] +pub(crate) struct NonABI { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_trace_macros)] +pub(crate) struct TraceMacros { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_bench_sig)] +pub(crate) struct BenchSig { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_arg_non_lifetime)] +pub(crate) struct TestArgNonLifetime { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_should_panic)] +pub(crate) struct ShouldPanic { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_test_args)] +pub(crate) struct TestArgs { + #[primary_span] + pub(crate) span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_alloc_must_statics)] +pub(crate) struct AllocMustStatics { + #[primary_span] + pub(crate) span: Span, +} + #[derive(Diagnostic)] #[diag(builtin_macros_concat_bytes_invalid)] pub(crate) struct ConcatBytesInvalid { @@ -201,6 +278,10 @@ pub(crate) struct BadDeriveTarget { pub(crate) item: Span, } +#[derive(Diagnostic)] +#[diag(builtin_macros_tests_not_support)] +pub(crate) struct TestsNotSupport {} + #[derive(Diagnostic)] #[diag(builtin_macros_unexpected_lit, code = "E0777")] pub(crate) struct BadDeriveLit { @@ -732,3 +813,10 @@ pub(crate) struct TestRunnerNargs { #[primary_span] pub(crate) span: Span, } + +#[derive(Diagnostic)] +#[diag(builtin_macros_expected_register_class_or_explict_register)] +pub(crate) struct ExpectedRegisterClassOrExplictRegister { + #[primary_span] + pub(crate) span: Span, +} diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index f0d378d12f712..5772471931f9d 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -1,5 +1,6 @@ use crate::util::check_builtin_macro_attribute; +use crate::errors; use rustc_ast::expand::allocator::{ global_fn_name, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS, }; @@ -34,7 +35,7 @@ pub fn expand( { (item, true, ecx.with_def_site_ctxt(ty.span)) } else { - ecx.sess.parse_sess.span_diagnostic.span_err(item.span(), "allocators must be statics"); + ecx.sess.parse_sess.span_diagnostic.emit_err(errors::AllocMustStatics{span: item.span()}); return vec![orig_item]; }; diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 52b5601bb11b8..b35a2e2a2927e 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -1,3 +1,4 @@ +use crate::errors; use rustc_ast::ptr::P; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, attr, NodeId}; @@ -83,12 +84,7 @@ pub fn inject( impl<'a> CollectProcMacros<'a> { fn check_not_pub_in_root(&self, vis: &ast::Visibility, sp: Span) { if self.is_proc_macro_crate && self.in_root && vis.kind.is_pub() { - self.handler.span_err( - sp, - "`proc-macro` crate types currently cannot export any items other \ - than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, \ - or `#[proc_macro_attribute]`", - ); + self.handler.emit_err(errors::ProcMacro { span: sp }); } } @@ -157,9 +153,9 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { fn visit_item(&mut self, item: &'a ast::Item) { if let ast::ItemKind::MacroDef(..) = item.kind { if self.is_proc_macro_crate && attr::contains_name(&item.attrs, sym::macro_export) { - let msg = - "cannot export macro_rules! macros from a `proc-macro` crate type currently"; - self.handler.span_err(self.source_map.guess_head_span(item.span), msg); + self.handler.emit_err(errors::ExportMacroRules { + span: self.source_map.guess_head_span(item.span), + }); } } diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index d7a92dac50f69..6bc4f6fc1fcfc 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -576,12 +576,7 @@ fn check_bench_signature( // N.B., inadequate check, but we're running // well before resolve, can't get too deep. if f.sig.decl.inputs.len() != 1 { - return Err(cx.sess.parse_sess.span_diagnostic.span_err( - i.span, - "functions used as benches must have \ - signature `fn(&mut Bencher) -> impl Termination`", - )); + return Err(cx.sess.parse_sess.span_diagnostic.emit_err(errors::BenchSig { span: i.span })); } - Ok(()) } diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 9bc1e27b4ec74..81b618548dab9 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -63,10 +63,7 @@ pub fn inject(krate: &mut ast::Crate, sess: &Session, resolver: &mut dyn Resolve // Silently allow compiling with panic=abort on these platforms, // but with old behavior (abort if a test fails). } else { - span_diagnostic.err( - "building tests with panic=abort is not supported \ - without `-Zpanic_abort_tests`", - ); + span_diagnostic.emit_err(errors::TestsNotSupport {}); } PanicStrategy::Unwind } diff --git a/compiler/rustc_builtin_macros/src/trace_macros.rs b/compiler/rustc_builtin_macros/src/trace_macros.rs index 9c98723e1f43f..af1a392acc5e5 100644 --- a/compiler/rustc_builtin_macros/src/trace_macros.rs +++ b/compiler/rustc_builtin_macros/src/trace_macros.rs @@ -1,3 +1,4 @@ +use crate::errors; use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_expand::base::{self, ExtCtxt}; use rustc_span::symbol::kw; @@ -20,7 +21,7 @@ pub fn expand_trace_macros( }; err |= cursor.next().is_some(); if err { - cx.span_err(sp, "trace_macros! accepts only `true` or `false`") + cx.emit_err(errors::TraceMacros { span: sp }); } else { cx.set_trace_macros(value); } From d8d09b06815b14badfa9940f7bfc2a3ff5698ac6 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:04 +1000 Subject: [PATCH 08/23] Declare a `run-coverage` test mode/suite in bootstrap --- src/bootstrap/builder.rs | 1 + src/bootstrap/test.rs | 14 ++++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 7c8e3536df588..77d59452ffced 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -686,6 +686,7 @@ impl<'a> Builder<'a> { test::Tidy, test::Ui, test::RunPassValgrind, + test::RunCoverage, test::MirOpt, test::Codegen, test::CodegenUnits, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index ec447a1cd73ba..398895d16fa0f 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1319,6 +1319,8 @@ host_test!(RunMakeFullDeps { default_test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly" }); +host_test!(RunCoverage { path: "tests/run-coverage", mode: "run-coverage", suite: "run-coverage" }); + // For the mir-opt suite we do not use macros, as we need custom behavior when blessing. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct MirOpt { @@ -1516,7 +1518,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the .arg(builder.ensure(tool::JsonDocLint { compiler: json_compiler, target })); } - if mode == "run-make" { + if mode == "run-make" || mode == "run-coverage" { let rust_demangler = builder .ensure(tool::RustDemangler { compiler, @@ -1703,17 +1705,21 @@ note: if you're sure you want to do this, please open an issue as to why. In the add_link_lib_path(vec![llvm_libdir.trim().into()], &mut cmd); } - // Only pass correct values for these flags for the `run-make` suite as it - // requires that a C++ compiler was configured which isn't always the case. - if !builder.config.dry_run() && matches!(suite, "run-make" | "run-make-fulldeps") { + if !builder.config.dry_run() + && (matches!(suite, "run-make" | "run-make-fulldeps") || mode == "run-coverage") + { // The llvm/bin directory contains many useful cross-platform // tools. Pass the path to run-make tests so they can use them. + // (The run-coverage tests also need these tools to process + // coverage reports.) let llvm_bin_path = llvm_config .parent() .expect("Expected llvm-config to be contained in directory"); assert!(llvm_bin_path.is_dir()); cmd.arg("--llvm-bin-dir").arg(llvm_bin_path); + } + if !builder.config.dry_run() && matches!(suite, "run-make" | "run-make-fulldeps") { // If LLD is available, add it to the PATH if builder.config.lld_enabled { let lld_install_root = From 5b51d9cadb0a91e337b3a2e624e038eedcd0f529 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:04 +1000 Subject: [PATCH 09/23] Extract a common function for setting up environment vars --- src/tools/compiletest/src/runtest.rs | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 5c8ee7895d3b8..4439d60ac06cb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1598,7 +1598,15 @@ impl<'test> TestCx<'test> { } fn exec_compiled_test(&self) -> ProcRes { - let env = &self.props.exec_env; + let prepare_env = |cmd: &mut Command| { + for key in &self.props.unset_exec_env { + cmd.env_remove(key); + } + + for (key, val) in &self.props.exec_env { + cmd.env(key, val); + } + }; let proc_res = match &*self.config.target { // This is pretty similar to below, we're transforming: @@ -1635,10 +1643,7 @@ impl<'test> TestCx<'test> { .args(support_libs) .args(args); - for key in &self.props.unset_exec_env { - test_client.env_remove(key); - } - test_client.envs(env.clone()); + prepare_env(&mut test_client); self.compose_and_run( test_client, @@ -1653,10 +1658,7 @@ impl<'test> TestCx<'test> { let mut wr_run = Command::new("wr-run"); wr_run.args(&[&prog]).args(args); - for key in &self.props.unset_exec_env { - wr_run.env_remove(key); - } - wr_run.envs(env.clone()); + prepare_env(&mut wr_run); self.compose_and_run( wr_run, @@ -1671,10 +1673,7 @@ impl<'test> TestCx<'test> { let mut program = Command::new(&prog); program.args(args).current_dir(&self.output_base_dir()); - for key in &self.props.unset_exec_env { - program.env_remove(key); - } - program.envs(env.clone()); + prepare_env(&mut program); self.compose_and_run( program, From a32cdee4662852eeeba64eebb35516421d330d5b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:04 +1000 Subject: [PATCH 10/23] Introduce `exec_compiled_test_general` This will allow the `run-coverage` mode to easily set environment variable `LLVM_PROFILE_FILE`, and to prevent the executable from being deleted after a successful run. --- src/tools/compiletest/src/runtest.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4439d60ac06cb..c7093c9780dbb 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1598,6 +1598,14 @@ impl<'test> TestCx<'test> { } fn exec_compiled_test(&self) -> ProcRes { + self.exec_compiled_test_general(&[], true) + } + + fn exec_compiled_test_general( + &self, + env_extra: &[(&str, &str)], + delete_after_success: bool, + ) -> ProcRes { let prepare_env = |cmd: &mut Command| { for key in &self.props.unset_exec_env { cmd.env_remove(key); @@ -1606,6 +1614,9 @@ impl<'test> TestCx<'test> { for (key, val) in &self.props.exec_env { cmd.env(key, val); } + for (key, val) in env_extra { + cmd.env(key, val); + } }; let proc_res = match &*self.config.target { @@ -1684,7 +1695,7 @@ impl<'test> TestCx<'test> { } }; - if proc_res.status.success() { + if delete_after_success && proc_res.status.success() { // delete the executable after running it to save space. // it is ok if the deletion failed. let _ = fs::remove_file(self.make_exe_name()); From 75d01f8821f6da653a10fb773c18b56803ed076c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:04 +1000 Subject: [PATCH 11/23] Remember whether `failure-status` was explicitly specified Currently a test without a `failure-status` directive is treated as having an expected failure-status of 1, but `run-coverage` tests will want to treat those tests as expecting success instead. --- src/tools/compiletest/src/header.rs | 11 ++++------- src/tools/compiletest/src/runtest.rs | 2 +- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 8cc935e54d117..00720e1c4db72 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -161,7 +161,7 @@ pub struct TestProps { // customized normalization rules pub normalize_stdout: Vec<(String, String)>, pub normalize_stderr: Vec<(String, String)>, - pub failure_status: i32, + pub failure_status: Option, // For UI tests, allows compiler to exit with arbitrary failure status pub dont_check_failure_status: bool, // Whether or not `rustfix` should apply the `CodeSuggestion`s of this test and compile the @@ -257,7 +257,7 @@ impl TestProps { check_test_line_numbers_match: false, normalize_stdout: vec![], normalize_stderr: vec![], - failure_status: -1, + failure_status: None, dont_check_failure_status: false, run_rustfix: false, rustfix_only_machine_applicable: false, @@ -428,7 +428,7 @@ impl TestProps { .parse_name_value_directive(ln, FAILURE_STATUS) .and_then(|code| code.trim().parse::().ok()) { - self.failure_status = code; + self.failure_status = Some(code); } config.set_name_directive( @@ -491,11 +491,8 @@ impl TestProps { }); } - if self.failure_status == -1 { - self.failure_status = 1; - } if self.should_ice { - self.failure_status = 101; + self.failure_status = Some(101); } if config.mode == Mode::Incremental { diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c7093c9780dbb..91b9f668ce517 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -384,7 +384,7 @@ impl<'test> TestCx<'test> { } fn check_correct_failure_status(&self, proc_res: &ProcRes) { - let expected_status = Some(self.props.failure_status); + let expected_status = Some(self.props.failure_status.unwrap_or(1)); let received_status = proc_res.status.code(); if expected_status != received_status { From a42bbd0eddca3f22923112fa99686de5b79e23e3 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:04 +1000 Subject: [PATCH 12/23] Move the `RUSTC_PROFILER_SUPPORT` check into `CachedNeedsConditions` --- src/tools/compiletest/src/header/needs.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/header/needs.rs b/src/tools/compiletest/src/header/needs.rs index 0e306696a90c9..62364ede47b38 100644 --- a/src/tools/compiletest/src/header/needs.rs +++ b/src/tools/compiletest/src/header/needs.rs @@ -87,7 +87,7 @@ pub(super) fn handle_needs( }, Need { name: "needs-profiler-support", - condition: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(), + condition: cache.profiler_support, ignore_reason: "ignored when profiler support is disabled", }, Need { @@ -195,6 +195,7 @@ pub(super) struct CachedNeedsConditions { sanitizer_memtag: bool, sanitizer_shadow_call_stack: bool, sanitizer_safestack: bool, + profiler_support: bool, xray: bool, rust_lld: bool, i686_dlltool: bool, @@ -232,6 +233,7 @@ impl CachedNeedsConditions { sanitizer_memtag: util::MEMTAG_SUPPORTED_TARGETS.contains(target), sanitizer_shadow_call_stack: util::SHADOWCALLSTACK_SUPPORTED_TARGETS.contains(target), sanitizer_safestack: util::SAFESTACK_SUPPORTED_TARGETS.contains(target), + profiler_support: std::env::var_os("RUSTC_PROFILER_SUPPORT").is_some(), xray: util::XRAY_SUPPORTED_TARGETS.contains(target), // For tests using the `needs-rust-lld` directive (e.g. for `-Zgcc-ld=lld`), we need to find From 22e119bbacd3aa11db04d84947b4fb2c5ccb0435 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:04 +1000 Subject: [PATCH 13/23] Add a custom `run-coverage` mode to compiletest --- src/tools/compiletest/src/common.rs | 3 + src/tools/compiletest/src/header.rs | 37 ++++- src/tools/compiletest/src/runtest.rs | 195 ++++++++++++++++++++++++++- 3 files changed, 232 insertions(+), 3 deletions(-) diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 85a8fbcffbe2d..81684c6f9f9ea 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -66,6 +66,7 @@ string_enum! { JsDocTest => "js-doc-test", MirOpt => "mir-opt", Assembly => "assembly", + RunCoverage => "run-coverage", } } @@ -626,6 +627,7 @@ pub const UI_EXTENSIONS: &[&str] = &[ UI_STDERR_64, UI_STDERR_32, UI_STDERR_16, + UI_COVERAGE, ]; pub const UI_STDERR: &str = "stderr"; pub const UI_STDOUT: &str = "stdout"; @@ -635,6 +637,7 @@ pub const UI_RUN_STDOUT: &str = "run.stdout"; pub const UI_STDERR_64: &str = "64bit.stderr"; pub const UI_STDERR_32: &str = "32bit.stderr"; pub const UI_STDERR_16: &str = "16bit.stderr"; +pub const UI_COVERAGE: &str = "coverage"; /// Absolute path to the directory where all output for all tests in the given /// `relative_dir` group should reside. Example: diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index 00720e1c4db72..b699accf34c12 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -612,10 +612,25 @@ pub fn line_directive<'line>( } fn iter_header(testfile: &Path, rdr: R, it: &mut dyn FnMut(Option<&str>, &str, usize)) { + iter_header_extra(testfile, rdr, &[], it) +} + +fn iter_header_extra( + testfile: &Path, + rdr: impl Read, + extra_directives: &[&str], + it: &mut dyn FnMut(Option<&str>, &str, usize), +) { if testfile.is_dir() { return; } + // Process any extra directives supplied by the caller (e.g. because they + // are implied by the test mode), with a dummy line number of 0. + for directive in extra_directives { + it(None, directive, 0); + } + let comment = if testfile.extension().map(|e| e == "rs") == Some(true) { "//" } else { "#" }; let mut rdr = BufReader::new(rdr); @@ -894,7 +909,27 @@ pub fn make_test_description( let mut ignore_message = None; let mut should_fail = false; - iter_header(path, src, &mut |revision, ln, line_number| { + let extra_directives: &[&str] = match config.mode { + // The run-coverage tests are treated as having these extra directives, + // without needing to specify them manually in every test file. + // (Some of the comments below have been copied over from + // `tests/run-make/coverage-reports/Makefile`.) + Mode::RunCoverage => { + &[ + "needs-profiler-support", + // FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works + // properly. Since we only have GCC on the CI ignore the test for now. + "ignore-windows-gnu", + // FIXME(pietroalbini): this test currently does not work on cross-compiled + // targets because remote-test is not capable of sending back the *.profraw + // files generated by the LLVM instrumentation. + "ignore-cross-compile", + ] + } + _ => &[], + }; + + iter_header_extra(path, src, extra_directives, &mut |revision, ln, line_number| { if revision.is_some() && revision != cfg { return; } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 91b9f668ce517..920db24a1a4f7 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -6,8 +6,8 @@ use crate::common::{Assembly, Incremental, JsDocTest, MirOpt, RunMake, RustdocJs use crate::common::{Codegen, CodegenUnits, DebugInfo, Debugger, Rustdoc}; use crate::common::{CompareMode, FailMode, PassMode}; use crate::common::{Config, TestPaths}; -use crate::common::{Pretty, RunPassValgrind}; -use crate::common::{UI_RUN_STDERR, UI_RUN_STDOUT}; +use crate::common::{Pretty, RunCoverage, RunPassValgrind}; +use crate::common::{UI_COVERAGE, UI_RUN_STDERR, UI_RUN_STDOUT}; use crate::compute_diff::{write_diff, write_filtered_diff}; use crate::errors::{self, Error, ErrorKind}; use crate::header::TestProps; @@ -253,6 +253,7 @@ impl<'test> TestCx<'test> { MirOpt => self.run_mir_opt_test(), Assembly => self.run_assembly_test(), JsDocTest => self.run_js_doc_test(), + RunCoverage => self.run_coverage_test(), } } @@ -465,6 +466,184 @@ impl<'test> TestCx<'test> { } } + fn run_coverage_test(&self) { + let should_run = self.run_if_enabled(); + let proc_res = self.compile_test(should_run, Emit::None); + + if !proc_res.status.success() { + self.fatal_proc_rec("compilation failed!", &proc_res); + } + drop(proc_res); + + if let WillExecute::Disabled = should_run { + return; + } + + let profraw_path = self.output_base_dir().join("default.profraw"); + let profdata_path = self.output_base_dir().join("default.profdata"); + + // Delete any existing profraw/profdata files to rule out unintended + // interference between repeated test runs. + if profraw_path.exists() { + std::fs::remove_file(&profraw_path).unwrap(); + } + if profdata_path.exists() { + std::fs::remove_file(&profdata_path).unwrap(); + } + + let proc_res = self.exec_compiled_test_general( + &[("LLVM_PROFILE_FILE", &profraw_path.to_str().unwrap())], + false, + ); + if self.props.failure_status.is_some() { + self.check_correct_failure_status(&proc_res); + } else if !proc_res.status.success() { + self.fatal_proc_rec("test run failed!", &proc_res); + } + drop(proc_res); + + // Run `llvm-profdata merge` to index the raw coverage output. + let proc_res = self.run_llvm_tool("llvm-profdata", |cmd| { + cmd.args(["merge", "--sparse", "--output"]); + cmd.arg(&profdata_path); + cmd.arg(&profraw_path); + }); + if !proc_res.status.success() { + self.fatal_proc_rec("llvm-profdata merge failed!", &proc_res); + } + drop(proc_res); + + // Run `llvm-cov show` to produce a coverage report in text format. + let proc_res = self.run_llvm_tool("llvm-cov", |cmd| { + cmd.args(["show", "--format=text", "--show-line-counts-or-regions"]); + + cmd.arg("--Xdemangler"); + cmd.arg(self.config.rust_demangler_path.as_ref().unwrap()); + + cmd.arg("--instr-profile"); + cmd.arg(&profdata_path); + + cmd.arg("--object"); + cmd.arg(&self.make_exe_name()); + }); + if !proc_res.status.success() { + self.fatal_proc_rec("llvm-cov show failed!", &proc_res); + } + + let kind = UI_COVERAGE; + + let expected_coverage = self.load_expected_output(kind); + let normalized_actual_coverage = + self.normalize_coverage_output(&proc_res.stdout).unwrap_or_else(|err| { + self.fatal_proc_rec(&err, &proc_res); + }); + + let coverage_errors = self.compare_output( + kind, + &normalized_actual_coverage, + &expected_coverage, + self.props.compare_output_lines_by_subset, + ); + + if coverage_errors > 0 { + self.fatal_proc_rec( + &format!("{} errors occurred comparing coverage output.", coverage_errors), + &proc_res, + ); + } + } + + fn run_llvm_tool(&self, name: &str, configure_cmd_fn: impl FnOnce(&mut Command)) -> ProcRes { + let tool_path = self + .config + .llvm_bin_dir + .as_ref() + .expect("this test expects the LLVM bin dir to be available") + .join(name); + + let mut cmd = Command::new(tool_path); + configure_cmd_fn(&mut cmd); + + let output = cmd.output().unwrap_or_else(|_| panic!("failed to exec `{cmd:?}`")); + + let proc_res = ProcRes { + status: output.status, + stdout: String::from_utf8(output.stdout).unwrap(), + stderr: String::from_utf8(output.stderr).unwrap(), + cmdline: format!("{cmd:?}"), + }; + self.dump_output(&proc_res.stdout, &proc_res.stderr); + + proc_res + } + + fn normalize_coverage_output(&self, coverage: &str) -> Result { + let normalized = self.normalize_output(coverage, &[]); + + let mut lines = normalized.lines().collect::>(); + + Self::sort_coverage_subviews(&mut lines)?; + + let joined_lines = lines.iter().flat_map(|line| [line, "\n"]).collect::(); + Ok(joined_lines) + } + + fn sort_coverage_subviews(coverage_lines: &mut Vec<&str>) -> Result<(), String> { + let mut output_lines = Vec::new(); + + // We accumulate a list of zero or more "subviews", where each + // subview is a list of one or more lines. + let mut subviews: Vec> = Vec::new(); + + fn flush<'a>(subviews: &mut Vec>, output_lines: &mut Vec<&'a str>) { + if subviews.is_empty() { + return; + } + + // Take and clear the list of accumulated subviews. + let mut subviews = std::mem::take(subviews); + + // The last "subview" should be just a boundary line on its own, + // so exclude it when sorting the other subviews. + let except_last = subviews.len() - 1; + (&mut subviews[..except_last]).sort(); + + for view in subviews { + for line in view { + output_lines.push(line); + } + } + } + + for (line, line_num) in coverage_lines.iter().zip(1..) { + if line.starts_with(" ------------------") { + // This is a subview boundary line, so start a new subview. + subviews.push(vec![line]); + } else if line.starts_with(" |") { + // Add this line to the current subview. + subviews + .last_mut() + .ok_or(format!( + "unexpected subview line outside of a subview on line {line_num}" + ))? + .push(line); + } else { + // This line is not part of a subview, so sort and print any + // accumulated subviews, and then print the line as-is. + flush(&mut subviews, &mut output_lines); + output_lines.push(line); + } + } + + flush(&mut subviews, &mut output_lines); + assert!(subviews.is_empty()); + + assert_eq!(output_lines.len(), coverage_lines.len()); + *coverage_lines = output_lines; + + Ok(()) + } + fn run_pretty_test(&self) { if self.props.pp_exact.is_some() { logv(self.config, "testing for exact pretty-printing".to_owned()); @@ -1822,6 +2001,7 @@ impl<'test> TestCx<'test> { || self.is_vxworks_pure_static() || self.config.target.contains("bpf") || !self.config.target_cfg().dynamic_linking + || self.config.mode == RunCoverage { // We primarily compile all auxiliary libraries as dynamic libraries // to avoid code size bloat and large binaries as much as possible @@ -1832,6 +2012,10 @@ impl<'test> TestCx<'test> { // dynamic libraries so we just go back to building a normal library. Note, // however, that for MUSL if the library is built with `force_host` then // it's ok to be a dylib as the host should always support dylibs. + // + // Coverage tests want static linking by default so that coverage + // mappings in auxiliary libraries can be merged into the final + // executable. (false, Some("lib")) } else { (true, Some("dylib")) @@ -2009,6 +2193,10 @@ impl<'test> TestCx<'test> { } } DebugInfo => { /* debuginfo tests must be unoptimized */ } + RunCoverage => { + // Coverage reports are affected by optimization level, and + // the current snapshots assume no optimization by default. + } _ => { rustc.arg("-O"); } @@ -2075,6 +2263,9 @@ impl<'test> TestCx<'test> { rustc.arg(dir_opt); } + RunCoverage => { + rustc.arg("-Cinstrument-coverage"); + } RunPassValgrind | Pretty | DebugInfo | Codegen | Rustdoc | RustdocJson | RunMake | CodegenUnits | JsDocTest | Assembly => { // do not use JSON output From e0625b4586c5a0f855a1157b09ae384f5de0ecf7 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:04 +1000 Subject: [PATCH 14/23] Migrate most of the existing coverage tests over to `run-coverage` --- .../abort.coverage} | 0 tests/{run-make/coverage => run-coverage}/abort.rs | 0 .../assert.coverage} | 2 +- tests/{run-make/coverage => run-coverage}/assert.rs | 2 +- .../async.coverage} | 0 tests/{run-make/coverage => run-coverage}/async.rs | 0 .../async2.coverage} | 0 tests/{run-make/coverage => run-coverage}/async2.rs | 0 .../closure.coverage} | 4 ++-- tests/{run-make/coverage => run-coverage}/closure.rs | 4 ++-- .../closure_macro.coverage} | 0 tests/{run-make/coverage => run-coverage}/closure_macro.rs | 0 .../closure_macro_async.coverage} | 0 .../coverage => run-coverage}/closure_macro_async.rs | 0 .../conditions.coverage} | 0 tests/{run-make/coverage => run-coverage}/conditions.rs | 0 .../continue.coverage} | 0 tests/{run-make/coverage => run-coverage}/continue.rs | 0 .../dead_code.coverage} | 0 tests/{run-make/coverage => run-coverage}/dead_code.rs | 0 .../drop_trait.coverage} | 2 +- tests/{run-make/coverage => run-coverage}/drop_trait.rs | 2 +- .../generator.coverage} | 0 tests/{run-make/coverage => run-coverage}/generator.rs | 0 .../generics.coverage} | 2 +- tests/{run-make/coverage => run-coverage}/generics.rs | 2 +- .../if.coverage} | 0 tests/{run-make/coverage => run-coverage}/if.rs | 0 .../if_else.coverage} | 0 tests/{run-make/coverage => run-coverage}/if_else.rs | 0 .../inline-dead.coverage} | 0 tests/{run-make/coverage => run-coverage}/inline-dead.rs | 0 .../inline.coverage} | 0 tests/{run-make/coverage => run-coverage}/inline.rs | 0 .../inner_items.coverage} | 0 tests/{run-make/coverage => run-coverage}/inner_items.rs | 0 .../issue-83601.coverage} | 0 tests/{run-make/coverage => run-coverage}/issue-83601.rs | 0 .../issue-84561.coverage} | 2 +- tests/{run-make/coverage => run-coverage}/issue-84561.rs | 2 +- .../issue-93054.coverage} | 0 tests/{run-make/coverage => run-coverage}/issue-93054.rs | 0 .../lazy_boolean.coverage} | 0 tests/{run-make/coverage => run-coverage}/lazy_boolean.rs | 0 .../loop_break_value.coverage} | 0 tests/{run-make/coverage => run-coverage}/loop_break_value.rs | 0 .../loops_branches.coverage} | 0 tests/{run-make/coverage => run-coverage}/loops_branches.rs | 0 .../match_or_pattern.coverage} | 0 tests/{run-make/coverage => run-coverage}/match_or_pattern.rs | 0 .../nested_loops.coverage} | 0 tests/{run-make/coverage => run-coverage}/nested_loops.rs | 0 .../no_cov_crate.coverage} | 0 tests/{run-make/coverage => run-coverage}/no_cov_crate.rs | 0 .../overflow.coverage} | 2 +- tests/{run-make/coverage => run-coverage}/overflow.rs | 2 +- .../panic_unwind.coverage} | 2 +- tests/{run-make/coverage => run-coverage}/panic_unwind.rs | 2 +- .../partial_eq.coverage} | 0 tests/{run-make/coverage => run-coverage}/partial_eq.rs | 0 .../simple_loop.coverage} | 0 tests/{run-make/coverage => run-coverage}/simple_loop.rs | 0 .../simple_match.coverage} | 0 tests/{run-make/coverage => run-coverage}/simple_match.rs | 0 .../sort_groups.coverage} | 0 tests/{run-make/coverage => run-coverage}/sort_groups.rs | 0 .../test_harness.coverage} | 0 tests/{run-make/coverage => run-coverage}/test_harness.rs | 0 .../tight_inf_loop.coverage} | 0 tests/{run-make/coverage => run-coverage}/tight_inf_loop.rs | 0 .../try_error_result.coverage} | 2 +- tests/{run-make/coverage => run-coverage}/try_error_result.rs | 2 +- .../unused.coverage} | 0 tests/{run-make/coverage => run-coverage}/unused.rs | 0 .../while.coverage} | 0 tests/{run-make/coverage => run-coverage}/while.rs | 0 .../while_early_ret.coverage} | 2 +- tests/{run-make/coverage => run-coverage}/while_early_ret.rs | 2 +- .../yield.coverage} | 0 tests/{run-make/coverage => run-coverage}/yield.rs | 0 tests/run-make/coverage-reports/Makefile | 4 ++++ 81 files changed, 24 insertions(+), 20 deletions(-) rename tests/{run-make/coverage-reports/expected_show_coverage.abort.txt => run-coverage/abort.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/abort.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.assert.txt => run-coverage/assert.coverage} (97%) rename tests/{run-make/coverage => run-coverage}/assert.rs (98%) rename tests/{run-make/coverage-reports/expected_show_coverage.async.txt => run-coverage/async.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/async.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.async2.txt => run-coverage/async2.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/async2.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.closure.txt => run-coverage/closure.coverage} (98%) rename tests/{run-make/coverage => run-coverage}/closure.rs (98%) rename tests/{run-make/coverage-reports/expected_show_coverage.closure_macro.txt => run-coverage/closure_macro.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/closure_macro.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt => run-coverage/closure_macro_async.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/closure_macro_async.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.conditions.txt => run-coverage/conditions.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/conditions.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.continue.txt => run-coverage/continue.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/continue.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.dead_code.txt => run-coverage/dead_code.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/dead_code.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.drop_trait.txt => run-coverage/drop_trait.coverage} (96%) rename tests/{run-make/coverage => run-coverage}/drop_trait.rs (95%) rename tests/{run-make/coverage-reports/expected_show_coverage.generator.txt => run-coverage/generator.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/generator.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.generics.txt => run-coverage/generics.coverage} (98%) rename tests/{run-make/coverage => run-coverage}/generics.rs (97%) rename tests/{run-make/coverage-reports/expected_show_coverage.if.txt => run-coverage/if.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/if.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.if_else.txt => run-coverage/if_else.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/if_else.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.inline-dead.txt => run-coverage/inline-dead.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/inline-dead.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.inline.txt => run-coverage/inline.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/inline.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.inner_items.txt => run-coverage/inner_items.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/inner_items.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.issue-83601.txt => run-coverage/issue-83601.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/issue-83601.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.issue-84561.txt => run-coverage/issue-84561.coverage} (99%) rename tests/{run-make/coverage => run-coverage}/issue-84561.rs (99%) rename tests/{run-make/coverage-reports/expected_show_coverage.issue-93054.txt => run-coverage/issue-93054.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/issue-93054.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt => run-coverage/lazy_boolean.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/lazy_boolean.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.loop_break_value.txt => run-coverage/loop_break_value.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/loop_break_value.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.loops_branches.txt => run-coverage/loops_branches.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/loops_branches.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt => run-coverage/match_or_pattern.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/match_or_pattern.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.nested_loops.txt => run-coverage/nested_loops.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/nested_loops.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt => run-coverage/no_cov_crate.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/no_cov_crate.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.overflow.txt => run-coverage/overflow.coverage} (99%) rename tests/{run-make/coverage => run-coverage}/overflow.rs (99%) rename tests/{run-make/coverage-reports/expected_show_coverage.panic_unwind.txt => run-coverage/panic_unwind.coverage} (96%) rename tests/{run-make/coverage => run-coverage}/panic_unwind.rs (96%) rename tests/{run-make/coverage-reports/expected_show_coverage.partial_eq.txt => run-coverage/partial_eq.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/partial_eq.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.simple_loop.txt => run-coverage/simple_loop.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/simple_loop.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.simple_match.txt => run-coverage/simple_match.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/simple_match.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.sort_groups.txt => run-coverage/sort_groups.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/sort_groups.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.test_harness.txt => run-coverage/test_harness.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/test_harness.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt => run-coverage/tight_inf_loop.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/tight_inf_loop.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.try_error_result.txt => run-coverage/try_error_result.coverage} (99%) rename tests/{run-make/coverage => run-coverage}/try_error_result.rs (99%) rename tests/{run-make/coverage-reports/expected_show_coverage.unused.txt => run-coverage/unused.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/unused.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.while.txt => run-coverage/while.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/while.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.while_early_ret.txt => run-coverage/while_early_ret.coverage} (97%) rename tests/{run-make/coverage => run-coverage}/while_early_ret.rs (97%) rename tests/{run-make/coverage-reports/expected_show_coverage.yield.txt => run-coverage/yield.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/yield.rs (100%) diff --git a/tests/run-make/coverage-reports/expected_show_coverage.abort.txt b/tests/run-coverage/abort.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.abort.txt rename to tests/run-coverage/abort.coverage diff --git a/tests/run-make/coverage/abort.rs b/tests/run-coverage/abort.rs similarity index 100% rename from tests/run-make/coverage/abort.rs rename to tests/run-coverage/abort.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.assert.txt b/tests/run-coverage/assert.coverage similarity index 97% rename from tests/run-make/coverage-reports/expected_show_coverage.assert.txt rename to tests/run-coverage/assert.coverage index 405688806eaae..a7134a149e2fe 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.assert.txt +++ b/tests/run-coverage/assert.coverage @@ -1,5 +1,5 @@ 1| |#![allow(unused_assignments)] - 2| |// expect-exit-status-101 + 2| |// failure-status: 101 3| | 4| 4|fn might_fail_assert(one_plus_one: u32) { 5| 4| println!("does 1 + 1 = {}?", one_plus_one); diff --git a/tests/run-make/coverage/assert.rs b/tests/run-coverage/assert.rs similarity index 98% rename from tests/run-make/coverage/assert.rs rename to tests/run-coverage/assert.rs index c85f2748eb9d8..d32a37e078e42 100644 --- a/tests/run-make/coverage/assert.rs +++ b/tests/run-coverage/assert.rs @@ -1,5 +1,5 @@ #![allow(unused_assignments)] -// expect-exit-status-101 +// failure-status: 101 fn might_fail_assert(one_plus_one: u32) { println!("does 1 + 1 = {}?", one_plus_one); diff --git a/tests/run-make/coverage-reports/expected_show_coverage.async.txt b/tests/run-coverage/async.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.async.txt rename to tests/run-coverage/async.coverage diff --git a/tests/run-make/coverage/async.rs b/tests/run-coverage/async.rs similarity index 100% rename from tests/run-make/coverage/async.rs rename to tests/run-coverage/async.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.async2.txt b/tests/run-coverage/async2.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.async2.txt rename to tests/run-coverage/async2.coverage diff --git a/tests/run-make/coverage/async2.rs b/tests/run-coverage/async2.rs similarity index 100% rename from tests/run-make/coverage/async2.rs rename to tests/run-coverage/async2.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure.txt b/tests/run-coverage/closure.coverage similarity index 98% rename from tests/run-make/coverage-reports/expected_show_coverage.closure.txt rename to tests/run-coverage/closure.coverage index 002ecec3b916a..45d36b72e3a2f 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.closure.txt +++ b/tests/run-coverage/closure.coverage @@ -1,6 +1,6 @@ 1| |#![allow(unused_assignments, unused_variables)] - 2| |// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs - 3| 1|fn main() { + 2| |// compile-flags: -C opt-level=2 + 3| 1|fn main() { // ^^ fix described in rustc_middle/mir/mono.rs 4| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure 5| 1| // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from 6| 1| // dependent conditions. diff --git a/tests/run-make/coverage/closure.rs b/tests/run-coverage/closure.rs similarity index 98% rename from tests/run-make/coverage/closure.rs rename to tests/run-coverage/closure.rs index 32ec0bcdf8c99..eb3a1ebff8894 100644 --- a/tests/run-make/coverage/closure.rs +++ b/tests/run-coverage/closure.rs @@ -1,6 +1,6 @@ #![allow(unused_assignments, unused_variables)] -// compile-flags: -C opt-level=2 # fix described in rustc_middle/mir/mono.rs -fn main() { +// compile-flags: -C opt-level=2 +fn main() { // ^^ fix described in rustc_middle/mir/mono.rs // Initialize test constants in a way that cannot be determined at compile time, to ensure // rustc and LLVM cannot optimize out statements (or coverage counters) downstream from // dependent conditions. diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt b/tests/run-coverage/closure_macro.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.closure_macro.txt rename to tests/run-coverage/closure_macro.coverage diff --git a/tests/run-make/coverage/closure_macro.rs b/tests/run-coverage/closure_macro.rs similarity index 100% rename from tests/run-make/coverage/closure_macro.rs rename to tests/run-coverage/closure_macro.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt b/tests/run-coverage/closure_macro_async.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.closure_macro_async.txt rename to tests/run-coverage/closure_macro_async.coverage diff --git a/tests/run-make/coverage/closure_macro_async.rs b/tests/run-coverage/closure_macro_async.rs similarity index 100% rename from tests/run-make/coverage/closure_macro_async.rs rename to tests/run-coverage/closure_macro_async.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.conditions.txt b/tests/run-coverage/conditions.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.conditions.txt rename to tests/run-coverage/conditions.coverage diff --git a/tests/run-make/coverage/conditions.rs b/tests/run-coverage/conditions.rs similarity index 100% rename from tests/run-make/coverage/conditions.rs rename to tests/run-coverage/conditions.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.continue.txt b/tests/run-coverage/continue.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.continue.txt rename to tests/run-coverage/continue.coverage diff --git a/tests/run-make/coverage/continue.rs b/tests/run-coverage/continue.rs similarity index 100% rename from tests/run-make/coverage/continue.rs rename to tests/run-coverage/continue.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt b/tests/run-coverage/dead_code.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.dead_code.txt rename to tests/run-coverage/dead_code.coverage diff --git a/tests/run-make/coverage/dead_code.rs b/tests/run-coverage/dead_code.rs similarity index 100% rename from tests/run-make/coverage/dead_code.rs rename to tests/run-coverage/dead_code.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt b/tests/run-coverage/drop_trait.coverage similarity index 96% rename from tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt rename to tests/run-coverage/drop_trait.coverage index fe6a9e93cbf71..293001e9590ea 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.drop_trait.txt +++ b/tests/run-coverage/drop_trait.coverage @@ -1,5 +1,5 @@ 1| |#![allow(unused_assignments)] - 2| |// expect-exit-status-1 + 2| |// failure-status: 1 3| | 4| |struct Firework { 5| | strength: i32, diff --git a/tests/run-make/coverage/drop_trait.rs b/tests/run-coverage/drop_trait.rs similarity index 95% rename from tests/run-make/coverage/drop_trait.rs rename to tests/run-coverage/drop_trait.rs index d15bfc0f87719..a9b5d1d1e7fe9 100644 --- a/tests/run-make/coverage/drop_trait.rs +++ b/tests/run-coverage/drop_trait.rs @@ -1,5 +1,5 @@ #![allow(unused_assignments)] -// expect-exit-status-1 +// failure-status: 1 struct Firework { strength: i32, diff --git a/tests/run-make/coverage-reports/expected_show_coverage.generator.txt b/tests/run-coverage/generator.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.generator.txt rename to tests/run-coverage/generator.coverage diff --git a/tests/run-make/coverage/generator.rs b/tests/run-coverage/generator.rs similarity index 100% rename from tests/run-make/coverage/generator.rs rename to tests/run-coverage/generator.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.generics.txt b/tests/run-coverage/generics.coverage similarity index 98% rename from tests/run-make/coverage-reports/expected_show_coverage.generics.txt rename to tests/run-coverage/generics.coverage index 7eb33a29a926b..7a7649674cac8 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.generics.txt +++ b/tests/run-coverage/generics.coverage @@ -1,5 +1,5 @@ 1| |#![allow(unused_assignments)] - 2| |// expect-exit-status-1 + 2| |// failure-status: 1 3| | 4| |struct Firework where T: Copy + std::fmt::Display { 5| | strength: T, diff --git a/tests/run-make/coverage/generics.rs b/tests/run-coverage/generics.rs similarity index 97% rename from tests/run-make/coverage/generics.rs rename to tests/run-coverage/generics.rs index 18b38868496d4..150ffb9db395a 100644 --- a/tests/run-make/coverage/generics.rs +++ b/tests/run-coverage/generics.rs @@ -1,5 +1,5 @@ #![allow(unused_assignments)] -// expect-exit-status-1 +// failure-status: 1 struct Firework where T: Copy + std::fmt::Display { strength: T, diff --git a/tests/run-make/coverage-reports/expected_show_coverage.if.txt b/tests/run-coverage/if.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.if.txt rename to tests/run-coverage/if.coverage diff --git a/tests/run-make/coverage/if.rs b/tests/run-coverage/if.rs similarity index 100% rename from tests/run-make/coverage/if.rs rename to tests/run-coverage/if.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.if_else.txt b/tests/run-coverage/if_else.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.if_else.txt rename to tests/run-coverage/if_else.coverage diff --git a/tests/run-make/coverage/if_else.rs b/tests/run-coverage/if_else.rs similarity index 100% rename from tests/run-make/coverage/if_else.rs rename to tests/run-coverage/if_else.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt b/tests/run-coverage/inline-dead.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.inline-dead.txt rename to tests/run-coverage/inline-dead.coverage diff --git a/tests/run-make/coverage/inline-dead.rs b/tests/run-coverage/inline-dead.rs similarity index 100% rename from tests/run-make/coverage/inline-dead.rs rename to tests/run-coverage/inline-dead.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inline.txt b/tests/run-coverage/inline.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.inline.txt rename to tests/run-coverage/inline.coverage diff --git a/tests/run-make/coverage/inline.rs b/tests/run-coverage/inline.rs similarity index 100% rename from tests/run-make/coverage/inline.rs rename to tests/run-coverage/inline.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt b/tests/run-coverage/inner_items.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.inner_items.txt rename to tests/run-coverage/inner_items.coverage diff --git a/tests/run-make/coverage/inner_items.rs b/tests/run-coverage/inner_items.rs similarity index 100% rename from tests/run-make/coverage/inner_items.rs rename to tests/run-coverage/inner_items.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt b/tests/run-coverage/issue-83601.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.issue-83601.txt rename to tests/run-coverage/issue-83601.coverage diff --git a/tests/run-make/coverage/issue-83601.rs b/tests/run-coverage/issue-83601.rs similarity index 100% rename from tests/run-make/coverage/issue-83601.rs rename to tests/run-coverage/issue-83601.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt b/tests/run-coverage/issue-84561.coverage similarity index 99% rename from tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt rename to tests/run-coverage/issue-84561.coverage index 4a60432c14c18..7a97e353245a7 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.issue-84561.txt +++ b/tests/run-coverage/issue-84561.coverage @@ -1,6 +1,6 @@ 1| |// This demonstrated Issue #84561: function-like macros produce unintuitive coverage results. 2| | - 3| |// expect-exit-status-101 + 3| |// failure-status: 101 4| 21|#[derive(PartialEq, Eq)] 5| |struct Foo(u32); 6| 1|fn test3() { diff --git a/tests/run-make/coverage/issue-84561.rs b/tests/run-coverage/issue-84561.rs similarity index 99% rename from tests/run-make/coverage/issue-84561.rs rename to tests/run-coverage/issue-84561.rs index b39a289c45e20..facf5b5b4cfbe 100644 --- a/tests/run-make/coverage/issue-84561.rs +++ b/tests/run-coverage/issue-84561.rs @@ -1,6 +1,6 @@ // This demonstrated Issue #84561: function-like macros produce unintuitive coverage results. -// expect-exit-status-101 +// failure-status: 101 #[derive(PartialEq, Eq)] struct Foo(u32); fn test3() { diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt b/tests/run-coverage/issue-93054.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.issue-93054.txt rename to tests/run-coverage/issue-93054.coverage diff --git a/tests/run-make/coverage/issue-93054.rs b/tests/run-coverage/issue-93054.rs similarity index 100% rename from tests/run-make/coverage/issue-93054.rs rename to tests/run-coverage/issue-93054.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt b/tests/run-coverage/lazy_boolean.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.lazy_boolean.txt rename to tests/run-coverage/lazy_boolean.coverage diff --git a/tests/run-make/coverage/lazy_boolean.rs b/tests/run-coverage/lazy_boolean.rs similarity index 100% rename from tests/run-make/coverage/lazy_boolean.rs rename to tests/run-coverage/lazy_boolean.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt b/tests/run-coverage/loop_break_value.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.loop_break_value.txt rename to tests/run-coverage/loop_break_value.coverage diff --git a/tests/run-make/coverage/loop_break_value.rs b/tests/run-coverage/loop_break_value.rs similarity index 100% rename from tests/run-make/coverage/loop_break_value.rs rename to tests/run-coverage/loop_break_value.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt b/tests/run-coverage/loops_branches.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.loops_branches.txt rename to tests/run-coverage/loops_branches.coverage diff --git a/tests/run-make/coverage/loops_branches.rs b/tests/run-coverage/loops_branches.rs similarity index 100% rename from tests/run-make/coverage/loops_branches.rs rename to tests/run-coverage/loops_branches.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt b/tests/run-coverage/match_or_pattern.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.match_or_pattern.txt rename to tests/run-coverage/match_or_pattern.coverage diff --git a/tests/run-make/coverage/match_or_pattern.rs b/tests/run-coverage/match_or_pattern.rs similarity index 100% rename from tests/run-make/coverage/match_or_pattern.rs rename to tests/run-coverage/match_or_pattern.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt b/tests/run-coverage/nested_loops.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.nested_loops.txt rename to tests/run-coverage/nested_loops.coverage diff --git a/tests/run-make/coverage/nested_loops.rs b/tests/run-coverage/nested_loops.rs similarity index 100% rename from tests/run-make/coverage/nested_loops.rs rename to tests/run-coverage/nested_loops.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt b/tests/run-coverage/no_cov_crate.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.no_cov_crate.txt rename to tests/run-coverage/no_cov_crate.coverage diff --git a/tests/run-make/coverage/no_cov_crate.rs b/tests/run-coverage/no_cov_crate.rs similarity index 100% rename from tests/run-make/coverage/no_cov_crate.rs rename to tests/run-coverage/no_cov_crate.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.overflow.txt b/tests/run-coverage/overflow.coverage similarity index 99% rename from tests/run-make/coverage-reports/expected_show_coverage.overflow.txt rename to tests/run-coverage/overflow.coverage index 25e822bffd11f..95043759166bd 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.overflow.txt +++ b/tests/run-coverage/overflow.coverage @@ -1,5 +1,5 @@ 1| |#![allow(unused_assignments)] - 2| |// expect-exit-status-101 + 2| |// failure-status: 101 3| | 4| 4|fn might_overflow(to_add: u32) -> u32 { 5| 4| if to_add > 5 { diff --git a/tests/run-make/coverage/overflow.rs b/tests/run-coverage/overflow.rs similarity index 99% rename from tests/run-make/coverage/overflow.rs rename to tests/run-coverage/overflow.rs index e537b0e95c32a..7df8de6f3cd13 100644 --- a/tests/run-make/coverage/overflow.rs +++ b/tests/run-coverage/overflow.rs @@ -1,5 +1,5 @@ #![allow(unused_assignments)] -// expect-exit-status-101 +// failure-status: 101 fn might_overflow(to_add: u32) -> u32 { if to_add > 5 { diff --git a/tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt b/tests/run-coverage/panic_unwind.coverage similarity index 96% rename from tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt rename to tests/run-coverage/panic_unwind.coverage index 114507dc9fd2a..58b9ba448eea4 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.panic_unwind.txt +++ b/tests/run-coverage/panic_unwind.coverage @@ -1,5 +1,5 @@ 1| |#![allow(unused_assignments)] - 2| |// expect-exit-status-101 + 2| |// failure-status: 101 3| | 4| 4|fn might_panic(should_panic: bool) { 5| 4| if should_panic { diff --git a/tests/run-make/coverage/panic_unwind.rs b/tests/run-coverage/panic_unwind.rs similarity index 96% rename from tests/run-make/coverage/panic_unwind.rs rename to tests/run-coverage/panic_unwind.rs index 03128c2cce628..638d2eb6aaaf8 100644 --- a/tests/run-make/coverage/panic_unwind.rs +++ b/tests/run-coverage/panic_unwind.rs @@ -1,5 +1,5 @@ #![allow(unused_assignments)] -// expect-exit-status-101 +// failure-status: 101 fn might_panic(should_panic: bool) { if should_panic { diff --git a/tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt b/tests/run-coverage/partial_eq.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.partial_eq.txt rename to tests/run-coverage/partial_eq.coverage diff --git a/tests/run-make/coverage/partial_eq.rs b/tests/run-coverage/partial_eq.rs similarity index 100% rename from tests/run-make/coverage/partial_eq.rs rename to tests/run-coverage/partial_eq.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt b/tests/run-coverage/simple_loop.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.simple_loop.txt rename to tests/run-coverage/simple_loop.coverage diff --git a/tests/run-make/coverage/simple_loop.rs b/tests/run-coverage/simple_loop.rs similarity index 100% rename from tests/run-make/coverage/simple_loop.rs rename to tests/run-coverage/simple_loop.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt b/tests/run-coverage/simple_match.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.simple_match.txt rename to tests/run-coverage/simple_match.coverage diff --git a/tests/run-make/coverage/simple_match.rs b/tests/run-coverage/simple_match.rs similarity index 100% rename from tests/run-make/coverage/simple_match.rs rename to tests/run-coverage/simple_match.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.sort_groups.txt b/tests/run-coverage/sort_groups.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.sort_groups.txt rename to tests/run-coverage/sort_groups.coverage diff --git a/tests/run-make/coverage/sort_groups.rs b/tests/run-coverage/sort_groups.rs similarity index 100% rename from tests/run-make/coverage/sort_groups.rs rename to tests/run-coverage/sort_groups.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.test_harness.txt b/tests/run-coverage/test_harness.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.test_harness.txt rename to tests/run-coverage/test_harness.coverage diff --git a/tests/run-make/coverage/test_harness.rs b/tests/run-coverage/test_harness.rs similarity index 100% rename from tests/run-make/coverage/test_harness.rs rename to tests/run-coverage/test_harness.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt b/tests/run-coverage/tight_inf_loop.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.tight_inf_loop.txt rename to tests/run-coverage/tight_inf_loop.coverage diff --git a/tests/run-make/coverage/tight_inf_loop.rs b/tests/run-coverage/tight_inf_loop.rs similarity index 100% rename from tests/run-make/coverage/tight_inf_loop.rs rename to tests/run-coverage/tight_inf_loop.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt b/tests/run-coverage/try_error_result.coverage similarity index 99% rename from tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt rename to tests/run-coverage/try_error_result.coverage index 0ad0180b76149..efe573a5607da 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.try_error_result.txt +++ b/tests/run-coverage/try_error_result.coverage @@ -1,5 +1,5 @@ 1| |#![allow(unused_assignments)] - 2| |// expect-exit-status-1 + 2| |// failure-status: 1 3| | 4| 6|fn call(return_error: bool) -> Result<(),()> { 5| 6| if return_error { diff --git a/tests/run-make/coverage/try_error_result.rs b/tests/run-coverage/try_error_result.rs similarity index 99% rename from tests/run-make/coverage/try_error_result.rs rename to tests/run-coverage/try_error_result.rs index cd0acf7230222..9eb1d2db218b6 100644 --- a/tests/run-make/coverage/try_error_result.rs +++ b/tests/run-coverage/try_error_result.rs @@ -1,5 +1,5 @@ #![allow(unused_assignments)] -// expect-exit-status-1 +// failure-status: 1 fn call(return_error: bool) -> Result<(),()> { if return_error { diff --git a/tests/run-make/coverage-reports/expected_show_coverage.unused.txt b/tests/run-coverage/unused.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.unused.txt rename to tests/run-coverage/unused.coverage diff --git a/tests/run-make/coverage/unused.rs b/tests/run-coverage/unused.rs similarity index 100% rename from tests/run-make/coverage/unused.rs rename to tests/run-coverage/unused.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.while.txt b/tests/run-coverage/while.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.while.txt rename to tests/run-coverage/while.coverage diff --git a/tests/run-make/coverage/while.rs b/tests/run-coverage/while.rs similarity index 100% rename from tests/run-make/coverage/while.rs rename to tests/run-coverage/while.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt b/tests/run-coverage/while_early_ret.coverage similarity index 97% rename from tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt rename to tests/run-coverage/while_early_ret.coverage index d19afc0de61d3..2ce94e0131d1c 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.while_early_ret.txt +++ b/tests/run-coverage/while_early_ret.coverage @@ -1,5 +1,5 @@ 1| |#![allow(unused_assignments)] - 2| |// expect-exit-status-1 + 2| |// failure-status: 1 3| | 4| 1|fn main() -> Result<(),u8> { 5| 1| let mut countdown = 10; diff --git a/tests/run-make/coverage/while_early_ret.rs b/tests/run-coverage/while_early_ret.rs similarity index 97% rename from tests/run-make/coverage/while_early_ret.rs rename to tests/run-coverage/while_early_ret.rs index 1fcea9c85c44a..1c83c8fc7a8f1 100644 --- a/tests/run-make/coverage/while_early_ret.rs +++ b/tests/run-coverage/while_early_ret.rs @@ -1,5 +1,5 @@ #![allow(unused_assignments)] -// expect-exit-status-1 +// failure-status: 1 fn main() -> Result<(),u8> { let mut countdown = 10; diff --git a/tests/run-make/coverage-reports/expected_show_coverage.yield.txt b/tests/run-coverage/yield.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.yield.txt rename to tests/run-coverage/yield.coverage diff --git a/tests/run-make/coverage/yield.rs b/tests/run-coverage/yield.rs similarity index 100% rename from tests/run-make/coverage/yield.rs rename to tests/run-coverage/yield.rs diff --git a/tests/run-make/coverage-reports/Makefile b/tests/run-make/coverage-reports/Makefile index 0ae409c4119e8..283b89edaf02b 100644 --- a/tests/run-make/coverage-reports/Makefile +++ b/tests/run-make/coverage-reports/Makefile @@ -1,3 +1,7 @@ +# NOTE: Most of the tests previously associated with this makefile have been +# migrated over to the custom `run-coverage` test suite instead, so only a few +# harder-to-port tests remain here. + # needs-profiler-support # ignore-windows-gnu From d05653cbe0722a020b12214296ce2c3e50f78934 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:04 +1000 Subject: [PATCH 15/23] Declare a `run-coverage-rustdoc` suite for coverage tests that need `rustdoc` --- src/bootstrap/builder.rs | 1 + src/bootstrap/test.rs | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index 77d59452ffced..a1d3453377ab0 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -695,6 +695,7 @@ impl<'a> Builder<'a> { test::Debuginfo, test::UiFullDeps, test::Rustdoc, + test::RunCoverageRustdoc, test::Pretty, test::Crate, test::CrateLibrustc, diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 398895d16fa0f..2c1f612e39f52 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -1320,6 +1320,11 @@ host_test!(RunMakeFullDeps { default_test!(Assembly { path: "tests/assembly", mode: "assembly", suite: "assembly" }); host_test!(RunCoverage { path: "tests/run-coverage", mode: "run-coverage", suite: "run-coverage" }); +host_test!(RunCoverageRustdoc { + path: "tests/run-coverage-rustdoc", + mode: "run-coverage", + suite: "run-coverage-rustdoc" +}); // For the mir-opt suite we do not use macros, as we need custom behavior when blessing. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -1505,6 +1510,7 @@ note: if you're sure you want to do this, please open an issue as to why. In the || (mode == "ui" && is_rustdoc) || mode == "js-doc-test" || mode == "rustdoc-json" + || suite == "run-coverage-rustdoc" { cmd.arg("--rustdoc-path").arg(builder.rustdoc(compiler)); } From 9d2564a1102bf20f5310c872582518302e5f049b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:04 +1000 Subject: [PATCH 16/23] Expand `run-coverage` to support the remaining `coverage-reports` tests --- src/tools/compiletest/src/runtest.rs | 118 ++++++++++++++++++++++++++- 1 file changed, 115 insertions(+), 3 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 920db24a1a4f7..8bdc2d65d2719 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -502,11 +502,18 @@ impl<'test> TestCx<'test> { } drop(proc_res); + let mut profraw_paths = vec![profraw_path]; + let mut bin_paths = vec![self.make_exe_name()]; + + if self.config.suite == "run-coverage-rustdoc" { + self.run_doctests_for_coverage(&mut profraw_paths, &mut bin_paths); + } + // Run `llvm-profdata merge` to index the raw coverage output. let proc_res = self.run_llvm_tool("llvm-profdata", |cmd| { cmd.args(["merge", "--sparse", "--output"]); cmd.arg(&profdata_path); - cmd.arg(&profraw_path); + cmd.args(&profraw_paths); }); if !proc_res.status.success() { self.fatal_proc_rec("llvm-profdata merge failed!", &proc_res); @@ -523,8 +530,10 @@ impl<'test> TestCx<'test> { cmd.arg("--instr-profile"); cmd.arg(&profdata_path); - cmd.arg("--object"); - cmd.arg(&self.make_exe_name()); + for bin in &bin_paths { + cmd.arg("--object"); + cmd.arg(bin); + } }); if !proc_res.status.success() { self.fatal_proc_rec("llvm-cov show failed!", &proc_res); @@ -553,6 +562,82 @@ impl<'test> TestCx<'test> { } } + /// Run any doctests embedded in this test file, and add any resulting + /// `.profraw` files and doctest executables to the given vectors. + fn run_doctests_for_coverage( + &self, + profraw_paths: &mut Vec, + bin_paths: &mut Vec, + ) { + // Put .profraw files and doctest executables in dedicated directories, + // to make it easier to glob them all later. + let profraws_dir = self.output_base_dir().join("doc_profraws"); + let bins_dir = self.output_base_dir().join("doc_bins"); + + // Remove existing directories to prevent cross-run interference. + if profraws_dir.try_exists().unwrap() { + std::fs::remove_dir_all(&profraws_dir).unwrap(); + } + if bins_dir.try_exists().unwrap() { + std::fs::remove_dir_all(&bins_dir).unwrap(); + } + + let mut rustdoc_cmd = + Command::new(self.config.rustdoc_path.as_ref().expect("--rustdoc-path not passed")); + + // In general there will be multiple doctest binaries running, so we + // tell the profiler runtime to write their coverage data into separate + // profraw files. + rustdoc_cmd.env("LLVM_PROFILE_FILE", profraws_dir.join("%p-%m.profraw")); + + rustdoc_cmd.args(["--test", "-Cinstrument-coverage"]); + + // Without this, the doctests complain about not being able to find + // their enclosing file's crate for some reason. + rustdoc_cmd.args(["--crate-name", "workaround_for_79771"]); + + // Persist the doctest binaries so that `llvm-cov show` can read their + // embedded coverage mappings later. + rustdoc_cmd.arg("-Zunstable-options"); + rustdoc_cmd.arg("--persist-doctests"); + rustdoc_cmd.arg(&bins_dir); + + rustdoc_cmd.arg("-L"); + rustdoc_cmd.arg(self.aux_output_dir_name()); + + rustdoc_cmd.arg(&self.testpaths.file); + + let proc_res = self.compose_and_run_compiler(rustdoc_cmd, None); + if !proc_res.status.success() { + self.fatal_proc_rec("rustdoc --test failed!", &proc_res) + } + + fn glob_iter(path: impl AsRef) -> impl Iterator { + let path_str = path.as_ref().to_str().unwrap(); + let iter = glob(path_str).unwrap(); + iter.map(Result::unwrap) + } + + // Find all profraw files in the profraw directory. + for p in glob_iter(profraws_dir.join("*.profraw")) { + profraw_paths.push(p); + } + // Find all executables in the `--persist-doctests` directory, while + // avoiding other file types (e.g. `.pdb` on Windows). This doesn't + // need to be perfect, as long as it can handle the files actually + // produced by `rustdoc --test`. + for p in glob_iter(bins_dir.join("**/*")) { + let is_bin = p.is_file() + && match p.extension() { + None => true, + Some(ext) => ext == OsStr::new("exe"), + }; + if is_bin { + bin_paths.push(p); + } + } + } + fn run_llvm_tool(&self, name: &str, configure_cmd_fn: impl FnOnce(&mut Command)) -> ProcRes { let tool_path = self .config @@ -582,12 +667,39 @@ impl<'test> TestCx<'test> { let mut lines = normalized.lines().collect::>(); + Self::sort_coverage_file_sections(&mut lines)?; Self::sort_coverage_subviews(&mut lines)?; let joined_lines = lines.iter().flat_map(|line| [line, "\n"]).collect::(); Ok(joined_lines) } + /// Coverage reports can describe multiple source files, separated by + /// blank lines. The order of these files is unpredictable (since it + /// depends on implementation details), so we need to sort the file + /// sections into a consistent order before comparing against a snapshot. + fn sort_coverage_file_sections(coverage_lines: &mut Vec<&str>) -> Result<(), String> { + // Group the lines into file sections, separated by blank lines. + let mut sections = coverage_lines.split(|line| line.is_empty()).collect::>(); + + // The last section should be empty, representing an extra trailing blank line. + if !sections.last().is_some_and(|last| last.is_empty()) { + return Err("coverage report should end with an extra blank line".to_owned()); + } + + // Sort the file sections (not including the final empty "section"). + let except_last = sections.len() - 1; + (&mut sections[..except_last]).sort(); + + // Join the file sections back into a flat list of lines, with + // sections separated by blank lines. + let joined = sections.join(&[""] as &[_]); + assert_eq!(joined.len(), coverage_lines.len()); + *coverage_lines = joined; + + Ok(()) + } + fn sort_coverage_subviews(coverage_lines: &mut Vec<&str>) -> Result<(), String> { let mut output_lines = Vec::new(); From a2c0b388970c95e9ccb088e2abc2cb4f02ed90ae Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:04 +1000 Subject: [PATCH 17/23] Migrate the remaining `run-make/coverage-reports` tests over to `run-coverage` To make it easier to verify that the output snapshots have been migrated faithfully, this change adds some temporary helper code that lets us avoid having to completely re-bless the existing snapshots. A later change in this PR will then re-bless the tests and remove the temporary helper code. --- src/tools/compiletest/src/runtest.rs | 12 ++++++++++++ .../auxiliary}/doctest_crate.rs | 0 .../doctest.coverage} | 6 +++--- .../coverage => run-coverage-rustdoc}/doctest.rs | 2 +- .../auxiliary}/inline_always_with_dead_code.rs | 0 .../auxiliary}/unused_mod_helper.rs | 0 .../lib => run-coverage/auxiliary}/used_crate.rs | 4 ++-- .../auxiliary}/used_inline_crate.rs | 4 ++-- .../issue-85461.coverage} | 6 +++--- .../coverage => run-coverage}/issue-85461.rs | 2 +- .../unused_mod.coverage} | 0 .../coverage => run-coverage}/unused_mod.rs | 2 +- .../uses_crate.coverage} | 4 ++-- .../coverage => run-coverage}/uses_crate.rs | 8 ++++++-- .../uses_inline_crate.coverage} | 4 ++-- .../coverage => run-coverage}/uses_inline_crate.rs | 8 +++++--- 16 files changed, 40 insertions(+), 22 deletions(-) rename tests/{run-make/coverage/lib => run-coverage-rustdoc/auxiliary}/doctest_crate.rs (100%) rename tests/{run-make/coverage-reports/expected_show_coverage.doctest.txt => run-coverage-rustdoc/doctest.coverage} (98%) rename tests/{run-make/coverage => run-coverage-rustdoc}/doctest.rs (99%) rename tests/{run-make/coverage/lib => run-coverage/auxiliary}/inline_always_with_dead_code.rs (100%) rename tests/{run-make/coverage/lib => run-coverage/auxiliary}/unused_mod_helper.rs (100%) rename tests/{run-make/coverage/lib => run-coverage/auxiliary}/used_crate.rs (97%) rename tests/{run-make/coverage/lib => run-coverage/auxiliary}/used_inline_crate.rs (96%) rename tests/{run-make/coverage-reports/expected_show_coverage.issue-85461.txt => run-coverage/issue-85461.coverage} (88%) rename tests/{run-make/coverage => run-coverage}/issue-85461.rs (84%) rename tests/{run-make/coverage-reports/expected_show_coverage.unused_mod.txt => run-coverage/unused_mod.coverage} (100%) rename tests/{run-make/coverage => run-coverage}/unused_mod.rs (59%) rename tests/{run-make/coverage-reports/expected_show_coverage.uses_crate.txt => run-coverage/uses_crate.coverage} (98%) rename tests/{run-make/coverage => run-coverage}/uses_crate.rs (79%) rename tests/{run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt => run-coverage/uses_inline_crate.coverage} (98%) rename tests/{run-make/coverage => run-coverage}/uses_inline_crate.rs (82%) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 8bdc2d65d2719..9f2c45ca1cf23 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -524,6 +524,14 @@ impl<'test> TestCx<'test> { let proc_res = self.run_llvm_tool("llvm-cov", |cmd| { cmd.args(["show", "--format=text", "--show-line-counts-or-regions"]); + // Temporarily ignore these files so that we can migrate the + // existing output snapshots mostly as-is. + // This code will be removed later in the same PR. + cmd.args([ + "--ignore-filename-regex", + "(uses_crate.rs|uses_inline_crate.rs|unused_mod.rs)", + ]); + cmd.arg("--Xdemangler"); cmd.arg(self.config.rust_demangler_path.as_ref().unwrap()); @@ -690,6 +698,10 @@ impl<'test> TestCx<'test> { // Sort the file sections (not including the final empty "section"). let except_last = sections.len() - 1; (&mut sections[..except_last]).sort(); + // Temporarily sort the file sections in reverse order so that we can + // migrate the existing output snapshots mostly as-is. + // This code will be removed later in the same PR. + (&mut sections[..except_last]).sort_by(|a, b| b.cmp(a)); // Join the file sections back into a flat list of lines, with // sections separated by blank lines. diff --git a/tests/run-make/coverage/lib/doctest_crate.rs b/tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs similarity index 100% rename from tests/run-make/coverage/lib/doctest_crate.rs rename to tests/run-coverage-rustdoc/auxiliary/doctest_crate.rs diff --git a/tests/run-make/coverage-reports/expected_show_coverage.doctest.txt b/tests/run-coverage-rustdoc/doctest.coverage similarity index 98% rename from tests/run-make/coverage-reports/expected_show_coverage.doctest.txt rename to tests/run-coverage-rustdoc/doctest.coverage index 732de65262791..8cd25ec371b93 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.doctest.txt +++ b/tests/run-coverage-rustdoc/doctest.coverage @@ -1,4 +1,4 @@ -../coverage/doctest.rs: +$DIR/doctest.rs: 1| |//! This test ensures that code from doctests is properly re-mapped. 2| |//! See for more info. 3| |//! @@ -67,7 +67,7 @@ 63| |//! doctest_main() 64| |//! } 65| |//! ``` - 66| | + 66| |// aux-build:doctest_crate.rs 67| |/// doctest attached to fn testing external code: 68| |/// ``` 69| 1|/// extern crate doctest_crate; @@ -102,7 +102,7 @@ 98| |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care 99| |// if the indentation changed. I don't know if there is a more viable solution. -../coverage/lib/doctest_crate.rs: +$DIR/auxiliary/doctest_crate.rs: 1| |/// A function run only from within doctests 2| 3|pub fn fn_run_in_doctests(conditional: usize) { 3| 3| match conditional { diff --git a/tests/run-make/coverage/doctest.rs b/tests/run-coverage-rustdoc/doctest.rs similarity index 99% rename from tests/run-make/coverage/doctest.rs rename to tests/run-coverage-rustdoc/doctest.rs index ec04ea5706379..251b0c291e94d 100644 --- a/tests/run-make/coverage/doctest.rs +++ b/tests/run-coverage-rustdoc/doctest.rs @@ -63,7 +63,7 @@ //! doctest_main() //! } //! ``` - +// aux-build:doctest_crate.rs /// doctest attached to fn testing external code: /// ``` /// extern crate doctest_crate; diff --git a/tests/run-make/coverage/lib/inline_always_with_dead_code.rs b/tests/run-coverage/auxiliary/inline_always_with_dead_code.rs similarity index 100% rename from tests/run-make/coverage/lib/inline_always_with_dead_code.rs rename to tests/run-coverage/auxiliary/inline_always_with_dead_code.rs diff --git a/tests/run-make/coverage/lib/unused_mod_helper.rs b/tests/run-coverage/auxiliary/unused_mod_helper.rs similarity index 100% rename from tests/run-make/coverage/lib/unused_mod_helper.rs rename to tests/run-coverage/auxiliary/unused_mod_helper.rs diff --git a/tests/run-make/coverage/lib/used_crate.rs b/tests/run-coverage/auxiliary/used_crate.rs similarity index 97% rename from tests/run-make/coverage/lib/used_crate.rs rename to tests/run-coverage/auxiliary/used_crate.rs index 8b8b1f7f351fd..16592d48ddacf 100644 --- a/tests/run-make/coverage/lib/used_crate.rs +++ b/tests/run-coverage/auxiliary/used_crate.rs @@ -1,6 +1,6 @@ #![allow(unused_assignments, unused_variables)] -// compile-flags: -C opt-level=3 # validates coverage now works with optimizations -use std::fmt::Debug; +// compile-flags: -C opt-level=3 +use std::fmt::Debug; // ^^ validates coverage now works with optimizations pub fn used_function() { // Initialize test constants in a way that cannot be determined at compile time, to ensure diff --git a/tests/run-make/coverage/lib/used_inline_crate.rs b/tests/run-coverage/auxiliary/used_inline_crate.rs similarity index 96% rename from tests/run-make/coverage/lib/used_inline_crate.rs rename to tests/run-coverage/auxiliary/used_inline_crate.rs index 4a052756d4e27..8b8e9d5483f33 100644 --- a/tests/run-make/coverage/lib/used_inline_crate.rs +++ b/tests/run-coverage/auxiliary/used_inline_crate.rs @@ -1,7 +1,7 @@ #![allow(unused_assignments, unused_variables)] -// compile-flags: -C opt-level=3 # validates coverage now works with optimizations - +// compile-flags: -C opt-level=3 +// ^^ validates coverage now works with optimizations use std::fmt::Debug; pub fn used_function() { diff --git a/tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt b/tests/run-coverage/issue-85461.coverage similarity index 88% rename from tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt rename to tests/run-coverage/issue-85461.coverage index 1aa4a22c33e18..0f11a69bd7a55 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.issue-85461.txt +++ b/tests/run-coverage/issue-85461.coverage @@ -1,6 +1,6 @@ -../coverage/issue-85461.rs: +$DIR/issue-85461.rs: 1| |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)] - 2| | + 2| |// aux-build:inline_always_with_dead_code.rs 3| |extern crate inline_always_with_dead_code; 4| | 5| |use inline_always_with_dead_code::{bar, baz}; @@ -10,7 +10,7 @@ 9| 1| baz::call_me(); 10| 1|} -../coverage/lib/inline_always_with_dead_code.rs: +$DIR/auxiliary/inline_always_with_dead_code.rs: 1| |// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0 2| | 3| |#![allow(dead_code)] diff --git a/tests/run-make/coverage/issue-85461.rs b/tests/run-coverage/issue-85461.rs similarity index 84% rename from tests/run-make/coverage/issue-85461.rs rename to tests/run-coverage/issue-85461.rs index a1b9ebb1ed348..6f626b4a65b4d 100644 --- a/tests/run-make/coverage/issue-85461.rs +++ b/tests/run-coverage/issue-85461.rs @@ -1,5 +1,5 @@ // Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)] - +// aux-build:inline_always_with_dead_code.rs extern crate inline_always_with_dead_code; use inline_always_with_dead_code::{bar, baz}; diff --git a/tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt b/tests/run-coverage/unused_mod.coverage similarity index 100% rename from tests/run-make/coverage-reports/expected_show_coverage.unused_mod.txt rename to tests/run-coverage/unused_mod.coverage diff --git a/tests/run-make/coverage/unused_mod.rs b/tests/run-coverage/unused_mod.rs similarity index 59% rename from tests/run-make/coverage/unused_mod.rs rename to tests/run-coverage/unused_mod.rs index 679b4e5318803..6e62839c99856 100644 --- a/tests/run-make/coverage/unused_mod.rs +++ b/tests/run-coverage/unused_mod.rs @@ -1,4 +1,4 @@ -#[path = "lib/unused_mod_helper.rs"] +#[path = "auxiliary/unused_mod_helper.rs"] mod unused_module; fn main() { diff --git a/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt b/tests/run-coverage/uses_crate.coverage similarity index 98% rename from tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt rename to tests/run-coverage/uses_crate.coverage index 412f4a93b9c99..5eb6d2667be4e 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.uses_crate.txt +++ b/tests/run-coverage/uses_crate.coverage @@ -1,6 +1,6 @@ 1| |#![allow(unused_assignments, unused_variables)] - 2| |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations - 3| |use std::fmt::Debug; + 2| |// compile-flags: -C opt-level=3 + 3| |use std::fmt::Debug; // ^^ validates coverage now works with optimizations 4| | 5| 1|pub fn used_function() { 6| 1| // Initialize test constants in a way that cannot be determined at compile time, to ensure diff --git a/tests/run-make/coverage/uses_crate.rs b/tests/run-coverage/uses_crate.rs similarity index 79% rename from tests/run-make/coverage/uses_crate.rs rename to tests/run-coverage/uses_crate.rs index 1ee8037a1e79a..ab466970f8e99 100644 --- a/tests/run-make/coverage/uses_crate.rs +++ b/tests/run-coverage/uses_crate.rs @@ -1,8 +1,12 @@ // FIXME #110395 -// ignore-llvm-cov-show-diffs +// ignore-linux + +// Validates coverage now works with optimizations +// compile-flags: -C opt-level=3 #![allow(unused_assignments, unused_variables)] -// compile-flags: -C opt-level=3 # validates coverage now works with optimizations + +// aux-build:used_crate.rs extern crate used_crate; fn main() { diff --git a/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt b/tests/run-coverage/uses_inline_crate.coverage similarity index 98% rename from tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt rename to tests/run-coverage/uses_inline_crate.coverage index 66ca9e80a3278..9ba7177ef35f3 100644 --- a/tests/run-make/coverage-reports/expected_show_coverage.uses_inline_crate.txt +++ b/tests/run-coverage/uses_inline_crate.coverage @@ -1,7 +1,7 @@ 1| |#![allow(unused_assignments, unused_variables)] 2| | - 3| |// compile-flags: -C opt-level=3 # validates coverage now works with optimizations - 4| | + 3| |// compile-flags: -C opt-level=3 + 4| |// ^^ validates coverage now works with optimizations 5| |use std::fmt::Debug; 6| | 7| 1|pub fn used_function() { diff --git a/tests/run-make/coverage/uses_inline_crate.rs b/tests/run-coverage/uses_inline_crate.rs similarity index 82% rename from tests/run-make/coverage/uses_inline_crate.rs rename to tests/run-coverage/uses_inline_crate.rs index f7aff3c3f8a5d..4bd66d2f89cb8 100644 --- a/tests/run-make/coverage/uses_inline_crate.rs +++ b/tests/run-coverage/uses_inline_crate.rs @@ -1,10 +1,12 @@ // FIXME #110395 -// ignore-llvm-cov-show-diffs +// ignore-linux -#![allow(unused_assignments, unused_variables)] +// Validates coverage now works with optimizations +// compile-flags: -C opt-level=3 -// compile-flags: -C opt-level=3 # validates coverage now works with optimizations +#![allow(unused_assignments, unused_variables)] +// aux-build:used_inline_crate.rs extern crate used_inline_crate; fn main() { From edd051c31e267212e21ee30931078210ee55f579 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:04 +1000 Subject: [PATCH 18/23] Re-bless the newly-migrated tests --- src/tools/compiletest/src/runtest.rs | 12 --------- tests/run-coverage-rustdoc/doctest.coverage | 22 ++++++++-------- tests/run-coverage/issue-85461.coverage | 24 +++++++++--------- tests/run-coverage/unused_mod.coverage | 9 +++++++ tests/run-coverage/uses_crate.coverage | 22 ++++++++++++++++ tests/run-coverage/uses_inline_crate.coverage | 25 +++++++++++++++++++ 6 files changed, 79 insertions(+), 35 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 9f2c45ca1cf23..8bdc2d65d2719 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -524,14 +524,6 @@ impl<'test> TestCx<'test> { let proc_res = self.run_llvm_tool("llvm-cov", |cmd| { cmd.args(["show", "--format=text", "--show-line-counts-or-regions"]); - // Temporarily ignore these files so that we can migrate the - // existing output snapshots mostly as-is. - // This code will be removed later in the same PR. - cmd.args([ - "--ignore-filename-regex", - "(uses_crate.rs|uses_inline_crate.rs|unused_mod.rs)", - ]); - cmd.arg("--Xdemangler"); cmd.arg(self.config.rust_demangler_path.as_ref().unwrap()); @@ -698,10 +690,6 @@ impl<'test> TestCx<'test> { // Sort the file sections (not including the final empty "section"). let except_last = sections.len() - 1; (&mut sections[..except_last]).sort(); - // Temporarily sort the file sections in reverse order so that we can - // migrate the existing output snapshots mostly as-is. - // This code will be removed later in the same PR. - (&mut sections[..except_last]).sort_by(|a, b| b.cmp(a)); // Join the file sections back into a flat list of lines, with // sections separated by blank lines. diff --git a/tests/run-coverage-rustdoc/doctest.coverage b/tests/run-coverage-rustdoc/doctest.coverage index 8cd25ec371b93..0fce73a6048b5 100644 --- a/tests/run-coverage-rustdoc/doctest.coverage +++ b/tests/run-coverage-rustdoc/doctest.coverage @@ -1,3 +1,14 @@ +$DIR/auxiliary/doctest_crate.rs: + 1| |/// A function run only from within doctests + 2| 3|pub fn fn_run_in_doctests(conditional: usize) { + 3| 3| match conditional { + 4| 1| 1 => assert_eq!(1, 1), // this is run, + 5| 1| 2 => assert_eq!(1, 1), // this, + 6| 1| 3 => assert_eq!(1, 1), // and this too + 7| 0| _ => assert_eq!(1, 2), // however this is not + 8| | } + 9| 3|} + $DIR/doctest.rs: 1| |//! This test ensures that code from doctests is properly re-mapped. 2| |//! See for more info. @@ -102,14 +113,3 @@ $DIR/doctest.rs: 98| |// what affect it might have on diagnostic messages from the compiler, and whether anyone would care 99| |// if the indentation changed. I don't know if there is a more viable solution. -$DIR/auxiliary/doctest_crate.rs: - 1| |/// A function run only from within doctests - 2| 3|pub fn fn_run_in_doctests(conditional: usize) { - 3| 3| match conditional { - 4| 1| 1 => assert_eq!(1, 1), // this is run, - 5| 1| 2 => assert_eq!(1, 1), // this, - 6| 1| 3 => assert_eq!(1, 1), // and this too - 7| 0| _ => assert_eq!(1, 2), // however this is not - 8| | } - 9| 3|} - diff --git a/tests/run-coverage/issue-85461.coverage b/tests/run-coverage/issue-85461.coverage index 0f11a69bd7a55..d78a4a1129ca1 100644 --- a/tests/run-coverage/issue-85461.coverage +++ b/tests/run-coverage/issue-85461.coverage @@ -1,15 +1,3 @@ -$DIR/issue-85461.rs: - 1| |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)] - 2| |// aux-build:inline_always_with_dead_code.rs - 3| |extern crate inline_always_with_dead_code; - 4| | - 5| |use inline_always_with_dead_code::{bar, baz}; - 6| | - 7| 1|fn main() { - 8| 1| bar::call_me(); - 9| 1| baz::call_me(); - 10| 1|} - $DIR/auxiliary/inline_always_with_dead_code.rs: 1| |// compile-flags: -Cinstrument-coverage -Ccodegen-units=4 -Copt-level=0 2| | @@ -34,3 +22,15 @@ $DIR/auxiliary/inline_always_with_dead_code.rs: 21| 1| } 22| |} +$DIR/issue-85461.rs: + 1| |// Regression test for #85461: MSVC sometimes fail to link with dead code and #[inline(always)] + 2| |// aux-build:inline_always_with_dead_code.rs + 3| |extern crate inline_always_with_dead_code; + 4| | + 5| |use inline_always_with_dead_code::{bar, baz}; + 6| | + 7| 1|fn main() { + 8| 1| bar::call_me(); + 9| 1| baz::call_me(); + 10| 1|} + diff --git a/tests/run-coverage/unused_mod.coverage b/tests/run-coverage/unused_mod.coverage index 82d6fccc2714a..e1d82f66f7557 100644 --- a/tests/run-coverage/unused_mod.coverage +++ b/tests/run-coverage/unused_mod.coverage @@ -1,4 +1,13 @@ +$DIR/auxiliary/unused_mod_helper.rs: 1| 0|pub fn never_called_function() { 2| 0| println!("I am never called"); 3| 0|} +$DIR/unused_mod.rs: + 1| |#[path = "auxiliary/unused_mod_helper.rs"] + 2| |mod unused_module; + 3| | + 4| 1|fn main() { + 5| 1| println!("hello world!"); + 6| 1|} + diff --git a/tests/run-coverage/uses_crate.coverage b/tests/run-coverage/uses_crate.coverage index 5eb6d2667be4e..a3b78e21405a1 100644 --- a/tests/run-coverage/uses_crate.coverage +++ b/tests/run-coverage/uses_crate.coverage @@ -1,3 +1,4 @@ +$DIR/auxiliary/used_crate.rs: 1| |#![allow(unused_assignments, unused_variables)] 2| |// compile-flags: -C opt-level=3 3| |use std::fmt::Debug; // ^^ validates coverage now works with optimizations @@ -146,3 +147,24 @@ 99| |// functions" list, which would then omit coverage results for 100| |// `unused_generic_function()`, below. +$DIR/uses_crate.rs: + 1| |// FIXME #110395 + 2| |// ignore-linux + 3| | + 4| |// Validates coverage now works with optimizations + 5| |// compile-flags: -C opt-level=3 + 6| | + 7| |#![allow(unused_assignments, unused_variables)] + 8| | + 9| |// aux-build:used_crate.rs + 10| |extern crate used_crate; + 11| | + 12| 1|fn main() { + 13| 1| used_crate::used_function(); + 14| 1| let some_vec = vec![1, 2, 3, 4]; + 15| 1| used_crate::used_only_from_bin_crate_generic_function(&some_vec); + 16| 1| used_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs"); + 17| 1| used_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec); + 18| 1| used_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function("interesting?"); + 19| 1|} + diff --git a/tests/run-coverage/uses_inline_crate.coverage b/tests/run-coverage/uses_inline_crate.coverage index 9ba7177ef35f3..f878d8107c53f 100644 --- a/tests/run-coverage/uses_inline_crate.coverage +++ b/tests/run-coverage/uses_inline_crate.coverage @@ -1,3 +1,4 @@ +$DIR/auxiliary/used_inline_crate.rs: 1| |#![allow(unused_assignments, unused_variables)] 2| | 3| |// compile-flags: -C opt-level=3 @@ -137,3 +138,27 @@ 89| 2| used_only_from_this_lib_crate_generic_function("used ONLY from library used_crate.rs"); 90| 2|} +$DIR/uses_inline_crate.rs: + 1| |// FIXME #110395 + 2| |// ignore-linux + 3| | + 4| |// Validates coverage now works with optimizations + 5| |// compile-flags: -C opt-level=3 + 6| | + 7| |#![allow(unused_assignments, unused_variables)] + 8| | + 9| |// aux-build:used_inline_crate.rs + 10| |extern crate used_inline_crate; + 11| | + 12| 1|fn main() { + 13| 1| used_inline_crate::used_function(); + 14| 1| used_inline_crate::used_inline_function(); + 15| 1| let some_vec = vec![1, 2, 3, 4]; + 16| 1| used_inline_crate::used_only_from_bin_crate_generic_function(&some_vec); + 17| 1| used_inline_crate::used_only_from_bin_crate_generic_function("used from bin uses_crate.rs"); + 18| 1| used_inline_crate::used_from_bin_crate_and_lib_crate_generic_function(some_vec); + 19| 1| used_inline_crate::used_with_same_type_from_bin_crate_and_lib_crate_generic_function( + 20| 1| "interesting?", + 21| 1| ); + 22| 1|} + From 7b4e75b98965f45dd35a31968d388c7deca997a2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 12 Jun 2023 18:07:05 +1000 Subject: [PATCH 19/23] Remove the old `coverage-reports` and `coverage` directories --- src/tools/compiletest/src/header.rs | 2 +- tests/run-make/coverage-llvmir/Makefile | 2 +- tests/run-make/coverage-reports/Makefile | 182 ------------------ .../coverage-reports/normalize_paths.py | 12 -- .../coverage-reports/sort_subviews.py | 50 ----- .../coverage/WARNING_KEEP_NAMES_SHORT.txt | 10 - .../run-make/coverage/compiletest-ignore-dir | 3 - tests/run-make/coverage/coverage_tools.mk | 6 - 8 files changed, 2 insertions(+), 265 deletions(-) delete mode 100644 tests/run-make/coverage-reports/Makefile delete mode 100755 tests/run-make/coverage-reports/normalize_paths.py delete mode 100755 tests/run-make/coverage-reports/sort_subviews.py delete mode 100644 tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt delete mode 100644 tests/run-make/coverage/compiletest-ignore-dir delete mode 100644 tests/run-make/coverage/coverage_tools.mk diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index b699accf34c12..c835962ad12fd 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -913,7 +913,7 @@ pub fn make_test_description( // The run-coverage tests are treated as having these extra directives, // without needing to specify them manually in every test file. // (Some of the comments below have been copied over from - // `tests/run-make/coverage-reports/Makefile`.) + // `tests/run-make/coverage-reports/Makefile`, which no longer exists.) Mode::RunCoverage => { &[ "needs-profiler-support", diff --git a/tests/run-make/coverage-llvmir/Makefile b/tests/run-make/coverage-llvmir/Makefile index 7be6550533224..be92f8ac8fc9a 100644 --- a/tests/run-make/coverage-llvmir/Makefile +++ b/tests/run-make/coverage-llvmir/Makefile @@ -6,7 +6,7 @@ # version during testing, with an additional directive at the top of this file # that sets, for example: `min-llvm-version: 12.0` -include ../coverage/coverage_tools.mk +include ../tools.mk BASEDIR=../coverage-llvmir diff --git a/tests/run-make/coverage-reports/Makefile b/tests/run-make/coverage-reports/Makefile deleted file mode 100644 index 283b89edaf02b..0000000000000 --- a/tests/run-make/coverage-reports/Makefile +++ /dev/null @@ -1,182 +0,0 @@ -# NOTE: Most of the tests previously associated with this makefile have been -# migrated over to the custom `run-coverage` test suite instead, so only a few -# harder-to-port tests remain here. - -# needs-profiler-support -# ignore-windows-gnu - -# FIXME(pietroalbini): this test currently does not work on cross-compiled -# targets because remote-test is not capable of sending back the *.profraw -# files generated by the LLVM instrumentation. -# ignore-cross-compile - -# Rust coverage maps support LLVM Coverage Mapping Format versions 5 and 6, -# corresponding with LLVM versions 12 and 13, respectively. -# When upgrading LLVM versions, consider whether to enforce a minimum LLVM -# version during testing, with an additional directive at the top of this file -# that sets, for example: `min-llvm-version: 12.0` - -# FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works -# properly. Since we only have GCC on the CI ignore the test for now. - -include ../coverage/coverage_tools.mk - -BASEDIR=../coverage-reports -SOURCEDIR=../coverage - -# The `llvm-cov show` flag `--debug`, used to generate the `counters` output files, is only -# enabled if LLVM assertions are enabled. This requires Rust config `llvm/optimize` and not -# `llvm/release_debuginfo`. Note that some CI builds disable debug assertions (by setting -# `NO_LLVM_ASSERTIONS=1`), so the tests must still pass even if the `--debug` flag is -# not supported. (Note that `counters` files are only produced in the `$(TMPDIR)` -# directory, for inspection and debugging support. They are *not* copied to `expected_*` -# files when `--bless`ed.) -LLVM_COV_DEBUG := $(shell \ - "$(LLVM_BIN_DIR)"/llvm-cov show --debug 2>&1 | \ - grep -q "Unknown command line argument '--debug'"; \ - echo $$?) -ifeq ($(LLVM_COV_DEBUG), 1) -DEBUG_FLAG=--debug -endif - -# FIXME(richkadel): I'm adding `--ignore-filename-regex=` line(s) for specific test(s) that produce -# `llvm-cov` results for multiple files (for example `uses_crate.rs` and `used_crate/mod.rs`) as a -# workaround for two problems causing tests to fail on Windows: -# -# 1. When multiple files appear in the `llvm-cov show` results, each file's coverage results can -# appear in different a different order. Whether this is random or, somehow, platform-specific, -# the Windows output flips the order of the files, compared to Linux. In the `uses_crate.rs` -# test, the only test-unique (interesting) results we care about are the results for only one -# of the two files, `mod/uses_crate.rs`, so the workaround is to ignore all but this one file. -# In the future, we may want a more sophisticated solution that splits apart `llvm-cov show` -# results into separate results files for each result (taking care not to create new file -# paths that might be too long for Windows MAX_PATH limits when creating these new sub-results, -# as well). -# 2. When multiple files appear in the `llvm-cov show` results, the results for each file are -# prefixed with their filename, including platform-specific path separators (`\` for Windows, -# and `/` everywhere else). This could be filtered or normalized of course, but by ignoring -# coverage results for all but one of the file, the filenames are no longer included anyway. -# If this changes (if/when we decide to support `llvm-cov show` results for multiple files), -# the file path separator differences may need to be addressed. -# -# Since this is only a workaround, I decided to implement the override by adding an option for -# each file to be ignored, using a `--ignore-filename-regex=` entry for each one, rather than -# implement some more sophisticated solution with a new custom test directive in the test file -# itself (similar to `expect-exit-status`) because that would add a lot of complexity and still -# be a workaround, with the same result, with no benefit. -# -# Yes these `--ignore-filename-regex=` options are included in all invocations of `llvm-cov show` -# for now, but it is effectively ignored for all tests that don't include this file anyway. -# -# (Note that it's also possible the `_counters..txt` and `.json` files (if generated) -# may order results from multiple files inconsistently, which might also have to be accommodated -# if and when we allow `llvm-cov` to produce results for multiple files. Note, the path separators -# appear to be normalized to `/` in those files, thankfully.) -LLVM_COV_IGNORE_FILES=\ - --ignore-filename-regex='(uses_crate.rs|uses_inline_crate.rs|unused_mod.rs)' - -all: $(patsubst $(SOURCEDIR)/lib/%.rs,%,$(wildcard $(SOURCEDIR)/lib/*.rs)) $(patsubst $(SOURCEDIR)/%.rs,%,$(wildcard $(SOURCEDIR)/*.rs)) - -# Ensure there are no `expected` results for tests that may have been removed or renamed -.PHONY: clear_expected_if_blessed -clear_expected_if_blessed: -ifdef RUSTC_BLESS_TEST - rm -f expected_* -endif - --include clear_expected_if_blessed - -%: $(SOURCEDIR)/lib/%.rs - # Compile the test library with coverage instrumentation - $(RUSTC) $(SOURCEDIR)/lib/$@.rs \ - $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/lib/$@.rs ) \ - --crate-type rlib -Cinstrument-coverage --target $(TARGET) - -%: $(SOURCEDIR)/%.rs - # Compile the test program with coverage instrumentation - $(RUSTC) $(SOURCEDIR)/$@.rs \ - $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \ - -L "$(TMPDIR)" -Cinstrument-coverage --target $(TARGET) - - # Run it in order to generate some profiling data, - # with `LLVM_PROFILE_FILE=` environment variable set to - # output the coverage stats for this run. - LLVM_PROFILE_FILE="$(TMPDIR)"/$@.profraw \ - $(call RUN,$@) || \ - ( \ - status=$$?; \ - grep -q "^\/\/ expect-exit-status-$$status" $(SOURCEDIR)/$@.rs || \ - ( >&2 echo "program exited with an unexpected exit status: $$status"; \ - false \ - ) \ - ) - - # Run it through rustdoc as well to cover doctests. - # `%p` is the pid, and `%m` the binary signature. We suspect that the pid alone - # might result in overwritten files and failed tests, as rustdoc spawns each - # doctest as its own process, so make sure the filename is as unique as possible. - LLVM_PROFILE_FILE="$(TMPDIR)"/$@-%p-%m.profraw \ - $(RUSTDOC) --crate-name workaround_for_79771 --test $(SOURCEDIR)/$@.rs \ - $$( sed -n 's/^\/\/ compile-flags: \([^#]*\).*/\1/p' $(SOURCEDIR)/$@.rs ) \ - -L "$(TMPDIR)" -Cinstrument-coverage \ - -Z unstable-options --persist-doctests=$(TMPDIR)/rustdoc-$@ - - # Postprocess the profiling data so it can be used by the llvm-cov tool - "$(LLVM_BIN_DIR)"/llvm-profdata merge --sparse \ - "$(TMPDIR)"/$@*.profraw \ - -o "$(TMPDIR)"/$@.profdata - - # Generate a coverage report using `llvm-cov show`. - "$(LLVM_BIN_DIR)"/llvm-cov show \ - $(DEBUG_FLAG) \ - $(LLVM_COV_IGNORE_FILES) \ - --compilation-dir=. \ - --Xdemangler="$(RUST_DEMANGLER)" \ - --show-line-counts-or-regions \ - --instr-profile="$(TMPDIR)"/$@.profdata \ - $(call BIN,"$(TMPDIR)"/$@) \ - $$( \ - for file in $(TMPDIR)/rustdoc-$@/*/rust_out*; do \ - [ -x "$$file" ] && printf "%s %s " -object $$file; \ - done \ - ) \ - 2> "$(TMPDIR)"/show_coverage_stderr.$@.txt \ - | "$(PYTHON)" $(BASEDIR)/normalize_paths.py \ - | "$(PYTHON)" $(BASEDIR)/sort_subviews.py \ - > "$(TMPDIR)"/actual_show_coverage.$@.txt || \ - ( status=$$? ; \ - >&2 cat "$(TMPDIR)"/show_coverage_stderr.$@.txt ; \ - exit $$status \ - ) - -ifdef DEBUG_FLAG - # The first line (beginning with "Args:" contains hard-coded, build-specific - # file paths. Strip that line and keep the remaining lines with counter debug - # data. - tail -n +2 "$(TMPDIR)"/show_coverage_stderr.$@.txt \ - > "$(TMPDIR)"/actual_show_coverage_counters.$@.txt -endif - -ifdef RUSTC_BLESS_TEST - cp "$(TMPDIR)"/actual_show_coverage.$@.txt \ - expected_show_coverage.$@.txt -else - # Compare the show coverage output (`--bless` refreshes `typical` files). - # - # `llvm-cov show` normally prints instantiation groups in an unpredictable - # order, but we have used `sort_subviews.py` to sort them, so we can still - # check the output directly with `diff`. - # - # Some of the test cases are currently not working (since #110393) and have - # been marked with `// ignore-llvm-cov-show-diffs` so that they don't fail - # the build. - - $(DIFF) \ - expected_show_coverage.$@.txt "$(TMPDIR)"/actual_show_coverage.$@.txt || \ - ( grep -q '^\/\/ ignore-llvm-cov-show-diffs' $(SOURCEDIR)/$@.rs && \ - >&2 echo 'diff failed, but suppressed with `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs' \ - ) || \ - ( >&2 echo 'diff failed, and not suppressed without `// ignore-llvm-cov-show-diffs` in $(SOURCEDIR)/$@.rs'; \ - false \ - ) -endif diff --git a/tests/run-make/coverage-reports/normalize_paths.py b/tests/run-make/coverage-reports/normalize_paths.py deleted file mode 100755 index e5777ad2512f1..0000000000000 --- a/tests/run-make/coverage-reports/normalize_paths.py +++ /dev/null @@ -1,12 +0,0 @@ -#!/usr/bin/env python - -from __future__ import print_function - -import sys - -# Normalize file paths in output -for line in sys.stdin: - if line.startswith("..") and line.rstrip().endswith(".rs:"): - print(line.replace("\\", "/"), end='') - else: - print(line, end='') diff --git a/tests/run-make/coverage-reports/sort_subviews.py b/tests/run-make/coverage-reports/sort_subviews.py deleted file mode 100755 index 10cfc51d44771..0000000000000 --- a/tests/run-make/coverage-reports/sort_subviews.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python3 - -# `llvm-cov show` prints grouped subviews (e.g. for generic functions) in an -# unstable order, which is inconvenient when checking output snapshots with -# `diff`. To work around that, this script detects consecutive subviews in its -# piped input, and sorts them while preserving their contents. - -from __future__ import print_function - -import sys - - -def main(): - subviews = [] - - def flush_subviews(): - if not subviews: - return - - # The last "subview" should be just a boundary line on its own, so - # temporarily remove it before sorting the accumulated subviews. - terminator = subviews.pop() - subviews.sort() - subviews.append(terminator) - - for view in subviews: - for line in view: - print(line, end="") - - subviews.clear() - - for line in sys.stdin: - if line.startswith(" ------------------"): - # This is a subview boundary line, so start a new subview. - subviews.append([line]) - elif line.startswith(" |"): - # Add this line to the current subview. - subviews[-1].append(line) - else: - # This line is not part of a subview, so sort and print any - # accumulated subviews, and then print the line as-is. - flush_subviews() - print(line, end="") - - flush_subviews() - assert not subviews - - -if __name__ == "__main__": - main() diff --git a/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt b/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt deleted file mode 100644 index 6a1403b8a0004..0000000000000 --- a/tests/run-make/coverage/WARNING_KEEP_NAMES_SHORT.txt +++ /dev/null @@ -1,10 +0,0 @@ -IMPORTANT: The Rust test programs in this directory generate various output -files in the `../coverage*` directories (`expected` and `actual` files). - -Microsoft Windows has a relatively short limit on file paths (not individual -path components, but the entire path). The files generated by these -`../coverage*` tests typically have file paths that include the program -source file name plus function and type names (depending on the program). - -Keep the test file names short, and keep function names and other symbols -short as well, to avoid hitting the Windows limits. diff --git a/tests/run-make/coverage/compiletest-ignore-dir b/tests/run-make/coverage/compiletest-ignore-dir deleted file mode 100644 index 470ff996098b3..0000000000000 --- a/tests/run-make/coverage/compiletest-ignore-dir +++ /dev/null @@ -1,3 +0,0 @@ -# Directory "coverage" supports the tests at prefix ../coverage-* - -# Use ./x.py [options] test tests/run-make/coverage to run all related tests. diff --git a/tests/run-make/coverage/coverage_tools.mk b/tests/run-make/coverage/coverage_tools.mk deleted file mode 100644 index 028c020a461d0..0000000000000 --- a/tests/run-make/coverage/coverage_tools.mk +++ /dev/null @@ -1,6 +0,0 @@ -# Common Makefile include for Rust `run-make/coverage-* tests. Include this -# file with the line: -# -# include ../coverage/coverage_tools.mk - -include ../tools.mk From 453603a4b52cc2a5e1acdab120840acc3f3a1811 Mon Sep 17 00:00:00 2001 From: He1pa <18012015693@163.com> Date: Wed, 28 Jun 2023 10:52:48 +0800 Subject: [PATCH 20/23] fix typo --- compiler/rustc_builtin_macros/messages.ftl | 2 +- compiler/rustc_builtin_macros/src/asm.rs | 2 +- compiler/rustc_builtin_macros/src/errors.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 68349449f55cf..322222ae33039 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -116,7 +116,7 @@ builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern -builtin_macros_expected_register_class_or_explict_register = expected register class or explicit register +builtin_macros_expected_register_class_or_explicit_register = expected register class or explicit register builtin_macros_export_macro_rules = cannot export macro_rules! macros from a `proc-macro` crate type currently diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 5dcbb42ca846b..6187e4f513b00 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -424,7 +424,7 @@ fn parse_reg<'a>( ast::InlineAsmRegOrRegClass::Reg(symbol) } _ => { - return Err(p.sess.create_err(errors::ExpectedRegisterClassOrExplictRegister { + return Err(p.sess.create_err(errors::ExpectedRegisterClassOrExplicitRegister { span: p.token.span, })); } diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index c3beb5da86e62..7b2a375a822bf 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -815,8 +815,8 @@ pub(crate) struct TestRunnerNargs { } #[derive(Diagnostic)] -#[diag(builtin_macros_expected_register_class_or_explict_register)] -pub(crate) struct ExpectedRegisterClassOrExplictRegister { +#[diag(builtin_macros_expected_register_class_or_explicit_register)] +pub(crate) struct ExpectedRegisterClassOrExplicitRegister { #[primary_span] pub(crate) span: Span, } From 212f1a98a01c133fb1841fdcb583ba0b914dfc9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Wed, 28 Jun 2023 23:51:12 +0800 Subject: [PATCH 21/23] Set error handler output format as soon as possible --- compiler/rustc_session/src/config.rs | 2 ++ tests/ui/diagnostic-flags/colored-session-opt-error.rs | 3 +++ tests/ui/diagnostic-flags/colored-session-opt-error.stderr | 2 ++ 3 files changed, 7 insertions(+) create mode 100644 tests/ui/diagnostic-flags/colored-session-opt-error.rs create mode 100644 tests/ui/diagnostic-flags/colored-session-opt-error.stderr diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 480d2478e8174..91fa3db811fbb 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -2405,6 +2405,8 @@ pub fn build_session_options( let error_format = parse_error_format(handler, matches, color, json_rendered); + handler.abort_if_error_and_set_error_format(error_format); + let diagnostic_width = matches.opt_get("diagnostic-width").unwrap_or_else(|_| { handler.early_error("`--diagnostic-width` must be an positive integer"); }); diff --git a/tests/ui/diagnostic-flags/colored-session-opt-error.rs b/tests/ui/diagnostic-flags/colored-session-opt-error.rs new file mode 100644 index 0000000000000..5511ff0193fd3 --- /dev/null +++ b/tests/ui/diagnostic-flags/colored-session-opt-error.rs @@ -0,0 +1,3 @@ +// check-pass +// compile-flags: -Cremark=foo --error-format=human --color always +fn main() {} diff --git a/tests/ui/diagnostic-flags/colored-session-opt-error.stderr b/tests/ui/diagnostic-flags/colored-session-opt-error.stderr new file mode 100644 index 0000000000000..ef79d5b0f2f82 --- /dev/null +++ b/tests/ui/diagnostic-flags/colored-session-opt-error.stderr @@ -0,0 +1,2 @@ +warning: -C remark requires "-C debuginfo=n" to show source locations + From 1805d44ec9e0a0337a551bff7de84b6a88b79096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=AE=B8=E6=9D=B0=E5=8F=8B=20Jieyou=20Xu=20=28Joe=29?= Date: Thu, 29 Jun 2023 01:32:31 +0800 Subject: [PATCH 22/23] Update UI tests which relied on old behavior of constructing a default error handler every time `early_warn` is called --- tests/ui/conditional-compilation/cfg-arg-invalid-1.rs | 2 +- tests/ui/conditional-compilation/cfg-arg-invalid-2.rs | 2 +- tests/ui/conditional-compilation/cfg-arg-invalid-4.rs | 2 +- tests/ui/conditional-compilation/cfg-arg-invalid-6.rs | 2 +- tests/ui/conditional-compilation/cfg-arg-invalid-8.rs | 2 +- tests/ui/conditional-compilation/cfg-arg-invalid-9.rs | 2 +- tests/ui/conditional-compilation/cfg-empty-codemap.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs index d20e79b9db338..0898ca9cda4df 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-1.rs @@ -1,3 +1,3 @@ -// compile-flags: --cfg a(b=c) +// compile-flags: --error-format=human --cfg a(b=c) // error-pattern: invalid `--cfg` argument: `a(b=c)` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs index 48d656a4a28d9..70e4256006677 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-2.rs @@ -1,3 +1,3 @@ -// compile-flags: --cfg a{b} +// compile-flags: --error-format=human --cfg a{b} // error-pattern: invalid `--cfg` argument: `a{b}` (expected `key` or `key="value"`) fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs index e7dfa17b4b6c4..2adc27eb932eb 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-4.rs @@ -1,3 +1,3 @@ -// compile-flags: --cfg a(b) +// compile-flags: --error-format=human --cfg a(b) // error-pattern: invalid `--cfg` argument: `a(b)` (expected `key` or `key="value"`) fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs index 9fa726f93e3ea..be3ded7dd8b4a 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-6.rs @@ -1,3 +1,3 @@ -// compile-flags: --cfg a{ +// compile-flags: --error-format=human --cfg a{ // error-pattern: invalid `--cfg` argument: `a{` (expected `key` or `key="value"`) fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs index 1d7fa7885348e..4a2f16f113330 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-8.rs @@ -1,3 +1,3 @@ -// compile-flags: --cfg ) +// compile-flags: --error-format=human --cfg ) // error-pattern: invalid `--cfg` argument: `)` (expected `key` or `key="value"`) fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs b/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs index 628b335c87302..a61989a3e9fe1 100644 --- a/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs +++ b/tests/ui/conditional-compilation/cfg-arg-invalid-9.rs @@ -1,4 +1,4 @@ // Test for missing quotes around value, issue #66450. -// compile-flags: --cfg key=value +// compile-flags: --error-format=human --cfg key=value // error-pattern: invalid `--cfg` argument: `key=value` (expected `key` or `key="value"`, ensure escaping is appropriate for your shell, try 'key="value"' or key=\"value\") fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-empty-codemap.rs b/tests/ui/conditional-compilation/cfg-empty-codemap.rs index 9e34cacf74d2a..c7aded7338a20 100644 --- a/tests/ui/conditional-compilation/cfg-empty-codemap.rs +++ b/tests/ui/conditional-compilation/cfg-empty-codemap.rs @@ -1,6 +1,6 @@ // Tests that empty source_maps don't ICE (#23301) -// compile-flags: --cfg "" +// compile-flags: --error-format=human --cfg "" // error-pattern: invalid `--cfg` argument: `""` (expected `key` or `key="value"`) From aafc801d691fb216d3975b0719ad1dd1b3eab527 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 29 Jun 2023 00:46:41 +0000 Subject: [PATCH 23/23] Make the Elaboratable trait take clauses --- compiler/rustc_infer/src/traits/util.rs | 82 +++++++++++++------------ 1 file changed, 42 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index 847b267b6144d..66389cf59957c 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -80,14 +80,14 @@ pub struct Elaborator<'tcx, O> { pub trait Elaboratable<'tcx> { fn predicate(&self) -> ty::Predicate<'tcx>; - // Makes a new `Self` but with a different predicate. - fn child(&self, predicate: ty::Predicate<'tcx>) -> Self; + // Makes a new `Self` but with a different clause that comes from elaboration. + fn child(&self, clause: ty::Clause<'tcx>) -> Self; - // Makes a new `Self` but with a different predicate and a different cause - // code (if `Self` has one). + // Makes a new `Self` but with a different clause and a different cause + // code (if `Self` has one, such as [`PredicateObligation`]). fn child_with_derived_cause( &self, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, span: Span, parent_trait_pred: ty::PolyTraitPredicate<'tcx>, index: usize, @@ -99,18 +99,18 @@ impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> { self.predicate } - fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { + fn child(&self, clause: ty::Clause<'tcx>) -> Self { Obligation { cause: self.cause.clone(), param_env: self.param_env, recursion_depth: 0, - predicate, + predicate: clause.as_predicate(), } } fn child_with_derived_cause( &self, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, span: Span, parent_trait_pred: ty::PolyTraitPredicate<'tcx>, index: usize, @@ -123,7 +123,12 @@ impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> { span, })) }); - Obligation { cause, param_env: self.param_env, recursion_depth: 0, predicate } + Obligation { + cause, + param_env: self.param_env, + recursion_depth: 0, + predicate: clause.as_predicate(), + } } } @@ -132,18 +137,18 @@ impl<'tcx> Elaboratable<'tcx> for ty::Predicate<'tcx> { *self } - fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { - predicate + fn child(&self, clause: ty::Clause<'tcx>) -> Self { + clause.as_predicate() } fn child_with_derived_cause( &self, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, _span: Span, _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, _index: usize, ) -> Self { - predicate + clause.as_predicate() } } @@ -152,18 +157,18 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) { self.0 } - fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { - (predicate, self.1) + fn child(&self, clause: ty::Clause<'tcx>) -> Self { + (clause.as_predicate(), self.1) } fn child_with_derived_cause( &self, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, _span: Span, _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, _index: usize, ) -> Self { - (predicate, self.1) + (clause.as_predicate(), self.1) } } @@ -172,18 +177,18 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Clause<'tcx>, Span) { self.0.as_predicate() } - fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { - (predicate.expect_clause(), self.1) + fn child(&self, clause: ty::Clause<'tcx>) -> Self { + (clause, self.1) } fn child_with_derived_cause( &self, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, _span: Span, _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, _index: usize, ) -> Self { - (predicate.expect_clause(), self.1) + (clause, self.1) } } @@ -192,18 +197,18 @@ impl<'tcx> Elaboratable<'tcx> for ty::Clause<'tcx> { self.as_predicate() } - fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { - predicate.expect_clause() + fn child(&self, clause: ty::Clause<'tcx>) -> Self { + clause } fn child_with_derived_cause( &self, - predicate: ty::Predicate<'tcx>, + clause: ty::Clause<'tcx>, _span: Span, _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, _index: usize, ) -> Self { - predicate.expect_clause() + clause } } @@ -252,14 +257,13 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { }; let obligations = - predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| { + predicates.predicates.iter().enumerate().map(|(index, &(mut clause, span))| { // when parent predicate is non-const, elaborate it to non-const predicates. if data.constness == ty::BoundConstness::NotConst { - pred = pred.without_const(tcx); + clause = clause.without_const(tcx); } elaboratable.child_with_derived_cause( - pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)) - .as_predicate(), + clause.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), span, bound_predicate.rebind(data), index, @@ -333,17 +337,15 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { if r.is_late_bound() { None } else { - Some(ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives( - ty::OutlivesPredicate(r, r_min), + Some(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate( + r, r_min, ))) } } Component::Param(p) => { let ty = tcx.mk_ty_param(p.index, p.name); - Some(ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives( - ty::OutlivesPredicate(ty, r_min), - ))) + Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, r_min))) } Component::UnresolvedInferenceVariable(_) => None, @@ -351,8 +353,9 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { Component::Alias(alias_ty) => { // We might end up here if we have `Foo<::Assoc>: 'a`. // With this, we can deduce that `::Assoc: 'a`. - Some(ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives( - ty::OutlivesPredicate(alias_ty.to_ty(tcx), r_min), + Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate( + alias_ty.to_ty(tcx), + r_min, ))) } @@ -362,10 +365,9 @@ impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { None } }) - .map(|predicate_kind| { - bound_predicate.rebind(predicate_kind).to_predicate(tcx) - }) - .map(|predicate| elaboratable.child(predicate)), + .map(|clause| { + elaboratable.child(bound_predicate.rebind(clause).to_predicate(tcx)) + }), ); } ty::PredicateKind::Clause(ty::ClauseKind::TypeWellFormedFromEnv(..)) => {