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);