From: Arthur Cohen <[email protected]>
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.
---
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 ca7b3e495d0..32d5d32e43f 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 3d230ce55c3..2b7ee5cb8bf 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 296821131b1..c875d6914b3 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 abbfd36a6f5..2a3496b11c6 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 8233af2b0a3..6d996ca6026 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 7983beb69bc..63bbf8ebf0f 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);
--
2.49.0