From acd6e4c0fd10ac356d2bddbf47595748d0e3f2db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 3 May 2024 10:28:09 +0000 Subject: [PATCH 01/10] tests(coverage): Add mcdc_non_control_flow tests --- tests/coverage/mcdc_non_control_flow.cov-map | 199 ++++++++++++++++++ tests/coverage/mcdc_non_control_flow.coverage | 98 +++++++++ tests/coverage/mcdc_non_control_flow.rs | 72 +++++++ 3 files changed, 369 insertions(+) create mode 100644 tests/coverage/mcdc_non_control_flow.cov-map create mode 100644 tests/coverage/mcdc_non_control_flow.coverage create mode 100644 tests/coverage/mcdc_non_control_flow.rs diff --git a/tests/coverage/mcdc_non_control_flow.cov-map b/tests/coverage/mcdc_non_control_flow.cov-map new file mode 100644 index 0000000000000..3f422d85e7992 --- /dev/null +++ b/tests/coverage/mcdc_non_control_flow.cov-map @@ -0,0 +1,199 @@ +Function name: mcdc_non_control_flow::assign_3 +Raw bytes (73): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 09, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 22, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 20, 1e, 11, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 20, 09, 0d, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 9 +- expression 0 operands: lhs = Counter(1), rhs = Expression(1, Add) +- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(4) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +- expression 4 operands: lhs = Counter(0), rhs = Counter(1) +- expression 5 operands: lhs = Expression(8, Sub), rhs = Counter(4) +- expression 6 operands: lhs = Counter(0), rhs = Counter(1) +- expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(4) +- expression 8 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 9 +- Code(Counter(0)) at (prev + 22, 1) to (start + 0, 40) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = (c1 + ((c2 + c3) + c4)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(8, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Expression(8, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c0 - c1) +- Branch { true: Expression(7, Sub), false: Counter(4) } at (prev + 0, 18) to (start + 0, 19) + true = ((c0 - c1) - c4) + false = c4 +- Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 24) + = ((c0 - c1) - c4) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 23) to (start + 0, 24) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = (c1 + ((c2 + c3) + c4)) + +Function name: mcdc_non_control_flow::assign_3_bis +Raw bytes (82): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 02, 00, 00, 00, 12, 00, 13, 13, 00, 17, 00, 18, 20, 0d, 11, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 7 +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(4) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(1), rhs = Counter(2) +- expression 4 operands: lhs = Expression(5, Sub), rhs = Expression(6, Sub) +- expression 5 operands: lhs = Counter(1), rhs = Counter(2) +- expression 6 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 10 +- Code(Counter(0)) at (prev + 27, 1) to (start + 0, 44) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = ((c2 + c3) + c4) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) +- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Counter(2), false: Expression(5, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = (c1 - c2) +- Code(Expression(4, Add)) at (prev + 0, 23) to (start + 0, 24) + = ((c1 - c2) + (c0 - c1)) +- Branch { true: Counter(3), false: Counter(4) } at (prev + 0, 23) to (start + 0, 24) + true = c3 + false = c4 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = ((c2 + c3) + c4) + +Function name: mcdc_non_control_flow::assign_and +Raw bytes (51): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 07, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(3, Sub) +- expression 1 operands: lhs = Counter(2), rhs = Counter(3) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 12, 1) to (start + 0, 33) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = ((c2 + c3) + (c0 - c1)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = ((c2 + c3) + (c0 - c1)) + +Function name: mcdc_non_control_flow::assign_or +Raw bytes (51): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 07, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 4 +- expression 0 operands: lhs = Expression(1, Add), rhs = Counter(3) +- expression 1 operands: lhs = Counter(1), rhs = Counter(2) +- expression 2 operands: lhs = Counter(0), rhs = Counter(1) +- expression 3 operands: lhs = Counter(0), rhs = Counter(1) +Number of file 0 mappings: 7 +- Code(Counter(0)) at (prev + 17, 1) to (start + 0, 32) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = ((c1 + c2) + c3) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Expression(3, Sub)) at (prev + 0, 18) to (start + 0, 19) + = (c0 - c1) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = ((c1 + c2) + c3) + +Function name: mcdc_non_control_flow::foo +Raw bytes (9): 0x[01, 01, 00, 01, 01, 25, 01, 02, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 0 +Number of file 0 mappings: 1 +- Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2) + +Function name: mcdc_non_control_flow::func_call +Raw bytes (39): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 05, 01, 29, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 0d, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 3 +- expression 0 operands: lhs = Counter(0), rhs = Counter(1) +- expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub) +- expression 2 operands: lhs = Counter(2), rhs = Counter(3) +Number of file 0 mappings: 5 +- Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10) +- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 9) to (start + 0, 10) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 14) to (start + 0, 15) + true = c2 + false = c3 +- Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) + = ((c2 + c3) + (c0 - c1)) + +Function name: mcdc_non_control_flow::right_comb_tree +Raw bytes (117): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0d, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 1a, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 20, 4a, 19, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 20, 46, 15, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 20, 42, 11, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 20, 09, 0d, 00, 24, 00, 27, 03, 01, 05, 01, 02] +Number of files: 1 +- file 0 => global file 1 +Number of expressions: 19 +- expression 0 operands: lhs = Expression(1, Add), rhs = Expression(6, Sub) +- expression 1 operands: lhs = Expression(2, Add), rhs = Counter(6) +- expression 2 operands: lhs = Expression(3, Add), rhs = Counter(5) +- expression 3 operands: lhs = Expression(4, Add), rhs = Counter(4) +- expression 4 operands: lhs = Counter(2), rhs = Counter(3) +- expression 5 operands: lhs = Counter(0), rhs = Counter(1) +- expression 6 operands: lhs = Counter(0), rhs = Counter(1) +- expression 7 operands: lhs = Counter(1), rhs = Counter(6) +- expression 8 operands: lhs = Counter(1), rhs = Counter(6) +- expression 9 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 10 operands: lhs = Counter(1), rhs = Counter(6) +- expression 11 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 12 operands: lhs = Counter(1), rhs = Counter(6) +- expression 13 operands: lhs = Expression(17, Sub), rhs = Counter(4) +- expression 14 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 15 operands: lhs = Counter(1), rhs = Counter(6) +- expression 16 operands: lhs = Expression(17, Sub), rhs = Counter(4) +- expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5) +- expression 18 operands: lhs = Counter(1), rhs = Counter(6) +Number of file 0 mappings: 13 +- Code(Counter(0)) at (prev + 32, 1) to (start + 0, 65) +- Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) + = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) +- Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) +- Branch { true: Counter(1), false: Expression(6, Sub) } at (prev + 0, 13) to (start + 0, 14) + true = c1 + false = (c0 - c1) +- Code(Counter(1)) at (prev + 0, 19) to (start + 0, 20) +- Branch { true: Expression(18, Sub), false: Counter(6) } at (prev + 0, 19) to (start + 0, 20) + true = (c1 - c6) + false = c6 +- Code(Expression(18, Sub)) at (prev + 0, 25) to (start + 0, 26) + = (c1 - c6) +- Branch { true: Expression(17, Sub), false: Counter(5) } at (prev + 0, 25) to (start + 0, 26) + true = ((c1 - c6) - c5) + false = c5 +- Code(Expression(17, Sub)) at (prev + 0, 31) to (start + 0, 32) + = ((c1 - c6) - c5) +- Branch { true: Expression(16, Sub), false: Counter(4) } at (prev + 0, 31) to (start + 0, 32) + true = (((c1 - c6) - c5) - c4) + false = c4 +- Code(Expression(16, Sub)) at (prev + 0, 36) to (start + 0, 39) + = (((c1 - c6) - c5) - c4) +- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 36) to (start + 0, 39) + true = c2 + false = c3 +- Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) + = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) + diff --git a/tests/coverage/mcdc_non_control_flow.coverage b/tests/coverage/mcdc_non_control_flow.coverage new file mode 100644 index 0000000000000..4e53a7a0d8e85 --- /dev/null +++ b/tests/coverage/mcdc_non_control_flow.coverage @@ -0,0 +1,98 @@ + LL| |#![feature(coverage_attribute)] + LL| |//@ edition: 2021 + LL| |//@ min-llvm-version: 18 + LL| |//@ compile-flags: -Zcoverage-options=mcdc + LL| |//@ llvm-cov-flags: --show-mcdc + LL| | + LL| |// This test ensures that boolean expressions that are not inside control flow + LL| |// decisions are correctly instrumented. + LL| | + LL| |use core::hint::black_box; + LL| | + LL| 3|fn assign_and(a: bool, b: bool) { + LL| 3| let x = a && b; + ^2 + LL| 3| black_box(x); + LL| 3|} + LL| | + LL| 3|fn assign_or(a: bool, b: bool) { + LL| 3| let x = a || b; + ^1 + LL| 3| black_box(x); + LL| 3|} + LL| | + LL| 4|fn assign_3(a: bool, b: bool, c: bool) { + LL| 4| let x = a || b && c; + ^2 ^1 + LL| 4| black_box(x); + LL| 4|} + LL| | + LL| 4|fn assign_3_bis(a: bool, b: bool, c: bool) { + LL| 4| let x = a && b || c; + ^2 ^3 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:19) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, - = F } + | 2 { T, F = F } + | 3 { T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | MC/DC Coverage for Decision: 100.00% + | + ------------------ + LL| 4| black_box(x); + LL| 4|} + LL| | + LL| 3|fn right_comb_tree(a: bool, b: bool, c: bool, d: bool, e: bool) { + LL| 3| let x = a && (b && (c && (d && (e)))); + ^2 ^1 ^1 ^1 + LL| 3| black_box(x); + LL| 3|} + LL| | + LL| 3|fn foo(a: bool) -> bool { + LL| 3| black_box(a) + LL| 3|} + LL| | + LL| 3|fn func_call(a: bool, b: bool) { + LL| 3| foo(a && b); + ^2 + LL| 3|} + LL| | + LL| |#[coverage(off)] + LL| |fn main() { + LL| | assign_and(true, false); + LL| | assign_and(true, true); + LL| | assign_and(false, false); + LL| | + LL| | assign_or(true, false); + LL| | assign_or(true, true); + LL| | assign_or(false, false); + LL| | + LL| | assign_3(true, false, false); + LL| | assign_3(true, true, false); + LL| | assign_3(false, false, true); + LL| | assign_3(false, true, true); + LL| | + LL| | assign_3_bis(true, false, false); + LL| | assign_3_bis(true, true, false); + LL| | assign_3_bis(false, false, true); + LL| | assign_3_bis(false, true, true); + LL| | + LL| | right_comb_tree(false, false, false, true, true); + LL| | right_comb_tree(true, false, false, true, true); + LL| | right_comb_tree(true, true, true, true, true); + LL| | + LL| | func_call(true, false); + LL| | func_call(true, true); + LL| | func_call(false, false); + LL| |} + diff --git a/tests/coverage/mcdc_non_control_flow.rs b/tests/coverage/mcdc_non_control_flow.rs new file mode 100644 index 0000000000000..85c0a6c6ae58a --- /dev/null +++ b/tests/coverage/mcdc_non_control_flow.rs @@ -0,0 +1,72 @@ +#![feature(coverage_attribute)] +//@ edition: 2021 +//@ min-llvm-version: 18 +//@ compile-flags: -Zcoverage-options=mcdc +//@ llvm-cov-flags: --show-mcdc + +// This test ensures that boolean expressions that are not inside control flow +// decisions are correctly instrumented. + +use core::hint::black_box; + +fn assign_and(a: bool, b: bool) { + let x = a && b; + black_box(x); +} + +fn assign_or(a: bool, b: bool) { + let x = a || b; + black_box(x); +} + +fn assign_3(a: bool, b: bool, c: bool) { + let x = a || b && c; + black_box(x); +} + +fn assign_3_bis(a: bool, b: bool, c: bool) { + let x = a && b || c; + black_box(x); +} + +fn right_comb_tree(a: bool, b: bool, c: bool, d: bool, e: bool) { + let x = a && (b && (c && (d && (e)))); + black_box(x); +} + +fn foo(a: bool) -> bool { + black_box(a) +} + +fn func_call(a: bool, b: bool) { + foo(a && b); +} + +#[coverage(off)] +fn main() { + assign_and(true, false); + assign_and(true, true); + assign_and(false, false); + + assign_or(true, false); + assign_or(true, true); + assign_or(false, false); + + assign_3(true, false, false); + assign_3(true, true, false); + assign_3(false, false, true); + assign_3(false, true, true); + + assign_3_bis(true, false, false); + assign_3_bis(true, true, false); + assign_3_bis(false, false, true); + assign_3_bis(false, true, true); + + right_comb_tree(false, false, false, true, true); + right_comb_tree(true, false, false, true, true); + right_comb_tree(true, true, true, true, true); + + func_call(true, false); + func_call(true, true); + func_call(false, false); +} From 9b05e154f39f1a413ebc09c8f1dd751f991b3bba Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 8 Jun 2024 12:04:38 +0200 Subject: [PATCH 02/10] StorageLive: refresh storage (instead of UB) when local is already live --- compiler/rustc_const_eval/messages.ftl | 2 -- .../rustc_const_eval/src/interpret/eval_context.rs | 8 +++----- compiler/rustc_middle/src/mir/syntax.rs | 11 +++++++---- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 2dbeb7d5e0ca4..14c036b8df9b5 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -73,8 +73,6 @@ const_eval_division_by_zero = dividing by zero const_eval_division_overflow = overflow in signed division (dividing MIN by -1) -const_eval_double_storage_live = - StorageLive on a local that was already live const_eval_dyn_call_not_a_method = `dyn` call trying to call something that is not a method diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 7c2100fcbe38a..c1daa2fac338e 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1103,11 +1103,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { Operand::Immediate(Immediate::Uninit) }); - // StorageLive expects the local to be dead, and marks it live. + // If the local is already live, deallocate its old memory. let old = mem::replace(&mut self.frame_mut().locals[local].value, local_val); - if !matches!(old, LocalValue::Dead) { - throw_ub_custom!(fluent::const_eval_double_storage_live); - } + self.deallocate_local(old)?; Ok(()) } @@ -1121,7 +1119,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { assert!(local != mir::RETURN_PLACE, "Cannot make return place dead"); trace!("{:?} is now dead", local); - // It is entirely okay for this local to be already dead (at least that's how we currently generate MIR) + // If the local is already dead, this is a NOP. let old = mem::replace(&mut self.frame_mut().locals[local].value, LocalValue::Dead); self.deallocate_local(old)?; Ok(()) diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index ebe77a1abfd8b..9855c72197edc 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -361,16 +361,19 @@ pub enum StatementKind<'tcx> { /// At any point during the execution of a function, each local is either allocated or /// unallocated. Except as noted below, all locals except function parameters are initially /// unallocated. `StorageLive` statements cause memory to be allocated for the local while - /// `StorageDead` statements cause the memory to be freed. Using a local in any way (not only - /// reading/writing from it) while it is unallocated is UB. + /// `StorageDead` statements cause the memory to be freed. In other words, + /// `StorageLive`/`StorageDead` act like the heap operations `allocate`/`deallocate`, but for + /// stack-allocated local variables. Using a local in any way (not only reading/writing from it) + /// while it is unallocated is UB. /// /// Some locals have no `StorageLive` or `StorageDead` statements within the entire MIR body. /// These locals are implicitly allocated for the full duration of the function. There is a /// convenience method at `rustc_mir_dataflow::storage::always_storage_live_locals` for /// computing these locals. /// - /// If the local is already allocated, calling `StorageLive` again is UB. However, for an - /// unallocated local an additional `StorageDead` all is simply a nop. + /// If the local is already allocated, calling `StorageLive` again will implicitly free the + /// local and then allocate fresh uninitilized memory. If a local is already deallocated, + /// calling `StorageDead` again is a NOP. StorageLive(Local), /// See `StorageLive` above. From 408c8eb983b2c460e56e1e71db26d6b7e76aa695 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 14 Jun 2024 12:14:32 +0200 Subject: [PATCH 03/10] add Miri tests --- .../miri/tests/fail/storage-live-dead-var.rs | 14 ++++++++++++++ .../tests/fail/storage-live-dead-var.stderr | 15 +++++++++++++++ .../miri/tests/fail/storage-live-resets-var.rs | 17 +++++++++++++++++ .../tests/fail/storage-live-resets-var.stderr | 15 +++++++++++++++ 4 files changed, 61 insertions(+) create mode 100644 src/tools/miri/tests/fail/storage-live-dead-var.rs create mode 100644 src/tools/miri/tests/fail/storage-live-dead-var.stderr create mode 100644 src/tools/miri/tests/fail/storage-live-resets-var.rs create mode 100644 src/tools/miri/tests/fail/storage-live-resets-var.stderr diff --git a/src/tools/miri/tests/fail/storage-live-dead-var.rs b/src/tools/miri/tests/fail/storage-live-dead-var.rs new file mode 100644 index 0000000000000..83ab98d79d1a1 --- /dev/null +++ b/src/tools/miri/tests/fail/storage-live-dead-var.rs @@ -0,0 +1,14 @@ +#![feature(core_intrinsics, custom_mir)] +use std::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime")] +fn main() { + mir! { + let val: i32; + { + val = 42; //~ERROR: accessing a dead local variable + StorageLive(val); // too late... (but needs to be here to make `val` not implicitly live) + Return() + } + } +} diff --git a/src/tools/miri/tests/fail/storage-live-dead-var.stderr b/src/tools/miri/tests/fail/storage-live-dead-var.stderr new file mode 100644 index 0000000000000..ccc77b1c978dc --- /dev/null +++ b/src/tools/miri/tests/fail/storage-live-dead-var.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: accessing a dead local variable + --> $DIR/storage-live-dead-var.rs:LL:CC + | +LL | val = 42; + | ^^^^^^^^ accessing a dead local variable + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/storage-live-dead-var.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/storage-live-resets-var.rs b/src/tools/miri/tests/fail/storage-live-resets-var.rs new file mode 100644 index 0000000000000..bfdd9e78943e9 --- /dev/null +++ b/src/tools/miri/tests/fail/storage-live-resets-var.rs @@ -0,0 +1,17 @@ +#![feature(core_intrinsics, custom_mir)] +use std::intrinsics::mir::*; + +#[custom_mir(dialect = "runtime")] +fn main() { + mir! { + let val: i32; + let _val2: i32; + { + StorageLive(val); + val = 42; + StorageLive(val); // reset val to `uninit` + _val2 = val; //~ERROR: uninitialized + Return() + } + } +} diff --git a/src/tools/miri/tests/fail/storage-live-resets-var.stderr b/src/tools/miri/tests/fail/storage-live-resets-var.stderr new file mode 100644 index 0000000000000..07d39cc9d6b3f --- /dev/null +++ b/src/tools/miri/tests/fail/storage-live-resets-var.stderr @@ -0,0 +1,15 @@ +error: Undefined Behavior: constructing invalid value: encountered uninitialized memory, but expected an integer + --> $DIR/storage-live-resets-var.rs:LL:CC + | +LL | _val2 = val; + | ^^^^^^^^^^^ constructing invalid value: encountered uninitialized memory, but expected an integer + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + = note: BACKTRACE: + = note: inside `main` at $DIR/storage-live-resets-var.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + From 207c5bc5a9007acd5bf3dbd58ef361bbb3ff3866 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 17 Jun 2024 08:48:49 +0300 Subject: [PATCH 04/10] override user defined channel when using precompiled rustc Signed-off-by: onur-ozkan --- src/bootstrap/src/core/config/config.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index a1d8ca3cbcaa7..0438dee7241fe 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -1718,7 +1718,23 @@ impl Config { config.omit_git_hash = omit_git_hash.unwrap_or(default); config.rust_info = GitInfo::new(config.omit_git_hash, &config.src); - if config.rust_info.is_from_tarball() && !is_user_configured_rust_channel { + // We need to override `rust.channel` if it's manually specified when using the CI rustc. + // This is because if the compiler uses a different channel than the one specified in config.toml, + // tests may fail due to using a different channel than the one used by the compiler during tests. + if let Some(commit) = &config.download_rustc_commit { + if is_user_configured_rust_channel { + println!( + "WARNING: `rust.download-rustc` is enabled. The `rust.channel` option will be overridden by the CI rustc's channel." + ); + + let channel = config + .read_file_by_commit(&PathBuf::from("src/ci/channel"), commit) + .trim() + .to_owned(); + + config.channel = channel; + } + } else if config.rust_info.is_from_tarball() && !is_user_configured_rust_channel { ci_channel.clone_into(&mut config.channel); } From 5ae2446109ccdc64921561228eb983f795705b17 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Mon, 17 Jun 2024 08:49:36 +0300 Subject: [PATCH 05/10] simplify `Builder::doc_rust_lang_org_channel` This is already handled at the config parsing level, so we can simplify it. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/builder.rs | 23 ++++++----------------- 1 file changed, 6 insertions(+), 17 deletions(-) diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index d9e4cbae17d71..73e2cebc21c15 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -1036,23 +1036,12 @@ impl<'a> Builder<'a> { } pub fn doc_rust_lang_org_channel(&self) -> String { - // When using precompiled compiler from CI, we need to use CI rustc's channel and - // ignore `rust.channel` from the configuration. Otherwise most of the rustdoc tests - // will fail due to incompatible `DOC_RUST_LANG_ORG_CHANNEL`. - let channel = if let Some(commit) = self.config.download_rustc_commit() { - self.config - .read_file_by_commit(&PathBuf::from("src/ci/channel"), commit) - .trim() - .to_owned() - } else { - match &*self.config.channel { - "stable" => &self.version, - "beta" => "beta", - "nightly" | "dev" => "nightly", - // custom build of rustdoc maybe? link to the latest stable docs just in case - _ => "stable", - } - .to_owned() + let channel = match &*self.config.channel { + "stable" => &self.version, + "beta" => "beta", + "nightly" | "dev" => "nightly", + // custom build of rustdoc maybe? link to the latest stable docs just in case + _ => "stable", }; format!("https://doc.rust-lang.org/{channel}") From e003a12ad540835083bcefdb77f65bb94ca24279 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 18 Jun 2024 20:54:11 -0700 Subject: [PATCH 06/10] Unconditionally warn on usage of `wasm32-wasi` This commit is a continuation of the work originally proposed in rust-lang/compiler-team#607 and later amended in rust-lang/compiler-team#695. The end goal is to rename `wasm32-wasi` to `wasm32-wasip1` to reflect WASI's development and distinguish the preexisting target from the `wasm32-wasip2` target that WASI is now developing. Work for this transition began in #120468 which landed in Rust 1.78 which became stable on 2024-05-02. This implements the next phase of the transition plan to warn on usage of `wasm32-wasi`. This is intended to help alert users that a removal is pending and all release channels have the replacement available as well. This will reach stable on 2024-09-05. The next stage of the plan is to remove the `wasm32-wasi` target some time in October 2024 which means that the removal will reach stable on 2025-01-09. For reference a full schedule of this transition is listed [here]. Currently this implementation is a simple unconditional warning whenever `rustc --target wasm32-wasi` is invoked. As-implemented there's no way to turn off the warning other than to switch to the `wasm32-wasip1` target. [here]: https://github.com/rust-lang/rust/pull/120468#issuecomment-1977878747 --- compiler/rustc_session/src/config.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 5f9c3a14d6032..24143808ef492 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1311,6 +1311,20 @@ pub fn build_target_config(early_dcx: &EarlyDiagCtxt, opts: &Options, sysroot: & for warning in warnings.warning_messages() { early_dcx.early_warn(warning) } + + // The `wasm32-wasi` target is being renamed to `wasm32-wasip1` as + // part of rust-lang/compiler-team#607 and + // rust-lang/compiler-team#695. Warn unconditionally on usage to + // raise awareness of the renaming. This code will be deleted in + // October 2024. + if opts.target_triple.triple() == "wasm32-wasi" { + early_dcx.early_warn( + "the `wasm32-wasi` target is being renamed to \ + `wasm32-wasip1` and the `wasm32-wasi` target will be \ + removed from nightly in October 2024 and removed from \ + stable Rust in January 2025", + ) + } if !matches!(target.pointer_width, 16 | 32 | 64) { early_dcx.early_fatal(format!( "target specification was invalid: unrecognized target-pointer-width {}", From 6c7c824767e2e9c992da74e449da27889bbd4bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 3 May 2024 09:56:13 +0000 Subject: [PATCH 07/10] coverage: Make MCDC take in account last RHS of condition-coverage Condition coverage extends branch coverage to treat the specific case of last operands of boolean decisions not involved in control flow. This is ultimately made for MCDC to be exhaustive on all boolean expressions. This patch adds a call to `visit_branch_coverage_operation` to track the top-level operand of the said decisions, and changes `visit_coverage_standalone_condition` so MCDC branch registration is called when enabled on these _last RHS_ cases. --- .../rustc_mir_build/src/build/coverageinfo.rs | 68 ++++++++++++------- .../rustc_mir_build/src/build/expr/into.rs | 3 + 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/coverageinfo.rs b/compiler/rustc_mir_build/src/build/coverageinfo.rs index 855dcbbcb346e..876faca5172ac 100644 --- a/compiler/rustc_mir_build/src/build/coverageinfo.rs +++ b/compiler/rustc_mir_build/src/build/coverageinfo.rs @@ -118,17 +118,35 @@ impl BranchInfoBuilder { } } - fn add_two_way_branch<'tcx>( + fn register_two_way_branch<'tcx>( &mut self, + tcx: TyCtxt<'tcx>, cfg: &mut CFG<'tcx>, source_info: SourceInfo, true_block: BasicBlock, false_block: BasicBlock, ) { - let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block); - let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block); - - self.branch_spans.push(BranchSpan { span: source_info.span, true_marker, false_marker }); + // Separate path for handling branches when MC/DC is enabled. + if let Some(mcdc_info) = self.mcdc_info.as_mut() { + let inject_block_marker = + |source_info, block| self.markers.inject_block_marker(cfg, source_info, block); + mcdc_info.visit_evaluated_condition( + tcx, + source_info, + true_block, + false_block, + inject_block_marker, + ); + } else { + let true_marker = self.markers.inject_block_marker(cfg, source_info, true_block); + let false_marker = self.markers.inject_block_marker(cfg, source_info, false_block); + + self.branch_spans.push(BranchSpan { + span: source_info.span, + true_marker, + false_marker, + }); + } } pub(crate) fn into_done(self) -> Option> { @@ -205,7 +223,14 @@ impl<'tcx> Builder<'_, 'tcx> { mir::TerminatorKind::if_(mir::Operand::Copy(place), true_block, false_block), ); - branch_info.add_two_way_branch(&mut self.cfg, source_info, true_block, false_block); + // Separate path for handling branches when MC/DC is enabled. + branch_info.register_two_way_branch( + self.tcx, + &mut self.cfg, + source_info, + true_block, + false_block, + ); let join_block = self.cfg.start_new_block(); self.cfg.goto(true_block, source_info, join_block); @@ -236,22 +261,13 @@ impl<'tcx> Builder<'_, 'tcx> { let source_info = SourceInfo { span: self.thir[expr_id].span, scope: self.source_scope }; - // Separate path for handling branches when MC/DC is enabled. - if let Some(mcdc_info) = branch_info.mcdc_info.as_mut() { - let inject_block_marker = |source_info, block| { - branch_info.markers.inject_block_marker(&mut self.cfg, source_info, block) - }; - mcdc_info.visit_evaluated_condition( - self.tcx, - source_info, - then_block, - else_block, - inject_block_marker, - ); - return; - } - - branch_info.add_two_way_branch(&mut self.cfg, source_info, then_block, else_block); + branch_info.register_two_way_branch( + self.tcx, + &mut self.cfg, + source_info, + then_block, + else_block, + ); } /// If branch coverage is enabled, inject marker statements into `true_block` @@ -270,6 +286,12 @@ impl<'tcx> Builder<'_, 'tcx> { // FIXME(#124144) This may need special handling when MC/DC is enabled. let source_info = SourceInfo { span: pattern.span, scope: self.source_scope }; - branch_info.add_two_way_branch(&mut self.cfg, source_info, true_block, false_block); + branch_info.register_two_way_branch( + self.tcx, + &mut self.cfg, + source_info, + true_block, + false_block, + ); } } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index c08a3b6691afc..6b4dd8b64a425 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -150,6 +150,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::LogicalOp { op, lhs, rhs } => { let condition_scope = this.local_scope(); let source_info = this.source_info(expr.span); + + this.visit_coverage_branch_operation(op, expr.span); + // We first evaluate the left-hand side of the predicate ... let (then_block, else_block) = this.in_if_then_scope(condition_scope, expr.span, |this| { From e15adef457b25b91906fde1510405fa4f3992188 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20P=C3=A9ron?= Date: Fri, 3 May 2024 10:37:02 +0000 Subject: [PATCH 08/10] tests(coverage): Bless mcdc_non_control_flow tests --- tests/coverage/mcdc_non_control_flow.cov-map | 63 ++++----- tests/coverage/mcdc_non_control_flow.coverage | 122 ++++++++++++++++-- 2 files changed, 147 insertions(+), 38 deletions(-) diff --git a/tests/coverage/mcdc_non_control_flow.cov-map b/tests/coverage/mcdc_non_control_flow.cov-map index 3f422d85e7992..937c36e1f16c4 100644 --- a/tests/coverage/mcdc_non_control_flow.cov-map +++ b/tests/coverage/mcdc_non_control_flow.cov-map @@ -1,5 +1,5 @@ Function name: mcdc_non_control_flow::assign_3 -Raw bytes (73): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 09, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 22, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 20, 1e, 11, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 20, 09, 0d, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Raw bytes (89): 0x[01, 01, 09, 05, 07, 0b, 11, 09, 0d, 01, 05, 01, 05, 22, 11, 01, 05, 22, 11, 01, 05, 0a, 01, 16, 01, 00, 28, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 22, 01, 00, 02, 00, 0d, 00, 0e, 22, 00, 12, 00, 13, 30, 1e, 11, 02, 03, 00, 00, 12, 00, 13, 1e, 00, 17, 00, 18, 30, 09, 0d, 03, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 9 @@ -12,29 +12,30 @@ Number of expressions: 9 - expression 6 operands: lhs = Counter(0), rhs = Counter(1) - expression 7 operands: lhs = Expression(8, Sub), rhs = Counter(4) - expression 8 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 9 +Number of file 0 mappings: 10 - Code(Counter(0)) at (prev + 22, 1) to (start + 0, 40) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = (c1 + ((c2 + c3) + c4)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Counter(1), false: Expression(8, Sub) } at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) +- MCDCBranch { true: Counter(1), false: Expression(8, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Expression(8, Sub)) at (prev + 0, 18) to (start + 0, 19) = (c0 - c1) -- Branch { true: Expression(7, Sub), false: Counter(4) } at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Expression(7, Sub), false: Counter(4), condition_id: 2, true_next_id: 3, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) true = ((c0 - c1) - c4) false = c4 - Code(Expression(7, Sub)) at (prev + 0, 23) to (start + 0, 24) = ((c0 - c1) - c4) -- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 23) to (start + 0, 24) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 3, true_next_id: 0, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) true = c2 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = (c1 + ((c2 + c3) + c4)) Function name: mcdc_non_control_flow::assign_3_bis -Raw bytes (82): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 02, 00, 00, 00, 12, 00, 13, 13, 00, 17, 00, 18, 20, 0d, 11, 00, 17, 00, 18, 03, 01, 05, 01, 02] +Raw bytes (85): 0x[01, 01, 07, 07, 11, 09, 0d, 01, 05, 05, 09, 16, 1a, 05, 09, 01, 05, 0a, 01, 1b, 01, 00, 2c, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 03, 00, 0d, 00, 18, 30, 05, 1a, 01, 03, 02, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 16, 03, 00, 02, 00, 12, 00, 13, 13, 00, 17, 00, 18, 30, 0d, 11, 02, 00, 00, 00, 17, 00, 18, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 7 @@ -50,24 +51,24 @@ Number of file 0 mappings: 10 - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c2 + c3) + c4) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) -- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 3 } at (prev + 0, 13) to (start + 0, 24) +- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 3, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) -- MCDCBranch { true: Counter(2), false: Expression(5, Sub), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Counter(2), false: Expression(5, Sub), condition_id: 3, true_next_id: 0, false_next_id: 2 } at (prev + 0, 18) to (start + 0, 19) true = c2 false = (c1 - c2) - Code(Expression(4, Add)) at (prev + 0, 23) to (start + 0, 24) = ((c1 - c2) + (c0 - c1)) -- Branch { true: Counter(3), false: Counter(4) } at (prev + 0, 23) to (start + 0, 24) +- MCDCBranch { true: Counter(3), false: Counter(4), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 23) to (start + 0, 24) true = c3 false = c4 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + c4) Function name: mcdc_non_control_flow::assign_and -Raw bytes (51): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 07, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Raw bytes (64): 0x[01, 01, 04, 07, 0e, 09, 0d, 01, 05, 01, 05, 08, 01, 0c, 01, 00, 21, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -75,23 +76,24 @@ Number of expressions: 4 - expression 1 operands: lhs = Counter(2), rhs = Counter(3) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) - expression 3 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 7 +Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 12, 1) to (start + 0, 33) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c2 + c3) + (c0 - c1)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) +- MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 18) to (start + 0, 19) -- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) true = c2 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) = ((c2 + c3) + (c0 - c1)) Function name: mcdc_non_control_flow::assign_or -Raw bytes (51): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 07, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 0e, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 20, 09, 0d, 00, 12, 00, 13, 03, 01, 05, 01, 02] +Raw bytes (64): 0x[01, 01, 04, 07, 0d, 05, 09, 01, 05, 01, 05, 08, 01, 11, 01, 00, 20, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 02, 00, 0d, 00, 13, 30, 05, 0e, 01, 00, 02, 00, 0d, 00, 0e, 0e, 00, 12, 00, 13, 30, 09, 0d, 02, 00, 00, 00, 12, 00, 13, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 4 @@ -99,17 +101,18 @@ Number of expressions: 4 - expression 1 operands: lhs = Counter(1), rhs = Counter(2) - expression 2 operands: lhs = Counter(0), rhs = Counter(1) - expression 3 operands: lhs = Counter(0), rhs = Counter(1) -Number of file 0 mappings: 7 +Number of file 0 mappings: 8 - Code(Counter(0)) at (prev + 17, 1) to (start + 0, 32) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = ((c1 + c2) + c3) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Counter(1), false: Expression(3, Sub) } at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 0, 13) to (start + 0, 19) +- MCDCBranch { true: Counter(1), false: Expression(3, Sub), condition_id: 1, true_next_id: 0, false_next_id: 2 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Expression(3, Sub)) at (prev + 0, 18) to (start + 0, 19) = (c0 - c1) -- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 18) to (start + 0, 19) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 18) to (start + 0, 19) true = c2 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) @@ -124,27 +127,28 @@ Number of file 0 mappings: 1 - Code(Counter(0)) at (prev + 37, 1) to (start + 2, 2) Function name: mcdc_non_control_flow::func_call -Raw bytes (39): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 05, 01, 29, 01, 01, 0a, 20, 05, 02, 01, 09, 00, 0a, 05, 00, 0e, 00, 0f, 20, 09, 0d, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] +Raw bytes (52): 0x[01, 01, 03, 01, 05, 0b, 02, 09, 0d, 06, 01, 29, 01, 01, 0a, 28, 00, 02, 01, 09, 00, 0f, 30, 05, 02, 01, 02, 00, 00, 09, 00, 0a, 05, 00, 0e, 00, 0f, 30, 09, 0d, 02, 00, 00, 00, 0e, 00, 0f, 07, 01, 01, 00, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 3 - expression 0 operands: lhs = Counter(0), rhs = Counter(1) - expression 1 operands: lhs = Expression(2, Add), rhs = Expression(0, Sub) - expression 2 operands: lhs = Counter(2), rhs = Counter(3) -Number of file 0 mappings: 5 +Number of file 0 mappings: 6 - Code(Counter(0)) at (prev + 41, 1) to (start + 1, 10) -- Branch { true: Counter(1), false: Expression(0, Sub) } at (prev + 1, 9) to (start + 0, 10) +- MCDCDecision { bitmap_idx: 0, conditions_num: 2 } at (prev + 1, 9) to (start + 0, 15) +- MCDCBranch { true: Counter(1), false: Expression(0, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 9) to (start + 0, 10) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 14) to (start + 0, 15) -- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 14) to (start + 0, 15) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 2, true_next_id: 0, false_next_id: 0 } at (prev + 0, 14) to (start + 0, 15) true = c2 false = c3 - Code(Expression(1, Add)) at (prev + 1, 1) to (start + 0, 2) = ((c2 + c3) + (c0 - c1)) Function name: mcdc_non_control_flow::right_comb_tree -Raw bytes (117): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0d, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 20, 05, 1a, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 20, 4a, 19, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 20, 46, 15, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 20, 42, 11, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 20, 09, 0d, 00, 24, 00, 27, 03, 01, 05, 01, 02] +Raw bytes (139): 0x[01, 01, 13, 07, 1a, 0b, 19, 0f, 15, 13, 11, 09, 0d, 01, 05, 01, 05, 05, 19, 05, 19, 4a, 15, 05, 19, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 46, 11, 4a, 15, 05, 19, 0e, 01, 20, 01, 00, 41, 03, 01, 09, 00, 0a, 01, 00, 0d, 00, 0e, 28, 00, 05, 00, 0d, 00, 2a, 30, 05, 1a, 01, 02, 00, 00, 0d, 00, 0e, 05, 00, 13, 00, 14, 30, 4a, 19, 02, 03, 00, 00, 13, 00, 14, 4a, 00, 19, 00, 1a, 30, 46, 15, 03, 04, 00, 00, 19, 00, 1a, 46, 00, 1f, 00, 20, 30, 42, 11, 04, 05, 00, 00, 1f, 00, 20, 42, 00, 24, 00, 27, 30, 09, 0d, 05, 00, 00, 00, 24, 00, 27, 03, 01, 05, 01, 02] Number of files: 1 - file 0 => global file 1 Number of expressions: 19 @@ -167,31 +171,32 @@ Number of expressions: 19 - expression 16 operands: lhs = Expression(17, Sub), rhs = Counter(4) - expression 17 operands: lhs = Expression(18, Sub), rhs = Counter(5) - expression 18 operands: lhs = Counter(1), rhs = Counter(6) -Number of file 0 mappings: 13 +Number of file 0 mappings: 14 - Code(Counter(0)) at (prev + 32, 1) to (start + 0, 65) - Code(Expression(0, Add)) at (prev + 1, 9) to (start + 0, 10) = (((((c2 + c3) + c4) + c5) + c6) + (c0 - c1)) - Code(Counter(0)) at (prev + 0, 13) to (start + 0, 14) -- Branch { true: Counter(1), false: Expression(6, Sub) } at (prev + 0, 13) to (start + 0, 14) +- MCDCDecision { bitmap_idx: 0, conditions_num: 5 } at (prev + 0, 13) to (start + 0, 42) +- MCDCBranch { true: Counter(1), false: Expression(6, Sub), condition_id: 1, true_next_id: 2, false_next_id: 0 } at (prev + 0, 13) to (start + 0, 14) true = c1 false = (c0 - c1) - Code(Counter(1)) at (prev + 0, 19) to (start + 0, 20) -- Branch { true: Expression(18, Sub), false: Counter(6) } at (prev + 0, 19) to (start + 0, 20) +- MCDCBranch { true: Expression(18, Sub), false: Counter(6), condition_id: 2, true_next_id: 3, false_next_id: 0 } at (prev + 0, 19) to (start + 0, 20) true = (c1 - c6) false = c6 - Code(Expression(18, Sub)) at (prev + 0, 25) to (start + 0, 26) = (c1 - c6) -- Branch { true: Expression(17, Sub), false: Counter(5) } at (prev + 0, 25) to (start + 0, 26) +- MCDCBranch { true: Expression(17, Sub), false: Counter(5), condition_id: 3, true_next_id: 4, false_next_id: 0 } at (prev + 0, 25) to (start + 0, 26) true = ((c1 - c6) - c5) false = c5 - Code(Expression(17, Sub)) at (prev + 0, 31) to (start + 0, 32) = ((c1 - c6) - c5) -- Branch { true: Expression(16, Sub), false: Counter(4) } at (prev + 0, 31) to (start + 0, 32) +- MCDCBranch { true: Expression(16, Sub), false: Counter(4), condition_id: 4, true_next_id: 5, false_next_id: 0 } at (prev + 0, 31) to (start + 0, 32) true = (((c1 - c6) - c5) - c4) false = c4 - Code(Expression(16, Sub)) at (prev + 0, 36) to (start + 0, 39) = (((c1 - c6) - c5) - c4) -- Branch { true: Counter(2), false: Counter(3) } at (prev + 0, 36) to (start + 0, 39) +- MCDCBranch { true: Counter(2), false: Counter(3), condition_id: 5, true_next_id: 0, false_next_id: 0 } at (prev + 0, 36) to (start + 0, 39) true = c2 false = c3 - Code(Expression(0, Add)) at (prev + 1, 5) to (start + 1, 2) diff --git a/tests/coverage/mcdc_non_control_flow.coverage b/tests/coverage/mcdc_non_control_flow.coverage index 4e53a7a0d8e85..cd733885a98b6 100644 --- a/tests/coverage/mcdc_non_control_flow.coverage +++ b/tests/coverage/mcdc_non_control_flow.coverage @@ -12,18 +12,76 @@ LL| 3|fn assign_and(a: bool, b: bool) { LL| 3| let x = a && b; ^2 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:19) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, - = F } + | 2 { T, F = F } + | 3 { T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | MC/DC Coverage for Decision: 100.00% + | + ------------------ LL| 3| black_box(x); LL| 3|} LL| | LL| 3|fn assign_or(a: bool, b: bool) { LL| 3| let x = a || b; ^1 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:19) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, F = F } + | 2 { T, - = T } + | + | C1-Pair: covered: (1,2) + | C2-Pair: not covered + | MC/DC Coverage for Decision: 50.00% + | + ------------------ LL| 3| black_box(x); LL| 3|} LL| | LL| 4|fn assign_3(a: bool, b: bool, c: bool) { LL| 4| let x = a || b && c; ^2 ^1 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:24) + | + | Number of Conditions: 3 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:18) + | Condition C3 --> (LL:23) + | + | Executed MC/DC Test Vectors: + | + | C1, C2, C3 Result + | 1 { F, F, - = F } + | 2 { T, -, - = T } + | 3 { F, T, T = T } + | + | C1-Pair: covered: (1,2) + | C2-Pair: covered: (1,3) + | C3-Pair: not covered + | MC/DC Coverage for Decision: 66.67% + | + ------------------ LL| 4| black_box(x); LL| 4|} LL| | @@ -31,22 +89,24 @@ LL| 4| let x = a && b || c; ^2 ^3 ------------------ - |---> MC/DC Decision Region (LL:13) to (LL:19) + |---> MC/DC Decision Region (LL:13) to (LL:24) | - | Number of Conditions: 2 + | Number of Conditions: 3 | Condition C1 --> (LL:13) | Condition C2 --> (LL:18) + | Condition C3 --> (LL:23) | | Executed MC/DC Test Vectors: | - | C1, C2 Result - | 1 { F, - = F } - | 2 { T, F = F } - | 3 { T, T = T } + | C1, C2, C3 Result + | 1 { T, F, F = F } + | 2 { F, -, T = T } + | 3 { T, T, - = T } | - | C1-Pair: covered: (1,3) - | C2-Pair: covered: (2,3) - | MC/DC Coverage for Decision: 100.00% + | C1-Pair: not covered + | C2-Pair: covered: (1,3) + | C3-Pair: not covered + | MC/DC Coverage for Decision: 33.33% | ------------------ LL| 4| black_box(x); @@ -55,6 +115,31 @@ LL| 3|fn right_comb_tree(a: bool, b: bool, c: bool, d: bool, e: bool) { LL| 3| let x = a && (b && (c && (d && (e)))); ^2 ^1 ^1 ^1 + ------------------ + |---> MC/DC Decision Region (LL:13) to (LL:42) + | + | Number of Conditions: 5 + | Condition C1 --> (LL:13) + | Condition C2 --> (LL:19) + | Condition C3 --> (LL:25) + | Condition C4 --> (LL:31) + | Condition C5 --> (LL:36) + | + | Executed MC/DC Test Vectors: + | + | C1, C2, C3, C4, C5 Result + | 1 { F, -, -, -, - = F } + | 2 { T, F, -, -, - = F } + | 3 { T, T, T, T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | C3-Pair: not covered + | C4-Pair: not covered + | C5-Pair: not covered + | MC/DC Coverage for Decision: 40.00% + | + ------------------ LL| 3| black_box(x); LL| 3|} LL| | @@ -65,6 +150,25 @@ LL| 3|fn func_call(a: bool, b: bool) { LL| 3| foo(a && b); ^2 + ------------------ + |---> MC/DC Decision Region (LL:9) to (LL:15) + | + | Number of Conditions: 2 + | Condition C1 --> (LL:9) + | Condition C2 --> (LL:14) + | + | Executed MC/DC Test Vectors: + | + | C1, C2 Result + | 1 { F, - = F } + | 2 { T, F = F } + | 3 { T, T = T } + | + | C1-Pair: covered: (1,3) + | C2-Pair: covered: (2,3) + | MC/DC Coverage for Decision: 100.00% + | + ------------------ LL| 3|} LL| | LL| |#[coverage(off)] From ba4510ece85018408627b2d3ceef1a3b7889cb71 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 27 May 2024 11:49:05 +0000 Subject: [PATCH 09/10] Allow constraining opaque types during subtyping in the trait system --- compiler/rustc_infer/src/infer/mod.rs | 4 +- .../impl-trait/lazy_subtyping_of_opaques.rs | 67 +++++-------------- .../lazy_subtyping_of_opaques.stderr | 21 ------ .../lazy_subtyping_of_opaques.rs | 3 +- .../lazy_subtyping_of_opaques.stderr | 31 +++++---- 5 files changed, 38 insertions(+), 88 deletions(-) delete mode 100644 tests/ui/impl-trait/lazy_subtyping_of_opaques.stderr diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 510e9a06dfb06..4d6ddd7ba66ab 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -878,9 +878,9 @@ impl<'tcx> InferCtxt<'tcx> { self.enter_forall(predicate, |ty::SubtypePredicate { a_is_expected, a, b }| { if a_is_expected { - Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::No, a, b)) + Ok(self.at(cause, param_env).sub(DefineOpaqueTypes::Yes, a, b)) } else { - Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::No, b, a)) + Ok(self.at(cause, param_env).sup(DefineOpaqueTypes::Yes, b, a)) } }) } diff --git a/tests/ui/impl-trait/lazy_subtyping_of_opaques.rs b/tests/ui/impl-trait/lazy_subtyping_of_opaques.rs index 65331894725a8..8fd1f35645a8a 100644 --- a/tests/ui/impl-trait/lazy_subtyping_of_opaques.rs +++ b/tests/ui/impl-trait/lazy_subtyping_of_opaques.rs @@ -2,58 +2,23 @@ //! No hidden types are being constrained in the subtyping predicate, but type and //! lifetime variables get subtyped in the generic parameter list of the opaque. -use std::iter; - -mod either { - pub enum Either { - Left(L), - Right(R), - } - - impl> Iterator for Either { - type Item = L::Item; - fn next(&mut self) -> Option { - todo!() - } - } - pub use self::Either::{Left, Right}; -} - -pub enum BabeConsensusLogRef<'a> { - NextEpochData(BabeNextEpochRef<'a>), - NextConfigData, -} - -impl<'a> BabeConsensusLogRef<'a> { - pub fn scale_encoding( - &self, - ) -> impl Iterator + Clone + 'a> + Clone + 'a { - //~^ ERROR is not satisfied - //~| ERROR is not satisfied - //~| ERROR is not satisfied - match self { - BabeConsensusLogRef::NextEpochData(digest) => either::Left(either::Left( - digest.scale_encoding().map(either::Left).map(either::Left), - )), - BabeConsensusLogRef::NextConfigData => either::Right( - // The Opaque type from ``scale_encoding` gets used opaquely here, while the `R` - // generic parameter of `Either` contains type variables that get subtyped and the - // opaque type contains lifetime variables that get subtyped. - iter::once(either::Right(either::Left([1]))) - .chain(std::iter::once([1]).map(either::Right).map(either::Right)), - ), - } - } -} - -pub struct BabeNextEpochRef<'a>(&'a ()); - -impl<'a> BabeNextEpochRef<'a> { - pub fn scale_encoding( - &self, - ) -> impl Iterator + Clone + 'a> + Clone + 'a { - std::iter::once([1]) +//@ check-pass + +fn foo() -> impl Default + Copy { + if false { + let x = Default::default(); + // add `Subtype(?x, ?y)` obligation + let y = x; + + // Make a tuple `(?x, ?y)` and equate it with `(impl Default, u32)`. + // For us to try and prove a `Subtype(impl Default, u32)` obligation, + // we have to instantiate both `?x` and `?y` without any + // `select_where_possible` calls inbetween. + let mut tup = &mut (x, y); + let assign_tup = &mut (foo(), 1u32); + tup = assign_tup; } + 1u32 } fn main() {} diff --git a/tests/ui/impl-trait/lazy_subtyping_of_opaques.stderr b/tests/ui/impl-trait/lazy_subtyping_of_opaques.stderr deleted file mode 100644 index 2f8c957c2c7dc..0000000000000 --- a/tests/ui/impl-trait/lazy_subtyping_of_opaques.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error[E0277]: the trait bound `Either + Clone + '_> + Clone + '_, fn(impl AsRef<[u8]> + Clone + '_) -> Either + Clone + '_, _> {Either:: + Clone + '_, _>::Left}>, fn(Either + Clone + '_, _>) -> Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either:: + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Left}>, _>, std::iter::Chain + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>>, Map, fn([{integer}; 1]) -> Either<[{integer}; 1], [{integer}; 1]> {Either::<[{integer}; 1], [{integer}; 1]>::Right}>, fn(Either<[{integer}; 1], [{integer}; 1]>) -> Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either:: + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Right}>>>: Clone` is not satisfied - --> $DIR/lazy_subtyping_of_opaques.rs:30:10 - | -LL | ) -> impl Iterator + Clone + 'a> + Clone + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Either + Clone + '_> + Clone + '_, fn(impl AsRef<[u8]> + Clone + '_) -> Either + Clone + '_, _> {Either:: + Clone + '_, _>::Left}>, fn(Either + Clone + '_, _>) -> Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either:: + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Left}>, _>, std::iter::Chain + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>>, Map, fn([{integer}; 1]) -> Either<[{integer}; 1], [{integer}; 1]> {Either::<[{integer}; 1], [{integer}; 1]>::Right}>, fn(Either<[{integer}; 1], [{integer}; 1]>) -> Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>> {Either:: + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>::Right}>>>` - -error[E0277]: the trait bound `Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>: AsRef<[u8]>` is not satisfied - --> $DIR/lazy_subtyping_of_opaques.rs:30:31 - | -LL | ) -> impl Iterator + Clone + 'a> + Clone + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsRef<[u8]>` is not implemented for `Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>` - -error[E0277]: the trait bound `Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>: Clone` is not satisfied - --> $DIR/lazy_subtyping_of_opaques.rs:30:31 - | -LL | ) -> impl Iterator + Clone + 'a> + Clone + 'a { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Either + Clone + '_, _>, Either<[{integer}; 1], [{integer}; 1]>>` - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs index 72a90287e374f..1bc352041a57d 100644 --- a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs +++ b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs @@ -7,9 +7,10 @@ type Tait = impl FnOnce() -> (); fn reify_as_tait() -> Thunk { + //~^ ERROR: expected a `FnOnce()` closure, found `()` Thunk::new(|cont| cont) //~^ ERROR: mismatched types - //~| ERROR: mismatched types + //~| ERROR: expected a `FnOnce()` closure, found `()` } struct Thunk(F); diff --git a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr index 5a35dc27446cb..7bc2fa1b09ea6 100644 --- a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr +++ b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr @@ -1,26 +1,31 @@ -error[E0308]: mismatched types - --> $DIR/lazy_subtyping_of_opaques.rs:10:23 +error[E0277]: expected a `FnOnce()` closure, found `()` + --> $DIR/lazy_subtyping_of_opaques.rs:11:23 | -LL | type Tait = impl FnOnce() -> (); - | ------------------- the found opaque type -... LL | Thunk::new(|cont| cont) - | ^^^^ expected `()`, found opaque type + | ^^^^ expected an `FnOnce()` closure, found `()` | - = note: expected unit type `()` - found opaque type `Tait` + = help: the trait `FnOnce()` is not implemented for `()` + = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` -error[E0308]: mismatched types - --> $DIR/lazy_subtyping_of_opaques.rs:10:5 +error[E0277]: expected a `FnOnce()` closure, found `()` + --> $DIR/lazy_subtyping_of_opaques.rs:9:23 | LL | fn reify_as_tait() -> Thunk { - | ----------- expected `Thunk<_>` because of return type + | ^^^^^^^^^^^ expected an `FnOnce()` closure, found `()` + | + = help: the trait `FnOnce()` is not implemented for `()` + = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` + +error[E0308]: mismatched types + --> $DIR/lazy_subtyping_of_opaques.rs:11:5 + | LL | Thunk::new(|cont| cont) | ^^^^^^^^^^^^^^^^^^^^^^^ expected `Thunk<_>`, found `()` | = note: expected struct `Thunk<_>` found unit type `()` -error: aborting due to 2 previous errors +error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0277, E0308. +For more information about an error, try `rustc --explain E0277`. From fd4fe7d129cac2b7a0668847117775ee23031771 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 1 Jun 2024 21:35:43 +1000 Subject: [PATCH 10/10] Remove `src/tools/rust-demangler` --- Cargo.lock | 8 -- Cargo.toml | 1 - config.example.toml | 4 +- src/bootstrap/src/core/build_steps/clippy.rs | 1 - src/bootstrap/src/core/build_steps/dist.rs | 93 +----------------- src/bootstrap/src/core/build_steps/install.rs | 16 --- src/bootstrap/src/core/build_steps/test.rs | 59 ----------- src/bootstrap/src/core/build_steps/tool.rs | 1 - src/bootstrap/src/core/builder.rs | 5 - src/bootstrap/src/utils/tarball.rs | 5 - src/doc/rustc/src/instrument-coverage.md | 8 +- src/tools/rust-demangler/Cargo.toml | 16 --- src/tools/rust-demangler/README.md | 36 ------- src/tools/rust-demangler/src/lib.rs | 21 ---- src/tools/rust-demangler/src/main.rs | 97 ------------------- src/tools/rust-demangler/tests/lib.rs | 84 ---------------- 16 files changed, 5 insertions(+), 450 deletions(-) delete mode 100644 src/tools/rust-demangler/Cargo.toml delete mode 100644 src/tools/rust-demangler/README.md delete mode 100644 src/tools/rust-demangler/src/lib.rs delete mode 100644 src/tools/rust-demangler/src/main.rs delete mode 100644 src/tools/rust-demangler/tests/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 14ee031ad047e..da99ac9b8afc7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3479,14 +3479,6 @@ dependencies = [ "wasmparser", ] -[[package]] -name = "rust-demangler" -version = "0.0.1" -dependencies = [ - "regex", - "rustc-demangle", -] - [[package]] name = "rustbook" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index a601ebf4369e0..c17ea99d03767 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,6 @@ members = [ "src/tools/remote-test-client", "src/tools/remote-test-server", "src/tools/rust-installer", - "src/tools/rust-demangler", "src/tools/rustdoc", "src/tools/rls", "src/tools/rustfmt", diff --git a/config.example.toml b/config.example.toml index 76541ee4e9e7e..679abcdc7771b 100644 --- a/config.example.toml +++ b/config.example.toml @@ -321,8 +321,7 @@ # # If `extended = false`, the only one of these built by default is rustdoc. # -# If `extended = true`, they're all included, with the exception of -# rust-demangler which additionally requires `profiler = true` to be set. +# If `extended = true`, they are all included. # # If any enabled tool fails to build, the installation fails. #tools = [ @@ -334,7 +333,6 @@ # "rust-analyzer-proc-macro-srv", # "analysis", # "src", -# "rust-demangler", # if profiler = true #] # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index 01b5e99116ff2..40a2112b19254 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -322,7 +322,6 @@ lint_any!( RemoteTestServer, "src/tools/remote-test-server", "remote-test-server"; Rls, "src/tools/rls", "rls"; RustAnalyzer, "src/tools/rust-analyzer", "rust-analyzer"; - RustDemangler, "src/tools/rust-demangler", "rust-demangler"; Rustdoc, "src/tools/rustdoc", "clippy"; Rustfmt, "src/tools/rustfmt", "rustfmt"; RustInstaller, "src/tools/rust-installer", "rust-installer"; diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index f651f751441f3..54136d2aebda2 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1459,62 +1459,6 @@ impl Step for Rustfmt { } } -#[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] -pub struct RustDemangler { - pub compiler: Compiler, - pub target: TargetSelection, -} - -impl Step for RustDemangler { - type Output = Option; - const DEFAULT: bool = true; - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - // While other tools use `should_build_extended_tool` to decide whether to be run by - // default or not, `rust-demangler` must be build when *either* it's enabled as a tool like - // the other ones or if `profiler = true`. Because we don't know the target at this stage - // we run the step by default when only `extended = true`, and decide whether to actually - // run it or not later. - let default = run.builder.config.extended; - run.alias("rust-demangler").default_condition(default) - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustDemangler { - compiler: run.builder.compiler_for( - run.builder.top_stage, - run.builder.config.build, - run.target, - ), - target: run.target, - }); - } - - fn run(self, builder: &Builder<'_>) -> Option { - let compiler = self.compiler; - let target = self.target; - - // Only build this extended tool if explicitly included in `tools`, or if `profiler = true` - let condition = should_build_extended_tool(builder, "rust-demangler") - || builder.config.profiler_enabled(target); - if builder.config.extended && !condition { - return None; - } - - let rust_demangler = - builder.ensure(tool::RustDemangler { compiler, target, extra_features: Vec::new() }); - - // Prepare the image directory - let mut tarball = Tarball::new(builder, "rust-demangler", &target.triple); - tarball.set_overlay(OverlayKind::RustDemangler); - tarball.is_preview(true); - tarball.add_file(rust_demangler, "bin", 0o755); - tarball.add_legal_and_readme_to("share/doc/rust-demangler"); - Some(tarball.generate()) - } -} - #[derive(Debug, PartialOrd, Ord, Clone, Hash, PartialEq, Eq)] pub struct Extended { stage: u32, @@ -1572,7 +1516,6 @@ impl Step for Extended { add_component!("rust-docs" => Docs { host: target }); add_component!("rust-json-docs" => JsonDocs { host: target }); - add_component!("rust-demangler"=> RustDemangler { compiler, target }); add_component!("cargo" => Cargo { compiler, target }); add_component!("rustfmt" => Rustfmt { compiler, target }); add_component!("rls" => Rls { compiler, target }); @@ -1636,7 +1579,7 @@ impl Step for Extended { let xform = |p: &Path| { let mut contents = t!(fs::read_to_string(p)); - for tool in &["rust-demangler", "miri", "rust-docs"] { + for tool in &["miri", "rust-docs"] { if !built_tools.contains(tool) { contents = filter(&contents, tool); } @@ -1677,7 +1620,7 @@ impl Step for Extended { prepare("rust-analysis"); prepare("clippy"); prepare("rust-analyzer"); - for tool in &["rust-docs", "rust-demangler", "miri", "rustc-codegen-cranelift"] { + for tool in &["rust-docs", "miri", "rustc-codegen-cranelift"] { if built_tools.contains(tool) { prepare(tool); } @@ -1717,8 +1660,6 @@ impl Step for Extended { "rust-analyzer-preview".to_string() } else if name == "clippy" { "clippy-preview".to_string() - } else if name == "rust-demangler" { - "rust-demangler-preview".to_string() } else if name == "miri" { "miri-preview".to_string() } else if name == "rustc-codegen-cranelift" { @@ -1738,7 +1679,7 @@ impl Step for Extended { prepare("cargo"); prepare("rust-analysis"); prepare("rust-std"); - for tool in &["clippy", "rust-analyzer", "rust-docs", "rust-demangler", "miri"] { + for tool in &["clippy", "rust-analyzer", "rust-docs", "miri"] { if built_tools.contains(tool) { prepare(tool); } @@ -1862,25 +1803,6 @@ impl Step for Extended { .arg(etc.join("msi/remove-duplicates.xsl")), ); } - if built_tools.contains("rust-demangler") { - builder.run( - Command::new(&heat) - .current_dir(&exe) - .arg("dir") - .arg("rust-demangler") - .args(heat_flags) - .arg("-cg") - .arg("RustDemanglerGroup") - .arg("-dr") - .arg("RustDemangler") - .arg("-var") - .arg("var.RustDemanglerDir") - .arg("-out") - .arg(exe.join("RustDemanglerGroup.wxs")) - .arg("-t") - .arg(etc.join("msi/remove-duplicates.xsl")), - ); - } if built_tools.contains("miri") { builder.run( Command::new(&heat) @@ -1958,9 +1880,6 @@ impl Step for Extended { if built_tools.contains("rust-docs") { cmd.arg("-dDocsDir=rust-docs"); } - if built_tools.contains("rust-demangler") { - cmd.arg("-dRustDemanglerDir=rust-demangler"); - } if built_tools.contains("rust-analyzer") { cmd.arg("-dRustAnalyzerDir=rust-analyzer"); } @@ -1987,9 +1906,6 @@ impl Step for Extended { if built_tools.contains("miri") { candle("MiriGroup.wxs".as_ref()); } - if built_tools.contains("rust-demangler") { - candle("RustDemanglerGroup.wxs".as_ref()); - } if built_tools.contains("rust-analyzer") { candle("RustAnalyzerGroup.wxs".as_ref()); } @@ -2031,9 +1947,6 @@ impl Step for Extended { if built_tools.contains("rust-analyzer") { cmd.arg("RustAnalyzerGroup.wixobj"); } - if built_tools.contains("rust-demangler") { - cmd.arg("RustDemanglerGroup.wixobj"); - } if built_tools.contains("rust-docs") { cmd.arg("DocsGroup.wixobj"); } diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index 6a75f35c93a6e..c47233ca42abe 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -265,22 +265,6 @@ install!((self, builder, _config), ); } }; - RustDemangler, alias = "rust-demangler", Self::should_build(_config), only_hosts: true, { - // NOTE: Even though `should_build` may return true for `extended` default tools, - // dist::RustDemangler may still return None, unless the target-dependent `profiler` config - // is also true, or the `tools` array explicitly includes "rust-demangler". - if let Some(tarball) = builder.ensure(dist::RustDemangler { - compiler: self.compiler, - target: self.target - }) { - install_sh(builder, "rust-demangler", self.compiler.stage, Some(self.target), &tarball); - } else { - builder.info( - &format!("skipping Install RustDemangler stage{} ({})", - self.compiler.stage, self.target), - ); - } - }; Rustc, path = "compiler/rustc", true, only_hosts: true, { let tarball = builder.ensure(dist::Rustc { compiler: builder.compiler(builder.top_stage, self.target), diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 7556a19c90ca0..445096e9786d4 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -432,65 +432,6 @@ impl Step for Rustfmt { } } -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct RustDemangler { - stage: u32, - host: TargetSelection, -} - -impl Step for RustDemangler { - type Output = (); - const ONLY_HOSTS: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src/tools/rust-demangler") - } - - fn make_run(run: RunConfig<'_>) { - run.builder.ensure(RustDemangler { stage: run.builder.top_stage, host: run.target }); - } - - /// Runs `cargo test` for rust-demangler. - fn run(self, builder: &Builder<'_>) { - let stage = self.stage; - let host = self.host; - let compiler = builder.compiler(stage, host); - - let rust_demangler = builder.ensure(tool::RustDemangler { - compiler, - target: self.host, - extra_features: Vec::new(), - }); - let mut cargo = tool::prepare_tool_cargo( - builder, - compiler, - Mode::ToolRustc, - host, - "test", - "src/tools/rust-demangler", - SourceType::InTree, - &[], - ); - - let dir = testdir(builder, compiler.host); - t!(fs::create_dir_all(dir)); - - cargo.env("RUST_DEMANGLER_DRIVER_PATH", rust_demangler); - cargo.add_rustc_lib_path(builder); - - run_cargo_test( - cargo, - &[], - &[], - "rust-demangler", - "rust-demangler", - compiler, - host, - builder, - ); - } -} - #[derive(Debug, Clone, PartialEq, Eq, Hash)] pub struct Miri { target: TargetSelection, diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs index e0a9674ae5a90..613484788b608 100644 --- a/src/bootstrap/src/core/build_steps/tool.rs +++ b/src/bootstrap/src/core/build_steps/tool.rs @@ -964,7 +964,6 @@ tool_extended!((self, builder), // But `builder.cargo` doesn't know how to handle ToolBootstrap in stages other than 0, // and this is close enough for now. Rls, "src/tools/rls", "rls", stable=true, tool_std=true; - RustDemangler, "src/tools/rust-demangler", "rust-demangler", stable=false, tool_std=true; Rustfmt, "src/tools/rustfmt", "rustfmt", stable=true, add_bins_to_sysroot = ["rustfmt", "cargo-fmt"]; ); diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs index d9e4cbae17d71..dd47ae96329bb 100644 --- a/src/bootstrap/src/core/builder.rs +++ b/src/bootstrap/src/core/builder.rs @@ -736,7 +736,6 @@ impl<'a> Builder<'a> { tool::Rls, tool::RustAnalyzer, tool::RustAnalyzerProcMacroSrv, - tool::RustDemangler, tool::Rustdoc, tool::Clippy, tool::CargoClippy, @@ -774,7 +773,6 @@ impl<'a> Builder<'a> { clippy::RemoteTestServer, clippy::Rls, clippy::RustAnalyzer, - clippy::RustDemangler, clippy::Rustdoc, clippy::Rustfmt, clippy::RustInstaller, @@ -842,7 +840,6 @@ impl<'a> Builder<'a> { test::Miri, test::CargoMiri, test::Clippy, - test::RustDemangler, test::CompiletestTest, test::CrateRunMakeSupport, test::RustdocJSStd, @@ -903,7 +900,6 @@ impl<'a> Builder<'a> { dist::Rls, dist::RustAnalyzer, dist::Rustfmt, - dist::RustDemangler, dist::Clippy, dist::Miri, dist::LlvmTools, @@ -930,7 +926,6 @@ impl<'a> Builder<'a> { install::Cargo, install::RustAnalyzer, install::Rustfmt, - install::RustDemangler, install::Clippy, install::Miri, install::LlvmTools, diff --git a/src/bootstrap/src/utils/tarball.rs b/src/bootstrap/src/utils/tarball.rs index 57cdf7473a191..fd934f18de23f 100644 --- a/src/bootstrap/src/utils/tarball.rs +++ b/src/bootstrap/src/utils/tarball.rs @@ -23,7 +23,6 @@ pub(crate) enum OverlayKind { Clippy, Miri, Rustfmt, - RustDemangler, Rls, RustAnalyzer, RustcCodegenCranelift, @@ -58,9 +57,6 @@ impl OverlayKind { "src/tools/rustfmt/LICENSE-APACHE", "src/tools/rustfmt/LICENSE-MIT", ], - OverlayKind::RustDemangler => { - &["src/tools/rust-demangler/README.md", "LICENSE-APACHE", "LICENSE-MIT"] - } OverlayKind::Rls => &["src/tools/rls/README.md", "LICENSE-APACHE", "LICENSE-MIT"], OverlayKind::RustAnalyzer => &[ "src/tools/rust-analyzer/README.md", @@ -85,7 +81,6 @@ impl OverlayKind { match self { OverlayKind::Rust => builder.rust_version(), OverlayKind::Llvm => builder.rust_version(), - OverlayKind::RustDemangler => builder.release_num("rust-demangler"), OverlayKind::Cargo => { builder.cargo_info.version(builder, &builder.release_num("cargo")) } diff --git a/src/doc/rustc/src/instrument-coverage.md b/src/doc/rustc/src/instrument-coverage.md index 32dc992c42fac..ed091d8fc5710 100644 --- a/src/doc/rustc/src/instrument-coverage.md +++ b/src/doc/rustc/src/instrument-coverage.md @@ -49,12 +49,6 @@ One option for a Rust demangler is [`rustfilt`], which can be installed with: cargo install rustfilt ``` -Another option, if you are building from the Rust compiler source distribution, is to use the `rust-demangler` tool included in the Rust source distribution, which can be built with: - -```shell -$ ./x.py build rust-demangler -``` - [`rustfilt`]: https://crates.io/crates/rustfilt ## Compiling with coverage enabled @@ -164,7 +158,7 @@ $ llvm-cov show -Xdemangler=rustfilt target/debug/examples/formatjson5 \ Some of the more notable options in this example include: -- `--Xdemangler=rustfilt` - the command name or path used to demangle Rust symbols (`rustfilt` in the example, but this could also be a path to the `rust-demangler` tool) +- `--Xdemangler=rustfilt` - the command name or path used to demangle Rust symbols (`rustfilt` in the example) - `target/debug/examples/formatjson5` - the instrumented binary (from which to extract the coverage map) - `--instr-profile=.profdata` - the location of the `.profdata` file created by `llvm-profdata merge` (from the `.profraw` file generated by the instrumented binary) - `--name=` - to show coverage for a specific function (or, consider using another filter option, such as `--name-regex=`) diff --git a/src/tools/rust-demangler/Cargo.toml b/src/tools/rust-demangler/Cargo.toml deleted file mode 100644 index 2bb73b3262d8d..0000000000000 --- a/src/tools/rust-demangler/Cargo.toml +++ /dev/null @@ -1,16 +0,0 @@ -[package] -name = "rust-demangler" -version = "0.0.1" -edition = "2021" - -[dependencies] -regex = "1.0" -rustc-demangle = "0.1.17" - -[lib] -name = "rust_demangler" -doctest = false - -[[bin]] -name = "rust-demangler" -test = false diff --git a/src/tools/rust-demangler/README.md b/src/tools/rust-demangler/README.md deleted file mode 100644 index 4e8a689a13a47..0000000000000 --- a/src/tools/rust-demangler/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# rust-demangler - -_Demangles rustc mangled names._ - -`rust-demangler` supports the requirements of the [`llvm-cov show -Xdemangler` -option](https://llvm.org/docs/CommandGuide/llvm-cov.html#cmdoption-llvm-cov-show-xdemangler), -to perform Rust-specific symbol demangling: - -> _The demangler is expected to read a newline-separated list of symbols from -> stdin and write a newline-separated list of the same length to stdout._ - -To use `rust-demangler` with `llvm-cov` for example: - -```shell -$ TARGET="${PWD}/build/x86_64-unknown-linux-gnu" -$ "${TARGET}"/llvm/bin/llvm-cov show \ - --Xdemangler=path/to/rust-demangler \ - --instr-profile=main.profdata ./main --show-line-counts-or-regions -``` - -`rust-demangler` is a Rust "extended tool", used in Rust compiler tests, and -optionally included in Rust distributions that enable coverage profiling. Symbol -demangling is implemented using the -[rustc-demangle](https://crates.io/crates/rustc-demangle) crate. - -_(Note, for Rust developers, the third-party tool -[`rustfilt`](https://crates.io/crates/rustfilt) also supports `llvm-cov` symbol -demangling. `rustfilt` is a more generalized tool that searches any body of -text, using pattern matching, to find and demangle Rust symbols.)_ - -## License - -Rust-demangler is distributed under the terms of both the MIT license and the -Apache License (Version 2.0). - -See [LICENSE-APACHE](/LICENSE-APACHE) and [LICENSE-MIT](/LICENSE-MIT) for details. diff --git a/src/tools/rust-demangler/src/lib.rs b/src/tools/rust-demangler/src/lib.rs deleted file mode 100644 index 1d972229d9536..0000000000000 --- a/src/tools/rust-demangler/src/lib.rs +++ /dev/null @@ -1,21 +0,0 @@ -use regex::Regex; -use rustc_demangle::demangle; -use std::str::Lines; - -const REPLACE_COLONS: &str = "::"; - -pub fn create_disambiguator_re() -> Regex { - Regex::new(r"\[[a-f0-9]{5,16}\]::").unwrap() -} - -pub fn demangle_lines(lines: Lines<'_>, strip_crate_disambiguators: Option) -> Vec { - let mut demangled_lines = Vec::new(); - for mangled in lines { - let mut demangled = demangle(mangled).to_string(); - if let Some(re) = &strip_crate_disambiguators { - demangled = re.replace_all(&demangled, REPLACE_COLONS).to_string(); - } - demangled_lines.push(demangled); - } - demangled_lines -} diff --git a/src/tools/rust-demangler/src/main.rs b/src/tools/rust-demangler/src/main.rs deleted file mode 100644 index 1b5ef5d2442ba..0000000000000 --- a/src/tools/rust-demangler/src/main.rs +++ /dev/null @@ -1,97 +0,0 @@ -//! Demangles rustc mangled names. -//! -//! Note regarding crate disambiguators: -//! -//! Some demangled symbol paths can include "crate disambiguator" suffixes, represented as a large -//! hexadecimal value enclosed in square braces, and appended to the name of the crate. a suffix to the -//! original crate name. For example, the `core` crate, here, includes a disambiguator: -//! -//! ```rust -//! as core[a7a74cee373f048]::ops::drop::Drop>::drop -//! ``` -//! -//! These disambiguators are known to vary depending on environmental circumstances. As a result, -//! tests that compare results including demangled names can fail across development environments, -//! particularly with cross-platform testing. Also, the resulting crate paths are not syntactically -//! valid, and don't match the original source symbol paths, which can impact development tools. -//! -//! For these reasons, by default, `rust-demangler` uses a heuristic to remove crate disambiguators -//! from their original demangled representation before printing them to standard output. If crate -//! disambiguators are required, add the `-d` (or `--disambiguators`) flag, and the disambiguators -//! will not be removed. -//! -//! Also note that the disambiguators are stripped by a Regex pattern that is tolerant to some -//! variation in the number of hexadecimal digits. The disambiguators come from a hash value, which -//! typically generates a 16-digit hex representation on a 64-bit architecture; however, leading -//! zeros are not included, which can shorten the hex digit length, and a different hash algorithm -//! that might also be dependent on the architecture, might shorten the length even further. A -//! minimum length of 5 digits is assumed, which should be more than sufficient to support hex -//! representations that generate only 8-digits of precision with an extremely rare (but not -//! impossible) result with up to 3 leading zeros. -//! -//! Using a minimum number of digits less than 5 risks the possibility of stripping demangled name -//! components with a similar pattern. For example, some closures instantiated multiple times -//! include their own disambiguators, demangled as non-hashed zero-based indexes in square brackets. -//! These disambiguators seem to have more analytical value (for instance, in coverage analysis), so -//! they are not removed. - -use rust_demangler::*; -use std::io::{self, Read, Write}; - -fn main() -> io::Result<()> { - // FIXME(richkadel): In Issue #77615 discussed updating the `rustc-demangle` library, to provide - // an option to generate demangled names without including crate disambiguators. If that - // happens, update this tool to use that option (if the `-d` flag is not set) instead stripping - // them via the Regex heuristic. The update the doc comments and help. - - // Strip hashed hexadecimal crate disambiguators. Leading zeros are not enforced, and can be - // different across different platform/architecture types, so while 16 hex digits are common, - // they can also be shorter. - // - // Also note that a demangled symbol path may include the `[]` pattern, with zero-based - // indexes (such as for closures, and possibly for types defined in anonymous scopes). Preferably - // these should not be stripped. - // - // The minimum length of 5 digits supports the possibility that some target architecture (maybe - // a 32-bit or smaller architecture) could generate a hash value with a maximum of 8 digits, - // and more than three leading zeros should be extremely unlikely. Conversely, it should be - // sufficient to assume the zero-based indexes for closures and anonymous scopes will never - // exceed the value 9999. - let mut strip_crate_disambiguators = Some(create_disambiguator_re()); - - let mut args = std::env::args(); - let progname = args.next().unwrap(); - for arg in args { - if arg == "--disambiguators" || arg == "-d" { - strip_crate_disambiguators = None; - } else { - eprintln!(); - eprintln!("Usage: {} [-d|--disambiguators]", progname); - eprintln!(); - eprintln!( - "This tool converts a list of Rust mangled symbols (one per line) into a\n\ - corresponding list of demangled symbols." - ); - eprintln!(); - eprintln!( - "With -d (--disambiguators), Rust symbols mangled with the v0 symbol mangler may\n\ - include crate disambiguators (a hexadecimal hash value, typically up to 16 digits\n\ - long, enclosed in square brackets)." - ); - eprintln!(); - eprintln!( - "By default, crate disambiguators are removed, using a heuristics-based regular\n\ - expression. (See the `rust-demangler` doc comments for more information.)" - ); - eprintln!(); - std::process::exit(1) - } - } - - let mut buffer = String::new(); - io::stdin().read_to_string(&mut buffer)?; - let mut demangled_lines = demangle_lines(buffer.lines(), strip_crate_disambiguators); - demangled_lines.push("".to_string()); // ensure a trailing newline - io::stdout().write_all(demangled_lines.join("\n").as_bytes())?; - Ok(()) -} diff --git a/src/tools/rust-demangler/tests/lib.rs b/src/tools/rust-demangler/tests/lib.rs deleted file mode 100644 index 85019df7867dd..0000000000000 --- a/src/tools/rust-demangler/tests/lib.rs +++ /dev/null @@ -1,84 +0,0 @@ -use rust_demangler::*; - -const MANGLED_INPUT: &str = r" -_RNvC6_123foo3bar -_RNqCs4fqI2P2rA04_11utf8_identsu30____7hkackfecea1cbdathfdh9hlq6y -_RNCNCNgCs6DXkGYLi8lr_2cc5spawn00B5_ -_RNCINkXs25_NgCsbmNqQUJIY6D_4core5sliceINyB9_4IterhENuNgNoBb_4iter8iterator8Iterator9rpositionNCNgNpB9_6memchr7memrchrs_0E0Bb_ -_RINbNbCskIICzLVDPPb_5alloc5alloc8box_freeDINbNiB4_5boxed5FnBoxuEp6OutputuEL_ECs1iopQbuBiw2_3std -INtC8arrayvec8ArrayVechKj7b_E -_RMCs4fqI2P2rA04_13const_genericINtB0_8UnsignedKhb_E -_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKs98_E -_RMCs4fqI2P2rA04_13const_genericINtB0_6SignedKanb_E -_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb0_E -_RMCs4fqI2P2rA04_13const_genericINtB0_4BoolKb1_E -_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc76_E -_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKca_E -_RMCs4fqI2P2rA04_13const_genericINtB0_4CharKc2202_E -_RNvNvMCs4fqI2P2rA04_13const_genericINtB4_3FooKpE3foo3FOO -_RC3foo.llvm.9D1C9369 -_RC3foo.llvm.9D1C9369@@16 -_RNvC9backtrace3foo.llvm.A5310EB9 -_RNvNtNtNtNtCs92dm3009vxr_4rand4rngs7adapter9reseeding4fork23FORK_HANDLER_REGISTERED.0.0 -"; - -const DEMANGLED_OUTPUT: &str = r" -123foo[0]::bar -utf8_idents[317d481089b8c8fe]::საჭმელად_გემრიელი_სადილი -cc[4d6468d6c9fd4bb3]::spawn::{closure#0}::{closure#0} - as core[846817f741e54dfd]::iter::iterator::Iterator>::rposition::::{closure#0} -alloc[f15a878b47eb696b]::alloc::box_free::> -INtC8arrayvec8ArrayVechKj7b_E -> -> -> -> -> -> -> -> ->::foo::FOO -foo[0] -foo[0] -backtrace[0]::foo -rand[693ea8e72247470f]::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0 -"; - -const DEMANGLED_OUTPUT_NO_CRATE_DISAMBIGUATORS: &str = r" -123foo[0]::bar -utf8_idents::საჭმელად_გემრიელი_სადილი -cc::spawn::{closure#0}::{closure#0} - as core::iter::iterator::Iterator>::rposition::::{closure#0} -alloc::alloc::box_free::> -INtC8arrayvec8ArrayVechKj7b_E -> -> -> -> -> -> -> -> ->::foo::FOO -foo[0] -foo[0] -backtrace[0]::foo -rand::rngs::adapter::reseeding::fork::FORK_HANDLER_REGISTERED.0.0 -"; - -#[test] -fn test_demangle_lines() { - let demangled_lines = demangle_lines(MANGLED_INPUT.lines(), None); - for (expected, actual) in DEMANGLED_OUTPUT.lines().zip(demangled_lines) { - assert_eq!(expected, actual); - } -} - -#[test] -fn test_demangle_lines_no_crate_disambiguators() { - let demangled_lines = demangle_lines(MANGLED_INPUT.lines(), Some(create_disambiguator_re())); - for (expected, actual) in DEMANGLED_OUTPUT_NO_CRATE_DISAMBIGUATORS.lines().zip(demangled_lines) - { - assert_eq!(expected, actual); - } -}