From: Owen Avery <[email protected]>

This should help detect issues like
https://github.com/Rust-GCC/gccrs/issues/3444.

gcc/rust/ChangeLog:

        * ast/rust-ast.h (Stmt::get_node_id): Make virtual.
        (Type::get_node_id): Likewise.
        (AssociatedItem::get_node_id): New virtual member function.
        * ast/rust-expr.h (TypeCastExpr::get_casted_expr_ptr): New
        member function.
        (TypeCastExpr::get_type_to_cast_to_ptr): Likewise.
        (ClosureExprInner::get_definition_expr_ptr): Likewise.
        * ast/rust-item.h (TypeAlias::get_node_id): New member function
        to override AssociatedItem::get_node_id.
        (ConstantItem::get_node_id): Likewise.
        * expand/rust-expand-visitor.cc
        (ExpandVisitor::maybe_expand_expr): Adjust
        macro_invoc_expect_id.
        (ExpandVisitor::maybe_expand_type): Likewise and add an overload
        for std::unique_ptr<TypeNoBounds>.
        (ExpandVisitor::visit): Check macro_invoc_expect_id and
        generally improve visitors so that the testsuite will still
        pass.
        * expand/rust-expand-visitor.h (ExpandVisitor::ExpandVisitor):
        Initialize member variable macro_invoc_expect_id.
        (ExpandVisitor::maybe_expand_type): Add an overload for
        std::unique_ptr<TypeNoBounds>.
        (ExpandVisitor::expand_macro_children): Adjust
        macro_invoc_expect_id.
        (ExpandVisitor::visit): Add an overload for TypeCastExpr.
        (ExpandVisitor::macro_invoc_expect_id): New member variable.

gcc/testsuite/ChangeLog:

        * rust/compile/macros/mbe/macro49.rs: Add missing lang items.

Signed-off-by: Owen Avery <[email protected]>
---
 gcc/rust/ast/rust-ast.h                       |  9 +++-
 gcc/rust/ast/rust-expr.h                      | 18 +++++++
 gcc/rust/ast/rust-item.h                      |  6 +++
 gcc/rust/expand/rust-expand-visitor.cc        | 47 ++++++++++++++++++-
 gcc/rust/expand/rust-expand-visitor.h         | 10 +++-
 .../rust/compile/macros/mbe/macro49.rs        | 11 +++++
 6 files changed, 96 insertions(+), 5 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 2d2c5d0b4d7..0feaf514105 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1137,7 +1137,9 @@ public:
 
   virtual void mark_for_strip () = 0;
   virtual bool is_marked_for_strip () const = 0;
-  NodeId get_node_id () const { return node_id; }
+
+  // TODO: put this in a virtual base class?
+  virtual NodeId get_node_id () const { return node_id; }
 
   virtual Kind get_stmt_kind () = 0;
 
@@ -1536,7 +1538,8 @@ public:
 
   virtual location_t get_locus () const = 0;
 
-  NodeId get_node_id () const { return node_id; }
+  // TODO: put this in a virtual base class?
+  virtual NodeId get_node_id () const { return node_id; }
   virtual Type *reconstruct_impl () const = 0;
 
 protected:
@@ -1799,6 +1802,8 @@ public:
   virtual bool is_marked_for_strip () const = 0;
 
   virtual location_t get_locus () const = 0;
+
+  virtual NodeId get_node_id () const = 0;
 };
 
 // Item used in trait declarations - abstract base class
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 03cad86de3d..8e5abe15219 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -865,6 +865,12 @@ public:
     return *main_or_left_expr;
   }
 
+  std::unique_ptr<Expr> &get_casted_expr_ptr ()
+  {
+    rust_assert (main_or_left_expr != nullptr);
+    return main_or_left_expr;
+  }
+
   // TODO: is this better? Or is a "vis_block" better?
   TypeNoBounds &get_type_to_cast_to ()
   {
@@ -872,6 +878,12 @@ public:
     return *type_to_convert_to;
   }
 
+  std::unique_ptr<TypeNoBounds> &get_type_to_cast_to_ptr ()
+  {
+    rust_assert (type_to_convert_to != nullptr);
+    return type_to_convert_to;
+  }
+
   Expr::Kind get_expr_kind () const override { return Expr::Kind::TypeCast; }
 
 protected:
@@ -2597,6 +2609,12 @@ public:
     return *closure_inner;
   }
 
+  std::unique_ptr<Expr> &get_definition_expr_ptr ()
+  {
+    rust_assert (closure_inner != nullptr);
+    return closure_inner;
+  }
+
 protected:
   /* Use covariance to implement clone function as returning this object rather
    * than base */
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index d11eed7687b..375f66ddcc1 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -1567,6 +1567,9 @@ public:
 
   location_t get_locus () const override final { return locus; }
 
+  // needed to override AssociatedItem::get_node_id
+  NodeId get_node_id () const override final { return VisItem::get_node_id (); 
}
+
   void accept_vis (ASTVisitor &vis) override;
 
   // Invalid if existing type is null, so base stripping on that.
@@ -2515,6 +2518,9 @@ public:
 
   location_t get_locus () const override final { return locus; }
 
+  // needed to override AssociatedItem::get_node_id
+  NodeId get_node_id () const override final { return VisItem::get_node_id (); 
}
+
   void accept_vis (ASTVisitor &vis) override;
 
   // Invalid if type or expression are null, so base stripping on that.
diff --git a/gcc/rust/expand/rust-expand-visitor.cc 
b/gcc/rust/expand/rust-expand-visitor.cc
index 8f6e7faa0c4..a53f0640109 100644
--- a/gcc/rust/expand/rust-expand-visitor.cc
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -329,10 +329,15 @@ ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr)
 void
 ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
 {
+  NodeId old_expect = expr->get_node_id ();
+  std::swap (macro_invoc_expect_id, old_expect);
+
   expander.push_context (MacroExpander::ContextType::EXPR);
   expr->accept_vis (*this);
   expander.pop_context ();
 
+  std::swap (macro_invoc_expect_id, old_expect);
+
   auto final_fragment = expander.take_expanded_fragment ();
   if (final_fragment.should_expand ()
       && final_fragment.is_expression_fragment ())
@@ -342,14 +347,37 @@ ExpandVisitor::maybe_expand_expr 
(std::unique_ptr<AST::Expr> &expr)
 void
 ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
 {
-  expander.push_context (MacroExpander::ContextType::TYPE);
+  NodeId old_expect = type->get_node_id ();
+  std::swap (macro_invoc_expect_id, old_expect);
 
+  expander.push_context (MacroExpander::ContextType::TYPE);
   type->accept_vis (*this);
+  expander.pop_context ();
+
+  std::swap (macro_invoc_expect_id, old_expect);
+
   auto final_fragment = expander.take_expanded_fragment ();
   if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
     type = final_fragment.take_type_fragment ();
+}
+
+// HACK: maybe we shouldn't have TypeNoBounds as a base class
+void
+ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type)
+{
+  NodeId old_expect = type->get_node_id ();
+  std::swap (macro_invoc_expect_id, old_expect);
 
+  expander.push_context (MacroExpander::ContextType::TYPE);
+  type->accept_vis (*this);
   expander.pop_context ();
+
+  std::swap (macro_invoc_expect_id, old_expect);
+
+  auto final_fragment = expander.take_expanded_fragment ();
+  if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
+    type = std::make_unique<AST::ParenthesisedType> (
+      final_fragment.take_type_fragment (), BUILTINS_LOCATION);
 }
 
 // FIXME: Can this be refactored into a `scoped` method? Which takes a
@@ -465,6 +493,14 @@ ExpandVisitor::visit (AST::ConstGenericParam &)
 void
 ExpandVisitor::visit (AST::MacroInvocation &macro_invoc)
 {
+  if (macro_invoc_expect_id != macro_invoc.get_node_id ())
+    {
+      rust_internal_error_at (
+       macro_invoc.get_locus (),
+       "attempting to expand node with id %d into position with node id %d",
+       (int) macro_invoc.get_node_id (), (int) macro_invoc_expect_id);
+    }
+
   // TODO: Can we do the AST fragment replacing here? Probably not, right?
   expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ()
                                        ? AST::InvocKind::Semicoloned
@@ -568,6 +604,13 @@ ExpandVisitor::visit (AST::LazyBooleanExpr &expr)
   maybe_expand_expr (expr.get_right_expr_ptr ());
 }
 
+void
+ExpandVisitor::visit (AST::TypeCastExpr &expr)
+{
+  maybe_expand_expr (expr.get_casted_expr_ptr ());
+  maybe_expand_type (expr.get_type_to_cast_to_ptr ());
+}
+
 void
 ExpandVisitor::visit (AST::AssignmentExpr &expr)
 {
@@ -615,7 +658,7 @@ ExpandVisitor::visit (AST::ClosureExprInner &expr)
 {
   expand_closure_params (expr.get_params ());
 
-  visit (expr.get_definition_expr ());
+  maybe_expand_expr (expr.get_definition_expr_ptr ());
 }
 
 void
diff --git a/gcc/rust/expand/rust-expand-visitor.h 
b/gcc/rust/expand/rust-expand-visitor.h
index 845e10cfec7..01a0d1cb297 100644
--- a/gcc/rust/expand/rust-expand-visitor.h
+++ b/gcc/rust/expand/rust-expand-visitor.h
@@ -38,7 +38,9 @@ bool is_builtin (AST::Attribute &attr);
 class ExpandVisitor : public AST::DefaultASTVisitor
 {
 public:
-  ExpandVisitor (MacroExpander &expander) : expander (expander) {}
+  ExpandVisitor (MacroExpander &expander)
+    : expander (expander), macro_invoc_expect_id (UNKNOWN_NODEID)
+  {}
 
   /* Expand all of the macro invocations currently contained in a crate */
   void go (AST::Crate &crate);
@@ -56,6 +58,7 @@ public:
      type : Core guidelines R33, this function reseat the pointer.
    */
   void maybe_expand_type (std::unique_ptr<AST::Type> &type);
+  void maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type);
 
   /**
    * Expand all macro invocations in lieu of types within a vector of struct
@@ -128,7 +131,10 @@ public:
        auto &value = *it;
 
        // Perform expansion
+       NodeId old_expect = value->get_node_id ();
+       std::swap (macro_invoc_expect_id, old_expect);
        value->accept_vis (*this);
+       std::swap (macro_invoc_expect_id, old_expect);
 
        auto final_fragment = expander.take_expanded_fragment ();
 
@@ -214,6 +220,7 @@ public:
   void visit (AST::ArithmeticOrLogicalExpr &expr) override;
   void visit (AST::ComparisonExpr &expr) override;
   void visit (AST::LazyBooleanExpr &expr) override;
+  void visit (AST::TypeCastExpr &expr) override;
   void visit (AST::AssignmentExpr &expr) override;
   void visit (AST::CompoundAssignmentExpr &expr) override;
   void visit (AST::GroupedExpr &expr) override;
@@ -287,6 +294,7 @@ public:
 
 private:
   MacroExpander &expander;
+  NodeId macro_invoc_expect_id;
 };
 
 } // namespace Rust
diff --git a/gcc/testsuite/rust/compile/macros/mbe/macro49.rs 
b/gcc/testsuite/rust/compile/macros/mbe/macro49.rs
index 0900f7cecdb..9d63ff1e627 100644
--- a/gcc/testsuite/rust/compile/macros/mbe/macro49.rs
+++ b/gcc/testsuite/rust/compile/macros/mbe/macro49.rs
@@ -1,3 +1,14 @@
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "fn_once"]
+trait FnOnce<Args> {
+    #[lang = "fn_once_output"]
+    type Output;
+
+    extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
+}
+
 macro_rules! closure {
     () => {{
         14 + 15
-- 
2.50.1

Reply via email to