https://gcc.gnu.org/g:796f8f694415245016e398a59773d4cb8db35479

commit r16-2951-g796f8f694415245016e398a59773d4cb8db35479
Author: Arthur Cohen <arthur.co...@embecosm.com>
Date:   Mon Jul 21 09:36:16 2025 +0200

    gccrs: ast: Use AnonConst for array type sizes
    
    gcc/rust/ChangeLog:
    
            * ast/rust-expr.h: Add handling for deferred consts.
            * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
            * ast/rust-ast.cc (AnonConst::as_string): Likewise.
            (ArrayType::as_string): Likewise.
            * ast/rust-type.h (class ArrayType): Use AnonConst for sizes.
            * parse/rust-parse-impl.h (Parser::parse_anon_const): New function.
            (Parser::parse_slice_or_array_type): Call it.
            * parse/rust-parse.h: Declare it.

Diff:
---
 gcc/rust/ast/rust-ast-visitor.cc |  3 ++-
 gcc/rust/ast/rust-ast.cc         | 11 +++++++++--
 gcc/rust/ast/rust-expr.h         | 40 ++++++++++++++++++++++++++++++++++------
 gcc/rust/ast/rust-type.h         | 29 +++++++++++++----------------
 gcc/rust/parse/rust-parse-impl.h | 32 +++++++++++++++++++++++++++++---
 gcc/rust/parse/rust-parse.h      |  9 +++++++++
 6 files changed, 96 insertions(+), 28 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index ca7b3e495d0f..32d5d32e43fe 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -464,7 +464,8 @@ DefaultASTVisitor::visit (AST::ConstBlock &expr)
 void
 DefaultASTVisitor::visit (AST::AnonConst &expr)
 {
-  visit (expr.get_inner_expr ());
+  if (!expr.is_deferred ())
+    visit (expr.get_inner_expr ());
 }
 
 void
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 3d230ce55c32..2b7ee5cb8bf0 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -1281,7 +1281,14 @@ BlockExpr::as_string () const
 std::string
 AnonConst::as_string () const
 {
-  return "AnonConst: " + expr->as_string ();
+  std::string str = "AnonConst: ";
+
+  if (kind == AnonConst::Kind::DeferredInference)
+    str += "_";
+  else
+    str += expr.value ()->as_string ();
+
+  return str;
 }
 
 std::string
@@ -2768,7 +2775,7 @@ std::string
 ArrayType::as_string () const
 {
   // TODO: rewrite to work with non-linearisable types and exprs
-  return "[" + elem_type->as_string () + "; " + size->as_string () + "]";
+  return "[" + elem_type->as_string () + "; " + size.as_string () + "]";
 }
 
 std::string
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 296821131b1e..c875d6914b3d 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -1,6 +1,7 @@
 #ifndef RUST_AST_EXPR_H
 #define RUST_AST_EXPR_H
 
+#include "optional.h"
 #include "rust-ast.h"
 #include "rust-common.h"
 #include "rust-path.h"
@@ -2759,24 +2760,42 @@ protected:
 class AnonConst : public ExprWithBlock
 {
 public:
+  enum class Kind
+  {
+    Explicit,
+    DeferredInference,
+  };
+
   AnonConst (std::unique_ptr<Expr> &&expr, location_t locus = UNKNOWN_LOCATION)
-    : ExprWithBlock (), locus (locus), expr (std::move (expr))
+    : ExprWithBlock (), locus (locus), kind (Kind::Explicit),
+      expr (std::move (expr))
   {
-    rust_assert (this->expr);
+    rust_assert (this->expr.value ());
   }
 
+  AnonConst (location_t locus = UNKNOWN_LOCATION)
+    : ExprWithBlock (), locus (locus), kind (Kind::DeferredInference),
+      expr (tl::nullopt)
+  {}
+
   AnonConst (const AnonConst &other)
   {
     node_id = other.node_id;
     locus = other.locus;
-    expr = other.expr->clone_expr ();
+    kind = other.kind;
+
+    if (other.expr)
+      expr = other.expr.value ()->clone_expr ();
   }
 
   AnonConst operator= (const AnonConst &other)
   {
     node_id = other.node_id;
     locus = other.locus;
-    expr = other.expr->clone_expr ();
+    kind = other.kind;
+
+    if (other.expr)
+      expr = other.expr.value ()->clone_expr ();
 
     return *this;
   }
@@ -2786,7 +2805,13 @@ public:
   Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; }
 
   location_t get_locus () const override { return locus; }
-  Expr &get_inner_expr () { return *expr; }
+
+  Expr &get_inner_expr ()
+  {
+    rust_assert (expr.has_value ());
+    return *expr.value ();
+  }
+
   NodeId get_node_id () const override { return node_id; }
 
   /* FIXME: AnonConst are always "internal" and should not have outer 
attributes
@@ -2807,9 +2832,12 @@ public:
 
   void accept_vis (ASTVisitor &vis) override;
 
+  bool is_deferred () const { return kind == Kind::DeferredInference; }
+
 private:
   location_t locus;
-  std::unique_ptr<Expr> expr;
+  Kind kind;
+  tl::optional<std::unique_ptr<Expr>> expr;
 
   AnonConst *clone_expr_with_block_impl () const override
   {
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index abbfd36a6f57..2a3496b11c62 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -21,6 +21,7 @@
 
 #include "optional.h"
 #include "rust-ast.h"
+#include "rust-expr.h"
 #include "rust-path.h"
 
 namespace Rust {
@@ -678,27 +679,26 @@ protected:
 class ArrayType : public TypeNoBounds
 {
   std::unique_ptr<Type> elem_type;
-  std::unique_ptr<Expr> size;
+  AnonConst size;
   location_t locus;
 
 public:
   // Constructor requires pointers for polymorphism
-  ArrayType (std::unique_ptr<Type> type, std::unique_ptr<Expr> array_size,
-            location_t locus)
+  ArrayType (std::unique_ptr<Type> type, AnonConst array_size, location_t 
locus)
     : elem_type (std::move (type)), size (std::move (array_size)), locus 
(locus)
   {}
 
   // Copy constructor requires deep copies of both unique pointers
   ArrayType (ArrayType const &other)
-    : elem_type (other.elem_type->clone_type ()),
-      size (other.size->clone_expr ()), locus (other.locus)
+    : elem_type (other.elem_type->clone_type ()), size (other.size),
+      locus (other.locus)
   {}
 
   // Overload assignment operator to deep copy pointers
   ArrayType &operator= (ArrayType const &other)
   {
     elem_type = other.elem_type->clone_type ();
-    size = other.size->clone_expr ();
+    size = other.size;
     locus = other.locus;
     return *this;
   }
@@ -721,17 +721,15 @@ public:
   }
 
   // TODO: would a "vis_expr" be better?
-  Expr &get_size_expr ()
+  AnonConst &get_size_expr ()
   {
-    rust_assert (size != nullptr);
-    return *size;
+    // rust_assert (size != nullptr);
+
+    return size;
   }
 
   std::unique_ptr<Type> &get_element_type () { return elem_type; }
 
-  // Additional getter for direct access to the size expr unique_ptr
-  std::unique_ptr<Expr> &get_size_ptr () { return size; }
-
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
@@ -741,10 +739,9 @@ protected:
   }
   ArrayType *reconstruct_impl () const override
   {
-    return new ArrayType (
-      elem_type->reconstruct (),
-      size->clone_expr () /* FIXME: This should be `reconstruct_expr()` */,
-      locus);
+    return new ArrayType (elem_type->reconstruct (),
+                         size /* FIXME: This should be `reconstruct_expr()` */,
+                         locus);
   }
 };
 
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 8233af2b0a32..6d996ca60263 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -22,10 +22,13 @@
 /* DO NOT INCLUDE ANYWHERE - this is automatically included with rust-parse.h
  * This is also the reason why there are no include guards. */
 
+#include "expected.h"
+#include "rust-ast.h"
 #include "rust-common.h"
 #include "rust-expr.h"
 #include "rust-item.h"
 #include "rust-common.h"
+#include "rust-parse.h"
 #include "rust-token.h"
 #define INCLUDE_ALGORITHM
 #include "rust-diagnostics.h"
@@ -7272,6 +7275,27 @@ Parser<ManagedTokenSource>::parse_block_expr (
                        std::move (label), locus, end_locus));
 }
 
+/* Parse an anonymous const expression. This can be a regular const expression
+ * or an underscore for deferred const inference */
+template <typename ManagedTokenSource>
+tl::expected<AST::AnonConst, AnonConstError>
+Parser<ManagedTokenSource>::parse_anon_const ()
+{
+  auto current = lexer.peek_token ();
+  auto locus = current->get_locus ();
+
+  // Special case deferred inference constants
+  if (maybe_skip_token (UNDERSCORE))
+    return AST::AnonConst (locus);
+
+  auto expr = parse_expr ();
+
+  if (!expr)
+    return tl::make_unexpected (AnonConstError::InvalidSizeExpr);
+
+  return AST::AnonConst (std::move (expr), locus);
+}
+
 /* Parse a "const block", a block preceded by the `const` keyword whose
  * statements can be const evaluated and used in constant contexts */
 template <typename ManagedTokenSource>
@@ -9848,8 +9872,9 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type ()
        lexer.skip_token ();
 
        // parse required array size expression
-       std::unique_ptr<AST::Expr> size = parse_expr ();
-       if (size == nullptr)
+       auto size = parse_anon_const ();
+
+       if (!size)
          {
            Error error (lexer.peek_token ()->get_locus (),
                         "failed to parse size expression in array type");
@@ -9864,7 +9889,8 @@ Parser<ManagedTokenSource>::parse_slice_or_array_type ()
          }
 
        return std::unique_ptr<AST::ArrayType> (
-         new AST::ArrayType (std::move (inner_type), std::move (size), locus));
+         new AST::ArrayType (std::move (inner_type), std::move (*size),
+                             locus));
       }
     default:
       // error
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index 7983beb69bc2..63bbf8ebf0fb 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -34,11 +34,18 @@ class ParseLifetimeParamError
 class ParseLifetimeError
 {
 };
+
+enum class AnonConstError
+{
+  InvalidSizeExpr,
+};
+
 enum class ParseLoopLabelError
 {
   NOT_LOOP_LABEL,
   MISSING_COLON,
 };
+
 enum class ParseSelfError
 {
   SELF_PTR,
@@ -166,6 +173,8 @@ public:
                    tl::optional<AST::LoopLabel> = tl::nullopt,
                    location_t pratt_parsed_loc = UNKNOWN_LOCATION);
 
+  tl::expected<AST::AnonConst, AnonConstError> parse_anon_const ();
+
   std::unique_ptr<AST::ConstBlock>
   parse_const_block_expr (AST::AttrVec outer_attrs = AST::AttrVec (),
                          location_t loc = UNKNOWN_LOCATION);

Reply via email to