From e61d37aae9a47461370cbd3c49123eba6fb64dc9 Mon Sep 17 00:00:00 2001 From: Kushal Pal Date: Mon, 12 Aug 2024 05:48:27 +0000 Subject: [PATCH] Move errors with locations gcc/rust/ChangeLog: * checks/errors/borrowck/rust-borrow-checker-diagnostics.cc (BorrowCheckerDiagnostics::report_move_errors): Specify locations for code causing errors and related moves. gcc/testsuite/ChangeLog: * rust/borrowck/test_move.rs: Test rich-errors related to moves. * rust/borrowck/test_move_conditional.rs: Likewise. Signed-off-by: Kushal Pal --- .../rust-borrow-checker-diagnostics.cc | 39 ++++++++++++++-- gcc/testsuite/rust/borrowck/test_move.rs | 22 +++++++-- .../rust/borrowck/test_move_conditional.rs | 45 +++++++++++++++++-- 3 files changed, 96 insertions(+), 10 deletions(-) diff --git a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc index dc010291073d..f2e4c38cfa0f 100644 --- a/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc +++ b/gcc/rust/checks/errors/borrowck/rust-borrow-checker-diagnostics.cc @@ -34,11 +34,42 @@ BorrowCheckerDiagnostics::report_errors () void BorrowCheckerDiagnostics::report_move_errors () { - if (!move_errors.empty ()) + for (const auto &pair : move_errors) { - rust_error_at (hir_function->get_locus (), - "Found move errors in function %s", - hir_function->get_function_name ().as_string ().c_str ()); + auto error_location = get_statement (pair.first).get_location (); + + // in future, we can use the assigned at location to hint the + // user to implement copy trait for the type + /* + for (auto it : facts.path_assigned_at_base) + { + if (pair.second[0] == it.first) + { + auto point_assigned_at = it.second; + auto assigned_at_location + = get_statement (point_assigned_at).get_location (); + } + } + */ + + std::vector labels{ + {"moved value used here", error_location}}; + // add labels to all the moves for the given path + for (auto it : facts.path_moved_at_base) + { + if (pair.second[0] == it.first) + { + auto point_moved_at = it.second; + // don't label the move location where the error occured + if (pair.first != point_moved_at) + { + auto move_at_location + = get_statement (point_moved_at).get_location (); + labels.push_back ({"value moved here", move_at_location}); + } + } + } + multi_label_error ("use of moved value", error_location, labels); } } diff --git a/gcc/testsuite/rust/borrowck/test_move.rs b/gcc/testsuite/rust/borrowck/test_move.rs index 26a1a5b7bdec..b6475839c04a 100644 --- a/gcc/testsuite/rust/borrowck/test_move.rs +++ b/gcc/testsuite/rust/borrowck/test_move.rs @@ -1,11 +1,27 @@ -// { dg-additional-options "-frust-compile-until=compilation -frust-borrowcheck" } -fn test_move() { // { dg-error "Found move errors in function test_move" } +// { dg-additional-options "-frust-compile-until=compilation -frust-borrowcheck -fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } +// { dg-enable-nn-line-numbers "" } + +fn test_move() { struct A { i: i32, } let a = A { i: 1 }; let b = a; - let c = a; + let c = a; //~ ERROR + // { dg-error "use of moved value" "" { target *-*-* } .-1 } + /* + { dg-begin-multiline-output "" } + NN | let b = a; + | ~ + | | + | value moved here + NN | let c = a; //~ ERROR + | ^ + | | + | moved value used here + { dg-end-multiline-output "" } + */ + } fn test_move_fixed() { diff --git a/gcc/testsuite/rust/borrowck/test_move_conditional.rs b/gcc/testsuite/rust/borrowck/test_move_conditional.rs index e1e8e2025cf1..94882bca5a77 100644 --- a/gcc/testsuite/rust/borrowck/test_move_conditional.rs +++ b/gcc/testsuite/rust/borrowck/test_move_conditional.rs @@ -1,6 +1,7 @@ -// { dg-additional-options "-frust-compile-until=compilation -frust-borrowcheck" } +// { dg-additional-options "-frust-compile-until=compilation -frust-borrowcheck -fdiagnostics-show-caret -fdiagnostics-show-line-numbers" } +// { dg-enable-nn-line-numbers "" } -fn test_move_conditional(b1: bool, b2:bool) { // { dg-error "Found move errors in function test_move" } +fn test_move_conditional(b1: bool, b2:bool) { struct A { i: i32, } @@ -9,9 +10,47 @@ fn test_move_conditional(b1: bool, b2:bool) { // { dg-error "Found move errors i let b = a; if b1 { let b = a; + // { dg-error "use of moved value" "" { target *-*-* } .-1 } + /* + { dg-begin-multiline-output "" } + NN | let b = a; + | ~ + | | + | value moved here + NN | if b1 { + NN | let b = a; + | ~ + | | + | value moved here +...... + NN | let c = a; + | ^ + | | + | moved value used here + { dg-end-multiline-output "" } + */ } if b2 { let c = a; + // { dg-error "use of moved value" "" { target *-*-* } .-1 } + /* + { dg-begin-multiline-output "" } + NN | let b = a; + | ~ + | | + | value moved here + NN | if b1 { + NN | let b = a; + | ^ + | | + | moved value used here +...... + NN | let c = a; + | ~ + | | + | value moved here + { dg-end-multiline-output "" } + */ } } @@ -25,4 +64,4 @@ fn test_move_fixed(b1: bool, b2:bool) { if b2 { let c = a; } -} \ No newline at end of file +}