Skip to content

Handle patterns in macro expansion #4076

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Aug 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 28 additions & 14 deletions gcc/rust/ast/rust-ast-fragment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -107,29 +107,42 @@ Fragment::should_expand () const
bool
Fragment::is_expression_fragment () const
{
return is_single_fragment_of_kind (SingleASTNode::NodeType::EXPRESSION);
return is_single_fragment_of_kind (SingleASTNode::Kind::Expr);
}

bool
Fragment::is_type_fragment () const
{
return is_single_fragment_of_kind (SingleASTNode::NodeType::TYPE);
return is_single_fragment_of_kind (SingleASTNode::Kind::Type);
}

bool
Fragment::is_pattern_fragment () const
{
return is_single_fragment_of_kind (SingleASTNode::Kind::Pattern);
}

std::unique_ptr<Expr>
Fragment::take_expression_fragment ()
{
assert_single_fragment (SingleASTNode::NodeType::EXPRESSION);
assert_single_fragment (SingleASTNode::Kind::Expr);
return nodes[0].take_expr ();
}

std::unique_ptr<Type>
Fragment::take_type_fragment ()
{
assert_single_fragment (SingleASTNode::NodeType::TYPE);
assert_single_fragment (SingleASTNode::Kind::Type);
return nodes[0].take_type ();
}

std::unique_ptr<Pattern>
Fragment::take_pattern_fragment ()
{
assert_single_fragment (SingleASTNode::Kind::Pattern);
return nodes[0].take_pattern ();
}

void
Fragment::accept_vis (ASTVisitor &vis)
{
Expand All @@ -144,21 +157,22 @@ Fragment::is_single_fragment () const
}

bool
Fragment::is_single_fragment_of_kind (SingleASTNode::NodeType expected) const
Fragment::is_single_fragment_of_kind (SingleASTNode::Kind expected) const
{
return is_single_fragment () && nodes[0].get_kind () == expected;
}

void
Fragment::assert_single_fragment (SingleASTNode::NodeType expected) const
{
static const std::map<SingleASTNode::NodeType, const char *> str_map = {
{SingleASTNode::NodeType::ASSOC_ITEM, "associated item"},
{SingleASTNode::NodeType::ITEM, "item"},
{SingleASTNode::NodeType::TYPE, "type"},
{SingleASTNode::NodeType::EXPRESSION, "expr"},
{SingleASTNode::NodeType::STMT, "stmt"},
{SingleASTNode::NodeType::EXTERN, "extern"},
Fragment::assert_single_fragment (SingleASTNode::Kind expected) const
{
static const std::map<SingleASTNode::Kind, const char *> str_map = {
{SingleASTNode::Kind::Assoc, "associated item"},
{SingleASTNode::Kind::Item, "item"},
{SingleASTNode::Kind::Type, "type"},
{SingleASTNode::Kind::Expr, "expr"},
{SingleASTNode::Kind::Stmt, "stmt"},
{SingleASTNode::Kind::Extern, "extern"},
{SingleASTNode::Kind::Pattern, "pattern"},
};

auto actual = nodes[0].get_kind ();
Expand Down
6 changes: 4 additions & 2 deletions gcc/rust/ast/rust-ast-fragment.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,11 @@ class Fragment

bool is_expression_fragment () const;
bool is_type_fragment () const;
bool is_pattern_fragment () const;

std::unique_ptr<Expr> take_expression_fragment ();
std::unique_ptr<Type> take_type_fragment ();
std::unique_ptr<Pattern> take_pattern_fragment ();

void accept_vis (ASTVisitor &vis);

Expand Down Expand Up @@ -119,8 +121,8 @@ class Fragment
* one Node will be extracted from the `nodes` vector
*/
bool is_single_fragment () const;
bool is_single_fragment_of_kind (SingleASTNode::NodeType expected) const;
void assert_single_fragment (SingleASTNode::NodeType expected) const;
bool is_single_fragment_of_kind (SingleASTNode::Kind expected) const;
void assert_single_fragment (SingleASTNode::Kind expected) const;
};

enum class InvocKind
Expand Down
76 changes: 46 additions & 30 deletions gcc/rust/ast/rust-ast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -48,29 +48,33 @@ SingleASTNode::SingleASTNode (SingleASTNode const &other)
kind = other.kind;
switch (kind)
{
case EXPRESSION:
case Kind::Expr:
expr = other.expr->clone_expr ();
break;

case ITEM:
case Kind::Item:
item = other.item->clone_item ();
break;

case STMT:
case Kind::Stmt:
stmt = other.stmt->clone_stmt ();
break;

case EXTERN:
case Kind::Extern:
external_item = other.external_item->clone_external_item ();
break;

case ASSOC_ITEM:
case Kind::Assoc:
assoc_item = other.assoc_item->clone_associated_item ();
break;

case TYPE:
case Kind::Type:
type = other.type->clone_type ();
break;

case Kind::Pattern:
pattern = other.pattern->clone_pattern ();
break;
}
}

Expand All @@ -80,29 +84,33 @@ SingleASTNode::operator= (SingleASTNode const &other)
kind = other.kind;
switch (kind)
{
case EXPRESSION:
case Kind::Expr:
expr = other.expr->clone_expr ();
break;

case ITEM:
case Kind::Item:
item = other.item->clone_item ();
break;

case STMT:
case Kind::Stmt:
stmt = other.stmt->clone_stmt ();
break;

case EXTERN:
case Kind::Extern:
external_item = other.external_item->clone_external_item ();
break;

case ASSOC_ITEM:
case Kind::Assoc:
assoc_item = other.assoc_item->clone_associated_item ();
break;

case TYPE:
case Kind::Type:
type = other.type->clone_type ();
break;

case Kind::Pattern:
pattern = other.pattern->clone_pattern ();
break;
}
return *this;
}
Expand All @@ -112,29 +120,33 @@ SingleASTNode::accept_vis (ASTVisitor &vis)
{
switch (kind)
{
case EXPRESSION:
case Kind::Expr:
expr->accept_vis (vis);
break;

case ITEM:
case Kind::Item:
item->accept_vis (vis);
break;

case STMT:
case Kind::Stmt:
stmt->accept_vis (vis);
break;

case EXTERN:
case Kind::Extern:
external_item->accept_vis (vis);
break;

case ASSOC_ITEM:
case Kind::Assoc:
assoc_item->accept_vis (vis);
break;

case TYPE:
case Kind::Type:
type->accept_vis (vis);
break;

case Kind::Pattern:
pattern->accept_vis (vis);
break;
}
}

Expand All @@ -143,18 +155,20 @@ SingleASTNode::is_error ()
{
switch (kind)
{
case EXPRESSION:
case Kind::Expr:
return expr == nullptr;
case ITEM:
case Kind::Item:
return item == nullptr;
case STMT:
case Kind::Stmt:
return stmt == nullptr;
case EXTERN:
case Kind::Extern:
return external_item == nullptr;
case ASSOC_ITEM:
case Kind::Assoc:
return assoc_item == nullptr;
case TYPE:
case Kind::Type:
return type == nullptr;
case Kind::Pattern:
return pattern == nullptr;
}

rust_unreachable ();
Expand All @@ -166,18 +180,20 @@ SingleASTNode::as_string () const
{
switch (kind)
{
case EXPRESSION:
case Kind::Expr:
return "Expr: " + expr->as_string ();
case ITEM:
case Kind::Item:
return "Item: " + item->as_string ();
case STMT:
case Kind::Stmt:
return "Stmt: " + stmt->as_string ();
case EXTERN:
case Kind::Extern:
return "External Item: " + external_item->as_string ();
case ASSOC_ITEM:
case Kind::Assoc:
return "Associated Item: " + assoc_item->as_string ();
case TYPE:
case Kind::Type:
return "Type: " + type->as_string ();
case Kind::Pattern:
return "Pattern: " + pattern->as_string ();
}

rust_unreachable ();
Expand Down
50 changes: 31 additions & 19 deletions gcc/rust/ast/rust-ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -1962,18 +1962,19 @@ struct MacroInvocData
class SingleASTNode : public Visitable
{
public:
enum NodeType
{
EXPRESSION,
ITEM,
STMT,
EXTERN,
ASSOC_ITEM,
TYPE,
enum class Kind
{
Expr,
Item,
Stmt,
Extern,
Assoc,
Type,
Pattern,
};

private:
NodeType kind;
Kind kind;

// FIXME make this a union
std::unique_ptr<Expr> expr;
Expand All @@ -1982,30 +1983,35 @@ class SingleASTNode : public Visitable
std::unique_ptr<ExternalItem> external_item;
std::unique_ptr<AssociatedItem> assoc_item;
std::unique_ptr<Type> type;
std::unique_ptr<Pattern> pattern;

public:
SingleASTNode (std::unique_ptr<Expr> expr)
: kind (EXPRESSION), expr (std::move (expr))
: kind (Kind::Expr), expr (std::move (expr))
{}

SingleASTNode (std::unique_ptr<Item> item)
: kind (ITEM), item (std::move (item))
: kind (Kind::Item), item (std::move (item))
{}

SingleASTNode (std::unique_ptr<Stmt> stmt)
: kind (STMT), stmt (std::move (stmt))
: kind (Kind::Stmt), stmt (std::move (stmt))
{}

SingleASTNode (std::unique_ptr<ExternalItem> item)
: kind (EXTERN), external_item (std::move (item))
: kind (Kind::Extern), external_item (std::move (item))
{}

SingleASTNode (std::unique_ptr<AssociatedItem> item)
: kind (ASSOC_ITEM), assoc_item (std::move (item))
: kind (Kind::Assoc), assoc_item (std::move (item))
{}

SingleASTNode (std::unique_ptr<Type> type)
: kind (TYPE), type (std::move (type))
: kind (Kind::Type), type (std::move (type))
{}

SingleASTNode (std::unique_ptr<Pattern> pattern)
: kind (Kind::Pattern), pattern (std::move (pattern))
{}

SingleASTNode (SingleASTNode const &other);
Expand All @@ -2015,23 +2021,23 @@ class SingleASTNode : public Visitable
SingleASTNode (SingleASTNode &&other) = default;
SingleASTNode &operator= (SingleASTNode &&other) = default;

NodeType get_kind () const { return kind; }
Kind get_kind () const { return kind; }

std::unique_ptr<Expr> &get_expr ()
{
rust_assert (kind == EXPRESSION);
rust_assert (kind == Kind::Expr);
return expr;
}

std::unique_ptr<Item> &get_item ()
{
rust_assert (kind == ITEM);
rust_assert (kind == Kind::Item);
return item;
}

std::unique_ptr<Stmt> &get_stmt ()
{
rust_assert (kind == STMT);
rust_assert (kind == Kind::Stmt);
return stmt;
}

Expand Down Expand Up @@ -2076,6 +2082,12 @@ class SingleASTNode : public Visitable
return std::move (type);
}

std::unique_ptr<Pattern> take_pattern ()
{
rust_assert (!is_error ());
return std::move (pattern);
}

void accept_vis (ASTVisitor &vis) override;

bool is_error ();
Expand Down
Loading
Loading