https://gcc.gnu.org/g:7f6e3f37c5049a5a397e0d9acab119d30bf89407
commit r17-4313-g7f6e3f37c5049a5a397e0d9acab119d30bf89407 Author: Lishin <[email protected]> Date: Fri Aug 28 17:28:27 2026 +0000 gccrs: Reject multiple move sources in product-type expressions Pass the struct expression HIR ID through BIR so moves from the same expression can be identified. For now, report the case as unsupported when an expression moves more than one value. gcc/rust/ChangeLog: * checks/errors/borrowck/rust-bir-builder-expr-stmt.cc (ExprStmtBuilder::visit): Pass the struct expression HIR ID. * checks/errors/borrowck/rust-bir-builder-internal.h (AbstractBuilder::push_tmp_assignment): Propagate move sites. (AbstractBuilder::move_place): Likewise. (AbstractBuilder::move_all): Likewise. * checks/errors/borrowck/rust-bir-drop-analysis.cc (annotate_drop_statements): Reject multiple move sources. gcc/testsuite/ChangeLog: * rust/compile/drop-conditional-product-move.rs: New test. Signed-off-by: Lishin <[email protected]> Diff: --- .../errors/borrowck/rust-bir-builder-expr-stmt.cc | 2 +- .../errors/borrowck/rust-bir-builder-internal.h | 25 ++++++----- .../errors/borrowck/rust-bir-drop-analysis.cc | 16 ++++++- .../rust/compile/drop-conditional-product-move.rs | 49 ++++++++++++++++++++++ 4 files changed, 79 insertions(+), 13 deletions(-) diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc index 889e4611eca0..6586e9521bec 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc @@ -111,7 +111,7 @@ ExprStmtBuilder::visit (HIR::StructExprStructFields &fields) { field_locations.push_back (field->get_locus ()); } - move_all (init_values, field_locations); + move_all (init_values, field_locations, fields.get_mappings ().get_hirid ()); return_expr (new InitializerExpr (std::move (init_values)), lookup_type (fields), fields.get_locus ()); } diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h index b5644741d9eb..b1ced93ebd65 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h +++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-internal.h @@ -280,17 +280,19 @@ protected: // Helpers to add BIR statements } void push_tmp_assignment (AbstractExpr *rhs, TyTy::BaseType *tyty, - location_t location) + location_t location, + tl::optional<HirId> move_site = tl::nullopt) { PlaceId tmp = ctx.place_db.add_temporary (tyty); push_storage_live (tmp); - push_assignment (tmp, rhs, location); + push_assignment (tmp, rhs, location, move_site); } - void push_tmp_assignment (PlaceId rhs, location_t location) + void push_tmp_assignment (PlaceId rhs, location_t location, + tl::optional<HirId> move_site = tl::nullopt) { - push_tmp_assignment (new Assignment (rhs), ctx.place_db[rhs].tyty, - location); + push_tmp_assignment (new Assignment (rhs), ctx.place_db[rhs].tyty, location, + move_site); } void push_switch (PlaceId switch_val, location_t location, @@ -353,7 +355,8 @@ protected: // Helpers to add BIR statements return translated; } - PlaceId move_place (PlaceId arg, location_t location) + PlaceId move_place (PlaceId arg, location_t location, + tl::optional<HirId> move_site = tl::nullopt) { auto &place = ctx.place_db[arg]; @@ -366,7 +369,7 @@ protected: // Helpers to add BIR statements if (place.is_rvalue ()) return arg; - push_tmp_assignment (arg, location); + push_tmp_assignment (arg, location, move_site); return translated; } @@ -379,12 +382,14 @@ protected: // Helpers to add BIR statements } template <typename T> - void move_all (T &args, std::vector<location_t> locations) + void move_all (T &args, std::vector<location_t> locations, + tl::optional<HirId> move_site = tl::nullopt) { rust_assert (args.size () == locations.size ()); std::transform (args.begin (), args.end (), locations.begin (), - args.begin (), [this] (PlaceId arg, location_t location) { - return move_place (arg, location); + args.begin (), + [this, move_site] (PlaceId arg, location_t location) { + return move_place (arg, location, move_site); }); } diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.cc b/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.cc index 22be1553eee5..8a52d78f1b7b 100644 --- a/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.cc +++ b/gcc/rust/checks/errors/borrowck/rust-bir-drop-analysis.cc @@ -18,6 +18,7 @@ #include "rust-bir-drop-analysis.h" #include "rust-bir.h" +#include "rust-diagnostics.h" #include "rust-hir-map.h" namespace Rust { @@ -301,8 +302,19 @@ annotate_drop_statements ( static_cast<NodeId> ( rhs_place.variable_or_field_index)); if (hirid.has_value ()) - results.move_sources[move_site.value ()] - = hirid.value (); + { + auto move_source + = results.move_sources.find (move_site.value ()); + if (move_source != results.move_sources.end () + && move_source->second != hirid.value ()) + rust_sorry_at (statement.get_location (), + "moving multiple IDs within the " + "same location is not " + "yet supported"); + else + results.move_sources.emplace (move_site.value (), + hirid.value ()); + } } } } diff --git a/gcc/testsuite/rust/compile/drop-conditional-product-move.rs b/gcc/testsuite/rust/compile/drop-conditional-product-move.rs new file mode 100644 index 000000000000..a221a030809e --- /dev/null +++ b/gcc/testsuite/rust/compile/drop-conditional-product-move.rs @@ -0,0 +1,49 @@ +// { dg-additional-options "-frust-borrowcheck -w" } + +#![feature(no_core)] +#![feature(lang_items)] +#![no_core] + +#[lang = "sized"] +pub trait Sized {} + +#[lang = "drop"] +pub trait Drop { + fn drop(&mut self); +} + +struct Droppable { + value: i32, +} + +impl Drop for Droppable { + fn drop(&mut self) {} +} + +struct Pair { + first: Droppable, + second: Droppable, +} + +fn unconditional_product_move() { + let first = Droppable { value: 1 }; + let second = Droppable { value: 2 }; + let _pair = Pair { first, second }; // { dg-message "sorry, unimplemented: moving multiple IDs within the same location is not yet supported" } +} + +fn conditional_product_move(condition: bool) { + let first = Droppable { value: 1 }; + let second = Droppable { value: 2 }; + + if condition { + let _pair = Pair { + first, + second, // { dg-message "sorry, unimplemented: moving multiple IDs within the same location is not yet supported" } + }; + } +} + +fn main() { + unconditional_product_move(); + conditional_product_move(true); +}
