[COMMITTED 36/83] gccrs: Reject multiple move sources in product-type expressions
arthur.cohen@opensrcsec.com
arthur.cohen@opensrcsec.com
Wed Sep 16 12:29:55 GMT 2026
From: Lishin <lishin1008@gmail.com>
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 <lishin1008@gmail.com>
---
.../borrowck/rust-bir-builder-expr-stmt.cc | 2 +-
.../borrowck/rust-bir-builder-internal.h | 25 ++++++----
.../errors/borrowck/rust-bir-drop-analysis.cc | 16 +++++-
.../compile/drop-conditional-product-move.rs | 49 +++++++++++++++++++
4 files changed, 79 insertions(+), 13 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/drop-conditional-product-move.rs
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 889e4611eca..6586e9521be 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 b5644741d9e..b1ced93ebd6 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 22be1553eee..8a52d78f1b7 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 00000000000..a221a030809
--- /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);
+}
--
2.50.1
More information about the Gcc-rust
mailing list