about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
Diffstat (limited to 'tests')
-rw-r--r--tests/codegen/align-byval-alignment-mismatch.rs126
-rw-r--r--tests/coverage/branch_generics.cov-map54
-rw-r--r--tests/coverage/branch_generics.coverage62
-rw-r--r--tests/coverage/branch_generics.rs19
-rw-r--r--tests/coverage/branch_guard.cov-map32
-rw-r--r--tests/coverage/branch_guard.coverage45
-rw-r--r--tests/coverage/branch_guard.rs37
-rw-r--r--tests/coverage/branch_if.cov-map188
-rw-r--r--tests/coverage/branch_if.coverage115
-rw-r--r--tests/coverage/branch_if.rs81
-rw-r--r--tests/coverage/branch_while.cov-map98
-rw-r--r--tests/coverage/branch_while.coverage74
-rw-r--r--tests/coverage/branch_while.rs58
-rw-r--r--tests/rustdoc-js/auxiliary/interner.rs245
-rw-r--r--tests/rustdoc-js/looks-like-rustc-interner.js9
-rw-r--r--tests/rustdoc-js/looks-like-rustc-interner.rs5
-rw-r--r--tests/ui/diagnostic_namespace/deny_malformed_attribute.rs7
-rw-r--r--tests/ui/diagnostic_namespace/deny_malformed_attribute.stderr14
-rw-r--r--tests/ui/lint/lint-qualification.fixed7
-rw-r--r--tests/ui/lint/lint-qualification.rs5
-rw-r--r--tests/ui/lint/lint-qualification.stderr30
-rw-r--r--tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.fixed50
-rw-r--r--tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.rs50
-rw-r--r--tests/ui/lint/unnecessary-qualification/lint-unnecessary-qualification-issue-121331.stderr31
-rw-r--r--tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.fixed11
-rw-r--r--tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.rs11
-rw-r--r--tests/ui/resolve/issue-113808-invalid-unused-qualifications-suggestion.stderr2
-rw-r--r--tests/ui/resolve/unused-qualifications-suggestion.fixed2
-rw-r--r--tests/ui/resolve/unused-qualifications-suggestion.rs2
-rw-r--r--tests/ui/resolve/unused-qualifications-suggestion.stderr2
-rw-r--r--tests/ui/simd/const-err-trumps-simd-err.rs24
-rw-r--r--tests/ui/simd/const-err-trumps-simd-err.stderr17
-rw-r--r--tests/ui/stats/hir-stats.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/in-where-clause.rs2
34 files changed, 1497 insertions, 24 deletions
diff --git a/tests/codegen/align-byval-alignment-mismatch.rs b/tests/codegen/align-byval-alignment-mismatch.rs
new file mode 100644
index 00000000000..306e3ce1358
--- /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);
+}
diff --git a/tests/coverage/branch_generics.cov-map b/tests/coverage/branch_generics.cov-map
new file mode 100644
index 00000000000..719e97efad4
--- /dev/null
+++ b/tests/coverage/branch_generics.cov-map
@@ -0,0 +1,54 @@
+Function name: branch_generics::print_size::<()>
+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: 5
+- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36)
+- 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::<u32>
+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: 5
+- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36)
+- 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::<u64>
+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: 5
+- Code(Counter(0)) at (prev + 6, 1) to (start + 1, 36)
+- 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))
+
diff --git a/tests/coverage/branch_generics.coverage b/tests/coverage/branch_generics.coverage
new file mode 100644
index 00000000000..e7cec151ce6
--- /dev/null
+++ b/tests/coverage/branch_generics.coverage
@@ -0,0 +1,62 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |//@ edition: 2021
+   LL|       |//@ compile-flags: -Zcoverage-options=branch
+   LL|       |//@ llvm-cov-flags: --show-branches=count
+   LL|       |
+   LL|      3|fn print_size<T>() {
+   LL|      3|    if std::mem::size_of::<T>() > 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");
+   LL|      2|    }
+   LL|      3|}
+  ------------------
+  | branch_generics::print_size::<()>:
+  |   LL|      1|fn print_size<T>() {
+  |   LL|      1|    if std::mem::size_of::<T>() > 4 {
+  |  ------------------
+  |  |  Branch (LL:8): [True: 0, False: 1]
+  |  ------------------
+  |   LL|      0|        println!("size > 4");
+  |   LL|      1|    } else {
+  |   LL|      1|        println!("size <= 4");
+  |   LL|      1|    }
+  |   LL|      1|}
+  ------------------
+  | branch_generics::print_size::<u32>:
+  |   LL|      1|fn print_size<T>() {
+  |   LL|      1|    if std::mem::size_of::<T>() > 4 {
+  |  ------------------
+  |  |  Branch (LL:8): [True: 0, False: 1]
+  |  ------------------
+  |   LL|      0|        println!("size > 4");
+  |   LL|      1|    } else {
+  |   LL|      1|        println!("size <= 4");
+  |   LL|      1|    }
+  |   LL|      1|}
+  ------------------
+  | branch_generics::print_size::<u64>:
+  |   LL|      1|fn print_size<T>() {
+  |   LL|      1|    if std::mem::size_of::<T>() > 4 {
+  |  ------------------
+  |  |  Branch (LL:8): [True: 1, False: 0]
+  |  ------------------
+  |   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::<u32>();
+   LL|       |    print_size::<u64>();
+   LL|       |}
+
diff --git a/tests/coverage/branch_generics.rs b/tests/coverage/branch_generics.rs
new file mode 100644
index 00000000000..d870ace7006
--- /dev/null
+++ b/tests/coverage/branch_generics.rs
@@ -0,0 +1,19 @@
+#![feature(coverage_attribute)]
+//@ edition: 2021
+//@ compile-flags: -Zcoverage-options=branch
+//@ llvm-cov-flags: --show-branches=count
+
+fn print_size<T>() {
+    if std::mem::size_of::<T>() > 4 {
+        println!("size > 4");
+    } else {
+        println!("size <= 4");
+    }
+}
+
+#[coverage(off)]
+fn main() {
+    print_size::<()>();
+    print_size::<u32>();
+    print_size::<u64>();
+}
diff --git a/tests/coverage/branch_guard.cov-map b/tests/coverage/branch_guard.cov-map
new file mode 100644
index 00000000000..0b3622f6347
--- /dev/null
+++ b/tests/coverage/branch_guard.cov-map
@@ -0,0 +1,32 @@
+Function name: branch_guard::branch_match_guard
+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: 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(5, Add)) at (prev + 3, 14) to (start + 2, 10)
+    = (c1 + c2)
+- 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
new file mode 100644
index 00000000000..f89b965b5d0
--- /dev/null
+++ b/tests/coverage/branch_guard.coverage
@@ -0,0 +1,45 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |//@ edition: 2021
+   LL|       |//@ compile-flags: -Zcoverage-options=branch
+   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<u32>) {
+   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
+  ------------------
+  |  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|        _ => {
+   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 00000000000..fa049e6206d
--- /dev/null
+++ b/tests/coverage/branch_guard.rs
@@ -0,0 +1,37 @@
+#![feature(coverage_attribute)]
+//@ edition: 2021
+//@ compile-flags: -Zcoverage-options=branch
+//@ llvm-cov-flags: --show-branches=count
+
+macro_rules! no_merge {
+    () => {
+        for _ in 0..1 {}
+    };
+}
+
+fn branch_match_guard(x: Option<u32>) {
+    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 00000000000..0dbfd92541b
--- /dev/null
+++ b/tests/coverage/branch_if.cov-map
@@ -0,0 +1,188 @@
+Function name: branch_if::branch_and
+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: 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(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 + (c3 + (c1 - c2)))
+
+Function name: branch_if::branch_not
+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: 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(40, Add), rhs = Counter(3)
+- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- 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 = 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(40, Add)) at (prev + 1, 8) to (start + 0, 10)
+    = (c2 + (c1 - c2))
+- 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(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(37, Sub)) at (prev + 2, 6) to (start + 0, 7)
+    = ((c3 + ((c2 + (c1 - c2)) - c3)) - c4)
+- Code(Expression(36, Add)) at (prev + 1, 8) to (start + 0, 12)
+    = (c4 + ((c3 + ((c2 + (c1 - c2)) - c3)) - c4))
+- 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(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 (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: 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(21, Add), rhs = Counter(3)
+- expression 3 operands: lhs = Counter(2), rhs = Expression(0, Sub)
+- 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(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(20, Sub)) at (prev + 2, 6) to (start + 0, 7)
+    = ((c2 + (c1 - c2)) - c3)
+- Code(Expression(19, Add)) at (prev + 1, 8) to (start + 0, 22)
+    = (c3 + ((c2 + (c1 - c2)) - c3))
+- 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(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 (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
+- 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: 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)
+- 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 00000000000..2a9a408b16a
--- /dev/null
+++ b/tests/coverage/branch_if.coverage
@@ -0,0 +1,115 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |//@ edition: 2021
+   LL|       |//@ compile-flags: -Zcoverage-options=branch
+   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 {
+  ------------------
+  |  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|}
+   LL|       |
+   LL|      3|fn branch_not_as(a: bool) {
+   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|}
+   LL|       |
+   LL|     15|fn branch_and(a: bool, b: bool) {
+   LL|     15|    no_merge!();
+   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");
+   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
+  ------------------
+  |  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");
+   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 00000000000..151eede75bb
--- /dev/null
+++ b/tests/coverage/branch_if.rs
@@ -0,0 +1,81 @@
+#![feature(coverage_attribute)]
+//@ edition: 2021
+//@ compile-flags: -Zcoverage-options=branch
+//@ 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 00000000000..d5f54f1abea
--- /dev/null
+++ b/tests/coverage/branch_while.cov-map
@@ -0,0 +1,98 @@
+Function name: branch_while::while_cond
+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: 3
+- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 1 operands: lhs = Expression(0, Add), rhs = Counter(2)
+- 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(2, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = ((c1 + c2) - c2)
+
+Function name: branch_while::while_cond_not
+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: 3
+- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 1 operands: lhs = Expression(0, Add), rhs = Counter(2)
+- 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(2, Sub)) at (prev + 3, 1) to (start + 0, 2)
+    = ((c1 + c2) - c2)
+
+Function name: branch_while::while_op_and
+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: 4
+- expression 0 operands: lhs = Counter(1), rhs = Counter(2)
+- expression 1 operands: lhs = Expression(0, Add), rhs = Counter(3)
+- 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)
+- 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(3, Add)) at (prev + 4, 1) to (start + 0, 2)
+    = (c4 + c3)
+
+Function name: branch_while::while_op_or
+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: 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 = 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)
+- 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))
+- 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)
+- 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(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
new file mode 100644
index 00000000000..8d9a6c3bc68
--- /dev/null
+++ b/tests/coverage/branch_while.coverage
@@ -0,0 +1,74 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |//@ edition: 2021
+   LL|       |//@ compile-flags: -Zcoverage-options=branch
+   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 {
+  ------------------
+  |  Branch (LL:11): [True: 8, False: 1]
+  ------------------
+   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) {
+  ------------------
+  |  Branch (LL:11): [True: 8, False: 1]
+  ------------------
+   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 {
+  ------------------
+  |  Branch (LL:11): [True: 5, False: 0]
+  |  Branch (LL:20): [True: 4, False: 1]
+  ------------------
+   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
+  ------------------
+  |  Branch (LL:11): [True: 4, False: 5]
+  |  Branch (LL:20): [True: 4, False: 1]
+  ------------------
+   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 00000000000..507815fbecb
--- /dev/null
+++ b/tests/coverage/branch_while.rs
@@ -0,0 +1,58 @@
+#![feature(coverage_attribute)]
+//@ edition: 2021
+//@ compile-flags: -Zcoverage-options=branch
+//@ 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();
+}
diff --git a/tests/rustdoc-js/auxiliary/interner.rs b/tests/rustdoc-js/auxiliary/interner.rs
new file mode 100644
index 00000000000..c95029be9f0
--- /dev/null
+++ b/tests/rustdoc-js/auxiliary/interner.rs
@@ -0,0 +1,245 @@
+#![feature(associated_type_defaults)]
+
+use std::cmp::Ord;
+use std::fmt::{Debug, Formatter};
+use std::hash::Hash;
+use std::ops::ControlFlow;
+
+pub trait Interner: Sized {
+    type DefId: Copy + Debug + Hash + Ord;
+    type AdtDef: Copy + Debug + Hash + Ord;
+    type GenericArgs: Copy
+        + DebugWithInfcx<Self>
+        + Hash
+        + Ord
+        + IntoIterator<Item = Self::GenericArg>;
+    type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Ord;
+    type Term: Copy + Debug + Hash + Ord;
+    type Binder<T: TypeVisitable<Self>>: BoundVars<Self> + TypeSuperVisitable<Self>;
+    type BoundVars: IntoIterator<Item = Self::BoundVar>;
+    type BoundVar;
+    type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator<Item = CanonicalVarInfo<Self>>;
+    type Ty: Copy
+        + DebugWithInfcx<Self>
+        + Hash
+        + Ord
+        + Into<Self::GenericArg>
+        + IntoKind<Kind = TyKind<Self>>
+        + TypeSuperVisitable<Self>
+        + Flags
+        + Ty<Self>;
+    type Tys: Copy + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
+    type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Ord;
+    type ParamTy: Copy + Debug + Hash + Ord;
+    type BoundTy: Copy + Debug + Hash + Ord;
+    type PlaceholderTy: Copy + Debug + Hash + Ord + PlaceholderLike;
+    type ErrorGuaranteed: Copy + Debug + Hash + Ord;
+    type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Ord;
+    type PolyFnSig: Copy + DebugWithInfcx<Self> + Hash + Ord;
+    type AllocId: Copy + Debug + Hash + Ord;
+    type Const: Copy
+        + DebugWithInfcx<Self>
+        + Hash
+        + Ord
+        + Into<Self::GenericArg>
+        + IntoKind<Kind = ConstKind<Self>>
+        + ConstTy<Self>
+        + TypeSuperVisitable<Self>
+        + Flags
+        + Const<Self>;
+    type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Ord;
+    type PlaceholderConst: Copy + Debug + Hash + Ord + PlaceholderLike;
+    type ParamConst: Copy + Debug + Hash + Ord;
+    type BoundConst: Copy + Debug + Hash + Ord;
+    type ValueConst: Copy + Debug + Hash + Ord;
+    type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Ord;
+    type Region: Copy
+        + DebugWithInfcx<Self>
+        + Hash
+        + Ord
+        + Into<Self::GenericArg>
+        + IntoKind<Kind = RegionKind<Self>>
+        + Flags
+        + Region<Self>;
+    type EarlyParamRegion: Copy + Debug + Hash + Ord;
+    type LateParamRegion: Copy + Debug + Hash + Ord;
+    type BoundRegion: Copy + Debug + Hash + Ord;
+    type InferRegion: Copy + DebugWithInfcx<Self> + Hash + Ord;
+    type PlaceholderRegion: Copy + Debug + Hash + Ord + PlaceholderLike;
+    type Predicate: Copy + Debug + Hash + Eq + TypeSuperVisitable<Self> + Flags;
+    type TraitPredicate: Copy + Debug + Hash + Eq;
+    type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
+    type TypeOutlivesPredicate: Copy + Debug + Hash + Eq;
+    type ProjectionPredicate: Copy + Debug + Hash + Eq;
+    type NormalizesTo: Copy + Debug + Hash + Eq;
+    type SubtypePredicate: Copy + Debug + Hash + Eq;
+    type CoercePredicate: Copy + Debug + Hash + Eq;
+    type ClosureKind: Copy + Debug + Hash + Eq;
+
+    // Required method
+    fn mk_canonical_var_infos(
+        self,
+        infos: &[CanonicalVarInfo<Self>]
+    ) -> Self::CanonicalVars;
+}
+
+pub trait DebugWithInfcx<I: Interner>: Debug {
+    // Required method
+    fn fmt<Infcx: InferCtxtLike<Interner = I>>(
+        this: WithInfcx<'_, Infcx, &Self>,
+        f: &mut Formatter<'_>
+    ) -> std::fmt::Result;
+}
+
+pub trait TypeVisitable<I: Interner>: Debug + Clone {
+    // Required method
+    fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result;
+}
+
+pub trait BoundVars<I: Interner> {
+    // Required methods
+    fn bound_vars(&self) -> I::BoundVars;
+    fn has_no_bound_vars(&self) -> bool;
+}
+
+pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
+    // Required method
+    fn super_visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result;
+}
+
+pub struct CanonicalVarInfo<I: Interner> {
+    pub kind: CanonicalVarKind<I>,
+}
+
+pub struct CanonicalVarKind<I>(std::marker::PhantomData<I>);
+
+pub struct TyKind<I>(std::marker::PhantomData<I>);
+
+pub trait IntoKind {
+    type Kind;
+
+    // Required method
+    fn kind(self) -> Self::Kind;
+}
+pub trait Flags {
+    // Required methods
+    fn flags(&self) -> TypeFlags;
+    fn outer_exclusive_binder(&self) -> DebruijnIndex;
+}
+pub struct TypeFlags;
+
+pub trait Ty<I: Interner<Ty = Self>> {
+    // Required method
+    fn new_anon_bound(
+        interner: I,
+        debruijn: DebruijnIndex,
+        var: BoundVar
+    ) -> Self;
+}
+
+pub trait PlaceholderLike {
+    // Required methods
+    fn universe(self) -> UniverseIndex;
+    fn var(self) -> BoundVar;
+    fn with_updated_universe(self, ui: UniverseIndex) -> Self;
+    fn new(ui: UniverseIndex, var: BoundVar) -> Self;
+}
+
+pub struct UniverseIndex;
+
+pub struct BoundVar;
+
+pub struct ConstKind<I>(std::marker::PhantomData<I>);
+pub trait Const<I: Interner<Const = Self>> {
+    // Required method
+    fn new_anon_bound(
+        interner: I,
+        debruijn: DebruijnIndex,
+        var: BoundVar,
+        ty: I::Ty
+    ) -> Self;
+}
+
+pub trait ConstTy<I: Interner> {
+    // Required method
+    fn ty(self) -> I::Ty;
+}
+
+pub struct DebruijnIndex;
+
+pub struct RegionKind<I>(std::marker::PhantomData<I>);
+pub trait Region<I: Interner<Region = Self>> {
+    // Required method
+    fn new_anon_bound(
+        interner: I,
+        debruijn: DebruijnIndex,
+        var: BoundVar
+    ) -> Self;
+}
+
+pub trait TypeVisitor<I: Interner>: Sized {
+    type Result: VisitorResult = ();
+
+    // Provided methods
+    fn visit_binder<T: TypeVisitable<I>>(
+        &mut self,
+        t: &I::Binder<T>
+    ) -> Self::Result { unimplemented!() }
+    fn visit_ty(&mut self, t: I::Ty) -> Self::Result { unimplemented!() }
+    fn visit_region(&mut self, _r: I::Region) -> Self::Result { unimplemented!() }
+    fn visit_const(&mut self, c: I::Const) -> Self::Result { unimplemented!() }
+    fn visit_predicate(&mut self, p: I::Predicate) -> Self::Result { unimplemented!() }
+}
+
+pub trait VisitorResult {
+    type Residual;
+
+    // Required methods
+    fn output() -> Self;
+    fn from_residual(residual: Self::Residual) -> Self;
+    fn from_branch(b: ControlFlow<Self::Residual>) -> Self;
+    fn branch(self) -> ControlFlow<Self::Residual>;
+}
+
+impl VisitorResult for () {
+    type Residual = ();
+    fn output() -> Self {}
+    fn from_residual(_: Self::Residual) -> Self {}
+    fn from_branch(_: ControlFlow<Self::Residual>) -> Self {}
+    fn branch(self) -> ControlFlow<Self::Residual> { ControlFlow::Continue(()) }
+}
+
+pub struct WithInfcx<'a, Infcx: InferCtxtLike, T> {
+    pub data: T,
+    pub infcx: &'a Infcx,
+}
+
+pub trait InferCtxtLike {
+    type Interner: Interner;
+
+    // Required methods
+    fn interner(&self) -> Self::Interner;
+    fn universe_of_ty(&self, ty: TyVid) -> Option<UniverseIndex>;
+    fn root_ty_var(&self, vid: TyVid) -> TyVid;
+    fn probe_ty_var(
+        &self,
+        vid: TyVid
+    ) -> Option<<Self::Interner as Interner>::Ty>;
+    fn universe_of_lt(
+        &self,
+        lt: <Self::Interner as Interner>::InferRegion
+    ) -> Option<UniverseIndex>;
+    fn opportunistic_resolve_lt_var(
+        &self,
+        vid: <Self::Interner as Interner>::InferRegion
+    ) -> Option<<Self::Interner as Interner>::Region>;
+    fn universe_of_ct(&self, ct: ConstVid) -> Option<UniverseIndex>;
+    fn root_ct_var(&self, vid: ConstVid) -> ConstVid;
+    fn probe_ct_var(
+        &self,
+        vid: ConstVid
+    ) -> Option<<Self::Interner as Interner>::Const>;
+}
+
+pub struct TyVid;
+pub struct ConstVid;
diff --git a/tests/rustdoc-js/looks-like-rustc-interner.js b/tests/rustdoc-js/looks-like-rustc-interner.js
new file mode 100644
index 00000000000..a4806d23499
--- /dev/null
+++ b/tests/rustdoc-js/looks-like-rustc-interner.js
@@ -0,0 +1,9 @@
+// https://github.com/rust-lang/rust/pull/122247
+// exact-check
+
+const EXPECTED = {
+    'query': 'canonicalvarinfo, intoiterator -> intoiterator',
+    'others': [
+        { 'path': 'looks_like_rustc_interner::Interner', 'name': 'mk_canonical_var_infos' },
+    ],
+};
diff --git a/tests/rustdoc-js/looks-like-rustc-interner.rs b/tests/rustdoc-js/looks-like-rustc-interner.rs
new file mode 100644
index 00000000000..f304e28d952
--- /dev/null
+++ b/tests/rustdoc-js/looks-like-rustc-interner.rs
@@ -0,0 +1,5 @@
+//@ aux-crate:interner=interner.rs
+// https://github.com/rust-lang/rust/pull/122247
+extern crate interner;
+#[doc(inline)]
+pub use interner::*;
diff --git a/tests/ui/diagnostic_namespace/deny_malformed_attribute.rs b/tests/ui/diagnostic_namespace/deny_malformed_attribute.rs
new file mode 100644
index 00000000000..1d946a14aff
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/deny_malformed_attribute.rs
@@ -0,0 +1,7 @@
+#![deny(unknown_or_malformed_diagnostic_attributes)]
+
+#[diagnostic::unknown_attribute]
+//~^ERROR unknown diagnostic attribute
+struct Foo;
+
+fn main() {}
diff --git a/tests/ui/diagnostic_namespace/deny_malformed_attribute.stderr b/tests/ui/diagnostic_namespace/deny_malformed_attribute.stderr
new file mode 100644
index 00000000000..a646d3613de
--- /dev/null
+++ b/tests/ui/diagnostic_namespace/deny_malformed_attribute.stderr
@@ -0,0 +1,14 @@
+error: unknown diagnostic attribute
+  --> $DIR/deny_malformed_attribute.rs:3:15
+   |
+LL | #[diagnostic::unknown_attribute]
+   |               ^^^^^^^^^^^^^^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/deny_malformed_attribute.rs:1:9
+   |
+LL | #![deny(unknown_or_malformed_diagnostic_attributes)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/lint/lint-qualification.fixed b/tests/ui/lint/lint-qualification.fixed
index 2b1f8b59175..6fe6ba2792f 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 _ = <bool as Default>::default(); // issue #121999
     //~^ ERROR: unnecessary qualification
diff --git a/tests/ui/lint/lint-qualification.rs b/tests/ui/lint/lint-qualification.rs
index 002fdbf7724..19d339b006c 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 _ = <bool as ::std::default::Default>::default(); // issue #121999
     //~^ ERROR: unnecessary qualification
diff --git a/tests/ui/lint/lint-qualification.stderr b/tests/ui/lint/lint-qualification.stderr
index 8dddcf23f75..9e5c9b2df13 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<String> = std::vec::Vec::<String>::new();
    |            ^^^^^^^^^^^^^^^^^^^^^
@@ -64,7 +64,7 @@ LL +     let _: Vec<String> = std::vec::Vec::<String>::new();
    |
 
 error: unnecessary qualification
-  --> $DIR/lint-qualification.rs:20:36
+  --> $DIR/lint-qualification.rs:21:36
    |
 LL |     let _: std::vec::Vec<String> = std::vec::Vec::<String>::new();
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -75,20 +75,20 @@ LL -     let _: std::vec::Vec<String> = std::vec::Vec::<String>::new();
 LL +     let _: std::vec::Vec<String> = Vec::<String>::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 _ = <bool as ::std::default::Default>::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 00000000000..d554bbfcc98
--- /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<T>(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 00000000000..4d79f5ab745
--- /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<T>(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 00000000000..52ed13ea150
--- /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 8a67b20eec1..d95faef8ac4 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<str> 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<str> for C {
+    type Output = ();
+    fn index(&self, _: str) -> &Self::Output {
+        &()
+    }
+}
+
 mod inner {
     pub trait Trait<T> {}
 }
@@ -29,4 +39,5 @@ use inner::Trait;
 impl Trait<u8> for () {}
 //~^ ERROR unnecessary qualification
 
+impl Trait<A> 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 528edb331cf..0eee8f71ad4 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<str> 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<str> for C {
+    type Output = ();
+    fn index(&self, _: str) -> &Self::Output {
+        &()
+    }
+}
+
 mod inner {
     pub trait Trait<T> {}
 }
@@ -29,4 +39,5 @@ use inner::Trait;
 impl inner::Trait<u8> for () {}
 //~^ ERROR unnecessary qualification
 
+impl Trait<A> 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 bcda7210712..e105b754b71 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<str> 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<u8> for () {}
    |      ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/resolve/unused-qualifications-suggestion.fixed b/tests/ui/resolve/unused-qualifications-suggestion.fixed
index 6935f611b36..22e0daea467 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 b3fe04ff0ea..89516c1344a 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 e3dac37fc6e..5b71ba9e222 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();
    |     ^^^^^^^^^^^^^^
diff --git a/tests/ui/simd/const-err-trumps-simd-err.rs b/tests/ui/simd/const-err-trumps-simd-err.rs
new file mode 100644
index 00000000000..06a747273ab
--- /dev/null
+++ b/tests/ui/simd/const-err-trumps-simd-err.rs
@@ -0,0 +1,24 @@
+//@build-fail
+//! Make sure that monomorphization-time const errors from `static_assert` take priority over the
+//! error from simd_extract. Basically this checks that if a const fails to evaluate in some
+//! function, we don't bother codegen'ing the function.
+#![feature(generic_arg_infer)]
+#![feature(core_intrinsics)]
+#![feature(repr_simd)]
+#![feature(inline_const)]
+use std::intrinsics::simd::*;
+
+#[repr(simd)]
+#[allow(non_camel_case_types)]
+struct int8x4_t(u8,u8,u8,u8);
+
+fn get_elem<const LANE: u32>(a: int8x4_t) -> u8 {
+    const { assert!(LANE < 4); } // the error should be here...
+    //~^ ERROR failed
+    //~| assertion failed
+    unsafe { simd_extract(a, LANE) } // ...not here
+}
+
+fn main() {
+    get_elem::<4>(int8x4_t(0,0,0,0));
+}
diff --git a/tests/ui/simd/const-err-trumps-simd-err.stderr b/tests/ui/simd/const-err-trumps-simd-err.stderr
new file mode 100644
index 00000000000..6e6aba8b6f1
--- /dev/null
+++ b/tests/ui/simd/const-err-trumps-simd-err.stderr
@@ -0,0 +1,17 @@
+error[E0080]: evaluation of `get_elem::<4>::{constant#0}` failed
+  --> $DIR/const-err-trumps-simd-err.rs:16:13
+   |
+LL |     const { assert!(LANE < 4); } // the error should be here...
+   |             ^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'assertion failed: LANE < 4', $DIR/const-err-trumps-simd-err.rs:16:13
+   |
+   = note: this error originates in the macro `assert` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+note: the above error was encountered while instantiating `fn get_elem::<4>`
+  --> $DIR/const-err-trumps-simd-err.rs:23:5
+   |
+LL |     get_elem::<4>(int8x4_t(0,0,0,0));
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/stats/hir-stats.stderr b/tests/ui/stats/hir-stats.stderr
index 579a5d5180e..dc24833c267 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
diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.rs b/tests/ui/type-alias-impl-trait/in-where-clause.rs
index 0ad6e7a6f60..7c0de39c7c9 100644
--- a/tests/ui/type-alias-impl-trait/in-where-clause.rs
+++ b/tests/ui/type-alias-impl-trait/in-where-clause.rs
@@ -1,5 +1,5 @@
 //! We evaluate `1 + 2` with `Reveal::All` during typeck, causing
-//! us to to get the concrete type of `Bar` while computing it.
+//! us to get the concrete type of `Bar` while computing it.
 //! This again requires type checking `foo`.
 #![feature(type_alias_impl_trait)]
 type Bar = impl Sized;