From 3a6af84fca1b41614887748e9fdb0e2b2a13fb96 Mon Sep 17 00:00:00 2001 From: Elliot Roberts Date: Tue, 12 Apr 2022 07:46:07 -0700 Subject: [PATCH 01/23] change std::process to drop supplementary groups based on CAP_SETGID --- library/std/src/os/unix/process.rs | 7 +++++++ .../std/src/sys/pal/unix/process/process_unix.rs | 14 +++++++++++--- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/library/std/src/os/unix/process.rs b/library/std/src/os/unix/process.rs index e45457b2e42b4..72ea54bd77203 100644 --- a/library/std/src/os/unix/process.rs +++ b/library/std/src/os/unix/process.rs @@ -39,6 +39,13 @@ pub trait CommandExt: Sealed { /// Sets the child process's user ID. This translates to a /// `setuid` call in the child process. Failure in the `setuid` /// call will cause the spawn to fail. + /// + /// # Notes + /// + /// This will also trigger a call to `setgroups(0, NULL)` in the child + /// process if no groups have been specified. + /// This removes supplementary groups that might have given the child + /// unwanted permissions. #[stable(feature = "rust1", since = "1.0.0")] fn uid(&mut self, id: UserId) -> &mut process::Command; diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs index 97cbd1929d329..f017d39d804aa 100644 --- a/library/std/src/sys/pal/unix/process/process_unix.rs +++ b/library/std/src/sys/pal/unix/process/process_unix.rs @@ -330,14 +330,22 @@ impl Command { if let Some(u) = self.get_uid() { // When dropping privileges from root, the `setgroups` call // will remove any extraneous groups. We only drop groups - // if the current uid is 0 and we weren't given an explicit + // if we have CAP_SETGID and we weren't given an explicit // set of groups. If we don't call this, then even though our // uid has dropped, we may still have groups that enable us to // do super-user things. //FIXME: Redox kernel does not support setgroups yet #[cfg(not(target_os = "redox"))] - if libc::getuid() == 0 && self.get_groups().is_none() { - cvt(libc::setgroups(0, crate::ptr::null()))?; + if self.get_groups().is_none() { + let res = cvt(libc::setgroups(0, crate::ptr::null())); + if let Err(e) = res { + // Here we ignore the case of not having CAP_SETGID. + // An alternative would be to require CAP_SETGID (in + // addition to CAP_SETUID) for setting the UID. + if e.raw_os_error() != Some(libc::EPERM) { + return Err(e.into()); + } + } } cvt(libc::setuid(u as uid_t))?; } From aa692a577eee7fa1aaa72d29efeb860bbae6572f Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Tue, 24 Oct 2023 14:59:05 +0800 Subject: [PATCH 02/23] [AIX] Remove AixLinker's debuginfo() implementation `-s` option doesn't perfectly fit into debuginfo()'s semantics and may unexpectedly remove metadata in shared libraries. Remove the implementation and suggest user to use `strip` utility instead. --- compiler/rustc_codegen_ssa/src/back/linker.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index e52efd8695558..9bdff2abee9ee 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -1639,16 +1639,7 @@ impl<'a> Linker for AixLinker<'a> { fn ehcont_guard(&mut self) {} - fn debuginfo(&mut self, strip: Strip, _: &[PathBuf]) { - match strip { - Strip::None => {} - // FIXME: -s strips the symbol table, line number information - // and relocation information. - Strip::Debuginfo | Strip::Symbols => { - self.cmd.arg("-s"); - } - } - } + fn debuginfo(&mut self, _: Strip, _: &[PathBuf]) {} fn no_crt_objects(&mut self) {} From e74e6e767d4b5cc1f033cee5b5ef4704dd8fee31 Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Tue, 5 Mar 2024 15:37:37 +0800 Subject: [PATCH 03/23] Rebased --- compiler/rustc_codegen_ssa/src/back/link.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index fcb3602b7349c..b52e6242d992d 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1080,6 +1080,21 @@ fn link_natively<'a>( } } + if sess.target.is_like_aix { + let stripcmd = "/usr/bin/strip"; + match strip { + Strip::Debuginfo => { + // FIXME: AIX's strip utility only offers option to strip line number information. + strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-l")) + } + Strip::Symbols => { + // Must be noted this option removes symbol __aix_rust_metadata and thus removes .info section which contains metadata. + strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-r")) + } + Strip::None => {} + } + } + Ok(()) } From b1c390989fc8b74aa36f445cd66316a8ca96455d Mon Sep 17 00:00:00 2001 From: Kai Luo Date: Tue, 5 Mar 2024 15:42:31 +0800 Subject: [PATCH 04/23] Adjust wording --- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index b52e6242d992d..a8d6963294df3 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1088,7 +1088,7 @@ fn link_natively<'a>( strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-l")) } Strip::Symbols => { - // Must be noted this option removes symbol __aix_rust_metadata and thus removes .info section which contains metadata. + // Must be noted this option might remove symbol __aix_rust_metadata and thus removes .info section which contains metadata. strip_symbols_with_external_utility(sess, stripcmd, out_filename, Some("-r")) } Strip::None => {} From 207fe38630fdcfecea048aa41c6a9dd47c19573f Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Fri, 8 Mar 2024 17:11:27 -0500 Subject: [PATCH 05/23] copy byval argument to alloca if alignment is insufficient --- compiler/rustc_codegen_llvm/src/abi.rs | 104 ++++++++------- compiler/rustc_codegen_ssa/src/mir/mod.rs | 62 +++++---- .../codegen/align-byval-alignment-mismatch.rs | 126 ++++++++++++++++++ 3 files changed, 220 insertions(+), 72 deletions(-) create mode 100644 tests/codegen/align-byval-alignment-mismatch.rs diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index 147939d3a529a..e5f5146fac8fb 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -203,57 +203,63 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { val: &'ll Value, dst: PlaceRef<'tcx, &'ll Value>, ) { - if self.is_ignore() { - return; - } - if self.is_sized_indirect() { - OperandValue::Ref(val, None, self.layout.align.abi).store(bx, dst) - } else if self.is_unsized_indirect() { - bug!("unsized `ArgAbi` must be handled through `store_fn_arg`"); - } else if let PassMode::Cast { cast, pad_i32: _ } = &self.mode { - // FIXME(eddyb): Figure out when the simpler Store is safe, clang - // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}. - let can_store_through_cast_ptr = false; - if can_store_through_cast_ptr { - bx.store(val, dst.llval, self.layout.align.abi); - } else { - // The actual return type is a struct, but the ABI - // adaptation code has cast it into some scalar type. The - // code that follows is the only reliable way I have - // found to do a transform like i64 -> {i32,i32}. - // Basically we dump the data onto the stack then memcpy it. - // - // Other approaches I tried: - // - Casting rust ret pointer to the foreign type and using Store - // is (a) unsafe if size of foreign type > size of rust type and - // (b) runs afoul of strict aliasing rules, yielding invalid - // assembly under -O (specifically, the store gets removed). - // - Truncating foreign type to correct integral type and then - // bitcasting to the struct type yields invalid cast errors. - - // We instead thus allocate some scratch space... - let scratch_size = cast.size(bx); - let scratch_align = cast.align(bx); - let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align); - bx.lifetime_start(llscratch, scratch_size); - - // ... where we first store the value... - bx.store(val, llscratch, scratch_align); - - // ... and then memcpy it to the intended destination. - bx.memcpy( - dst.llval, - self.layout.align.abi, - llscratch, - scratch_align, - bx.const_usize(self.layout.size.bytes()), - MemFlags::empty(), - ); + match &self.mode { + PassMode::Ignore => {} + // Sized indirect arguments + PassMode::Indirect { attrs, meta_attrs: None, on_stack: _ } => { + let align = attrs.pointee_align.unwrap_or(self.layout.align.abi); + OperandValue::Ref(val, None, align).store(bx, dst); + } + // Unsized indirect qrguments + PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + bug!("unsized `ArgAbi` must be handled through `store_fn_arg`"); + } + PassMode::Cast { cast, pad_i32: _ } => { + // FIXME(eddyb): Figure out when the simpler Store is safe, clang + // uses it for i16 -> {i8, i8}, but not for i24 -> {i8, i8, i8}. + let can_store_through_cast_ptr = false; + if can_store_through_cast_ptr { + bx.store(val, dst.llval, self.layout.align.abi); + } else { + // The actual return type is a struct, but the ABI + // adaptation code has cast it into some scalar type. The + // code that follows is the only reliable way I have + // found to do a transform like i64 -> {i32,i32}. + // Basically we dump the data onto the stack then memcpy it. + // + // Other approaches I tried: + // - Casting rust ret pointer to the foreign type and using Store + // is (a) unsafe if size of foreign type > size of rust type and + // (b) runs afoul of strict aliasing rules, yielding invalid + // assembly under -O (specifically, the store gets removed). + // - Truncating foreign type to correct integral type and then + // bitcasting to the struct type yields invalid cast errors. + + // We instead thus allocate some scratch space... + let scratch_size = cast.size(bx); + let scratch_align = cast.align(bx); + let llscratch = bx.alloca(cast.llvm_type(bx), scratch_align); + bx.lifetime_start(llscratch, scratch_size); + + // ... where we first store the value... + bx.store(val, llscratch, scratch_align); + + // ... and then memcpy it to the intended destination. + bx.memcpy( + dst.llval, + self.layout.align.abi, + llscratch, + scratch_align, + bx.const_usize(self.layout.size.bytes()), + MemFlags::empty(), + ); - bx.lifetime_end(llscratch, scratch_size); + bx.lifetime_end(llscratch, scratch_size); + } + } + _ => { + OperandRef::from_immediate_or_packed_pair(bx, val, self.layout).val.store(bx, dst); } - } else { - OperandRef::from_immediate_or_packed_pair(bx, val, self.layout).val.store(bx, dst); } } diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index a6fcf1fd38c1f..2ae51d18c7ef9 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -367,29 +367,45 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } - if arg.is_sized_indirect() { - // Don't copy an indirect argument to an alloca, the caller - // already put it in a temporary alloca and gave it up. - // FIXME: lifetimes - let llarg = bx.get_param(llarg_idx); - llarg_idx += 1; - LocalRef::Place(PlaceRef::new_sized(llarg, arg.layout)) - } else if arg.is_unsized_indirect() { - // As the storage for the indirect argument lives during - // the whole function call, we just copy the fat pointer. - let llarg = bx.get_param(llarg_idx); - llarg_idx += 1; - let llextra = bx.get_param(llarg_idx); - llarg_idx += 1; - let indirect_operand = OperandValue::Pair(llarg, llextra); - - let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout); - indirect_operand.store(bx, tmp); - LocalRef::UnsizedPlace(tmp) - } else { - let tmp = PlaceRef::alloca(bx, arg.layout); - bx.store_fn_arg(arg, &mut llarg_idx, tmp); - LocalRef::Place(tmp) + match arg.mode { + // Sized indirect arguments + PassMode::Indirect { attrs, meta_attrs: None, on_stack: _ } => { + // Don't copy an indirect argument to an alloca, the caller already put it + // in a temporary alloca and gave it up. + // FIXME: lifetimes + if let Some(pointee_align) = attrs.pointee_align + && pointee_align < arg.layout.align.abi + { + // ...unless the argument is underaligned, then we need to copy it to + // a higher-aligned alloca. + let tmp = PlaceRef::alloca(bx, arg.layout); + bx.store_fn_arg(arg, &mut llarg_idx, tmp); + LocalRef::Place(tmp) + } else { + let llarg = bx.get_param(llarg_idx); + llarg_idx += 1; + LocalRef::Place(PlaceRef::new_sized(llarg, arg.layout)) + } + } + // Unsized indirect qrguments + PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + // As the storage for the indirect argument lives during + // the whole function call, we just copy the fat pointer. + let llarg = bx.get_param(llarg_idx); + llarg_idx += 1; + let llextra = bx.get_param(llarg_idx); + llarg_idx += 1; + let indirect_operand = OperandValue::Pair(llarg, llextra); + + let tmp = PlaceRef::alloca_unsized_indirect(bx, arg.layout); + indirect_operand.store(bx, tmp); + LocalRef::UnsizedPlace(tmp) + } + _ => { + let tmp = PlaceRef::alloca(bx, arg.layout); + bx.store_fn_arg(arg, &mut llarg_idx, tmp); + LocalRef::Place(tmp) + } } }) .collect::>(); diff --git a/tests/codegen/align-byval-alignment-mismatch.rs b/tests/codegen/align-byval-alignment-mismatch.rs new file mode 100644 index 0000000000000..306e3ce1358af --- /dev/null +++ b/tests/codegen/align-byval-alignment-mismatch.rs @@ -0,0 +1,126 @@ +// ignore-tidy-linelength +//@ revisions:i686-linux x86_64-linux + +//@[i686-linux] compile-flags: --target i686-unknown-linux-gnu +//@[i686-linux] needs-llvm-components: x86 +//@[x86_64-linux] compile-flags: --target x86_64-unknown-linux-gnu +//@[x86_64-linux] needs-llvm-components: x86 + +// Tests that we correctly copy arguments into allocas when the alignment of the byval argument +// is different from the alignment of the Rust type. + +// For the following test cases: +// All of the `*_decreases_alignment` functions should codegen to a direct call, since the +// alignment is already sufficient. +// All off the `*_increases_alignment` functions should copy the argument to an alloca +// on i686-unknown-linux-gnu, since the alignment needs to be increased, and should codegen +// to a direct call on x86_64-unknown-linux-gnu, where byval alignment matches Rust alignment. + +#![feature(no_core, lang_items)] +#![crate_type = "lib"] +#![no_std] +#![no_core] +#![allow(non_camel_case_types)] + +#[lang = "sized"] +trait Sized {} +#[lang = "freeze"] +trait Freeze {} +#[lang = "copy"] +trait Copy {} + +// This type has align 1 in Rust, but as a byval argument on i686-linux, it will have align 4. +#[repr(C)] +#[repr(packed)] +struct Align1 { + x: u128, + y: u128, + z: u128, +} + +// This type has align 16 in Rust, but as a byval argument on i686-linux, it will have align 4. +#[repr(C)] +#[repr(align(16))] +struct Align16 { + x: u128, + y: u128, + z: u128, +} + +extern "C" { + fn extern_c_align1(x: Align1); + fn extern_c_align16(x: Align16); +} + +// CHECK-LABEL: @rust_to_c_increases_alignment +#[no_mangle] +pub unsafe fn rust_to_c_increases_alignment(x: Align1) { + // i686-linux: start: + // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca %Align1, align 4 + // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 4 {{.*}}[[ALLOCA]], ptr {{.*}}align 1 {{.*}}%x + // i686-linux-NEXT: call void @extern_c_align1({{.+}} [[ALLOCA]]) + + // x86_64-linux: start: + // x86_64-linux-NEXT: call void @extern_c_align1 + extern_c_align1(x); +} + +// CHECK-LABEL: @rust_to_c_decreases_alignment +#[no_mangle] +pub unsafe fn rust_to_c_decreases_alignment(x: Align16) { + // CHECK: start: + // CHECK-NEXT: call void @extern_c_align16 + extern_c_align16(x); +} + +extern "Rust" { + fn extern_rust_align1(x: Align1); + fn extern_rust_align16(x: Align16); +} + +// CHECK-LABEL: @c_to_rust_decreases_alignment +#[no_mangle] +pub unsafe extern "C" fn c_to_rust_decreases_alignment(x: Align1) { + // CHECK: start: + // CHECK-NEXT: call void @extern_rust_align1 + extern_rust_align1(x); +} + +// CHECK-LABEL: @c_to_rust_increases_alignment +#[no_mangle] +pub unsafe extern "C" fn c_to_rust_increases_alignment(x: Align16) { + // i686-linux: start: + // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca %Align16, align 16 + // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 16 {{.*}}[[ALLOCA]], ptr {{.*}}align 4 {{.*}}%0 + // i686-linux-NEXT: call void @extern_rust_align16({{.+}} [[ALLOCA]]) + + // x86_64-linux: start: + // x86_64-linux-NEXT: call void @extern_rust_align16 + extern_rust_align16(x); +} + +extern "Rust" { + fn extern_rust_ref_align1(x: &Align1); + fn extern_rust_ref_align16(x: &Align16); +} + +// CHECK-LABEL: @c_to_rust_ref_decreases_alignment +#[no_mangle] +pub unsafe extern "C" fn c_to_rust_ref_decreases_alignment(x: Align1) { + // CHECK: start: + // CHECK-NEXT: call void @extern_rust_ref_align1 + extern_rust_ref_align1(&x); +} + +// CHECK-LABEL: @c_to_rust_ref_increases_alignment +#[no_mangle] +pub unsafe extern "C" fn c_to_rust_ref_increases_alignment(x: Align16) { + // i686-linux: start: + // i686-linux-NEXT: [[ALLOCA:%[0-9a-z]+]] = alloca %Align16, align 16 + // i686-linux-NEXT: call void @llvm.memcpy.{{.+}}(ptr {{.*}}align 16 {{.*}}[[ALLOCA]], ptr {{.*}}align 4 {{.*}}%0 + // i686-linux-NEXT: call void @extern_rust_ref_align16({{.+}} [[ALLOCA]]) + + // x86_64-linux: start: + // x86_64-linux-NEXT: call void @extern_rust_ref_align16 + extern_rust_ref_align16(&x); +} From 818f13095ac79db831078c7a2b3dede90eecf86f Mon Sep 17 00:00:00 2001 From: Erik Desjardins Date: Mon, 11 Mar 2024 09:39:43 -0400 Subject: [PATCH 06/23] update make_indirect_byval comment about missing fix (this PR is the fix) --- compiler/rustc_target/src/abi/call/mod.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_target/src/abi/call/mod.rs b/compiler/rustc_target/src/abi/call/mod.rs index cb587e28a6c99..486afc5f8f30a 100644 --- a/compiler/rustc_target/src/abi/call/mod.rs +++ b/compiler/rustc_target/src/abi/call/mod.rs @@ -633,10 +633,8 @@ impl<'a, Ty> ArgAbi<'a, Ty> { /// If the resulting alignment differs from the type's alignment, /// the argument will be copied to an alloca with sufficient alignment, /// either in the caller (if the type's alignment is lower than the byval alignment) - /// or in the callee† (if the type's alignment is higher than the byval alignment), + /// or in the callee (if the type's alignment is higher than the byval alignment), /// to ensure that Rust code never sees an underaligned pointer. - /// - /// † This is currently broken, see . pub fn make_indirect_byval(&mut self, byval_align: Option) { assert!(!self.layout.is_unsized(), "used byval ABI for unsized layout"); self.make_indirect(); From 89fab06a772985cad3e117f52a7f5fdb12804fc1 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Mon, 25 Dec 2023 21:23:15 +1100 Subject: [PATCH 07/23] coverage: Add branch coverage tests (with branch coverage disabled) --- tests/coverage/branch_generics.cov-map | 45 ++++++++ tests/coverage/branch_generics.coverage | 48 +++++++++ tests/coverage/branch_generics.rs | 19 ++++ tests/coverage/branch_guard.cov-map | 24 +++++ tests/coverage/branch_guard.coverage | 39 +++++++ tests/coverage/branch_guard.rs | 37 +++++++ tests/coverage/branch_if.cov-map | 136 ++++++++++++++++++++++++ tests/coverage/branch_if.coverage | 86 +++++++++++++++ tests/coverage/branch_if.rs | 81 ++++++++++++++ tests/coverage/branch_while.cov-map | 74 +++++++++++++ tests/coverage/branch_while.coverage | 60 +++++++++++ tests/coverage/branch_while.rs | 58 ++++++++++ 12 files changed, 707 insertions(+) create mode 100644 tests/coverage/branch_generics.cov-map create mode 100644 tests/coverage/branch_generics.coverage create mode 100644 tests/coverage/branch_generics.rs create mode 100644 tests/coverage/branch_guard.cov-map create mode 100644 tests/coverage/branch_guard.coverage create mode 100644 tests/coverage/branch_guard.rs create mode 100644 tests/coverage/branch_if.cov-map create mode 100644 tests/coverage/branch_if.coverage create mode 100644 tests/coverage/branch_if.rs create mode 100644 tests/coverage/branch_while.cov-map create mode 100644 tests/coverage/branch_while.coverage create mode 100644 tests/coverage/branch_while.rs diff --git a/tests/coverage/branch_generics.cov-map b/tests/coverage/branch_generics.cov-map new file mode 100644 index 0000000000000..ff8bb632a54f6 --- /dev/null +++ b/tests/coverage/branch_generics.cov-map @@ -0,0 +1,45 @@ +Function name: branch_generics::print_size::<()> +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 06, 01, 01, 24, 05, 01, 25, 02, 06, 02, 02, 0c, 02, 06, 07, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36) +- Code(Counter(1)) at (prev + 1, 37) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: branch_generics::print_size:: +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 06, 01, 01, 24, 05, 01, 25, 02, 06, 02, 02, 0c, 02, 06, 07, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36) +- Code(Counter(1)) at (prev + 1, 37) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + +Function name: branch_generics::print_size:: +Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 06, 01, 01, 24, 05, 01, 25, 02, 06, 02, 02, 0c, 02, 06, 07, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) +Number of file 0 mappings: 4 +- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36) +- Code(Counter(1)) at (prev + 1, 37) to (start + 2, 6) +- Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) + = (c0 - c1) +- Code(Expression(1, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c1 + (c0 - c1)) + diff --git a/tests/coverage/branch_generics.coverage b/tests/coverage/branch_generics.coverage new file mode 100644 index 0000000000000..cfbd2d3f4bd46 --- /dev/null +++ b/tests/coverage/branch_generics.coverage @@ -0,0 +1,48 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| | + LL| |//@ llvm-cov-flags: --show-branches=count + LL| | + LL| 3|fn print_size() { + LL| 3| if std::mem::size_of::() > 4 { + LL| 1| println!("size > 4"); + LL| 2| } else { + LL| 2| println!("size <= 4"); + LL| 2| } + LL| 3|} + ------------------ + | branch_generics::print_size::<()>: + | LL| 1|fn print_size() { + | LL| 1| if std::mem::size_of::() > 4 { + | LL| 0| println!("size > 4"); + | LL| 1| } else { + | LL| 1| println!("size <= 4"); + | LL| 1| } + | LL| 1|} + ------------------ + | branch_generics::print_size::: + | LL| 1|fn print_size() { + | LL| 1| if std::mem::size_of::() > 4 { + | LL| 0| println!("size > 4"); + | LL| 1| } else { + | LL| 1| println!("size <= 4"); + | LL| 1| } + | LL| 1|} + ------------------ + | branch_generics::print_size::: + | LL| 1|fn print_size() { + | LL| 1| if std::mem::size_of::() > 4 { + | LL| 1| println!("size > 4"); + | LL| 1| } else { + | LL| 0| println!("size <= 4"); + | LL| 0| } + | LL| 1|} + ------------------ + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | print_size::<()>(); + LL| | print_size::(); + LL| | print_size::(); + LL| |} + diff --git a/tests/coverage/branch_generics.rs b/tests/coverage/branch_generics.rs new file mode 100644 index 0000000000000..ad1f5be33c4b1 --- /dev/null +++ b/tests/coverage/branch_generics.rs @@ -0,0 +1,19 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 + +//@ llvm-cov-flags: --show-branches=count + +fn print_size() { + if std::mem::size_of::() > 4 { + println!("size > 4"); + } else { + println!("size <= 4"); + } +} + +#[coverage(off)] +fn main() { + print_size::<()>(); + print_size::(); + print_size::(); +} diff --git a/tests/coverage/branch_guard.cov-map b/tests/coverage/branch_guard.cov-map new file mode 100644 index 0000000000000..e0cbbf491960f --- /dev/null +++ b/tests/coverage/branch_guard.cov-map @@ -0,0 +1,24 @@ +Function name: branch_guard::branch_match_guard +Raw bytes (67): 0x[01, 01, 04, 05, 09, 0b, 15, 0f, 11, 03, 0d, 0b, 01, 0c, 01, 01, 10, 1d, 03, 0b, 00, 0c, 15, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 19, 00, 14, 00, 19, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 1d, 00, 14, 00, 19, 11, 00, 1d, 02, 0a, 03, 03, 0e, 02, 0a, 07, 04, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(5) +- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(4) +- expression 3 operands: lhs = Expression(0, Add), rhs = Counter(3) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(7)) at (prev + 3, 11) to (start + 0, 12) +- Code(Counter(5)) at (prev + 1, 20) to (start + 2, 10) +- Code(Counter(3)) at (prev + 3, 14) to (start + 0, 15) +- Code(Counter(6)) at (prev + 0, 20) to (start + 0, 25) +- Code(Counter(3)) at (prev + 0, 29) to (start + 2, 10) +- Code(Counter(4)) at (prev + 3, 14) to (start + 0, 15) +- Code(Counter(7)) at (prev + 0, 20) to (start + 0, 25) +- Code(Counter(4)) at (prev + 0, 29) to (start + 2, 10) +- Code(Expression(0, Add)) at (prev + 3, 14) to (start + 2, 10) + = (c1 + c2) +- Code(Expression(1, Add)) at (prev + 4, 1) to (start + 0, 2) + = ((((c1 + c2) + c3) + c4) + c5) + diff --git a/tests/coverage/branch_guard.coverage b/tests/coverage/branch_guard.coverage new file mode 100644 index 0000000000000..6156ae88c7461 --- /dev/null +++ b/tests/coverage/branch_guard.coverage @@ -0,0 +1,39 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| | + LL| |//@ llvm-cov-flags: --show-branches=count + LL| | + LL| |macro_rules! no_merge { + LL| | () => { + LL| | for _ in 0..1 {} + LL| | }; + LL| |} + LL| | + LL| 4|fn branch_match_guard(x: Option) { + LL| 4| no_merge!(); + LL| | + LL| 1| match x { + LL| 1| Some(0) => { + LL| 1| println!("zero"); + LL| 1| } + LL| 3| Some(x) if x % 2 == 0 => { + ^2 + LL| 2| println!("is nonzero and even"); + LL| 2| } + LL| 1| Some(x) if x % 3 == 0 => { + LL| 1| println!("is nonzero and odd, but divisible by 3"); + LL| 1| } + LL| 0| _ => { + LL| 0| println!("something else"); + LL| 0| } + LL| | } + LL| 4|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | branch_match_guard(Some(0)); + LL| | branch_match_guard(Some(2)); + LL| | branch_match_guard(Some(6)); + LL| | branch_match_guard(Some(3)); + LL| |} + diff --git a/tests/coverage/branch_guard.rs b/tests/coverage/branch_guard.rs new file mode 100644 index 0000000000000..a7cb389227e81 --- /dev/null +++ b/tests/coverage/branch_guard.rs @@ -0,0 +1,37 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 + +//@ llvm-cov-flags: --show-branches=count + +macro_rules! no_merge { + () => { + for _ in 0..1 {} + }; +} + +fn branch_match_guard(x: Option) { + no_merge!(); + + match x { + Some(0) => { + println!("zero"); + } + Some(x) if x % 2 == 0 => { + println!("is nonzero and even"); + } + Some(x) if x % 3 == 0 => { + println!("is nonzero and odd, but divisible by 3"); + } + _ => { + println!("something else"); + } + } +} + +#[coverage(off)] +fn main() { + branch_match_guard(Some(0)); + branch_match_guard(Some(2)); + branch_match_guard(Some(6)); + branch_match_guard(Some(3)); +} diff --git a/tests/coverage/branch_if.cov-map b/tests/coverage/branch_if.cov-map new file mode 100644 index 0000000000000..6fb5ef767148f --- /dev/null +++ b/tests/coverage/branch_if.cov-map @@ -0,0 +1,136 @@ +Function name: branch_if::branch_and +Raw bytes (40): 0x[01, 01, 03, 06, 0d, 05, 09, 11, 03, 06, 01, 2b, 01, 01, 10, 05, 03, 08, 00, 09, 09, 00, 0d, 00, 0e, 11, 00, 0f, 02, 06, 03, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 3 +- expression 0 operands: lhs = Expression(1, Sub), rhs = Counter(3) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Counter(4), rhs = Expression(0, Add) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 43, 1) to (start + 1, 16) +- Code(Counter(1)) at (prev + 3, 8) to (start + 0, 9) +- Code(Counter(2)) at (prev + 0, 13) to (start + 0, 14) +- Code(Counter(4)) at (prev + 0, 15) to (start + 2, 6) +- Code(Expression(0, Add)) at (prev + 2, 12) to (start + 2, 6) + = ((c1 - c2) + c3) +- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) + = (c4 + ((c1 - c2) + c3)) + +Function name: branch_if::branch_not +Raw bytes (132): 0x[01, 01, 1d, 05, 09, 09, 02, 73, 0d, 09, 02, 0d, 6e, 73, 0d, 09, 02, 6b, 11, 0d, 6e, 73, 0d, 09, 02, 11, 66, 6b, 11, 0d, 6e, 73, 0d, 09, 02, 63, 15, 11, 66, 6b, 11, 0d, 6e, 73, 0d, 09, 02, 15, 5e, 63, 15, 11, 66, 6b, 11, 0d, 6e, 73, 0d, 09, 02, 0e, 01, 0c, 01, 01, 10, 05, 03, 08, 00, 09, 09, 01, 09, 00, 11, 02, 01, 06, 00, 07, 73, 01, 08, 00, 0a, 6e, 00, 0b, 02, 06, 0d, 02, 06, 00, 07, 6b, 01, 08, 00, 0b, 11, 00, 0c, 02, 06, 66, 02, 06, 00, 07, 63, 01, 08, 00, 0c, 5e, 00, 0d, 02, 06, 15, 02, 06, 00, 07, 5b, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 29 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Expression(28, Add), rhs = Counter(3) +- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 4 operands: lhs = Counter(3), rhs = Expression(27, Sub) +- expression 5 operands: lhs = Expression(28, Add), rhs = Counter(3) +- expression 6 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 7 operands: lhs = Expression(26, Add), rhs = Counter(4) +- expression 8 operands: lhs = Counter(3), rhs = Expression(27, Sub) +- expression 9 operands: lhs = Expression(28, Add), rhs = Counter(3) +- expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 11 operands: lhs = Counter(4), rhs = Expression(25, Sub) +- expression 12 operands: lhs = Expression(26, Add), rhs = Counter(4) +- expression 13 operands: lhs = Counter(3), rhs = Expression(27, Sub) +- expression 14 operands: lhs = Expression(28, Add), rhs = Counter(3) +- expression 15 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 16 operands: lhs = Expression(24, Add), rhs = Counter(5) +- expression 17 operands: lhs = Counter(4), rhs = Expression(25, Sub) +- expression 18 operands: lhs = Expression(26, Add), rhs = Counter(4) +- expression 19 operands: lhs = Counter(3), rhs = Expression(27, Sub) +- expression 20 operands: lhs = Expression(28, Add), rhs = Counter(3) +- expression 21 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 22 operands: lhs = Counter(5), rhs = Expression(23, Sub) +- expression 23 operands: lhs = Expression(24, Add), rhs = Counter(5) +- expression 24 operands: lhs = Counter(4), rhs = Expression(25, Sub) +- expression 25 operands: lhs = Expression(26, Add), rhs = Counter(4) +- expression 26 operands: lhs = Counter(3), rhs = Expression(27, Sub) +- expression 27 operands: lhs = Expression(28, Add), rhs = Counter(3) +- expression 28 operands: lhs = Counter(2), rhs = Expression(0, Sub) +Number of file 0 mappings: 14 +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(1)) at (prev + 3, 8) to (start + 0, 9) +- Code(Counter(2)) at (prev + 1, 9) to (start + 0, 17) +- Code(Expression(0, Sub)) at (prev + 1, 6) to (start + 0, 7) + = (c1 - c2) +- Code(Expression(28, Add)) at (prev + 1, 8) to (start + 0, 10) + = (c2 + (c1 - c2)) +- Code(Expression(27, Sub)) at (prev + 0, 11) to (start + 2, 6) + = ((c2 + (c1 - c2)) - c3) +- Code(Counter(3)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(26, Add)) at (prev + 1, 8) to (start + 0, 11) + = (c3 + ((c2 + (c1 - c2)) - c3)) +- Code(Counter(4)) at (prev + 0, 12) to (start + 2, 6) +- Code(Expression(25, Sub)) at (prev + 2, 6) to (start + 0, 7) + = ((c3 + ((c2 + (c1 - c2)) - c3)) - c4) +- Code(Expression(24, Add)) at (prev + 1, 8) to (start + 0, 12) + = (c4 + ((c3 + ((c2 + (c1 - c2)) - c3)) - c4)) +- Code(Expression(23, Sub)) at (prev + 0, 13) to (start + 2, 6) + = ((c4 + ((c3 + ((c2 + (c1 - c2)) - c3)) - c4)) - c5) +- Code(Counter(5)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(22, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c5 + ((c4 + ((c3 + ((c2 + (c1 - c2)) - c3)) - c4)) - c5)) + +Function name: branch_if::branch_not_as +Raw bytes (91): 0x[01, 01, 10, 05, 09, 09, 02, 3f, 0d, 09, 02, 0d, 3a, 3f, 0d, 09, 02, 37, 11, 0d, 3a, 3f, 0d, 09, 02, 11, 32, 37, 11, 0d, 3a, 3f, 0d, 09, 02, 0b, 01, 1d, 01, 01, 10, 05, 03, 08, 00, 14, 02, 00, 15, 02, 06, 09, 02, 06, 00, 07, 3f, 01, 08, 00, 15, 0d, 00, 16, 02, 06, 3a, 02, 06, 00, 07, 37, 01, 08, 00, 16, 32, 00, 17, 02, 06, 11, 02, 06, 00, 07, 2f, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 16 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Expression(15, Add), rhs = Counter(3) +- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 4 operands: lhs = Counter(3), rhs = Expression(14, Sub) +- expression 5 operands: lhs = Expression(15, Add), rhs = Counter(3) +- expression 6 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 7 operands: lhs = Expression(13, Add), rhs = Counter(4) +- expression 8 operands: lhs = Counter(3), rhs = Expression(14, Sub) +- expression 9 operands: lhs = Expression(15, Add), rhs = Counter(3) +- expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 11 operands: lhs = Counter(4), rhs = Expression(12, Sub) +- expression 12 operands: lhs = Expression(13, Add), rhs = Counter(4) +- expression 13 operands: lhs = Counter(3), rhs = Expression(14, Sub) +- expression 14 operands: lhs = Expression(15, Add), rhs = Counter(3) +- expression 15 operands: lhs = Counter(2), rhs = Expression(0, Sub) +Number of file 0 mappings: 11 +- Code(Counter(0)) at (prev + 29, 1) to (start + 1, 16) +- Code(Counter(1)) at (prev + 3, 8) to (start + 0, 20) +- Code(Expression(0, Sub)) at (prev + 0, 21) to (start + 2, 6) + = (c1 - c2) +- Code(Counter(2)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(15, Add)) at (prev + 1, 8) to (start + 0, 21) + = (c2 + (c1 - c2)) +- Code(Counter(3)) at (prev + 0, 22) to (start + 2, 6) +- Code(Expression(14, Sub)) at (prev + 2, 6) to (start + 0, 7) + = ((c2 + (c1 - c2)) - c3) +- Code(Expression(13, Add)) at (prev + 1, 8) to (start + 0, 22) + = (c3 + ((c2 + (c1 - c2)) - c3)) +- Code(Expression(12, Sub)) at (prev + 0, 23) to (start + 2, 6) + = ((c3 + ((c2 + (c1 - c2)) - c3)) - c4) +- Code(Counter(4)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(11, Add)) at (prev + 1, 1) to (start + 0, 2) + = (c4 + ((c3 + ((c2 + (c1 - c2)) - c3)) - c4)) + +Function name: branch_if::branch_or +Raw bytes (42): 0x[01, 01, 04, 05, 09, 09, 0d, 0f, 11, 09, 0d, 06, 01, 35, 01, 01, 10, 05, 03, 08, 00, 09, 02, 00, 0d, 00, 0e, 0f, 00, 0f, 02, 06, 11, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(4) +- expression 3 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 53, 1) to (start + 1, 16) +- Code(Counter(1)) at (prev + 3, 8) to (start + 0, 9) +- Code(Expression(0, Sub)) at (prev + 0, 13) to (start + 0, 14) + = (c1 - c2) +- Code(Expression(3, Add)) at (prev + 0, 15) to (start + 2, 6) + = (c2 + c3) +- Code(Counter(4)) at (prev + 2, 12) to (start + 2, 6) +- Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) + = ((c2 + c3) + c4) + diff --git a/tests/coverage/branch_if.coverage b/tests/coverage/branch_if.coverage new file mode 100644 index 0000000000000..babefb51d3f21 --- /dev/null +++ b/tests/coverage/branch_if.coverage @@ -0,0 +1,86 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| | + LL| |//@ llvm-cov-flags: --show-branches=count + LL| | + LL| |macro_rules! no_merge { + LL| | () => { + LL| | for _ in 0..1 {} + LL| | }; + LL| |} + LL| | + LL| 3|fn branch_not(a: bool) { + LL| 3| no_merge!(); + LL| | + LL| 3| if a { + LL| 2| say("a") + LL| 1| } + LL| 3| if !a { + LL| 1| say("not a"); + LL| 2| } + LL| 3| if !!a { + LL| 2| say("not not a"); + LL| 2| } + ^1 + LL| 3| if !!!a { + LL| 1| say("not not not a"); + LL| 2| } + LL| 3|} + LL| | + LL| 3|fn branch_not_as(a: bool) { + LL| 3| no_merge!(); + LL| | + LL| 3| if !(a as bool) { + LL| 1| say("not (a as bool)"); + LL| 2| } + LL| 3| if !!(a as bool) { + LL| 2| say("not not (a as bool)"); + LL| 2| } + ^1 + LL| 3| if !!!(a as bool) { + LL| 1| say("not not (a as bool)"); + LL| 2| } + LL| 3|} + LL| | + LL| 15|fn branch_and(a: bool, b: bool) { + LL| 15| no_merge!(); + LL| | + LL| 15| if a && b { + ^12 + LL| 8| say("both"); + LL| 8| } else { + LL| 7| say("not both"); + LL| 7| } + LL| 15|} + LL| | + LL| 15|fn branch_or(a: bool, b: bool) { + LL| 15| no_merge!(); + LL| | + LL| 15| if a || b { + ^3 + LL| 14| say("either"); + LL| 14| } else { + LL| 1| say("neither"); + LL| 1| } + LL| 15|} + LL| | + LL| |#[coverage(off)] + LL| |fn say(message: &str) { + LL| | core::hint::black_box(message); + LL| |} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | for a in [false, true, true] { + LL| | branch_not(a); + LL| | branch_not_as(a); + LL| | } + LL| | + LL| | for a in [false, true, true, true, true] { + LL| | for b in [false, true, true] { + LL| | branch_and(a, b); + LL| | branch_or(a, b); + LL| | } + LL| | } + LL| |} + diff --git a/tests/coverage/branch_if.rs b/tests/coverage/branch_if.rs new file mode 100644 index 0000000000000..55ef159ebdfc5 --- /dev/null +++ b/tests/coverage/branch_if.rs @@ -0,0 +1,81 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 + +//@ llvm-cov-flags: --show-branches=count + +macro_rules! no_merge { + () => { + for _ in 0..1 {} + }; +} + +fn branch_not(a: bool) { + no_merge!(); + + if a { + say("a") + } + if !a { + say("not a"); + } + if !!a { + say("not not a"); + } + if !!!a { + say("not not not a"); + } +} + +fn branch_not_as(a: bool) { + no_merge!(); + + if !(a as bool) { + say("not (a as bool)"); + } + if !!(a as bool) { + say("not not (a as bool)"); + } + if !!!(a as bool) { + say("not not (a as bool)"); + } +} + +fn branch_and(a: bool, b: bool) { + no_merge!(); + + if a && b { + say("both"); + } else { + say("not both"); + } +} + +fn branch_or(a: bool, b: bool) { + no_merge!(); + + if a || b { + say("either"); + } else { + say("neither"); + } +} + +#[coverage(off)] +fn say(message: &str) { + core::hint::black_box(message); +} + +#[coverage(off)] +fn main() { + for a in [false, true, true] { + branch_not(a); + branch_not_as(a); + } + + for a in [false, true, true, true, true] { + for b in [false, true, true] { + branch_and(a, b); + branch_or(a, b); + } + } +} diff --git a/tests/coverage/branch_while.cov-map b/tests/coverage/branch_while.cov-map new file mode 100644 index 0000000000000..63a7c438163ea --- /dev/null +++ b/tests/coverage/branch_while.cov-map @@ -0,0 +1,74 @@ +Function name: branch_while::while_cond +Raw bytes (33): 0x[01, 01, 02, 05, 09, 03, 09, 05, 01, 0c, 01, 01, 10, 05, 03, 09, 00, 12, 03, 01, 0b, 00, 10, 09, 00, 11, 02, 06, 06, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Expression(0, Add), rhs = Counter(2) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) +- Code(Counter(1)) at (prev + 3, 9) to (start + 0, 18) +- Code(Expression(0, Add)) at (prev + 1, 11) to (start + 0, 16) + = (c1 + c2) +- Code(Counter(2)) at (prev + 0, 17) to (start + 2, 6) +- Code(Expression(1, Sub)) at (prev + 3, 1) to (start + 0, 2) + = ((c1 + c2) - c2) + +Function name: branch_while::while_cond_not +Raw bytes (33): 0x[01, 01, 02, 05, 09, 03, 09, 05, 01, 15, 01, 01, 10, 05, 03, 09, 00, 12, 03, 01, 0b, 00, 14, 09, 00, 15, 02, 06, 06, 03, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 2 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Expression(0, Add), rhs = Counter(2) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 21, 1) to (start + 1, 16) +- Code(Counter(1)) at (prev + 3, 9) to (start + 0, 18) +- Code(Expression(0, Add)) at (prev + 1, 11) to (start + 0, 20) + = (c1 + c2) +- Code(Counter(2)) at (prev + 0, 21) to (start + 2, 6) +- Code(Expression(1, Sub)) at (prev + 3, 1) to (start + 0, 2) + = ((c1 + c2) - c2) + +Function name: branch_while::while_op_and +Raw bytes (40): 0x[01, 01, 03, 05, 09, 03, 0d, 11, 0d, 06, 01, 1e, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 06, 00, 14, 00, 19, 09, 00, 1a, 03, 06, 0b, 04, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 3 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 2 operands: lhs = Counter(4), rhs = Counter(3) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16) +- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 18) +- Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 16) + = (c1 + c2) +- Code(Expression(1, Sub)) at (prev + 0, 20) to (start + 0, 25) + = ((c1 + c2) - c3) +- Code(Counter(2)) at (prev + 0, 26) to (start + 3, 6) +- Code(Expression(2, Add)) at (prev + 4, 1) to (start + 0, 2) + = (c4 + c3) + +Function name: branch_while::while_op_or +Raw bytes (46): 0x[01, 01, 06, 05, 0f, 09, 0d, 03, 09, 09, 0d, 16, 0d, 03, 09, 06, 01, 29, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 16, 00, 14, 00, 19, 0f, 00, 1a, 03, 06, 12, 04, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 6 +- expression 0 operands: lhs = Counter(1), rhs = Expression(3, Add) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(2) +- expression 3 operands: lhs = Counter(2), rhs = Counter(3) +- expression 4 operands: lhs = Expression(5, Sub), rhs = Counter(3) +- expression 5 operands: lhs = Expression(0, Add), rhs = Counter(2) +Number of file 0 mappings: 6 +- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 16) +- Code(Counter(1)) at (prev + 3, 9) to (start + 1, 18) +- Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 16) + = (c1 + (c2 + c3)) +- Code(Expression(5, Sub)) at (prev + 0, 20) to (start + 0, 25) + = ((c1 + (c2 + c3)) - c2) +- Code(Expression(3, Add)) at (prev + 0, 26) to (start + 3, 6) + = (c2 + c3) +- Code(Expression(4, Sub)) at (prev + 4, 1) to (start + 0, 2) + = (((c1 + (c2 + c3)) - c2) - c3) + diff --git a/tests/coverage/branch_while.coverage b/tests/coverage/branch_while.coverage new file mode 100644 index 0000000000000..d2351a7de09a2 --- /dev/null +++ b/tests/coverage/branch_while.coverage @@ -0,0 +1,60 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| | + LL| |//@ llvm-cov-flags: --show-branches=count + LL| | + LL| |macro_rules! no_merge { + LL| | () => { + LL| | for _ in 0..1 {} + LL| | }; + LL| |} + LL| | + LL| 1|fn while_cond() { + LL| 1| no_merge!(); + LL| | + LL| 1| let mut a = 8; + LL| 9| while a > 0 { + LL| 8| a -= 1; + LL| 8| } + LL| 1|} + LL| | + LL| 1|fn while_cond_not() { + LL| 1| no_merge!(); + LL| | + LL| 1| let mut a = 8; + LL| 9| while !(a == 0) { + LL| 8| a -= 1; + LL| 8| } + LL| 1|} + LL| | + LL| 1|fn while_op_and() { + LL| 1| no_merge!(); + LL| | + LL| 1| let mut a = 8; + LL| 1| let mut b = 4; + LL| 5| while a > 0 && b > 0 { + LL| 4| a -= 1; + LL| 4| b -= 1; + LL| 4| } + LL| 1|} + LL| | + LL| 1|fn while_op_or() { + LL| 1| no_merge!(); + LL| | + LL| 1| let mut a = 4; + LL| 1| let mut b = 8; + LL| 9| while a > 0 || b > 0 { + ^5 + LL| 8| a -= 1; + LL| 8| b -= 1; + LL| 8| } + LL| 1|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | while_cond(); + LL| | while_cond_not(); + LL| | while_op_and(); + LL| | while_op_or(); + LL| |} + diff --git a/tests/coverage/branch_while.rs b/tests/coverage/branch_while.rs new file mode 100644 index 0000000000000..99e9a798eff5f --- /dev/null +++ b/tests/coverage/branch_while.rs @@ -0,0 +1,58 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 + +//@ llvm-cov-flags: --show-branches=count + +macro_rules! no_merge { + () => { + for _ in 0..1 {} + }; +} + +fn while_cond() { + no_merge!(); + + let mut a = 8; + while a > 0 { + a -= 1; + } +} + +fn while_cond_not() { + no_merge!(); + + let mut a = 8; + while !(a == 0) { + a -= 1; + } +} + +fn while_op_and() { + no_merge!(); + + let mut a = 8; + let mut b = 4; + while a > 0 && b > 0 { + a -= 1; + b -= 1; + } +} + +fn while_op_or() { + no_merge!(); + + let mut a = 4; + let mut b = 8; + while a > 0 || b > 0 { + a -= 1; + b -= 1; + } +} + +#[coverage(off)] +fn main() { + while_cond(); + while_cond_not(); + while_op_and(); + while_op_or(); +} From 975109892cf8887223b37d066e23bb766b04f79e Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 8 Feb 2024 11:46:26 +1100 Subject: [PATCH 08/23] Allow `rustc_mir_transform` to register hook providers --- compiler/rustc_mir_transform/src/coverage/query.rs | 6 +++--- compiler/rustc_mir_transform/src/lib.rs | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index dfc7c3a713bc2..1354273e2c488 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -3,12 +3,12 @@ use super::*; use rustc_data_structures::captures::Captures; use rustc_middle::mir::coverage::*; use rustc_middle::mir::{Body, CoverageIdsInfo}; -use rustc_middle::query::Providers; use rustc_middle::ty::{self}; +use rustc_middle::util::Providers; -/// A `query` provider for retrieving coverage information injected into MIR. +/// Registers query/hook implementations related to coverage. pub(crate) fn provide(providers: &mut Providers) { - providers.coverage_ids_info = |tcx, def_id| coverage_ids_info(tcx, def_id); + providers.queries.coverage_ids_info = coverage_ids_info; } /// Query implementation for `coverage_ids_info`. diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 0491de7826590..4551380152217 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -37,8 +37,9 @@ use rustc_middle::mir::{ LocalDecl, MirPass, MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, SourceInfo, Statement, StatementKind, TerminatorKind, START_BLOCK, }; -use rustc_middle::query::Providers; +use rustc_middle::query; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; +use rustc_middle::util::Providers; use rustc_span::{source_map::Spanned, sym, DUMMY_SP}; use rustc_trait_selection::traits; @@ -124,7 +125,7 @@ pub fn provide(providers: &mut Providers) { ffi_unwind_calls::provide(providers); shim::provide(providers); cross_crate_inline::provide(providers); - *providers = Providers { + providers.queries = query::Providers { mir_keys, mir_const, mir_const_qualif, @@ -139,7 +140,7 @@ pub fn provide(providers: &mut Providers) { mir_inliner_callees: inline::cycle::mir_inliner_callees, promoted_mir, deduced_param_attrs: deduce_param_attrs::deduced_param_attrs, - ..*providers + ..providers.queries }; } From 73475d0d597dfb42a0d2071b4369f5c3dc7281b1 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 8 Feb 2024 12:21:22 +1100 Subject: [PATCH 09/23] coverage: Make `is_eligible_for_coverage` a hook method This will allow MIR building to check whether a function is eligible for coverage instrumentation, and avoid collecting branch coverage info if it is not. --- compiler/rustc_middle/src/hooks/mod.rs | 7 +++ .../rustc_mir_transform/src/coverage/mod.rs | 34 +------------- .../rustc_mir_transform/src/coverage/query.rs | 45 ++++++++++++++++--- 3 files changed, 48 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_middle/src/hooks/mod.rs b/compiler/rustc_middle/src/hooks/mod.rs index 8588ae2033613..b984df3646e61 100644 --- a/compiler/rustc_middle/src/hooks/mod.rs +++ b/compiler/rustc_middle/src/hooks/mod.rs @@ -6,6 +6,7 @@ use crate::mir; use crate::query::TyCtxtAt; use crate::ty::{Ty, TyCtxt}; +use rustc_span::def_id::LocalDefId; use rustc_span::DUMMY_SP; macro_rules! declare_hooks { @@ -70,4 +71,10 @@ declare_hooks! { /// Getting a &core::panic::Location referring to a span. hook const_caller_location(file: rustc_span::Symbol, line: u32, col: u32) -> mir::ConstValue<'tcx>; + + /// Returns `true` if this def is a function-like thing that is eligible for + /// coverage instrumentation under `-Cinstrument-coverage`. + /// + /// (Eligible functions might nevertheless be skipped for other reasons.) + hook is_eligible_for_coverage(key: LocalDefId) -> bool; } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 4c5be0a3f4bed..bde135834860b 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -14,7 +14,6 @@ use self::spans::{BcbMapping, BcbMappingKind, CoverageSpans}; use crate::MirPass; use rustc_middle::hir; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::*; use rustc_middle::mir::{ self, BasicBlock, BasicBlockData, Coverage, SourceInfo, Statement, StatementKind, Terminator, @@ -44,7 +43,7 @@ impl<'tcx> MirPass<'tcx> for InstrumentCoverage { let def_id = mir_source.def_id().expect_local(); - if !is_eligible_for_coverage(tcx, def_id) { + if !tcx.is_eligible_for_coverage(def_id) { trace!("InstrumentCoverage skipped for {def_id:?} (not eligible)"); return; } @@ -349,37 +348,6 @@ fn check_code_region(code_region: CodeRegion) -> Option { } } -fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { - // Only instrument functions, methods, and closures (not constants since they are evaluated - // at compile time by Miri). - // FIXME(#73156): Handle source code coverage in const eval, but note, if and when const - // expressions get coverage spans, we will probably have to "carve out" space for const - // expressions from coverage spans in enclosing MIR's, like we do for closures. (That might - // be tricky if const expressions have no corresponding statements in the enclosing MIR. - // Closures are carved out by their initial `Assign` statement.) - if !tcx.def_kind(def_id).is_fn_like() { - trace!("InstrumentCoverage skipped for {def_id:?} (not an fn-like)"); - return false; - } - - // Don't instrument functions with `#[automatically_derived]` on their - // enclosing impl block, on the assumption that most users won't care about - // coverage for derived impls. - if let Some(impl_of) = tcx.impl_of_method(def_id.to_def_id()) - && tcx.is_automatically_derived(impl_of) - { - trace!("InstrumentCoverage skipped for {def_id:?} (automatically derived)"); - return false; - } - - if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_COVERAGE) { - trace!("InstrumentCoverage skipped for {def_id:?} (`#[coverage(off)]`)"); - return false; - } - - true -} - /// Function information extracted from HIR by the coverage instrumentor. #[derive(Debug)] struct ExtractedHirInfo { diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index 1354273e2c488..1de7b6f66a7bc 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,16 +1,51 @@ -use super::*; - use rustc_data_structures::captures::Captures; -use rustc_middle::mir::coverage::*; -use rustc_middle::mir::{Body, CoverageIdsInfo}; -use rustc_middle::ty::{self}; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use rustc_middle::mir::coverage::{CounterId, CoverageKind}; +use rustc_middle::mir::{Body, Coverage, CoverageIdsInfo, Statement, StatementKind}; +use rustc_middle::query::TyCtxtAt; +use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::util::Providers; +use rustc_span::def_id::LocalDefId; /// Registers query/hook implementations related to coverage. pub(crate) fn provide(providers: &mut Providers) { + providers.hooks.is_eligible_for_coverage = + |TyCtxtAt { tcx, .. }, def_id| is_eligible_for_coverage(tcx, def_id); providers.queries.coverage_ids_info = coverage_ids_info; } +/// Hook implementation for [`TyCtxt::is_eligible_for_coverage`]. +fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { + // Only instrument functions, methods, and closures (not constants since they are evaluated + // at compile time by Miri). + // FIXME(#73156): Handle source code coverage in const eval, but note, if and when const + // expressions get coverage spans, we will probably have to "carve out" space for const + // expressions from coverage spans in enclosing MIR's, like we do for closures. (That might + // be tricky if const expressions have no corresponding statements in the enclosing MIR. + // Closures are carved out by their initial `Assign` statement.) + if !tcx.def_kind(def_id).is_fn_like() { + trace!("InstrumentCoverage skipped for {def_id:?} (not an fn-like)"); + return false; + } + + // Don't instrument functions with `#[automatically_derived]` on their + // enclosing impl block, on the assumption that most users won't care about + // coverage for derived impls. + if let Some(impl_of) = tcx.impl_of_method(def_id.to_def_id()) + && tcx.is_automatically_derived(impl_of) + { + trace!("InstrumentCoverage skipped for {def_id:?} (automatically derived)"); + return false; + } + + if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NO_COVERAGE) { + trace!("InstrumentCoverage skipped for {def_id:?} (`#[coverage(off)]`)"); + return false; + } + + true +} + /// Query implementation for `coverage_ids_info`. fn coverage_ids_info<'tcx>( tcx: TyCtxt<'tcx>, From c921ab17134a7e526ec9df3942890f5b501addcb Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 8 Feb 2024 12:39:15 +1100 Subject: [PATCH 10/23] coverage: Add `CoverageKind::BlockMarker` --- .../rustc_codegen_llvm/src/coverageinfo/mod.rs | 4 ++-- compiler/rustc_middle/src/mir/coverage.rs | 16 ++++++++++++++++ compiler/rustc_middle/src/ty/structural_impls.rs | 1 + .../src/coverage/spans/from_mir.rs | 5 +++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs index 733a77d24c2a4..133084b7c12ae 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mod.rs @@ -88,7 +88,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { match coverage.kind { // Marker statements have no effect during codegen, // so return early and don't create `func_coverage`. - CoverageKind::SpanMarker => return, + CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => return, // Match exhaustively to ensure that newly-added kinds are classified correctly. CoverageKind::CounterIncrement { .. } | CoverageKind::ExpressionUsed { .. } => {} } @@ -108,7 +108,7 @@ impl<'tcx> CoverageInfoBuilderMethods<'tcx> for Builder<'_, '_, 'tcx> { let Coverage { kind } = coverage; match *kind { - CoverageKind::SpanMarker => unreachable!( + CoverageKind::SpanMarker | CoverageKind::BlockMarker { .. } => unreachable!( "unexpected marker statement {kind:?} should have caused an early return" ), CoverageKind::CounterIncrement { id } => { diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 18e198eb9fcab..ed3a73af1ce27 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -6,6 +6,15 @@ use rustc_span::Symbol; use std::fmt::{self, Debug, Formatter}; +rustc_index::newtype_index! { + /// Used by [`CoverageKind::BlockMarker`] to mark blocks during THIR-to-MIR + /// lowering, so that those blocks can be identified later. + #[derive(HashStable)] + #[encodable] + #[debug_format = "BlockMarkerId({})"] + pub struct BlockMarkerId {} +} + rustc_index::newtype_index! { /// ID of a coverage counter. Values ascend from 0. /// @@ -83,6 +92,12 @@ pub enum CoverageKind { /// codegen. SpanMarker, + /// Marks its enclosing basic block with an ID that can be referred to by + /// other data in the MIR body. + /// + /// Has no effect during codegen. + BlockMarker { id: BlockMarkerId }, + /// Marks the point in MIR control flow represented by a coverage counter. /// /// This is eventually lowered to `llvm.instrprof.increment` in LLVM IR. @@ -107,6 +122,7 @@ impl Debug for CoverageKind { use CoverageKind::*; match self { SpanMarker => write!(fmt, "SpanMarker"), + BlockMarker { id } => write!(fmt, "BlockMarker({:?})", id.index()), CounterIncrement { id } => write!(fmt, "CounterIncrement({:?})", id.index()), ExpressionUsed { id } => write!(fmt, "ExpressionUsed({:?})", id.index()), } diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index c8fb11673cf89..4b015640f916e 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -405,6 +405,7 @@ TrivialTypeTraversalImpls! { ::rustc_hir::HirId, ::rustc_hir::MatchSource, ::rustc_target::asm::InlineAsmRegOrRegClass, + crate::mir::coverage::BlockMarkerId, crate::mir::coverage::CounterId, crate::mir::coverage::ExpressionId, crate::mir::Local, diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 099a354f45dd1..223613cfc6fdf 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -225,6 +225,11 @@ fn filtered_statement_span(statement: &Statement<'_>) -> Option { Some(statement.source_info.span) } + StatementKind::Coverage(box mir::Coverage { + // Block markers are used for branch coverage, so ignore them here. + kind: CoverageKind::BlockMarker {..} + }) => None, + StatementKind::Coverage(box mir::Coverage { // These coverage statements should not exist prior to coverage instrumentation. kind: CoverageKind::CounterIncrement { .. } | CoverageKind::ExpressionUsed { .. } From 12cd3220624fe50d039b268cc5ff35c7895ef293 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?John=20K=C3=A5re=20Alsaker?= Date: Wed, 28 Feb 2024 22:42:31 +0100 Subject: [PATCH 11/23] Make incremental sessions identity no longer depend on the crate names provided by source code --- compiler/rustc_driver_impl/src/lib.rs | 3 +- compiler/rustc_incremental/src/persist/fs.rs | 22 +++--- .../rustc_incremental/src/persist/load.rs | 12 ++-- compiler/rustc_interface/messages.ftl | 3 - compiler/rustc_interface/src/errors.rs | 9 --- compiler/rustc_interface/src/queries.rs | 6 +- compiler/rustc_interface/src/util.rs | 68 ++----------------- compiler/rustc_session/messages.ftl | 3 + compiler/rustc_session/src/errors.rs | 9 ++- compiler/rustc_session/src/output.rs | 65 +++++++++++++++++- 10 files changed, 101 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index c448835413571..938f9f0beaacd 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -28,7 +28,7 @@ use rustc_errors::{ markdown, ColorConfig, DiagCtxt, ErrCode, ErrorGuaranteed, FatalError, PResult, }; use rustc_feature::find_gated_cfg; -use rustc_interface::util::{self, collect_crate_types, get_codegen_backend}; +use rustc_interface::util::{self, get_codegen_backend}; use rustc_interface::{interface, Queries}; use rustc_lint::unerased_lint_store; use rustc_metadata::creader::MetadataLoader; @@ -37,6 +37,7 @@ use rustc_session::config::{nightly_options, CG_OPTIONS, Z_OPTIONS}; use rustc_session::config::{ErrorOutputType, Input, OutFileName, OutputType}; use rustc_session::getopts::{self, Matches}; use rustc_session::lint::{Lint, LintId}; +use rustc_session::output::collect_crate_types; use rustc_session::{config, filesearch, EarlyDiagCtxt, Session}; use rustc_span::def_id::LOCAL_CRATE; use rustc_span::source_map::FileLoader; diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index dd9c16d006a96..1462037c8c8e7 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -110,8 +110,9 @@ use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_data_structures::{base_n, flock}; use rustc_errors::ErrorGuaranteed; use rustc_fs_util::{link_or_copy, try_canonicalize, LinkOrCopy}; +use rustc_session::config::CrateType; +use rustc_session::output::{collect_crate_types, find_crate_name}; use rustc_session::{Session, StableCrateId}; -use rustc_span::Symbol; use std::fs as std_fs; use std::io::{self, ErrorKind}; @@ -205,11 +206,7 @@ pub fn in_incr_comp_dir(incr_comp_session_dir: &Path, file_name: &str) -> PathBu /// The garbage collection will take care of it. /// /// [`rustc_interface::queries::dep_graph`]: ../../rustc_interface/struct.Queries.html#structfield.dep_graph -pub(crate) fn prepare_session_directory( - sess: &Session, - crate_name: Symbol, - stable_crate_id: StableCrateId, -) -> Result<(), ErrorGuaranteed> { +pub(crate) fn prepare_session_directory(sess: &Session) -> Result<(), ErrorGuaranteed> { if sess.opts.incremental.is_none() { return Ok(()); } @@ -219,7 +216,7 @@ pub(crate) fn prepare_session_directory( debug!("prepare_session_directory"); // {incr-comp-dir}/{crate-name-and-disambiguator} - let crate_dir = crate_path(sess, crate_name, stable_crate_id); + let crate_dir = crate_path(sess); debug!("crate-dir: {}", crate_dir.display()); create_dir(sess, &crate_dir, "crate")?; @@ -604,9 +601,18 @@ fn string_to_timestamp(s: &str) -> Result { Ok(UNIX_EPOCH + duration) } -fn crate_path(sess: &Session, crate_name: Symbol, stable_crate_id: StableCrateId) -> PathBuf { +fn crate_path(sess: &Session) -> PathBuf { let incr_dir = sess.opts.incremental.as_ref().unwrap().clone(); + let crate_name = find_crate_name(sess, &[]); + let crate_types = collect_crate_types(sess, &[]); + let stable_crate_id = StableCrateId::new( + crate_name, + crate_types.contains(&CrateType::Executable), + sess.opts.cg.metadata.clone(), + sess.cfg_version, + ); + let stable_crate_id = base_n::encode(stable_crate_id.as_u64() as u128, INT_ENCODE_BASE); let crate_name = format!("{crate_name}-{stable_crate_id}"); diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 96bfe766c20f5..357f2ae92d4c3 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -8,8 +8,8 @@ use rustc_middle::query::on_disk_cache::OnDiskCache; use rustc_serialize::opaque::MemDecoder; use rustc_serialize::Decodable; use rustc_session::config::IncrementalStateAssertion; -use rustc_session::{Session, StableCrateId}; -use rustc_span::{ErrorGuaranteed, Symbol}; +use rustc_session::Session; +use rustc_span::ErrorGuaranteed; use std::path::{Path, PathBuf}; use super::data::*; @@ -190,13 +190,9 @@ pub fn load_query_result_cache(sess: &Session) -> Option> { /// Setups the dependency graph by loading an existing graph from disk and set up streaming of a /// new graph to an incremental session directory. -pub fn setup_dep_graph( - sess: &Session, - crate_name: Symbol, - stable_crate_id: StableCrateId, -) -> Result { +pub fn setup_dep_graph(sess: &Session) -> Result { // `load_dep_graph` can only be called after `prepare_session_directory`. - prepare_session_directory(sess, crate_name, stable_crate_id)?; + prepare_session_directory(sess)?; let res = sess.opts.build_dep_graph().then(|| load_dep_graph(sess)); diff --git a/compiler/rustc_interface/messages.ftl b/compiler/rustc_interface/messages.ftl index bd9fad8b04296..47dfbc1d7fbf1 100644 --- a/compiler/rustc_interface/messages.ftl +++ b/compiler/rustc_interface/messages.ftl @@ -48,6 +48,3 @@ interface_rustc_error_unexpected_annotation = interface_temps_dir_error = failed to find or create the directory specified by `--temps-dir` - -interface_unsupported_crate_type_for_target = - dropping unsupported crate type `{$crate_type}` for target `{$target_triple}` diff --git a/compiler/rustc_interface/src/errors.rs b/compiler/rustc_interface/src/errors.rs index a9ab2720d89a5..29294003b8f29 100644 --- a/compiler/rustc_interface/src/errors.rs +++ b/compiler/rustc_interface/src/errors.rs @@ -1,7 +1,5 @@ use rustc_macros::Diagnostic; -use rustc_session::config::CrateType; use rustc_span::{Span, Symbol}; -use rustc_target::spec::TargetTriple; use std::io; use std::path::Path; @@ -90,13 +88,6 @@ pub struct FailedWritingFile<'a> { #[diag(interface_proc_macro_crate_panic_abort)] pub struct ProcMacroCratePanicAbort; -#[derive(Diagnostic)] -#[diag(interface_unsupported_crate_type_for_target)] -pub struct UnsupportedCrateTypeForTarget<'a> { - pub crate_type: CrateType, - pub target_triple: &'a TargetTriple, -} - #[derive(Diagnostic)] #[diag(interface_multiple_output_types_adaption)] pub struct MultipleOutputTypesAdaption; diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index c22188226961e..ee677a092e2f1 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::{GlobalCtxt, TyCtxt}; use rustc_serialize::opaque::FileEncodeResult; use rustc_session::config::{self, CrateType, OutputFilenames, OutputType}; use rustc_session::cstore::Untracked; -use rustc_session::output::find_crate_name; +use rustc_session::output::{collect_crate_types, find_crate_name}; use rustc_session::Session; use rustc_span::symbol::sym; use std::any::Any; @@ -128,7 +128,7 @@ impl<'tcx> Queries<'tcx> { // parse `#[crate_name]` even if `--crate-name` was passed, to make sure it matches. let crate_name = find_crate_name(sess, &pre_configured_attrs); - let crate_types = util::collect_crate_types(sess, &pre_configured_attrs); + let crate_types = collect_crate_types(sess, &pre_configured_attrs); let stable_crate_id = StableCrateId::new( crate_name, crate_types.contains(&CrateType::Executable), @@ -136,7 +136,7 @@ impl<'tcx> Queries<'tcx> { sess.cfg_version, ); let outputs = util::build_output_filenames(&pre_configured_attrs, sess); - let dep_graph = setup_dep_graph(sess, crate_name, stable_crate_id)?; + let dep_graph = setup_dep_graph(sess)?; let cstore = FreezeLock::new(Box::new(CStore::new( self.compiler.codegen_backend.metadata_loader(), diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 829b00aabc126..7d48f90db3625 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -7,14 +7,15 @@ use rustc_data_structures::sync; use rustc_metadata::{load_symbol_from_dylib, DylibError}; use rustc_parse::validate_attr; use rustc_session as session; -use rustc_session::config::{self, Cfg, CrateType, OutFileName, OutputFilenames, OutputTypes}; +use rustc_session::config::{Cfg, OutFileName, OutputFilenames, OutputTypes}; use rustc_session::filesearch::sysroot_candidates; use rustc_session::lint::{self, BuiltinLintDiag, LintBuffer}; -use rustc_session::{filesearch, output, Session}; +use rustc_session::{filesearch, Session}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; -use rustc_span::symbol::{sym, Symbol}; +use rustc_span::symbol::sym; use rustc_target::spec::Target; +use session::output::{categorize_crate_type, CRATE_TYPES}; use session::EarlyDiagCtxt; use std::env::consts::{DLL_PREFIX, DLL_SUFFIX}; use std::path::{Path, PathBuf}; @@ -399,67 +400,6 @@ pub(crate) fn check_attr_crate_type( } } -const CRATE_TYPES: &[(Symbol, CrateType)] = &[ - (sym::rlib, CrateType::Rlib), - (sym::dylib, CrateType::Dylib), - (sym::cdylib, CrateType::Cdylib), - (sym::lib, config::default_lib_output()), - (sym::staticlib, CrateType::Staticlib), - (sym::proc_dash_macro, CrateType::ProcMacro), - (sym::bin, CrateType::Executable), -]; - -fn categorize_crate_type(s: Symbol) -> Option { - Some(CRATE_TYPES.iter().find(|(key, _)| *key == s)?.1) -} - -pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { - // If we're generating a test executable, then ignore all other output - // styles at all other locations - if session.opts.test { - return vec![CrateType::Executable]; - } - - // Only check command line flags if present. If no types are specified by - // command line, then reuse the empty `base` Vec to hold the types that - // will be found in crate attributes. - // JUSTIFICATION: before wrapper fn is available - #[allow(rustc::bad_opt_access)] - let mut base = session.opts.crate_types.clone(); - if base.is_empty() { - let attr_types = attrs.iter().filter_map(|a| { - if a.has_name(sym::crate_type) - && let Some(s) = a.value_str() - { - categorize_crate_type(s) - } else { - None - } - }); - base.extend(attr_types); - if base.is_empty() { - base.push(output::default_output_for_target(session)); - } else { - base.sort(); - base.dedup(); - } - } - - base.retain(|crate_type| { - if output::invalid_output_for_target(session, *crate_type) { - session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget { - crate_type: *crate_type, - target_triple: &session.opts.target_triple, - }); - false - } else { - true - } - }); - - base -} - fn multiple_output_types_to_stdout( output_types: &OutputTypes, single_output_file_is_stdout: bool, diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl index af8c962a2ed6a..42c681e496174 100644 --- a/compiler/rustc_session/messages.ftl +++ b/compiler/rustc_session/messages.ftl @@ -111,4 +111,7 @@ session_unleashed_feature_help_unnamed = skipping check that does not even have session_unstable_virtual_function_elimination = `-Zvirtual-function-elimination` requires `-Clto` +session_unsupported_crate_type_for_target = + dropping unsupported crate type `{$crate_type}` for target `{$target_triple}` + session_unsupported_dwarf_version = requested DWARF version {$dwarf_version} is greater than 5 diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 5f04915a9e755..d523da1ad7e38 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -10,7 +10,7 @@ use rustc_macros::Diagnostic; use rustc_span::{Span, Symbol}; use rustc_target::spec::{SplitDebuginfo, StackProtector, TargetTriple}; -use crate::parse::ParseSess; +use crate::{config::CrateType, parse::ParseSess}; pub struct FeatureGateError { pub span: MultiSpan, @@ -345,6 +345,13 @@ pub(crate) struct BinaryFloatLiteralNotSupported { pub span: Span, } +#[derive(Diagnostic)] +#[diag(session_unsupported_crate_type_for_target)] +pub struct UnsupportedCrateTypeForTarget<'a> { + pub crate_type: CrateType, + pub target_triple: &'a TargetTriple, +} + pub fn report_lit_error( psess: &ParseSess, err: LitError, diff --git a/compiler/rustc_session/src/output.rs b/compiler/rustc_session/src/output.rs index 74d26237f2463..35cd3cbab66ce 100644 --- a/compiler/rustc_session/src/output.rs +++ b/compiler/rustc_session/src/output.rs @@ -1,7 +1,7 @@ //! Related to out filenames of compilation (e.g. binaries). -use crate::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType}; +use crate::config::{self, CrateType, Input, OutFileName, OutputFilenames, OutputType}; use crate::errors::{ - CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable, + self, CrateNameDoesNotMatch, CrateNameEmpty, CrateNameInvalid, FileIsNotWriteable, InvalidCharacterInCrateName, InvalidCrateNameHelp, }; use crate::Session; @@ -200,3 +200,64 @@ pub fn invalid_output_for_target(sess: &Session, crate_type: CrateType) -> bool false } + +pub const CRATE_TYPES: &[(Symbol, CrateType)] = &[ + (sym::rlib, CrateType::Rlib), + (sym::dylib, CrateType::Dylib), + (sym::cdylib, CrateType::Cdylib), + (sym::lib, config::default_lib_output()), + (sym::staticlib, CrateType::Staticlib), + (sym::proc_dash_macro, CrateType::ProcMacro), + (sym::bin, CrateType::Executable), +]; + +pub fn categorize_crate_type(s: Symbol) -> Option { + Some(CRATE_TYPES.iter().find(|(key, _)| *key == s)?.1) +} + +pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { + // If we're generating a test executable, then ignore all other output + // styles at all other locations + if session.opts.test { + return vec![CrateType::Executable]; + } + + // Only check command line flags if present. If no types are specified by + // command line, then reuse the empty `base` Vec to hold the types that + // will be found in crate attributes. + // JUSTIFICATION: before wrapper fn is available + #[allow(rustc::bad_opt_access)] + let mut base = session.opts.crate_types.clone(); + if base.is_empty() { + let attr_types = attrs.iter().filter_map(|a| { + if a.has_name(sym::crate_type) + && let Some(s) = a.value_str() + { + categorize_crate_type(s) + } else { + None + } + }); + base.extend(attr_types); + if base.is_empty() { + base.push(default_output_for_target(session)); + } else { + base.sort(); + base.dedup(); + } + } + + base.retain(|crate_type| { + if invalid_output_for_target(session, *crate_type) { + session.dcx().emit_warn(errors::UnsupportedCrateTypeForTarget { + crate_type: *crate_type, + target_triple: &session.opts.target_triple, + }); + false + } else { + true + } + }); + + base +} From f2ec0d3d26dc31c84274b853cc04ce25371c8d3d Mon Sep 17 00:00:00 2001 From: Pavel Grigorenko Date: Thu, 14 Mar 2024 01:37:12 +0300 Subject: [PATCH 12/23] Implement `Duration::as_millis_{f64,f32}` --- library/core/src/time.rs | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index b533f53993870..78494b866b108 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -856,6 +856,48 @@ impl Duration { (self.secs as f32) + (self.nanos.0 as f32) / (NANOS_PER_SEC as f32) } + /// Returns the number of milliseconds contained by this `Duration` as `f64`. + /// + /// The returned value does include the fractional (nanosecond) part of the duration. + /// + /// # Examples + /// ``` + /// #![feature(duration_millis_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 345_678_000); + /// assert_eq!(dur.as_millis_f64(), 2345.678); + /// ``` + #[unstable(feature = "duration_millis_float", issue = "122451")] + #[must_use] + #[inline] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + pub const fn as_millis_f64(&self) -> f64 { + (self.secs as f64) * (MILLIS_PER_SEC as f64) + + (self.nanos.0 as f64) / (NANOS_PER_MILLI as f64) + } + + /// Returns the number of milliseconds contained by this `Duration` as `f32`. + /// + /// The returned value does include the fractional (nanosecond) part of the duration. + /// + /// # Examples + /// ``` + /// #![feature(duration_millis_float)] + /// use std::time::Duration; + /// + /// let dur = Duration::new(2, 345_678_000); + /// assert_eq!(dur.as_millis_f32(), 2345.678); + /// ``` + #[unstable(feature = "duration_millis_float", issue = "122451")] + #[must_use] + #[inline] + #[rustc_const_unstable(feature = "duration_consts_float", issue = "72440")] + pub const fn as_millis_f32(&self) -> f32 { + (self.secs as f32) * (MILLIS_PER_SEC as f32) + + (self.nanos.0 as f32) / (NANOS_PER_MILLI as f32) + } + /// Creates a new `Duration` from the specified number of seconds represented /// as `f64`. /// From 1a81a941ad62f6a619789eb67903121622488209 Mon Sep 17 00:00:00 2001 From: surechen Date: Mon, 11 Mar 2024 22:39:02 +0800 Subject: [PATCH 13/23] fixes #121331 --- compiler/rustc_lint_defs/src/builtin.rs | 1 + compiler/rustc_resolve/src/check_unused.rs | 60 +++++++++++++++++-- compiler/rustc_resolve/src/imports.rs | 11 ++-- compiler/rustc_resolve/src/late.rs | 29 +++++---- compiler/rustc_resolve/src/lib.rs | 7 ++- tests/ui/lint/lint-qualification.fixed | 7 ++- tests/ui/lint/lint-qualification.rs | 5 +- tests/ui/lint/lint-qualification.stderr | 30 +++++----- ...necessary-qualification-issue-121331.fixed | 50 ++++++++++++++++ ...-unnecessary-qualification-issue-121331.rs | 50 ++++++++++++++++ ...ecessary-qualification-issue-121331.stderr | 31 ++++++++++ ...lid-unused-qualifications-suggestion.fixed | 11 ++++ ...nvalid-unused-qualifications-suggestion.rs | 11 ++++ ...id-unused-qualifications-suggestion.stderr | 2 +- .../unused-qualifications-suggestion.fixed | 2 + .../unused-qualifications-suggestion.rs | 2 + .../unused-qualifications-suggestion.stderr | 2 +- 17 files changed, 269 insertions(+), 42 deletions(-) create mode 100644 tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.fixed create mode 100644 tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.rs create mode 100644 tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index f2560b35aa2e1..c209f2772ff48 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -556,6 +556,7 @@ declare_lint! { /// fn main() { /// use foo::bar; /// foo::bar(); + /// bar(); /// } /// ``` /// diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index bf1ea2e270932..f6004fed8284e 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -23,18 +23,19 @@ // - `check_unused` finally emits the diagnostics based on the data generated // in the last step -use crate::imports::ImportKind; +use crate::imports::{Import, ImportKind}; use crate::module_to_string; use crate::Resolver; -use crate::NameBindingKind; +use crate::{LexicalScopeBinding, NameBindingKind}; use rustc_ast as ast; use rustc_ast::visit::{self, Visitor}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{pluralize, MultiSpan}; use rustc_hir::def::{DefKind, Res}; -use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS}; +use rustc_session::lint::builtin::{MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES}; +use rustc_session::lint::builtin::{UNUSED_IMPORTS, UNUSED_QUALIFICATIONS}; use rustc_session::lint::BuiltinLintDiag; use rustc_span::symbol::{kw, Ident}; use rustc_span::{Span, DUMMY_SP}; @@ -514,8 +515,59 @@ impl Resolver<'_, '_> { } } + let mut redundant_imports = UnordSet::default(); for import in check_redundant_imports { - self.check_for_redundant_imports(import); + if self.check_for_redundant_imports(import) + && let Some(id) = import.id() + { + redundant_imports.insert(id); + } + } + + // The lint fixes for unused_import and unnecessary_qualification may conflict. + // Deleting both unused imports and unnecessary segments of an item may result + // in the item not being found. + for unn_qua in &self.potentially_unnecessary_qualifications { + if let LexicalScopeBinding::Item(name_binding) = unn_qua.binding + && let NameBindingKind::Import { import, .. } = name_binding.kind + && (is_unused_import(import, &unused_imports) + || is_redundant_import(import, &redundant_imports)) + { + continue; + } + + self.lint_buffer.buffer_lint_with_diagnostic( + UNUSED_QUALIFICATIONS, + unn_qua.node_id, + unn_qua.path_span, + "unnecessary qualification", + BuiltinLintDiag::UnusedQualifications { removal_span: unn_qua.removal_span }, + ); + } + + fn is_redundant_import( + import: Import<'_>, + redundant_imports: &UnordSet, + ) -> bool { + if let Some(id) = import.id() + && redundant_imports.contains(&id) + { + return true; + } + false + } + + fn is_unused_import( + import: Import<'_>, + unused_imports: &FxIndexMap, + ) -> bool { + if let Some(unused_import) = unused_imports.get(&import.root_id) + && let Some(id) = import.id() + && unused_import.unused.contains(&id) + { + return true; + } + false } } } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index ea08041f2aadd..9bf3e9ccabdf1 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1306,7 +1306,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { None } - pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) { + pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'a>) -> bool { // This function is only called for single imports. let ImportKind::Single { source, target, ref source_bindings, ref target_bindings, id, .. @@ -1317,12 +1317,12 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { // Skip if the import is of the form `use source as target` and source != target. if source != target { - return; + return false; } // Skip if the import was produced by a macro. if import.parent_scope.expansion != LocalExpnId::ROOT { - return; + return false; } // Skip if we are inside a named module (in contrast to an anonymous @@ -1332,7 +1332,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { if import.used.get() == Some(Used::Other) || self.effective_visibilities.is_exported(self.local_def_id(id)) { - return; + return false; } let mut is_redundant = true; @@ -1375,7 +1375,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { format!("the item `{source}` is imported redundantly"), BuiltinLintDiag::RedundantImport(redundant_spans, source), ); + return true; } + + false } fn resolve_glob_import(&mut self, import: Import<'a>) { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index a996188db0229..c9b5c659f0f47 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -580,6 +580,15 @@ impl MaybeExported<'_> { } } +/// Used for recording UnnecessaryQualification. +#[derive(Debug)] +pub(crate) struct UnnecessaryQualification<'a> { + pub binding: LexicalScopeBinding<'a>, + pub node_id: NodeId, + pub path_span: Span, + pub removal_span: Span, +} + #[derive(Default)] struct DiagMetadata<'ast> { /// The current trait's associated items' ident, used for diagnostic suggestions. @@ -4654,20 +4663,16 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> { let ns = if i + 1 == path.len() { ns } else { TypeNS }; let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?; let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?; - - (res == binding.res()).then_some(seg) + (res == binding.res()).then_some((seg, binding)) }); - if let Some(unqualified) = unqualified { - self.r.lint_buffer.buffer_lint_with_diagnostic( - lint::builtin::UNUSED_QUALIFICATIONS, - finalize.node_id, - finalize.path_span, - "unnecessary qualification", - lint::BuiltinLintDiag::UnusedQualifications { - removal_span: path[0].ident.span.until(unqualified.ident.span), - }, - ); + if let Some((seg, binding)) = unqualified { + self.r.potentially_unnecessary_qualifications.push(UnnecessaryQualification { + binding, + node_id: finalize.node_id, + path_span: finalize.path_span, + removal_span: path[0].ident.span.until(seg.ident.span), + }); } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ccb67ea78cfdb..dfc2d029d4cfd 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -68,7 +68,7 @@ use std::fmt; use diagnostics::{ImportSuggestion, LabelSuggestion, Suggestion}; use imports::{Import, ImportData, ImportKind, NameResolution}; -use late::{HasGenericParams, PathSource, PatternSource}; +use late::{HasGenericParams, PathSource, PatternSource, UnnecessaryQualification}; use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef}; use crate::effective_visibilities::EffectiveVisibilitiesVisitor; @@ -372,7 +372,7 @@ impl<'a> From<&'a ast::PathSegment> for Segment { /// This refers to the thing referred by a name. The difference between `Res` and `Item` is that /// items are visible in their whole block, while `Res`es only from the place they are defined /// forward. -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] enum LexicalScopeBinding<'a> { Item(NameBinding<'a>), Res(Res), @@ -1105,6 +1105,8 @@ pub struct Resolver<'a, 'tcx> { potentially_unused_imports: Vec>, + potentially_unnecessary_qualifications: Vec>, + /// Table for mapping struct IDs into struct constructor IDs, /// it's not used during normal resolution, only for better error reporting. /// Also includes of list of each fields visibility @@ -1464,6 +1466,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> { local_macro_def_scopes: FxHashMap::default(), name_already_seen: FxHashMap::default(), potentially_unused_imports: Vec::new(), + potentially_unnecessary_qualifications: Default::default(), struct_constructors: Default::default(), unused_macros: Default::default(), unused_macro_rules: Default::default(), diff --git a/tests/ui/lint/lint-qualification.fixed b/tests/ui/lint/lint-qualification.fixed index 2b1f8b591752a..6fe6ba2792fe6 100644 --- a/tests/ui/lint/lint-qualification.fixed +++ b/tests/ui/lint/lint-qualification.fixed @@ -1,5 +1,6 @@ //@ run-rustfix #![deny(unused_qualifications)] +#![deny(unused_imports)] #![allow(deprecated, dead_code)] mod foo { @@ -21,8 +22,10 @@ fn main() { //~^ ERROR: unnecessary qualification //~| ERROR: unnecessary qualification - use std::fmt; - let _: fmt::Result = Ok(()); //~ ERROR: unnecessary qualification + + //~^ ERROR: unused import: `std::fmt` + let _: std::fmt::Result = Ok(()); + // don't report unnecessary qualification because fix(#122373) for issue #121331 let _ = ::default(); // issue #121999 //~^ ERROR: unnecessary qualification diff --git a/tests/ui/lint/lint-qualification.rs b/tests/ui/lint/lint-qualification.rs index 002fdbf7724a7..19d339b006c9a 100644 --- a/tests/ui/lint/lint-qualification.rs +++ b/tests/ui/lint/lint-qualification.rs @@ -1,5 +1,6 @@ //@ run-rustfix #![deny(unused_qualifications)] +#![deny(unused_imports)] #![allow(deprecated, dead_code)] mod foo { @@ -22,7 +23,9 @@ fn main() { //~| ERROR: unnecessary qualification use std::fmt; - let _: std::fmt::Result = Ok(()); //~ ERROR: unnecessary qualification + //~^ ERROR: unused import: `std::fmt` + let _: std::fmt::Result = Ok(()); + // don't report unnecessary qualification because fix(#122373) for issue #121331 let _ = ::default(); // issue #121999 //~^ ERROR: unnecessary qualification diff --git a/tests/ui/lint/lint-qualification.stderr b/tests/ui/lint/lint-qualification.stderr index 8dddcf23f7575..9e5c9b2df13f1 100644 --- a/tests/ui/lint/lint-qualification.stderr +++ b/tests/ui/lint/lint-qualification.stderr @@ -1,5 +1,5 @@ error: unnecessary qualification - --> $DIR/lint-qualification.rs:11:5 + --> $DIR/lint-qualification.rs:12:5 | LL | foo::bar(); | ^^^^^^^^ @@ -16,7 +16,7 @@ LL + bar(); | error: unnecessary qualification - --> $DIR/lint-qualification.rs:12:5 + --> $DIR/lint-qualification.rs:13:5 | LL | crate::foo::bar(); | ^^^^^^^^^^^^^^^ @@ -28,7 +28,7 @@ LL + bar(); | error: unnecessary qualification - --> $DIR/lint-qualification.rs:17:13 + --> $DIR/lint-qualification.rs:18:13 | LL | let _ = std::string::String::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL + let _ = String::new(); | error: unnecessary qualification - --> $DIR/lint-qualification.rs:18:13 + --> $DIR/lint-qualification.rs:19:13 | LL | let _ = ::std::env::current_dir(); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -52,7 +52,7 @@ LL + let _ = std::env::current_dir(); | error: unnecessary qualification - --> $DIR/lint-qualification.rs:20:12 + --> $DIR/lint-qualification.rs:21:12 | LL | let _: std::vec::Vec = std::vec::Vec::::new(); | ^^^^^^^^^^^^^^^^^^^^^ @@ -64,7 +64,7 @@ LL + let _: Vec = std::vec::Vec::::new(); | error: unnecessary qualification - --> $DIR/lint-qualification.rs:20:36 + --> $DIR/lint-qualification.rs:21:36 | LL | let _: std::vec::Vec = std::vec::Vec::::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -75,20 +75,20 @@ LL - let _: std::vec::Vec = std::vec::Vec::::new(); LL + let _: std::vec::Vec = Vec::::new(); | -error: unnecessary qualification - --> $DIR/lint-qualification.rs:25:12 - | -LL | let _: std::fmt::Result = Ok(()); - | ^^^^^^^^^^^^^^^^ +error: unused import: `std::fmt` + --> $DIR/lint-qualification.rs:25:9 | -help: remove the unnecessary path segments +LL | use std::fmt; + | ^^^^^^^^ | -LL - let _: std::fmt::Result = Ok(()); -LL + let _: fmt::Result = Ok(()); +note: the lint level is defined here + --> $DIR/lint-qualification.rs:3:9 | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ error: unnecessary qualification - --> $DIR/lint-qualification.rs:27:13 + --> $DIR/lint-qualification.rs:30:13 | LL | let _ = ::default(); // issue #121999 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.fixed b/tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.fixed new file mode 100644 index 0000000000000..d554bbfcc98c9 --- /dev/null +++ b/tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.fixed @@ -0,0 +1,50 @@ +//@ run-rustfix +//@ edition:2021 +#![deny(unused_qualifications)] +#![deny(unused_imports)] +#![feature(coroutines, coroutine_trait)] + +use std::ops::{ + Coroutine, + CoroutineState::{self}, + //~^ ERROR unused import: `*` +}; +use std::pin::Pin; + +#[allow(dead_code)] +fn finish(mut amt: usize, mut t: T) -> T::Return + where T: Coroutine<(), Yield = ()> + Unpin, +{ + loop { + match Pin::new(&mut t).resume(()) { + CoroutineState::Yielded(()) => amt = amt.checked_sub(1).unwrap(), + CoroutineState::Complete(ret) => { + assert_eq!(amt, 0); + return ret + } + } + } +} + + +mod foo { + pub fn bar() {} +} + +pub fn main() { + + use foo::bar; + bar(); + //~^ ERROR unnecessary qualification + bar(); + + // The item `use std::string::String` is imported redundantly. + // Suppress `unused_imports` reporting, otherwise the fixed file will report an error + #[allow(unused_imports)] + use std::string::String; + let s = String::new(); + let y = std::string::String::new(); + // unnecessary qualification + println!("{} {}", s, y); + +} diff --git a/tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.rs b/tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.rs new file mode 100644 index 0000000000000..4d79f5ab74530 --- /dev/null +++ b/tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.rs @@ -0,0 +1,50 @@ +//@ run-rustfix +//@ edition:2021 +#![deny(unused_qualifications)] +#![deny(unused_imports)] +#![feature(coroutines, coroutine_trait)] + +use std::ops::{ + Coroutine, + CoroutineState::{self, *}, + //~^ ERROR unused import: `*` +}; +use std::pin::Pin; + +#[allow(dead_code)] +fn finish(mut amt: usize, mut t: T) -> T::Return + where T: Coroutine<(), Yield = ()> + Unpin, +{ + loop { + match Pin::new(&mut t).resume(()) { + CoroutineState::Yielded(()) => amt = amt.checked_sub(1).unwrap(), + CoroutineState::Complete(ret) => { + assert_eq!(amt, 0); + return ret + } + } + } +} + + +mod foo { + pub fn bar() {} +} + +pub fn main() { + + use foo::bar; + foo::bar(); + //~^ ERROR unnecessary qualification + bar(); + + // The item `use std::string::String` is imported redundantly. + // Suppress `unused_imports` reporting, otherwise the fixed file will report an error + #[allow(unused_imports)] + use std::string::String; + let s = String::new(); + let y = std::string::String::new(); + // unnecessary qualification + println!("{} {}", s, y); + +} diff --git a/tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.stderr b/tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.stderr new file mode 100644 index 0000000000000..52ed13ea150d7 --- /dev/null +++ b/tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.stderr @@ -0,0 +1,31 @@ +error: unused import: `*` + --> $DIR/lint-unnecessary-qualification-issue-121331.rs:9:28 + | +LL | CoroutineState::{self, *}, + | ^ + | +note: the lint level is defined here + --> $DIR/lint-unnecessary-qualification-issue-121331.rs:4:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: unnecessary qualification + --> $DIR/lint-unnecessary-qualification-issue-121331.rs:37:5 + | +LL | foo::bar(); + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-unnecessary-qualification-issue-121331.rs:3:9 + | +LL | #![deny(unused_qualifications)] + | ^^^^^^^^^^^^^^^^^^^^^ +help: remove the unnecessary path segments + | +LL - foo::bar(); +LL + bar(); + | + +error: aborting due to 2 previous errors + diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed index 8a67b20eec11d..d95faef8ac44b 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed @@ -18,6 +18,16 @@ impl Index for A { } } +// This is used to make `use std::ops::Index;` not unused_import. +// details in fix(#122373) for issue #121331 +pub struct C; +impl Index for C { + type Output = (); + fn index(&self, _: str) -> &Self::Output { + &() + } +} + mod inner { pub trait Trait {} } @@ -29,4 +39,5 @@ use inner::Trait; impl Trait for () {} //~^ ERROR unnecessary qualification +impl Trait for A {} fn main() {} diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs index 528edb331cf55..0eee8f71ad4e1 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs @@ -18,6 +18,16 @@ impl ops::Index for A { } } +// This is used to make `use std::ops::Index;` not unused_import. +// details in fix(#122373) for issue #121331 +pub struct C; +impl Index for C { + type Output = (); + fn index(&self, _: str) -> &Self::Output { + &() + } +} + mod inner { pub trait Trait {} } @@ -29,4 +39,5 @@ use inner::Trait; impl inner::Trait for () {} //~^ ERROR unnecessary qualification +impl Trait for A {} fn main() {} diff --git a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr index bcda721071235..e105b754b7195 100644 --- a/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr +++ b/tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr @@ -16,7 +16,7 @@ LL + impl Index for A { | error: unnecessary qualification - --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:29:6 + --> $DIR/issue-113808-invalid-unused-qualifications-suggestion.rs:39:6 | LL | impl inner::Trait for () {} | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/resolve/unused-qualifications-suggestion.fixed b/tests/ui/resolve/unused-qualifications-suggestion.fixed index 6935f611b361f..22e0daea46764 100644 --- a/tests/ui/resolve/unused-qualifications-suggestion.fixed +++ b/tests/ui/resolve/unused-qualifications-suggestion.fixed @@ -16,8 +16,10 @@ fn main() { use foo::bar; bar(); //~^ ERROR unnecessary qualification + bar(); use baz::qux::quux; quux(); //~^ ERROR unnecessary qualification + quux(); } diff --git a/tests/ui/resolve/unused-qualifications-suggestion.rs b/tests/ui/resolve/unused-qualifications-suggestion.rs index b3fe04ff0ea4b..89516c1344a9e 100644 --- a/tests/ui/resolve/unused-qualifications-suggestion.rs +++ b/tests/ui/resolve/unused-qualifications-suggestion.rs @@ -16,8 +16,10 @@ fn main() { use foo::bar; foo::bar(); //~^ ERROR unnecessary qualification + bar(); use baz::qux::quux; baz::qux::quux(); //~^ ERROR unnecessary qualification + quux(); } diff --git a/tests/ui/resolve/unused-qualifications-suggestion.stderr b/tests/ui/resolve/unused-qualifications-suggestion.stderr index e3dac37fc6e22..5b71ba9e2223c 100644 --- a/tests/ui/resolve/unused-qualifications-suggestion.stderr +++ b/tests/ui/resolve/unused-qualifications-suggestion.stderr @@ -16,7 +16,7 @@ LL + bar(); | error: unnecessary qualification - --> $DIR/unused-qualifications-suggestion.rs:21:5 + --> $DIR/unused-qualifications-suggestion.rs:22:5 | LL | baz::qux::quux(); | ^^^^^^^^^^^^^^ From f9cdaeb6fdbfc91705bb790d892219db544a787c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 8 Feb 2024 12:41:44 +1100 Subject: [PATCH 14/23] coverage: Data structures for recording branch info during MIR building --- compiler/rustc_middle/src/mir/coverage.rs | 23 +++++++++++-- compiler/rustc_middle/src/mir/mod.rs | 8 +++++ compiler/rustc_middle/src/mir/pretty.rs | 22 +++++++++++++ .../rustc_mir_build/src/build/coverageinfo.rs | 32 +++++++++++++++++++ .../rustc_mir_build/src/build/custom/mod.rs | 1 + compiler/rustc_mir_build/src/build/mod.rs | 12 +++++-- 6 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 compiler/rustc_mir_build/src/build/coverageinfo.rs diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index ed3a73af1ce27..2c51aec3a7609 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -2,7 +2,7 @@ use rustc_index::IndexVec; use rustc_macros::HashStable; -use rustc_span::Symbol; +use rustc_span::{Span, Symbol}; use std::fmt::{self, Debug, Formatter}; @@ -93,7 +93,7 @@ pub enum CoverageKind { SpanMarker, /// Marks its enclosing basic block with an ID that can be referred to by - /// other data in the MIR body. + /// side data in [`BranchInfo`]. /// /// Has no effect during codegen. BlockMarker { id: BlockMarkerId }, @@ -218,3 +218,22 @@ pub struct FunctionCoverageInfo { pub expressions: IndexVec, pub mappings: Vec, } + +/// Branch information recorded during THIR-to-MIR lowering, and stored in MIR. +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct BranchInfo { + /// 1 more than the highest-numbered [`CoverageKind::BlockMarker`] that was + /// injected into the MIR body. This makes it possible to allocate per-ID + /// data structures without having to scan the entire body first. + pub num_block_markers: usize, + pub branch_spans: Vec, +} + +#[derive(Clone, Debug)] +#[derive(TyEncodable, TyDecodable, Hash, HashStable, TypeFoldable, TypeVisitable)] +pub struct BranchSpan { + pub span: Span, + pub true_marker: BlockMarkerId, + pub false_marker: BlockMarkerId, +} diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index b71c614dc4fe9..d57ffc0f8b5c5 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -403,6 +403,12 @@ pub struct Body<'tcx> { pub tainted_by_errors: Option, + /// Branch coverage information collected during MIR building, to be used by + /// the `InstrumentCoverage` pass. + /// + /// Only present if branch coverage is enabled and this function is eligible. + pub coverage_branch_info: Option>, + /// Per-function coverage information added by the `InstrumentCoverage` /// pass, to be used in conjunction with the coverage statements injected /// into this body's blocks. @@ -450,6 +456,7 @@ impl<'tcx> Body<'tcx> { is_polymorphic: false, injection_phase: None, tainted_by_errors, + coverage_branch_info: None, function_coverage_info: None, }; body.is_polymorphic = body.has_non_region_param(); @@ -479,6 +486,7 @@ impl<'tcx> Body<'tcx> { is_polymorphic: false, injection_phase: None, tainted_by_errors: None, + coverage_branch_info: None, function_coverage_info: None, }; body.is_polymorphic = body.has_non_region_param(); diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 8ae65f3832fd7..94751c4476157 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -461,6 +461,9 @@ pub fn write_mir_intro<'tcx>( // Add an empty line before the first block is printed. writeln!(w)?; + if let Some(branch_info) = &body.coverage_branch_info { + write_coverage_branch_info(branch_info, w)?; + } if let Some(function_coverage_info) = &body.function_coverage_info { write_function_coverage_info(function_coverage_info, w)?; } @@ -468,6 +471,25 @@ pub fn write_mir_intro<'tcx>( Ok(()) } +fn write_coverage_branch_info( + branch_info: &coverage::BranchInfo, + w: &mut dyn io::Write, +) -> io::Result<()> { + let coverage::BranchInfo { branch_spans, .. } = branch_info; + + for coverage::BranchSpan { span, true_marker, false_marker } in branch_spans { + writeln!( + w, + "{INDENT}coverage branch {{ true: {true_marker:?}, false: {false_marker:?} }} => {span:?}", + )?; + } + if !branch_spans.is_empty() { + writeln!(w)?; + } + + Ok(()) +} + fn write_function_coverage_info( function_coverage_info: &coverage::FunctionCoverageInfo, w: &mut dyn io::Write, diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs new file mode 100644 index 0000000000000..3fdf48f54c983 --- /dev/null +++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs @@ -0,0 +1,32 @@ +use rustc_middle::mir; +use rustc_middle::mir::coverage::BranchSpan; +use rustc_middle::ty::TyCtxt; +use rustc_span::def_id::LocalDefId; + +pub(crate) struct BranchInfoBuilder { + num_block_markers: usize, + branch_spans: Vec, +} + +impl BranchInfoBuilder { + /// Creates a new branch info builder, but only if branch coverage instrumentation + /// is enabled and `def_id` represents a function that is eligible for coverage. + pub(crate) fn new_if_enabled(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { + if tcx.sess.instrument_coverage_branch() && tcx.is_eligible_for_coverage(def_id) { + Some(Self { num_block_markers: 0, branch_spans: vec![] }) + } else { + None + } + } + + pub(crate) fn into_done(self) -> Option> { + let Self { num_block_markers, branch_spans } = self; + + if num_block_markers == 0 { + assert!(branch_spans.is_empty()); + return None; + } + + Some(Box::new(mir::coverage::BranchInfo { num_block_markers, branch_spans })) + } +} diff --git a/compiler/rustc_mir_build/src/build/custom/mod.rs b/compiler/rustc_mir_build/src/build/custom/mod.rs index c2bff9084c67e..288b787798b49 100644 --- a/compiler/rustc_mir_build/src/build/custom/mod.rs +++ b/compiler/rustc_mir_build/src/build/custom/mod.rs @@ -60,6 +60,7 @@ pub(super) fn build_custom_mir<'tcx>( tainted_by_errors: None, injection_phase: None, pass_count: 0, + coverage_branch_info: None, function_coverage_info: None, }; diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index 45954bdb114f2..2fe5d3fb5e0df 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -234,6 +234,10 @@ struct Builder<'a, 'tcx> { // the root (most of them do) and saves us from retracing many sub-paths // many times, and rechecking many nodes. lint_level_roots_cache: GrowableBitSet, + + /// Collects additional coverage information during MIR building. + /// Only present if branch coverage is enabled and this function is eligible. + coverage_branch_info: Option, } type CaptureMap<'tcx> = SortedIndexMultiMap>; @@ -807,6 +811,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { unit_temp: None, var_debug_info: vec![], lint_level_roots_cache: GrowableBitSet::new_empty(), + coverage_branch_info: coverageinfo::BranchInfoBuilder::new_if_enabled(tcx, def), }; assert_eq!(builder.cfg.start_new_block(), START_BLOCK); @@ -826,7 +831,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - Body::new( + let mut body = Body::new( MirSource::item(self.def_id.to_def_id()), self.cfg.basic_blocks, self.source_scopes, @@ -837,7 +842,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.fn_span, self.coroutine, None, - ) + ); + body.coverage_branch_info = self.coverage_branch_info.and_then(|b| b.into_done()); + body } fn insert_upvar_arg(&mut self) { @@ -1111,6 +1118,7 @@ pub(crate) fn parse_float_into_scalar( mod block; mod cfg; +mod coverageinfo; mod custom; mod expr; mod matches; From c1bec0ce6b6eefabd153c315ccec4dfce3808885 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 29 Nov 2023 15:48:50 +1100 Subject: [PATCH 15/23] coverage: Record branch information during MIR building --- .../rustc_mir_build/src/build/coverageinfo.rs | 124 +++++++++++++++++- .../rustc_mir_build/src/build/matches/mod.rs | 11 ++ 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs index 3fdf48f54c983..0b8ec234dda7a 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs @@ -1,26 +1,92 @@ -use rustc_middle::mir; -use rustc_middle::mir::coverage::BranchSpan; +use std::assert_matches::assert_matches; +use std::collections::hash_map::Entry; + +use rustc_data_structures::fx::FxHashMap; +use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageKind}; +use rustc_middle::mir::{self, BasicBlock, UnOp}; +use rustc_middle::thir::{ExprId, ExprKind, Thir}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::LocalDefId; +use crate::build::Builder; + pub(crate) struct BranchInfoBuilder { + /// Maps condition expressions to their enclosing `!`, for better instrumentation. + nots: FxHashMap, + num_block_markers: usize, branch_spans: Vec, } +#[derive(Clone, Copy)] +struct NotInfo { + /// When visiting the associated expression as a branch condition, treat this + /// enclosing `!` as the branch condition instead. + enclosing_not: ExprId, + /// True if the associated expression is nested within an odd number of `!` + /// expressions relative to `enclosing_not` (inclusive of `enclosing_not`). + is_flipped: bool, +} + impl BranchInfoBuilder { /// Creates a new branch info builder, but only if branch coverage instrumentation /// is enabled and `def_id` represents a function that is eligible for coverage. pub(crate) fn new_if_enabled(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { if tcx.sess.instrument_coverage_branch() && tcx.is_eligible_for_coverage(def_id) { - Some(Self { num_block_markers: 0, branch_spans: vec![] }) + Some(Self { nots: FxHashMap::default(), num_block_markers: 0, branch_spans: vec![] }) } else { None } } + /// Unary `!` expressions inside an `if` condition are lowered by lowering + /// their argument instead, and then reversing the then/else arms of that `if`. + /// + /// That's awkward for branch coverage instrumentation, so to work around that + /// we pre-emptively visit any affected `!` expressions, and record extra + /// information that [`Builder::visit_coverage_branch_condition`] can use to + /// synthesize branch instrumentation for the enclosing `!`. + pub(crate) fn visit_unary_not(&mut self, thir: &Thir<'_>, unary_not: ExprId) { + assert_matches!(thir[unary_not].kind, ExprKind::Unary { op: UnOp::Not, .. }); + + self.visit_with_not_info( + thir, + unary_not, + // Set `is_flipped: false` for the `!` itself, so that its enclosed + // expression will have `is_flipped: true`. + NotInfo { enclosing_not: unary_not, is_flipped: false }, + ); + } + + fn visit_with_not_info(&mut self, thir: &Thir<'_>, expr_id: ExprId, not_info: NotInfo) { + match self.nots.entry(expr_id) { + // This expression has already been marked by an enclosing `!`. + Entry::Occupied(_) => return, + Entry::Vacant(entry) => entry.insert(not_info), + }; + + match thir[expr_id].kind { + ExprKind::Unary { op: UnOp::Not, arg } => { + // Invert the `is_flipped` flag for the contents of this `!`. + let not_info = NotInfo { is_flipped: !not_info.is_flipped, ..not_info }; + self.visit_with_not_info(thir, arg, not_info); + } + ExprKind::Scope { value, .. } => self.visit_with_not_info(thir, value, not_info), + ExprKind::Use { source } => self.visit_with_not_info(thir, source, not_info), + // All other expressions (including `&&` and `||`) don't need any + // special handling of their contents, so stop visiting. + _ => {} + } + } + + fn next_block_marker_id(&mut self) -> BlockMarkerId { + let id = BlockMarkerId::from_usize(self.num_block_markers); + self.num_block_markers += 1; + id + } + pub(crate) fn into_done(self) -> Option> { - let Self { num_block_markers, branch_spans } = self; + let Self { nots: _, num_block_markers, branch_spans } = self; if num_block_markers == 0 { assert!(branch_spans.is_empty()); @@ -30,3 +96,53 @@ impl BranchInfoBuilder { Some(Box::new(mir::coverage::BranchInfo { num_block_markers, branch_spans })) } } + +impl Builder<'_, '_> { + /// If branch coverage is enabled, inject marker statements into `then_block` + /// and `else_block`, and record their IDs in the table of branch spans. + pub(crate) fn visit_coverage_branch_condition( + &mut self, + mut expr_id: ExprId, + mut then_block: BasicBlock, + mut else_block: BasicBlock, + ) { + // Bail out if branch coverage is not enabled for this function. + let Some(branch_info) = self.coverage_branch_info.as_ref() else { return }; + + // If this condition expression is nested within one or more `!` expressions, + // replace it with the enclosing `!` collected by `visit_unary_not`. + if let Some(&NotInfo { enclosing_not, is_flipped }) = branch_info.nots.get(&expr_id) { + expr_id = enclosing_not; + if is_flipped { + std::mem::swap(&mut then_block, &mut else_block); + } + } + let source_info = self.source_info(self.thir[expr_id].span); + + // Now that we have `source_info`, we can upgrade to a &mut reference. + let branch_info = self.coverage_branch_info.as_mut().expect("upgrading & to &mut"); + + let mut inject_branch_marker = |block: BasicBlock| { + let id = branch_info.next_block_marker_id(); + + let marker_statement = mir::Statement { + source_info, + kind: mir::StatementKind::Coverage(Box::new(mir::Coverage { + kind: CoverageKind::BlockMarker { id }, + })), + }; + self.cfg.push(block, marker_statement); + + id + }; + + let true_marker = inject_branch_marker(then_block); + let false_marker = inject_branch_marker(else_block); + + branch_info.branch_spans.push(BranchSpan { + span: source_info.span, + true_marker, + false_marker, + }); + } +} diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 4d5ed65c8416c..e7808ff880b57 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -105,6 +105,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { success_block.unit() } ExprKind::Unary { op: UnOp::Not, arg } => { + // Improve branch coverage instrumentation by noting conditions + // nested within one or more `!` expressions. + // (Skipped if branch coverage is not enabled.) + if let Some(branch_info) = this.coverage_branch_info.as_mut() { + branch_info.visit_unary_not(this.thir, expr_id); + } + let local_scope = this.local_scope(); let (success_block, failure_block) = this.in_if_then_scope(local_scope, expr_span, |this| { @@ -149,6 +156,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let else_block = this.cfg.start_new_block(); let term = TerminatorKind::if_(operand, then_block, else_block); + // Record branch coverage info for this condition. + // (Does nothing if branch coverage is not enabled.) + this.visit_coverage_branch_condition(expr_id, then_block, else_block); + let source_info = this.source_info(expr_span); this.cfg.terminate(block, source_info, term); this.break_for_else(else_block, source_info); From 31d0b5017857cef35031a7d4210bd045758dcae2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 16 Nov 2023 17:48:23 +1100 Subject: [PATCH 16/23] coverage: Include recorded branch info in coverage instrumentation --- .../src/coverageinfo/ffi.rs | 12 +++- compiler/rustc_middle/src/mir/coverage.rs | 9 ++- .../rustc_mir_transform/src/coverage/mod.rs | 4 ++ .../rustc_mir_transform/src/coverage/spans.rs | 12 ++++ .../src/coverage/spans/from_mir.rs | 55 ++++++++++++++++++- 5 files changed, 85 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs index 017843c7e7d15..2af28146a51ea 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/ffi.rs @@ -164,6 +164,15 @@ impl CounterMappingRegion { end_line, end_col, ), + MappingKind::Branch { true_term, false_term } => Self::branch_region( + Counter::from_term(true_term), + Counter::from_term(false_term), + local_file_id, + start_line, + start_col, + end_line, + end_col, + ), } } @@ -188,9 +197,6 @@ impl CounterMappingRegion { } } - // This function might be used in the future; the LLVM API is still evolving, as is coverage - // support. - #[allow(dead_code)] pub(crate) fn branch_region( counter: Counter, false_counter: Counter, diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs index 2c51aec3a7609..645a417c32250 100644 --- a/compiler/rustc_middle/src/mir/coverage.rs +++ b/compiler/rustc_middle/src/mir/coverage.rs @@ -179,14 +179,18 @@ pub struct Expression { pub enum MappingKind { /// Associates a normal region of code with a counter/expression/zero. Code(CovTerm), + /// Associates a branch region with separate counters for true and false. + Branch { true_term: CovTerm, false_term: CovTerm }, } impl MappingKind { /// Iterator over all coverage terms in this mapping kind. pub fn terms(&self) -> impl Iterator { - let one = |a| std::iter::once(a); + let one = |a| std::iter::once(a).chain(None); + let two = |a, b| std::iter::once(a).chain(Some(b)); match *self { Self::Code(term) => one(term), + Self::Branch { true_term, false_term } => two(true_term, false_term), } } @@ -195,6 +199,9 @@ impl MappingKind { pub fn map_terms(&self, map_fn: impl Fn(CovTerm) -> CovTerm) -> Self { match *self { Self::Code(term) => Self::Code(map_fn(term)), + Self::Branch { true_term, false_term } => { + Self::Branch { true_term: map_fn(true_term), false_term: map_fn(false_term) } + } } } } diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index bde135834860b..b2407c545071b 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -139,6 +139,10 @@ fn create_mappings<'tcx>( .filter_map(|&BcbMapping { kind: bcb_mapping_kind, span }| { let kind = match bcb_mapping_kind { BcbMappingKind::Code(bcb) => MappingKind::Code(term_for_bcb(bcb)), + BcbMappingKind::Branch { true_bcb, false_bcb } => MappingKind::Branch { + true_term: term_for_bcb(true_bcb), + false_term: term_for_bcb(false_bcb), + }, }; let code_region = make_code_region(source_map, file_name, span, body_span)?; Some(Mapping { kind, code_region }) diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index 4260a6f0c6f79..672de1fbe60fd 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -13,6 +13,8 @@ mod from_mir; pub(super) enum BcbMappingKind { /// Associates an ordinary executable code span with its corresponding BCB. Code(BasicCoverageBlock), + /// Associates a branch span with BCBs for its true and false arms. + Branch { true_bcb: BasicCoverageBlock, false_bcb: BasicCoverageBlock }, } #[derive(Debug)] @@ -66,6 +68,12 @@ pub(super) fn generate_coverage_spans( // Each span produced by the generator represents an ordinary code region. BcbMapping { kind: BcbMappingKind::Code(bcb), span } })); + + mappings.extend(from_mir::extract_branch_mappings( + mir_body, + hir_info.body_span, + basic_coverage_blocks, + )); } if mappings.is_empty() { @@ -80,6 +88,10 @@ pub(super) fn generate_coverage_spans( for &BcbMapping { kind, span: _ } in &mappings { match kind { BcbMappingKind::Code(bcb) => insert(bcb), + BcbMappingKind::Branch { true_bcb, false_bcb } => { + insert(true_bcb); + insert(false_bcb); + } } } diff --git a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs index 223613cfc6fdf..86097bdcd9537 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs @@ -1,7 +1,9 @@ use rustc_data_structures::captures::Captures; use rustc_data_structures::fx::FxHashSet; +use rustc_index::IndexVec; +use rustc_middle::mir::coverage::{BlockMarkerId, BranchSpan, CoverageKind}; use rustc_middle::mir::{ - self, AggregateKind, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, + self, AggregateKind, BasicBlock, FakeReadCause, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; use rustc_span::{ExpnKind, MacroKind, Span, Symbol}; @@ -9,6 +11,7 @@ use rustc_span::{ExpnKind, MacroKind, Span, Symbol}; use crate::coverage::graph::{ BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB, }; +use crate::coverage::spans::{BcbMapping, BcbMappingKind}; use crate::coverage::ExtractedHirInfo; /// Traverses the MIR body to produce an initial collection of coverage-relevant @@ -179,8 +182,6 @@ fn is_closure_like(statement: &Statement<'_>) -> bool { /// If the MIR `Statement` has a span contributive to computing coverage spans, /// return it; otherwise return `None`. fn filtered_statement_span(statement: &Statement<'_>) -> Option { - use mir::coverage::CoverageKind; - match statement.kind { // These statements have spans that are often outside the scope of the executed source code // for their parent `BasicBlock`. @@ -363,3 +364,51 @@ impl SpanFromMir { Self { span, visible_macro, bcb, is_hole } } } + +pub(super) fn extract_branch_mappings( + mir_body: &mir::Body<'_>, + body_span: Span, + basic_coverage_blocks: &CoverageGraph, +) -> Vec { + let Some(branch_info) = mir_body.coverage_branch_info.as_deref() else { + return vec![]; + }; + + let mut block_markers = IndexVec::>::from_elem_n( + None, + branch_info.num_block_markers, + ); + + // Fill out the mapping from block marker IDs to their enclosing blocks. + for (bb, data) in mir_body.basic_blocks.iter_enumerated() { + for statement in &data.statements { + if let StatementKind::Coverage(coverage) = &statement.kind + && let CoverageKind::BlockMarker { id } = coverage.kind + { + block_markers[id] = Some(bb); + } + } + } + + branch_info + .branch_spans + .iter() + .filter_map(|&BranchSpan { span: raw_span, true_marker, false_marker }| { + // For now, ignore any branch span that was introduced by + // expansion. This makes things like assert macros less noisy. + if !raw_span.ctxt().outer_expn_data().is_root() { + return None; + } + let (span, _) = unexpand_into_body_span_with_visible_macro(raw_span, body_span)?; + + let bcb_from_marker = |marker: BlockMarkerId| { + Some(basic_coverage_blocks.bcb_from_bb(block_markers[marker]?)?) + }; + + let true_bcb = bcb_from_marker(true_marker)?; + let false_bcb = bcb_from_marker(false_marker)?; + + Some(BcbMapping { kind: BcbMappingKind::Branch { true_bcb, false_bcb }, span }) + }) + .collect::>() +} From 5fb1f61a7702d87380026e9f1c7a1fac01920d18 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 10 Mar 2024 21:20:27 +1100 Subject: [PATCH 17/23] coverage: Enable branch coverage in the branch coverage tests --- tests/coverage/branch_generics.cov-map | 27 ++-- tests/coverage/branch_generics.coverage | 16 +- tests/coverage/branch_generics.rs | 2 +- tests/coverage/branch_guard.cov-map | 26 ++-- tests/coverage/branch_guard.coverage | 8 +- tests/coverage/branch_guard.rs | 2 +- tests/coverage/branch_if.cov-map | 186 +++++++++++++++--------- tests/coverage/branch_if.coverage | 31 +++- tests/coverage/branch_if.rs | 2 +- tests/coverage/branch_while.cov-map | 70 ++++++--- tests/coverage/branch_while.coverage | 16 +- tests/coverage/branch_while.rs | 2 +- 12 files changed, 272 insertions(+), 116 deletions(-) diff --git a/tests/coverage/branch_generics.cov-map b/tests/coverage/branch_generics.cov-map index ff8bb632a54f6..719e97efad455 100644 --- a/tests/coverage/branch_generics.cov-map +++ b/tests/coverage/branch_generics.cov-map @@ -1,43 +1,52 @@ Function name: branch_generics::print_size::<()> -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 06, 01, 01, 24, 05, 01, 25, 02, 06, 02, 02, 0c, 02, 06, 07, 03, 01, 00, 02] +Raw bytes (35): 0x[01, 01, 02, 01, 05, 05, 02, 05, 01, 06, 01, 01, 24, 20, 05, 02, 01, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 07, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) -Number of file 0 mappings: 4 +Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36) -- Code(Counter(1)) at (prev + 1, 37) to (start + 2, 6) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 8) to (start + 0, 36) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 37) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - c1) - Code(Expression(1, Add)) at (prev + 3, 1) to (start + 0, 2) = (c1 + (c0 - c1)) Function name: branch_generics::print_size:: -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 06, 01, 01, 24, 05, 01, 25, 02, 06, 02, 02, 0c, 02, 06, 07, 03, 01, 00, 02] +Raw bytes (35): 0x[01, 01, 02, 01, 05, 05, 02, 05, 01, 06, 01, 01, 24, 20, 05, 02, 01, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 07, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) -Number of file 0 mappings: 4 +Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36) -- Code(Counter(1)) at (prev + 1, 37) to (start + 2, 6) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 8) to (start + 0, 36) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 37) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - c1) - Code(Expression(1, Add)) at (prev + 3, 1) to (start + 0, 2) = (c1 + (c0 - c1)) Function name: branch_generics::print_size:: -Raw bytes (28): 0x[01, 01, 02, 01, 05, 05, 02, 04, 01, 06, 01, 01, 24, 05, 01, 25, 02, 06, 02, 02, 0c, 02, 06, 07, 03, 01, 00, 02] +Raw bytes (35): 0x[01, 01, 02, 01, 05, 05, 02, 05, 01, 06, 01, 01, 24, 20, 05, 02, 01, 08, 00, 24, 05, 00, 25, 02, 06, 02, 02, 0c, 02, 06, 07, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 2 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub) -Number of file 0 mappings: 4 +Number of file 0 mappings: 5 - Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36) -- Code(Counter(1)) at (prev + 1, 37) to (start + 2, 6) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 8) to (start + 0, 36) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 37) to (start + 2, 6) - Code(Expression(0, Sub)) at (prev + 2, 12) to (start + 2, 6) = (c0 - c1) - Code(Expression(1, Add)) at (prev + 3, 1) to (start + 0, 2) diff --git a/tests/coverage/branch_generics.coverage b/tests/coverage/branch_generics.coverage index cfbd2d3f4bd46..e7cec151ce62c 100644 --- a/tests/coverage/branch_generics.coverage +++ b/tests/coverage/branch_generics.coverage @@ -1,10 +1,15 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| | + LL| |//@ compile-flags: -Zcoverage-options=branch LL| |//@ llvm-cov-flags: --show-branches=count LL| | LL| 3|fn print_size() { LL| 3| if std::mem::size_of::() > 4 { + ------------------ + | Branch (LL:8): [True: 0, False: 1] + | Branch (LL:8): [True: 0, False: 1] + | Branch (LL:8): [True: 1, False: 0] + ------------------ LL| 1| println!("size > 4"); LL| 2| } else { LL| 2| println!("size <= 4"); @@ -14,6 +19,9 @@ | branch_generics::print_size::<()>: | LL| 1|fn print_size() { | LL| 1| if std::mem::size_of::() > 4 { + | ------------------ + | | Branch (LL:8): [True: 0, False: 1] + | ------------------ | LL| 0| println!("size > 4"); | LL| 1| } else { | LL| 1| println!("size <= 4"); @@ -23,6 +31,9 @@ | branch_generics::print_size::: | LL| 1|fn print_size() { | LL| 1| if std::mem::size_of::() > 4 { + | ------------------ + | | Branch (LL:8): [True: 0, False: 1] + | ------------------ | LL| 0| println!("size > 4"); | LL| 1| } else { | LL| 1| println!("size <= 4"); @@ -32,6 +43,9 @@ | branch_generics::print_size::: | LL| 1|fn print_size() { | LL| 1| if std::mem::size_of::() > 4 { + | ------------------ + | | Branch (LL:8): [True: 1, False: 0] + | ------------------ | LL| 1| println!("size > 4"); | LL| 1| } else { | LL| 0| println!("size <= 4"); diff --git a/tests/coverage/branch_generics.rs b/tests/coverage/branch_generics.rs index ad1f5be33c4b1..d870ace7006b3 100644 --- a/tests/coverage/branch_generics.rs +++ b/tests/coverage/branch_generics.rs @@ -1,6 +1,6 @@ #![feature(coverage_attribute)] //@ edition: 2021 - +//@ compile-flags: -Zcoverage-options=branch //@ llvm-cov-flags: --show-branches=count fn print_size() { diff --git a/tests/coverage/branch_guard.cov-map b/tests/coverage/branch_guard.cov-map index e0cbbf491960f..0b3622f6347a8 100644 --- a/tests/coverage/branch_guard.cov-map +++ b/tests/coverage/branch_guard.cov-map @@ -1,24 +1,32 @@ Function name: branch_guard::branch_match_guard -Raw bytes (67): 0x[01, 01, 04, 05, 09, 0b, 15, 0f, 11, 03, 0d, 0b, 01, 0c, 01, 01, 10, 1d, 03, 0b, 00, 0c, 15, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 19, 00, 14, 00, 19, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 1d, 00, 14, 00, 19, 11, 00, 1d, 02, 0a, 03, 03, 0e, 02, 0a, 07, 04, 01, 00, 02] +Raw bytes (85): 0x[01, 01, 06, 19, 0d, 05, 09, 0f, 15, 13, 11, 17, 0d, 05, 09, 0d, 01, 0c, 01, 01, 10, 1d, 03, 0b, 00, 0c, 15, 01, 14, 02, 0a, 0d, 03, 0e, 00, 0f, 19, 00, 14, 00, 19, 20, 0d, 02, 00, 14, 00, 1e, 0d, 00, 1d, 02, 0a, 11, 03, 0e, 00, 0f, 1d, 00, 14, 00, 19, 20, 11, 09, 00, 14, 00, 1e, 11, 00, 1d, 02, 0a, 17, 03, 0e, 02, 0a, 0b, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 4 -- expression 0 operands: lhs = Counter(1), rhs = Counter(2) -- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(5) -- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(4) -- expression 3 operands: lhs = Expression(0, Add), rhs = Counter(3) -Number of file 0 mappings: 11 +Number of expressions: 6 +- expression 0 operands: lhs = Counter(6), rhs = Counter(3) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(5) +- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(4) +- expression 4 operands: lhs = Expression(5, Add), rhs = Counter(3) +- expression 5 operands: lhs = Counter(1), rhs = Counter(2) +Number of file 0 mappings: 13 - Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) - Code(Counter(7)) at (prev + 3, 11) to (start + 0, 12) - Code(Counter(5)) at (prev + 1, 20) to (start + 2, 10) - Code(Counter(3)) at (prev + 3, 14) to (start + 0, 15) - Code(Counter(6)) at (prev + 0, 20) to (start + 0, 25) +- Branch { true: Counter(3), false: Expression(0, Sub) } at (prev + 0, 20) to (start + 0, 30) + true = c3 + false = (c6 - c3) - Code(Counter(3)) at (prev + 0, 29) to (start + 2, 10) - Code(Counter(4)) at (prev + 3, 14) to (start + 0, 15) - Code(Counter(7)) at (prev + 0, 20) to (start + 0, 25) +- Branch { true: Counter(4), false: Counter(2) } at (prev + 0, 20) to (start + 0, 30) + true = c4 + false = c2 - Code(Counter(4)) at (prev + 0, 29) to (start + 2, 10) -- Code(Expression(0, Add)) at (prev + 3, 14) to (start + 2, 10) +- Code(Expression(5, Add)) at (prev + 3, 14) to (start + 2, 10) = (c1 + c2) -- Code(Expression(1, Add)) at (prev + 4, 1) to (start + 0, 2) +- Code(Expression(2, Add)) at (prev + 4, 1) to (start + 0, 2) = ((((c1 + c2) + c3) + c4) + c5) diff --git a/tests/coverage/branch_guard.coverage b/tests/coverage/branch_guard.coverage index 6156ae88c7461..f89b965b5d0f7 100644 --- a/tests/coverage/branch_guard.coverage +++ b/tests/coverage/branch_guard.coverage @@ -1,6 +1,6 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| | + LL| |//@ compile-flags: -Zcoverage-options=branch LL| |//@ llvm-cov-flags: --show-branches=count LL| | LL| |macro_rules! no_merge { @@ -18,9 +18,15 @@ LL| 1| } LL| 3| Some(x) if x % 2 == 0 => { ^2 + ------------------ + | Branch (LL:20): [True: 2, False: 1] + ------------------ LL| 2| println!("is nonzero and even"); LL| 2| } LL| 1| Some(x) if x % 3 == 0 => { + ------------------ + | Branch (LL:20): [True: 1, False: 0] + ------------------ LL| 1| println!("is nonzero and odd, but divisible by 3"); LL| 1| } LL| 0| _ => { diff --git a/tests/coverage/branch_guard.rs b/tests/coverage/branch_guard.rs index a7cb389227e81..fa049e6206dc5 100644 --- a/tests/coverage/branch_guard.rs +++ b/tests/coverage/branch_guard.rs @@ -1,6 +1,6 @@ #![feature(coverage_attribute)] //@ edition: 2021 - +//@ compile-flags: -Zcoverage-options=branch //@ llvm-cov-flags: --show-branches=count macro_rules! no_merge { diff --git a/tests/coverage/branch_if.cov-map b/tests/coverage/branch_if.cov-map index 6fb5ef767148f..0dbfd92541b03 100644 --- a/tests/coverage/branch_if.cov-map +++ b/tests/coverage/branch_if.cov-map @@ -1,121 +1,167 @@ Function name: branch_if::branch_and -Raw bytes (40): 0x[01, 01, 03, 06, 0d, 05, 09, 11, 03, 06, 01, 2b, 01, 01, 10, 05, 03, 08, 00, 09, 09, 00, 0d, 00, 0e, 11, 00, 0f, 02, 06, 03, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Raw bytes (56): 0x[01, 01, 04, 05, 09, 0d, 02, 11, 0f, 0d, 02, 08, 01, 2b, 01, 01, 10, 05, 03, 08, 00, 09, 20, 09, 02, 00, 08, 00, 09, 09, 00, 0d, 00, 0e, 20, 11, 0d, 00, 0d, 00, 0e, 11, 00, 0f, 02, 06, 0f, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 3 -- expression 0 operands: lhs = Expression(1, Sub), rhs = Counter(3) -- expression 1 operands: lhs = Counter(1), rhs = Counter(2) -- expression 2 operands: lhs = Counter(4), rhs = Expression(0, Add) -Number of file 0 mappings: 6 +Number of expressions: 4 +- expression 0 operands: lhs = Counter(1), rhs = Counter(2) +- expression 1 operands: lhs = Counter(3), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Counter(4), rhs = Expression(3, Add) +- expression 3 operands: lhs = Counter(3), rhs = Expression(0, Sub) +Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 43, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 3, 8) to (start + 0, 9) +- Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) + true = c2 + false = (c1 - c2) - Code(Counter(2)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(4), false: Counter(3) } at (prev + 0, 13) to (start + 0, 14) + true = c4 + false = c3 - Code(Counter(4)) at (prev + 0, 15) to (start + 2, 6) -- Code(Expression(0, Add)) at (prev + 2, 12) to (start + 2, 6) - = ((c1 - c2) + c3) +- Code(Expression(3, Add)) at (prev + 2, 12) to (start + 2, 6) + = (c3 + (c1 - c2)) - Code(Expression(2, Add)) at (prev + 3, 1) to (start + 0, 2) - = (c4 + ((c1 - c2) + c3)) + = (c4 + (c3 + (c1 - c2))) Function name: branch_if::branch_not -Raw bytes (132): 0x[01, 01, 1d, 05, 09, 09, 02, 73, 0d, 09, 02, 0d, 6e, 73, 0d, 09, 02, 6b, 11, 0d, 6e, 73, 0d, 09, 02, 11, 66, 6b, 11, 0d, 6e, 73, 0d, 09, 02, 63, 15, 11, 66, 6b, 11, 0d, 6e, 73, 0d, 09, 02, 15, 5e, 63, 15, 11, 66, 6b, 11, 0d, 6e, 73, 0d, 09, 02, 0e, 01, 0c, 01, 01, 10, 05, 03, 08, 00, 09, 09, 01, 09, 00, 11, 02, 01, 06, 00, 07, 73, 01, 08, 00, 0a, 6e, 00, 0b, 02, 06, 0d, 02, 06, 00, 07, 6b, 01, 08, 00, 0b, 11, 00, 0c, 02, 06, 66, 02, 06, 00, 07, 63, 01, 08, 00, 0c, 5e, 00, 0d, 02, 06, 15, 02, 06, 00, 07, 5b, 01, 01, 00, 02] +Raw bytes (224): 0x[01, 01, 29, 05, 09, 09, 02, a3, 01, 0d, 09, 02, a3, 01, 0d, 09, 02, 0d, 9e, 01, a3, 01, 0d, 09, 02, 9b, 01, 11, 0d, 9e, 01, a3, 01, 0d, 09, 02, 9b, 01, 11, 0d, 9e, 01, a3, 01, 0d, 09, 02, 11, 96, 01, 9b, 01, 11, 0d, 9e, 01, a3, 01, 0d, 09, 02, 93, 01, 15, 11, 96, 01, 9b, 01, 11, 0d, 9e, 01, a3, 01, 0d, 09, 02, 93, 01, 15, 11, 96, 01, 9b, 01, 11, 0d, 9e, 01, a3, 01, 0d, 09, 02, 15, 8e, 01, 93, 01, 15, 11, 96, 01, 9b, 01, 11, 0d, 9e, 01, a3, 01, 0d, 09, 02, 12, 01, 0c, 01, 01, 10, 05, 03, 08, 00, 09, 20, 09, 02, 00, 08, 00, 09, 09, 01, 09, 00, 11, 02, 01, 06, 00, 07, a3, 01, 01, 08, 00, 0a, 20, 9e, 01, 0d, 00, 08, 00, 0a, 9e, 01, 00, 0b, 02, 06, 0d, 02, 06, 00, 07, 9b, 01, 01, 08, 00, 0b, 20, 11, 96, 01, 00, 08, 00, 0b, 11, 00, 0c, 02, 06, 96, 01, 02, 06, 00, 07, 93, 01, 01, 08, 00, 0c, 20, 8e, 01, 15, 00, 08, 00, 0c, 8e, 01, 00, 0d, 02, 06, 15, 02, 06, 00, 07, 8b, 01, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 29 +Number of expressions: 41 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) - expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub) -- expression 2 operands: lhs = Expression(28, Add), rhs = Counter(3) +- expression 2 operands: lhs = Expression(40, Add), rhs = Counter(3) - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) -- expression 4 operands: lhs = Counter(3), rhs = Expression(27, Sub) -- expression 5 operands: lhs = Expression(28, Add), rhs = Counter(3) -- expression 6 operands: lhs = Counter(2), rhs = Expression(0, Sub) -- expression 7 operands: lhs = Expression(26, Add), rhs = Counter(4) -- expression 8 operands: lhs = Counter(3), rhs = Expression(27, Sub) -- expression 9 operands: lhs = Expression(28, Add), rhs = Counter(3) -- expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub) -- expression 11 operands: lhs = Counter(4), rhs = Expression(25, Sub) -- expression 12 operands: lhs = Expression(26, Add), rhs = Counter(4) -- expression 13 operands: lhs = Counter(3), rhs = Expression(27, Sub) -- expression 14 operands: lhs = Expression(28, Add), rhs = Counter(3) -- expression 15 operands: lhs = Counter(2), rhs = Expression(0, Sub) -- expression 16 operands: lhs = Expression(24, Add), rhs = Counter(5) -- expression 17 operands: lhs = Counter(4), rhs = Expression(25, Sub) -- expression 18 operands: lhs = Expression(26, Add), rhs = Counter(4) -- expression 19 operands: lhs = Counter(3), rhs = Expression(27, Sub) -- expression 20 operands: lhs = Expression(28, Add), rhs = Counter(3) +- expression 4 operands: lhs = Expression(40, Add), rhs = Counter(3) +- expression 5 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 6 operands: lhs = Counter(3), rhs = Expression(39, Sub) +- expression 7 operands: lhs = Expression(40, Add), rhs = Counter(3) +- expression 8 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 9 operands: lhs = Expression(38, Add), rhs = Counter(4) +- expression 10 operands: lhs = Counter(3), rhs = Expression(39, Sub) +- expression 11 operands: lhs = Expression(40, Add), rhs = Counter(3) +- expression 12 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 13 operands: lhs = Expression(38, Add), rhs = Counter(4) +- expression 14 operands: lhs = Counter(3), rhs = Expression(39, Sub) +- expression 15 operands: lhs = Expression(40, Add), rhs = Counter(3) +- expression 16 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 17 operands: lhs = Counter(4), rhs = Expression(37, Sub) +- expression 18 operands: lhs = Expression(38, Add), rhs = Counter(4) +- expression 19 operands: lhs = Counter(3), rhs = Expression(39, Sub) +- expression 20 operands: lhs = Expression(40, Add), rhs = Counter(3) - expression 21 operands: lhs = Counter(2), rhs = Expression(0, Sub) -- expression 22 operands: lhs = Counter(5), rhs = Expression(23, Sub) -- expression 23 operands: lhs = Expression(24, Add), rhs = Counter(5) -- expression 24 operands: lhs = Counter(4), rhs = Expression(25, Sub) -- expression 25 operands: lhs = Expression(26, Add), rhs = Counter(4) -- expression 26 operands: lhs = Counter(3), rhs = Expression(27, Sub) -- expression 27 operands: lhs = Expression(28, Add), rhs = Counter(3) -- expression 28 operands: lhs = Counter(2), rhs = Expression(0, Sub) -Number of file 0 mappings: 14 +- expression 22 operands: lhs = Expression(36, Add), rhs = Counter(5) +- expression 23 operands: lhs = Counter(4), rhs = Expression(37, Sub) +- expression 24 operands: lhs = Expression(38, Add), rhs = Counter(4) +- expression 25 operands: lhs = Counter(3), rhs = Expression(39, Sub) +- expression 26 operands: lhs = Expression(40, Add), rhs = Counter(3) +- expression 27 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 28 operands: lhs = Expression(36, Add), rhs = Counter(5) +- expression 29 operands: lhs = Counter(4), rhs = Expression(37, Sub) +- expression 30 operands: lhs = Expression(38, Add), rhs = Counter(4) +- expression 31 operands: lhs = Counter(3), rhs = Expression(39, Sub) +- expression 32 operands: lhs = Expression(40, Add), rhs = Counter(3) +- expression 33 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 34 operands: lhs = Counter(5), rhs = Expression(35, Sub) +- expression 35 operands: lhs = Expression(36, Add), rhs = Counter(5) +- expression 36 operands: lhs = Counter(4), rhs = Expression(37, Sub) +- expression 37 operands: lhs = Expression(38, Add), rhs = Counter(4) +- expression 38 operands: lhs = Counter(3), rhs = Expression(39, Sub) +- expression 39 operands: lhs = Expression(40, Add), rhs = Counter(3) +- expression 40 operands: lhs = Counter(2), rhs = Expression(0, Sub) +Number of file 0 mappings: 18 - Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 3, 8) to (start + 0, 9) +- Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) + true = c2 + false = (c1 - c2) - Code(Counter(2)) at (prev + 1, 9) to (start + 0, 17) - Code(Expression(0, Sub)) at (prev + 1, 6) to (start + 0, 7) = (c1 - c2) -- Code(Expression(28, Add)) at (prev + 1, 8) to (start + 0, 10) +- Code(Expression(40, Add)) at (prev + 1, 8) to (start + 0, 10) = (c2 + (c1 - c2)) -- Code(Expression(27, Sub)) at (prev + 0, 11) to (start + 2, 6) +- Branch { true: Expression(39, Sub), false: Counter(3) } at (prev + 0, 8) to (start + 0, 10) + true = ((c2 + (c1 - c2)) - c3) + false = c3 +- Code(Expression(39, Sub)) at (prev + 0, 11) to (start + 2, 6) = ((c2 + (c1 - c2)) - c3) - Code(Counter(3)) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(26, Add)) at (prev + 1, 8) to (start + 0, 11) +- Code(Expression(38, Add)) at (prev + 1, 8) to (start + 0, 11) = (c3 + ((c2 + (c1 - c2)) - c3)) +- Branch { true: Counter(4), false: Expression(37, Sub) } at (prev + 0, 8) to (start + 0, 11) + true = c4 + false = ((c3 + ((c2 + (c1 - c2)) - c3)) - c4) - Code(Counter(4)) at (prev + 0, 12) to (start + 2, 6) -- Code(Expression(25, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(37, Sub)) at (prev + 2, 6) to (start + 0, 7) = ((c3 + ((c2 + (c1 - c2)) - c3)) - c4) -- Code(Expression(24, Add)) at (prev + 1, 8) to (start + 0, 12) +- Code(Expression(36, Add)) at (prev + 1, 8) to (start + 0, 12) = (c4 + ((c3 + ((c2 + (c1 - c2)) - c3)) - c4)) -- Code(Expression(23, Sub)) at (prev + 0, 13) to (start + 2, 6) +- Branch { true: Expression(35, Sub), false: Counter(5) } at (prev + 0, 8) to (start + 0, 12) + true = ((c4 + ((c3 + ((c2 + (c1 - c2)) - c3)) - c4)) - c5) + false = c5 +- Code(Expression(35, Sub)) at (prev + 0, 13) to (start + 2, 6) = ((c4 + ((c3 + ((c2 + (c1 - c2)) - c3)) - c4)) - c5) - Code(Counter(5)) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(22, Add)) at (prev + 1, 1) to (start + 0, 2) +- Code(Expression(34, Add)) at (prev + 1, 1) to (start + 0, 2) = (c5 + ((c4 + ((c3 + ((c2 + (c1 - c2)) - c3)) - c4)) - c5)) Function name: branch_if::branch_not_as -Raw bytes (91): 0x[01, 01, 10, 05, 09, 09, 02, 3f, 0d, 09, 02, 0d, 3a, 3f, 0d, 09, 02, 37, 11, 0d, 3a, 3f, 0d, 09, 02, 11, 32, 37, 11, 0d, 3a, 3f, 0d, 09, 02, 0b, 01, 1d, 01, 01, 10, 05, 03, 08, 00, 14, 02, 00, 15, 02, 06, 09, 02, 06, 00, 07, 3f, 01, 08, 00, 15, 0d, 00, 16, 02, 06, 3a, 02, 06, 00, 07, 37, 01, 08, 00, 16, 32, 00, 17, 02, 06, 11, 02, 06, 00, 07, 2f, 01, 01, 00, 02] +Raw bytes (124): 0x[01, 01, 16, 05, 09, 09, 02, 57, 0d, 09, 02, 57, 0d, 09, 02, 0d, 52, 57, 0d, 09, 02, 4f, 11, 0d, 52, 57, 0d, 09, 02, 4f, 11, 0d, 52, 57, 0d, 09, 02, 11, 4a, 4f, 11, 0d, 52, 57, 0d, 09, 02, 0e, 01, 1d, 01, 01, 10, 05, 03, 08, 00, 14, 20, 02, 09, 00, 08, 00, 14, 02, 00, 15, 02, 06, 09, 02, 06, 00, 07, 57, 01, 08, 00, 15, 20, 0d, 52, 00, 08, 00, 15, 0d, 00, 16, 02, 06, 52, 02, 06, 00, 07, 4f, 01, 08, 00, 16, 20, 4a, 11, 00, 08, 00, 16, 4a, 00, 17, 02, 06, 11, 02, 06, 00, 07, 47, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 16 +Number of expressions: 22 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) - expression 1 operands: lhs = Counter(2), rhs = Expression(0, Sub) -- expression 2 operands: lhs = Expression(15, Add), rhs = Counter(3) +- expression 2 operands: lhs = Expression(21, Add), rhs = Counter(3) - expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub) -- expression 4 operands: lhs = Counter(3), rhs = Expression(14, Sub) -- expression 5 operands: lhs = Expression(15, Add), rhs = Counter(3) -- expression 6 operands: lhs = Counter(2), rhs = Expression(0, Sub) -- expression 7 operands: lhs = Expression(13, Add), rhs = Counter(4) -- expression 8 operands: lhs = Counter(3), rhs = Expression(14, Sub) -- expression 9 operands: lhs = Expression(15, Add), rhs = Counter(3) -- expression 10 operands: lhs = Counter(2), rhs = Expression(0, Sub) -- expression 11 operands: lhs = Counter(4), rhs = Expression(12, Sub) -- expression 12 operands: lhs = Expression(13, Add), rhs = Counter(4) -- expression 13 operands: lhs = Counter(3), rhs = Expression(14, Sub) -- expression 14 operands: lhs = Expression(15, Add), rhs = Counter(3) -- expression 15 operands: lhs = Counter(2), rhs = Expression(0, Sub) -Number of file 0 mappings: 11 +- expression 4 operands: lhs = Expression(21, Add), rhs = Counter(3) +- expression 5 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 6 operands: lhs = Counter(3), rhs = Expression(20, Sub) +- expression 7 operands: lhs = Expression(21, Add), rhs = Counter(3) +- expression 8 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 9 operands: lhs = Expression(19, Add), rhs = Counter(4) +- expression 10 operands: lhs = Counter(3), rhs = Expression(20, Sub) +- expression 11 operands: lhs = Expression(21, Add), rhs = Counter(3) +- expression 12 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 13 operands: lhs = Expression(19, Add), rhs = Counter(4) +- expression 14 operands: lhs = Counter(3), rhs = Expression(20, Sub) +- expression 15 operands: lhs = Expression(21, Add), rhs = Counter(3) +- expression 16 operands: lhs = Counter(2), rhs = Expression(0, Sub) +- expression 17 operands: lhs = Counter(4), rhs = Expression(18, Sub) +- expression 18 operands: lhs = Expression(19, Add), rhs = Counter(4) +- expression 19 operands: lhs = Counter(3), rhs = Expression(20, Sub) +- expression 20 operands: lhs = Expression(21, Add), rhs = Counter(3) +- expression 21 operands: lhs = Counter(2), rhs = Expression(0, Sub) +Number of file 0 mappings: 14 - Code(Counter(0)) at (prev + 29, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 3, 8) to (start + 0, 20) +- Branch { true: Expression(0, Sub), false: Counter(2) } at (prev + 0, 8) to (start + 0, 20) + true = (c1 - c2) + false = c2 - Code(Expression(0, Sub)) at (prev + 0, 21) to (start + 2, 6) = (c1 - c2) - Code(Counter(2)) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(15, Add)) at (prev + 1, 8) to (start + 0, 21) +- Code(Expression(21, Add)) at (prev + 1, 8) to (start + 0, 21) = (c2 + (c1 - c2)) +- Branch { true: Counter(3), false: Expression(20, Sub) } at (prev + 0, 8) to (start + 0, 21) + true = c3 + false = ((c2 + (c1 - c2)) - c3) - Code(Counter(3)) at (prev + 0, 22) to (start + 2, 6) -- Code(Expression(14, Sub)) at (prev + 2, 6) to (start + 0, 7) +- Code(Expression(20, Sub)) at (prev + 2, 6) to (start + 0, 7) = ((c2 + (c1 - c2)) - c3) -- Code(Expression(13, Add)) at (prev + 1, 8) to (start + 0, 22) +- Code(Expression(19, Add)) at (prev + 1, 8) to (start + 0, 22) = (c3 + ((c2 + (c1 - c2)) - c3)) -- Code(Expression(12, Sub)) at (prev + 0, 23) to (start + 2, 6) +- Branch { true: Expression(18, Sub), false: Counter(4) } at (prev + 0, 8) to (start + 0, 22) + true = ((c3 + ((c2 + (c1 - c2)) - c3)) - c4) + false = c4 +- Code(Expression(18, Sub)) at (prev + 0, 23) to (start + 2, 6) = ((c3 + ((c2 + (c1 - c2)) - c3)) - c4) - Code(Counter(4)) at (prev + 2, 6) to (start + 0, 7) -- Code(Expression(11, Add)) at (prev + 1, 1) to (start + 0, 2) +- Code(Expression(17, Add)) at (prev + 1, 1) to (start + 0, 2) = (c4 + ((c3 + ((c2 + (c1 - c2)) - c3)) - c4)) Function name: branch_if::branch_or -Raw bytes (42): 0x[01, 01, 04, 05, 09, 09, 0d, 0f, 11, 09, 0d, 06, 01, 35, 01, 01, 10, 05, 03, 08, 00, 09, 02, 00, 0d, 00, 0e, 0f, 00, 0f, 02, 06, 11, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] +Raw bytes (56): 0x[01, 01, 04, 05, 09, 09, 0d, 0f, 11, 09, 0d, 08, 01, 35, 01, 01, 10, 05, 03, 08, 00, 09, 20, 09, 02, 00, 08, 00, 09, 02, 00, 0d, 00, 0e, 20, 0d, 11, 00, 0d, 00, 0e, 0f, 00, 0f, 02, 06, 11, 02, 0c, 02, 06, 0b, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -123,11 +169,17 @@ Number of expressions: 4 - expression 1 operands: lhs = Counter(2), rhs = Counter(3) - expression 2 operands: lhs = Expression(3, Add), rhs = Counter(4) - expression 3 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 6 +Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 53, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 3, 8) to (start + 0, 9) +- Branch { true: Counter(2), false: Expression(0, Sub) } at (prev + 0, 8) to (start + 0, 9) + true = c2 + false = (c1 - c2) - Code(Expression(0, Sub)) at (prev + 0, 13) to (start + 0, 14) = (c1 - c2) +- Branch { true: Counter(3), false: Counter(4) } at (prev + 0, 13) to (start + 0, 14) + true = c3 + false = c4 - Code(Expression(3, Add)) at (prev + 0, 15) to (start + 2, 6) = (c2 + c3) - Code(Counter(4)) at (prev + 2, 12) to (start + 2, 6) diff --git a/tests/coverage/branch_if.coverage b/tests/coverage/branch_if.coverage index babefb51d3f21..2a9a408b16aff 100644 --- a/tests/coverage/branch_if.coverage +++ b/tests/coverage/branch_if.coverage @@ -1,6 +1,6 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| | + LL| |//@ compile-flags: -Zcoverage-options=branch LL| |//@ llvm-cov-flags: --show-branches=count LL| | LL| |macro_rules! no_merge { @@ -13,16 +13,28 @@ LL| 3| no_merge!(); LL| | LL| 3| if a { + ------------------ + | Branch (LL:8): [True: 2, False: 1] + ------------------ LL| 2| say("a") LL| 1| } LL| 3| if !a { + ------------------ + | Branch (LL:8): [True: 1, False: 2] + ------------------ LL| 1| say("not a"); LL| 2| } LL| 3| if !!a { + ------------------ + | Branch (LL:8): [True: 2, False: 1] + ------------------ LL| 2| say("not not a"); LL| 2| } ^1 LL| 3| if !!!a { + ------------------ + | Branch (LL:8): [True: 1, False: 2] + ------------------ LL| 1| say("not not not a"); LL| 2| } LL| 3|} @@ -31,13 +43,22 @@ LL| 3| no_merge!(); LL| | LL| 3| if !(a as bool) { + ------------------ + | Branch (LL:8): [True: 1, False: 2] + ------------------ LL| 1| say("not (a as bool)"); LL| 2| } LL| 3| if !!(a as bool) { + ------------------ + | Branch (LL:8): [True: 2, False: 1] + ------------------ LL| 2| say("not not (a as bool)"); LL| 2| } ^1 LL| 3| if !!!(a as bool) { + ------------------ + | Branch (LL:8): [True: 1, False: 2] + ------------------ LL| 1| say("not not (a as bool)"); LL| 2| } LL| 3|} @@ -47,6 +68,10 @@ LL| | LL| 15| if a && b { ^12 + ------------------ + | Branch (LL:8): [True: 12, False: 3] + | Branch (LL:13): [True: 8, False: 4] + ------------------ LL| 8| say("both"); LL| 8| } else { LL| 7| say("not both"); @@ -58,6 +83,10 @@ LL| | LL| 15| if a || b { ^3 + ------------------ + | Branch (LL:8): [True: 12, False: 3] + | Branch (LL:13): [True: 2, False: 1] + ------------------ LL| 14| say("either"); LL| 14| } else { LL| 1| say("neither"); diff --git a/tests/coverage/branch_if.rs b/tests/coverage/branch_if.rs index 55ef159ebdfc5..151eede75bbc7 100644 --- a/tests/coverage/branch_if.rs +++ b/tests/coverage/branch_if.rs @@ -1,6 +1,6 @@ #![feature(coverage_attribute)] //@ edition: 2021 - +//@ compile-flags: -Zcoverage-options=branch //@ llvm-cov-flags: --show-branches=count macro_rules! no_merge { diff --git a/tests/coverage/branch_while.cov-map b/tests/coverage/branch_while.cov-map index 63a7c438163ea..d5f54f1abea20 100644 --- a/tests/coverage/branch_while.cov-map +++ b/tests/coverage/branch_while.cov-map @@ -1,74 +1,98 @@ Function name: branch_while::while_cond -Raw bytes (33): 0x[01, 01, 02, 05, 09, 03, 09, 05, 01, 0c, 01, 01, 10, 05, 03, 09, 00, 12, 03, 01, 0b, 00, 10, 09, 00, 11, 02, 06, 06, 03, 01, 00, 02] +Raw bytes (42): 0x[01, 01, 03, 05, 09, 03, 09, 03, 09, 06, 01, 0c, 01, 01, 10, 05, 03, 09, 00, 12, 03, 01, 0b, 00, 10, 20, 09, 0a, 00, 0b, 00, 10, 09, 00, 11, 02, 06, 0a, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 2 +Number of expressions: 3 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) - expression 1 operands: lhs = Expression(0, Add), rhs = Counter(2) -Number of file 0 mappings: 5 +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(2) +Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 12, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 3, 9) to (start + 0, 18) - Code(Expression(0, Add)) at (prev + 1, 11) to (start + 0, 16) = (c1 + c2) +- Branch { true: Counter(2), false: Expression(2, Sub) } at (prev + 0, 11) to (start + 0, 16) + true = c2 + false = ((c1 + c2) - c2) - Code(Counter(2)) at (prev + 0, 17) to (start + 2, 6) -- Code(Expression(1, Sub)) at (prev + 3, 1) to (start + 0, 2) +- Code(Expression(2, Sub)) at (prev + 3, 1) to (start + 0, 2) = ((c1 + c2) - c2) Function name: branch_while::while_cond_not -Raw bytes (33): 0x[01, 01, 02, 05, 09, 03, 09, 05, 01, 15, 01, 01, 10, 05, 03, 09, 00, 12, 03, 01, 0b, 00, 14, 09, 00, 15, 02, 06, 06, 03, 01, 00, 02] +Raw bytes (42): 0x[01, 01, 03, 05, 09, 03, 09, 03, 09, 06, 01, 15, 01, 01, 10, 05, 03, 09, 00, 12, 03, 01, 0b, 00, 14, 20, 09, 0a, 00, 0b, 00, 14, 09, 00, 15, 02, 06, 0a, 03, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 2 +Number of expressions: 3 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) - expression 1 operands: lhs = Expression(0, Add), rhs = Counter(2) -Number of file 0 mappings: 5 +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(2) +Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 21, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 3, 9) to (start + 0, 18) - Code(Expression(0, Add)) at (prev + 1, 11) to (start + 0, 20) = (c1 + c2) +- Branch { true: Counter(2), false: Expression(2, Sub) } at (prev + 0, 11) to (start + 0, 20) + true = c2 + false = ((c1 + c2) - c2) - Code(Counter(2)) at (prev + 0, 21) to (start + 2, 6) -- Code(Expression(1, Sub)) at (prev + 3, 1) to (start + 0, 2) +- Code(Expression(2, Sub)) at (prev + 3, 1) to (start + 0, 2) = ((c1 + c2) - c2) Function name: branch_while::while_op_and -Raw bytes (40): 0x[01, 01, 03, 05, 09, 03, 0d, 11, 0d, 06, 01, 1e, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 06, 00, 14, 00, 19, 09, 00, 1a, 03, 06, 0b, 04, 01, 00, 02] +Raw bytes (56): 0x[01, 01, 04, 05, 09, 03, 0d, 03, 0d, 11, 0d, 08, 01, 1e, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 20, 0a, 0d, 00, 0b, 00, 10, 0a, 00, 14, 00, 19, 20, 09, 11, 00, 14, 00, 19, 09, 00, 1a, 03, 06, 0f, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 3 +Number of expressions: 4 - expression 0 operands: lhs = Counter(1), rhs = Counter(2) - expression 1 operands: lhs = Expression(0, Add), rhs = Counter(3) -- expression 2 operands: lhs = Counter(4), rhs = Counter(3) -Number of file 0 mappings: 6 +- expression 2 operands: lhs = Expression(0, Add), rhs = Counter(3) +- expression 3 operands: lhs = Counter(4), rhs = Counter(3) +Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 30, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 3, 9) to (start + 1, 18) - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 16) = (c1 + c2) -- Code(Expression(1, Sub)) at (prev + 0, 20) to (start + 0, 25) +- Branch { true: Expression(2, Sub), false: Counter(3) } at (prev + 0, 11) to (start + 0, 16) + true = ((c1 + c2) - c3) + false = c3 +- Code(Expression(2, Sub)) at (prev + 0, 20) to (start + 0, 25) = ((c1 + c2) - c3) +- Branch { true: Counter(2), false: Counter(4) } at (prev + 0, 20) to (start + 0, 25) + true = c2 + false = c4 - Code(Counter(2)) at (prev + 0, 26) to (start + 3, 6) -- Code(Expression(2, Add)) at (prev + 4, 1) to (start + 0, 2) +- Code(Expression(3, Add)) at (prev + 4, 1) to (start + 0, 2) = (c4 + c3) Function name: branch_while::while_op_or -Raw bytes (46): 0x[01, 01, 06, 05, 0f, 09, 0d, 03, 09, 09, 0d, 16, 0d, 03, 09, 06, 01, 29, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 16, 00, 14, 00, 19, 0f, 00, 1a, 03, 06, 12, 04, 01, 00, 02] +Raw bytes (66): 0x[01, 01, 09, 05, 1b, 09, 0d, 03, 09, 03, 09, 22, 0d, 03, 09, 09, 0d, 22, 0d, 03, 09, 08, 01, 29, 01, 01, 10, 05, 03, 09, 01, 12, 03, 02, 0b, 00, 10, 20, 09, 22, 00, 0b, 00, 10, 22, 00, 14, 00, 19, 20, 0d, 1e, 00, 14, 00, 19, 1b, 00, 1a, 03, 06, 1e, 04, 01, 00, 02] Number of files: 1 - file 0 => global file 1 -Number of expressions: 6 -- expression 0 operands: lhs = Counter(1), rhs = Expression(3, Add) +Number of expressions: 9 +- expression 0 operands: lhs = Counter(1), rhs = Expression(6, Add) - expression 1 operands: lhs = Counter(2), rhs = Counter(3) - expression 2 operands: lhs = Expression(0, Add), rhs = Counter(2) -- expression 3 operands: lhs = Counter(2), rhs = Counter(3) -- expression 4 operands: lhs = Expression(5, Sub), rhs = Counter(3) +- expression 3 operands: lhs = Expression(0, Add), rhs = Counter(2) +- expression 4 operands: lhs = Expression(8, Sub), rhs = Counter(3) - expression 5 operands: lhs = Expression(0, Add), rhs = Counter(2) -Number of file 0 mappings: 6 +- expression 6 operands: lhs = Counter(2), rhs = Counter(3) +- expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(3) +- expression 8 operands: lhs = Expression(0, Add), rhs = Counter(2) +Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 41, 1) to (start + 1, 16) - Code(Counter(1)) at (prev + 3, 9) to (start + 1, 18) - Code(Expression(0, Add)) at (prev + 2, 11) to (start + 0, 16) = (c1 + (c2 + c3)) -- Code(Expression(5, Sub)) at (prev + 0, 20) to (start + 0, 25) +- Branch { true: Counter(2), false: Expression(8, Sub) } at (prev + 0, 11) to (start + 0, 16) + true = c2 + false = ((c1 + (c2 + c3)) - c2) +- Code(Expression(8, Sub)) at (prev + 0, 20) to (start + 0, 25) = ((c1 + (c2 + c3)) - c2) -- Code(Expression(3, Add)) at (prev + 0, 26) to (start + 3, 6) +- Branch { true: Counter(3), false: Expression(7, Sub) } at (prev + 0, 20) to (start + 0, 25) + true = c3 + false = (((c1 + (c2 + c3)) - c2) - c3) +- Code(Expression(6, Add)) at (prev + 0, 26) to (start + 3, 6) = (c2 + c3) -- Code(Expression(4, Sub)) at (prev + 4, 1) to (start + 0, 2) +- Code(Expression(7, Sub)) at (prev + 4, 1) to (start + 0, 2) = (((c1 + (c2 + c3)) - c2) - c3) diff --git a/tests/coverage/branch_while.coverage b/tests/coverage/branch_while.coverage index d2351a7de09a2..8d9a6c3bc68b7 100644 --- a/tests/coverage/branch_while.coverage +++ b/tests/coverage/branch_while.coverage @@ -1,6 +1,6 @@ LL| |#![feature(coverage_attribute)] LL| |//@ edition: 2021 - LL| | + LL| |//@ compile-flags: -Zcoverage-options=branch LL| |//@ llvm-cov-flags: --show-branches=count LL| | LL| |macro_rules! no_merge { @@ -14,6 +14,9 @@ LL| | LL| 1| let mut a = 8; LL| 9| while a > 0 { + ------------------ + | Branch (LL:11): [True: 8, False: 1] + ------------------ LL| 8| a -= 1; LL| 8| } LL| 1|} @@ -23,6 +26,9 @@ LL| | LL| 1| let mut a = 8; LL| 9| while !(a == 0) { + ------------------ + | Branch (LL:11): [True: 8, False: 1] + ------------------ LL| 8| a -= 1; LL| 8| } LL| 1|} @@ -33,6 +39,10 @@ LL| 1| let mut a = 8; LL| 1| let mut b = 4; LL| 5| while a > 0 && b > 0 { + ------------------ + | Branch (LL:11): [True: 5, False: 0] + | Branch (LL:20): [True: 4, False: 1] + ------------------ LL| 4| a -= 1; LL| 4| b -= 1; LL| 4| } @@ -45,6 +55,10 @@ LL| 1| let mut b = 8; LL| 9| while a > 0 || b > 0 { ^5 + ------------------ + | Branch (LL:11): [True: 4, False: 5] + | Branch (LL:20): [True: 4, False: 1] + ------------------ LL| 8| a -= 1; LL| 8| b -= 1; LL| 8| } diff --git a/tests/coverage/branch_while.rs b/tests/coverage/branch_while.rs index 99e9a798eff5f..507815fbecbeb 100644 --- a/tests/coverage/branch_while.rs +++ b/tests/coverage/branch_while.rs @@ -1,6 +1,6 @@ #![feature(coverage_attribute)] //@ edition: 2021 - +//@ compile-flags: -Zcoverage-options=branch //@ llvm-cov-flags: --show-branches=count macro_rules! no_merge { From 060c7ce7e9e09c463352a1cabd3ea1d7264deef2 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 13 Mar 2024 20:53:10 +1100 Subject: [PATCH 18/23] coverage: `-Zcoverage-options=branch` is no longer a placeholder --- compiler/rustc_session/src/config.rs | 2 +- src/doc/rustc/src/instrument-coverage.md | 2 +- src/doc/unstable-book/src/compiler-flags/coverage-options.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 5c52ee66128c9..b7ee2c9802541 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -146,7 +146,7 @@ pub enum InstrumentCoverage { /// Individual flag values controlled by `-Z coverage-options`. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] pub struct CoverageOptions { - /// Add branch coverage instrumentation (placeholder flag; not yet implemented). + /// Add branch coverage instrumentation. pub branch: bool, } diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md index 7780f2102ba6b..185a3ba5dbd41 100644 --- a/src/doc/rustc/src/instrument-coverage.md +++ b/src/doc/rustc/src/instrument-coverage.md @@ -352,7 +352,7 @@ This unstable option provides finer control over some aspects of coverage instrumentation. Pass one or more of the following values, separated by commas. - `branch` or `no-branch` - - Placeholder for potential branch coverage support in the future. + - Enables or disables branch coverage instrumentation. ## Other references diff --git a/src/doc/unstable-book/src/compiler-flags/coverage-options.md b/src/doc/unstable-book/src/compiler-flags/coverage-options.md index 105dce6151178..450573cc6c746 100644 --- a/src/doc/unstable-book/src/compiler-flags/coverage-options.md +++ b/src/doc/unstable-book/src/compiler-flags/coverage-options.md @@ -5,4 +5,4 @@ This option controls details of the coverage instrumentation performed by Multiple options can be passed, separated by commas. Valid options are: -- `branch` or `no-branch`: Placeholder for future branch coverage support. +- `branch` or `no-branch`: Enables or disables branch coverage instrumentation. From ca9f0630a93a12abb9a4a35f3bb1948c54515c2d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 14 Mar 2024 11:25:05 +0100 Subject: [PATCH 19/23] Rename `ast::StmtKind::Local` into `ast::StmtKind::Let` --- compiler/rustc_ast/src/ast.rs | 2 +- compiler/rustc_ast/src/ast_traits.rs | 8 ++++---- compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/block.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- compiler/rustc_expand/src/build.rs | 2 +- compiler/rustc_expand/src/expand.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/unused.rs | 4 ++-- compiler/rustc_parse/src/parser/stmt.rs | 8 ++++---- compiler/rustc_passes/src/hir_stats.rs | 2 +- src/tools/clippy/clippy_utils/src/ast_utils.rs | 2 +- src/tools/rustfmt/src/attr.rs | 2 +- src/tools/rustfmt/src/spanned.rs | 2 +- src/tools/rustfmt/src/stmt.rs | 2 +- src/tools/rustfmt/src/visitor.rs | 2 +- 17 files changed, 24 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index d522c285e3ebe..d0e8b86b71d3b 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1021,7 +1021,7 @@ impl Stmt { #[derive(Clone, Encodable, Decodable, Debug)] pub enum StmtKind { /// A local (let) binding. - Local(P), + Let(P), /// An item definition. Item(P), /// Expr without trailing semi-colon. diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs index 4dc9c30a2c807..a0486227f2afb 100644 --- a/compiler/rustc_ast/src/ast_traits.rs +++ b/compiler/rustc_ast/src/ast_traits.rs @@ -182,7 +182,7 @@ impl HasTokens for Option { impl HasTokens for StmtKind { fn tokens(&self) -> Option<&LazyAttrTokenStream> { match self { - StmtKind::Local(local) => local.tokens.as_ref(), + StmtKind::Let(local) => local.tokens.as_ref(), StmtKind::Item(item) => item.tokens(), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens(), StmtKind::Empty => return None, @@ -191,7 +191,7 @@ impl HasTokens for StmtKind { } fn tokens_mut(&mut self) -> Option<&mut Option> { match self { - StmtKind::Local(local) => Some(&mut local.tokens), + StmtKind::Let(local) => Some(&mut local.tokens), StmtKind::Item(item) => item.tokens_mut(), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.tokens_mut(), StmtKind::Empty => return None, @@ -355,7 +355,7 @@ impl HasAttrs for StmtKind { fn attrs(&self) -> &[Attribute] { match self { - StmtKind::Local(local) => &local.attrs, + StmtKind::Let(local) => &local.attrs, StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.attrs(), StmtKind::Item(item) => item.attrs(), StmtKind::Empty => &[], @@ -365,7 +365,7 @@ impl HasAttrs for StmtKind { fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) { match self { - StmtKind::Local(local) => f(&mut local.attrs), + StmtKind::Let(local) => f(&mut local.attrs), StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f), StmtKind::Item(item) => item.visit_attrs(f), StmtKind::Empty => {} diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 9ec92c9d4edfe..83468c5f10122 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -1567,7 +1567,7 @@ pub fn noop_flat_map_stmt_kind( vis: &mut T, ) -> SmallVec<[StmtKind; 1]> { match kind { - StmtKind::Local(mut local) => smallvec![StmtKind::Local({ + StmtKind::Let(mut local) => smallvec![StmtKind::Let({ vis.visit_local(&mut local); local })], diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 7296e29301f35..d75ff4565e6f0 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -787,7 +787,7 @@ pub fn walk_block<'a, V: Visitor<'a>>(visitor: &mut V, block: &'a Block) -> V::R pub fn walk_stmt<'a, V: Visitor<'a>>(visitor: &mut V, statement: &'a Stmt) -> V::Result { match &statement.kind { - StmtKind::Local(local) => try_visit!(visitor.visit_local(local)), + StmtKind::Let(local) => try_visit!(visitor.visit_local(local)), StmtKind::Item(item) => try_visit!(visitor.visit_item(item)), StmtKind::Expr(expr) | StmtKind::Semi(expr) => try_visit!(visitor.visit_expr(expr)), StmtKind::Empty => {} diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 865a56b2c1f15..5f60fbe567071 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -32,7 +32,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let mut expr = None; while let [s, tail @ ..] = ast_stmts { match &s.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { let hir_id = self.lower_node_id(s.id); let local = self.lower_local(local); self.alias_attrs(hir_id, local.hir_id); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index e5d7b8489033a..c50878e32a460 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1212,7 +1212,7 @@ impl<'a> State<'a> { fn print_stmt(&mut self, st: &ast::Stmt) { self.maybe_print_comment(st.span.lo()); match &st.kind { - ast::StmtKind::Local(loc) => { + ast::StmtKind::Let(loc) => { self.print_outer_attributes(&loc.attrs); self.space_if_not_bol(); self.ibox(INDENT_UNIT); diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 989b7b485c992..e71047f94fa9a 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -218,7 +218,7 @@ impl<'a> ExtCtxt<'a> { } pub fn stmt_local(&self, local: P, span: Span) -> ast::Stmt { - ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Local(local), span } + ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Let(local), span } } pub fn stmt_item(&self, sp: Span, item: P) -> ast::Stmt { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 3544a8f0a8d92..cac1e8f80e323 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -1389,7 +1389,7 @@ impl InvocationCollectorNode for ast::Stmt { StmtKind::Item(item) => matches!(item.kind, ItemKind::MacCall(..)), StmtKind::Semi(expr) => matches!(expr.kind, ExprKind::MacCall(..)), StmtKind::Expr(..) => unreachable!(), - StmtKind::Local(..) | StmtKind::Empty => false, + StmtKind::Let(..) | StmtKind::Empty => false, } } fn take_mac_call(self) -> (P, Self::AttrsTy, AddSemicolon) { diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 595dc08b081ed..d1343e3b4bae8 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -989,7 +989,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: & impl EarlyLintPass for UnusedDocComment { fn check_stmt(&mut self, cx: &EarlyContext<'_>, stmt: &ast::Stmt) { let kind = match stmt.kind { - ast::StmtKind::Local(..) => "statements", + ast::StmtKind::Let(..) => "statements", // Disabled pending discussion in #78306 ast::StmtKind::Item(..) => return, // expressions will be reported by `check_expr`. diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index f84d1c6c2d0aa..3e10879e2411a 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -914,7 +914,7 @@ trait UnusedDelimLint { fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { match s.kind { - StmtKind::Local(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => { + StmtKind::Let(ref local) if Self::LINT_EXPR_IN_PATTERN_MATCHING_CTX => { if let Some((init, els)) = local.kind.init_else_opt() { let ctx = match els { None => UnusedDelimsCtx::AssignedValue, @@ -1189,7 +1189,7 @@ impl EarlyLintPass for UnusedParens { } fn check_stmt(&mut self, cx: &EarlyContext<'_>, s: &ast::Stmt) { - if let StmtKind::Local(ref local) = s.kind { + if let StmtKind::Let(ref local) = s.kind { self.check_unused_parens_pat(cx, &local.pat, true, false, (true, false)); } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 73f5829adec64..fc907760531f7 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -254,7 +254,7 @@ impl<'a> Parser<'a> { let local = this.parse_local(attrs)?; // FIXME - maybe capture semicolon in recovery? Ok(( - this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)), + this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), TrailingToken::None, )) })?; @@ -278,7 +278,7 @@ impl<'a> Parser<'a> { } else { TrailingToken::None }; - Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)), trailing)) + Ok((this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Let(local)), trailing)) }) } @@ -764,7 +764,7 @@ impl<'a> Parser<'a> { } } StmtKind::Expr(_) | StmtKind::MacCall(_) => {} - StmtKind::Local(local) if let Err(mut e) = self.expect_semi() => { + StmtKind::Let(local) if let Err(mut e) = self.expect_semi() => { // We might be at the `,` in `let x = foo;`. Try to recover. match &mut local.kind { LocalKind::Init(expr) | LocalKind::InitElse(expr, _) => { @@ -820,7 +820,7 @@ impl<'a> Parser<'a> { } eat_semi = false; } - StmtKind::Empty | StmtKind::Item(_) | StmtKind::Local(_) | StmtKind::Semi(_) => { + StmtKind::Empty | StmtKind::Item(_) | StmtKind::Let(_) | StmtKind::Semi(_) => { eat_semi = false } } diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index be6ba585d2004..61dd02ae7dc8f 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -539,7 +539,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { fn visit_stmt(&mut self, s: &'v ast::Stmt) { record_variants!( (self, s, s.kind, Id::None, ast, Stmt, StmtKind), - [Local, Item, Expr, Semi, Empty, MacCall] + [Let, Item, Expr, Semi, Empty, MacCall] ); ast_visit::walk_stmt(self, s) } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index 3b3939da7b6bc..3874c1169e48c 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -267,7 +267,7 @@ pub fn eq_block(l: &Block, r: &Block) -> bool { pub fn eq_stmt(l: &Stmt, r: &Stmt) -> bool { use StmtKind::*; match (&l.kind, &r.kind) { - (Local(l), Local(r)) => { + (Let(l), Let(r)) => { eq_pat(&l.pat, &r.pat) && both(&l.ty, &r.ty, |l, r| eq_ty(l, r)) && eq_local_kind(&l.kind, &r.kind) diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs index 4d83547d664e2..83f59837d442c 100644 --- a/src/tools/rustfmt/src/attr.rs +++ b/src/tools/rustfmt/src/attr.rs @@ -26,7 +26,7 @@ pub(crate) fn get_attrs_from_stmt(stmt: &ast::Stmt) -> &[ast::Attribute] { pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span { match stmt.kind { - ast::StmtKind::Local(ref local) => local.span, + ast::StmtKind::Let(ref local) => local.span, ast::StmtKind::Item(ref item) => item.span, ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => expr.span, ast::StmtKind::MacCall(ref mac_stmt) => mac_stmt.mac.span(), diff --git a/src/tools/rustfmt/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs index 5960b14449948..4aaf7fdb27fb0 100644 --- a/src/tools/rustfmt/src/spanned.rs +++ b/src/tools/rustfmt/src/spanned.rs @@ -61,7 +61,7 @@ implement_spanned!(ast::Local); impl Spanned for ast::Stmt { fn span(&self) -> Span { match self.kind { - ast::StmtKind::Local(ref local) => mk_sp(local.span().lo(), self.span.hi()), + ast::StmtKind::Let(ref local) => mk_sp(local.span().lo(), self.span.hi()), ast::StmtKind::Item(ref item) => mk_sp(item.span().lo(), self.span.hi()), ast::StmtKind::Expr(ref expr) | ast::StmtKind::Semi(ref expr) => { mk_sp(expr.span().lo(), self.span.hi()) diff --git a/src/tools/rustfmt/src/stmt.rs b/src/tools/rustfmt/src/stmt.rs index e3fe4ebca11f1..73a9cce416c18 100644 --- a/src/tools/rustfmt/src/stmt.rs +++ b/src/tools/rustfmt/src/stmt.rs @@ -115,7 +115,7 @@ fn format_stmt( skip_out_of_file_lines_range!(context, stmt.span()); let result = match stmt.kind { - ast::StmtKind::Local(ref local) => local.rewrite(context, shape), + ast::StmtKind::Let(ref local) => local.rewrite(context, shape), ast::StmtKind::Expr(ref ex) | ast::StmtKind::Semi(ref ex) => { let suffix = if semicolon_for_stmt(context, stmt, is_last_expr) { ";" diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 47f772b485daf..6209b37004bf1 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -150,7 +150,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_item(item); self.last_pos = stmt.span().hi(); } - ast::StmtKind::Local(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { + ast::StmtKind::Let(..) | ast::StmtKind::Expr(..) | ast::StmtKind::Semi(..) => { let attrs = get_attrs_from_stmt(stmt.as_ast_node()); if contains_skip(attrs) { self.push_skipped_with_span( From a4e0e50a3fb8d8658729f2860be54871597078da Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 14 Mar 2024 11:53:38 +0100 Subject: [PATCH 20/23] Rename `hir::StmtKind::Local` into `hir::StmtKind::Let` --- compiler/rustc_ast_lowering/src/block.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 2 +- .../rustc_borrowck/src/diagnostics/conflict_errors.rs | 2 +- .../rustc_borrowck/src/diagnostics/mutability_errors.rs | 4 ++-- compiler/rustc_hir/src/hir.rs | 2 +- compiler/rustc_hir/src/intravisit.rs | 2 +- compiler/rustc_hir_analysis/src/check/errs.rs | 2 +- compiler/rustc_hir_analysis/src/check/region.rs | 4 ++-- compiler/rustc_hir_pretty/src/lib.rs | 4 ++-- compiler/rustc_hir_typeck/src/expr_use_visitor.rs | 4 ++-- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 6 +++--- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_hir_typeck/src/upvar.rs | 2 +- compiler/rustc_infer/src/infer/error_reporting/mod.rs | 2 +- compiler/rustc_infer/src/infer/error_reporting/suggest.rs | 4 ++-- compiler/rustc_middle/src/hir/map/mod.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/block.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_passes/src/hir_stats.rs | 2 +- compiler/rustc_passes/src/liveness.rs | 2 +- compiler/rustc_passes/src/naked_functions.rs | 2 +- .../src/traits/error_reporting/suggestions.rs | 2 +- src/tools/clippy/clippy_lints/src/attrs/utils.rs | 2 +- src/tools/clippy/clippy_lints/src/copies.rs | 8 ++++---- src/tools/clippy/clippy_lints/src/default.rs | 2 +- .../clippy/clippy_lints/src/default_numeric_fallback.rs | 2 +- src/tools/clippy/clippy_lints/src/entry.rs | 2 +- src/tools/clippy/clippy_lints/src/explicit_write.rs | 2 +- src/tools/clippy/clippy_lints/src/let_if_seq.rs | 2 +- src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs | 2 +- .../clippy_lints/src/loops/manual_while_let_some.rs | 2 +- src/tools/clippy/clippy_lints/src/loops/never_loop.rs | 2 +- src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs | 2 +- src/tools/clippy/clippy_lints/src/manual_let_else.rs | 2 +- src/tools/clippy/clippy_lints/src/map_unit_fn.rs | 2 +- .../clippy/clippy_lints/src/methods/needless_collect.rs | 2 +- src/tools/clippy/clippy_lints/src/methods/str_splitn.rs | 2 +- .../src/methods/unnecessary_result_map_or_else.rs | 2 +- src/tools/clippy/clippy_lints/src/misc.rs | 2 +- .../clippy_lints/src/mixed_read_write_in_expression.rs | 4 ++-- src/tools/clippy/clippy_lints/src/needless_late_init.rs | 2 +- src/tools/clippy/clippy_lints/src/no_effect.rs | 2 +- .../clippy/clippy_lints/src/pattern_type_mismatch.rs | 2 +- src/tools/clippy/clippy_lints/src/question_mark.rs | 2 +- src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs | 2 +- .../clippy/clippy_lints/src/redundant_closure_call.rs | 2 +- src/tools/clippy/clippy_lints/src/returns.rs | 2 +- .../clippy_lints/src/significant_drop_tightening.rs | 6 +++--- .../clippy/clippy_lints/src/slow_vector_initialization.rs | 2 +- src/tools/clippy/clippy_lints/src/swap.rs | 4 ++-- .../clippy/clippy_lints/src/undocumented_unsafe_blocks.rs | 4 ++-- src/tools/clippy/clippy_lints/src/uninit_vec.rs | 2 +- src/tools/clippy/clippy_lints/src/unused_io_amount.rs | 4 ++-- src/tools/clippy/clippy_lints/src/unused_peekable.rs | 4 ++-- src/tools/clippy/clippy_lints/src/utils/author.rs | 2 +- src/tools/clippy/clippy_utils/src/hir_utils.rs | 4 ++-- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- 58 files changed, 76 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index 5f60fbe567071..11a66fe87c9a6 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -36,7 +36,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let hir_id = self.lower_node_id(s.id); let local = self.lower_local(local); self.alias_attrs(hir_id, local.hir_id); - let kind = hir::StmtKind::Local(local); + let kind = hir::StmtKind::Let(local); let span = self.lower_span(s.span); stmts.push(hir::Stmt { hir_id, kind, span }); } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 94e1e06a95453..e8ff64a7fd2c3 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2356,7 +2356,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { span: self.lower_span(span), ty: None, }; - self.stmt(span, hir::StmtKind::Local(self.arena.alloc(local))) + self.stmt(span, hir::StmtKind::Let(self.arena.alloc(local))) } fn block_expr(&mut self, expr: &'hir hir::Expr<'hir>) -> &'hir hir::Block<'hir> { diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 0776f455efd9c..5af70937f622c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -616,7 +616,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // FIXME: We make sure that this is a normal top-level binding, // but we could suggest `todo!()` for all uninitalized bindings in the pattern pattern - if let hir::StmtKind::Local(hir::Local { span, ty, init: None, pat, .. }) = + if let hir::StmtKind::Let(hir::Local { span, ty, init: None, pat, .. }) = &ex.kind && let hir::PatKind::Binding(..) = pat.kind && span.contains(self.decl_span) diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index ebc9f1d109ee7..ee2e3d20fe56e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -558,7 +558,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { hir::intravisit::walk_stmt(self, stmt); let expr = match stmt.kind { hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr) => expr, - hir::StmtKind::Local(hir::Local { init: Some(expr), .. }) => expr, + hir::StmtKind::Let(hir::Local { init: Some(expr), .. }) => expr, _ => { return; } @@ -1305,7 +1305,7 @@ struct BindingFinder { impl<'tcx> Visitor<'tcx> for BindingFinder { type Result = ControlFlow; fn visit_stmt(&mut self, s: &'tcx hir::Stmt<'tcx>) -> Self::Result { - if let hir::StmtKind::Local(local) = s.kind + if let hir::StmtKind::Let(local) = s.kind && local.pat.span == self.span { ControlFlow::Break(local.hir_id) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 866b265c647a7..7006c90e17b76 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1209,7 +1209,7 @@ pub struct Stmt<'hir> { #[derive(Debug, Clone, Copy, HashStable_Generic)] pub enum StmtKind<'hir> { /// A local (`let`) binding. - Local(&'hir Local<'hir>), + Let(&'hir Local<'hir>), /// An item binding. Item(ItemId), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 32b4bf38fa96a..fbbad38d17f10 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -627,7 +627,7 @@ pub fn walk_block<'v, V: Visitor<'v>>(visitor: &mut V, block: &'v Block<'v>) -> pub fn walk_stmt<'v, V: Visitor<'v>>(visitor: &mut V, statement: &'v Stmt<'v>) -> V::Result { try_visit!(visitor.visit_id(statement.hir_id)); match statement.kind { - StmtKind::Local(ref local) => visitor.visit_local(local), + StmtKind::Let(ref local) => visitor.visit_local(local), StmtKind::Item(item) => visitor.visit_nested_item(item), StmtKind::Expr(ref expression) | StmtKind::Semi(ref expression) => { visitor.visit_expr(expression) diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs index b9dc5cbc4d206..f0c15a070b48a 100644 --- a/compiler/rustc_hir_analysis/src/check/errs.rs +++ b/compiler/rustc_hir_analysis/src/check/errs.rs @@ -27,7 +27,7 @@ pub fn maybe_expr_static_mut(tcx: TyCtxt<'_>, expr: hir::Expr<'_>) { /// Check for shared or mutable references of `static mut` inside statement pub fn maybe_stmt_static_mut(tcx: TyCtxt<'_>, stmt: hir::Stmt<'_>) { - if let hir::StmtKind::Local(loc) = stmt.kind + if let hir::StmtKind::Let(loc) = stmt.kind && let hir::PatKind::Binding(ba, _, _, _) = loc.pat.kind && matches!(ba.0, rustc_ast::ByRef::Yes) && let Some(init) = loc.init diff --git a/compiler/rustc_hir_analysis/src/check/region.rs b/compiler/rustc_hir_analysis/src/check/region.rs index 2a4dd6b0e0ef3..3c26729eff8af 100644 --- a/compiler/rustc_hir_analysis/src/check/region.rs +++ b/compiler/rustc_hir_analysis/src/check/region.rs @@ -123,7 +123,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h for (i, statement) in blk.stmts.iter().enumerate() { match statement.kind { - hir::StmtKind::Local(hir::Local { els: Some(els), .. }) => { + hir::StmtKind::Let(hir::Local { els: Some(els), .. }) => { // Let-else has a special lexical structure for variables. // First we take a checkpoint of the current scope context here. let mut prev_cx = visitor.cx; @@ -146,7 +146,7 @@ fn resolve_block<'tcx>(visitor: &mut RegionResolutionVisitor<'tcx>, blk: &'tcx h // From now on, we continue normally. visitor.cx = prev_cx; } - hir::StmtKind::Local(..) => { + hir::StmtKind::Let(..) => { // Each declaration introduces a subscope for bindings // introduced by the declaration; this subscope covers a // suffix of the block. Each subscope in a block has the diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index b5bb063c5ed8c..7d303d989c797 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -863,7 +863,7 @@ impl<'a> State<'a> { fn print_stmt(&mut self, st: &hir::Stmt<'_>) { self.maybe_print_comment(st.span.lo()); match st.kind { - hir::StmtKind::Local(loc) => { + hir::StmtKind::Let(loc) => { self.print_local(loc.init, loc.els, |this| this.print_local_decl(loc)); } hir::StmtKind::Item(item) => self.ann.nested(self, Nested::Item(item)), @@ -2306,7 +2306,7 @@ fn expr_requires_semi_to_be_stmt(e: &hir::Expr<'_>) -> bool { /// seen the semicolon, and thus don't need another. fn stmt_ends_with_semi(stmt: &hir::StmtKind<'_>) -> bool { match *stmt { - hir::StmtKind::Local(_) => true, + hir::StmtKind::Let(_) => true, hir::StmtKind::Item(_) => false, hir::StmtKind::Expr(e) => expr_requires_semi_to_be_stmt(e), hir::StmtKind::Semi(..) => false, diff --git a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs index ba0383d19b92a..43e9554459439 100644 --- a/compiler/rustc_hir_typeck/src/expr_use_visitor.rs +++ b/compiler/rustc_hir_typeck/src/expr_use_visitor.rs @@ -371,11 +371,11 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx> { fn walk_stmt(&mut self, stmt: &hir::Stmt<'_>) { match stmt.kind { - hir::StmtKind::Local(hir::Local { pat, init: Some(expr), els, .. }) => { + hir::StmtKind::Let(hir::Local { pat, init: Some(expr), els, .. }) => { self.walk_local(expr, pat, *els, |_| {}) } - hir::StmtKind::Local(_) => {} + hir::StmtKind::Let(_) => {} hir::StmtKind::Item(_) => { // We don't visit nested items in this visitor, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index a08582a67d94c..0bf81f8bae274 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -1593,7 +1593,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Don't do all the complex logic below for `DeclItem`. match stmt.kind { hir::StmtKind::Item(..) => return, - hir::StmtKind::Local(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {} + hir::StmtKind::Let(..) | hir::StmtKind::Expr(..) | hir::StmtKind::Semi(..) => {} } self.warn_if_unreachable(stmt.hir_id, stmt.span, "statement"); @@ -1602,7 +1602,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let old_diverges = self.diverges.replace(Diverges::Maybe); match stmt.kind { - hir::StmtKind::Local(l) => { + hir::StmtKind::Let(l) => { self.check_decl_local(l); } // Ignore for now. @@ -1765,7 +1765,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { [ hir::Stmt { kind: - hir::StmtKind::Local(hir::Local { + hir::StmtKind::Let(hir::Local { source: hir::LocalSource::AssignDesugar(_), .. diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 5a1c7b0561185..3f6f4cccba796 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1599,7 +1599,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn is_local_statement(&self, id: hir::HirId) -> bool { let node = self.tcx.hir_node(id); - matches!(node, Node::Stmt(Stmt { kind: StmtKind::Local(..), .. })) + matches!(node, Node::Stmt(Stmt { kind: StmtKind::Let(..), .. })) } /// Suggest that `&T` was cloned instead of `T` because `T` does not implement `Clone`, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 4c413e4d1c6a5..c5bbcc56f86a5 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2221,7 +2221,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { impl<'v> Visitor<'v> for LetVisitor { type Result = ControlFlow>>; fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result { - if let hir::StmtKind::Local(&hir::Local { pat, init, .. }) = ex.kind + if let hir::StmtKind::Let(&hir::Local { pat, init, .. }) = ex.kind && let Binding(_, _, ident, ..) = pat.kind && ident.name == self.ident_name { diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 211109b59417a..be14f5bf0d8b5 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -217,7 +217,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bug!(); }; for stmt in block.stmts { - let hir::StmtKind::Local(hir::Local { + let hir::StmtKind::Let(hir::Local { init: Some(init), source: hir::LocalSource::AsyncFn, pat, diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 222c0a3954255..6fb2aa8b1b91d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -2139,7 +2139,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { // the same span as the error and the type is specified. if let hir::Stmt { kind: - hir::StmtKind::Local(hir::Local { + hir::StmtKind::Let(hir::Local { init: Some(hir::Expr { span: init_span, .. }), ty: Some(array_ty), .. diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs index 8cdf39b173987..9081fbaa2dc2b 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs @@ -585,7 +585,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { } fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) -> Self::Result { - if let hir::StmtKind::Local(hir::Local { + if let hir::StmtKind::Let(hir::Local { span, pat: hir::Pat { .. }, ty: None, @@ -824,7 +824,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let hir = self.tcx.hir(); for stmt in blk.stmts.iter().rev() { - let hir::StmtKind::Local(local) = &stmt.kind else { + let hir::StmtKind::Let(local) = &stmt.kind else { continue; }; local.pat.walk(&mut find_compatible_candidates); diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index c05da36235851..142988dee7472 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -655,7 +655,7 @@ impl<'hir> Map<'hir> { | Node::ForeignItem(_) | Node::TraitItem(_) | Node::ImplItem(_) - | Node::Stmt(Stmt { kind: StmtKind::Local(_), .. }) => break, + | Node::Stmt(Stmt { kind: StmtKind::Let(_), .. }) => break, Node::Expr(expr @ Expr { kind: ExprKind::If(..) | ExprKind::Match(..), .. }) => { return Some(expr); } diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 1e93e126b706e..d4a347975dbae 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -63,7 +63,7 @@ impl<'tcx> Cx<'tcx> { // ignore for purposes of the MIR None } - hir::StmtKind::Local(local) => { + hir::StmtKind::Let(local) => { let remainder_scope = region::Scope { id: block_id, data: region::ScopeData::Remainder(region::FirstStatementIndex::new( diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 91ab5b30dea3d..eb2399f7a64f4 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -2444,7 +2444,7 @@ impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { // When checking statements ignore expressions, they will be checked later. - if let hir::StmtKind::Local(l) = stmt.kind { + if let hir::StmtKind::Let(l) = stmt.kind { self.check_attributes(l.hir_id, stmt.span, Target::Statement, None); } intravisit::walk_stmt(self, stmt) diff --git a/compiler/rustc_passes/src/hir_stats.rs b/compiler/rustc_passes/src/hir_stats.rs index 61dd02ae7dc8f..d742ffc69e450 100644 --- a/compiler/rustc_passes/src/hir_stats.rs +++ b/compiler/rustc_passes/src/hir_stats.rs @@ -277,7 +277,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { fn visit_stmt(&mut self, s: &'v hir::Stmt<'v>) { record_variants!( (self, s, s.kind, Id::Node(s.hir_id), hir, Stmt, StmtKind), - [Local, Item, Expr, Semi] + [Let, Item, Expr, Semi] ); hir_visit::walk_stmt(self, s) } diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index e5033e1f51f23..f0c3f7a385d60 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -771,7 +771,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { fn propagate_through_stmt(&mut self, stmt: &hir::Stmt<'_>, succ: LiveNode) -> LiveNode { match stmt.kind { - hir::StmtKind::Local(local) => { + hir::StmtKind::Let(local) => { // Note: we mark the variable as defined regardless of whether // there is an initializer. Initially I had thought to only mark // the live variable as defined if it was initialized, and then we diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs index 27c9c1306e6ac..bd34b0597e255 100644 --- a/compiler/rustc_passes/src/naked_functions.rs +++ b/compiler/rustc_passes/src/naked_functions.rs @@ -280,7 +280,7 @@ impl<'tcx> Visitor<'tcx> for CheckInlineAssembly<'tcx> { fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { match stmt.kind { StmtKind::Item(..) => {} - StmtKind::Local(..) => { + StmtKind::Let(..) => { self.items.push((ItemKind::NonAsm, stmt.span)); } StmtKind::Expr(expr) | StmtKind::Semi(expr) => { diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs index 1241227a5af39..2924a18654444 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs @@ -763,7 +763,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let hir_id = self.tcx.local_def_id_to_hir_id(def_id.as_local()?); match self.tcx.parent_hir_node(hir_id) { - hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(local), .. }) => { + hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Let(local), .. }) => { get_name(err, &local.pat.kind) } // Different to previous arm because one is `&hir::Local` and the other diff --git a/src/tools/clippy/clippy_lints/src/attrs/utils.rs b/src/tools/clippy/clippy_lints/src/attrs/utils.rs index 9b36cc00444f3..91ae19acbf7f6 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/utils.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/utils.rs @@ -52,7 +52,7 @@ fn is_relevant_block(cx: &LateContext<'_>, typeck_results: &ty::TypeckResults<'_ .as_ref() .map_or(false, |e| is_relevant_expr(cx, typeck_results, e)), |stmt| match &stmt.kind { - StmtKind::Local(_) => true, + StmtKind::Let(_) => true, StmtKind::Expr(expr) | StmtKind::Semi(expr) => is_relevant_expr(cx, typeck_results, expr), StmtKind::Item(_) => false, }, diff --git a/src/tools/clippy/clippy_lints/src/copies.rs b/src/tools/clippy/clippy_lints/src/copies.rs index 247048bbc49da..acdcb54be2719 100644 --- a/src/tools/clippy/clippy_lints/src/copies.rs +++ b/src/tools/clippy/clippy_lints/src/copies.rs @@ -349,7 +349,7 @@ impl BlockEq { /// If the statement is a local, checks if the bound names match the expected list of names. fn eq_binding_names(s: &Stmt<'_>, names: &[(HirId, Symbol)]) -> bool { - if let StmtKind::Local(l) = s.kind { + if let StmtKind::Let(l) = s.kind { let mut i = 0usize; let mut res = true; l.pat.each_binding_or_first(&mut |_, _, _, name| { @@ -389,7 +389,7 @@ fn eq_stmts( eq: &mut HirEqInterExpr<'_, '_, '_>, moved_bindings: &mut Vec<(HirId, Symbol)>, ) -> bool { - (if let StmtKind::Local(l) = stmt.kind { + (if let StmtKind::Let(l) = stmt.kind { let old_count = moved_bindings.len(); l.pat.each_binding_or_first(&mut |_, id, _, name| { moved_bindings.push((id, name.name)); @@ -432,7 +432,7 @@ fn scan_block_for_eq<'tcx>( .iter() .enumerate() .find(|&(i, stmt)| { - if let StmtKind::Local(l) = stmt.kind + if let StmtKind::Let(l) = stmt.kind && needs_ordered_drop(cx, cx.typeck_results().node_type(l.hir_id)) { local_needs_ordered_drop = true; @@ -509,7 +509,7 @@ fn scan_block_for_eq<'tcx>( // Clear out all locals seen at the end so far. None of them can be moved. let stmts = &blocks[0].stmts; for stmt in &stmts[stmts.len() - init..=stmts.len() - offset] { - if let StmtKind::Local(l) = stmt.kind { + if let StmtKind::Let(l) = stmt.kind { l.pat.each_binding_or_first(&mut |_, id, _, _| { // FIXME(rust/#120456) - is `swap_remove` correct? eq.locals.swap_remove(&id); diff --git a/src/tools/clippy/clippy_lints/src/default.rs b/src/tools/clippy/clippy_lints/src/default.rs index 8789efcc99444..98a6d9370c344 100644 --- a/src/tools/clippy/clippy_lints/src/default.rs +++ b/src/tools/clippy/clippy_lints/src/default.rs @@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for Default { // find all binding statements like `let mut _ = T::default()` where `T::default()` is the // `default` method of the `Default` trait, and store statement index in current block being // checked and the name of the bound variable - let (local, variant, binding_name, binding_type, span) = if let StmtKind::Local(local) = stmt.kind + let (local, variant, binding_name, binding_type, span) = if let StmtKind::Let(local) = stmt.kind // only take `let ...` statements && let Some(expr) = local.init && !any_parent_is_automatically_derived(cx.tcx, expr.hir_id) diff --git a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs index 59d2df0295fb4..1d6c4ce72e18b 100644 --- a/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs +++ b/src/tools/clippy/clippy_lints/src/default_numeric_fallback.rs @@ -221,7 +221,7 @@ impl<'a, 'tcx> Visitor<'tcx> for NumericFallbackVisitor<'a, 'tcx> { fn visit_stmt(&mut self, stmt: &'tcx Stmt<'_>) { match stmt.kind { // we cannot check the exact type since it's a hir::Ty which does not implement `is_numeric` - StmtKind::Local(local) => self.ty_bounds.push(ExplicitTyBound(local.ty.is_some())), + StmtKind::Let(local) => self.ty_bounds.push(ExplicitTyBound(local.ty.is_some())), _ => self.ty_bounds.push(ExplicitTyBound(false)), } diff --git a/src/tools/clippy/clippy_lints/src/entry.rs b/src/tools/clippy/clippy_lints/src/entry.rs index de6073c272360..ebda2ad83870d 100644 --- a/src/tools/clippy/clippy_lints/src/entry.rs +++ b/src/tools/clippy/clippy_lints/src/entry.rs @@ -423,7 +423,7 @@ impl<'tcx> Visitor<'tcx> for InsertSearcher<'_, 'tcx> { } }, StmtKind::Expr(e) => self.visit_expr(e), - StmtKind::Local(l) => { + StmtKind::Let(l) => { self.visit_pat(l.pat); if let Some(e) = l.init { self.allow_insert_closure &= !self.in_tail_pos; diff --git a/src/tools/clippy/clippy_lints/src/explicit_write.rs b/src/tools/clippy/clippy_lints/src/explicit_write.rs index de048fef5f224..2e9bec6a7b083 100644 --- a/src/tools/clippy/clippy_lints/src/explicit_write.rs +++ b/src/tools/clippy/clippy_lints/src/explicit_write.rs @@ -102,7 +102,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitWrite { fn look_in_block<'tcx, 'hir>(cx: &LateContext<'tcx>, kind: &'tcx ExprKind<'hir>) -> &'tcx ExprKind<'hir> { if let ExprKind::Block(block, _label @ None) = kind && let Block { - stmts: [Stmt { kind: StmtKind::Local(local), .. }], + stmts: [Stmt { kind: StmtKind::Let(local), .. }], expr: Some(expr_end_of_block), rules: BlockCheckMode::DefaultBlock, .. diff --git a/src/tools/clippy/clippy_lints/src/let_if_seq.rs b/src/tools/clippy/clippy_lints/src/let_if_seq.rs index 270162ae7717f..f084d89ccc282 100644 --- a/src/tools/clippy/clippy_lints/src/let_if_seq.rs +++ b/src/tools/clippy/clippy_lints/src/let_if_seq.rs @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for LetIfSeq { let mut it = block.stmts.iter().peekable(); while let Some(stmt) = it.next() { if let Some(expr) = it.peek() - && let hir::StmtKind::Local(local) = stmt.kind + && let hir::StmtKind::Let(local) = stmt.kind && let hir::PatKind::Binding(mode, canonical_id, ident, None) = local.pat.kind && let hir::StmtKind::Expr(if_) = expr.kind && let hir::ExprKind::If( diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs index 18f799e875a07..a7c1d1bd6cd36 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -410,7 +410,7 @@ fn get_assignments<'a, 'tcx>( stmts .iter() .filter_map(move |stmt| match stmt.kind { - StmtKind::Local(..) | StmtKind::Item(..) => None, + StmtKind::Let(..) | StmtKind::Item(..) => None, StmtKind::Expr(e) | StmtKind::Semi(e) => Some(e), }) .chain(*expr) diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs index ca584a454d035..b00a082bb8cf9 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_while_let_some.rs @@ -72,7 +72,7 @@ fn is_vec_pop_unwrap(cx: &LateContext<'_>, expr: &Expr<'_>, is_empty_recv: &Expr } fn check_local(cx: &LateContext<'_>, stmt: &Stmt<'_>, is_empty_recv: &Expr<'_>, loop_span: Span) { - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Some(init) = local.init && is_vec_pop_unwrap(cx, init, is_empty_recv) { diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs index 65d922f03df3a..6cc79440f39a0 100644 --- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs @@ -137,7 +137,7 @@ fn stmt_to_expr<'tcx>(stmt: &Stmt<'tcx>) -> Option<(&'tcx Expr<'tcx>, Option<&'t match stmt.kind { StmtKind::Semi(e) | StmtKind::Expr(e) => Some((e, None)), // add the let...else expression (if present) - StmtKind::Local(local) => local.init.map(|init| (init, local.els)), + StmtKind::Let(local) => local.init.map(|init| (init, local.els)), StmtKind::Item(..) => None, } } diff --git a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs index 735d704a43cee..93774b8976824 100644 --- a/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/while_let_loop.rs @@ -11,7 +11,7 @@ use rustc_lint::LateContext; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) { let (init, has_trailing_exprs) = match (loop_block.stmts, loop_block.expr) { ([stmt, stmts @ ..], expr) => { - if let StmtKind::Local(&Local { + if let StmtKind::Let(&Local { init: Some(e), els: None, .. diff --git a/src/tools/clippy/clippy_lints/src/manual_let_else.rs b/src/tools/clippy/clippy_lints/src/manual_let_else.rs index fdf8fa4e2771f..03e4d668dd8fb 100644 --- a/src/tools/clippy/clippy_lints/src/manual_let_else.rs +++ b/src/tools/clippy/clippy_lints/src/manual_let_else.rs @@ -53,7 +53,7 @@ impl<'tcx> QuestionMark { return; } - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Some(init) = local.init && local.els.is_none() && local.ty.is_none() diff --git a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs index 3b82c50a84e62..c9eab7109ebcd 100644 --- a/src/tools/clippy/clippy_lints/src/map_unit_fn.rs +++ b/src/tools/clippy/clippy_lints/src/map_unit_fn.rs @@ -138,7 +138,7 @@ fn reduce_unit_expression(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> Option< // If block only contains statements, // reduce `{ X; }` to `X` or `X;` match inner_stmt.kind { - hir::StmtKind::Local(local) => Some(local.span), + hir::StmtKind::Let(local) => Some(local.span), hir::StmtKind::Expr(e) => Some(e.span), hir::StmtKind::Semi(..) => Some(inner_stmt.span), hir::StmtKind::Item(..) => None, diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 55050ae693e76..78540353005d3 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -424,7 +424,7 @@ fn get_expr_and_hir_id_from_stmt<'v>(stmt: &'v Stmt<'v>) -> Option<(&'v Expr<'v> match stmt.kind { StmtKind::Expr(expr) | StmtKind::Semi(expr) => Some((expr, None)), StmtKind::Item(..) => None, - StmtKind::Local(Local { init, pat, .. }) => { + StmtKind::Let(Local { init, pat, .. }) => { if let PatKind::Binding(_, hir_id, ..) = pat.kind { init.map(|init_expr| (init_expr, Some(hir_id))) } else { diff --git a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs index 0e7ad8fc996e5..55cd1a38ec96c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs +++ b/src/tools/clippy/clippy_lints/src/methods/str_splitn.rs @@ -198,7 +198,7 @@ fn indirect_usage<'tcx>( binding: HirId, ctxt: SyntaxContext, ) -> Option> { - if let StmtKind::Local(&Local { + if let StmtKind::Let(&Local { pat: Pat { kind: PatKind::Binding(BindingAnnotation::NONE, _, ident, None), .. diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs index 7b0cf48ac43be..cdfaa690d5f4b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_result_map_or_else.rs @@ -27,7 +27,7 @@ fn emit_lint(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, def_arg: &E fn get_last_chain_binding_hir_id(mut hir_id: HirId, statements: &[Stmt<'_>]) -> Option { for stmt in statements { - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Some(init) = local.init && let ExprKind::Path(QPath::Resolved(_, path)) = init.kind && let hir::def::Res::Local(local_hir_id) = path.res diff --git a/src/tools/clippy/clippy_lints/src/misc.rs b/src/tools/clippy/clippy_lints/src/misc.rs index b9784a58596c1..4094d7ded7d82 100644 --- a/src/tools/clippy/clippy_lints/src/misc.rs +++ b/src/tools/clippy/clippy_lints/src/misc.rs @@ -143,7 +143,7 @@ impl<'tcx> LateLintPass<'tcx> for LintPass { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { if !in_external_macro(cx.tcx.sess, stmt.span) - && let StmtKind::Local(local) = stmt.kind + && let StmtKind::Let(local) = stmt.kind && let PatKind::Binding(BindingAnnotation(ByRef::Yes, mutabl), .., name, None) = local.pat.kind && let Some(init) = local.init // Do not emit if clippy::ref_patterns is not allowed to avoid having two lints for the same issue. diff --git a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs index a1f7dc7b38c40..12c7c18afde6c 100644 --- a/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs +++ b/src/tools/clippy/clippy_lints/src/mixed_read_write_in_expression.rs @@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for EvalOrderDependence { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { match stmt.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { if let Local { init: Some(e), .. } = local { DivergenceVisitor { cx }.visit_expr(e); } @@ -291,7 +291,7 @@ fn check_stmt<'tcx>(vis: &mut ReadVisitor<'_, 'tcx>, stmt: &'tcx Stmt<'_>) -> St StmtKind::Expr(expr) | StmtKind::Semi(expr) => check_expr(vis, expr), // If the declaration is of a local variable, check its initializer // expression if it has one. Otherwise, keep going. - StmtKind::Local(local) => local + StmtKind::Let(local) => local .init .as_ref() .map_or(StopEarly::KeepGoing, |expr| check_expr(vis, expr)), diff --git a/src/tools/clippy/clippy_lints/src/needless_late_init.rs b/src/tools/clippy/clippy_lints/src/needless_late_init.rs index 3e63c0a1d36e7..4cda4b171e31b 100644 --- a/src/tools/clippy/clippy_lints/src/needless_late_init.rs +++ b/src/tools/clippy/clippy_lints/src/needless_late_init.rs @@ -86,7 +86,7 @@ fn contains_let(cond: &Expr<'_>) -> bool { } fn stmt_needs_ordered_drop(cx: &LateContext<'_>, stmt: &Stmt<'_>) -> bool { - let StmtKind::Local(local) = stmt.kind else { + let StmtKind::Let(local) = stmt.kind else { return false; }; !local.pat.walk_short(|pat| { diff --git a/src/tools/clippy/clippy_lints/src/no_effect.rs b/src/tools/clippy/clippy_lints/src/no_effect.rs index cac34c8ce06e9..43810ec0ec743 100644 --- a/src/tools/clippy/clippy_lints/src/no_effect.rs +++ b/src/tools/clippy/clippy_lints/src/no_effect.rs @@ -174,7 +174,7 @@ impl NoEffect { ); return true; } - } else if let StmtKind::Local(local) = stmt.kind { + } else if let StmtKind::Let(local) = stmt.kind { if !is_lint_allowed(cx, NO_EFFECT_UNDERSCORE_BINDING, local.hir_id) && !matches!(local.source, LocalSource::AsyncFn) && let Some(init) = local.init diff --git a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs index 60ced9c12082d..fbca4329342a9 100644 --- a/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs +++ b/src/tools/clippy/clippy_lints/src/pattern_type_mismatch.rs @@ -82,7 +82,7 @@ declare_lint_pass!(PatternTypeMismatch => [PATTERN_TYPE_MISMATCH]); impl<'tcx> LateLintPass<'tcx> for PatternTypeMismatch { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { - if let StmtKind::Local(local) = stmt.kind { + if let StmtKind::Let(local) = stmt.kind { if in_external_macro(cx.sess(), local.pat.span) { return; } diff --git a/src/tools/clippy/clippy_lints/src/question_mark.rs b/src/tools/clippy/clippy_lints/src/question_mark.rs index cf7f730140ceb..831c291ed7cc5 100644 --- a/src/tools/clippy/clippy_lints/src/question_mark.rs +++ b/src/tools/clippy/clippy_lints/src/question_mark.rs @@ -109,7 +109,7 @@ fn find_let_else_ret_expression<'hir>(block: &'hir Block<'hir>) -> Option<&'hir } fn check_let_some_else_return_none(cx: &LateContext<'_>, stmt: &Stmt<'_>) { - if let StmtKind::Local(Local { + if let StmtKind::Let(Local { pat, init: Some(init_expr), els: Some(els), diff --git a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs index 650324d4249eb..d0b37cd92e002 100644 --- a/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs +++ b/src/tools/clippy/clippy_lints/src/read_zero_byte_vec.rs @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for ReadZeroByteVec { return; } - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let Local { pat, init: Some(init), .. } = local diff --git a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs index f61527cc0a9fe..c2673bc409fa8 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_closure_call.rs @@ -262,7 +262,7 @@ impl<'tcx> LateLintPass<'tcx> for RedundantClosureCall { } for w in block.stmts.windows(2) { - if let hir::StmtKind::Local(local) = w[0].kind + if let hir::StmtKind::Let(local) = w[0].kind && let Option::Some(t) = local.init && let hir::ExprKind::Closure { .. } = t.kind && let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind diff --git a/src/tools/clippy/clippy_lints/src/returns.rs b/src/tools/clippy/clippy_lints/src/returns.rs index 2af466d3f51e3..196975274674e 100644 --- a/src/tools/clippy/clippy_lints/src/returns.rs +++ b/src/tools/clippy/clippy_lints/src/returns.rs @@ -222,7 +222,7 @@ impl<'tcx> LateLintPass<'tcx> for Return { // we need both a let-binding stmt and an expr if let Some(retexpr) = block.expr && let Some(stmt) = block.stmts.iter().last() - && let StmtKind::Local(local) = &stmt.kind + && let StmtKind::Let(local) = &stmt.kind && local.ty.is_none() && cx.tcx.hir().attrs(local.hir_id).is_empty() && let Some(initexpr) = &local.init diff --git a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs index 6c99ccda7ea73..f8726aa173a9b 100644 --- a/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs +++ b/src/tools/clippy/clippy_lints/src/significant_drop_tightening.rs @@ -236,7 +236,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> StmtsChecker<'ap, 'lc, 'others, 'stmt, 'tcx fn manage_has_expensive_expr_after_last_attr(&mut self) { let has_expensive_stmt = match self.ap.curr_stmt.kind { hir::StmtKind::Expr(expr) if is_inexpensive_expr(expr) => false, - hir::StmtKind::Local(local) + hir::StmtKind::Let(local) if let Some(expr) = local.init && let hir::ExprKind::Path(_) = expr.kind => { @@ -290,7 +290,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o }; let mut ac = AttrChecker::new(self.cx, self.seen_types, self.type_cache); if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) { - if let hir::StmtKind::Local(local) = self.ap.curr_stmt.kind + if let hir::StmtKind::Let(local) = self.ap.curr_stmt.kind && let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind && !self.ap.apas.contains_key(&hir_id) && { @@ -326,7 +326,7 @@ impl<'ap, 'lc, 'others, 'stmt, 'tcx> Visitor<'tcx> for StmtsChecker<'ap, 'lc, 'o return; }; match self.ap.curr_stmt.kind { - hir::StmtKind::Local(local) => { + hir::StmtKind::Let(local) => { if let hir::PatKind::Binding(_, _, ident, _) = local.pat.kind { apa.last_bind_ident = ident; } diff --git a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs index 4837f2858a669..ff8e8fe702176 100644 --- a/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs +++ b/src/tools/clippy/clippy_lints/src/slow_vector_initialization.rs @@ -119,7 +119,7 @@ impl<'tcx> LateLintPass<'tcx> for SlowVectorInit { fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'_>) { // Matches statements which initializes vectors. For example: `let mut vec = Vec::with_capacity(10)` // or `Vec::new()` - if let StmtKind::Local(local) = stmt.kind + if let StmtKind::Let(local) = stmt.kind && let PatKind::Binding(BindingAnnotation::MUT, local_id, _, None) = local.pat.kind && let Some(init) = local.init && let Some(size_expr) = Self::as_vec_initializer(cx, init) diff --git a/src/tools/clippy/clippy_lints/src/swap.rs b/src/tools/clippy/clippy_lints/src/swap.rs index daa6fe8715ca8..be590aede158d 100644 --- a/src/tools/clippy/clippy_lints/src/swap.rs +++ b/src/tools/clippy/clippy_lints/src/swap.rs @@ -148,7 +148,7 @@ fn check_manual_swap(cx: &LateContext<'_>, block: &Block<'_>) { } for [s1, s2, s3] in block.stmts.array_windows::<3>() { - if let StmtKind::Local(tmp) = s1.kind + if let StmtKind::Let(tmp) = s1.kind // let t = foo(); && let Some(tmp_init) = tmp.init && let PatKind::Binding(.., ident, None) = tmp.pat.kind @@ -243,7 +243,7 @@ fn parse<'a, 'hir>(stmt: &'a Stmt<'hir>) -> Option<(ExprOrIdent<'hir>, &'a Expr< if let ExprKind::Assign(lhs, rhs, _) = expr.kind { return Some((ExprOrIdent::Expr(lhs), rhs)); } - } else if let StmtKind::Local(expr) = stmt.kind { + } else if let StmtKind::Let(expr) = stmt.kind { if let Some(rhs) = expr.init { if let PatKind::Binding(_, _, ident_l, _) = expr.pat.kind { return Some((ExprOrIdent::Ident(ident_l), rhs)); diff --git a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs index 559d7ace40edc..0efa65b28e230 100644 --- a/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs +++ b/src/tools/clippy/clippy_lints/src/undocumented_unsafe_blocks.rs @@ -158,7 +158,7 @@ impl<'tcx> LateLintPass<'tcx> for UndocumentedUnsafeBlocks { } fn check_stmt(&mut self, cx: &LateContext<'tcx>, stmt: &hir::Stmt<'tcx>) { - let (hir::StmtKind::Local(&hir::Local { init: Some(expr), .. }) + let (hir::StmtKind::Let(&hir::Local { init: Some(expr), .. }) | hir::StmtKind::Expr(expr) | hir::StmtKind::Semi(expr)) = stmt.kind else { @@ -358,7 +358,7 @@ fn block_parents_have_safety_comment( }, Node::Stmt(hir::Stmt { kind: - hir::StmtKind::Local(hir::Local { span, hir_id, .. }) + hir::StmtKind::Let(hir::Local { span, hir_id, .. }) | hir::StmtKind::Expr(hir::Expr { span, hir_id, .. }) | hir::StmtKind::Semi(hir::Expr { span, hir_id, .. }), .. diff --git a/src/tools/clippy/clippy_lints/src/uninit_vec.rs b/src/tools/clippy/clippy_lints/src/uninit_vec.rs index fc8519d562835..9ffcfcc0f50cb 100644 --- a/src/tools/clippy/clippy_lints/src/uninit_vec.rs +++ b/src/tools/clippy/clippy_lints/src/uninit_vec.rs @@ -153,7 +153,7 @@ impl<'tcx> VecLocation<'tcx> { /// or `self` expression for `Vec::reserve()`. fn extract_init_or_reserve_target<'tcx>(cx: &LateContext<'tcx>, stmt: &'tcx Stmt<'tcx>) -> Option> { match stmt.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { if let Some(init_expr) = local.init && let PatKind::Binding(_, hir_id, _, None) = local.pat.kind && let Some(init_kind) = get_vec_init_kind(cx, init_expr) diff --git a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs index 6b3ea7700b735..eb64dd633f606 100644 --- a/src/tools/clippy/clippy_lints/src/unused_io_amount.rs +++ b/src/tools/clippy/clippy_lints/src/unused_io_amount.rs @@ -61,10 +61,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedIoAmount { /// we need to check them at `check_expr` or `check_block` as they are not stmts /// but we can't check them at `check_expr` because we need the broader context /// because we should do this only for the final expression of the block, and not for - /// `StmtKind::Local` which binds values => the io amount is used. + /// `StmtKind::Let` which binds values => the io amount is used. /// /// To check for unused io amount in stmts, we only consider `StmtKind::Semi`. - /// `StmtKind::Local` is not considered because it binds values => the io amount is used. + /// `StmtKind::Let` is not considered because it binds values => the io amount is used. /// `StmtKind::Expr` is not considered because requires unit type => the io amount is used. /// `StmtKind::Item` is not considered because it's not an expression. /// diff --git a/src/tools/clippy/clippy_lints/src/unused_peekable.rs b/src/tools/clippy/clippy_lints/src/unused_peekable.rs index ba72b3450b933..f1d0c22b1aec1 100644 --- a/src/tools/clippy/clippy_lints/src/unused_peekable.rs +++ b/src/tools/clippy/clippy_lints/src/unused_peekable.rs @@ -56,7 +56,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedPeekable { for (idx, stmt) in block.stmts.iter().enumerate() { if !stmt.span.from_expansion() - && let StmtKind::Local(local) = stmt.kind + && let StmtKind::Let(local) = stmt.kind && let PatKind::Binding(_, binding, ident, _) = local.pat.kind && let Some(init) = local.init && !init.span.from_expansion() @@ -197,7 +197,7 @@ impl<'tcx> Visitor<'tcx> for PeekableVisitor<'_, 'tcx> { }, Node::Stmt(stmt) => { match stmt.kind { - StmtKind::Local(_) | StmtKind::Item(_) => self.found_peek_call = true, + StmtKind::Let(_) | StmtKind::Item(_) => self.found_peek_call = true, StmtKind::Expr(_) | StmtKind::Semi(_) => {}, } diff --git a/src/tools/clippy/clippy_lints/src/utils/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs index a0a6382046d02..187bfda129cd7 100644 --- a/src/tools/clippy/clippy_lints/src/utils/author.rs +++ b/src/tools/clippy/clippy_lints/src/utils/author.rs @@ -724,7 +724,7 @@ impl<'a, 'tcx> PrintVisitor<'a, 'tcx> { } match stmt.value.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { bind!(self, local); kind!("Local({local})"); self.option(field!(local.init), "init", |init| { diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index f7f5f7ca35ff0..106d1d0d77f01 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -108,7 +108,7 @@ pub struct HirEqInterExpr<'a, 'b, 'tcx> { impl HirEqInterExpr<'_, '_, '_> { pub fn eq_stmt(&mut self, left: &Stmt<'_>, right: &Stmt<'_>) -> bool { match (&left.kind, &right.kind) { - (&StmtKind::Local(l), &StmtKind::Local(r)) => { + (&StmtKind::Let(l), &StmtKind::Let(r)) => { // This additional check ensures that the type of the locals are equivalent even if the init // expression or type have some inferred parts. if let Some((typeck_lhs, typeck_rhs)) = self.inner.maybe_typeck_results { @@ -1030,7 +1030,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { std::mem::discriminant(&b.kind).hash(&mut self.s); match &b.kind { - StmtKind::Local(local) => { + StmtKind::Let(local) => { self.hash_pat(local.pat); if let Some(init) = local.init { self.hash_expr(init); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 708037a465558..dc0725730322b 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2161,7 +2161,7 @@ pub fn is_expr_used_or_unified(tcx: TyCtxt<'_>, expr: &Expr<'_>) -> bool { Node::Stmt(Stmt { kind: StmtKind::Expr(_) | StmtKind::Semi(_) - | StmtKind::Local(Local { + | StmtKind::Let(Local { pat: Pat { kind: PatKind::Wild, .. From ac1b8575c017b6cc99cf389ceffe853d7b53a694 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 14 Mar 2024 12:00:46 +0100 Subject: [PATCH 21/23] Update `tests/ui/stats/hir-stats.stderr` output --- tests/ui/stats/hir-stats.stderr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr index 579a5d5180ef6..dc24833c267c7 100644 --- a/tests/ui/stats/hir-stats.stderr +++ b/tests/ui/stats/hir-stats.stderr @@ -17,7 +17,7 @@ ast-stats-1 - Fn 96 ( 1.4%) 1 ast-stats-1 FnDecl 120 ( 1.8%) 5 24 ast-stats-1 FieldDef 160 ( 2.4%) 2 80 ast-stats-1 Stmt 160 ( 2.4%) 5 32 -ast-stats-1 - Local 32 ( 0.5%) 1 +ast-stats-1 - Let 32 ( 0.5%) 1 ast-stats-1 - MacCall 32 ( 0.5%) 1 ast-stats-1 - Expr 96 ( 1.4%) 3 ast-stats-1 Param 160 ( 2.4%) 4 40 @@ -75,7 +75,7 @@ ast-stats-2 - DocComment 32 ( 0.4%) 1 ast-stats-2 - Normal 96 ( 1.3%) 3 ast-stats-2 FieldDef 160 ( 2.2%) 2 80 ast-stats-2 Stmt 160 ( 2.2%) 5 32 -ast-stats-2 - Local 32 ( 0.4%) 1 +ast-stats-2 - Let 32 ( 0.4%) 1 ast-stats-2 - Semi 32 ( 0.4%) 1 ast-stats-2 - Expr 96 ( 1.3%) 3 ast-stats-2 Param 160 ( 2.2%) 4 40 @@ -131,7 +131,7 @@ hir-stats ImplItemRef 72 ( 0.8%) 2 36 hir-stats Arm 80 ( 0.9%) 2 40 hir-stats FieldDef 96 ( 1.1%) 2 48 hir-stats Stmt 96 ( 1.1%) 3 32 -hir-stats - Local 32 ( 0.4%) 1 +hir-stats - Let 32 ( 0.4%) 1 hir-stats - Semi 32 ( 0.4%) 1 hir-stats - Expr 32 ( 0.4%) 1 hir-stats FnDecl 120 ( 1.3%) 3 40 From 21904319f82606a67dcecf2984a653950be33949 Mon Sep 17 00:00:00 2001 From: James Farrell Date: Thu, 14 Mar 2024 16:42:15 +0000 Subject: [PATCH 22/23] Update version of cc crate Reason: In order to build the Windows version of the Rust toolchain for the Android platform, the following patch to the cc is crate is required to avoid incorrectly determining that we are building with the Android NDK: https://github.com/rust-lang/cc-rs/commit/57853c4bf8a89a0f4c9137eb367ac580305c6919 This patch is present in version 1.0.80 and newer versions of the cc crate. The rustc source distribution currently has 3 different versions of cc in the vendor directory, only one of which has the necessary fix. We (the Android Rust toolchain) are currently maintaining local patches to upgrade the cc crate dependency versions, which we would like to upstream. --- library/profiler_builtins/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/profiler_builtins/Cargo.toml b/library/profiler_builtins/Cargo.toml index 3371dfa124253..937149f8e86d6 100644 --- a/library/profiler_builtins/Cargo.toml +++ b/library/profiler_builtins/Cargo.toml @@ -13,4 +13,4 @@ core = { path = "../core" } compiler_builtins = { version = "0.1.0", features = ['rustc-dep-of-std'] } [build-dependencies] -cc = "1.0.69" +cc = "1.0.90" From 6e4cd8b7ccf12d6e4e97a44bbe4fd0093d12ca3d Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 14 Mar 2024 13:08:36 -0400 Subject: [PATCH 23/23] Make `SubdiagMessageOp` well-formed --- compiler/rustc_errors/src/diagnostic.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 0c3e7fb75b059..5d345e788e94e 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -189,7 +189,8 @@ where ); } -pub trait SubdiagMessageOp = Fn(&mut Diag<'_, G>, SubdiagMessage) -> SubdiagMessage; +pub trait SubdiagMessageOp = + Fn(&mut Diag<'_, G>, SubdiagMessage) -> SubdiagMessage; /// Trait implemented by lint types. This should not be implemented manually. Instead, use /// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic].