[COMMITTED 063/144] gccrs: Strong type PlaceId

arthur.cohen@embecosm.com arthur.cohen@embecosm.com
Wed Mar 19 14:43:44 GMT 2025


From: Kushal Pal <kushalpal109@gmail.com>

gcc/rust/ChangeLog:

	* checks/errors/borrowck/rust-bir-dump.cc (renumber_places):
	Use value of PlaceId as index.
	(Dump::visit_place): Likewise.
	(Dump::visit_scope): Likewise.
	(Dump::go): Refill `place_map` with for loop instead of
	using std::iota().
	* checks/errors/borrowck/rust-bir-fact-collector.h (points): Use
	value as index.
	* checks/errors/borrowck/rust-bir-place.h (struct PlaceId):
	PlaceId is now a class holding a uint32_t value. Overloaded
	comparision operators for easier comparision.

Signed-off-by: Kushal Pal <kushalpal109@gmail.com>
---
 .../checks/errors/borrowck/rust-bir-dump.cc   | 25 ++++--
 .../errors/borrowck/rust-bir-fact-collector.h | 61 +++++++------
 .../checks/errors/borrowck/rust-bir-place.h   | 88 +++++++++++--------
 3 files changed, 103 insertions(+), 71 deletions(-)

diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
index a35f47b86d6..924c7d9a6e8 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-dump.cc
@@ -53,16 +53,20 @@ renumber_places (const Function &func, std::vector<PlaceId> &place_map)
 {
   // Renumbering places to avoid gaps in the place id space.
   // This is needed to match MIR's shape.
-  size_t next_out_id = 0;
+  PlaceId next_out_id = INVALID_PLACE;
 
-  for (size_t in_id = FIRST_VARIABLE_PLACE; in_id < func.place_db.size ();
-       ++in_id)
+  for (PlaceId in_id = FIRST_VARIABLE_PLACE;
+       in_id.value < func.place_db.size (); ++in_id.value)
     {
       const Place &place = func.place_db[in_id];
       if (place.kind == Place::VARIABLE || place.kind == Place::TEMPORARY)
-	place_map[in_id] = next_out_id++;
+	{
+	  place_map[in_id.value] = next_out_id;
+	  ++next_out_id.value;
+	}
+
       else
-	place_map[in_id] = INVALID_PLACE;
+	place_map[in_id.value] = INVALID_PLACE;
     }
 }
 
@@ -110,7 +114,10 @@ Dump::go (bool enable_simplify_cfg)
   // To avoid mutation of the BIR, we use indirection through bb_fold_map.
   std::iota (bb_fold_map.begin (), bb_fold_map.end (), 0);
 
-  std::iota (place_map.begin (), place_map.end (), 0);
+  for (size_t i = 0; i < place_map.size (); ++i)
+    {
+      place_map[i] = {i};
+    }
 
   if (enable_simplify_cfg)
     simplify_cfg (func, bb_fold_map);
@@ -119,7 +126,7 @@ Dump::go (bool enable_simplify_cfg)
 
   stream << "fn " << name << "(";
   print_comma_separated (stream, func.arguments, [this] (PlaceId place_id) {
-    stream << "_" << place_map[place_id] << ": "
+    stream << "_" << place_map[place_id.value].value << ": "
 	   << get_tyty_name (func.place_db[place_id].tyty);
   });
   stream << ") -> " << get_tyty_name (func.place_db[RETURN_VALUE_PLACE].tyty);
@@ -228,7 +235,7 @@ Dump::visit_place (PlaceId place_id)
     {
     case Place::TEMPORARY:
     case Place::VARIABLE:
-      stream << "_" << place_map[place_id];
+      stream << "_" << place_map[place_id.value].value;
       break;
     case Place::DEREF:
       stream << "(";
@@ -365,7 +372,7 @@ Dump::visit_scope (ScopeId id, size_t depth)
   for (auto &local : scope.locals)
     {
       indent (depth + 1) << "let _";
-      stream << place_map[local] << ": "
+      stream << place_map[local.value].value << ": "
 	     << get_tyty_name (func.place_db[local].tyty);
       stream << ";\t";
 
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
index 9999bddaf59..fa7cbb38eef 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-fact-collector.h
@@ -88,8 +88,9 @@ public:
 protected: // Constructor and destructor.
   explicit FactCollector (Function &func)
     : place_db (func.place_db), basic_blocks (func.basic_blocks),
-      first_local (func.arguments.empty () ? FIRST_VARIABLE_PLACE
-					   : *func.arguments.rbegin () + 1),
+      first_local (func.arguments.empty ()
+		     ? FIRST_VARIABLE_PLACE
+		     : PlaceId{func.arguments.rbegin ()->value + 1}),
       location (func.location), tyctx (*Resolver::TypeCheckContext::get ()),
       next_fresh_region (place_db.peek_next_free_region ())
   {}
@@ -118,7 +119,8 @@ protected: // Main collection entry points (for different categories).
 
   void visit_places (const std::vector<PlaceId> &args)
   {
-    for (PlaceId place_id = 0; place_id < place_db.size (); ++place_id)
+    for (PlaceId place_id = INVALID_PLACE; place_id.value < place_db.size ();
+	 ++place_id.value)
       {
 	auto &place = place_db[place_id];
 
@@ -126,24 +128,28 @@ protected: // Main collection entry points (for different categories).
 	  {
 	  case Place::VARIABLE:
 	  case Place::TEMPORARY:
-	    facts.path_is_var.emplace_back (place_id, place_id);
+	    facts.path_is_var.emplace_back (place_id.value, place_id.value);
 	    for (auto &region : place.regions)
-	      facts.use_of_var_derefs_origin.emplace_back (place_id, region);
+	      facts.use_of_var_derefs_origin.emplace_back (place_id.value,
+							   region);
 
 	    // TODO: drop_of_var_derefs_origin
 	    break;
 	  case Place::FIELD:
 	    sanizite_field (place_id);
-	    facts.child_path.emplace_back (place_id, place.path.parent);
+	    facts.child_path.emplace_back (place_id.value,
+					   place.path.parent.value);
 	    break;
 	  case Place::INDEX:
 	    push_subset_all (place.tyty, place.regions,
 			     place_db[place.path.parent].regions);
-	    facts.child_path.emplace_back (place_id, place.path.parent);
+	    facts.child_path.emplace_back (place_id.value,
+					   place.path.parent.value);
 	    break;
 	  case Place::DEREF:
 	    sanitize_deref (place_id);
-	    facts.child_path.emplace_back (place_id, place.path.parent);
+	    facts.child_path.emplace_back (place_id.value,
+					   place.path.parent.value);
 	    break;
 	  case Place::CONSTANT:
 	  case Place::INVALID:
@@ -151,15 +157,17 @@ protected: // Main collection entry points (for different categories).
 	  }
       }
 
-    for (PlaceId arg = FIRST_VARIABLE_PLACE + 1; arg < first_local; ++arg)
+    for (PlaceId arg = PlaceId{FIRST_VARIABLE_PLACE.value + 1};
+	 arg < first_local; ++arg.value)
       facts.path_assigned_at_base.emplace_back (
-	arg, get_point (0, 0, PointPosition::START));
+	arg.value, get_point (0, 0, PointPosition::START));
 
-    for (PlaceId place = first_local; place < place_db.size (); ++place)
+    for (PlaceId place = first_local; place.value < place_db.size ();
+	 ++place.value)
       {
 	if (place_db[place].is_var ())
 	  facts.path_moved_at_base.emplace_back (
-	    place, get_point (0, 0, PointPosition::START));
+	    place.value, get_point (0, 0, PointPosition::START));
       }
   }
 
@@ -242,9 +250,9 @@ protected: // Main collection entry points (for different categories).
 	  break;
 	}
 	case Statement::Kind::STORAGE_DEAD: {
-	  facts.path_moved_at_base.emplace_back (stmt.get_place (),
+	  facts.path_moved_at_base.emplace_back (stmt.get_place ().value,
 						 get_current_point_mid ());
-	  facts.var_defined_at.emplace_back (stmt.get_place (),
+	  facts.var_defined_at.emplace_back (stmt.get_place ().value,
 					     get_current_point_mid ());
 	  break;
 	}
@@ -293,7 +301,8 @@ protected: // Main collection entry points (for different categories).
 
   void visit (const BorrowExpr &expr) override
   {
-    rust_debug ("\t_%u = BorrowExpr(_%u)", lhs - 1, expr.get_place () - 1);
+    rust_debug ("\t_%u = BorrowExpr(_%u)", lhs.value - 1,
+		expr.get_place ().value - 1);
 
     auto loan = place_db.get_loans ()[expr.get_loan ()];
 
@@ -330,8 +339,8 @@ protected: // Main collection entry points (for different categories).
 
   void visit (const Assignment &expr) override
   {
-    rust_debug ("\t_%u = Assignment(_%u) at %u:%u", lhs - 1,
-		expr.get_rhs () - 1, current_bb, current_stmt);
+    rust_debug ("\t_%u = Assignment(_%u) at %u:%u", lhs.value - 1,
+		expr.get_rhs ().value - 1, current_bb, current_stmt);
 
     issue_read_move (expr.get_rhs ());
     push_place_subset (lhs, expr.get_rhs ());
@@ -339,7 +348,8 @@ protected: // Main collection entry points (for different categories).
 
   void visit (const CallExpr &expr) override
   {
-    rust_debug ("\t_%u = CallExpr(_%u)", lhs - 1, expr.get_callable () - 1);
+    rust_debug ("\t_%u = CallExpr(_%u)", lhs.value - 1,
+		expr.get_callable ().value - 1);
 
     auto &return_place = place_db[lhs];
     auto &callable_place = place_db[expr.get_callable ()];
@@ -434,14 +444,14 @@ protected: // Generic BIR operations.
       return;
 
     if (place_id != RETURN_VALUE_PLACE)
-      facts.path_accessed_at_base.emplace_back (place_id,
+      facts.path_accessed_at_base.emplace_back (place_id.value,
 						get_current_point_mid ());
 
     if (place.is_var ())
-      facts.var_used_at.emplace_back (place_id, get_current_point_mid ());
+      facts.var_used_at.emplace_back (place_id.value, get_current_point_mid ());
     else if (place.is_path ())
       {
-	facts.var_used_at.emplace_back (place_db.get_var (place_id),
+	facts.var_used_at.emplace_back (place_db.get_var (place_id).value,
 					get_current_point_mid ());
       }
   }
@@ -468,11 +478,12 @@ protected: // Generic BIR operations.
     rust_assert (place.is_lvalue () || place.is_rvalue ());
 
     if (place.is_var ())
-      facts.var_defined_at.emplace_back (place_id, get_current_point_mid ());
+      facts.var_defined_at.emplace_back (place_id.value,
+					 get_current_point_mid ());
 
     if (!is_init)
       {
-	facts.path_assigned_at_base.emplace_back (place_id,
+	facts.path_assigned_at_base.emplace_back (place_id.value,
 						  get_current_point_mid ());
 	check_write_for_conflict (place_id);
 	kill_borrows_for_place (place_id);
@@ -485,8 +496,8 @@ protected: // Generic BIR operations.
       return;
 
     facts.path_moved_at_base.emplace_back (
-      place_id, initial ? get_point (0, 0, PointPosition::START)
-			: get_current_point_mid ());
+      place_id.value, initial ? get_point (0, 0, PointPosition::START)
+			      : get_current_point_mid ());
 
     check_move_behind_reference (place_id);
 
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-place.h b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
index 66da3dab380..1a7a1428df9 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-place.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-place.h
@@ -32,10 +32,20 @@ namespace Rust {
 namespace BIR {
 
 /** A unique identifier for a place in the BIR. */
-using PlaceId = uint32_t;
+struct PlaceId
+{
+  uint32_t value;
+  // some overloads for comparision
+  bool operator== (const PlaceId &rhs) const { return value == rhs.value; }
+  bool operator!= (const PlaceId &rhs) const { return !(operator== (rhs)); }
+  bool operator< (const PlaceId &rhs) const { return value < rhs.value; }
+  bool operator> (const PlaceId &rhs) const { return value > rhs.value; }
+  bool operator<= (const PlaceId &rhs) const { return !(operator> (rhs)); }
+  bool operator>= (const PlaceId &rhs) const { return !(operator< (rhs)); }
+};
 
-static constexpr PlaceId INVALID_PLACE = 0;
-static constexpr PlaceId RETURN_VALUE_PLACE = 1;
+static constexpr PlaceId INVALID_PLACE = {0};
+static constexpr PlaceId RETURN_VALUE_PLACE = {1};
 static constexpr PlaceId FIRST_VARIABLE_PLACE = RETURN_VALUE_PLACE;
 
 using Variance = TyTy::VarianceAnalysis::Variance;
@@ -188,8 +198,8 @@ public:
     scopes.emplace_back (); // Root scope.
   }
 
-  Place &operator[] (PlaceId id) { return places.at (id); }
-  const Place &operator[] (PlaceId id) const { return places.at (id); }
+  Place &operator[] (PlaceId id) { return places.at (id.value); }
+  const Place &operator[] (PlaceId id) const { return places.at (id.value); }
 
   decltype (places)::const_iterator begin () const { return places.begin (); }
   decltype (places)::const_iterator end () const { return places.end (); }
@@ -228,15 +238,15 @@ public:
     return current_scope;
   }
 
-  PlaceId add_place (Place &&place, PlaceId last_sibling = 0)
+  PlaceId add_place (Place &&place, PlaceId last_sibling = INVALID_PLACE)
   {
     places.emplace_back (std::forward<Place &&> (place));
-    PlaceId new_place = places.size () - 1;
-    Place &new_place_ref = places[new_place]; // Intentional shadowing.
-    if (last_sibling == 0)
-      places[new_place_ref.path.parent].path.first_child = new_place;
+    PlaceId new_place = {places.size () - 1};
+    Place &new_place_ref = places[new_place.value]; // Intentional shadowing.
+    if (last_sibling == INVALID_PLACE)
+      places[new_place_ref.path.parent.value].path.first_child = new_place;
     else
-      places[last_sibling].path.next_sibling = new_place;
+      places[last_sibling.value].path.next_sibling = new_place;
 
     if (new_place_ref.kind == Place::VARIABLE
 	|| new_place_ref.kind == Place::TEMPORARY)
@@ -256,36 +266,39 @@ public:
 
   PlaceId add_variable (NodeId id, TyTy::BaseType *tyty)
   {
-    return add_place ({Place::VARIABLE, id, {}, is_type_copy (tyty), tyty}, 0);
+    return add_place ({Place::VARIABLE, id, {}, is_type_copy (tyty), tyty},
+		      INVALID_PLACE);
   }
 
   WARN_UNUSED_RESULT PlaceId lookup_or_add_path (Place::Kind kind,
 						 TyTy::BaseType *tyty,
 						 PlaceId parent, size_t id = 0)
   {
-    PlaceId current = 0;
-    if (parent < places.size ())
+    PlaceId current = INVALID_PLACE;
+    if (parent.value < places.size ())
       {
-	current = places[parent].path.first_child;
-	while (current != 0)
+	current = places[parent.value].path.first_child;
+	while (current != INVALID_PLACE)
 	  {
-	    if (places[current].kind == kind
-		&& places[current].variable_or_field_index == id)
+	    if (places[current.value].kind == kind
+		&& places[current.value].variable_or_field_index == id)
 	      {
-		rust_assert (places[current].tyty->is_equal (*tyty));
+		rust_assert (places[current.value].tyty->is_equal (*tyty));
 		return current;
 	      }
-	    current = places[current].path.next_sibling;
+	    current = places[current.value].path.next_sibling;
 	  }
       }
-    return add_place ({kind, (uint32_t) id, Place::Path{parent, 0, 0},
+    return add_place ({kind, (uint32_t) id,
+		       Place::Path{parent, INVALID_PLACE, INVALID_PLACE},
 		       is_type_copy (tyty), tyty},
 		      current);
   }
 
   PlaceId add_temporary (TyTy::BaseType *tyty)
   {
-    return add_place ({Place::TEMPORARY, 0, {}, is_type_copy (tyty), tyty}, 0);
+    return add_place ({Place::TEMPORARY, 0, {}, is_type_copy (tyty), tyty},
+		      INVALID_PLACE);
   }
 
   PlaceId get_constant (TyTy::BaseType *tyty)
@@ -300,12 +313,12 @@ public:
   {
     PlaceId current = FIRST_VARIABLE_PLACE;
 
-    while (current != places.size ())
+    while (current.value != places.size ())
       {
-	if (places[current].kind == Place::VARIABLE
-	    && places[current].variable_or_field_index == id)
+	if (places[current.value].kind == Place::VARIABLE
+	    && places[current.value].variable_or_field_index == id)
 	  return current;
-	current++;
+	++current.value;
       }
     return INVALID_PLACE;
   }
@@ -315,23 +328,24 @@ public:
     LoanId id = loans.size ();
     loans.push_back (std::forward<Loan &&> (loan));
     PlaceId borrowed_place = loans.rbegin ()->place;
-    places[loans.rbegin ()->place].borrowed_by.push_back (id);
-    if (places[borrowed_place].kind == Place::DEREF)
+    places[loans.rbegin ()->place.value].borrowed_by.push_back (id);
+    if (places[borrowed_place.value].kind == Place::DEREF)
       {
-	places[places[borrowed_place].path.parent].borrowed_by.push_back (id);
+	places[places[borrowed_place.value].path.parent.value]
+	  .borrowed_by.push_back (id);
       }
     return id;
   }
 
   PlaceId get_var (PlaceId id) const
   {
-    if (places[id].is_var ())
+    if (places[id.value].is_var ())
       return id;
-    rust_assert (places[id].is_path ());
+    rust_assert (places[id.value].is_path ());
     PlaceId current = id;
-    while (!places[current].is_var ())
+    while (!places[current.value].is_var ())
       {
-	current = places[current].path.parent;
+	current = places[current.value].path.parent;
       }
     return current;
   }
@@ -348,18 +362,18 @@ public:
       return lookup;
 
     add_place ({Place::VARIABLE, id, {}, is_type_copy (tyty), tyty});
-    return places.size () - 1;
+    return {places.size () - 1};
   };
 
   template <typename FN> void for_each_path_from_root (PlaceId var, FN fn) const
   {
     PlaceId current = var;
-    current = places[current].path.first_child;
+    current = places[current.value].path.first_child;
     while (current != INVALID_PLACE)
       {
 	fn (current);
 	for_each_path_from_root (current, fn);
-	current = places[current].path.next_sibling;
+	current = places[current.value].path.next_sibling;
       }
   }
 
@@ -370,7 +384,7 @@ public:
     while (current != INVALID_PLACE)
       {
 	fn (current);
-	current = places[current].path.parent;
+	current = places[current.value].path.parent;
       }
   }
 
-- 
2.45.2



More information about the Gcc-rust mailing list