]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Refactor hir to avoid raw pointers and unneeded fwd
authorPierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
Tue, 15 Oct 2024 13:22:56 +0000 (15:22 +0200)
committerArthur Cohen <arthur.cohen@embecosm.com>
Fri, 21 Mar 2025 11:32:57 +0000 (12:32 +0100)
Refactor the hir tree files to remove raw pointer usage and most forward
declarations. Move implementation out of headers and split headers into
smaller and more manageable units.

gcc/rust/ChangeLog:

* Make-lang.in: Add new files.
* hir/tree/rust-hir-item.h: Move Item definition and remove
implementations to their corresponding cc file.
* hir/tree/rust-hir-expr.h: Move implementation to the corresponding
cc file.
* hir/tree/rust-hir-path.h: Likewise.
* hir/tree/rust-hir-pattern.h: Likewise.
* hir/tree/rust-hir-stmt.h: Likewise.
* hir/tree/rust-hir-type.h: Likewise.
* hir/tree/rust-hir-visitor.h: Likewise.
* hir/tree/rust-hir.h: Likewise.
* hir/tree/rust-hir.cc (Crate::Crate): Add implementations from Crate
and remove ConstGenericParam implementations to move them to their
own file.
* hir/tree/rust-hir-attrs.h: New file.
* hir/tree/rust-hir-bound-abstract.h: New file.
* hir/tree/rust-hir-bound.h: New file.
* hir/tree/rust-hir-expr-abstract.h: New file.
* hir/tree/rust-hir-expr.cc: New file.
* hir/tree/rust-hir-generic-param.cc: New file.
* hir/tree/rust-hir-generic-param.h: New file.
* hir/tree/rust-hir-item.cc: New file.
* hir/tree/rust-hir-literal.h: New file.
* hir/tree/rust-hir-node.h: New file.
* hir/tree/rust-hir-path.cc: New file.
* hir/tree/rust-hir-pattern-abstract.h: New file.
* hir/tree/rust-hir-simple-path.h: New file.
* hir/tree/rust-hir-stmt.cc: New file.
* hir/tree/rust-hir-trait-bound.h: New file.
* hir/tree/rust-hir-type-abstract.cc: New file.
* hir/tree/rust-hir-type-abstract.h: New file.
* hir/tree/rust-hir-type-no-bounds.h: New file.
* hir/tree/rust-hir-type.cc: New file.
* hir/tree/rust-hir-visibility.h: New file.
* hir/tree/rust-hir-visitable.h: New file.
* checks/lints/rust-lint-marklive.h: Use References.
* hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Reformat
vectors.
* hir/rust-hir-dump.cc (Dump::visit): Use reference.
* typecheck/rust-hir-type-check-struct.cc (TypeCheckStructExpr::resolve):
Use references.
* typecheck/rust-tyty-bounds.cc: Likewise.

Signed-off-by: Pierre-Emmanuel Patry <pierre-emmanuel.patry@embecosm.com>
36 files changed:
gcc/rust/Make-lang.in
gcc/rust/checks/lints/rust-lint-marklive.h
gcc/rust/hir/rust-ast-lower-expr.cc
gcc/rust/hir/rust-hir-dump.cc
gcc/rust/hir/tree/rust-hir-attrs.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-bound-abstract.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-bound.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-expr-abstract.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-expr.cc [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-expr.h
gcc/rust/hir/tree/rust-hir-generic-param.cc [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-generic-param.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-item.cc [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-item.h
gcc/rust/hir/tree/rust-hir-literal.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-node.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-path.cc [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-path.h
gcc/rust/hir/tree/rust-hir-pattern-abstract.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-pattern.h
gcc/rust/hir/tree/rust-hir-simple-path.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-stmt.cc [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-stmt.h
gcc/rust/hir/tree/rust-hir-trait-bound.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-type-abstract.cc [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-type-abstract.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-type-no-bounds.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-type.cc [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-type.h
gcc/rust/hir/tree/rust-hir-visibility.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-visitable.h [new file with mode: 0644]
gcc/rust/hir/tree/rust-hir-visitor.h
gcc/rust/hir/tree/rust-hir.cc
gcc/rust/hir/tree/rust-hir.h
gcc/rust/typecheck/rust-hir-type-check-struct.cc
gcc/rust/typecheck/rust-tyty-bounds.cc

index b1777e3996392b22997a7f54458c4a9718620829..9c5ec49ec4e440a0fe8fe90ae169fbee8829d87c 100644 (file)
@@ -178,6 +178,13 @@ GRS_OBJS = \
     rust/rust-polonius.o\
     rust/rust-hir-dot-operator.o \
     rust/rust-hir-path-probe.o \
+    rust/rust-hir-path.o \
+    rust/rust-hir-type.o \
+    rust/rust-hir-expr.o \
+    rust/rust-hir-type-abstract.o \
+    rust/rust-hir-item.o \
+    rust/rust-hir-stmt.o \
+    rust/rust-hir-generic-param.o \
     rust/rust-type-util.o \
     rust/rust-coercion.o \
     rust/rust-casts.o \
index 93a5be7ed1e88226c811381cb8ff812469bb52a6..86d96fc93673852a509c35862d1f5b471e5cd18d 100644 (file)
@@ -247,7 +247,7 @@ public:
     stct.get_struct_name ().accept_vis (*this);
     if (stct.has_struct_base ())
       {
-       stct.struct_base->base_struct->accept_vis (*this);
+       stct.get_struct_base ().get_base ().accept_vis (*this);
       }
   }
 
@@ -258,7 +258,7 @@ public:
 
   void visit (HIR::StructExprStructBase &stct) override
   {
-    stct.get_struct_base ()->base_struct->accept_vis (*this);
+    stct.get_struct_base ().get_base ().accept_vis (*this);
   }
 
   void visit (HIR::Module &module) override
index 9dd88b47b981305e1f855788e1d4cbfa351cfca3..2954a31d9f447fc89840f86a59fdd570f4b21e3e 100644 (file)
@@ -17,6 +17,7 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-ast-lower-expr.h"
+#include "optional.h"
 #include "rust-ast-lower-base.h"
 #include "rust-ast-lower-block.h"
 #include "rust-ast-lower-struct-field-expr.h"
@@ -77,7 +78,7 @@ ASTLoweringExpr::visit (AST::TupleIndexExpr &expr)
 void
 ASTLoweringExpr::visit (AST::TupleExpr &expr)
 {
-  std::vector<std::unique_ptr<HIR::Expr> > tuple_elements;
+  std::vector<std::unique_ptr<HIR::Expr>> tuple_elements;
   for (auto &e : expr.get_tuple_elems ())
     {
       HIR::Expr *t = ASTLoweringExpr::translate (*e);
@@ -174,7 +175,7 @@ ASTLoweringExpr::visit (AST::CallExpr &expr)
   HIR::Expr *func = ASTLoweringExpr::translate (expr.get_function_expr ());
 
   auto const &in_params = expr.get_params ();
-  std::vector<std::unique_ptr<HIR::Expr> > params;
+  std::vector<std::unique_ptr<HIR::Expr>> params;
   for (auto &param : in_params)
     {
       auto trans = ASTLoweringExpr::translate (*param);
@@ -200,7 +201,7 @@ ASTLoweringExpr::visit (AST::MethodCallExpr &expr)
   HIR::Expr *receiver = ASTLoweringExpr::translate (expr.get_receiver_expr ());
 
   auto const &in_params = expr.get_params ();
-  std::vector<std::unique_ptr<HIR::Expr> > params;
+  std::vector<std::unique_ptr<HIR::Expr>> params;
   for (auto &param : in_params)
     {
       auto trans = ASTLoweringExpr::translate (*param);
@@ -290,7 +291,7 @@ ASTLoweringExpr::visit (AST::ArrayIndexExpr &expr)
 void
 ASTLoweringExpr::visit (AST::ArrayElemsValues &elems)
 {
-  std::vector<std::unique_ptr<HIR::Expr> > elements;
+  std::vector<std::unique_ptr<HIR::Expr>> elements;
   for (auto &elem : elems.get_values ())
     {
       HIR::Expr *translated_elem = ASTLoweringExpr::translate (*elem);
@@ -511,16 +512,17 @@ ASTLoweringExpr::visit (AST::StructExprStructFields &struct_expr)
   HIR::PathInExpression copied_path (*path);
   delete path;
 
-  HIR::StructBase *base = nullptr;
+  tl::optional<std::unique_ptr<HIR::StructBase>> base = tl::nullopt;
   if (struct_expr.has_struct_base ())
     {
       HIR::Expr *translated_base = ASTLoweringExpr::translate (
        struct_expr.get_struct_base ().get_base_struct ());
-      base = new HIR::StructBase (std::unique_ptr<HIR::Expr> (translated_base));
+      base = tl::optional (Rust::make_unique<StructBase> (
+       std::unique_ptr<HIR::Expr> (translated_base)));
     }
 
   auto const &in_fields = struct_expr.get_fields ();
-  std::vector<std::unique_ptr<HIR::StructExprField> > fields;
+  std::vector<std::unique_ptr<HIR::StructExprField>> fields;
   for (auto &field : in_fields)
     {
       HIR::StructExprField *translated
@@ -535,7 +537,8 @@ ASTLoweringExpr::visit (AST::StructExprStructFields &struct_expr)
 
   translated
     = new HIR::StructExprStructFields (mapping, copied_path, std::move (fields),
-                                      struct_expr.get_locus (), base,
+                                      struct_expr.get_locus (),
+                                      std::move (base),
                                       struct_expr.get_inner_attrs (),
                                       struct_expr.get_outer_attrs ());
 }
index 65799e89f6ba3a2eb6eb8954fa82d16716c771cf..5d2a09db348392a82906aeb3bb1012f8d0b78b8b 100644 (file)
@@ -1171,7 +1171,7 @@ Dump::visit (StructExprStructFields &e)
   if (!e.has_struct_base ())
     put_field ("struct_base", "none");
   else
-    put_field ("struct_base", e.get_struct_base ()->as_string ());
+    put_field ("struct_base", e.get_struct_base ().as_string ());
 
   end ("StructExprStructFields");
 }
@@ -1182,7 +1182,7 @@ Dump::visit (StructExprStructBase &e)
   begin ("StructExprStructBase");
   do_structexprstruct (e);
 
-  put_field ("struct_base", e.get_struct_base ()->as_string ());
+  put_field ("struct_base", e.get_struct_base ().as_string ());
 
   end ("StructExprStructBase");
 }
diff --git a/gcc/rust/hir/tree/rust-hir-attrs.h b/gcc/rust/hir/tree/rust-hir-attrs.h
new file mode 100644 (file)
index 0000000..3e2b1d8
--- /dev/null
@@ -0,0 +1,56 @@
+
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_ATTRS_H
+#define RUST_HIR_ATTRS_H
+
+#include "rust-ast.h"
+
+namespace Rust {
+namespace HIR {
+
+class WithOuterAttrs
+{
+protected:
+  AST::AttrVec outer_attrs;
+
+public:
+  AST::AttrVec &get_outer_attrs () { return outer_attrs; }
+  const AST::AttrVec &get_outer_attrs () const { return outer_attrs; }
+
+  WithOuterAttrs (AST::AttrVec outer_attrs)
+    : outer_attrs (std::move (outer_attrs)){};
+};
+
+class WithInnerAttrs
+{
+protected:
+  AST::AttrVec inner_attrs;
+
+public:
+  AST::AttrVec get_inner_attrs () const { return inner_attrs; }
+
+  WithInnerAttrs (AST::AttrVec inner_attrs)
+    : inner_attrs (std::move (inner_attrs)){};
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-bound-abstract.h b/gcc/rust/hir/tree/rust-hir-bound-abstract.h
new file mode 100644 (file)
index 0000000..ffc915b
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_BOUND_ABSTRACT_H
+#define RUST_HIR_BOUND_ABSTRACT_H
+
+#include "rust-hir-visitable.h"
+#include "rust-system.h"
+#include "rust-hir-map.h"
+
+namespace Rust {
+namespace HIR {
+
+/* Abstract base class representing a type param bound - Lifetime and TraitBound
+ * extends it */
+class TypeParamBound : public FullVisitable
+{
+public:
+  using FullVisitable::accept_vis;
+  enum BoundType
+  {
+    LIFETIME,
+    TRAITBOUND
+  };
+
+  virtual ~TypeParamBound () {}
+
+  // Unique pointer custom clone function
+  std::unique_ptr<TypeParamBound> clone_type_param_bound () const
+  {
+    return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
+  }
+
+  virtual std::string as_string () const = 0;
+
+  virtual Analysis::NodeMapping get_mappings () const = 0;
+
+  virtual location_t get_locus () const = 0;
+
+  virtual BoundType get_bound_type () const = 0;
+
+protected:
+  // Clone function implementation as pure virtual method
+  virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-bound.h b/gcc/rust/hir/tree/rust-hir-bound.h
new file mode 100644 (file)
index 0000000..78bb133
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_BOUND_H
+#define RUST_HIR_BOUND_H
+
+#include "rust-hir-bound-abstract.h"
+#include "rust-common.h"
+#include "rust-hir-path.h"
+
+namespace Rust {
+namespace HIR {
+
+// Represents a lifetime (and is also a kind of type param bound)
+class Lifetime : public TypeParamBound
+{
+private:
+  AST::Lifetime::LifetimeType lifetime_type;
+  std::string lifetime_name;
+  location_t locus;
+  Analysis::NodeMapping mappings;
+
+public:
+  // Constructor
+  Lifetime (Analysis::NodeMapping mapping, AST::Lifetime::LifetimeType type,
+           std::string name, location_t locus)
+    : lifetime_type (type), lifetime_name (std::move (name)), locus (locus),
+      mappings (mapping)
+  {}
+
+  // Returns true if the lifetime is in an error state.
+  bool is_error () const
+  {
+    return lifetime_type == AST::Lifetime::LifetimeType::NAMED
+          && lifetime_name.empty ();
+  }
+
+  static Lifetime error ()
+  {
+    return Lifetime (Analysis::NodeMapping::get_error (),
+                    AST::Lifetime::LifetimeType::NAMED, "", UNDEF_LOCATION);
+  }
+
+  std::string as_string () const override;
+
+  void accept_vis (HIRFullVisitor &vis) override;
+
+  WARN_UNUSED_RESULT const std::string &get_name () const
+  {
+    return lifetime_name;
+  }
+
+  AST::Lifetime::LifetimeType get_lifetime_type () const
+  {
+    return lifetime_type;
+  }
+
+  location_t get_locus () const override final { return locus; }
+
+  Analysis::NodeMapping get_mappings () const override final
+  {
+    return mappings;
+  }
+
+  BoundType get_bound_type () const final override { return LIFETIME; }
+
+protected:
+  /* Use covariance to implement clone function as returning this object rather
+   * than base */
+  Lifetime *clone_type_param_bound_impl () const override
+  {
+    return new Lifetime (*this);
+  }
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-expr-abstract.h b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
new file mode 100644 (file)
index 0000000..ecf9bd1
--- /dev/null
@@ -0,0 +1,174 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_EXPR_ABSTRACT_H
+#define RUST_HIR_EXPR_ABSTRACT_H
+
+#include "rust-ast.h"
+#include "rust-hir-visitable.h"
+#include "rust-hir-node.h"
+
+namespace Rust {
+namespace HIR {
+
+// Base expression HIR node - abstract
+class Expr : public Node, virtual public FullVisitable
+{
+public:
+  using FullVisitable::accept_vis;
+
+protected:
+  AST::AttrVec outer_attrs;
+  Analysis::NodeMapping mappings;
+
+public:
+  enum BlockType
+  {
+    WITH_BLOCK,
+    WITHOUT_BLOCK,
+  };
+
+  enum ExprType
+  {
+    Lit,
+    Operator,
+    Grouped,
+    Array,
+    ArrayIndex,
+    Tuple,
+    TupleIdx,
+    Struct,
+    Call,
+    MethodCall,
+    FieldAccess,
+    Closure,
+    Block,
+    Continue,
+    Break,
+    Range,
+    Return,
+    UnsafeBlock,
+    BaseLoop,
+    If,
+    IfLet,
+    Match,
+    Await,
+    AsyncBlock,
+    Path,
+    InlineAsm,
+  };
+
+  BaseKind get_hir_kind () override final { return Node::BaseKind::EXPR; }
+
+  const AST::AttrVec &get_outer_attrs () const { return outer_attrs; }
+
+  // Unique pointer custom clone function
+  std::unique_ptr<Expr> clone_expr () const
+  {
+    return std::unique_ptr<Expr> (clone_expr_impl ());
+  }
+
+  // TODO: make pure virtual if move out outer attributes to derived classes
+  virtual std::string as_string () const;
+
+  virtual ~Expr () {}
+
+  virtual location_t get_locus () const = 0;
+
+  const Analysis::NodeMapping &get_mappings () const { return mappings; }
+
+  // Clone function implementation as pure virtual method
+  virtual Expr *clone_expr_impl () const = 0;
+
+  virtual BlockType get_block_expr_type () const = 0;
+
+  virtual ExprType get_expression_type () const = 0;
+
+  virtual void accept_vis (HIRExpressionVisitor &vis) = 0;
+
+protected:
+  // Constructor
+  Expr (Analysis::NodeMapping mappings,
+       AST::AttrVec outer_attribs = AST::AttrVec ());
+
+  // TODO: think of less hacky way to implement this kind of thing
+  // Sets outer attributes.
+  void set_outer_attrs (AST::AttrVec outer_attrs_to_set)
+  {
+    outer_attrs = std::move (outer_attrs_to_set);
+  }
+};
+
+// HIR node for an expression without an accompanying block - abstract
+class ExprWithoutBlock : public Expr
+{
+protected:
+  // Constructor
+  ExprWithoutBlock (Analysis::NodeMapping mappings,
+                   AST::AttrVec outer_attribs = AST::AttrVec ());
+
+  // pure virtual clone implementation
+  virtual ExprWithoutBlock *clone_expr_without_block_impl () const = 0;
+
+  /* Save having to specify two clone methods in derived classes by making expr
+   * clone return exprwithoutblock clone. Hopefully won't affect performance too
+   * much. */
+  ExprWithoutBlock *clone_expr_impl () const override
+  {
+    return clone_expr_without_block_impl ();
+  }
+
+public:
+  // Unique pointer custom clone function
+  std::unique_ptr<ExprWithoutBlock> clone_expr_without_block () const
+  {
+    return std::unique_ptr<ExprWithoutBlock> (clone_expr_without_block_impl ());
+  }
+
+  BlockType get_block_expr_type () const final override
+  {
+    return BlockType::WITHOUT_BLOCK;
+  };
+};
+
+// Base path expression HIR node - abstract
+class PathExpr : public ExprWithoutBlock
+{
+protected:
+  PathExpr (Analysis::NodeMapping mappings, AST::AttrVec outer_attribs)
+    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs))
+  {}
+
+public:
+  /* Replaces the outer attributes of this path expression with the given outer
+   * attributes. */
+  void replace_outer_attrs (AST::AttrVec outer_attrs)
+  {
+    set_outer_attrs (std::move (outer_attrs));
+  }
+
+  ExprType get_expression_type () const final override
+  {
+    return ExprType::Path;
+  }
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc b/gcc/rust/hir/tree/rust-hir-expr.cc
new file mode 100644 (file)
index 0000000..6c9a7a4
--- /dev/null
@@ -0,0 +1,1478 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-expr.h"
+#include "rust-operators.h"
+#include "rust-hir-stmt.h"
+
+namespace Rust {
+namespace HIR {
+
+Expr::Expr (Analysis::NodeMapping mappings, AST::AttrVec outer_attribs)
+  : outer_attrs (std::move (outer_attribs)), mappings (std::move (mappings))
+{}
+
+ExprWithoutBlock::ExprWithoutBlock (Analysis::NodeMapping mappings,
+                                   AST::AttrVec outer_attribs)
+  : Expr (std::move (mappings), std::move (outer_attribs))
+{}
+
+LoopLabel::LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label,
+                     location_t locus)
+  : label (std::move (loop_label)), locus (locus), mappings (mapping)
+{}
+
+ExprWithBlock::ExprWithBlock (Analysis::NodeMapping mappings,
+                             AST::AttrVec outer_attrs)
+  : Expr (std::move (mappings), std::move (outer_attrs))
+{}
+
+LiteralExpr::LiteralExpr (Analysis::NodeMapping mappings,
+                         std::string value_as_string, Literal::LitType type,
+                         PrimitiveCoreType type_hint, location_t locus,
+                         AST::AttrVec outer_attrs)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)),
+    literal (std::move (value_as_string), type, type_hint), locus (locus)
+{}
+
+LiteralExpr::LiteralExpr (Analysis::NodeMapping mappings, Literal literal,
+                         location_t locus, AST::AttrVec outer_attrs)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)),
+    literal (std::move (literal)), locus (locus)
+{}
+
+OperatorExpr::OperatorExpr (Analysis::NodeMapping mappings,
+                           std::unique_ptr<Expr> main_or_left_expr,
+                           AST::AttrVec outer_attribs, location_t locus)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    locus (locus), main_or_left_expr (std::move (main_or_left_expr))
+{}
+
+OperatorExpr::OperatorExpr (OperatorExpr const &other)
+  : ExprWithoutBlock (other), locus (other.locus),
+    main_or_left_expr (other.main_or_left_expr->clone_expr ())
+{}
+
+OperatorExpr &
+OperatorExpr::operator= (OperatorExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  main_or_left_expr = other.main_or_left_expr->clone_expr ();
+  locus = other.locus;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+BorrowExpr::BorrowExpr (Analysis::NodeMapping mappings,
+                       std::unique_ptr<Expr> borrow_lvalue, Mutability mut,
+                       AST::AttrVec outer_attribs, location_t locus)
+  : OperatorExpr (std::move (mappings), std::move (borrow_lvalue),
+                 std::move (outer_attribs), locus),
+    mut (mut)
+{}
+
+DereferenceExpr::DereferenceExpr (Analysis::NodeMapping mappings,
+                                 std::unique_ptr<Expr> deref_lvalue,
+                                 AST::AttrVec outer_attribs, location_t locus)
+  : OperatorExpr (std::move (mappings), std::move (deref_lvalue),
+                 std::move (outer_attribs), locus)
+{}
+
+ErrorPropagationExpr::ErrorPropagationExpr (
+  Analysis::NodeMapping mappings, std::unique_ptr<Expr> potential_error_value,
+  AST::AttrVec outer_attribs, location_t locus)
+  : OperatorExpr (std::move (mappings), std::move (potential_error_value),
+                 std::move (outer_attribs), locus)
+{}
+
+NegationExpr::NegationExpr (Analysis::NodeMapping mappings,
+                           std::unique_ptr<Expr> negated_value,
+                           ExprType expr_kind, AST::AttrVec outer_attribs,
+                           location_t locus)
+  : OperatorExpr (std::move (mappings), std::move (negated_value),
+                 std::move (outer_attribs), locus),
+    expr_type (expr_kind)
+{}
+
+ArithmeticOrLogicalExpr::ArithmeticOrLogicalExpr (
+  Analysis::NodeMapping mappings, std::unique_ptr<Expr> left_value,
+  std::unique_ptr<Expr> right_value, ExprType expr_kind, location_t locus)
+  : OperatorExpr (std::move (mappings), std::move (left_value), AST::AttrVec (),
+                 locus),
+    expr_type (expr_kind), right_expr (std::move (right_value))
+{}
+
+ArithmeticOrLogicalExpr::ArithmeticOrLogicalExpr (
+  ArithmeticOrLogicalExpr const &other)
+  : OperatorExpr (other), expr_type (other.expr_type),
+    right_expr (other.right_expr->clone_expr ())
+{}
+
+ArithmeticOrLogicalExpr &
+ArithmeticOrLogicalExpr::operator= (ArithmeticOrLogicalExpr const &other)
+{
+  OperatorExpr::operator= (other);
+  // main_or_left_expr = other.main_or_left_expr->clone_expr();
+  right_expr = other.right_expr->clone_expr ();
+  expr_type = other.expr_type;
+
+  return *this;
+}
+
+ComparisonExpr::ComparisonExpr (Analysis::NodeMapping mappings,
+                               std::unique_ptr<Expr> left_value,
+                               std::unique_ptr<Expr> right_value,
+                               ExprType comparison_kind, location_t locus)
+  : OperatorExpr (std::move (mappings), std::move (left_value), AST::AttrVec (),
+                 locus),
+    expr_type (comparison_kind), right_expr (std::move (right_value))
+{}
+
+ComparisonExpr::ComparisonExpr (ComparisonExpr const &other)
+  : OperatorExpr (other), expr_type (other.expr_type),
+    right_expr (other.right_expr->clone_expr ())
+{}
+
+ComparisonExpr &
+ComparisonExpr::operator= (ComparisonExpr const &other)
+{
+  OperatorExpr::operator= (other);
+  // main_or_left_expr = other.main_or_left_expr->clone_expr();
+  right_expr = other.right_expr->clone_expr ();
+  expr_type = other.expr_type;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+LazyBooleanExpr::LazyBooleanExpr (Analysis::NodeMapping mappings,
+                                 std::unique_ptr<Expr> left_bool_expr,
+                                 std::unique_ptr<Expr> right_bool_expr,
+                                 ExprType expr_kind, location_t locus)
+  : OperatorExpr (std::move (mappings), std::move (left_bool_expr),
+                 AST::AttrVec (), locus),
+    expr_type (expr_kind), right_expr (std::move (right_bool_expr))
+{}
+
+LazyBooleanExpr::LazyBooleanExpr (LazyBooleanExpr const &other)
+  : OperatorExpr (other), expr_type (other.expr_type),
+    right_expr (other.right_expr->clone_expr ())
+{}
+
+LazyBooleanExpr &
+LazyBooleanExpr::operator= (LazyBooleanExpr const &other)
+{
+  OperatorExpr::operator= (other);
+  // main_or_left_expr = other.main_or_left_expr->clone_expr();
+  right_expr = other.right_expr->clone_expr ();
+  expr_type = other.expr_type;
+
+  return *this;
+}
+
+TypeCastExpr::TypeCastExpr (Analysis::NodeMapping mappings,
+                           std::unique_ptr<Expr> expr_to_cast,
+                           std::unique_ptr<Type> type_to_cast_to,
+                           location_t locus)
+  : OperatorExpr (std::move (mappings), std::move (expr_to_cast),
+                 AST::AttrVec (), locus),
+    type_to_convert_to (std::move (type_to_cast_to))
+{}
+
+TypeCastExpr::TypeCastExpr (TypeCastExpr const &other)
+  : OperatorExpr (other),
+    type_to_convert_to (other.type_to_convert_to->clone_type ())
+{}
+
+TypeCastExpr &
+TypeCastExpr::operator= (TypeCastExpr const &other)
+{
+  OperatorExpr::operator= (other);
+  // main_or_left_expr = other.main_or_left_expr->clone_expr();
+  type_to_convert_to = other.type_to_convert_to->clone_type ();
+
+  return *this;
+}
+
+AssignmentExpr::AssignmentExpr (Analysis::NodeMapping mappings,
+                               std::unique_ptr<Expr> value_to_assign_to,
+                               std::unique_ptr<Expr> value_to_assign,
+                               location_t locus)
+  : OperatorExpr (std::move (mappings), std::move (value_to_assign_to),
+                 AST::AttrVec (), locus),
+    right_expr (std::move (value_to_assign))
+{}
+
+AssignmentExpr::AssignmentExpr (AssignmentExpr const &other)
+  : OperatorExpr (other), right_expr (other.right_expr->clone_expr ())
+{}
+
+AssignmentExpr &
+AssignmentExpr::operator= (AssignmentExpr const &other)
+{
+  OperatorExpr::operator= (other);
+  // main_or_left_expr = other.main_or_left_expr->clone_expr();
+  right_expr = other.right_expr->clone_expr ();
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+CompoundAssignmentExpr::CompoundAssignmentExpr (
+  Analysis::NodeMapping mappings, std::unique_ptr<Expr> value_to_assign_to,
+  std::unique_ptr<Expr> value_to_assign, ExprType expr_kind, location_t locus)
+  : OperatorExpr (std::move (mappings), std::move (value_to_assign_to),
+                 AST::AttrVec (), locus),
+    expr_type (expr_kind), right_expr (std::move (value_to_assign))
+{}
+
+CompoundAssignmentExpr::CompoundAssignmentExpr (
+  CompoundAssignmentExpr const &other)
+  : OperatorExpr (other), expr_type (other.expr_type),
+    right_expr (other.right_expr->clone_expr ())
+{}
+
+CompoundAssignmentExpr &
+CompoundAssignmentExpr::operator= (CompoundAssignmentExpr const &other)
+{
+  OperatorExpr::operator= (other);
+  // main_or_left_expr = other.main_or_left_expr->clone_expr();
+  right_expr = other.right_expr->clone_expr ();
+  expr_type = other.expr_type;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+GroupedExpr::GroupedExpr (Analysis::NodeMapping mappings,
+                         std::unique_ptr<Expr> parenthesised_expr,
+                         AST::AttrVec inner_attribs,
+                         AST::AttrVec outer_attribs, location_t locus)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    WithInnerAttrs (std::move (inner_attribs)),
+    expr_in_parens (std::move (parenthesised_expr)), locus (locus)
+{}
+
+GroupedExpr::GroupedExpr (GroupedExpr const &other)
+  : ExprWithoutBlock (other), WithInnerAttrs (other.inner_attrs),
+    expr_in_parens (other.expr_in_parens->clone_expr ()), locus (other.locus)
+{}
+
+GroupedExpr &
+GroupedExpr::operator= (GroupedExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  inner_attrs = other.inner_attrs;
+  expr_in_parens = other.expr_in_parens->clone_expr ();
+  locus = other.locus;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+ArrayElemsValues::ArrayElemsValues (Analysis::NodeMapping mappings,
+                                   std::vector<std::unique_ptr<Expr>> elems)
+  : ArrayElems (mappings), values (std::move (elems))
+{}
+
+ArrayElemsValues::ArrayElemsValues (ArrayElemsValues const &other)
+  : ArrayElems (other)
+{
+  values.reserve (other.values.size ());
+  for (const auto &e : other.values)
+    values.push_back (e->clone_expr ());
+}
+
+ArrayElemsValues &
+ArrayElemsValues::operator= (ArrayElemsValues const &other)
+{
+  values.reserve (other.values.size ());
+  for (const auto &e : other.values)
+    values.push_back (e->clone_expr ());
+
+  return *this;
+}
+
+ArrayElemsCopied::ArrayElemsCopied (Analysis::NodeMapping mappings,
+                                   std::unique_ptr<Expr> copied_elem,
+                                   std::unique_ptr<Expr> copy_amount)
+  : ArrayElems (mappings), elem_to_copy (std::move (copied_elem)),
+    num_copies (std::move (copy_amount))
+{}
+
+ArrayElemsCopied::ArrayElemsCopied (ArrayElemsCopied const &other)
+  : ArrayElems (other), elem_to_copy (other.elem_to_copy->clone_expr ()),
+    num_copies (other.num_copies->clone_expr ())
+{}
+
+ArrayElemsCopied &
+ArrayElemsCopied::operator= (ArrayElemsCopied const &other)
+{
+  elem_to_copy = other.elem_to_copy->clone_expr ();
+  num_copies = other.num_copies->clone_expr ();
+
+  return *this;
+}
+
+ArrayExpr::ArrayExpr (Analysis::NodeMapping mappings,
+                     std::unique_ptr<ArrayElems> array_elems,
+                     AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
+                     location_t locus)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    WithInnerAttrs (std::move (inner_attribs)),
+    internal_elements (std::move (array_elems)), locus (locus)
+{}
+
+ArrayExpr::ArrayExpr (ArrayExpr const &other)
+  : ExprWithoutBlock (other), WithInnerAttrs (other.inner_attrs),
+    locus (other.locus)
+{
+  if (other.has_array_elems ())
+    internal_elements = other.internal_elements->clone_array_elems ();
+}
+
+ArrayExpr &
+ArrayExpr::operator= (ArrayExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  inner_attrs = other.inner_attrs;
+  if (other.has_array_elems ())
+    internal_elements = other.internal_elements->clone_array_elems ();
+  locus = other.locus;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+ArrayIndexExpr::ArrayIndexExpr (Analysis::NodeMapping mappings,
+                               std::unique_ptr<Expr> array_expr,
+                               std::unique_ptr<Expr> array_index_expr,
+                               AST::AttrVec outer_attribs, location_t locus)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    array_expr (std::move (array_expr)),
+    index_expr (std::move (array_index_expr)), locus (locus)
+{}
+
+ArrayIndexExpr::ArrayIndexExpr (ArrayIndexExpr const &other)
+  : ExprWithoutBlock (other), array_expr (other.array_expr->clone_expr ()),
+    index_expr (other.index_expr->clone_expr ()), locus (other.locus)
+{}
+
+ArrayIndexExpr &
+ArrayIndexExpr::operator= (ArrayIndexExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  array_expr = other.array_expr->clone_expr ();
+  index_expr = other.index_expr->clone_expr ();
+  // outer_attrs = other.outer_attrs;
+  locus = other.locus;
+
+  return *this;
+}
+
+TupleExpr::TupleExpr (Analysis::NodeMapping mappings,
+                     std::vector<std::unique_ptr<Expr>> tuple_elements,
+                     AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
+                     location_t locus)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    WithInnerAttrs (std::move (inner_attribs)),
+    tuple_elems (std::move (tuple_elements)), locus (locus)
+{}
+
+TupleExpr::TupleExpr (TupleExpr const &other)
+  : ExprWithoutBlock (other), WithInnerAttrs (other.inner_attrs),
+    locus (other.locus)
+{
+  tuple_elems.reserve (other.tuple_elems.size ());
+  for (const auto &e : other.tuple_elems)
+    tuple_elems.push_back (e->clone_expr ());
+}
+
+TupleExpr &
+TupleExpr::operator= (TupleExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  inner_attrs = other.inner_attrs;
+  locus = other.locus;
+
+  tuple_elems.reserve (other.tuple_elems.size ());
+  for (const auto &e : other.tuple_elems)
+    tuple_elems.push_back (e->clone_expr ());
+
+  return *this;
+}
+
+TupleIndexExpr::TupleIndexExpr (Analysis::NodeMapping mappings,
+                               std::unique_ptr<Expr> tuple_expr,
+                               TupleIndex index, AST::AttrVec outer_attribs,
+                               location_t locus)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    tuple_expr (std::move (tuple_expr)), tuple_index (index), locus (locus)
+{}
+
+TupleIndexExpr::TupleIndexExpr (TupleIndexExpr const &other)
+  : ExprWithoutBlock (other), tuple_expr (other.tuple_expr->clone_expr ()),
+    tuple_index (other.tuple_index), locus (other.locus)
+{}
+
+TupleIndexExpr &
+TupleIndexExpr::operator= (TupleIndexExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  tuple_expr = other.tuple_expr->clone_expr ();
+  tuple_index = other.tuple_index;
+  locus = other.locus;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+StructExpr::StructExpr (Analysis::NodeMapping mappings,
+                       PathInExpression struct_path,
+                       AST::AttrVec outer_attribs)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    struct_name (std::move (struct_path))
+{}
+
+StructExprStruct::StructExprStruct (Analysis::NodeMapping mappings,
+                                   PathInExpression struct_path,
+                                   AST::AttrVec inner_attribs,
+                                   AST::AttrVec outer_attribs,
+                                   location_t locus)
+  : StructExpr (std::move (mappings), std::move (struct_path),
+               std::move (outer_attribs)),
+    WithInnerAttrs (std::move (inner_attribs)), locus (locus)
+{}
+
+StructBase::StructBase (std::unique_ptr<Expr> base_struct_ptr)
+  : base_struct (std::move (base_struct_ptr))
+{}
+
+StructBase::StructBase (StructBase const &other)
+{
+  /* HACK: gets around base_struct pointer being null (e.g. if no struct base
+   * exists) */
+  if (other.base_struct != nullptr)
+    other.base_struct->clone_expr ();
+}
+
+StructBase &
+StructBase::operator= (StructBase const &other)
+{
+  base_struct = other.base_struct->clone_expr ();
+
+  return *this;
+}
+
+StructExprField::StructExprField (Analysis::NodeMapping mapping,
+                                 location_t locus)
+  : mappings (mapping), locus (locus)
+{}
+
+StructExprFieldIdentifier::StructExprFieldIdentifier (
+  Analysis::NodeMapping mapping, Identifier field_identifier, location_t locus)
+  : StructExprField (mapping, locus), field_name (std::move (field_identifier))
+{}
+
+StructExprFieldWithVal::StructExprFieldWithVal (
+  Analysis::NodeMapping mapping, std::unique_ptr<Expr> field_value,
+  location_t locus)
+  : StructExprField (mapping, locus), value (std::move (field_value))
+{}
+
+StructExprFieldWithVal::StructExprFieldWithVal (
+  StructExprFieldWithVal const &other)
+  : StructExprField (other.mappings, other.locus),
+    value (other.value->clone_expr ())
+{}
+
+StructExprFieldWithVal &
+StructExprFieldWithVal::operator= (StructExprFieldWithVal const &other)
+{
+  value = other.value->clone_expr ();
+  mappings = other.mappings;
+  locus = other.locus;
+
+  return *this;
+}
+
+StructExprFieldIdentifierValue::StructExprFieldIdentifierValue (
+  Analysis::NodeMapping mapping, Identifier field_identifier,
+  std::unique_ptr<Expr> field_value, location_t locus)
+  : StructExprFieldWithVal (mapping, std::move (field_value), locus),
+    field_name (std::move (field_identifier))
+{}
+
+StructExprFieldIndexValue::StructExprFieldIndexValue (
+  Analysis::NodeMapping mapping, TupleIndex tuple_index,
+  std::unique_ptr<Expr> field_value, location_t locus)
+  : StructExprFieldWithVal (mapping, std::move (field_value), locus),
+    index (tuple_index)
+{}
+
+StructExprStructFields::StructExprStructFields (
+  Analysis::NodeMapping mappings, PathInExpression struct_path,
+  std::vector<std::unique_ptr<StructExprField>> expr_fields, location_t locus,
+  tl::optional<std::unique_ptr<StructBase>> base_struct,
+  AST::AttrVec inner_attribs = AST::AttrVec (),
+  AST::AttrVec outer_attribs = AST::AttrVec ())
+  : StructExprStruct (std::move (mappings), std::move (struct_path),
+                     std::move (inner_attribs), std::move (outer_attribs),
+                     locus),
+    fields (std::move (expr_fields)), struct_base (std::move (base_struct))
+{}
+
+StructExprStructFields::StructExprStructFields (
+  StructExprStructFields const &other)
+  : StructExprStruct (other),
+    struct_base (
+      other.has_struct_base () ? tl::optional<std::unique_ptr<StructBase>> (
+       Rust::make_unique<StructBase> (*other.struct_base.value ()))
+                              : tl::nullopt),
+    union_index (other.union_index)
+{
+  fields.reserve (other.fields.size ());
+  for (const auto &e : other.fields)
+    fields.push_back (e->clone_struct_expr_field ());
+}
+
+StructExprStructFields &
+StructExprStructFields::operator= (StructExprStructFields const &other)
+{
+  StructExprStruct::operator= (other);
+  struct_base = other.has_struct_base ()
+                 ? tl::optional<std::unique_ptr<StructBase>> (
+                   Rust::make_unique<StructBase> (*other.struct_base.value ()))
+                 : tl::nullopt;
+  union_index = other.union_index;
+
+  fields.reserve (other.fields.size ());
+  for (const auto &e : other.fields)
+    fields.push_back (e->clone_struct_expr_field ());
+
+  return *this;
+}
+
+StructExprStructBase::StructExprStructBase (Analysis::NodeMapping mappings,
+                                           PathInExpression struct_path,
+                                           StructBase base_struct,
+                                           AST::AttrVec inner_attribs,
+                                           AST::AttrVec outer_attribs,
+                                           location_t locus)
+  : StructExprStruct (std::move (mappings), std::move (struct_path),
+                     std::move (inner_attribs), std::move (outer_attribs),
+                     locus),
+    struct_base (std::move (base_struct))
+{}
+
+CallExpr::CallExpr (Analysis::NodeMapping mappings,
+                   std::unique_ptr<Expr> function_expr,
+                   std::vector<std::unique_ptr<Expr>> function_params,
+                   AST::AttrVec outer_attribs, location_t locus)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    function (std::move (function_expr)), params (std::move (function_params)),
+    locus (locus)
+{}
+
+CallExpr::CallExpr (CallExpr const &other)
+  : ExprWithoutBlock (other), function (other.function->clone_expr ()),
+    locus (other.locus)
+/*, params(other.params),*/ {
+  params.reserve (other.params.size ());
+  for (const auto &e : other.params)
+    params.push_back (e->clone_expr ());
+}
+
+CallExpr &
+CallExpr::operator= (CallExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  function = other.function->clone_expr ();
+  locus = other.locus;
+  // params = other.params;
+  // outer_attrs = other.outer_attrs;
+
+  params.reserve (other.params.size ());
+  for (const auto &e : other.params)
+    params.push_back (e->clone_expr ());
+
+  return *this;
+}
+
+MethodCallExpr::MethodCallExpr (
+  Analysis::NodeMapping mappings, std::unique_ptr<Expr> call_receiver,
+  PathExprSegment method_path, std::vector<std::unique_ptr<Expr>> method_params,
+  AST::AttrVec outer_attribs, location_t locus)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    receiver (std::move (call_receiver)), method_name (std::move (method_path)),
+    params (std::move (method_params)), locus (locus)
+{}
+
+MethodCallExpr::MethodCallExpr (MethodCallExpr const &other)
+  : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()),
+    method_name (other.method_name), locus (other.locus)
+/*, params(other.params),*/ {
+  params.reserve (other.params.size ());
+  for (const auto &e : other.params)
+    params.push_back (e->clone_expr ());
+}
+
+MethodCallExpr &
+MethodCallExpr::operator= (MethodCallExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  receiver = other.receiver->clone_expr ();
+  method_name = other.method_name;
+  locus = other.locus;
+  // params = other.params;
+  // outer_attrs = other.outer_attrs;
+
+  params.reserve (other.params.size ());
+  for (const auto &e : other.params)
+    params.push_back (e->clone_expr ());
+
+  return *this;
+}
+
+FieldAccessExpr::FieldAccessExpr (Analysis::NodeMapping mappings,
+                                 std::unique_ptr<Expr> field_access_receiver,
+                                 Identifier field_name,
+                                 AST::AttrVec outer_attribs, location_t locus)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    receiver (std::move (field_access_receiver)),
+    field (std::move (field_name)), locus (locus)
+{}
+
+FieldAccessExpr::FieldAccessExpr (FieldAccessExpr const &other)
+  : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()),
+    field (other.field), locus (other.locus)
+{}
+
+FieldAccessExpr &
+FieldAccessExpr::operator= (FieldAccessExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  receiver = other.receiver->clone_expr ();
+  field = other.field;
+  locus = other.locus;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+ClosureParam::ClosureParam (std::unique_ptr<Pattern> param_pattern,
+                           location_t locus, std::unique_ptr<Type> param_type,
+                           std::vector<AST::Attribute> outer_attrs)
+  : outer_attrs (std::move (outer_attrs)), pattern (std::move (param_pattern)),
+    type (std::move (param_type)), locus (locus)
+{}
+
+ClosureParam::ClosureParam (ClosureParam const &other)
+  : pattern (other.pattern->clone_pattern ())
+{
+  // guard to protect from null pointer dereference
+  if (other.pattern != nullptr)
+    pattern = other.pattern->clone_pattern ();
+  if (other.type != nullptr)
+    type = other.type->clone_type ();
+}
+
+ClosureParam &
+ClosureParam::operator= (ClosureParam const &other)
+{
+  outer_attrs = other.outer_attrs;
+
+  // guard to protect from null pointer dereference
+  if (other.pattern != nullptr)
+    pattern = other.pattern->clone_pattern ();
+  else
+    pattern = nullptr;
+  if (other.type != nullptr)
+    type = other.type->clone_type ();
+  else
+    type = nullptr;
+
+  return *this;
+}
+
+ClosureExpr::ClosureExpr (Analysis::NodeMapping mappings,
+                         std::vector<ClosureParam> closure_params,
+                         std::unique_ptr<Type> closure_return_type,
+                         std::unique_ptr<Expr> closure_expr, bool has_move,
+                         AST::AttrVec outer_attribs, location_t locus)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    has_move (has_move), params (std::move (closure_params)), locus (locus),
+    return_type (std::move (closure_return_type)),
+    expr (std::move (closure_expr))
+{}
+
+ClosureExpr::ClosureExpr (ClosureExpr const &other)
+  : ExprWithoutBlock (other.get_mappings (), other.get_outer_attrs ())
+{
+  return_type
+    = other.has_return_type () ? other.return_type->clone_type () : nullptr;
+  expr = other.expr->clone_expr ();
+  params = other.params;
+  has_move = other.has_move;
+}
+
+ClosureExpr &
+ClosureExpr::operator= (ClosureExpr const &other)
+{
+  mappings = other.mappings;
+  return_type
+    = other.has_return_type () ? other.return_type->clone_type () : nullptr;
+  expr = other.expr->clone_expr ();
+  params = other.params;
+  has_move = other.has_move;
+
+  return *this;
+}
+
+BlockExpr::BlockExpr (Analysis::NodeMapping mappings,
+                     std::vector<std::unique_ptr<Stmt>> block_statements,
+                     std::unique_ptr<Expr> block_expr, bool tail_reachable,
+                     AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
+                     LoopLabel label, location_t start_locus,
+                     location_t end_locus)
+  : ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
+    WithInnerAttrs (std::move (inner_attribs)),
+    statements (std::move (block_statements)), expr (std::move (block_expr)),
+    tail_reachable (tail_reachable), label (std::move (label)),
+    start_locus (start_locus), end_locus (end_locus)
+{}
+
+BlockExpr::BlockExpr (BlockExpr const &other)
+  : ExprWithBlock (other), /*statements(other.statements),*/
+    WithInnerAttrs (other.inner_attrs), label (other.label),
+    start_locus (other.start_locus), end_locus (other.end_locus)
+{
+  // guard to protect from null pointer dereference
+  if (other.expr != nullptr)
+    expr = other.expr->clone_expr ();
+
+  statements.reserve (other.statements.size ());
+  for (const auto &e : other.statements)
+    statements.push_back (e->clone_stmt ());
+}
+
+BlockExpr &
+BlockExpr::operator= (BlockExpr const &other)
+{
+  ExprWithBlock::operator= (other);
+  // statements = other.statements;
+  expr = other.expr->clone_expr ();
+  inner_attrs = other.inner_attrs;
+  start_locus = other.end_locus;
+  end_locus = other.end_locus;
+  // outer_attrs = other.outer_attrs;
+
+  statements.reserve (other.statements.size ());
+  for (const auto &e : other.statements)
+    statements.push_back (e->clone_stmt ());
+
+  return *this;
+}
+
+ContinueExpr::ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
+                           Lifetime label, AST::AttrVec outer_attribs)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    label (std::move (label)), locus (locus)
+{}
+
+BreakExpr::BreakExpr (Analysis::NodeMapping mappings, location_t locus,
+                     Lifetime break_label, std::unique_ptr<Expr> expr_in_break,
+                     AST::AttrVec outer_attribs)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    label (std::move (break_label)), break_expr (std::move (expr_in_break)),
+    locus (locus)
+{}
+
+BreakExpr::BreakExpr (BreakExpr const &other)
+  : ExprWithoutBlock (other), label (other.label), locus (other.locus)
+{
+  // guard to protect from null pointer dereference
+  if (other.break_expr != nullptr)
+    break_expr = other.break_expr->clone_expr ();
+}
+
+BreakExpr &
+BreakExpr::operator= (BreakExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  label = other.label;
+  break_expr = other.break_expr->clone_expr ();
+  locus = other.locus;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+RangeExpr::RangeExpr (Analysis::NodeMapping mappings, location_t locus)
+  : ExprWithoutBlock (std::move (mappings), AST::AttrVec ()), locus (locus)
+{}
+
+RangeFromToExpr::RangeFromToExpr (Analysis::NodeMapping mappings,
+                                 std::unique_ptr<Expr> range_from,
+                                 std::unique_ptr<Expr> range_to,
+                                 location_t locus)
+  : RangeExpr (std::move (mappings), locus), from (std::move (range_from)),
+    to (std::move (range_to))
+{}
+
+RangeFromToExpr::RangeFromToExpr (RangeFromToExpr const &other)
+  : RangeExpr (other), from (other.from->clone_expr ()),
+    to (other.to->clone_expr ())
+{}
+
+RangeFromToExpr &
+RangeFromToExpr::operator= (RangeFromToExpr const &other)
+{
+  RangeExpr::operator= (other);
+  from = other.from->clone_expr ();
+  to = other.to->clone_expr ();
+
+  return *this;
+}
+
+RangeFromExpr::RangeFromExpr (Analysis::NodeMapping mappings,
+                             std::unique_ptr<Expr> range_from,
+                             location_t locus)
+  : RangeExpr (std::move (mappings), locus), from (std::move (range_from))
+{}
+
+RangeFromExpr::RangeFromExpr (RangeFromExpr const &other)
+  : RangeExpr (other), from (other.from->clone_expr ())
+{}
+
+RangeFromExpr &
+RangeFromExpr::operator= (RangeFromExpr const &other)
+{
+  RangeExpr::operator= (other);
+  from = other.from->clone_expr ();
+
+  return *this;
+}
+
+RangeToExpr::RangeToExpr (Analysis::NodeMapping mappings,
+                         std::unique_ptr<Expr> range_to, location_t locus)
+  : RangeExpr (std::move (mappings), locus), to (std::move (range_to))
+{}
+
+RangeToExpr::RangeToExpr (RangeToExpr const &other)
+  : RangeExpr (other), to (other.to->clone_expr ())
+{}
+
+RangeToExpr &
+RangeToExpr::operator= (RangeToExpr const &other)
+{
+  RangeExpr::operator= (other);
+  to = other.to->clone_expr ();
+
+  return *this;
+}
+
+RangeFullExpr::RangeFullExpr (Analysis::NodeMapping mappings, location_t locus)
+  : RangeExpr (std::move (mappings), locus)
+{}
+
+RangeFromToInclExpr::RangeFromToInclExpr (Analysis::NodeMapping mappings,
+                                         std::unique_ptr<Expr> range_from,
+                                         std::unique_ptr<Expr> range_to,
+                                         location_t locus)
+  : RangeExpr (std::move (mappings), locus), from (std::move (range_from)),
+    to (std::move (range_to))
+{}
+
+RangeFromToInclExpr::RangeFromToInclExpr (RangeFromToInclExpr const &other)
+  : RangeExpr (other), from (other.from->clone_expr ()),
+    to (other.to->clone_expr ())
+{}
+
+RangeFromToInclExpr &
+RangeFromToInclExpr::operator= (RangeFromToInclExpr const &other)
+{
+  RangeExpr::operator= (other);
+  from = other.from->clone_expr ();
+  to = other.to->clone_expr ();
+
+  return *this;
+}
+
+RangeToInclExpr::RangeToInclExpr (Analysis::NodeMapping mappings,
+                                 std::unique_ptr<Expr> range_to,
+                                 location_t locus)
+  : RangeExpr (std::move (mappings), locus), to (std::move (range_to))
+{}
+
+RangeToInclExpr::RangeToInclExpr (RangeToInclExpr const &other)
+  : RangeExpr (other), to (other.to->clone_expr ())
+{}
+
+RangeToInclExpr &
+RangeToInclExpr::operator= (RangeToInclExpr const &other)
+{
+  RangeExpr::operator= (other);
+  to = other.to->clone_expr ();
+
+  return *this;
+}
+
+ReturnExpr::ReturnExpr (Analysis::NodeMapping mappings, location_t locus,
+                       std::unique_ptr<Expr> returned_expr,
+                       AST::AttrVec outer_attribs)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    return_expr (std::move (returned_expr)), locus (locus)
+{}
+
+ReturnExpr::ReturnExpr (ReturnExpr const &other)
+  : ExprWithoutBlock (other), locus (other.locus)
+{
+  // guard to protect from null pointer dereference
+  if (other.return_expr != nullptr)
+    return_expr = other.return_expr->clone_expr ();
+}
+
+ReturnExpr &
+ReturnExpr::operator= (ReturnExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  return_expr = other.return_expr->clone_expr ();
+  locus = other.locus;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+UnsafeBlockExpr::UnsafeBlockExpr (Analysis::NodeMapping mappings,
+                                 std::unique_ptr<BlockExpr> block_expr,
+                                 AST::AttrVec outer_attribs, location_t locus)
+  : ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
+    expr (std::move (block_expr)), locus (locus)
+{}
+
+UnsafeBlockExpr::UnsafeBlockExpr (UnsafeBlockExpr const &other)
+  : ExprWithBlock (other), expr (other.expr->clone_block_expr ()),
+    locus (other.locus)
+{}
+
+UnsafeBlockExpr &
+UnsafeBlockExpr::operator= (UnsafeBlockExpr const &other)
+{
+  ExprWithBlock::operator= (other);
+  expr = other.expr->clone_block_expr ();
+  locus = other.locus;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+BaseLoopExpr::BaseLoopExpr (Analysis::NodeMapping mappings,
+                           std::unique_ptr<BlockExpr> loop_block,
+                           location_t locus, LoopLabel loop_label,
+                           AST::AttrVec outer_attribs)
+  : ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
+    loop_label (std::move (loop_label)), loop_block (std::move (loop_block)),
+    locus (locus)
+{}
+
+BaseLoopExpr::BaseLoopExpr (BaseLoopExpr const &other)
+  : ExprWithBlock (other), loop_label (other.loop_label),
+    loop_block (other.loop_block->clone_block_expr ()), locus (other.locus)
+{}
+
+BaseLoopExpr &
+BaseLoopExpr::operator= (BaseLoopExpr const &other)
+{
+  ExprWithBlock::operator= (other);
+  loop_block = other.loop_block->clone_block_expr ();
+  loop_label = other.loop_label;
+  locus = other.locus;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+LoopExpr::LoopExpr (Analysis::NodeMapping mappings,
+                   std::unique_ptr<BlockExpr> loop_block, location_t locus,
+                   LoopLabel loop_label, AST::AttrVec outer_attribs)
+  : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
+                 std::move (loop_label), std::move (outer_attribs))
+{}
+
+WhileLoopExpr::WhileLoopExpr (Analysis::NodeMapping mappings,
+                             std::unique_ptr<Expr> loop_condition,
+                             std::unique_ptr<BlockExpr> loop_block,
+                             location_t locus, LoopLabel loop_label,
+                             AST::AttrVec outer_attribs)
+  : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
+                 std::move (loop_label), std::move (outer_attribs)),
+    condition (std::move (loop_condition))
+{}
+
+WhileLoopExpr::WhileLoopExpr (WhileLoopExpr const &other)
+  : BaseLoopExpr (other), condition (other.condition->clone_expr ())
+{}
+
+WhileLoopExpr &
+WhileLoopExpr::operator= (WhileLoopExpr const &other)
+{
+  BaseLoopExpr::operator= (other);
+  condition = other.condition->clone_expr ();
+  // loop_block = other.loop_block->clone_block_expr();
+  // loop_label = other.loop_label;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+WhileLetLoopExpr::WhileLetLoopExpr (
+  Analysis::NodeMapping mappings,
+  std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
+  std::unique_ptr<Expr> condition, std::unique_ptr<BlockExpr> loop_block,
+  location_t locus, LoopLabel loop_label, AST::AttrVec outer_attribs)
+  : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
+                 std::move (loop_label), std::move (outer_attribs)),
+    match_arm_patterns (std::move (match_arm_patterns)),
+    condition (std::move (condition))
+{}
+
+WhileLetLoopExpr::WhileLetLoopExpr (WhileLetLoopExpr const &other)
+  : BaseLoopExpr (other),
+    /*match_arm_patterns(other.match_arm_patterns),*/ condition (
+      other.condition->clone_expr ())
+{
+  match_arm_patterns.reserve (other.match_arm_patterns.size ());
+  for (const auto &e : other.match_arm_patterns)
+    match_arm_patterns.push_back (e->clone_pattern ());
+}
+
+WhileLetLoopExpr &
+WhileLetLoopExpr::operator= (WhileLetLoopExpr const &other)
+{
+  BaseLoopExpr::operator= (other);
+  // match_arm_patterns = other.match_arm_patterns;
+  condition = other.condition->clone_expr ();
+  // loop_block = other.loop_block->clone_block_expr();
+  // loop_label = other.loop_label;
+  // outer_attrs = other.outer_attrs;
+
+  match_arm_patterns.reserve (other.match_arm_patterns.size ());
+  for (const auto &e : other.match_arm_patterns)
+    match_arm_patterns.push_back (e->clone_pattern ());
+
+  return *this;
+}
+
+IfExpr::IfExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> condition,
+               std::unique_ptr<BlockExpr> if_block, location_t locus)
+  : ExprWithBlock (std::move (mappings), AST::AttrVec ()),
+    condition (std::move (condition)), if_block (std::move (if_block)),
+    locus (locus)
+{}
+
+IfExpr::IfExpr (IfExpr const &other)
+  : ExprWithBlock (other), condition (other.condition->clone_expr ()),
+    if_block (other.if_block->clone_block_expr ()), locus (other.locus)
+{}
+
+IfExpr &
+IfExpr::operator= (IfExpr const &other)
+{
+  ExprWithBlock::operator= (other);
+  condition = other.condition->clone_expr ();
+  if_block = other.if_block->clone_block_expr ();
+  locus = other.locus;
+
+  return *this;
+}
+
+IfExprConseqElse::IfExprConseqElse (Analysis::NodeMapping mappings,
+                                   std::unique_ptr<Expr> condition,
+                                   std::unique_ptr<BlockExpr> if_block,
+                                   std::unique_ptr<ExprWithBlock> else_block,
+                                   location_t locus)
+  : IfExpr (std::move (mappings), std::move (condition), std::move (if_block),
+           locus),
+    else_block (std::move (else_block))
+{}
+
+IfExprConseqElse::IfExprConseqElse (IfExprConseqElse const &other)
+  : IfExpr (other), else_block (other.else_block->clone_expr_with_block ())
+{}
+
+IfExprConseqElse &
+IfExprConseqElse::operator= (IfExprConseqElse const &other)
+{
+  IfExpr::operator= (other);
+  // condition = other.condition->clone_expr();
+  // if_block = other.if_block->clone_block_expr();
+  else_block = other.else_block->clone_expr_with_block ();
+
+  return *this;
+}
+
+MatchArm::MatchArm (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
+                   location_t locus, std::unique_ptr<Expr> guard_expr,
+                   AST::AttrVec outer_attrs)
+  : outer_attrs (std::move (outer_attrs)),
+    match_arm_patterns (std::move (match_arm_patterns)),
+    guard_expr (std::move (guard_expr)), locus (locus)
+{}
+
+MatchArm::MatchArm (MatchArm const &other) : outer_attrs (other.outer_attrs)
+{
+  // guard to protect from null pointer dereference
+  if (other.guard_expr != nullptr)
+    guard_expr = other.guard_expr->clone_expr ();
+
+  match_arm_patterns.reserve (other.match_arm_patterns.size ());
+  for (const auto &e : other.match_arm_patterns)
+    match_arm_patterns.push_back (e->clone_pattern ());
+
+  locus = other.locus;
+}
+
+MatchArm &
+MatchArm::operator= (MatchArm const &other)
+{
+  outer_attrs = other.outer_attrs;
+
+  if (other.guard_expr != nullptr)
+    guard_expr = other.guard_expr->clone_expr ();
+
+  match_arm_patterns.clear ();
+  match_arm_patterns.reserve (other.match_arm_patterns.size ());
+  for (const auto &e : other.match_arm_patterns)
+    match_arm_patterns.push_back (e->clone_pattern ());
+
+  return *this;
+}
+
+MatchCase::MatchCase (Analysis::NodeMapping mappings, MatchArm arm,
+                     std::unique_ptr<Expr> expr)
+  : mappings (mappings), arm (std::move (arm)), expr (std::move (expr))
+{}
+
+MatchCase::MatchCase (const MatchCase &other)
+  : mappings (other.mappings), arm (other.arm), expr (other.expr->clone_expr ())
+{}
+
+MatchCase &
+MatchCase::operator= (const MatchCase &other)
+{
+  mappings = other.mappings;
+  arm = other.arm;
+  expr = other.expr->clone_expr ();
+
+  return *this;
+}
+
+MatchExpr::MatchExpr (Analysis::NodeMapping mappings,
+                     std::unique_ptr<Expr> branch_value,
+                     std::vector<MatchCase> match_arms,
+                     AST::AttrVec inner_attrs, AST::AttrVec outer_attrs,
+                     location_t locus)
+  : ExprWithBlock (std::move (mappings), std::move (outer_attrs)),
+    WithInnerAttrs (std::move (inner_attrs)),
+    branch_value (std::move (branch_value)),
+    match_arms (std::move (match_arms)), locus (locus)
+{}
+
+MatchExpr::MatchExpr (MatchExpr const &other)
+  : ExprWithBlock (other), WithInnerAttrs (other.inner_attrs),
+    branch_value (other.branch_value->clone_expr ()),
+    match_arms (other.match_arms), locus (other.locus)
+{
+  /*match_arms.reserve (other.match_arms.size ());
+  for (const auto &e : other.match_arms)
+    match_arms.push_back (e->clone_match_case ());*/
+}
+
+MatchExpr &
+MatchExpr::operator= (MatchExpr const &other)
+{
+  ExprWithBlock::operator= (other);
+  branch_value = other.branch_value->clone_expr ();
+  inner_attrs = other.inner_attrs;
+  match_arms = other.match_arms;
+  // outer_attrs = other.outer_attrs;
+  locus = other.locus;
+
+  /*match_arms.reserve (other.match_arms.size ());
+  for (const auto &e : other.match_arms)
+    match_arms.push_back (e->clone_match_case ());*/
+
+  return *this;
+}
+
+AwaitExpr::AwaitExpr (Analysis::NodeMapping mappings,
+                     std::unique_ptr<Expr> awaited_expr,
+                     AST::AttrVec outer_attrs, location_t locus)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)),
+    awaited_expr (std::move (awaited_expr)), locus (locus)
+{}
+
+AwaitExpr::AwaitExpr (AwaitExpr const &other)
+  : ExprWithoutBlock (other), awaited_expr (other.awaited_expr->clone_expr ()),
+    locus (other.locus)
+{}
+
+AwaitExpr &
+AwaitExpr::operator= (AwaitExpr const &other)
+{
+  ExprWithoutBlock::operator= (other);
+  awaited_expr = other.awaited_expr->clone_expr ();
+  locus = other.locus;
+
+  return *this;
+}
+
+AsyncBlockExpr::AsyncBlockExpr (Analysis::NodeMapping mappings,
+                               std::unique_ptr<BlockExpr> block_expr,
+                               bool has_move, AST::AttrVec outer_attrs,
+                               location_t locus)
+  : ExprWithBlock (std::move (mappings), std::move (outer_attrs)),
+    has_move (has_move), block_expr (std::move (block_expr)), locus (locus)
+{}
+
+AsyncBlockExpr::AsyncBlockExpr (AsyncBlockExpr const &other)
+  : ExprWithBlock (other), has_move (other.has_move),
+    block_expr (other.block_expr->clone_block_expr ()), locus (other.locus)
+{}
+
+AsyncBlockExpr &
+AsyncBlockExpr::operator= (AsyncBlockExpr const &other)
+{
+  ExprWithBlock::operator= (other);
+  has_move = other.has_move;
+  block_expr = other.block_expr->clone_block_expr ();
+  locus = other.locus;
+
+  return *this;
+}
+
+OperatorExprMeta::OperatorExprMeta (HIR::CompoundAssignmentExpr &expr)
+  : node_mappings (expr.get_mappings ()),
+    lvalue_mappings (expr.get_expr ().get_mappings ()),
+    locus (expr.get_locus ())
+{}
+
+OperatorExprMeta::OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr)
+  : node_mappings (expr.get_mappings ()),
+    lvalue_mappings (expr.get_expr ().get_mappings ()),
+    locus (expr.get_locus ())
+{}
+
+OperatorExprMeta::OperatorExprMeta (HIR::NegationExpr &expr)
+  : node_mappings (expr.get_mappings ()),
+    lvalue_mappings (expr.get_expr ().get_mappings ()),
+    locus (expr.get_locus ())
+{}
+
+OperatorExprMeta::OperatorExprMeta (HIR::DereferenceExpr &expr)
+  : node_mappings (expr.get_mappings ()),
+    lvalue_mappings (expr.get_expr ().get_mappings ()),
+    locus (expr.get_locus ())
+{}
+
+OperatorExprMeta::OperatorExprMeta (HIR::ArrayIndexExpr &expr)
+  : node_mappings (expr.get_mappings ()),
+    lvalue_mappings (expr.get_array_expr ().get_mappings ()),
+    locus (expr.get_locus ())
+{}
+
+AnonConst::AnonConst (NodeId id, std::unique_ptr<Expr> expr)
+  : id (id), expr (std::move (expr))
+{
+  rust_assert (this->expr != nullptr);
+}
+
+AnonConst::AnonConst (const AnonConst &other)
+{
+  id = other.id;
+  expr = other.expr->clone_expr ();
+}
+
+AnonConst
+AnonConst::operator= (const AnonConst &other)
+{
+  id = other.id;
+  expr = other.expr->clone_expr ();
+  return *this;
+}
+
+InlineAsmOperand::In::In (
+  const tl::optional<struct AST::InlineAsmRegOrRegClass> &reg,
+  std::unique_ptr<Expr> expr)
+  : reg (reg), expr (std::move (expr))
+{
+  rust_assert (this->expr != nullptr);
+}
+
+InlineAsmOperand::In::In (const struct In &other)
+{
+  reg = other.reg;
+
+  expr = other.expr->clone_expr ();
+}
+
+InlineAsmOperand::In
+InlineAsmOperand::In::operator= (const struct In &other)
+{
+  reg = other.reg;
+  expr = other.expr->clone_expr ();
+
+  return *this;
+}
+
+InlineAsmOperand::Out::Out (
+  tl::optional<struct AST::InlineAsmRegOrRegClass> &reg, bool late,
+  std::unique_ptr<Expr> expr)
+  : reg (reg), late (late), expr (std::move (expr))
+{
+  rust_assert (this->expr != nullptr);
+}
+
+InlineAsmOperand::Out::Out (const struct Out &other)
+{
+  reg = other.reg;
+  late = other.late;
+  expr = other.expr->clone_expr ();
+}
+
+InlineAsmOperand::Out
+InlineAsmOperand::Out::operator= (const struct Out &other)
+{
+  reg = other.reg;
+  late = other.late;
+  expr = other.expr->clone_expr ();
+  return *this;
+}
+
+InlineAsmOperand::InOut::InOut (
+  tl::optional<struct AST::InlineAsmRegOrRegClass> &reg, bool late,
+  std::unique_ptr<Expr> expr)
+  : reg (reg), late (late), expr (std::move (expr))
+{
+  rust_assert (this->expr != nullptr);
+}
+
+InlineAsmOperand::InOut::InOut (const struct InOut &other)
+{
+  reg = other.reg;
+  late = other.late;
+  expr = other.expr->clone_expr ();
+}
+
+InlineAsmOperand::InOut
+InlineAsmOperand::InOut::operator= (const struct InOut &other)
+{
+  reg = other.reg;
+  late = other.late;
+  expr = other.expr->clone_expr ();
+
+  return *this;
+}
+
+InlineAsmOperand::SplitInOut::SplitInOut (
+  tl::optional<struct AST::InlineAsmRegOrRegClass> &reg, bool late,
+  std::unique_ptr<Expr> in_expr, std::unique_ptr<Expr> out_expr)
+  : reg (reg), late (late), in_expr (std::move (in_expr)),
+    out_expr (std::move (out_expr))
+{
+  rust_assert (this->in_expr != nullptr);
+  rust_assert (this->out_expr != nullptr);
+}
+
+InlineAsmOperand::SplitInOut::SplitInOut (const struct SplitInOut &other)
+{
+  reg = other.reg;
+  late = other.late;
+  in_expr = other.in_expr->clone_expr ();
+  out_expr = other.out_expr->clone_expr ();
+}
+
+InlineAsmOperand::SplitInOut
+InlineAsmOperand::SplitInOut::operator= (const struct SplitInOut &other)
+{
+  reg = other.reg;
+  late = other.late;
+  in_expr = other.in_expr->clone_expr ();
+  out_expr = other.out_expr->clone_expr ();
+
+  return *this;
+}
+
+InlineAsmOperand::Sym::Sym (std::unique_ptr<Expr> expr)
+  : expr (std::move (expr))
+{
+  rust_assert (this->expr != nullptr);
+}
+
+InlineAsmOperand::Sym::Sym (const struct Sym &other)
+{
+  expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
+}
+
+InlineAsmOperand::Sym
+InlineAsmOperand::Sym::operator= (const struct Sym &other)
+{
+  expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
+  return *this;
+}
+
+InlineAsmOperand::Label::Label (tl::optional<std::string> label_name,
+                               std::unique_ptr<Expr> expr)
+  : expr (std::move (expr))
+{
+  rust_assert (this->expr != nullptr);
+  if (label_name.has_value ())
+    this->label_name = label_name.value ();
+}
+
+InlineAsmOperand::Label::Label (const struct Label &other)
+{
+  expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
+}
+
+InlineAsmOperand::Label
+InlineAsmOperand::Label::operator= (const struct Label &other)
+{
+  expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
+  return *this;
+}
+
+InlineAsm::InlineAsm (location_t locus, bool is_global_asm,
+                     std::vector<AST::InlineAsmTemplatePiece> template_,
+                     std::vector<AST::TupleTemplateStr> template_strs,
+                     std::vector<HIR::InlineAsmOperand> operands,
+                     std::vector<AST::TupleClobber> clobber_abi,
+                     std::set<AST::InlineAsmOption> options,
+                     Analysis::NodeMapping mappings,
+                     AST::AttrVec outer_attribs)
+  : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+    locus (locus), is_global_asm (is_global_asm),
+    template_ (std::move (template_)),
+    template_strs (std::move (template_strs)), operands (std::move (operands)),
+    clobber_abi (std::move (clobber_abi)), options (std::move (options))
+{}
+
+} // namespace HIR
+} // namespace Rust
index c66b549a4d4a2a507236e0ebd4f0735d882e0daa..1273466b74cd933c77cda5cee70e06b1c044ac19 100644 (file)
 #ifndef RUST_HIR_EXPR_H
 #define RUST_HIR_EXPR_H
 
+#include "rust-hir-expr-abstract.h"
+#include "rust-hir-literal.h"
 #include "rust-common.h"
-#include "rust-ast-full-decls.h"
-#include "rust-hir.h"
-#include "rust-hir-path.h"
-#include "rust-operators.h"
+#include "rust-hir-bound.h"
+#include "rust-hir-attrs.h"
 #include "rust-expr.h"
+
 namespace Rust {
 namespace HIR {
 
@@ -42,9 +43,7 @@ public:
   std::string as_string () const;
 
   LoopLabel (Analysis::NodeMapping mapping, Lifetime loop_label,
-            location_t locus)
-    : label (std::move (loop_label)), locus (locus), mappings (mapping)
-  {}
+            location_t locus);
 
   // Returns whether the LoopLabel is in an error state.
   bool is_error () const { return label.is_error (); }
@@ -62,9 +61,7 @@ class ExprWithBlock : public Expr
   // TODO: should this mean that a BlockExpr should be a member variable?
 protected:
   ExprWithBlock (Analysis::NodeMapping mappings,
-                AST::AttrVec outer_attrs = AST::AttrVec ())
-    : Expr (std::move (mappings), std::move (outer_attrs))
-  {}
+                AST::AttrVec outer_attrs = AST::AttrVec ());
 
   // pure virtual clone implementation
   virtual ExprWithBlock *clone_expr_with_block_impl () const = 0;
@@ -106,16 +103,10 @@ public:
 
   LiteralExpr (Analysis::NodeMapping mappings, std::string value_as_string,
               Literal::LitType type, PrimitiveCoreType type_hint,
-              location_t locus, AST::AttrVec outer_attrs)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)),
-      literal (std::move (value_as_string), type, type_hint), locus (locus)
-  {}
+              location_t locus, AST::AttrVec outer_attrs);
 
   LiteralExpr (Analysis::NodeMapping mappings, Literal literal,
-              location_t locus, AST::AttrVec outer_attrs)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)),
-      literal (std::move (literal)), locus (locus)
-  {}
+              location_t locus, AST::AttrVec outer_attrs);
 
   // Unique pointer custom clone function
   std::unique_ptr<LiteralExpr> clone_literal_expr () const
@@ -180,27 +171,13 @@ protected:
   // Constructor (only for initialisation of expr purposes)
   OperatorExpr (Analysis::NodeMapping mappings,
                std::unique_ptr<Expr> main_or_left_expr,
-               AST::AttrVec outer_attribs, location_t locus)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      locus (locus), main_or_left_expr (std::move (main_or_left_expr))
-  {}
+               AST::AttrVec outer_attribs, location_t locus);
 
   // Copy constructor (only for initialisation of expr purposes)
-  OperatorExpr (OperatorExpr const &other)
-    : ExprWithoutBlock (other), locus (other.locus),
-      main_or_left_expr (other.main_or_left_expr->clone_expr ())
-  {}
+  OperatorExpr (OperatorExpr const &other);
 
   // Overload assignment operator to deep copy expr
-  OperatorExpr &operator= (OperatorExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    main_or_left_expr = other.main_or_left_expr->clone_expr ();
-    locus = other.locus;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  OperatorExpr &operator= (OperatorExpr const &other);
 
   // move constructors
   OperatorExpr (OperatorExpr &&other) = default;
@@ -228,11 +205,7 @@ public:
 
   BorrowExpr (Analysis::NodeMapping mappings,
              std::unique_ptr<Expr> borrow_lvalue, Mutability mut,
-             AST::AttrVec outer_attribs, location_t locus)
-    : OperatorExpr (std::move (mappings), std::move (borrow_lvalue),
-                   std::move (outer_attribs), locus),
-      mut (mut)
-  {}
+             AST::AttrVec outer_attribs, location_t locus);
 
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRExpressionVisitor &vis) override;
@@ -265,10 +238,7 @@ public:
   // Constructor calls OperatorExpr's protected constructor
   DereferenceExpr (Analysis::NodeMapping mappings,
                   std::unique_ptr<Expr> deref_lvalue,
-                  AST::AttrVec outer_attribs, location_t locus)
-    : OperatorExpr (std::move (mappings), std::move (deref_lvalue),
-                   std::move (outer_attribs), locus)
-  {}
+                  AST::AttrVec outer_attribs, location_t locus);
 
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRExpressionVisitor &vis) override;
@@ -298,10 +268,7 @@ public:
   // Constructor calls OperatorExpr's protected constructor
   ErrorPropagationExpr (Analysis::NodeMapping mappings,
                        std::unique_ptr<Expr> potential_error_value,
-                       AST::AttrVec outer_attribs, location_t locus)
-    : OperatorExpr (std::move (mappings), std::move (potential_error_value),
-                   std::move (outer_attribs), locus)
-  {}
+                       AST::AttrVec outer_attribs, location_t locus);
 
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRExpressionVisitor &vis) override;
@@ -342,11 +309,7 @@ public:
   // Constructor calls OperatorExpr's protected constructor
   NegationExpr (Analysis::NodeMapping mappings,
                std::unique_ptr<Expr> negated_value, ExprType expr_kind,
-               AST::AttrVec outer_attribs, location_t locus)
-    : OperatorExpr (std::move (mappings), std::move (negated_value),
-                   std::move (outer_attribs), locus),
-      expr_type (expr_kind)
-  {}
+               AST::AttrVec outer_attribs, location_t locus);
 
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRExpressionVisitor &vis) override;
@@ -388,29 +351,14 @@ public:
   ArithmeticOrLogicalExpr (Analysis::NodeMapping mappings,
                           std::unique_ptr<Expr> left_value,
                           std::unique_ptr<Expr> right_value,
-                          ExprType expr_kind, location_t locus)
-    : OperatorExpr (std::move (mappings), std::move (left_value),
-                   AST::AttrVec (), locus),
-      expr_type (expr_kind), right_expr (std::move (right_value))
-  {}
+                          ExprType expr_kind, location_t locus);
   // outer attributes not allowed
 
   // Copy constructor - probably required due to unique pointer
-  ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr const &other)
-    : OperatorExpr (other), expr_type (other.expr_type),
-      right_expr (other.right_expr->clone_expr ())
-  {}
+  ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr const &other);
 
   // Overload assignment operator
-  ArithmeticOrLogicalExpr &operator= (ArithmeticOrLogicalExpr const &other)
-  {
-    OperatorExpr::operator= (other);
-    // main_or_left_expr = other.main_or_left_expr->clone_expr();
-    right_expr = other.right_expr->clone_expr ();
-    expr_type = other.expr_type;
-
-    return *this;
-  }
+  ArithmeticOrLogicalExpr &operator= (ArithmeticOrLogicalExpr const &other);
 
   // move constructors
   ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr &&other) = default;
@@ -465,30 +413,14 @@ public:
   ComparisonExpr (Analysis::NodeMapping mappings,
                  std::unique_ptr<Expr> left_value,
                  std::unique_ptr<Expr> right_value, ExprType comparison_kind,
-                 location_t locus)
-    : OperatorExpr (std::move (mappings), std::move (left_value),
-                   AST::AttrVec (), locus),
-      expr_type (comparison_kind), right_expr (std::move (right_value))
-  {}
+                 location_t locus);
   // outer attributes not allowed
 
   // Copy constructor also calls OperatorExpr's protected constructor
-  ComparisonExpr (ComparisonExpr const &other)
-    : OperatorExpr (other), expr_type (other.expr_type),
-      right_expr (other.right_expr->clone_expr ())
-  {}
+  ComparisonExpr (ComparisonExpr const &other);
 
   // Overload assignment operator to deep copy
-  ComparisonExpr &operator= (ComparisonExpr const &other)
-  {
-    OperatorExpr::operator= (other);
-    // main_or_left_expr = other.main_or_left_expr->clone_expr();
-    right_expr = other.right_expr->clone_expr ();
-    expr_type = other.expr_type;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  ComparisonExpr &operator= (ComparisonExpr const &other);
 
   // move constructors
   ComparisonExpr (ComparisonExpr &&other) = default;
@@ -536,29 +468,14 @@ public:
   LazyBooleanExpr (Analysis::NodeMapping mappings,
                   std::unique_ptr<Expr> left_bool_expr,
                   std::unique_ptr<Expr> right_bool_expr, ExprType expr_kind,
-                  location_t locus)
-    : OperatorExpr (std::move (mappings), std::move (left_bool_expr),
-                   AST::AttrVec (), locus),
-      expr_type (expr_kind), right_expr (std::move (right_bool_expr))
-  {}
+                  location_t locus);
   // outer attributes not allowed
 
   // Copy constructor also calls OperatorExpr's protected constructor
-  LazyBooleanExpr (LazyBooleanExpr const &other)
-    : OperatorExpr (other), expr_type (other.expr_type),
-      right_expr (other.right_expr->clone_expr ())
-  {}
+  LazyBooleanExpr (LazyBooleanExpr const &other);
 
   // Overload assignment operator to deep copy
-  LazyBooleanExpr &operator= (LazyBooleanExpr const &other)
-  {
-    OperatorExpr::operator= (other);
-    // main_or_left_expr = other.main_or_left_expr->clone_expr();
-    right_expr = other.right_expr->clone_expr ();
-    expr_type = other.expr_type;
-
-    return *this;
-  }
+  LazyBooleanExpr &operator= (LazyBooleanExpr const &other);
 
   // move constructors
   LazyBooleanExpr (LazyBooleanExpr &&other) = default;
@@ -602,28 +519,14 @@ public:
   // Constructor requires calling protected constructor of OperatorExpr
   TypeCastExpr (Analysis::NodeMapping mappings,
                std::unique_ptr<Expr> expr_to_cast,
-               std::unique_ptr<Type> type_to_cast_to, location_t locus)
-    : OperatorExpr (std::move (mappings), std::move (expr_to_cast),
-                   AST::AttrVec (), locus),
-      type_to_convert_to (std::move (type_to_cast_to))
-  {}
+               std::unique_ptr<Type> type_to_cast_to, location_t locus);
   // outer attributes not allowed
 
   // Copy constructor also requires calling protected constructor
-  TypeCastExpr (TypeCastExpr const &other)
-    : OperatorExpr (other),
-      type_to_convert_to (other.type_to_convert_to->clone_type ())
-  {}
+  TypeCastExpr (TypeCastExpr const &other);
 
   // Overload assignment operator to deep copy
-  TypeCastExpr &operator= (TypeCastExpr const &other)
-  {
-    OperatorExpr::operator= (other);
-    // main_or_left_expr = other.main_or_left_expr->clone_expr();
-    type_to_convert_to = other.type_to_convert_to->clone_type ();
-
-    return *this;
-  }
+  TypeCastExpr &operator= (TypeCastExpr const &other);
 
   // move constructors as not supported in c++03
   TypeCastExpr (TypeCastExpr &&other) = default;
@@ -664,28 +567,14 @@ public:
   // Call OperatorExpr constructor to initialise left_expr
   AssignmentExpr (Analysis::NodeMapping mappings,
                  std::unique_ptr<Expr> value_to_assign_to,
-                 std::unique_ptr<Expr> value_to_assign, location_t locus)
-    : OperatorExpr (std::move (mappings), std::move (value_to_assign_to),
-                   AST::AttrVec (), locus),
-      right_expr (std::move (value_to_assign))
-  {}
+                 std::unique_ptr<Expr> value_to_assign, location_t locus);
   // outer attributes not allowed
 
   // Call OperatorExpr constructor in copy constructor, as well as clone
-  AssignmentExpr (AssignmentExpr const &other)
-    : OperatorExpr (other), right_expr (other.right_expr->clone_expr ())
-  {}
+  AssignmentExpr (AssignmentExpr const &other);
 
   // Overload assignment operator to clone unique_ptr right_expr
-  AssignmentExpr &operator= (AssignmentExpr const &other)
-  {
-    OperatorExpr::operator= (other);
-    // main_or_left_expr = other.main_or_left_expr->clone_expr();
-    right_expr = other.right_expr->clone_expr ();
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  AssignmentExpr &operator= (AssignmentExpr const &other);
 
   // move constructors
   AssignmentExpr (AssignmentExpr &&other) = default;
@@ -735,30 +624,14 @@ public:
   CompoundAssignmentExpr (Analysis::NodeMapping mappings,
                          std::unique_ptr<Expr> value_to_assign_to,
                          std::unique_ptr<Expr> value_to_assign,
-                         ExprType expr_kind, location_t locus)
-    : OperatorExpr (std::move (mappings), std::move (value_to_assign_to),
-                   AST::AttrVec (), locus),
-      expr_type (expr_kind), right_expr (std::move (value_to_assign))
-  {}
+                         ExprType expr_kind, location_t locus);
   // outer attributes not allowed
 
   // Have clone in copy constructor
-  CompoundAssignmentExpr (CompoundAssignmentExpr const &other)
-    : OperatorExpr (other), expr_type (other.expr_type),
-      right_expr (other.right_expr->clone_expr ())
-  {}
+  CompoundAssignmentExpr (CompoundAssignmentExpr const &other);
 
   // Overload assignment operator to clone
-  CompoundAssignmentExpr &operator= (CompoundAssignmentExpr const &other)
-  {
-    OperatorExpr::operator= (other);
-    // main_or_left_expr = other.main_or_left_expr->clone_expr();
-    right_expr = other.right_expr->clone_expr ();
-    expr_type = other.expr_type;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  CompoundAssignmentExpr &operator= (CompoundAssignmentExpr const &other);
 
   // move constructors
   CompoundAssignmentExpr (CompoundAssignmentExpr &&other) = default;
@@ -798,29 +671,13 @@ public:
   GroupedExpr (Analysis::NodeMapping mappings,
               std::unique_ptr<Expr> parenthesised_expr,
               AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
-              location_t locus)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      WithInnerAttrs (std::move (inner_attribs)),
-      expr_in_parens (std::move (parenthesised_expr)), locus (locus)
-  {}
+              location_t locus);
 
   // Copy constructor includes clone for expr_in_parens
-  GroupedExpr (GroupedExpr const &other)
-    : ExprWithoutBlock (other), WithInnerAttrs (other.inner_attrs),
-      expr_in_parens (other.expr_in_parens->clone_expr ()), locus (other.locus)
-  {}
+  GroupedExpr (GroupedExpr const &other);
 
   // Overloaded assignment operator to clone expr_in_parens
-  GroupedExpr &operator= (GroupedExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    inner_attrs = other.inner_attrs;
-    expr_in_parens = other.expr_in_parens->clone_expr ();
-    locus = other.locus;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  GroupedExpr &operator= (GroupedExpr const &other);
 
   // move constructors
   GroupedExpr (GroupedExpr &&other) = default;
@@ -893,33 +750,19 @@ protected:
 // Value array elements
 class ArrayElemsValues : public ArrayElems
 {
-  std::vector<std::unique_ptr<Expr> > values;
+  std::vector<std::unique_ptr<Expr>> values;
 
   // TODO: should this store location data?
 
 public:
   ArrayElemsValues (Analysis::NodeMapping mappings,
-                   std::vector<std::unique_ptr<Expr> > elems)
-    : ArrayElems (mappings), values (std::move (elems))
-  {}
+                   std::vector<std::unique_ptr<Expr>> elems);
 
   // copy constructor with vector clone
-  ArrayElemsValues (ArrayElemsValues const &other) : ArrayElems (other)
-  {
-    values.reserve (other.values.size ());
-    for (const auto &e : other.values)
-      values.push_back (e->clone_expr ());
-  }
+  ArrayElemsValues (ArrayElemsValues const &other);
 
   // overloaded assignment operator with vector clone
-  ArrayElemsValues &operator= (ArrayElemsValues const &other)
-  {
-    values.reserve (other.values.size ());
-    for (const auto &e : other.values)
-      values.push_back (e->clone_expr ());
-
-    return *this;
-  }
+  ArrayElemsValues &operator= (ArrayElemsValues const &other);
 
   // move constructors
   ArrayElemsValues (ArrayElemsValues &&other) = default;
@@ -931,7 +774,7 @@ public:
 
   size_t get_num_elements () const { return values.size (); }
 
-  std::vector<std::unique_ptr<Expr> > &get_values () { return values; }
+  std::vector<std::unique_ptr<Expr>> &get_values () { return values; }
 
   ArrayElems::ArrayExprType get_array_expr_type () const override final
   {
@@ -955,25 +798,13 @@ public:
   // Constructor requires pointers for polymorphism
   ArrayElemsCopied (Analysis::NodeMapping mappings,
                    std::unique_ptr<Expr> copied_elem,
-                   std::unique_ptr<Expr> copy_amount)
-    : ArrayElems (mappings), elem_to_copy (std::move (copied_elem)),
-      num_copies (std::move (copy_amount))
-  {}
+                   std::unique_ptr<Expr> copy_amount);
 
   // Copy constructor required due to unique_ptr - uses custom clone
-  ArrayElemsCopied (ArrayElemsCopied const &other)
-    : ArrayElems (other), elem_to_copy (other.elem_to_copy->clone_expr ()),
-      num_copies (other.num_copies->clone_expr ())
-  {}
+  ArrayElemsCopied (ArrayElemsCopied const &other);
 
   // Overloaded assignment operator for deep copying
-  ArrayElemsCopied &operator= (ArrayElemsCopied const &other)
-  {
-    elem_to_copy = other.elem_to_copy->clone_expr ();
-    num_copies = other.num_copies->clone_expr ();
-
-    return *this;
-  }
+  ArrayElemsCopied &operator= (ArrayElemsCopied const &other);
 
   // move constructors
   ArrayElemsCopied (ArrayElemsCopied &&other) = default;
@@ -1016,33 +847,13 @@ public:
   ArrayExpr (Analysis::NodeMapping mappings,
             std::unique_ptr<ArrayElems> array_elems,
             AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
-            location_t locus)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      WithInnerAttrs (std::move (inner_attribs)),
-      internal_elements (std::move (array_elems)), locus (locus)
-  {}
+            location_t locus);
 
   // Copy constructor requires cloning ArrayElems for polymorphism to hold
-  ArrayExpr (ArrayExpr const &other)
-    : ExprWithoutBlock (other), WithInnerAttrs (other.inner_attrs),
-      locus (other.locus)
-  {
-    if (other.has_array_elems ())
-      internal_elements = other.internal_elements->clone_array_elems ();
-  }
+  ArrayExpr (ArrayExpr const &other);
 
   // Overload assignment operator to clone internal_elements
-  ArrayExpr &operator= (ArrayExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    inner_attrs = other.inner_attrs;
-    if (other.has_array_elems ())
-      internal_elements = other.internal_elements->clone_array_elems ();
-    locus = other.locus;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  ArrayExpr &operator= (ArrayExpr const &other);
 
   // move constructors
   ArrayExpr (ArrayExpr &&other) = default;
@@ -1086,29 +897,13 @@ public:
   ArrayIndexExpr (Analysis::NodeMapping mappings,
                  std::unique_ptr<Expr> array_expr,
                  std::unique_ptr<Expr> array_index_expr,
-                 AST::AttrVec outer_attribs, location_t locus)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      array_expr (std::move (array_expr)),
-      index_expr (std::move (array_index_expr)), locus (locus)
-  {}
+                 AST::AttrVec outer_attribs, location_t locus);
 
   // Copy constructor requires special cloning due to unique_ptr
-  ArrayIndexExpr (ArrayIndexExpr const &other)
-    : ExprWithoutBlock (other), array_expr (other.array_expr->clone_expr ()),
-      index_expr (other.index_expr->clone_expr ()), locus (other.locus)
-  {}
+  ArrayIndexExpr (ArrayIndexExpr const &other);
 
   // Overload assignment operator to clone unique_ptrs
-  ArrayIndexExpr &operator= (ArrayIndexExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    array_expr = other.array_expr->clone_expr ();
-    index_expr = other.index_expr->clone_expr ();
-    // outer_attrs = other.outer_attrs;
-    locus = other.locus;
-
-    return *this;
-  }
+  ArrayIndexExpr &operator= (ArrayIndexExpr const &other);
 
   // move constructors
   ArrayIndexExpr (ArrayIndexExpr &&other) = default;
@@ -1146,7 +941,7 @@ protected:
 // HIR representation of a tuple
 class TupleExpr : public ExprWithoutBlock, public WithInnerAttrs
 {
-  std::vector<std::unique_ptr<Expr> > tuple_elems;
+  std::vector<std::unique_ptr<Expr>> tuple_elems;
   // replaces (inlined version of) TupleElements
 
   location_t locus;
@@ -1155,37 +950,15 @@ public:
   std::string as_string () const override;
 
   TupleExpr (Analysis::NodeMapping mappings,
-            std::vector<std::unique_ptr<Expr> > tuple_elements,
+            std::vector<std::unique_ptr<Expr>> tuple_elements,
             AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
-            location_t locus)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      WithInnerAttrs (std::move (inner_attribs)),
-      tuple_elems (std::move (tuple_elements)), locus (locus)
-  {}
+            location_t locus);
 
   // copy constructor with vector clone
-  TupleExpr (TupleExpr const &other)
-    : ExprWithoutBlock (other), WithInnerAttrs (other.inner_attrs),
-      locus (other.locus)
-  {
-    tuple_elems.reserve (other.tuple_elems.size ());
-    for (const auto &e : other.tuple_elems)
-      tuple_elems.push_back (e->clone_expr ());
-  }
+  TupleExpr (TupleExpr const &other);
 
   // overloaded assignment operator to vector clone
-  TupleExpr &operator= (TupleExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    inner_attrs = other.inner_attrs;
-    locus = other.locus;
-
-    tuple_elems.reserve (other.tuple_elems.size ());
-    for (const auto &e : other.tuple_elems)
-      tuple_elems.push_back (e->clone_expr ());
-
-    return *this;
-  }
+  TupleExpr &operator= (TupleExpr const &other);
 
   // move constructors
   TupleExpr (TupleExpr &&other) = default;
@@ -1199,14 +972,11 @@ public:
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRExpressionVisitor &vis) override;
 
-  const std::vector<std::unique_ptr<Expr> > &get_tuple_elems () const
-  {
-    return tuple_elems;
-  }
-  std::vector<std::unique_ptr<Expr> > &get_tuple_elems ()
+  const std::vector<std::unique_ptr<Expr>> &get_tuple_elems () const
   {
     return tuple_elems;
   }
+  std::vector<std::unique_ptr<Expr>> &get_tuple_elems () { return tuple_elems; }
 
   bool is_unit () const { return tuple_elems.size () == 0; }
 
@@ -1241,28 +1011,13 @@ public:
 
   TupleIndexExpr (Analysis::NodeMapping mappings,
                  std::unique_ptr<Expr> tuple_expr, TupleIndex index,
-                 AST::AttrVec outer_attribs, location_t locus)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      tuple_expr (std::move (tuple_expr)), tuple_index (index), locus (locus)
-  {}
+                 AST::AttrVec outer_attribs, location_t locus);
 
   // Copy constructor requires a clone for tuple_expr
-  TupleIndexExpr (TupleIndexExpr const &other)
-    : ExprWithoutBlock (other), tuple_expr (other.tuple_expr->clone_expr ()),
-      tuple_index (other.tuple_index), locus (other.locus)
-  {}
+  TupleIndexExpr (TupleIndexExpr const &other);
 
   // Overload assignment operator in order to clone
-  TupleIndexExpr &operator= (TupleIndexExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    tuple_expr = other.tuple_expr->clone_expr ();
-    tuple_index = other.tuple_index;
-    locus = other.locus;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  TupleIndexExpr &operator= (TupleIndexExpr const &other);
 
   // move constructors
   TupleIndexExpr (TupleIndexExpr &&other) = default;
@@ -1304,10 +1059,7 @@ protected:
 
   // Protected constructor to allow initialising struct_name
   StructExpr (Analysis::NodeMapping mappings, PathInExpression struct_path,
-             AST::AttrVec outer_attribs)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      struct_name (std::move (struct_path))
-  {}
+             AST::AttrVec outer_attribs);
 
 public:
   PathInExpression &get_struct_name () { return struct_name; }
@@ -1331,11 +1083,7 @@ public:
   // Constructor has to call protected constructor of base class
   StructExprStruct (Analysis::NodeMapping mappings,
                    PathInExpression struct_path, AST::AttrVec inner_attribs,
-                   AST::AttrVec outer_attribs, location_t locus)
-    : StructExpr (std::move (mappings), std::move (struct_path),
-                 std::move (outer_attribs)),
-      WithInnerAttrs (std::move (inner_attribs)), locus (locus)
-  {}
+                   AST::AttrVec outer_attribs, location_t locus);
 
   location_t get_locus () const override final { return locus; }
 
@@ -1362,33 +1110,21 @@ protected:
  * struct */
 struct StructBase
 {
-public:
+private:
   std::unique_ptr<Expr> base_struct;
 
+public:
   // TODO: should this store location data?
-  StructBase (std::unique_ptr<Expr> base_struct_ptr)
-    : base_struct (std::move (base_struct_ptr))
-  {}
+  StructBase (std::unique_ptr<Expr> base_struct_ptr);
 
   // Copy constructor requires clone
-  StructBase (StructBase const &other)
-  {
-    /* HACK: gets around base_struct pointer being null (e.g. if no struct base
-     * exists) */
-    if (other.base_struct != nullptr)
-      other.base_struct->clone_expr ();
-  }
+  StructBase (StructBase const &other);
 
   // Destructor
   ~StructBase () = default;
 
   // Overload assignment operator to clone base_struct
-  StructBase &operator= (StructBase const &other)
-  {
-    base_struct = other.base_struct->clone_expr ();
-
-    return *this;
-  }
+  StructBase &operator= (StructBase const &other);
 
   // move constructors
   StructBase (StructBase &&other) = default;
@@ -1402,7 +1138,7 @@ public:
 
   std::string as_string () const;
 
-  Expr *get_base () { return base_struct.get (); }
+  Expr &get_base () { return *base_struct; }
 };
 
 /* Base HIR node for a single struct expression field (in struct instance
@@ -1440,9 +1176,7 @@ protected:
   // pure virtual clone implementation
   virtual StructExprField *clone_struct_expr_field_impl () const = 0;
 
-  StructExprField (Analysis::NodeMapping mapping, location_t locus)
-    : mappings (mapping), locus (locus)
-  {}
+  StructExprField (Analysis::NodeMapping mapping, location_t locus);
 
   Analysis::NodeMapping mappings;
   location_t locus;
@@ -1457,10 +1191,7 @@ private:
   // TODO: should this store location data?
 public:
   StructExprFieldIdentifier (Analysis::NodeMapping mapping,
-                            Identifier field_identifier, location_t locus)
-    : StructExprField (mapping, locus),
-      field_name (std::move (field_identifier))
-  {}
+                            Identifier field_identifier, location_t locus);
 
   std::string as_string () const override { return field_name.as_string (); }
 
@@ -1491,25 +1222,13 @@ class StructExprFieldWithVal : public StructExprField
 
 protected:
   StructExprFieldWithVal (Analysis::NodeMapping mapping,
-                         std::unique_ptr<Expr> field_value, location_t locus)
-    : StructExprField (mapping, locus), value (std::move (field_value))
-  {}
+                         std::unique_ptr<Expr> field_value, location_t locus);
 
   // Copy constructor requires clone
-  StructExprFieldWithVal (StructExprFieldWithVal const &other)
-    : StructExprField (other.mappings, other.locus),
-      value (other.value->clone_expr ())
-  {}
+  StructExprFieldWithVal (StructExprFieldWithVal const &other);
 
   // Overload assignment operator to clone unique_ptr
-  StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other)
-  {
-    value = other.value->clone_expr ();
-    mappings = other.mappings;
-    locus = other.locus;
-
-    return *this;
-  }
+  StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other);
 
   // move constructors
   StructExprFieldWithVal (StructExprFieldWithVal &&other) = default;
@@ -1532,10 +1251,7 @@ public:
   StructExprFieldIdentifierValue (Analysis::NodeMapping mapping,
                                  Identifier field_identifier,
                                  std::unique_ptr<Expr> field_value,
-                                 location_t locus)
-    : StructExprFieldWithVal (mapping, std::move (field_value), locus),
-      field_name (std::move (field_identifier))
-  {}
+                                 location_t locus);
 
   std::string as_string () const override;
 
@@ -1569,10 +1285,7 @@ public:
   StructExprFieldIndexValue (Analysis::NodeMapping mapping,
                             TupleIndex tuple_index,
                             std::unique_ptr<Expr> field_value,
-                            location_t locus)
-    : StructExprFieldWithVal (mapping, std::move (field_value), locus),
-      index (tuple_index)
-  {}
+                            location_t locus);
 
   std::string as_string () const override;
 
@@ -1598,58 +1311,31 @@ protected:
 // HIR node of a struct creator with fields
 class StructExprStructFields : public StructExprStruct
 {
-public:
   // std::vector<StructExprField> fields;
-  std::vector<std::unique_ptr<StructExprField> > fields;
-
-  // bool has_struct_base;
-  // FIXME make unique_ptr
-  StructBase *struct_base;
+  std::vector<std::unique_ptr<StructExprField>> fields;
+  tl::optional<std::unique_ptr<StructBase>> struct_base;
 
+public:
   // For unions there is just one field, the index
   // is set when type checking
   int union_index = -1;
 
   std::string as_string () const override;
 
-  bool has_struct_base () const { return struct_base != nullptr; }
+  bool has_struct_base () const { return struct_base.has_value (); }
 
   // Constructor for StructExprStructFields when no struct base is used
   StructExprStructFields (
     Analysis::NodeMapping mappings, PathInExpression struct_path,
-    std::vector<std::unique_ptr<StructExprField> > expr_fields,
-    location_t locus, StructBase *base_struct,
-    AST::AttrVec inner_attribs = AST::AttrVec (),
-    AST::AttrVec outer_attribs = AST::AttrVec ())
-    : StructExprStruct (std::move (mappings), std::move (struct_path),
-                       std::move (inner_attribs), std::move (outer_attribs),
-                       locus),
-      fields (std::move (expr_fields)), struct_base (base_struct)
-  {}
+    std::vector<std::unique_ptr<StructExprField>> expr_fields, location_t locus,
+    tl::optional<std::unique_ptr<StructBase>> base_struct,
+    AST::AttrVec inner_attribs, AST::AttrVec outer_attribs);
 
   // copy constructor with vector clone
-  StructExprStructFields (StructExprStructFields const &other)
-    : StructExprStruct (other), struct_base (other.struct_base),
-      union_index (other.union_index)
-  {
-    fields.reserve (other.fields.size ());
-    for (const auto &e : other.fields)
-      fields.push_back (e->clone_struct_expr_field ());
-  }
+  StructExprStructFields (StructExprStructFields const &other);
 
   // overloaded assignment operator with vector clone
-  StructExprStructFields &operator= (StructExprStructFields const &other)
-  {
-    StructExprStruct::operator= (other);
-    struct_base = other.struct_base;
-    union_index = other.union_index;
-
-    fields.reserve (other.fields.size ());
-    for (const auto &e : other.fields)
-      fields.push_back (e->clone_struct_expr_field ());
-
-    return *this;
-  }
+  StructExprStructFields &operator= (StructExprStructFields const &other);
 
   // move constructors
   StructExprStructFields (StructExprStructFields &&other) = default;
@@ -1658,20 +1344,20 @@ public:
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRExpressionVisitor &vis) override;
 
-  std::vector<std::unique_ptr<StructExprField> > &get_fields ()
+  std::vector<std::unique_ptr<StructExprField>> &get_fields ()
   {
     return fields;
   };
 
-  const std::vector<std::unique_ptr<StructExprField> > &get_fields () const
+  const std::vector<std::unique_ptr<StructExprField>> &get_fields () const
   {
     return fields;
   };
 
-  StructBase *get_struct_base () { return struct_base; }
+  StructBase &get_struct_base () { return *struct_base.value (); }
 
-  void set_fields_as_owner (
-    std::vector<std::unique_ptr<StructExprField> > new_fields)
+  void
+  set_fields_as_owner (std::vector<std::unique_ptr<StructExprField>> new_fields)
   {
     fields = std::move (new_fields);
   }
@@ -1698,26 +1384,15 @@ class StructExprStructBase : public StructExprStruct
   StructBase struct_base;
 
 public:
-  std::string as_string () const override;
-
-  /*inline StructBase get_struct_base() const {
-      return struct_base;
-  }*/
-
   StructExprStructBase (Analysis::NodeMapping mappings,
                        PathInExpression struct_path, StructBase base_struct,
                        AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
-                       location_t locus)
-    : StructExprStruct (std::move (mappings), std::move (struct_path),
-                       std::move (inner_attribs), std::move (outer_attribs),
-                       locus),
-      struct_base (std::move (base_struct))
-  {}
+                       location_t locus);
 
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRExpressionVisitor &vis) override;
 
-  StructBase *get_struct_base () { return &struct_base; }
+  StructBase &get_struct_base () { return struct_base; }
 
 protected:
   /* Use covariance to implement clone function as returning this object rather
@@ -1739,45 +1414,21 @@ protected:
 class CallExpr : public ExprWithoutBlock
 {
   std::unique_ptr<Expr> function;
-  std::vector<std::unique_ptr<Expr> > params;
+  std::vector<std::unique_ptr<Expr>> params;
   location_t locus;
 
 public:
   std::string as_string () const override;
 
   CallExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> function_expr,
-           std::vector<std::unique_ptr<Expr> > function_params,
-           AST::AttrVec outer_attribs, location_t locus)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      function (std::move (function_expr)),
-      params (std::move (function_params)), locus (locus)
-  {}
+           std::vector<std::unique_ptr<Expr>> function_params,
+           AST::AttrVec outer_attribs, location_t locus);
 
   // copy constructor requires clone
-  CallExpr (CallExpr const &other)
-    : ExprWithoutBlock (other), function (other.function->clone_expr ()),
-      locus (other.locus)
-  /*, params(other.params),*/ {
-    params.reserve (other.params.size ());
-    for (const auto &e : other.params)
-      params.push_back (e->clone_expr ());
-  }
+  CallExpr (CallExpr const &other);
 
   // Overload assignment operator to clone
-  CallExpr &operator= (CallExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    function = other.function->clone_expr ();
-    locus = other.locus;
-    // params = other.params;
-    // outer_attrs = other.outer_attrs;
-
-    params.reserve (other.params.size ());
-    for (const auto &e : other.params)
-      params.push_back (e->clone_expr ());
-
-    return *this;
-  }
+  CallExpr &operator= (CallExpr const &other);
 
   // move constructors
   CallExpr (CallExpr &&other) = default;
@@ -1796,9 +1447,9 @@ public:
 
   size_t num_params () const { return params.size (); }
 
-  std::vector<std::unique_ptr<Expr> > &get_arguments () { return params; }
+  std::vector<std::unique_ptr<Expr>> &get_arguments () { return params; }
 
-  const std::vector<std::unique_ptr<Expr> > &get_arguments () const
+  const std::vector<std::unique_ptr<Expr>> &get_arguments () const
   {
     return params;
   }
@@ -1826,7 +1477,7 @@ class MethodCallExpr : public ExprWithoutBlock
 {
   std::unique_ptr<Expr> receiver;
   PathExprSegment method_name;
-  std::vector<std::unique_ptr<Expr> > params;
+  std::vector<std::unique_ptr<Expr>> params;
   location_t locus;
 
 public:
@@ -1835,40 +1486,14 @@ public:
   MethodCallExpr (Analysis::NodeMapping mappings,
                  std::unique_ptr<Expr> call_receiver,
                  PathExprSegment method_path,
-                 std::vector<std::unique_ptr<Expr> > method_params,
-                 AST::AttrVec outer_attribs, location_t locus)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      receiver (std::move (call_receiver)),
-      method_name (std::move (method_path)), params (std::move (method_params)),
-      locus (locus)
-  {}
+                 std::vector<std::unique_ptr<Expr>> method_params,
+                 AST::AttrVec outer_attribs, location_t locus);
 
   // copy constructor required due to cloning
-  MethodCallExpr (MethodCallExpr const &other)
-    : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()),
-      method_name (other.method_name), locus (other.locus)
-  /*, params(other.params),*/ {
-    params.reserve (other.params.size ());
-    for (const auto &e : other.params)
-      params.push_back (e->clone_expr ());
-  }
+  MethodCallExpr (MethodCallExpr const &other);
 
   // Overload assignment operator to clone receiver object
-  MethodCallExpr &operator= (MethodCallExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    receiver = other.receiver->clone_expr ();
-    method_name = other.method_name;
-    locus = other.locus;
-    // params = other.params;
-    // outer_attrs = other.outer_attrs;
-
-    params.reserve (other.params.size ());
-    for (const auto &e : other.params)
-      params.push_back (e->clone_expr ());
-
-    return *this;
-  }
+  MethodCallExpr &operator= (MethodCallExpr const &other);
 
   // move constructors
   MethodCallExpr (MethodCallExpr &&other) = default;
@@ -1887,9 +1512,9 @@ public:
   bool has_params () const { return !params.empty (); }
   size_t num_params () const { return params.size (); }
 
-  std::vector<std::unique_ptr<Expr> > &get_arguments () { return params; }
+  std::vector<std::unique_ptr<Expr>> &get_arguments () { return params; }
 
-  const std::vector<std::unique_ptr<Expr> > &get_arguments () const
+  const std::vector<std::unique_ptr<Expr>> &get_arguments () const
   {
     return params;
   }
@@ -1930,29 +1555,13 @@ public:
   FieldAccessExpr (Analysis::NodeMapping mappings,
                   std::unique_ptr<Expr> field_access_receiver,
                   Identifier field_name, AST::AttrVec outer_attribs,
-                  location_t locus)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      receiver (std::move (field_access_receiver)),
-      field (std::move (field_name)), locus (locus)
-  {}
+                  location_t locus);
 
   // Copy constructor required due to unique_ptr cloning
-  FieldAccessExpr (FieldAccessExpr const &other)
-    : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()),
-      field (other.field), locus (other.locus)
-  {}
+  FieldAccessExpr (FieldAccessExpr const &other);
 
   // Overload assignment operator to clone unique_ptr
-  FieldAccessExpr &operator= (FieldAccessExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    receiver = other.receiver->clone_expr ();
-    field = other.field;
-    locus = other.locus;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  FieldAccessExpr &operator= (FieldAccessExpr const &other);
 
   // move constructors
   FieldAccessExpr (FieldAccessExpr &&other) = default;
@@ -2004,42 +1613,15 @@ public:
   // Constructor for closure parameter
   ClosureParam (std::unique_ptr<Pattern> param_pattern, location_t locus,
                std::unique_ptr<Type> param_type = nullptr,
-               std::vector<AST::Attribute> outer_attrs = {})
-    : outer_attrs (std::move (outer_attrs)),
-      pattern (std::move (param_pattern)), type (std::move (param_type)),
-      locus (locus)
-  {}
+               std::vector<AST::Attribute> outer_attrs = {});
 
   // Copy constructor required due to cloning as a result of unique_ptrs
-  ClosureParam (ClosureParam const &other)
-    : pattern (other.pattern->clone_pattern ())
-  {
-    // guard to protect from null pointer dereference
-    if (other.pattern != nullptr)
-      pattern = other.pattern->clone_pattern ();
-    if (other.type != nullptr)
-      type = other.type->clone_type ();
-  }
+  ClosureParam (ClosureParam const &other);
 
   ~ClosureParam () = default;
 
   // Assignment operator must be overloaded to clone as well
-  ClosureParam &operator= (ClosureParam const &other)
-  {
-    outer_attrs = other.outer_attrs;
-
-    // guard to protect from null pointer dereference
-    if (other.pattern != nullptr)
-      pattern = other.pattern->clone_pattern ();
-    else
-      pattern = nullptr;
-    if (other.type != nullptr)
-      type = other.type->clone_type ();
-    else
-      type = nullptr;
-
-    return *this;
-  }
+  ClosureParam &operator= (ClosureParam const &other);
 
   // move constructors
   ClosureParam (ClosureParam &&other) = default;
@@ -2075,36 +1657,13 @@ public:
               std::vector<ClosureParam> closure_params,
               std::unique_ptr<Type> closure_return_type,
               std::unique_ptr<Expr> closure_expr, bool has_move,
-              AST::AttrVec outer_attribs, location_t locus)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      has_move (has_move), params (std::move (closure_params)), locus (locus),
-      return_type (std::move (closure_return_type)),
-      expr (std::move (closure_expr))
-  {}
+              AST::AttrVec outer_attribs, location_t locus);
 
   // Copy constructor requires cloning
-  ClosureExpr (ClosureExpr const &other)
-    : ExprWithoutBlock (other.get_mappings (), other.get_outer_attrs ())
-  {
-    return_type
-      = other.has_return_type () ? other.return_type->clone_type () : nullptr;
-    expr = other.expr->clone_expr ();
-    params = other.params;
-    has_move = other.has_move;
-  }
+  ClosureExpr (ClosureExpr const &other);
 
   // Overload assignment operator to clone unique_ptrs
-  ClosureExpr &operator= (ClosureExpr const &other)
-  {
-    mappings = other.mappings;
-    return_type
-      = other.has_return_type () ? other.return_type->clone_type () : nullptr;
-    expr = other.expr->clone_expr ();
-    params = other.params;
-    has_move = other.has_move;
-
-    return *this;
-  }
+  ClosureExpr &operator= (ClosureExpr const &other);
 
   // move constructors
   ClosureExpr (ClosureExpr &&other) = default;
@@ -2153,7 +1712,7 @@ class BlockExpr : public ExprWithBlock, public WithInnerAttrs
 {
   // FIXME this should be private + get/set
 public:
-  std::vector<std::unique_ptr<Stmt> > statements;
+  std::vector<std::unique_ptr<Stmt>> statements;
   std::unique_ptr<Expr> expr;
   bool tail_reachable;
   LoopLabel label;
@@ -2173,49 +1732,16 @@ public:
   bool is_tail_reachable () const { return tail_reachable; }
 
   BlockExpr (Analysis::NodeMapping mappings,
-            std::vector<std::unique_ptr<Stmt> > block_statements,
+            std::vector<std::unique_ptr<Stmt>> block_statements,
             std::unique_ptr<Expr> block_expr, bool tail_reachable,
             AST::AttrVec inner_attribs, AST::AttrVec outer_attribs,
-            LoopLabel label, location_t start_locus, location_t end_locus)
-    : ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
-      WithInnerAttrs (std::move (inner_attribs)),
-      statements (std::move (block_statements)), expr (std::move (block_expr)),
-      tail_reachable (tail_reachable), label (std::move (label)),
-      start_locus (start_locus), end_locus (end_locus)
-  {}
+            LoopLabel label, location_t start_locus, location_t end_locus);
 
   // Copy constructor with clone
-  BlockExpr (BlockExpr const &other)
-    : ExprWithBlock (other), /*statements(other.statements),*/
-      WithInnerAttrs (other.inner_attrs), label (other.label),
-      start_locus (other.start_locus), end_locus (other.end_locus)
-  {
-    // guard to protect from null pointer dereference
-    if (other.expr != nullptr)
-      expr = other.expr->clone_expr ();
-
-    statements.reserve (other.statements.size ());
-    for (const auto &e : other.statements)
-      statements.push_back (e->clone_stmt ());
-  }
+  BlockExpr (BlockExpr const &other);
 
   // Overloaded assignment operator to clone pointer
-  BlockExpr &operator= (BlockExpr const &other)
-  {
-    ExprWithBlock::operator= (other);
-    // statements = other.statements;
-    expr = other.expr->clone_expr ();
-    inner_attrs = other.inner_attrs;
-    start_locus = other.end_locus;
-    end_locus = other.end_locus;
-    // outer_attrs = other.outer_attrs;
-
-    statements.reserve (other.statements.size ());
-    for (const auto &e : other.statements)
-      statements.push_back (e->clone_stmt ());
-
-    return *this;
-  }
+  BlockExpr &operator= (BlockExpr const &other);
 
   // move constructors
   BlockExpr (BlockExpr &&other) = default;
@@ -2241,7 +1767,7 @@ public:
   bool has_final_expr () { return expr != nullptr; }
   Expr &get_final_expr () { return *expr; }
 
-  std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; }
+  std::vector<std::unique_ptr<Stmt>> &get_statements () { return statements; }
 
   ExprType get_expression_type () const final override
   {
@@ -2288,10 +1814,7 @@ public:
 
   // Constructor for a ContinueExpr with a label.
   ContinueExpr (Analysis::NodeMapping mappings, location_t locus,
-               Lifetime label, AST::AttrVec outer_attribs = AST::AttrVec ())
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      label (std::move (label)), locus (locus)
-  {}
+               Lifetime label, AST::AttrVec outer_attribs = AST::AttrVec ());
 
   location_t get_locus () const override final { return locus; }
 
@@ -2346,32 +1869,13 @@ public:
   BreakExpr (Analysis::NodeMapping mappings, location_t locus,
             Lifetime break_label,
             std::unique_ptr<Expr> expr_in_break = nullptr,
-            AST::AttrVec outer_attribs = AST::AttrVec ())
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      label (std::move (break_label)), break_expr (std::move (expr_in_break)),
-      locus (locus)
-  {}
+            AST::AttrVec outer_attribs = AST::AttrVec ());
 
   // Copy constructor defined to use clone for unique pointer
-  BreakExpr (BreakExpr const &other)
-    : ExprWithoutBlock (other), label (other.label), locus (other.locus)
-  {
-    // guard to protect from null pointer dereference
-    if (other.break_expr != nullptr)
-      break_expr = other.break_expr->clone_expr ();
-  }
+  BreakExpr (BreakExpr const &other);
 
   // Overload assignment operator to clone unique pointer
-  BreakExpr &operator= (BreakExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    label = other.label;
-    break_expr = other.break_expr->clone_expr ();
-    locus = other.locus;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  BreakExpr &operator= (BreakExpr const &other);
 
   // move constructors
   BreakExpr (BreakExpr &&other) = default;
@@ -2411,9 +1915,7 @@ class RangeExpr : public ExprWithoutBlock
 
 protected:
   // outer attributes not allowed before range expressions
-  RangeExpr (Analysis::NodeMapping mappings, location_t locus)
-    : ExprWithoutBlock (std::move (mappings), AST::AttrVec ()), locus (locus)
-  {}
+  RangeExpr (Analysis::NodeMapping mappings, location_t locus);
 
 public:
   location_t get_locus () const override final { return locus; }
@@ -2436,26 +1938,13 @@ public:
 
   RangeFromToExpr (Analysis::NodeMapping mappings,
                   std::unique_ptr<Expr> range_from,
-                  std::unique_ptr<Expr> range_to, location_t locus)
-    : RangeExpr (std::move (mappings), locus), from (std::move (range_from)),
-      to (std::move (range_to))
-  {}
+                  std::unique_ptr<Expr> range_to, location_t locus);
 
   // Copy constructor with cloning
-  RangeFromToExpr (RangeFromToExpr const &other)
-    : RangeExpr (other), from (other.from->clone_expr ()),
-      to (other.to->clone_expr ())
-  {}
+  RangeFromToExpr (RangeFromToExpr const &other);
 
   // Overload assignment operator to clone unique pointers
-  RangeFromToExpr &operator= (RangeFromToExpr const &other)
-  {
-    RangeExpr::operator= (other);
-    from = other.from->clone_expr ();
-    to = other.to->clone_expr ();
-
-    return *this;
-  }
+  RangeFromToExpr &operator= (RangeFromToExpr const &other);
 
   // move constructors
   RangeFromToExpr (RangeFromToExpr &&other) = default;
@@ -2493,23 +1982,13 @@ public:
   std::string as_string () const override;
 
   RangeFromExpr (Analysis::NodeMapping mappings,
-                std::unique_ptr<Expr> range_from, location_t locus)
-    : RangeExpr (std::move (mappings), locus), from (std::move (range_from))
-  {}
+                std::unique_ptr<Expr> range_from, location_t locus);
 
   // Copy constructor with clone
-  RangeFromExpr (RangeFromExpr const &other)
-    : RangeExpr (other), from (other.from->clone_expr ())
-  {}
+  RangeFromExpr (RangeFromExpr const &other);
 
   // Overload assignment operator to clone unique_ptr
-  RangeFromExpr &operator= (RangeFromExpr const &other)
-  {
-    RangeExpr::operator= (other);
-    from = other.from->clone_expr ();
-
-    return *this;
-  }
+  RangeFromExpr &operator= (RangeFromExpr const &other);
 
   // move constructors
   RangeFromExpr (RangeFromExpr &&other) = default;
@@ -2547,23 +2026,13 @@ public:
 
   // outer attributes not allowed
   RangeToExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> range_to,
-              location_t locus)
-    : RangeExpr (std::move (mappings), locus), to (std::move (range_to))
-  {}
+              location_t locus);
 
   // Copy constructor with clone
-  RangeToExpr (RangeToExpr const &other)
-    : RangeExpr (other), to (other.to->clone_expr ())
-  {}
+  RangeToExpr (RangeToExpr const &other);
 
   // Overload assignment operator to clone unique_ptr
-  RangeToExpr &operator= (RangeToExpr const &other)
-  {
-    RangeExpr::operator= (other);
-    to = other.to->clone_expr ();
-
-    return *this;
-  }
+  RangeToExpr &operator= (RangeToExpr const &other);
 
   // move constructors
   RangeToExpr (RangeToExpr &&other) = default;
@@ -2597,9 +2066,7 @@ class RangeFullExpr : public RangeExpr
 public:
   std::string as_string () const override;
 
-  RangeFullExpr (Analysis::NodeMapping mappings, location_t locus)
-    : RangeExpr (std::move (mappings), locus)
-  {}
+  RangeFullExpr (Analysis::NodeMapping mappings, location_t locus);
   // outer attributes not allowed
 
   void accept_vis (HIRFullVisitor &vis) override;
@@ -2633,27 +2100,14 @@ public:
 
   RangeFromToInclExpr (Analysis::NodeMapping mappings,
                       std::unique_ptr<Expr> range_from,
-                      std::unique_ptr<Expr> range_to, location_t locus)
-    : RangeExpr (std::move (mappings), locus), from (std::move (range_from)),
-      to (std::move (range_to))
-  {}
+                      std::unique_ptr<Expr> range_to, location_t locus);
   // outer attributes not allowed
 
   // Copy constructor with clone
-  RangeFromToInclExpr (RangeFromToInclExpr const &other)
-    : RangeExpr (other), from (other.from->clone_expr ()),
-      to (other.to->clone_expr ())
-  {}
+  RangeFromToInclExpr (RangeFromToInclExpr const &other);
 
   // Overload assignment operator to use clone
-  RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other)
-  {
-    RangeExpr::operator= (other);
-    from = other.from->clone_expr ();
-    to = other.to->clone_expr ();
-
-    return *this;
-  }
+  RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other);
 
   // move constructors
   RangeFromToInclExpr (RangeFromToInclExpr &&other) = default;
@@ -2691,24 +2145,14 @@ public:
   std::string as_string () const override;
 
   RangeToInclExpr (Analysis::NodeMapping mappings,
-                  std::unique_ptr<Expr> range_to, location_t locus)
-    : RangeExpr (std::move (mappings), locus), to (std::move (range_to))
-  {}
+                  std::unique_ptr<Expr> range_to, location_t locus);
   // outer attributes not allowed
 
   // Copy constructor with clone
-  RangeToInclExpr (RangeToInclExpr const &other)
-    : RangeExpr (other), to (other.to->clone_expr ())
-  {}
+  RangeToInclExpr (RangeToInclExpr const &other);
 
   // Overload assignment operator to clone pointer
-  RangeToInclExpr &operator= (RangeToInclExpr const &other)
-  {
-    RangeExpr::operator= (other);
-    to = other.to->clone_expr ();
-
-    return *this;
-  }
+  RangeToInclExpr &operator= (RangeToInclExpr const &other);
 
   // move constructors
   RangeToInclExpr (RangeToInclExpr &&other) = default;
@@ -2752,30 +2196,13 @@ public:
   // Constructor for ReturnExpr.
   ReturnExpr (Analysis::NodeMapping mappings, location_t locus,
              std::unique_ptr<Expr> returned_expr = nullptr,
-             AST::AttrVec outer_attribs = AST::AttrVec ())
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      return_expr (std::move (returned_expr)), locus (locus)
-  {}
+             AST::AttrVec outer_attribs = AST::AttrVec ());
 
   // Copy constructor with clone
-  ReturnExpr (ReturnExpr const &other)
-    : ExprWithoutBlock (other), locus (other.locus)
-  {
-    // guard to protect from null pointer dereference
-    if (other.return_expr != nullptr)
-      return_expr = other.return_expr->clone_expr ();
-  }
+  ReturnExpr (ReturnExpr const &other);
 
   // Overloaded assignment operator to clone return_expr pointer
-  ReturnExpr &operator= (ReturnExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    return_expr = other.return_expr->clone_expr ();
-    locus = other.locus;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  ReturnExpr &operator= (ReturnExpr const &other);
 
   // move constructors
   ReturnExpr (ReturnExpr &&other) = default;
@@ -2822,27 +2249,13 @@ public:
 
   UnsafeBlockExpr (Analysis::NodeMapping mappings,
                   std::unique_ptr<BlockExpr> block_expr,
-                  AST::AttrVec outer_attribs, location_t locus)
-    : ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
-      expr (std::move (block_expr)), locus (locus)
-  {}
+                  AST::AttrVec outer_attribs, location_t locus);
 
   // Copy constructor with clone
-  UnsafeBlockExpr (UnsafeBlockExpr const &other)
-    : ExprWithBlock (other), expr (other.expr->clone_block_expr ()),
-      locus (other.locus)
-  {}
+  UnsafeBlockExpr (UnsafeBlockExpr const &other);
 
   // Overloaded assignment operator to clone
-  UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other)
-  {
-    ExprWithBlock::operator= (other);
-    expr = other.expr->clone_block_expr ();
-    locus = other.locus;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other);
 
   // move constructors
   UnsafeBlockExpr (UnsafeBlockExpr &&other) = default;
@@ -2891,29 +2304,13 @@ protected:
   BaseLoopExpr (Analysis::NodeMapping mappings,
                std::unique_ptr<BlockExpr> loop_block, location_t locus,
                LoopLabel loop_label,
-               AST::AttrVec outer_attribs = AST::AttrVec ())
-    : ExprWithBlock (std::move (mappings), std::move (outer_attribs)),
-      loop_label (std::move (loop_label)), loop_block (std::move (loop_block)),
-      locus (locus)
-  {}
+               AST::AttrVec outer_attribs = AST::AttrVec ());
 
   // Copy constructor for BaseLoopExpr with clone
-  BaseLoopExpr (BaseLoopExpr const &other)
-    : ExprWithBlock (other), loop_label (other.loop_label),
-      loop_block (other.loop_block->clone_block_expr ()), locus (other.locus)
-  {}
+  BaseLoopExpr (BaseLoopExpr const &other);
 
   // Overloaded assignment operator to clone
-  BaseLoopExpr &operator= (BaseLoopExpr const &other)
-  {
-    ExprWithBlock::operator= (other);
-    loop_block = other.loop_block->clone_block_expr ();
-    loop_label = other.loop_label;
-    locus = other.locus;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  BaseLoopExpr &operator= (BaseLoopExpr const &other);
 
   // move constructors
   BaseLoopExpr (BaseLoopExpr &&other) = default;
@@ -2943,10 +2340,7 @@ public:
   // Constructor for LoopExpr
   LoopExpr (Analysis::NodeMapping mappings,
            std::unique_ptr<BlockExpr> loop_block, location_t locus,
-           LoopLabel loop_label, AST::AttrVec outer_attribs = AST::AttrVec ())
-    : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
-                   std::move (loop_label), std::move (outer_attribs))
-  {}
+           LoopLabel loop_label, AST::AttrVec outer_attribs = AST::AttrVec ());
 
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRExpressionVisitor &vis) override;
@@ -2977,28 +2371,13 @@ public:
                 std::unique_ptr<Expr> loop_condition,
                 std::unique_ptr<BlockExpr> loop_block, location_t locus,
                 LoopLabel loop_label,
-                AST::AttrVec outer_attribs = AST::AttrVec ())
-    : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
-                   std::move (loop_label), std::move (outer_attribs)),
-      condition (std::move (loop_condition))
-  {}
+                AST::AttrVec outer_attribs = AST::AttrVec ());
 
   // Copy constructor with clone
-  WhileLoopExpr (WhileLoopExpr const &other)
-    : BaseLoopExpr (other), condition (other.condition->clone_expr ())
-  {}
+  WhileLoopExpr (WhileLoopExpr const &other);
 
   // Overloaded assignment operator to clone
-  WhileLoopExpr &operator= (WhileLoopExpr const &other)
-  {
-    BaseLoopExpr::operator= (other);
-    condition = other.condition->clone_expr ();
-    // loop_block = other.loop_block->clone_block_expr();
-    // loop_label = other.loop_label;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  WhileLoopExpr &operator= (WhileLoopExpr const &other);
 
   // move constructors
   WhileLoopExpr (WhileLoopExpr &&other) = default;
@@ -3029,7 +2408,7 @@ protected:
 class WhileLetLoopExpr : public BaseLoopExpr
 {
   // MatchArmPatterns patterns;
-  std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
+  std::vector<std::unique_ptr<Pattern>> match_arm_patterns; // inlined
   std::unique_ptr<Expr> condition;
 
 public:
@@ -3037,44 +2416,17 @@ public:
 
   // Constructor with a loop label
   WhileLetLoopExpr (Analysis::NodeMapping mappings,
-                   std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
+                   std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
                    std::unique_ptr<Expr> condition,
                    std::unique_ptr<BlockExpr> loop_block, location_t locus,
                    LoopLabel loop_label,
-                   AST::AttrVec outer_attribs = AST::AttrVec ())
-    : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus,
-                   std::move (loop_label), std::move (outer_attribs)),
-      match_arm_patterns (std::move (match_arm_patterns)),
-      condition (std::move (condition))
-  {}
+                   AST::AttrVec outer_attribs = AST::AttrVec ());
 
   // Copy constructor with clone
-  WhileLetLoopExpr (WhileLetLoopExpr const &other)
-    : BaseLoopExpr (other),
-      /*match_arm_patterns(other.match_arm_patterns),*/ condition (
-       other.condition->clone_expr ())
-  {
-    match_arm_patterns.reserve (other.match_arm_patterns.size ());
-    for (const auto &e : other.match_arm_patterns)
-      match_arm_patterns.push_back (e->clone_pattern ());
-  }
+  WhileLetLoopExpr (WhileLetLoopExpr const &other);
 
   // Overloaded assignment operator to clone pointers
-  WhileLetLoopExpr &operator= (WhileLetLoopExpr const &other)
-  {
-    BaseLoopExpr::operator= (other);
-    // match_arm_patterns = other.match_arm_patterns;
-    condition = other.condition->clone_expr ();
-    // loop_block = other.loop_block->clone_block_expr();
-    // loop_label = other.loop_label;
-    // outer_attrs = other.outer_attrs;
-
-    match_arm_patterns.reserve (other.match_arm_patterns.size ());
-    for (const auto &e : other.match_arm_patterns)
-      match_arm_patterns.push_back (e->clone_pattern ());
-
-    return *this;
-  }
+  WhileLetLoopExpr &operator= (WhileLetLoopExpr const &other);
 
   // move constructors
   WhileLetLoopExpr (WhileLetLoopExpr &&other) = default;
@@ -3084,7 +2436,7 @@ public:
   void accept_vis (HIRExpressionVisitor &vis) override;
 
   Expr &get_cond () { return *condition; }
-  std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+  std::vector<std::unique_ptr<Pattern>> &get_patterns ()
   {
     return match_arm_patterns;
   }
@@ -3117,29 +2469,14 @@ public:
   std::string as_string () const override;
 
   IfExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> condition,
-         std::unique_ptr<BlockExpr> if_block, location_t locus)
-    : ExprWithBlock (std::move (mappings), AST::AttrVec ()),
-      condition (std::move (condition)), if_block (std::move (if_block)),
-      locus (locus)
-  {}
+         std::unique_ptr<BlockExpr> if_block, location_t locus);
   // outer attributes are never allowed on IfExprs
 
   // Copy constructor with clone
-  IfExpr (IfExpr const &other)
-    : ExprWithBlock (other), condition (other.condition->clone_expr ()),
-      if_block (other.if_block->clone_block_expr ()), locus (other.locus)
-  {}
+  IfExpr (IfExpr const &other);
 
   // Overloaded assignment operator to clone expressions
-  IfExpr &operator= (IfExpr const &other)
-  {
-    ExprWithBlock::operator= (other);
-    condition = other.condition->clone_expr ();
-    if_block = other.if_block->clone_block_expr ();
-    locus = other.locus;
-
-    return *this;
-  }
+  IfExpr &operator= (IfExpr const &other);
 
   // move constructors
   IfExpr (IfExpr &&other) = default;
@@ -3195,28 +2532,15 @@ public:
   IfExprConseqElse (Analysis::NodeMapping mappings,
                    std::unique_ptr<Expr> condition,
                    std::unique_ptr<BlockExpr> if_block,
-                   std::unique_ptr<ExprWithBlock> else_block, location_t locus)
-    : IfExpr (std::move (mappings), std::move (condition), std::move (if_block),
-             locus),
-      else_block (std::move (else_block))
-  {}
+                   std::unique_ptr<ExprWithBlock> else_block,
+                   location_t locus);
   // again, outer attributes not allowed
 
   // Copy constructor with clone
-  IfExprConseqElse (IfExprConseqElse const &other)
-    : IfExpr (other), else_block (other.else_block->clone_expr_with_block ())
-  {}
+  IfExprConseqElse (IfExprConseqElse const &other);
 
   // Overloaded assignment operator with cloning
-  IfExprConseqElse &operator= (IfExprConseqElse const &other)
-  {
-    IfExpr::operator= (other);
-    // condition = other.condition->clone_expr();
-    // if_block = other.if_block->clone_block_expr();
-    else_block = other.else_block->clone_expr_with_block ();
-
-    return *this;
-  }
+  IfExprConseqElse &operator= (IfExprConseqElse const &other);
 
   // move constructors
   IfExprConseqElse (IfExprConseqElse &&other) = default;
@@ -3257,7 +2581,7 @@ struct MatchArm
 {
 private:
   AST::AttrVec outer_attrs;
-  std::vector<std::unique_ptr<Pattern> > match_arm_patterns;
+  std::vector<std::unique_ptr<Pattern>> match_arm_patterns;
   std::unique_ptr<Expr> guard_expr;
   location_t locus;
 
@@ -3266,45 +2590,17 @@ public:
   bool has_match_arm_guard () const { return guard_expr != nullptr; }
 
   // Constructor for match arm with a guard expression
-  MatchArm (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
+  MatchArm (std::vector<std::unique_ptr<Pattern>> match_arm_patterns,
            location_t locus, std::unique_ptr<Expr> guard_expr = nullptr,
-           AST::AttrVec outer_attrs = AST::AttrVec ())
-    : outer_attrs (std::move (outer_attrs)),
-      match_arm_patterns (std::move (match_arm_patterns)),
-      guard_expr (std::move (guard_expr)), locus (locus)
-  {}
+           AST::AttrVec outer_attrs = AST::AttrVec ());
 
   // Copy constructor with clone
-  MatchArm (MatchArm const &other) : outer_attrs (other.outer_attrs)
-  {
-    // guard to protect from null pointer dereference
-    if (other.guard_expr != nullptr)
-      guard_expr = other.guard_expr->clone_expr ();
-
-    match_arm_patterns.reserve (other.match_arm_patterns.size ());
-    for (const auto &e : other.match_arm_patterns)
-      match_arm_patterns.push_back (e->clone_pattern ());
-
-    locus = other.locus;
-  }
+  MatchArm (MatchArm const &other);
 
   ~MatchArm () = default;
 
   // Overload assignment operator to clone
-  MatchArm &operator= (MatchArm const &other)
-  {
-    outer_attrs = other.outer_attrs;
-
-    if (other.guard_expr != nullptr)
-      guard_expr = other.guard_expr->clone_expr ();
-
-    match_arm_patterns.clear ();
-    match_arm_patterns.reserve (other.match_arm_patterns.size ());
-    for (const auto &e : other.match_arm_patterns)
-      match_arm_patterns.push_back (e->clone_pattern ());
-
-    return *this;
-  }
+  MatchArm &operator= (MatchArm const &other);
 
   // move constructors
   MatchArm (MatchArm &&other) = default;
@@ -3317,12 +2613,12 @@ public:
   static MatchArm create_error ()
   {
     location_t locus = UNDEF_LOCATION;
-    return MatchArm (std::vector<std::unique_ptr<Pattern> > (), locus);
+    return MatchArm (std::vector<std::unique_ptr<Pattern>> (), locus);
   }
 
   std::string as_string () const;
 
-  std::vector<std::unique_ptr<Pattern> > &get_patterns ()
+  std::vector<std::unique_ptr<Pattern>> &get_patterns ()
   {
     return match_arm_patterns;
   }
@@ -3343,23 +2639,11 @@ private:
 
 public:
   MatchCase (Analysis::NodeMapping mappings, MatchArm arm,
-            std::unique_ptr<Expr> expr)
-    : mappings (mappings), arm (std::move (arm)), expr (std::move (expr))
-  {}
+            std::unique_ptr<Expr> expr);
 
-  MatchCase (const MatchCase &other)
-    : mappings (other.mappings), arm (other.arm),
-      expr (other.expr->clone_expr ())
-  {}
-
-  MatchCase &operator= (const MatchCase &other)
-  {
-    mappings = other.mappings;
-    arm = other.arm;
-    expr = other.expr->clone_expr ();
+  MatchCase (const MatchCase &other);
 
-    return *this;
-  }
+  MatchCase &operator= (const MatchCase &other);
 
   MatchCase (MatchCase &&other) = default;
   MatchCase &operator= (MatchCase &&other) = default;
@@ -3388,40 +2672,13 @@ public:
 
   MatchExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> branch_value,
             std::vector<MatchCase> match_arms, AST::AttrVec inner_attrs,
-            AST::AttrVec outer_attrs, location_t locus)
-    : ExprWithBlock (std::move (mappings), std::move (outer_attrs)),
-      WithInnerAttrs (std::move (inner_attrs)),
-      branch_value (std::move (branch_value)),
-      match_arms (std::move (match_arms)), locus (locus)
-  {}
+            AST::AttrVec outer_attrs, location_t locus);
 
   // Copy constructor requires clone due to unique_ptr
-  MatchExpr (MatchExpr const &other)
-    : ExprWithBlock (other), WithInnerAttrs (other.inner_attrs),
-      branch_value (other.branch_value->clone_expr ()),
-      match_arms (other.match_arms), locus (other.locus)
-  {
-    /*match_arms.reserve (other.match_arms.size ());
-    for (const auto &e : other.match_arms)
-      match_arms.push_back (e->clone_match_case ());*/
-  }
+  MatchExpr (MatchExpr const &other);
 
   // Overloaded assignment operator to clone due to unique_ptr
-  MatchExpr &operator= (MatchExpr const &other)
-  {
-    ExprWithBlock::operator= (other);
-    branch_value = other.branch_value->clone_expr ();
-    inner_attrs = other.inner_attrs;
-    match_arms = other.match_arms;
-    // outer_attrs = other.outer_attrs;
-    locus = other.locus;
-
-    /*match_arms.reserve (other.match_arms.size ());
-    for (const auto &e : other.match_arms)
-      match_arms.push_back (e->clone_match_case ());*/
-
-    return *this;
-  }
+  MatchExpr &operator= (MatchExpr const &other);
 
   // move constructors
   MatchExpr (MatchExpr &&other) = default;
@@ -3464,26 +2721,13 @@ class AwaitExpr : public ExprWithoutBlock
 public:
   // TODO: ensure outer attributes are actually allowed
   AwaitExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> awaited_expr,
-            AST::AttrVec outer_attrs, location_t locus)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)),
-      awaited_expr (std::move (awaited_expr)), locus (locus)
-  {}
+            AST::AttrVec outer_attrs, location_t locus);
 
   // copy constructor with clone
-  AwaitExpr (AwaitExpr const &other)
-    : ExprWithoutBlock (other),
-      awaited_expr (other.awaited_expr->clone_expr ()), locus (other.locus)
-  {}
+  AwaitExpr (AwaitExpr const &other);
 
   // overloaded assignment operator with clone
-  AwaitExpr &operator= (AwaitExpr const &other)
-  {
-    ExprWithoutBlock::operator= (other);
-    awaited_expr = other.awaited_expr->clone_expr ();
-    locus = other.locus;
-
-    return *this;
-  }
+  AwaitExpr &operator= (AwaitExpr const &other);
 
   // move constructors
   AwaitExpr (AwaitExpr &&other) = default;
@@ -3522,27 +2766,13 @@ class AsyncBlockExpr : public ExprWithBlock
 public:
   AsyncBlockExpr (Analysis::NodeMapping mappings,
                  std::unique_ptr<BlockExpr> block_expr, bool has_move,
-                 AST::AttrVec outer_attrs, location_t locus)
-    : ExprWithBlock (std::move (mappings), std::move (outer_attrs)),
-      has_move (has_move), block_expr (std::move (block_expr)), locus (locus)
-  {}
+                 AST::AttrVec outer_attrs, location_t locus);
 
   // copy constructor with clone
-  AsyncBlockExpr (AsyncBlockExpr const &other)
-    : ExprWithBlock (other), has_move (other.has_move),
-      block_expr (other.block_expr->clone_block_expr ()), locus (other.locus)
-  {}
+  AsyncBlockExpr (AsyncBlockExpr const &other);
 
   // overloaded assignment operator to clone
-  AsyncBlockExpr &operator= (AsyncBlockExpr const &other)
-  {
-    ExprWithBlock::operator= (other);
-    has_move = other.has_move;
-    block_expr = other.block_expr->clone_block_expr ();
-    locus = other.locus;
-
-    return *this;
-  }
+  AsyncBlockExpr &operator= (AsyncBlockExpr const &other);
 
   // move constructors
   AsyncBlockExpr (AsyncBlockExpr &&other) = default;
@@ -3576,35 +2806,15 @@ protected:
 class OperatorExprMeta
 {
 public:
-  OperatorExprMeta (HIR::CompoundAssignmentExpr &expr)
-    : node_mappings (expr.get_mappings ()),
-      lvalue_mappings (expr.get_expr ().get_mappings ()),
-      locus (expr.get_locus ())
-  {}
+  OperatorExprMeta (HIR::CompoundAssignmentExpr &expr);
 
-  OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr)
-    : node_mappings (expr.get_mappings ()),
-      lvalue_mappings (expr.get_expr ().get_mappings ()),
-      locus (expr.get_locus ())
-  {}
+  OperatorExprMeta (HIR::ArithmeticOrLogicalExpr &expr);
 
-  OperatorExprMeta (HIR::NegationExpr &expr)
-    : node_mappings (expr.get_mappings ()),
-      lvalue_mappings (expr.get_expr ().get_mappings ()),
-      locus (expr.get_locus ())
-  {}
+  OperatorExprMeta (HIR::NegationExpr &expr);
 
-  OperatorExprMeta (HIR::DereferenceExpr &expr)
-    : node_mappings (expr.get_mappings ()),
-      lvalue_mappings (expr.get_expr ().get_mappings ()),
-      locus (expr.get_locus ())
-  {}
+  OperatorExprMeta (HIR::DereferenceExpr &expr);
 
-  OperatorExprMeta (HIR::ArrayIndexExpr &expr)
-    : node_mappings (expr.get_mappings ()),
-      lvalue_mappings (expr.get_array_expr ().get_mappings ()),
-      locus (expr.get_locus ())
-  {}
+  OperatorExprMeta (HIR::ArrayIndexExpr &expr);
 
   const Analysis::NodeMapping &get_mappings () const { return node_mappings; }
 
@@ -3679,23 +2889,12 @@ struct AnonConst
 {
   NodeId id;
   std::unique_ptr<Expr> expr;
-  AnonConst (NodeId id, std::unique_ptr<Expr> expr)
-    : id (id), expr (std::move (expr))
-  {
-    rust_assert (this->expr != nullptr);
-  }
-  AnonConst (const AnonConst &other)
-  {
-    id = other.id;
-    expr = other.expr->clone_expr ();
-  }
 
-  AnonConst operator= (const AnonConst &other)
-  {
-    id = other.id;
-    expr = other.expr->clone_expr ();
-    return *this;
-  }
+  AnonConst (NodeId id, std::unique_ptr<Expr> expr);
+
+  AnonConst (const AnonConst &other);
+
+  AnonConst operator= (const AnonConst &other);
 };
 
 class InlineAsmOperand
@@ -3707,26 +2906,11 @@ public:
     std::unique_ptr<Expr> expr;
 
     In (const tl::optional<struct AST::InlineAsmRegOrRegClass> &reg,
-       std::unique_ptr<Expr> expr)
-      : reg (reg), expr (std::move (expr))
-    {
-      rust_assert (this->expr != nullptr);
-    }
-
-    In (const struct In &other)
-    {
-      reg = other.reg;
-
-      expr = other.expr->clone_expr ();
-    }
-
-    In operator= (const struct In &other)
-    {
-      reg = other.reg;
-      expr = other.expr->clone_expr ();
-
-      return *this;
-    }
+       std::unique_ptr<Expr> expr);
+
+    In (const struct In &other);
+
+    In operator= (const struct In &other);
   };
 
   struct Out
@@ -3736,26 +2920,11 @@ public:
     std::unique_ptr<Expr> expr; // can be null
 
     Out (tl::optional<struct AST::InlineAsmRegOrRegClass> &reg, bool late,
-        std::unique_ptr<Expr> expr)
-      : reg (reg), late (late), expr (std::move (expr))
-    {
-      rust_assert (this->expr != nullptr);
-    }
-
-    Out (const struct Out &other)
-    {
-      reg = other.reg;
-      late = other.late;
-      expr = other.expr->clone_expr ();
-    }
-
-    Out operator= (const struct Out &other)
-    {
-      reg = other.reg;
-      late = other.late;
-      expr = other.expr->clone_expr ();
-      return *this;
-    }
+        std::unique_ptr<Expr> expr);
+
+    Out (const struct Out &other);
+
+    Out operator= (const struct Out &other);
   };
 
   struct InOut
@@ -3765,27 +2934,11 @@ public:
     std::unique_ptr<Expr> expr; // this can't be null
 
     InOut (tl::optional<struct AST::InlineAsmRegOrRegClass> &reg, bool late,
-          std::unique_ptr<Expr> expr)
-      : reg (reg), late (late), expr (std::move (expr))
-    {
-      rust_assert (this->expr != nullptr);
-    }
-
-    InOut (const struct InOut &other)
-    {
-      reg = other.reg;
-      late = other.late;
-      expr = other.expr->clone_expr ();
-    }
-
-    InOut operator= (const struct InOut &other)
-    {
-      reg = other.reg;
-      late = other.late;
-      expr = other.expr->clone_expr ();
-
-      return *this;
-    }
+          std::unique_ptr<Expr> expr);
+
+    InOut (const struct InOut &other);
+
+    InOut operator= (const struct InOut &other);
   };
 
   struct SplitInOut
@@ -3797,31 +2950,11 @@ public:
 
     SplitInOut (tl::optional<struct AST::InlineAsmRegOrRegClass> &reg,
                bool late, std::unique_ptr<Expr> in_expr,
-               std::unique_ptr<Expr> out_expr)
-      : reg (reg), late (late), in_expr (std::move (in_expr)),
-       out_expr (std::move (out_expr))
-    {
-      rust_assert (this->in_expr != nullptr);
-      rust_assert (this->out_expr != nullptr);
-    }
-
-    SplitInOut (const struct SplitInOut &other)
-    {
-      reg = other.reg;
-      late = other.late;
-      in_expr = other.in_expr->clone_expr ();
-      out_expr = other.out_expr->clone_expr ();
-    }
-
-    SplitInOut operator= (const struct SplitInOut &other)
-    {
-      reg = other.reg;
-      late = other.late;
-      in_expr = other.in_expr->clone_expr ();
-      out_expr = other.out_expr->clone_expr ();
-
-      return *this;
-    }
+               std::unique_ptr<Expr> out_expr);
+
+    SplitInOut (const struct SplitInOut &other);
+
+    SplitInOut operator= (const struct SplitInOut &other);
   };
 
   struct Const
@@ -3833,20 +2966,11 @@ public:
   {
     std::unique_ptr<Expr> expr;
 
-    Sym (std::unique_ptr<Expr> expr) : expr (std::move (expr))
-    {
-      rust_assert (this->expr != nullptr);
-    }
-    Sym (const struct Sym &other)
-    {
-      expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
-    }
-
-    Sym operator= (const struct Sym &other)
-    {
-      expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
-      return *this;
-    }
+    Sym (std::unique_ptr<Expr> expr);
+
+    Sym (const struct Sym &other);
+
+    Sym operator= (const struct Sym &other);
   };
 
   struct Label
@@ -3854,23 +2978,11 @@ public:
     std::string label_name;
     std::unique_ptr<Expr> expr;
 
-    Label (tl::optional<std::string> label_name, std::unique_ptr<Expr> expr)
-      : expr (std::move (expr))
-    {
-      rust_assert (this->expr != nullptr);
-      if (label_name.has_value ())
-       this->label_name = label_name.value ();
-    }
-    Label (const struct Label &other)
-    {
-      expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
-    }
-
-    Label operator= (const struct Label &other)
-    {
-      expr = std::unique_ptr<Expr> (other.expr->clone_expr ());
-      return *this;
-    }
+    Label (tl::optional<std::string> label_name, std::unique_ptr<Expr> expr);
+
+    Label (const struct Label &other);
+
+    Label operator= (const struct Label &other);
   };
 
 private:
@@ -3988,6 +3100,7 @@ public:
     // INFO: An inline asm is asm!, which is the opposite of a global_asm()
     return !this->is_global_asm;
   }
+
   InlineAsm (location_t locus, bool is_global_asm,
             std::vector<AST::InlineAsmTemplatePiece> template_,
             std::vector<AST::TupleTemplateStr> template_strs,
@@ -3995,15 +3108,7 @@ public:
             std::vector<AST::TupleClobber> clobber_abi,
             std::set<AST::InlineAsmOption> options,
             Analysis::NodeMapping mappings,
-            AST::AttrVec outer_attribs = AST::AttrVec ())
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
-      locus (locus), is_global_asm (is_global_asm),
-      template_ (std::move (template_)),
-      template_strs (std::move (template_strs)),
-      operands (std::move (operands)), clobber_abi (std::move (clobber_abi)),
-      options (std::move (options))
-
-  {}
+            AST::AttrVec outer_attribs = AST::AttrVec ());
 };
 
 } // namespace HIR
diff --git a/gcc/rust/hir/tree/rust-hir-generic-param.cc b/gcc/rust/hir/tree/rust-hir-generic-param.cc
new file mode 100644 (file)
index 0000000..e5afa8e
--- /dev/null
@@ -0,0 +1,95 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-generic-param.h"
+
+namespace Rust {
+namespace HIR {
+
+GenericParam::GenericParam (Analysis::NodeMapping mapping,
+                           enum GenericKind kind)
+  : mappings (mapping), kind (kind)
+{}
+
+LifetimeParam::LifetimeParam (Analysis::NodeMapping mappings, Lifetime lifetime,
+                             location_t locus,
+                             std::vector<Lifetime> lifetime_bounds,
+                             AST::AttrVec outer_attrs)
+  : GenericParam (mappings, GenericKind::LIFETIME),
+    lifetime (std::move (lifetime)),
+    lifetime_bounds (std::move (lifetime_bounds)),
+    outer_attrs (std::move (outer_attrs)), locus (locus)
+{}
+
+LifetimeParam::LifetimeParam (LifetimeParam const &other)
+  : GenericParam (other.mappings, GenericKind::LIFETIME),
+    lifetime (other.lifetime), lifetime_bounds (other.lifetime_bounds),
+    outer_attrs (other.outer_attrs), locus (other.locus)
+{}
+
+LifetimeParam &
+LifetimeParam::operator= (LifetimeParam const &other)
+{
+  lifetime = other.lifetime;
+  lifetime_bounds = other.lifetime_bounds;
+  outer_attrs = other.outer_attrs;
+  locus = other.locus;
+  mappings = other.mappings;
+
+  return *this;
+}
+
+ConstGenericParam::ConstGenericParam (std::string name,
+                                     std::unique_ptr<Type> type,
+                                     std::unique_ptr<Expr> default_expression,
+                                     Analysis::NodeMapping mapping,
+                                     location_t locus)
+  : GenericParam (mapping, GenericKind::CONST), name (std::move (name)),
+    type (std::move (type)),
+    default_expression (std::move (default_expression)), locus (locus)
+{}
+
+ConstGenericParam::ConstGenericParam (const ConstGenericParam &other)
+  : GenericParam (other)
+{
+  name = other.name;
+  locus = other.locus;
+
+  if (other.type)
+    type = other.type->clone_type ();
+  if (other.default_expression)
+    default_expression = other.default_expression->clone_expr ();
+}
+
+std::string
+ConstGenericParam::as_string () const
+{
+  auto result = "ConstGenericParam: " + name + " : " + type->as_string ();
+
+  if (default_expression)
+    result += " = " + default_expression->as_string ();
+
+  return result;
+}
+
+void
+ConstGenericParam::accept_vis (HIRFullVisitor &)
+{}
+
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-generic-param.h b/gcc/rust/hir/tree/rust-hir-generic-param.h
new file mode 100644 (file)
index 0000000..73b93d4
--- /dev/null
@@ -0,0 +1,186 @@
+
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_GENERIC_PARAM_H
+#define RUST_HIR_GENERIC_PARAM_H
+
+#include "rust-hir-visitable.h"
+#include "rust-hir-bound.h"
+
+namespace Rust {
+namespace HIR {
+
+/* Base generic parameter in HIR. Abstract - can be represented by a Lifetime or
+ * Type param */
+class GenericParam : public FullVisitable
+{
+public:
+  using FullVisitable::accept_vis;
+
+  virtual ~GenericParam () {}
+
+  enum class GenericKind
+  {
+    TYPE,
+    LIFETIME,
+    CONST,
+  };
+
+  virtual AST::AttrVec &get_outer_attrs () = 0;
+  virtual bool has_outer_attribute () const = 0;
+
+  // Unique pointer custom clone function
+  std::unique_ptr<GenericParam> clone_generic_param () const
+  {
+    return std::unique_ptr<GenericParam> (clone_generic_param_impl ());
+  }
+
+  virtual std::string as_string () const = 0;
+
+  virtual location_t get_locus () const = 0;
+
+  Analysis::NodeMapping get_mappings () const { return mappings; }
+
+  enum GenericKind get_kind () const { return kind; }
+
+protected:
+  // Clone function implementation as pure virtual method
+  virtual GenericParam *clone_generic_param_impl () const = 0;
+
+  Analysis::NodeMapping mappings;
+
+  enum GenericKind kind;
+
+  GenericParam (Analysis::NodeMapping mapping,
+               enum GenericKind kind = GenericKind::TYPE);
+};
+
+// A lifetime generic parameter (as opposed to a type generic parameter)
+class LifetimeParam : public GenericParam
+{
+  Lifetime lifetime;
+
+  // bool has_lifetime_bounds;
+  // LifetimeBounds lifetime_bounds;
+  std::vector<Lifetime> lifetime_bounds; // inlined LifetimeBounds
+
+  AST::AttrVec outer_attrs;
+
+  location_t locus;
+
+public:
+  Lifetime get_lifetime () { return lifetime; }
+
+  // Returns whether the lifetime param has any lifetime bounds.
+  bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); }
+
+  std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
+
+  // Returns whether the lifetime param has an outer attribute.
+  bool has_outer_attribute () const override { return outer_attrs.size () > 1; }
+
+  AST::AttrVec &get_outer_attrs () override { return outer_attrs; }
+
+  // Returns whether the lifetime param is in an error state.
+  bool is_error () const { return lifetime.is_error (); }
+
+  // Constructor
+  LifetimeParam (Analysis::NodeMapping mappings, Lifetime lifetime,
+                location_t locus = UNDEF_LOCATION,
+                std::vector<Lifetime> lifetime_bounds
+                = std::vector<Lifetime> (),
+                AST::AttrVec outer_attrs = std::vector<AST::Attribute> ());
+
+  // TODO: remove copy and assignment operator definitions - not required
+
+  // Copy constructor with clone
+  LifetimeParam (LifetimeParam const &other);
+
+  // Overloaded assignment operator to clone attribute
+  LifetimeParam &operator= (LifetimeParam const &other);
+
+  // move constructors
+  LifetimeParam (LifetimeParam &&other) = default;
+  LifetimeParam &operator= (LifetimeParam &&other) = default;
+
+  std::string as_string () const override;
+
+  void accept_vis (HIRFullVisitor &vis) override;
+
+  location_t get_locus () const override final { return locus; }
+
+protected:
+  /* Use covariance to implement clone function as returning this object rather
+   * than base */
+  LifetimeParam *clone_generic_param_impl () const override
+  {
+    return new LifetimeParam (*this);
+  }
+};
+
+class ConstGenericParam : public GenericParam
+{
+public:
+  ConstGenericParam (std::string name, std::unique_ptr<Type> type,
+                    std::unique_ptr<Expr> default_expression,
+                    Analysis::NodeMapping mapping, location_t locus);
+
+  ConstGenericParam (const ConstGenericParam &other);
+
+  bool has_outer_attribute () const override { return false; }
+
+  AST::AttrVec &get_outer_attrs () override { return outer_attrs; }
+
+  std::string as_string () const override final;
+
+  void accept_vis (HIRFullVisitor &vis) override final;
+
+  location_t get_locus () const override final { return locus; };
+
+  bool has_default_expression () { return default_expression != nullptr; }
+
+  std::string get_name () { return name; }
+  Type &get_type () { return *type; }
+  Expr &get_default_expression () { return *default_expression; }
+
+protected:
+  /* Use covariance to implement clone function as returning this object rather
+   * than base */
+  ConstGenericParam *clone_generic_param_impl () const override
+  {
+    return new ConstGenericParam (*this);
+  }
+
+private:
+  std::string name;
+  std::unique_ptr<Type> type;
+
+  /* const params have no outer attrs, should be empty */
+  AST::AttrVec outer_attrs = std::vector<AST::Attribute> ();
+
+  /* Optional - can be a null pointer if there is no default expression */
+  std::unique_ptr<Expr> default_expression;
+
+  location_t locus;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-item.cc b/gcc/rust/hir/tree/rust-hir-item.cc
new file mode 100644 (file)
index 0000000..f81f1ea
--- /dev/null
@@ -0,0 +1,1017 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-item.h"
+
+namespace Rust {
+namespace HIR {
+
+TypeParam::TypeParam (
+  Analysis::NodeMapping mappings, Identifier type_representation,
+  location_t locus,
+  std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
+  std::unique_ptr<Type>, AST::AttrVec outer_attrs)
+  : GenericParam (mappings), outer_attrs (std::move (outer_attrs)),
+    type_representation (std::move (type_representation)),
+    type_param_bounds (std::move (type_param_bounds)), type (std::move (type)),
+    locus (locus)
+{}
+
+TypeParam::TypeParam (TypeParam const &other)
+  : GenericParam (other.mappings), outer_attrs (other.outer_attrs),
+    type_representation (other.type_representation), locus (other.locus)
+{
+  // guard to prevent null pointer dereference
+  if (other.type != nullptr)
+    type = other.type->clone_type ();
+
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+}
+
+TypeParam &
+TypeParam::operator= (TypeParam const &other)
+{
+  type_representation = other.type_representation;
+  outer_attrs = other.outer_attrs;
+  locus = other.locus;
+  mappings = other.mappings;
+
+  // guard to prevent null pointer dereference
+  if (other.type != nullptr)
+    type = other.type->clone_type ();
+  else
+    type = nullptr;
+
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+
+  return *this;
+}
+
+Analysis::NodeMapping
+TypeParam::get_type_mappings () const
+{
+  rust_assert (type != nullptr);
+  return type->get_mappings ();
+}
+
+std::vector<std::unique_ptr<TypeParamBound>> &
+TypeParam::get_type_param_bounds ()
+{
+  return type_param_bounds;
+}
+
+TypeBoundWhereClauseItem::TypeBoundWhereClauseItem (
+  Analysis::NodeMapping mappings, std::vector<LifetimeParam> for_lifetimes,
+  std::unique_ptr<Type> bound_type,
+  std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
+  location_t locus)
+  : for_lifetimes (std::move (for_lifetimes)),
+    bound_type (std::move (bound_type)),
+    type_param_bounds (std::move (type_param_bounds)),
+    mappings (std::move (mappings)), locus (locus)
+{}
+
+TypeBoundWhereClauseItem::TypeBoundWhereClauseItem (
+  TypeBoundWhereClauseItem const &other)
+  : for_lifetimes (other.for_lifetimes),
+    bound_type (other.bound_type->clone_type ()), mappings (other.mappings)
+{
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+}
+
+TypeBoundWhereClauseItem &
+TypeBoundWhereClauseItem::operator= (TypeBoundWhereClauseItem const &other)
+{
+  mappings = other.mappings;
+  for_lifetimes = other.for_lifetimes;
+  bound_type = other.bound_type->clone_type ();
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+
+  return *this;
+}
+
+std::vector<std::unique_ptr<TypeParamBound>> &
+TypeBoundWhereClauseItem::get_type_param_bounds ()
+{
+  return type_param_bounds;
+}
+
+SelfParam::SelfParam (Analysis::NodeMapping mappings,
+                     ImplicitSelfKind self_kind, Lifetime lifetime, Type *type)
+  : self_kind (self_kind), lifetime (std::move (lifetime)), type (type),
+    mappings (mappings)
+{}
+
+SelfParam::SelfParam (Analysis::NodeMapping mappings,
+                     std::unique_ptr<Type> type, bool is_mut, location_t locus)
+  : self_kind (is_mut ? ImplicitSelfKind::MUT : ImplicitSelfKind::IMM),
+    lifetime (
+      Lifetime (mappings, AST::Lifetime::LifetimeType::NAMED, "", locus)),
+    type (std::move (type)), locus (locus), mappings (mappings)
+{}
+
+SelfParam::SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime,
+                     bool is_mut, location_t locus)
+  : self_kind (is_mut ? ImplicitSelfKind::MUT_REF : ImplicitSelfKind::IMM_REF),
+    lifetime (std::move (lifetime)), locus (locus), mappings (mappings)
+{}
+
+SelfParam::SelfParam (SelfParam const &other)
+  : self_kind (other.self_kind), lifetime (other.lifetime), locus (other.locus),
+    mappings (other.mappings)
+{
+  if (other.type != nullptr)
+    type = other.type->clone_type ();
+}
+
+SelfParam &
+SelfParam::operator= (SelfParam const &other)
+{
+  if (other.type != nullptr)
+    type = other.type->clone_type ();
+
+  self_kind = other.self_kind;
+  lifetime = other.lifetime;
+  locus = other.locus;
+  mappings = other.mappings;
+
+  return *this;
+}
+
+Mutability
+SelfParam::get_mut () const
+{
+  return (self_kind == ImplicitSelfKind::MUT
+         || self_kind == ImplicitSelfKind::MUT_REF)
+          ? Mutability::Mut
+          : Mutability::Imm;
+}
+
+bool
+SelfParam::is_mut () const
+{
+  return self_kind == ImplicitSelfKind::MUT
+        || self_kind == ImplicitSelfKind::MUT_REF;
+}
+
+bool
+SelfParam::is_ref () const
+{
+  return self_kind == ImplicitSelfKind::IMM_REF
+        || self_kind == ImplicitSelfKind::MUT_REF;
+}
+
+FunctionParam::FunctionParam (Analysis::NodeMapping mappings,
+                             std::unique_ptr<Pattern> param_name,
+                             std::unique_ptr<Type> param_type,
+                             location_t locus)
+  : param_name (std::move (param_name)), type (std::move (param_type)),
+    locus (locus), mappings (mappings)
+{}
+
+FunctionParam::FunctionParam (FunctionParam const &other)
+  : param_name (other.param_name->clone_pattern ()),
+    type (other.type->clone_type ()), locus (other.locus),
+    mappings (other.mappings)
+{}
+
+FunctionParam &
+FunctionParam::operator= (FunctionParam const &other)
+{
+  param_name = other.param_name->clone_pattern ();
+  type = other.type->clone_type ();
+  locus = other.locus;
+  mappings = other.mappings;
+
+  return *this;
+}
+
+VisItem &
+VisItem::operator= (VisItem const &other)
+{
+  Item::operator= (other);
+  visibility = other.visibility;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+VisItem::VisItem (VisItem const &other)
+  : Item (other), visibility (other.visibility)
+{}
+
+Module::Module (Analysis::NodeMapping mappings, Identifier module_name,
+               location_t locus, std::vector<std::unique_ptr<Item>> items,
+               Visibility visibility, AST::AttrVec inner_attrs,
+               AST::AttrVec outer_attrs)
+  : VisItem (std::move (mappings), std::move (visibility),
+            std::move (outer_attrs)),
+    WithInnerAttrs (std::move (inner_attrs)), module_name (module_name),
+    locus (locus), items (std::move (items))
+{}
+
+Module::Module (Module const &other)
+  : VisItem (other), WithInnerAttrs (other.inner_attrs), module_name ("")
+{
+  items.reserve (other.items.size ());
+  for (const auto &e : other.items)
+    items.push_back (e->clone_item ());
+}
+
+Module &
+Module::operator= (Module const &other)
+{
+  VisItem::operator= (other);
+  inner_attrs = other.inner_attrs;
+
+  items.reserve (other.items.size ());
+  for (const auto &e : other.items)
+    items.push_back (e->clone_item ());
+
+  return *this;
+}
+
+Function::Function (Analysis::NodeMapping mappings, Identifier function_name,
+                   FunctionQualifiers qualifiers,
+                   std::vector<std::unique_ptr<GenericParam>> generic_params,
+                   std::vector<FunctionParam> function_params,
+                   std::unique_ptr<Type> return_type, WhereClause where_clause,
+                   std::unique_ptr<BlockExpr> function_body, Visibility vis,
+                   AST::AttrVec outer_attrs, SelfParam self, location_t locus)
+  : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
+    qualifiers (std::move (qualifiers)),
+    function_name (std::move (function_name)),
+    generic_params (std::move (generic_params)),
+    function_params (std::move (function_params)),
+    return_type (std::move (return_type)),
+    where_clause (std::move (where_clause)),
+    function_body (std::move (function_body)), self (std::move (self)),
+    locus (locus)
+{}
+
+Function::Function (Function const &other)
+  : VisItem (other), qualifiers (other.qualifiers),
+    function_name (other.function_name),
+    function_params (other.function_params), where_clause (other.where_clause),
+    function_body (other.function_body->clone_block_expr ()), self (other.self),
+    locus (other.locus)
+{
+  // guard to prevent null dereference (always required)
+  if (other.return_type != nullptr)
+    return_type = other.return_type->clone_type ();
+  else
+    return_type = nullptr;
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+}
+
+Function &
+Function::operator= (Function const &other)
+{
+  VisItem::operator= (other);
+  function_name = other.function_name;
+  qualifiers = other.qualifiers;
+  function_params = other.function_params;
+
+  // guard to prevent null dereference (always required)
+  if (other.return_type != nullptr)
+    return_type = other.return_type->clone_type ();
+  else
+    return_type = nullptr;
+
+  where_clause = other.where_clause;
+  function_body = other.function_body->clone_block_expr ();
+  locus = other.locus;
+  self = other.self;
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  return *this;
+}
+
+TypeAlias::TypeAlias (Analysis::NodeMapping mappings, Identifier new_type_name,
+                     std::vector<std::unique_ptr<GenericParam>> generic_params,
+                     WhereClause where_clause,
+                     std::unique_ptr<Type> existing_type, Visibility vis,
+                     AST::AttrVec outer_attrs, location_t locus)
+  : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
+    new_type_name (std::move (new_type_name)),
+    generic_params (std::move (generic_params)),
+    where_clause (std::move (where_clause)),
+    existing_type (std::move (existing_type)), locus (locus)
+{}
+
+TypeAlias::TypeAlias (TypeAlias const &other)
+  : VisItem (other), new_type_name (other.new_type_name),
+    where_clause (other.where_clause),
+    existing_type (other.existing_type->clone_type ()), locus (other.locus)
+{
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+}
+
+TypeAlias &
+TypeAlias::operator= (TypeAlias const &other)
+{
+  VisItem::operator= (other);
+  new_type_name = other.new_type_name;
+  where_clause = other.where_clause;
+  existing_type = other.existing_type->clone_type ();
+  locus = other.locus;
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  return *this;
+}
+
+StructField::StructField (Analysis::NodeMapping mappings, Identifier field_name,
+                         std::unique_ptr<Type> field_type, Visibility vis,
+                         location_t locus, AST::AttrVec outer_attrs)
+  : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
+    field_name (std::move (field_name)), field_type (std::move (field_type)),
+    mappings (mappings), locus (locus)
+{}
+
+StructField::StructField (StructField const &other)
+  : outer_attrs (other.outer_attrs), visibility (other.visibility),
+    field_name (other.field_name), field_type (other.field_type->clone_type ()),
+    mappings (other.mappings)
+{}
+
+StructField &
+StructField::operator= (StructField const &other)
+{
+  field_name = other.field_name;
+  field_type = other.field_type->clone_type ();
+  visibility = other.visibility;
+  outer_attrs = other.outer_attrs;
+  mappings = other.mappings;
+
+  return *this;
+}
+
+TupleField::TupleField (Analysis::NodeMapping mapping,
+                       std::unique_ptr<Type> field_type, Visibility vis,
+                       location_t locus, AST::AttrVec outer_attrs)
+  : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
+    field_type (std::move (field_type)), locus (locus), mappings (mapping)
+{}
+
+TupleField::TupleField (TupleField const &other)
+  : outer_attrs (other.outer_attrs), visibility (other.visibility),
+    field_type (other.field_type->clone_type ()), locus (other.locus),
+    mappings (other.mappings)
+{}
+
+TupleField &
+TupleField::operator= (TupleField const &other)
+{
+  field_type = other.field_type->clone_type ();
+  visibility = other.visibility;
+  outer_attrs = other.outer_attrs;
+  locus = other.locus;
+  mappings = other.mappings;
+
+  return *this;
+}
+
+TupleStruct::TupleStruct (
+  Analysis::NodeMapping mappings, std::vector<TupleField> fields,
+  Identifier struct_name,
+  std::vector<std::unique_ptr<GenericParam>> generic_params,
+  WhereClause where_clause, Visibility vis, AST::AttrVec outer_attrs,
+  location_t locus)
+  : Struct (std::move (mappings), std::move (struct_name),
+           std::move (generic_params), std::move (where_clause),
+           std::move (vis), locus, std::move (outer_attrs)),
+    fields (std::move (fields))
+{}
+
+EnumItem::EnumItem (Analysis::NodeMapping mappings, Identifier variant_name,
+                   AST::AttrVec outer_attrs, location_t locus)
+  : Item (std::move (mappings), std::move (outer_attrs)),
+    variant_name (std::move (variant_name)), locus (locus)
+{}
+
+EnumItemTuple::EnumItemTuple (Analysis::NodeMapping mappings,
+                             Identifier variant_name,
+                             std::vector<TupleField> tuple_fields,
+                             AST::AttrVec outer_attrs, location_t locus)
+  : EnumItem (std::move (mappings), std::move (variant_name),
+             std::move (outer_attrs), locus),
+    tuple_fields (std::move (tuple_fields))
+{}
+
+EnumItemStruct::EnumItemStruct (Analysis::NodeMapping mappings,
+                               Identifier variant_name,
+                               std::vector<StructField> struct_fields,
+                               AST::AttrVec outer_attrs, location_t locus)
+  : EnumItem (std::move (mappings), std::move (variant_name),
+             std::move (outer_attrs), locus),
+    struct_fields (std::move (struct_fields))
+{}
+
+EnumItemDiscriminant::EnumItemDiscriminant (Analysis::NodeMapping mappings,
+                                           Identifier variant_name,
+                                           std::unique_ptr<Expr> expr,
+                                           AST::AttrVec outer_attrs,
+                                           location_t locus)
+  : EnumItem (std::move (mappings), std::move (variant_name),
+             std::move (outer_attrs), locus),
+    expression (std::move (expr))
+{}
+
+EnumItemDiscriminant::EnumItemDiscriminant (EnumItemDiscriminant const &other)
+  : EnumItem (other), expression (other.expression->clone_expr ())
+{}
+
+EnumItemDiscriminant &
+EnumItemDiscriminant::operator= (EnumItemDiscriminant const &other)
+{
+  EnumItem::operator= (other);
+  expression = other.expression->clone_expr ();
+  // variant_name = other.variant_name;
+  // outer_attrs = other.outer_attrs;
+
+  return *this;
+}
+
+Enum::Enum (Analysis::NodeMapping mappings, Identifier enum_name,
+           Visibility vis,
+           std::vector<std::unique_ptr<GenericParam>> generic_params,
+           WhereClause where_clause,
+           std::vector<std::unique_ptr<EnumItem>> items,
+           AST::AttrVec outer_attrs, location_t locus)
+  : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
+    enum_name (std::move (enum_name)),
+    generic_params (std::move (generic_params)),
+    where_clause (std::move (where_clause)), items (std::move (items)),
+    locus (locus)
+{}
+
+Enum::Enum (Enum const &other)
+  : VisItem (other), enum_name (other.enum_name),
+    where_clause (other.where_clause), locus (other.locus)
+{
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  items.reserve (other.items.size ());
+  for (const auto &e : other.items)
+    items.push_back (e->clone_enum_item ());
+}
+
+Enum &
+Enum::operator= (Enum const &other)
+{
+  VisItem::operator= (other);
+  enum_name = other.enum_name;
+  where_clause = other.where_clause;
+  locus = other.locus;
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  items.reserve (other.items.size ());
+  for (const auto &e : other.items)
+    items.push_back (e->clone_enum_item ());
+
+  return *this;
+}
+
+Union::Union (Analysis::NodeMapping mappings, Identifier union_name,
+             Visibility vis,
+             std::vector<std::unique_ptr<GenericParam>> generic_params,
+             WhereClause where_clause, std::vector<StructField> variants,
+             AST::AttrVec outer_attrs, location_t locus)
+  : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
+    union_name (std::move (union_name)),
+    generic_params (std::move (generic_params)),
+    where_clause (std::move (where_clause)), variants (std::move (variants)),
+    locus (locus)
+{}
+
+Union::Union (Union const &other)
+  : VisItem (other), union_name (other.union_name),
+    where_clause (other.where_clause), variants (other.variants),
+    locus (other.locus)
+{
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+}
+
+Union &
+Union::operator= (Union const &other)
+{
+  VisItem::operator= (other);
+  union_name = other.union_name;
+  where_clause = other.where_clause;
+  variants = other.variants;
+  locus = other.locus;
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  return *this;
+}
+
+ConstantItem::ConstantItem (Analysis::NodeMapping mappings, Identifier ident,
+                           Visibility vis, std::unique_ptr<Type> type,
+                           std::unique_ptr<Expr> const_expr,
+                           AST::AttrVec outer_attrs, location_t locus)
+  : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
+    identifier (std::move (ident)), type (std::move (type)),
+    const_expr (std::move (const_expr)), locus (locus)
+{}
+
+ConstantItem::ConstantItem (ConstantItem const &other)
+  : VisItem (other), identifier (other.identifier),
+    type (other.type->clone_type ()),
+    const_expr (other.const_expr->clone_expr ()), locus (other.locus)
+{}
+
+ConstantItem &
+ConstantItem::operator= (ConstantItem const &other)
+{
+  VisItem::operator= (other);
+  identifier = other.identifier;
+  type = other.type->clone_type ();
+  const_expr = other.const_expr->clone_expr ();
+  locus = other.locus;
+
+  return *this;
+}
+
+StaticItem::StaticItem (Analysis::NodeMapping mappings, Identifier name,
+                       Mutability mut, std::unique_ptr<Type> type,
+                       std::unique_ptr<Expr> expr, Visibility vis,
+                       AST::AttrVec outer_attrs, location_t locus)
+  : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
+    mut (mut), name (std::move (name)), type (std::move (type)),
+    expr (std::move (expr)), locus (locus)
+{}
+
+StaticItem::StaticItem (StaticItem const &other)
+  : VisItem (other), mut (other.mut), name (other.name),
+    type (other.type->clone_type ()), expr (other.expr->clone_expr ()),
+    locus (other.locus)
+{}
+
+StaticItem &
+StaticItem::operator= (StaticItem const &other)
+{
+  VisItem::operator= (other);
+  name = other.name;
+  mut = other.mut;
+  type = other.type->clone_type ();
+  expr = other.expr->clone_expr ();
+  locus = other.locus;
+
+  return *this;
+}
+
+TraitFunctionDecl::TraitFunctionDecl (
+  Identifier function_name, FunctionQualifiers qualifiers,
+  std::vector<std::unique_ptr<GenericParam>> generic_params, SelfParam self,
+  std::vector<FunctionParam> function_params, std::unique_ptr<Type> return_type,
+  WhereClause where_clause)
+  : qualifiers (std::move (qualifiers)),
+    function_name (std::move (function_name)),
+    generic_params (std::move (generic_params)),
+    function_params (std::move (function_params)),
+    return_type (std::move (return_type)),
+    where_clause (std::move (where_clause)), self (std::move (self))
+{}
+
+TraitFunctionDecl::TraitFunctionDecl (TraitFunctionDecl const &other)
+  : qualifiers (other.qualifiers), function_name (other.function_name),
+    function_params (other.function_params),
+    return_type (other.return_type->clone_type ()),
+    where_clause (other.where_clause), self (other.self)
+{
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+}
+
+TraitFunctionDecl &
+TraitFunctionDecl::operator= (TraitFunctionDecl const &other)
+{
+  function_name = other.function_name;
+  qualifiers = other.qualifiers;
+  function_params = other.function_params;
+  return_type = other.return_type->clone_type ();
+  where_clause = other.where_clause;
+  self = other.self;
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  return *this;
+}
+
+TraitItemFunc::TraitItemFunc (Analysis::NodeMapping mappings,
+                             TraitFunctionDecl decl,
+                             std::unique_ptr<BlockExpr> block_expr,
+                             AST::AttrVec outer_attrs, location_t locus)
+  : TraitItem (mappings), outer_attrs (std::move (outer_attrs)),
+    decl (std::move (decl)), block_expr (std::move (block_expr)), locus (locus)
+{}
+
+TraitItemFunc::TraitItemFunc (TraitItemFunc const &other)
+  : TraitItem (other.mappings), outer_attrs (other.outer_attrs),
+    decl (other.decl), locus (other.locus)
+{
+  if (other.block_expr != nullptr)
+    block_expr = other.block_expr->clone_block_expr ();
+}
+
+TraitItemFunc &
+TraitItemFunc::operator= (TraitItemFunc const &other)
+{
+  TraitItem::operator= (other);
+  outer_attrs = other.outer_attrs;
+  decl = other.decl;
+  locus = other.locus;
+  mappings = other.mappings;
+  if (other.block_expr != nullptr)
+    block_expr = other.block_expr->clone_block_expr ();
+
+  return *this;
+}
+
+TraitItemConst::TraitItemConst (Analysis::NodeMapping mappings, Identifier name,
+                               std::unique_ptr<Type> type,
+                               std::unique_ptr<Expr> expr,
+                               AST::AttrVec outer_attrs, location_t locus)
+  : TraitItem (mappings), outer_attrs (std::move (outer_attrs)),
+    name (std::move (name)), type (std::move (type)), expr (std::move (expr)),
+    locus (locus)
+{}
+
+TraitItemConst::TraitItemConst (TraitItemConst const &other)
+  : TraitItem (other.mappings), outer_attrs (other.outer_attrs),
+    name (other.name), type (other.type->clone_type ()),
+    expr (other.expr->clone_expr ()), locus (other.locus)
+{}
+
+TraitItemConst &
+TraitItemConst::operator= (TraitItemConst const &other)
+{
+  TraitItem::operator= (other);
+  outer_attrs = other.outer_attrs;
+  name = other.name;
+  type = other.type->clone_type ();
+  expr = other.expr->clone_expr ();
+  locus = other.locus;
+  mappings = other.mappings;
+
+  return *this;
+}
+
+TraitItemType::TraitItemType (
+  Analysis::NodeMapping mappings, Identifier name,
+  std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
+  AST::AttrVec outer_attrs, location_t locus)
+  : TraitItem (mappings), outer_attrs (std::move (outer_attrs)),
+    name (std::move (name)), type_param_bounds (std::move (type_param_bounds)),
+    locus (locus)
+{}
+
+TraitItemType::TraitItemType (TraitItemType const &other)
+  : TraitItem (other.mappings), outer_attrs (other.outer_attrs),
+    name (other.name), locus (other.locus)
+{
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+}
+
+TraitItemType &
+TraitItemType::operator= (TraitItemType const &other)
+{
+  TraitItem::operator= (other);
+  outer_attrs = other.outer_attrs;
+  name = other.name;
+  locus = other.locus;
+  mappings = other.mappings;
+
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+
+  return *this;
+}
+
+Trait::Trait (Analysis::NodeMapping mappings, Identifier name,
+             Unsafety unsafety,
+             std::vector<std::unique_ptr<GenericParam>> generic_params,
+             std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
+             WhereClause where_clause,
+             std::vector<std::unique_ptr<TraitItem>> trait_items,
+             Visibility vis, AST::AttrVec outer_attrs, location_t locus)
+  : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
+    unsafety (unsafety), name (std::move (name)),
+    generic_params (std::move (generic_params)),
+    type_param_bounds (std::move (type_param_bounds)),
+    where_clause (std::move (where_clause)),
+    trait_items (std::move (trait_items)), locus (locus)
+{}
+
+Trait::Trait (Trait const &other)
+  : VisItem (other), unsafety (other.unsafety), name (other.name),
+    where_clause (other.where_clause), locus (other.locus)
+{
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+
+  trait_items.reserve (other.trait_items.size ());
+  for (const auto &e : other.trait_items)
+    trait_items.push_back (e->clone_trait_item ());
+}
+
+Trait &
+Trait::operator= (Trait const &other)
+{
+  VisItem::operator= (other);
+  name = other.name;
+  unsafety = other.unsafety;
+  where_clause = other.where_clause;
+  locus = other.locus;
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+
+  trait_items.reserve (other.trait_items.size ());
+  for (const auto &e : other.trait_items)
+    trait_items.push_back (e->clone_trait_item ());
+
+  return *this;
+}
+
+ImplBlock::ImplBlock (Analysis::NodeMapping mappings,
+                     std::vector<std::unique_ptr<ImplItem>> impl_items,
+                     std::vector<std::unique_ptr<GenericParam>> generic_params,
+                     std::unique_ptr<Type> impl_type,
+                     std::unique_ptr<TypePath> trait_ref,
+                     WhereClause where_clause, BoundPolarity polarity,
+                     Visibility vis, AST::AttrVec inner_attrs,
+                     AST::AttrVec outer_attrs, location_t locus, bool unsafe)
+  : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
+    WithInnerAttrs (std::move (inner_attrs)),
+    generic_params (std::move (generic_params)),
+    impl_type (std::move (impl_type)), trait_ref (std::move (trait_ref)),
+    where_clause (std::move (where_clause)), polarity (polarity), locus (locus),
+    impl_items (std::move (impl_items)), unsafe (unsafe)
+{}
+
+ImplBlock::ImplBlock (ImplBlock const &other)
+  : VisItem (other), WithInnerAttrs (other.inner_attrs),
+    impl_type (other.impl_type->clone_type ()),
+    where_clause (other.where_clause), polarity (other.polarity),
+    locus (other.locus), unsafe (other.unsafe)
+{
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  impl_items.reserve (other.impl_items.size ());
+  for (const auto &e : other.impl_items)
+    impl_items.push_back (e->clone_inherent_impl_item ());
+}
+
+ImplBlock &
+ImplBlock::operator= (ImplBlock const &other)
+{
+  VisItem::operator= (other);
+  impl_type = other.impl_type->clone_type ();
+  where_clause = other.where_clause;
+  polarity = other.polarity;
+  inner_attrs = other.inner_attrs;
+  locus = other.locus;
+  unsafe = other.unsafe;
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  impl_items.reserve (other.impl_items.size ());
+  for (const auto &e : other.impl_items)
+    impl_items.push_back (e->clone_inherent_impl_item ());
+
+  return *this;
+}
+
+ExternalItem::ExternalItem (Analysis::NodeMapping mappings,
+                           Identifier item_name, Visibility vis,
+                           AST::AttrVec outer_attrs, location_t locus)
+  : mappings (mappings), outer_attrs (std::move (outer_attrs)),
+    visibility (std::move (vis)), item_name (std::move (item_name)),
+    locus (locus)
+{}
+
+ExternalItem::ExternalItem (ExternalItem const &other)
+  : mappings (other.mappings), outer_attrs (other.outer_attrs),
+    visibility (other.visibility), item_name (other.item_name),
+    locus (other.locus)
+{}
+
+ExternalItem &
+ExternalItem::operator= (ExternalItem const &other)
+{
+  mappings = other.mappings;
+  item_name = other.item_name;
+  visibility = other.visibility;
+  outer_attrs = other.outer_attrs;
+  locus = other.locus;
+
+  return *this;
+}
+
+ExternalStaticItem::ExternalStaticItem (Analysis::NodeMapping mappings,
+                                       Identifier item_name,
+                                       std::unique_ptr<Type> item_type,
+                                       Mutability mut, Visibility vis,
+                                       AST::AttrVec outer_attrs,
+                                       location_t locus)
+  : ExternalItem (std::move (mappings), std::move (item_name), std::move (vis),
+                 std::move (outer_attrs), locus),
+    mut (mut), item_type (std::move (item_type))
+{}
+
+ExternalStaticItem::ExternalStaticItem (ExternalStaticItem const &other)
+  : ExternalItem (other), mut (other.mut),
+    item_type (other.item_type->clone_type ())
+{}
+
+ExternalStaticItem &
+ExternalStaticItem::operator= (ExternalStaticItem const &other)
+{
+  ExternalItem::operator= (other);
+  item_type = other.item_type->clone_type ();
+  mut = other.mut;
+
+  return *this;
+}
+
+NamedFunctionParam::NamedFunctionParam (Analysis::NodeMapping mappings,
+                                       Identifier name,
+                                       std::unique_ptr<Type> param_type)
+  : name (std::move (name)), param_type (std::move (param_type)),
+    mappings (std::move (mappings))
+{}
+
+NamedFunctionParam::NamedFunctionParam (NamedFunctionParam const &other)
+  : name (other.name), param_type (other.param_type->clone_type ()),
+    mappings (other.mappings)
+{}
+
+NamedFunctionParam &
+NamedFunctionParam::operator= (NamedFunctionParam const &other)
+{
+  mappings = other.mappings;
+  name = other.name;
+  param_type = other.param_type->clone_type ();
+  // has_name = other.has_name;
+
+  return *this;
+}
+
+ExternalFunctionItem::ExternalFunctionItem (
+  Analysis::NodeMapping mappings, Identifier item_name,
+  std::vector<std::unique_ptr<GenericParam>> generic_params,
+  std::unique_ptr<Type> return_type, WhereClause where_clause,
+  std::vector<NamedFunctionParam> function_params, bool has_variadics,
+  Visibility vis, AST::AttrVec outer_attrs, location_t locus)
+  : ExternalItem (std::move (mappings), std::move (item_name), std::move (vis),
+                 std::move (outer_attrs), locus),
+    generic_params (std::move (generic_params)),
+    return_type (std::move (return_type)),
+    where_clause (std::move (where_clause)),
+    function_params (std::move (function_params)), has_variadics (has_variadics)
+{}
+
+ExternalFunctionItem::ExternalFunctionItem (ExternalFunctionItem const &other)
+  : ExternalItem (other), where_clause (other.where_clause),
+    function_params (other.function_params), has_variadics (other.has_variadics)
+{
+  if (other.return_type)
+    return_type = other.return_type->clone_type ();
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+}
+
+ExternalFunctionItem &
+ExternalFunctionItem::operator= (ExternalFunctionItem const &other)
+{
+  ExternalItem::operator= (other);
+
+  where_clause = other.where_clause;
+  function_params = other.function_params;
+  has_variadics = other.has_variadics;
+
+  if (other.return_type)
+    return_type = other.return_type->clone_type ();
+
+  generic_params.reserve (other.generic_params.size ());
+  for (const auto &e : other.generic_params)
+    generic_params.push_back (e->clone_generic_param ());
+
+  return *this;
+}
+
+ExternalTypeItem::ExternalTypeItem (Analysis::NodeMapping mappings,
+                                   Identifier item_name, Visibility vis,
+                                   location_t locus)
+  : ExternalItem (std::move (mappings), std::move (item_name),
+                 Visibility (std::move (vis)),
+                 /* FIXME: Is that correct? */
+                 {}, locus)
+{}
+
+ExternalTypeItem::ExternalTypeItem (ExternalTypeItem const &other)
+  : ExternalItem (other)
+{}
+
+ExternBlock::ExternBlock (
+  Analysis::NodeMapping mappings, ABI abi,
+  std::vector<std::unique_ptr<ExternalItem>> extern_items, Visibility vis,
+  AST::AttrVec inner_attrs, AST::AttrVec outer_attrs, location_t locus)
+  : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
+    WithInnerAttrs (std::move (inner_attrs)), abi (abi),
+    extern_items (std::move (extern_items)), locus (locus)
+{}
+
+ExternBlock::ExternBlock (ExternBlock const &other)
+  : VisItem (other), WithInnerAttrs (other.inner_attrs), abi (other.abi),
+    locus (other.locus)
+{
+  extern_items.reserve (other.extern_items.size ());
+  for (const auto &e : other.extern_items)
+    extern_items.push_back (e->clone_external_item ());
+}
+
+ExternBlock &
+ExternBlock::operator= (ExternBlock const &other)
+{
+  VisItem::operator= (other);
+  abi = other.abi;
+  inner_attrs = other.inner_attrs;
+  locus = other.locus;
+
+  extern_items.reserve (other.extern_items.size ());
+  for (const auto &e : other.extern_items)
+    extern_items.push_back (e->clone_external_item ());
+
+  return *this;
+}
+
+} // namespace HIR
+} // namespace Rust
index 7001466ade6c48efe8c7b3fbb5c238e7dd61f4e0..39097ceacae761c30497f196ccb5b8b2e7ba9dd3 100644 (file)
 #define RUST_HIR_ITEM_H
 
 #include "rust-abi.h"
-#include "rust-ast-full-decls.h"
+#include "rust-hir-stmt.h"
 #include "rust-common.h"
-#include "rust-hir-expr.h"
-#include "rust-hir.h"
-#include "rust-hir-path.h"
+#include "rust-hir-visibility.h"
+#include "rust-hir-generic-param.h"
 
 namespace Rust {
 namespace HIR {
-// forward decls
-class BlockExpr;
-class TypePath;
+
+// Rust "item" HIR node (declaration of top-level/module-level allowed stuff)
+class Item : public Stmt, public WithOuterAttrs
+{
+  // TODO: should outer attrs be defined here or in each derived class?
+public:
+  enum class ItemKind
+  {
+    Static,
+    Constant,
+    TypeAlias,
+    Function,
+    UseDeclaration,
+    ExternBlock,
+    ExternCrate,
+    Struct,
+    Union,
+    Enum,
+    EnumItem, // FIXME: ARTHUR: Do we need that?
+    Trait,
+    Impl,
+    Module,
+  };
+
+  static std::string item_kind_string (ItemKind kind);
+
+  virtual ItemKind get_item_kind () const = 0;
+
+  // Unique pointer custom clone function
+  std::unique_ptr<Item> clone_item () const
+  {
+    return std::unique_ptr<Item> (clone_item_impl ());
+  }
+
+  BaseKind get_hir_kind () override { return Node::BaseKind::ITEM; }
+
+  std::string as_string () const override;
+
+  /* Adds crate names to the vector passed by reference, if it can
+   * (polymorphism). */
+  virtual void
+  add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const
+  {}
+
+  bool is_item () const override final { return true; }
+
+protected:
+  // Constructor
+  Item (Analysis::NodeMapping mappings,
+       AST::AttrVec outer_attribs = AST::AttrVec ())
+    : Stmt (std::move (mappings)), WithOuterAttrs (std::move (outer_attribs))
+  {}
+
+  // Clone function implementation as pure virtual method
+  virtual Item *clone_item_impl () const = 0;
+
+  /* Save having to specify two clone methods in derived classes by making
+   * statement clone return item clone. Hopefully won't affect performance too
+   * much. */
+  Item *clone_stmt_impl () const override { return clone_item_impl (); }
+};
 
 // A type generic parameter (as opposed to a lifetime generic parameter)
 class TypeParam : public GenericParam
@@ -65,47 +122,13 @@ public:
             std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
             = std::vector<std::unique_ptr<TypeParamBound>> (),
             std::unique_ptr<Type> type = nullptr,
-            AST::AttrVec outer_attrs = std::vector<AST::Attribute> ())
-    : GenericParam (mappings), outer_attrs (std::move (outer_attrs)),
-      type_representation (std::move (type_representation)),
-      type_param_bounds (std::move (type_param_bounds)),
-      type (std::move (type)), locus (locus)
-  {}
+            AST::AttrVec outer_attrs = std::vector<AST::Attribute> ());
 
   // Copy constructor uses clone
-  TypeParam (TypeParam const &other)
-    : GenericParam (other.mappings), outer_attrs (other.outer_attrs),
-      type_representation (other.type_representation), locus (other.locus)
-  {
-    // guard to prevent null pointer dereference
-    if (other.type != nullptr)
-      type = other.type->clone_type ();
-
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-  }
+  TypeParam (TypeParam const &other);
 
   // Overloaded assignment operator to clone
-  TypeParam &operator= (TypeParam const &other)
-  {
-    type_representation = other.type_representation;
-    outer_attrs = other.outer_attrs;
-    locus = other.locus;
-    mappings = other.mappings;
-
-    // guard to prevent null pointer dereference
-    if (other.type != nullptr)
-      type = other.type->clone_type ();
-    else
-      type = nullptr;
-
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-
-    return *this;
-  }
+  TypeParam &operator= (TypeParam const &other);
   // move constructors
   TypeParam (TypeParam &&other) = default;
   TypeParam &operator= (TypeParam &&other) = default;
@@ -120,16 +143,9 @@ public:
 
   Type &get_type () { return *type; }
 
-  Analysis::NodeMapping get_type_mappings () const
-  {
-    rust_assert (type != nullptr);
-    return type->get_mappings ();
-  }
+  Analysis::NodeMapping get_type_mappings () const;
 
-  std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
-  {
-    return type_param_bounds;
-  }
+  std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ();
 
 protected:
   // Clone function implementation as (not pure) virtual method
@@ -234,35 +250,13 @@ public:
     Analysis::NodeMapping mappings, std::vector<LifetimeParam> for_lifetimes,
     std::unique_ptr<Type> bound_type,
     std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
-    location_t locus)
-    : for_lifetimes (std::move (for_lifetimes)),
-      bound_type (std::move (bound_type)),
-      type_param_bounds (std::move (type_param_bounds)),
-      mappings (std::move (mappings)), locus (locus)
-  {}
+    location_t locus);
 
   // Copy constructor requires clone
-  TypeBoundWhereClauseItem (TypeBoundWhereClauseItem const &other)
-    : for_lifetimes (other.for_lifetimes),
-      bound_type (other.bound_type->clone_type ()), mappings (other.mappings)
-  {
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-  }
+  TypeBoundWhereClauseItem (TypeBoundWhereClauseItem const &other);
 
   // Overload assignment operator to clone
-  TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem const &other)
-  {
-    mappings = other.mappings;
-    for_lifetimes = other.for_lifetimes;
-    bound_type = other.bound_type->clone_type ();
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-
-    return *this;
-  }
+  TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem const &other);
 
   // move constructors
   TypeBoundWhereClauseItem (TypeBoundWhereClauseItem &&other) = default;
@@ -279,10 +273,7 @@ public:
 
   Type &get_bound_type () { return *bound_type; }
 
-  std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ()
-  {
-    return type_param_bounds;
-  }
+  std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds ();
 
   Analysis::NodeMapping get_mappings () const override final
   {
@@ -379,51 +370,22 @@ private:
   Analysis::NodeMapping mappings;
 
   SelfParam (Analysis::NodeMapping mappings, ImplicitSelfKind self_kind,
-            Lifetime lifetime, Type *type)
-    : self_kind (self_kind), lifetime (std::move (lifetime)), type (type),
-      mappings (mappings)
-  {}
+            Lifetime lifetime, Type *type);
 
 public:
   // Type-based self parameter (not ref, no lifetime)
   SelfParam (Analysis::NodeMapping mappings, std::unique_ptr<Type> type,
-            bool is_mut, location_t locus)
-    : self_kind (is_mut ? ImplicitSelfKind::MUT : ImplicitSelfKind::IMM),
-      lifetime (
-       Lifetime (mappings, AST::Lifetime::LifetimeType::NAMED, "", locus)),
-      type (std::move (type)), locus (locus), mappings (mappings)
-  {}
+            bool is_mut, location_t locus);
 
   // Lifetime-based self parameter (is ref, no type)
   SelfParam (Analysis::NodeMapping mappings, Lifetime lifetime, bool is_mut,
-            location_t locus)
-    : self_kind (is_mut ? ImplicitSelfKind::MUT_REF
-                       : ImplicitSelfKind::IMM_REF),
-      lifetime (std::move (lifetime)), locus (locus), mappings (mappings)
-  {}
+            location_t locus);
 
   // Copy constructor requires clone
-  SelfParam (SelfParam const &other)
-    : self_kind (other.self_kind), lifetime (other.lifetime),
-      locus (other.locus), mappings (other.mappings)
-  {
-    if (other.type != nullptr)
-      type = other.type->clone_type ();
-  }
+  SelfParam (SelfParam const &other);
 
   // Overload assignment operator to use clone
-  SelfParam &operator= (SelfParam const &other)
-  {
-    if (other.type != nullptr)
-      type = other.type->clone_type ();
-
-    self_kind = other.self_kind;
-    lifetime = other.lifetime;
-    locus = other.locus;
-    mappings = other.mappings;
-
-    return *this;
-  }
+  SelfParam &operator= (SelfParam const &other);
 
   // move constructors
   SelfParam (SelfParam &&other) = default;
@@ -456,25 +418,11 @@ public:
 
   Analysis::NodeMapping get_mappings () { return mappings; }
 
-  Mutability get_mut () const
-  {
-    return (self_kind == ImplicitSelfKind::MUT
-           || self_kind == ImplicitSelfKind::MUT_REF)
-            ? Mutability::Mut
-            : Mutability::Imm;
-  }
+  Mutability get_mut () const;
 
-  bool is_mut () const
-  {
-    return self_kind == ImplicitSelfKind::MUT
-          || self_kind == ImplicitSelfKind::MUT_REF;
-  }
+  bool is_mut () const;
 
-  bool is_ref () const
-  {
-    return self_kind == ImplicitSelfKind::IMM_REF
-          || self_kind == ImplicitSelfKind::MUT_REF;
-  }
+  bool is_ref () const;
 };
 
 // Qualifiers for function, i.e. const, unsafe, extern etc.
@@ -516,28 +464,13 @@ struct FunctionParam
 public:
   FunctionParam (Analysis::NodeMapping mappings,
                 std::unique_ptr<Pattern> param_name,
-                std::unique_ptr<Type> param_type, location_t locus)
-    : param_name (std::move (param_name)), type (std::move (param_type)),
-      locus (locus), mappings (mappings)
-  {}
+                std::unique_ptr<Type> param_type, location_t locus);
 
   // Copy constructor uses clone
-  FunctionParam (FunctionParam const &other)
-    : param_name (other.param_name->clone_pattern ()),
-      type (other.type->clone_type ()), locus (other.locus),
-      mappings (other.mappings)
-  {}
+  FunctionParam (FunctionParam const &other);
 
   // Overload assignment operator to use clone
-  FunctionParam &operator= (FunctionParam const &other)
-  {
-    param_name = other.param_name->clone_pattern ();
-    type = other.type->clone_type ();
-    locus = other.locus;
-    mappings = other.mappings;
-
-    return *this;
-  }
+  FunctionParam &operator= (FunctionParam const &other);
 
   // move constructors
   FunctionParam (FunctionParam &&other) = default;
@@ -554,58 +487,6 @@ public:
   const Analysis::NodeMapping &get_mappings () const { return mappings; }
 };
 
-// Visibility of an item
-struct Visibility
-{
-public:
-  enum VisType
-  {
-    PRIVATE,
-    PUBLIC,
-    RESTRICTED,
-    ERROR,
-  };
-
-private:
-  VisType vis_type;
-  HIR::SimplePath path;
-  location_t locus;
-
-  // should this store location info?
-
-public:
-  Visibility (VisType vis_type,
-             HIR::SimplePath path = HIR::SimplePath::create_empty (),
-             location_t locus = UNDEF_LOCATION)
-    : vis_type (vis_type), path (std::move (path)), locus (locus)
-  {}
-
-  // Returns whether visibility is in an error state.
-  bool is_error () const { return vis_type == ERROR; }
-
-  // Does the current visibility refer to a simple `pub <item>` entirely public
-  bool is_public () const { return vis_type == PUBLIC; }
-
-  // Is the current visibility public restricted to a certain path
-  bool is_restricted () const { return vis_type == RESTRICTED; }
-
-  // Creates an error visibility.
-  static Visibility create_error ()
-  {
-    return Visibility (ERROR, HIR::SimplePath::create_empty ());
-  }
-
-  VisType get_vis_type () const { return vis_type; }
-
-  const HIR::SimplePath &get_path () const
-  {
-    rust_assert (!is_error ());
-    return path;
-  }
-
-  std::string as_string () const;
-};
-
 // Item that supports visibility - abstract base class
 class VisItem : public Item
 {
@@ -620,18 +501,10 @@ protected:
   {}
 
   // Visibility copy constructor
-  VisItem (VisItem const &other) : Item (other), visibility (other.visibility)
-  {}
+  VisItem (VisItem const &other);
 
   // Overload assignment operator to clone
-  VisItem &operator= (VisItem const &other)
-  {
-    Item::operator= (other);
-    visibility = other.visibility;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  VisItem &operator= (VisItem const &other);
 
   // move constructors
   VisItem (VisItem &&other) = default;
@@ -673,34 +546,13 @@ public:
          location_t locus, std::vector<std::unique_ptr<Item>> items,
          Visibility visibility = Visibility::create_error (),
          AST::AttrVec inner_attrs = AST::AttrVec (),
-         AST::AttrVec outer_attrs = AST::AttrVec ())
-    : VisItem (std::move (mappings), std::move (visibility),
-              std::move (outer_attrs)),
-      WithInnerAttrs (std::move (inner_attrs)), module_name (module_name),
-      locus (locus), items (std::move (items))
-  {}
+         AST::AttrVec outer_attrs = AST::AttrVec ());
 
   // Copy constructor with vector clone
-  Module (Module const &other)
-    : VisItem (other), WithInnerAttrs (other.inner_attrs), module_name ("")
-  {
-    items.reserve (other.items.size ());
-    for (const auto &e : other.items)
-      items.push_back (e->clone_item ());
-  }
+  Module (Module const &other);
 
   // Overloaded assignment operator with vector clone
-  Module &operator= (Module const &other)
-  {
-    VisItem::operator= (other);
-    inner_attrs = other.inner_attrs;
-
-    items.reserve (other.items.size ());
-    for (const auto &e : other.items)
-      items.push_back (e->clone_item ());
-
-    return *this;
-  }
+  Module &operator= (Module const &other);
 
   // move constructors
   Module (Module &&other) = default;
@@ -1120,63 +972,13 @@ public:
            std::vector<FunctionParam> function_params,
            std::unique_ptr<Type> return_type, WhereClause where_clause,
            std::unique_ptr<BlockExpr> function_body, Visibility vis,
-           AST::AttrVec outer_attrs, SelfParam self, location_t locus)
-    : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
-      qualifiers (std::move (qualifiers)),
-      function_name (std::move (function_name)),
-      generic_params (std::move (generic_params)),
-      function_params (std::move (function_params)),
-      return_type (std::move (return_type)),
-      where_clause (std::move (where_clause)),
-      function_body (std::move (function_body)), self (std::move (self)),
-      locus (locus)
-  {}
+           AST::AttrVec outer_attrs, SelfParam self, location_t locus);
 
   // Copy constructor with clone
-  Function (Function const &other)
-    : VisItem (other), qualifiers (other.qualifiers),
-      function_name (other.function_name),
-      function_params (other.function_params),
-      where_clause (other.where_clause),
-      function_body (other.function_body->clone_block_expr ()),
-      self (other.self), locus (other.locus)
-  {
-    // guard to prevent null dereference (always required)
-    if (other.return_type != nullptr)
-      return_type = other.return_type->clone_type ();
-    else
-      return_type = nullptr;
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-  }
+  Function (Function const &other);
 
   // Overloaded assignment operator to clone
-  Function &operator= (Function const &other)
-  {
-    VisItem::operator= (other);
-    function_name = other.function_name;
-    qualifiers = other.qualifiers;
-    function_params = other.function_params;
-
-    // guard to prevent null dereference (always required)
-    if (other.return_type != nullptr)
-      return_type = other.return_type->clone_type ();
-    else
-      return_type = nullptr;
-
-    where_clause = other.where_clause;
-    function_body = other.function_body->clone_block_expr ();
-    locus = other.locus;
-    self = other.self;
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-
-    return *this;
-  }
+  Function &operator= (Function const &other);
 
   // move constructors
   Function (Function &&other) = default;
@@ -1280,40 +1082,13 @@ public:
   TypeAlias (Analysis::NodeMapping mappings, Identifier new_type_name,
             std::vector<std::unique_ptr<GenericParam>> generic_params,
             WhereClause where_clause, std::unique_ptr<Type> existing_type,
-            Visibility vis, AST::AttrVec outer_attrs, location_t locus)
-    : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
-      new_type_name (std::move (new_type_name)),
-      generic_params (std::move (generic_params)),
-      where_clause (std::move (where_clause)),
-      existing_type (std::move (existing_type)), locus (locus)
-  {}
+            Visibility vis, AST::AttrVec outer_attrs, location_t locus);
 
   // Copy constructor
-  TypeAlias (TypeAlias const &other)
-    : VisItem (other), new_type_name (other.new_type_name),
-      where_clause (other.where_clause),
-      existing_type (other.existing_type->clone_type ()), locus (other.locus)
-  {
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-  }
+  TypeAlias (TypeAlias const &other);
 
   // Overloaded assignment operator to clone
-  TypeAlias &operator= (TypeAlias const &other)
-  {
-    VisItem::operator= (other);
-    new_type_name = other.new_type_name;
-    where_clause = other.where_clause;
-    existing_type = other.existing_type->clone_type ();
-    locus = other.locus;
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-
-    return *this;
-  }
+  TypeAlias &operator= (TypeAlias const &other);
 
   // move constructors
   TypeAlias (TypeAlias &&other) = default;
@@ -1468,32 +1243,15 @@ public:
 
   StructField (Analysis::NodeMapping mappings, Identifier field_name,
               std::unique_ptr<Type> field_type, Visibility vis,
-              location_t locus, AST::AttrVec outer_attrs = AST::AttrVec ())
-    : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
-      field_name (std::move (field_name)), field_type (std::move (field_type)),
-      mappings (mappings), locus (locus)
-  {}
+              location_t locus, AST::AttrVec outer_attrs = AST::AttrVec ());
 
   // Copy constructor
-  StructField (StructField const &other)
-    : outer_attrs (other.outer_attrs), visibility (other.visibility),
-      field_name (other.field_name),
-      field_type (other.field_type->clone_type ()), mappings (other.mappings)
-  {}
+  StructField (StructField const &other);
 
   ~StructField () = default;
 
   // Overloaded assignment operator to clone
-  StructField &operator= (StructField const &other)
-  {
-    field_name = other.field_name;
-    field_type = other.field_type->clone_type ();
-    visibility = other.visibility;
-    outer_attrs = other.outer_attrs;
-    mappings = other.mappings;
-
-    return *this;
-  }
+  StructField &operator= (StructField const &other);
 
   // move constructors
   StructField (StructField &&other) = default;
@@ -1598,31 +1356,15 @@ public:
   // Complete constructor
   TupleField (Analysis::NodeMapping mapping, std::unique_ptr<Type> field_type,
              Visibility vis, location_t locus,
-             AST::AttrVec outer_attrs = AST::AttrVec ())
-    : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
-      field_type (std::move (field_type)), locus (locus), mappings (mapping)
-  {}
+             AST::AttrVec outer_attrs = AST::AttrVec ());
 
   // Copy constructor with clone
-  TupleField (TupleField const &other)
-    : outer_attrs (other.outer_attrs), visibility (other.visibility),
-      field_type (other.field_type->clone_type ()), locus (other.locus),
-      mappings (other.mappings)
-  {}
+  TupleField (TupleField const &other);
 
   ~TupleField () = default;
 
   // Overloaded assignment operator to clone
-  TupleField &operator= (TupleField const &other)
-  {
-    field_type = other.field_type->clone_type ();
-    visibility = other.visibility;
-    outer_attrs = other.outer_attrs;
-    locus = other.locus;
-    mappings = other.mappings;
-
-    return *this;
-  }
+  TupleField &operator= (TupleField const &other);
 
   // move constructors
   TupleField (TupleField &&other) = default;
@@ -1656,12 +1398,7 @@ public:
               Identifier struct_name,
               std::vector<std::unique_ptr<GenericParam>> generic_params,
               WhereClause where_clause, Visibility vis,
-              AST::AttrVec outer_attrs, location_t locus)
-    : Struct (std::move (mappings), std::move (struct_name),
-             std::move (generic_params), std::move (where_clause),
-             std::move (vis), locus, std::move (outer_attrs)),
-      fields (std::move (fields))
-  {}
+              AST::AttrVec outer_attrs, location_t locus);
 
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRStmtVisitor &vis) override;
@@ -1706,10 +1443,7 @@ public:
   };
 
   EnumItem (Analysis::NodeMapping mappings, Identifier variant_name,
-           AST::AttrVec outer_attrs, location_t locus)
-    : Item (std::move (mappings), std::move (outer_attrs)),
-      variant_name (std::move (variant_name)), locus (locus)
-  {}
+           AST::AttrVec outer_attrs, location_t locus);
 
   // Unique pointer custom clone function
   std::unique_ptr<EnumItem> clone_enum_item () const
@@ -1752,11 +1486,7 @@ public:
 
   EnumItemTuple (Analysis::NodeMapping mappings, Identifier variant_name,
                 std::vector<TupleField> tuple_fields, AST::AttrVec outer_attrs,
-                location_t locus)
-    : EnumItem (std::move (mappings), std::move (variant_name),
-               std::move (outer_attrs), locus),
-      tuple_fields (std::move (tuple_fields))
-  {}
+                location_t locus);
 
   std::string as_string () const override;
 
@@ -1790,11 +1520,7 @@ public:
 
   EnumItemStruct (Analysis::NodeMapping mappings, Identifier variant_name,
                  std::vector<StructField> struct_fields,
-                 AST::AttrVec outer_attrs, location_t locus)
-    : EnumItem (std::move (mappings), std::move (variant_name),
-               std::move (outer_attrs), locus),
-      struct_fields (std::move (struct_fields))
-  {}
+                 AST::AttrVec outer_attrs, location_t locus);
 
   std::string as_string () const override;
 
@@ -1819,27 +1545,13 @@ class EnumItemDiscriminant : public EnumItem
 public:
   EnumItemDiscriminant (Analysis::NodeMapping mappings, Identifier variant_name,
                        std::unique_ptr<Expr> expr, AST::AttrVec outer_attrs,
-                       location_t locus)
-    : EnumItem (std::move (mappings), std::move (variant_name),
-               std::move (outer_attrs), locus),
-      expression (std::move (expr))
-  {}
+                       location_t locus);
 
   // Copy constructor with clone
-  EnumItemDiscriminant (EnumItemDiscriminant const &other)
-    : EnumItem (other), expression (other.expression->clone_expr ())
-  {}
+  EnumItemDiscriminant (EnumItemDiscriminant const &other);
 
   // Overloaded assignment operator to clone
-  EnumItemDiscriminant &operator= (EnumItemDiscriminant const &other)
-  {
-    EnumItem::operator= (other);
-    expression = other.expression->clone_expr ();
-    // variant_name = other.variant_name;
-    // outer_attrs = other.outer_attrs;
-
-    return *this;
-  }
+  EnumItemDiscriminant &operator= (EnumItemDiscriminant const &other);
 
   // move constructors
   EnumItemDiscriminant (EnumItemDiscriminant &&other) = default;
@@ -1903,48 +1615,15 @@ public:
   Enum (Analysis::NodeMapping mappings, Identifier enum_name, Visibility vis,
        std::vector<std::unique_ptr<GenericParam>> generic_params,
        WhereClause where_clause, std::vector<std::unique_ptr<EnumItem>> items,
-       AST::AttrVec outer_attrs, location_t locus)
-    : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
-      enum_name (std::move (enum_name)),
-      generic_params (std::move (generic_params)),
-      where_clause (std::move (where_clause)), items (std::move (items)),
-      locus (locus)
-  {}
+       AST::AttrVec outer_attrs, location_t locus);
 
   // TODO: constructor with less arguments
 
   // Copy constructor with vector clone
-  Enum (Enum const &other)
-    : VisItem (other), enum_name (other.enum_name),
-      where_clause (other.where_clause), locus (other.locus)
-  {
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-
-    items.reserve (other.items.size ());
-    for (const auto &e : other.items)
-      items.push_back (e->clone_enum_item ());
-  }
+  Enum (Enum const &other);
 
   // Overloaded assignment operator with vector clone
-  Enum &operator= (Enum const &other)
-  {
-    VisItem::operator= (other);
-    enum_name = other.enum_name;
-    where_clause = other.where_clause;
-    locus = other.locus;
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-
-    items.reserve (other.items.size ());
-    for (const auto &e : other.items)
-      items.push_back (e->clone_enum_item ());
-
-    return *this;
-  }
+  Enum &operator= (Enum const &other);
 
   // Move constructors
   Enum (Enum &&other) = default;
@@ -2012,40 +1691,13 @@ public:
   Union (Analysis::NodeMapping mappings, Identifier union_name, Visibility vis,
         std::vector<std::unique_ptr<GenericParam>> generic_params,
         WhereClause where_clause, std::vector<StructField> variants,
-        AST::AttrVec outer_attrs, location_t locus)
-    : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
-      union_name (std::move (union_name)),
-      generic_params (std::move (generic_params)),
-      where_clause (std::move (where_clause)), variants (std::move (variants)),
-      locus (locus)
-  {}
+        AST::AttrVec outer_attrs, location_t locus);
 
   // copy constructor with vector clone
-  Union (Union const &other)
-    : VisItem (other), union_name (other.union_name),
-      where_clause (other.where_clause), variants (other.variants),
-      locus (other.locus)
-  {
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-  }
+  Union (Union const &other);
 
   // overloaded assignment operator with vector clone
-  Union &operator= (Union const &other)
-  {
-    VisItem::operator= (other);
-    union_name = other.union_name;
-    where_clause = other.where_clause;
-    variants = other.variants;
-    locus = other.locus;
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-
-    return *this;
-  }
+  Union &operator= (Union const &other);
 
   // move constructors
   Union (Union &&other) = default;
@@ -2089,29 +1741,12 @@ public:
   ConstantItem (Analysis::NodeMapping mappings, Identifier ident,
                Visibility vis, std::unique_ptr<Type> type,
                std::unique_ptr<Expr> const_expr, AST::AttrVec outer_attrs,
-               location_t locus)
-    : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
-      identifier (std::move (ident)), type (std::move (type)),
-      const_expr (std::move (const_expr)), locus (locus)
-  {}
+               location_t locus);
 
-  ConstantItem (ConstantItem const &other)
-    : VisItem (other), identifier (other.identifier),
-      type (other.type->clone_type ()),
-      const_expr (other.const_expr->clone_expr ()), locus (other.locus)
-  {}
+  ConstantItem (ConstantItem const &other);
 
   // Overload assignment operator to clone
-  ConstantItem &operator= (ConstantItem const &other)
-  {
-    VisItem::operator= (other);
-    identifier = other.identifier;
-    type = other.type->clone_type ();
-    const_expr = other.const_expr->clone_expr ();
-    locus = other.locus;
-
-    return *this;
-  }
+  ConstantItem &operator= (ConstantItem const &other);
 
   // move constructors
   ConstantItem (ConstantItem &&other) = default;
@@ -2185,31 +1820,13 @@ public:
 
   StaticItem (Analysis::NodeMapping mappings, Identifier name, Mutability mut,
              std::unique_ptr<Type> type, std::unique_ptr<Expr> expr,
-             Visibility vis, AST::AttrVec outer_attrs, location_t locus)
-    : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
-      mut (mut), name (std::move (name)), type (std::move (type)),
-      expr (std::move (expr)), locus (locus)
-  {}
+             Visibility vis, AST::AttrVec outer_attrs, location_t locus);
 
   // Copy constructor with clone
-  StaticItem (StaticItem const &other)
-    : VisItem (other), mut (other.mut), name (other.name),
-      type (other.type->clone_type ()), expr (other.expr->clone_expr ()),
-      locus (other.locus)
-  {}
+  StaticItem (StaticItem const &other);
 
   // Overloaded assignment operator to clone
-  StaticItem &operator= (StaticItem const &other)
-  {
-    VisItem::operator= (other);
-    name = other.name;
-    mut = other.mut;
-    type = other.type->clone_type ();
-    expr = other.expr->clone_expr ();
-    locus = other.locus;
-
-    return *this;
-  }
+  StaticItem &operator= (StaticItem const &other);
 
   // move constructors
   StaticItem (StaticItem &&other) = default;
@@ -2258,45 +1875,15 @@ public:
                     std::vector<std::unique_ptr<GenericParam>> generic_params,
                     SelfParam self, std::vector<FunctionParam> function_params,
                     std::unique_ptr<Type> return_type,
-                    WhereClause where_clause)
-    : qualifiers (std::move (qualifiers)),
-      function_name (std::move (function_name)),
-      generic_params (std::move (generic_params)),
-      function_params (std::move (function_params)),
-      return_type (std::move (return_type)),
-      where_clause (std::move (where_clause)), self (std::move (self))
-  {}
+                    WhereClause where_clause);
 
   // Copy constructor with clone
-  TraitFunctionDecl (TraitFunctionDecl const &other)
-    : qualifiers (other.qualifiers), function_name (other.function_name),
-      function_params (other.function_params),
-      return_type (other.return_type->clone_type ()),
-      where_clause (other.where_clause), self (other.self)
-  {
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-  }
+  TraitFunctionDecl (TraitFunctionDecl const &other);
 
   ~TraitFunctionDecl () = default;
 
   // Overloaded assignment operator with clone
-  TraitFunctionDecl &operator= (TraitFunctionDecl const &other)
-  {
-    function_name = other.function_name;
-    qualifiers = other.qualifiers;
-    function_params = other.function_params;
-    return_type = other.return_type->clone_type ();
-    where_clause = other.where_clause;
-    self = other.self;
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-
-    return *this;
-  }
+  TraitFunctionDecl &operator= (TraitFunctionDecl const &other);
 
   // move constructors
   TraitFunctionDecl (TraitFunctionDecl &&other) = default;
@@ -2350,34 +1937,13 @@ public:
 
   TraitItemFunc (Analysis::NodeMapping mappings, TraitFunctionDecl decl,
                 std::unique_ptr<BlockExpr> block_expr,
-                AST::AttrVec outer_attrs, location_t locus)
-    : TraitItem (mappings), outer_attrs (std::move (outer_attrs)),
-      decl (std::move (decl)), block_expr (std::move (block_expr)),
-      locus (locus)
-  {}
+                AST::AttrVec outer_attrs, location_t locus);
 
   // Copy constructor with clone
-  TraitItemFunc (TraitItemFunc const &other)
-    : TraitItem (other.mappings), outer_attrs (other.outer_attrs),
-      decl (other.decl), locus (other.locus)
-  {
-    if (other.block_expr != nullptr)
-      block_expr = other.block_expr->clone_block_expr ();
-  }
+  TraitItemFunc (TraitItemFunc const &other);
 
   // Overloaded assignment operator to clone
-  TraitItemFunc &operator= (TraitItemFunc const &other)
-  {
-    TraitItem::operator= (other);
-    outer_attrs = other.outer_attrs;
-    decl = other.decl;
-    locus = other.locus;
-    mappings = other.mappings;
-    if (other.block_expr != nullptr)
-      block_expr = other.block_expr->clone_block_expr ();
-
-    return *this;
-  }
+  TraitItemFunc &operator= (TraitItemFunc const &other);
 
   // move constructors
   TraitItemFunc (TraitItemFunc &&other) = default;
@@ -2439,32 +2005,13 @@ public:
 
   TraitItemConst (Analysis::NodeMapping mappings, Identifier name,
                  std::unique_ptr<Type> type, std::unique_ptr<Expr> expr,
-                 AST::AttrVec outer_attrs, location_t locus)
-    : TraitItem (mappings), outer_attrs (std::move (outer_attrs)),
-      name (std::move (name)), type (std::move (type)), expr (std::move (expr)),
-      locus (locus)
-  {}
+                 AST::AttrVec outer_attrs, location_t locus);
 
   // Copy constructor with clones
-  TraitItemConst (TraitItemConst const &other)
-    : TraitItem (other.mappings), outer_attrs (other.outer_attrs),
-      name (other.name), type (other.type->clone_type ()),
-      expr (other.expr->clone_expr ()), locus (other.locus)
-  {}
+  TraitItemConst (TraitItemConst const &other);
 
   // Overloaded assignment operator to clone
-  TraitItemConst &operator= (TraitItemConst const &other)
-  {
-    TraitItem::operator= (other);
-    outer_attrs = other.outer_attrs;
-    name = other.name;
-    type = other.type->clone_type ();
-    expr = other.expr->clone_expr ();
-    locus = other.locus;
-    mappings = other.mappings;
-
-    return *this;
-  }
+  TraitItemConst &operator= (TraitItemConst const &other);
 
   // move constructors
   TraitItemConst (TraitItemConst &&other) = default;
@@ -2527,37 +2074,13 @@ public:
 
   TraitItemType (Analysis::NodeMapping mappings, Identifier name,
                 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
-                AST::AttrVec outer_attrs, location_t locus)
-    : TraitItem (mappings), outer_attrs (std::move (outer_attrs)),
-      name (std::move (name)),
-      type_param_bounds (std::move (type_param_bounds)), locus (locus)
-  {}
+                AST::AttrVec outer_attrs, location_t locus);
 
   // Copy constructor with vector clone
-  TraitItemType (TraitItemType const &other)
-    : TraitItem (other.mappings), outer_attrs (other.outer_attrs),
-      name (other.name), locus (other.locus)
-  {
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-  }
+  TraitItemType (TraitItemType const &other);
 
   // Overloaded assignment operator with vector clone
-  TraitItemType &operator= (TraitItemType const &other)
-  {
-    TraitItem::operator= (other);
-    outer_attrs = other.outer_attrs;
-    name = other.name;
-    locus = other.locus;
-    mappings = other.mappings;
-
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-
-    return *this;
-  }
+  TraitItemType &operator= (TraitItemType const &other);
 
   // default move constructors
   TraitItemType (TraitItemType &&other) = default;
@@ -2645,56 +2168,13 @@ public:
         std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
         WhereClause where_clause,
         std::vector<std::unique_ptr<TraitItem>> trait_items, Visibility vis,
-        AST::AttrVec outer_attrs, location_t locus)
-    : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
-      unsafety (unsafety), name (std::move (name)),
-      generic_params (std::move (generic_params)),
-      type_param_bounds (std::move (type_param_bounds)),
-      where_clause (std::move (where_clause)),
-      trait_items (std::move (trait_items)), locus (locus)
-  {}
+        AST::AttrVec outer_attrs, location_t locus);
 
   // Copy constructor with vector clone
-  Trait (Trait const &other)
-    : VisItem (other), unsafety (other.unsafety), name (other.name),
-      where_clause (other.where_clause), locus (other.locus)
-  {
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-
-    trait_items.reserve (other.trait_items.size ());
-    for (const auto &e : other.trait_items)
-      trait_items.push_back (e->clone_trait_item ());
-  }
+  Trait (Trait const &other);
 
   // Overloaded assignment operator with vector clone
-  Trait &operator= (Trait const &other)
-  {
-    VisItem::operator= (other);
-    name = other.name;
-    unsafety = other.unsafety;
-    where_clause = other.where_clause;
-    locus = other.locus;
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-
-    trait_items.reserve (other.trait_items.size ());
-    for (const auto &e : other.trait_items)
-      trait_items.push_back (e->clone_trait_item ());
-
-    return *this;
-  }
+  Trait &operator= (Trait const &other);
 
   // default move constructors
   Trait (Trait &&other) = default;
@@ -2753,50 +2233,11 @@ public:
             std::unique_ptr<Type> impl_type,
             std::unique_ptr<TypePath> trait_ref, WhereClause where_clause,
             BoundPolarity polarity, Visibility vis, AST::AttrVec inner_attrs,
-            AST::AttrVec outer_attrs, location_t locus, bool unsafe = false)
-    : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
-      WithInnerAttrs (std::move (inner_attrs)),
-      generic_params (std::move (generic_params)),
-      impl_type (std::move (impl_type)), trait_ref (std::move (trait_ref)),
-      where_clause (std::move (where_clause)), polarity (polarity),
-      locus (locus), impl_items (std::move (impl_items)), unsafe (unsafe)
-  {}
-
-  ImplBlock (ImplBlock const &other)
-    : VisItem (other), WithInnerAttrs (other.inner_attrs),
-      impl_type (other.impl_type->clone_type ()),
-      where_clause (other.where_clause), polarity (other.polarity),
-      locus (other.locus), unsafe (other.unsafe)
-  {
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-
-    impl_items.reserve (other.impl_items.size ());
-    for (const auto &e : other.impl_items)
-      impl_items.push_back (e->clone_inherent_impl_item ());
-  }
-
-  ImplBlock &operator= (ImplBlock const &other)
-  {
-    VisItem::operator= (other);
-    impl_type = other.impl_type->clone_type ();
-    where_clause = other.where_clause;
-    polarity = other.polarity;
-    inner_attrs = other.inner_attrs;
-    locus = other.locus;
-    unsafe = other.unsafe;
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
+            AST::AttrVec outer_attrs, location_t locus, bool unsafe = false);
 
-    impl_items.reserve (other.impl_items.size ());
-    for (const auto &e : other.impl_items)
-      impl_items.push_back (e->clone_inherent_impl_item ());
+  ImplBlock (ImplBlock const &other);
 
-    return *this;
-  }
+  ImplBlock &operator= (ImplBlock const &other);
 
   ImplBlock (ImplBlock &&other) = default;
   ImplBlock &operator= (ImplBlock &&other) = default;
@@ -2905,30 +2346,13 @@ public:
 
 protected:
   ExternalItem (Analysis::NodeMapping mappings, Identifier item_name,
-               Visibility vis, AST::AttrVec outer_attrs, location_t locus)
-    : mappings (mappings), outer_attrs (std::move (outer_attrs)),
-      visibility (std::move (vis)), item_name (std::move (item_name)),
-      locus (locus)
-  {}
+               Visibility vis, AST::AttrVec outer_attrs, location_t locus);
 
   // Copy constructor
-  ExternalItem (ExternalItem const &other)
-    : mappings (other.mappings), outer_attrs (other.outer_attrs),
-      visibility (other.visibility), item_name (other.item_name),
-      locus (other.locus)
-  {}
+  ExternalItem (ExternalItem const &other);
 
   // Overloaded assignment operator to clone
-  ExternalItem &operator= (ExternalItem const &other)
-  {
-    mappings = other.mappings;
-    item_name = other.item_name;
-    visibility = other.visibility;
-    outer_attrs = other.outer_attrs;
-    locus = other.locus;
-
-    return *this;
-  }
+  ExternalItem &operator= (ExternalItem const &other);
 
   // move constructors
   ExternalItem (ExternalItem &&other) = default;
@@ -2948,27 +2372,13 @@ public:
   ExternalStaticItem (Analysis::NodeMapping mappings, Identifier item_name,
                      std::unique_ptr<Type> item_type, Mutability mut,
                      Visibility vis, AST::AttrVec outer_attrs,
-                     location_t locus)
-    : ExternalItem (std::move (mappings), std::move (item_name),
-                   std::move (vis), std::move (outer_attrs), locus),
-      mut (mut), item_type (std::move (item_type))
-  {}
+                     location_t locus);
 
   // Copy constructor
-  ExternalStaticItem (ExternalStaticItem const &other)
-    : ExternalItem (other), mut (other.mut),
-      item_type (other.item_type->clone_type ())
-  {}
+  ExternalStaticItem (ExternalStaticItem const &other);
 
   // Overloaded assignment operator to clone
-  ExternalStaticItem &operator= (ExternalStaticItem const &other)
-  {
-    ExternalItem::operator= (other);
-    item_type = other.item_type->clone_type ();
-    mut = other.mut;
-
-    return *this;
-  }
+  ExternalStaticItem &operator= (ExternalStaticItem const &other);
 
   // move constructors
   ExternalStaticItem (ExternalStaticItem &&other) = default;
@@ -3008,29 +2418,15 @@ public:
   bool has_name () const { return name.as_string () != "_"; }
 
   NamedFunctionParam (Analysis::NodeMapping mappings, Identifier name,
-                     std::unique_ptr<Type> param_type)
-    : name (std::move (name)), param_type (std::move (param_type)),
-      mappings (std::move (mappings))
-  {}
+                     std::unique_ptr<Type> param_type);
 
   // Copy constructor
-  NamedFunctionParam (NamedFunctionParam const &other)
-    : name (other.name), param_type (other.param_type->clone_type ()),
-      mappings (other.mappings)
-  {}
+  NamedFunctionParam (NamedFunctionParam const &other);
 
   ~NamedFunctionParam () = default;
 
   // Overloaded assignment operator to clone
-  NamedFunctionParam &operator= (NamedFunctionParam const &other)
-  {
-    mappings = other.mappings;
-    name = other.name;
-    param_type = other.param_type->clone_type ();
-    // has_name = other.has_name;
-
-    return *this;
-  }
+  NamedFunctionParam &operator= (NamedFunctionParam const &other);
 
   // move constructors
   NamedFunctionParam (NamedFunctionParam &&other) = default;
@@ -3082,48 +2478,13 @@ public:
     std::vector<std::unique_ptr<GenericParam>> generic_params,
     std::unique_ptr<Type> return_type, WhereClause where_clause,
     std::vector<NamedFunctionParam> function_params, bool has_variadics,
-    Visibility vis, AST::AttrVec outer_attrs, location_t locus)
-    : ExternalItem (std::move (mappings), std::move (item_name),
-                   std::move (vis), std::move (outer_attrs), locus),
-      generic_params (std::move (generic_params)),
-      return_type (std::move (return_type)),
-      where_clause (std::move (where_clause)),
-      function_params (std::move (function_params)),
-      has_variadics (has_variadics)
-  {}
+    Visibility vis, AST::AttrVec outer_attrs, location_t locus);
 
   // Copy constructor with clone
-  ExternalFunctionItem (ExternalFunctionItem const &other)
-    : ExternalItem (other), where_clause (other.where_clause),
-      function_params (other.function_params),
-      has_variadics (other.has_variadics)
-  {
-    if (other.return_type)
-      return_type = other.return_type->clone_type ();
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-  }
+  ExternalFunctionItem (ExternalFunctionItem const &other);
 
   // Overloaded assignment operator with clone
-  ExternalFunctionItem &operator= (ExternalFunctionItem const &other)
-  {
-    ExternalItem::operator= (other);
-
-    where_clause = other.where_clause;
-    function_params = other.function_params;
-    has_variadics = other.has_variadics;
-
-    if (other.return_type)
-      return_type = other.return_type->clone_type ();
-
-    generic_params.reserve (other.generic_params.size ());
-    for (const auto &e : other.generic_params)
-      generic_params.push_back (e->clone_generic_param ());
-
-    return *this;
-  }
+  ExternalFunctionItem &operator= (ExternalFunctionItem const &other);
 
   // move constructors
   ExternalFunctionItem (ExternalFunctionItem &&other) = default;
@@ -3163,14 +2524,9 @@ class ExternalTypeItem : public ExternalItem
 {
 public:
   ExternalTypeItem (Analysis::NodeMapping mappings, Identifier item_name,
-                   Visibility vis, location_t locus)
-    : ExternalItem (std::move (mappings), std::move (item_name),
-                   Visibility (std::move (vis)),
-                   /* FIXME: Is that correct? */
-                   {}, locus)
-  {}
+                   Visibility vis, location_t locus);
 
-  ExternalTypeItem (ExternalTypeItem const &other) : ExternalItem (other) {}
+  ExternalTypeItem (ExternalTypeItem const &other);
 
   ExternalTypeItem (ExternalTypeItem &&other) = default;
   ExternalTypeItem &operator= (ExternalTypeItem &&other) = default;
@@ -3210,36 +2566,13 @@ public:
   ExternBlock (Analysis::NodeMapping mappings, ABI abi,
               std::vector<std::unique_ptr<ExternalItem>> extern_items,
               Visibility vis, AST::AttrVec inner_attrs,
-              AST::AttrVec outer_attrs, location_t locus)
-    : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)),
-      WithInnerAttrs (std::move (inner_attrs)), abi (abi),
-      extern_items (std::move (extern_items)), locus (locus)
-  {}
+              AST::AttrVec outer_attrs, location_t locus);
 
   // Copy constructor with vector clone
-  ExternBlock (ExternBlock const &other)
-    : VisItem (other), WithInnerAttrs (other.inner_attrs), abi (other.abi),
-      locus (other.locus)
-  {
-    extern_items.reserve (other.extern_items.size ());
-    for (const auto &e : other.extern_items)
-      extern_items.push_back (e->clone_external_item ());
-  }
+  ExternBlock (ExternBlock const &other);
 
   // Overloaded assignment operator with vector clone
-  ExternBlock &operator= (ExternBlock const &other)
-  {
-    VisItem::operator= (other);
-    abi = other.abi;
-    inner_attrs = other.inner_attrs;
-    locus = other.locus;
-
-    extern_items.reserve (other.extern_items.size ());
-    for (const auto &e : other.extern_items)
-      extern_items.push_back (e->clone_external_item ());
-
-    return *this;
-  }
+  ExternBlock &operator= (ExternBlock const &other);
 
   // move constructors
   ExternBlock (ExternBlock &&other) = default;
diff --git a/gcc/rust/hir/tree/rust-hir-literal.h b/gcc/rust/hir/tree/rust-hir-literal.h
new file mode 100644 (file)
index 0000000..9a97e71
--- /dev/null
@@ -0,0 +1,78 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_LITERAL_H
+#define RUST_HIR_LITERAL_H
+
+#include "rust-token.h"
+
+namespace Rust {
+namespace HIR {
+// A literal - value with a type. Used in LiteralExpr and LiteralPattern.
+struct Literal
+{
+public:
+  enum LitType
+  {
+    CHAR,
+    STRING,
+    BYTE,
+    BYTE_STRING,
+    INT,
+    FLOAT,
+    BOOL
+  };
+
+private:
+  std::string value_as_string;
+  LitType type;
+  PrimitiveCoreType type_hint;
+
+public:
+  std::string as_string () const { return value_as_string; }
+
+  LitType get_lit_type () const { return type; }
+
+  PrimitiveCoreType get_type_hint () const { return type_hint; }
+
+  Literal (std::string value_as_string, LitType type,
+          PrimitiveCoreType type_hint)
+    : value_as_string (std::move (value_as_string)), type (type),
+      type_hint (type_hint)
+  {}
+
+  static Literal create_error ()
+  {
+    return Literal ("", CHAR, PrimitiveCoreType::CORETYPE_UNKNOWN);
+  }
+
+  void set_lit_type (LitType lt) { type = lt; }
+
+  // Returns whether literal is in an invalid state.
+  bool is_error () const { return value_as_string == ""; }
+
+  bool is_equal (Literal &other)
+  {
+    return value_as_string == other.value_as_string && type == other.type
+          && type_hint == other.type_hint;
+  }
+};
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-node.h b/gcc/rust/hir/tree/rust-hir-node.h
new file mode 100644 (file)
index 0000000..4010c23
--- /dev/null
@@ -0,0 +1,63 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_NODE_H
+#define RUST_HIR_NODE_H
+
+namespace Rust {
+
+namespace HIR {
+
+class Node
+{
+public:
+  // Kind for downcasting various HIR nodes to other base classes when visiting
+  // them
+  enum BaseKind
+  {
+    /* class ExternalItem */
+    EXTERNAL,
+    /* class TraitItem */
+    TRAIT_ITEM,
+    /* class VisItem */
+    VIS_ITEM,
+    /* class Item */
+    ITEM,
+    /* class ImplItem */
+    IMPL,
+    /* class Type */
+    TYPE,
+    /* class Stmt */
+    STMT,
+    /* class Expr */
+    EXPR,
+    /* class Pattern */
+    PATTERN,
+  };
+
+  /**
+   * Get the kind of HIR node we are dealing with. This is useful for
+   * downcasting to more precise types when necessary, i.e going from an `Item*`
+   * to a `VisItem*`
+   */
+  virtual BaseKind get_hir_kind () = 0;
+};
+
+} // namespace HIR
+} // namespace Rust
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-path.cc b/gcc/rust/hir/tree/rust-hir-path.cc
new file mode 100644 (file)
index 0000000..c8d3079
--- /dev/null
@@ -0,0 +1,383 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-path.h"
+#include "rust-hir-bound.h"
+
+namespace Rust {
+namespace HIR {
+
+GenericArgsBinding::GenericArgsBinding (Identifier ident,
+                                       std::unique_ptr<Type> type_ptr,
+                                       location_t locus)
+  : identifier (std::move (ident)), type (std::move (type_ptr)), locus (locus)
+{}
+
+GenericArgsBinding::GenericArgsBinding (GenericArgsBinding const &other)
+  : identifier (other.identifier), type (other.type->clone_type ()),
+    locus (other.locus)
+{}
+
+GenericArgsBinding &
+GenericArgsBinding::operator= (GenericArgsBinding const &other)
+{
+  identifier = other.identifier;
+  type = other.type->clone_type ();
+  locus = other.locus;
+  return *this;
+}
+
+ConstGenericArg::ConstGenericArg (std::unique_ptr<Expr> expression,
+                                 location_t locus)
+  : expression (std::move (expression)), locus (locus)
+{}
+
+ConstGenericArg::ConstGenericArg (const ConstGenericArg &other)
+  : locus (other.locus)
+{
+  expression = other.expression->clone_expr ();
+}
+
+ConstGenericArg
+ConstGenericArg::operator= (const ConstGenericArg &other)
+{
+  expression = other.expression->clone_expr ();
+  locus = other.locus;
+
+  return *this;
+}
+
+GenericArgs &
+GenericArgs::operator= (GenericArgs const &other)
+{
+  lifetime_args = other.lifetime_args;
+  binding_args = other.binding_args;
+  const_args = other.const_args;
+  locus = other.locus;
+
+  type_args.clear ();
+  type_args.reserve (other.type_args.size ());
+  for (const auto &e : other.type_args)
+    type_args.push_back (e->clone_type ());
+
+  return *this;
+}
+
+GenericArgs::GenericArgs (std::vector<Lifetime> lifetime_args,
+                         std::vector<std::unique_ptr<Type> > type_args,
+                         std::vector<GenericArgsBinding> binding_args,
+                         std::vector<ConstGenericArg> const_args,
+                         location_t locus)
+  : lifetime_args (std::move (lifetime_args)),
+    type_args (std::move (type_args)), binding_args (std::move (binding_args)),
+    const_args (std::move (const_args)), locus (locus)
+{}
+
+GenericArgs::GenericArgs (GenericArgs const &other)
+  : lifetime_args (other.lifetime_args), binding_args (other.binding_args),
+    const_args (other.const_args), locus (other.locus)
+{
+  type_args.clear ();
+  type_args.reserve (other.type_args.size ());
+
+  for (const auto &e : other.type_args)
+    type_args.push_back (e->clone_type ());
+}
+
+bool
+GenericArgs::is_empty () const
+{
+  return lifetime_args.size () == 0 && type_args.size () == 0
+        && binding_args.size () == 0;
+}
+
+PathExprSegment::PathExprSegment (Analysis::NodeMapping mappings,
+                                 PathIdentSegment segment_name,
+                                 location_t locus, GenericArgs generic_args)
+  : mappings (std::move (mappings)), segment_name (std::move (segment_name)),
+    generic_args (std::move (generic_args)), locus (locus)
+{}
+
+PathExprSegment::PathExprSegment (PathExprSegment const &other)
+  : mappings (other.mappings), segment_name (other.segment_name),
+    generic_args (other.generic_args), locus (other.locus)
+{}
+
+PathExprSegment &
+PathExprSegment::operator= (PathExprSegment const &other)
+{
+  mappings = other.mappings;
+  segment_name = other.segment_name;
+  generic_args = other.generic_args;
+  locus = other.locus;
+
+  return *this;
+}
+
+void
+PathPattern::iterate_path_segments (std::function<bool (PathExprSegment &)> cb)
+{
+  for (auto it = segments.begin (); it != segments.end (); it++)
+    {
+      if (!cb (*it))
+       return;
+    }
+}
+
+PathInExpression::PathInExpression (Analysis::NodeMapping mappings,
+                                   std::vector<PathExprSegment> path_segments,
+                                   location_t locus,
+                                   bool has_opening_scope_resolution,
+                                   std::vector<AST::Attribute> outer_attrs)
+  : PathPattern (std::move (path_segments)),
+    PathExpr (std::move (mappings), std::move (outer_attrs)),
+    has_opening_scope_resolution (has_opening_scope_resolution), locus (locus)
+{}
+
+bool
+PathInExpression::is_self () const
+
+{
+  if (!is_single_segment ())
+    return false;
+
+  return get_final_segment ().get_segment ().as_string ().compare ("self") == 0;
+}
+
+TypePathSegment::TypePathSegment (Analysis::NodeMapping mappings,
+                                 PathIdentSegment ident_segment,
+                                 bool has_separating_scope_resolution,
+                                 location_t locus)
+  : mappings (std::move (mappings)), ident_segment (std::move (ident_segment)),
+    locus (locus),
+    has_separating_scope_resolution (has_separating_scope_resolution),
+    type (SegmentType::REG)
+{}
+
+TypePathSegment::TypePathSegment (Analysis::NodeMapping mappings,
+                                 std::string segment_name,
+                                 bool has_separating_scope_resolution,
+                                 location_t locus)
+  : mappings (std::move (mappings)),
+    ident_segment (PathIdentSegment (std::move (segment_name))), locus (locus),
+    has_separating_scope_resolution (has_separating_scope_resolution),
+    type (SegmentType::REG)
+{}
+
+TypePathSegmentGeneric::TypePathSegmentGeneric (
+  Analysis::NodeMapping mappings, PathIdentSegment ident_segment,
+  bool has_separating_scope_resolution, GenericArgs generic_args,
+  location_t locus)
+  : TypePathSegment (std::move (mappings), std::move (ident_segment),
+                    has_separating_scope_resolution, locus),
+    generic_args (std::move (generic_args))
+{}
+
+TypePathSegmentGeneric::TypePathSegmentGeneric (
+  Analysis::NodeMapping mappings, std::string segment_name,
+  bool has_separating_scope_resolution, std::vector<Lifetime> lifetime_args,
+  std::vector<std::unique_ptr<Type> > type_args,
+  std::vector<GenericArgsBinding> binding_args,
+  std::vector<ConstGenericArg> const_args, location_t locus)
+  : TypePathSegment (std::move (mappings), std::move (segment_name),
+                    has_separating_scope_resolution, locus),
+    generic_args (GenericArgs (std::move (lifetime_args), std::move (type_args),
+                              std::move (binding_args), std::move (const_args),
+                              locus))
+{}
+
+TypePathFunction::TypePathFunction (std::vector<std::unique_ptr<Type> > inputs,
+                                   std::unique_ptr<Type> type)
+  : inputs (std::move (inputs)), return_type (std::move (type))
+{}
+
+TypePathFunction::TypePathFunction (TypePathFunction const &other)
+{
+  return_type = other.has_return_type ()
+                 ? other.get_return_type ().clone_type ()
+                 : nullptr;
+
+  inputs.reserve (other.inputs.size ());
+  for (const auto &e : other.inputs)
+    inputs.push_back (e->clone_type ());
+}
+
+TypePathFunction &
+TypePathFunction::operator= (TypePathFunction const &other)
+{
+  return_type = other.has_return_type ()
+                 ? other.get_return_type ().clone_type ()
+                 : nullptr;
+
+  inputs.reserve (other.inputs.size ());
+  for (const auto &e : other.inputs)
+    inputs.push_back (e->clone_type ());
+
+  return *this;
+}
+
+TypePathSegmentFunction::TypePathSegmentFunction (
+  Analysis::NodeMapping mappings, PathIdentSegment ident_segment,
+  bool has_separating_scope_resolution, TypePathFunction function_path,
+  location_t locus)
+  : TypePathSegment (std::move (mappings), std::move (ident_segment),
+                    has_separating_scope_resolution, locus),
+    function_path (std::move (function_path))
+{}
+
+TypePathSegmentFunction::TypePathSegmentFunction (
+  Analysis::NodeMapping mappings, std::string segment_name,
+  bool has_separating_scope_resolution, TypePathFunction function_path,
+  location_t locus)
+  : TypePathSegment (std::move (mappings), std::move (segment_name),
+                    has_separating_scope_resolution, locus),
+    function_path (std::move (function_path))
+{}
+
+TypePath::TypePath (Analysis::NodeMapping mappings,
+                   std::vector<std::unique_ptr<TypePathSegment> > segments,
+                   location_t locus, bool has_opening_scope_resolution)
+  : TypeNoBounds (mappings, locus),
+    has_opening_scope_resolution (has_opening_scope_resolution),
+    segments (std::move (segments))
+{}
+
+TypePath::TypePath (TypePath const &other)
+  : TypeNoBounds (other.mappings, other.locus),
+    has_opening_scope_resolution (other.has_opening_scope_resolution)
+{
+  segments.reserve (other.segments.size ());
+  for (const auto &e : other.segments)
+    segments.push_back (e->clone_type_path_segment ());
+}
+
+TypePath &
+TypePath::operator= (TypePath const &other)
+{
+  has_opening_scope_resolution = other.has_opening_scope_resolution;
+  locus = other.locus;
+  mappings = other.mappings;
+
+  segments.reserve (other.segments.size ());
+  for (const auto &e : other.segments)
+    segments.push_back (e->clone_type_path_segment ());
+
+  return *this;
+}
+
+QualifiedPathType::QualifiedPathType (Analysis::NodeMapping mappings,
+                                     std::unique_ptr<Type> type,
+                                     std::unique_ptr<TypePath> trait,
+                                     location_t locus)
+  : type (std::move (type)), trait (std::move (trait)), locus (locus),
+    mappings (mappings)
+{}
+
+QualifiedPathType::QualifiedPathType (QualifiedPathType const &other)
+  : type (other.type->clone_type ()),
+    trait (other.has_as_clause ()
+            ? std::unique_ptr<HIR::TypePath> (new HIR::TypePath (*other.trait))
+            : nullptr),
+    locus (other.locus), mappings (other.mappings)
+{}
+
+QualifiedPathType &
+QualifiedPathType::operator= (QualifiedPathType const &other)
+{
+  type = other.type->clone_type ();
+  locus = other.locus;
+  mappings = other.mappings;
+  trait = other.has_as_clause ()
+           ? std::unique_ptr<HIR::TypePath> (new HIR::TypePath (*other.trait))
+           : nullptr;
+
+  return *this;
+}
+
+bool
+QualifiedPathType::trait_has_generic_args () const
+{
+  rust_assert (has_as_clause ());
+  bool is_generic_seg = trait->get_final_segment ().get_type ()
+                       == TypePathSegment::SegmentType::GENERIC;
+  if (!is_generic_seg)
+    return false;
+
+  auto &seg
+    = static_cast<TypePathSegmentGeneric &> (trait->get_final_segment ());
+  return seg.has_generic_args ();
+}
+
+GenericArgs &
+QualifiedPathType::get_trait_generic_args ()
+{
+  rust_assert (trait_has_generic_args ());
+  auto &seg
+    = static_cast<TypePathSegmentGeneric &> (trait->get_final_segment ());
+  return seg.get_generic_args ();
+}
+
+QualifiedPathInExpression::QualifiedPathInExpression (
+  Analysis::NodeMapping mappings, QualifiedPathType qual_path_type,
+  std::vector<PathExprSegment> path_segments, location_t locus,
+  std::vector<AST::Attribute> outer_attrs)
+  : PathPattern (std::move (path_segments)),
+    PathExpr (std::move (mappings), std::move (outer_attrs)),
+    path_type (std::move (qual_path_type)), locus (locus)
+{}
+
+QualifiedPathInType::QualifiedPathInType (
+  Analysis::NodeMapping mappings, QualifiedPathType qual_path_type,
+  std::unique_ptr<TypePathSegment> associated_segment,
+  std::vector<std::unique_ptr<TypePathSegment> > path_segments,
+  location_t locus)
+  : TypeNoBounds (mappings, locus), path_type (std::move (qual_path_type)),
+    associated_segment (std::move (associated_segment)),
+    segments (std::move (path_segments))
+{}
+
+QualifiedPathInType::QualifiedPathInType (QualifiedPathInType const &other)
+  : TypeNoBounds (other.mappings, other.locus), path_type (other.path_type)
+{
+  auto seg = other.associated_segment->clone_type_path_segment_impl ();
+  associated_segment = std::unique_ptr<TypePathSegment> (seg);
+
+  segments.reserve (other.segments.size ());
+  for (const auto &e : other.segments)
+    segments.push_back (e->clone_type_path_segment ());
+}
+
+QualifiedPathInType &
+QualifiedPathInType::operator= (QualifiedPathInType const &other)
+{
+  auto seg = other.associated_segment->clone_type_path_segment_impl ();
+  associated_segment = std::unique_ptr<TypePathSegment> (seg);
+
+  path_type = other.path_type;
+  locus = other.locus;
+  mappings = other.mappings;
+
+  segments.reserve (other.segments.size ());
+  for (const auto &e : other.segments)
+    segments.push_back (e->clone_type_path_segment ());
+
+  return *this;
+}
+
+} // namespace HIR
+} // namespace Rust
index 18197837afae975c7b491366a306c93e19b48a3f..8b9814f227a7d52a03b9e9d75f8547453bbddb8a 100644 (file)
 #ifndef RUST_HIR_PATH_H
 #define RUST_HIR_PATH_H
 
-#include "rust-hir.h"
+#include "rust-hir-simple-path.h"
+#include "rust-hir-type-no-bounds.h"
+#include "rust-hir-pattern-abstract.h"
+#include "rust-hir-expr-abstract.h"
 
 namespace Rust {
 namespace HIR {
@@ -76,27 +79,16 @@ public:
 
   // Pointer type for type in constructor to enable polymorphism
   GenericArgsBinding (Identifier ident, std::unique_ptr<Type> type_ptr,
-                     location_t locus = UNDEF_LOCATION)
-    : identifier (std::move (ident)), type (std::move (type_ptr)), locus (locus)
-  {}
+                     location_t locus = UNDEF_LOCATION);
 
   // Copy constructor has to deep copy the type as it is a unique pointer
-  GenericArgsBinding (GenericArgsBinding const &other)
-    : identifier (other.identifier), type (other.type->clone_type ()),
-      locus (other.locus)
-  {}
+  GenericArgsBinding (GenericArgsBinding const &other);
 
   // default destructor
   ~GenericArgsBinding () = default;
 
   // Overload assignment operator to deep copy the pointed-to type
-  GenericArgsBinding &operator= (GenericArgsBinding const &other)
-  {
-    identifier = other.identifier;
-    type = other.type->clone_type ();
-    locus = other.locus;
-    return *this;
-  }
+  GenericArgsBinding &operator= (GenericArgsBinding const &other);
 
   // move constructors
   GenericArgsBinding (GenericArgsBinding &&other) = default;
@@ -119,22 +111,11 @@ class ConstGenericArg
   // at name-resolution, hence no need for ambiguities here
 
 public:
-  ConstGenericArg (std::unique_ptr<Expr> expression, location_t locus)
-    : expression (std::move (expression)), locus (locus)
-  {}
-
-  ConstGenericArg (const ConstGenericArg &other) : locus (other.locus)
-  {
-    expression = other.expression->clone_expr ();
-  }
+  ConstGenericArg (std::unique_ptr<Expr> expression, location_t locus);
 
-  ConstGenericArg operator= (const ConstGenericArg &other)
-  {
-    expression = other.expression->clone_expr ();
-    locus = other.locus;
+  ConstGenericArg (const ConstGenericArg &other);
 
-    return *this;
-  }
+  ConstGenericArg operator= (const ConstGenericArg &other);
 
   std::unique_ptr<Expr> &get_expression () { return expression; }
 
@@ -162,42 +143,15 @@ public:
   GenericArgs (std::vector<Lifetime> lifetime_args,
               std::vector<std::unique_ptr<Type> > type_args,
               std::vector<GenericArgsBinding> binding_args,
-              std::vector<ConstGenericArg> const_args, location_t locus)
-    : lifetime_args (std::move (lifetime_args)),
-      type_args (std::move (type_args)),
-      binding_args (std::move (binding_args)),
-      const_args (std::move (const_args)), locus (locus)
-  {}
+              std::vector<ConstGenericArg> const_args, location_t locus);
 
   // copy constructor with vector clone
-  GenericArgs (GenericArgs const &other)
-    : lifetime_args (other.lifetime_args), binding_args (other.binding_args),
-      const_args (other.const_args), locus (other.locus)
-  {
-    type_args.clear ();
-    type_args.reserve (other.type_args.size ());
-
-    for (const auto &e : other.type_args)
-      type_args.push_back (e->clone_type ());
-  }
+  GenericArgs (GenericArgs const &other);
 
   ~GenericArgs () = default;
 
   // overloaded assignment operator to vector clone
-  GenericArgs &operator= (GenericArgs const &other)
-  {
-    lifetime_args = other.lifetime_args;
-    binding_args = other.binding_args;
-    const_args = other.const_args;
-    locus = other.locus;
-
-    type_args.clear ();
-    type_args.reserve (other.type_args.size ());
-    for (const auto &e : other.type_args)
-      type_args.push_back (e->clone_type ());
-
-    return *this;
-  }
+  GenericArgs &operator= (GenericArgs const &other);
 
   // move constructors
   GenericArgs (GenericArgs &&other) = default;
@@ -209,11 +163,7 @@ public:
     return GenericArgs ({}, {}, {}, {}, locus);
   }
 
-  bool is_empty () const
-  {
-    return lifetime_args.size () == 0 && type_args.size () == 0
-          && binding_args.size () == 0;
-  }
+  bool is_empty () const;
 
   std::string as_string () const;
 
@@ -245,25 +195,11 @@ private:
 public:
   PathExprSegment (Analysis::NodeMapping mappings,
                   PathIdentSegment segment_name, location_t locus,
-                  GenericArgs generic_args)
-    : mappings (std::move (mappings)), segment_name (std::move (segment_name)),
-      generic_args (std::move (generic_args)), locus (locus)
-  {}
+                  GenericArgs generic_args);
 
-  PathExprSegment (PathExprSegment const &other)
-    : mappings (other.mappings), segment_name (other.segment_name),
-      generic_args (other.generic_args), locus (other.locus)
-  {}
-
-  PathExprSegment &operator= (PathExprSegment const &other)
-  {
-    mappings = other.mappings;
-    segment_name = other.segment_name;
-    generic_args = other.generic_args;
-    locus = other.locus;
+  PathExprSegment (PathExprSegment const &other);
 
-    return *this;
-  }
+  PathExprSegment &operator= (PathExprSegment const &other);
 
   // move constructors
   PathExprSegment (PathExprSegment &&other) = default;
@@ -308,14 +244,7 @@ public:
 
   std::string as_string () const override;
 
-  void iterate_path_segments (std::function<bool (PathExprSegment &)> cb)
-  {
-    for (auto it = segments.begin (); it != segments.end (); it++)
-      {
-       if (!cb (*it))
-         return;
-      }
-  }
+  void iterate_path_segments (std::function<bool (PathExprSegment &)> cb);
 
   size_t get_num_segments () const { return segments.size (); }
 
@@ -349,11 +278,7 @@ public:
                    location_t locus = UNDEF_LOCATION,
                    bool has_opening_scope_resolution = false,
                    std::vector<AST::Attribute> outer_attrs
-                   = std::vector<AST::Attribute> ())
-    : PathPattern (std::move (path_segments)),
-      PathExpr (std::move (mappings), std::move (outer_attrs)),
-      has_opening_scope_resolution (has_opening_scope_resolution), locus (locus)
-  {}
+                   = std::vector<AST::Attribute> ());
 
   // Creates an error state path in expression.
   static PathInExpression create_error ()
@@ -385,14 +310,7 @@ public:
 
   bool opening_scope_resolution () { return has_opening_scope_resolution; }
 
-  bool is_self () const
-  {
-    if (!is_single_segment ())
-      return false;
-
-    return get_final_segment ().get_segment ().as_string ().compare ("self")
-          == 0;
-  }
+  bool is_self () const;
 
   const Analysis::NodeMapping &get_mappings () const override final
   {
@@ -456,21 +374,10 @@ public:
 
   TypePathSegment (Analysis::NodeMapping mappings,
                   PathIdentSegment ident_segment,
-                  bool has_separating_scope_resolution, location_t locus)
-    : mappings (std::move (mappings)),
-      ident_segment (std::move (ident_segment)), locus (locus),
-      has_separating_scope_resolution (has_separating_scope_resolution),
-      type (SegmentType::REG)
-  {}
+                  bool has_separating_scope_resolution, location_t locus);
 
   TypePathSegment (Analysis::NodeMapping mappings, std::string segment_name,
-                  bool has_separating_scope_resolution, location_t locus)
-    : mappings (std::move (mappings)),
-      ident_segment (PathIdentSegment (std::move (segment_name))),
-      locus (locus),
-      has_separating_scope_resolution (has_separating_scope_resolution),
-      type (SegmentType::REG)
-  {}
+                  bool has_separating_scope_resolution, location_t locus);
 
   virtual std::string as_string () const { return ident_segment.as_string (); }
 
@@ -511,11 +418,7 @@ public:
   TypePathSegmentGeneric (Analysis::NodeMapping mappings,
                          PathIdentSegment ident_segment,
                          bool has_separating_scope_resolution,
-                         GenericArgs generic_args, location_t locus)
-    : TypePathSegment (std::move (mappings), std::move (ident_segment),
-                      has_separating_scope_resolution, locus),
-      generic_args (std::move (generic_args))
-  {}
+                         GenericArgs generic_args, location_t locus);
 
   // Constructor from segment name and all args
   TypePathSegmentGeneric (Analysis::NodeMapping mappings,
@@ -525,13 +428,7 @@ public:
                          std::vector<std::unique_ptr<Type> > type_args,
                          std::vector<GenericArgsBinding> binding_args,
                          std::vector<ConstGenericArg> const_args,
-                         location_t locus)
-    : TypePathSegment (std::move (mappings), std::move (segment_name),
-                      has_separating_scope_resolution, locus),
-      generic_args (
-       GenericArgs (std::move (lifetime_args), std::move (type_args),
-                    std::move (binding_args), std::move (const_args), locus))
-  {}
+                         location_t locus);
 
   std::string as_string () const override;
 
@@ -566,37 +463,15 @@ public:
 
   // Constructor
   TypePathFunction (std::vector<std::unique_ptr<Type> > inputs,
-                   std::unique_ptr<Type> type)
-    : inputs (std::move (inputs)), return_type (std::move (type))
-  {}
+                   std::unique_ptr<Type> type);
 
   // Copy constructor with clone
-  TypePathFunction (TypePathFunction const &other)
-  {
-    return_type = other.has_return_type ()
-                   ? other.get_return_type ().clone_type ()
-                   : nullptr;
-
-    inputs.reserve (other.inputs.size ());
-    for (const auto &e : other.inputs)
-      inputs.push_back (e->clone_type ());
-  }
+  TypePathFunction (TypePathFunction const &other);
 
   ~TypePathFunction () = default;
 
   // Overloaded assignment operator to clone type
-  TypePathFunction &operator= (TypePathFunction const &other)
-  {
-    return_type = other.has_return_type ()
-                   ? other.get_return_type ().clone_type ()
-                   : nullptr;
-
-    inputs.reserve (other.inputs.size ());
-    for (const auto &e : other.inputs)
-      inputs.push_back (e->clone_type ());
-
-    return *this;
-  }
+  TypePathFunction &operator= (TypePathFunction const &other);
 
   // move constructors
   TypePathFunction (TypePathFunction &&other) = default;
@@ -624,21 +499,13 @@ public:
   TypePathSegmentFunction (Analysis::NodeMapping mappings,
                           PathIdentSegment ident_segment,
                           bool has_separating_scope_resolution,
-                          TypePathFunction function_path, location_t locus)
-    : TypePathSegment (std::move (mappings), std::move (ident_segment),
-                      has_separating_scope_resolution, locus),
-      function_path (std::move (function_path))
-  {}
+                          TypePathFunction function_path, location_t locus);
 
   // Constructor with segment name and TypePathFn
   TypePathSegmentFunction (Analysis::NodeMapping mappings,
                           std::string segment_name,
                           bool has_separating_scope_resolution,
-                          TypePathFunction function_path, location_t locus)
-    : TypePathSegment (std::move (mappings), std::move (segment_name),
-                      has_separating_scope_resolution, locus),
-      function_path (std::move (function_path))
-  {}
+                          TypePathFunction function_path, location_t locus);
 
   std::string as_string () const override;
 
@@ -698,35 +565,13 @@ public:
   // Constructor
   TypePath (Analysis::NodeMapping mappings,
            std::vector<std::unique_ptr<TypePathSegment> > segments,
-           location_t locus, bool has_opening_scope_resolution = false)
-    : TypeNoBounds (mappings, locus),
-      has_opening_scope_resolution (has_opening_scope_resolution),
-      segments (std::move (segments))
-  {}
+           location_t locus, bool has_opening_scope_resolution = false);
 
   // Copy constructor with vector clone
-  TypePath (TypePath const &other)
-    : TypeNoBounds (other.mappings, other.locus),
-      has_opening_scope_resolution (other.has_opening_scope_resolution)
-  {
-    segments.reserve (other.segments.size ());
-    for (const auto &e : other.segments)
-      segments.push_back (e->clone_type_path_segment ());
-  }
+  TypePath (TypePath const &other);
 
   // Overloaded assignment operator with clone
-  TypePath &operator= (TypePath const &other)
-  {
-    has_opening_scope_resolution = other.has_opening_scope_resolution;
-    locus = other.locus;
-    mappings = other.mappings;
-
-    segments.reserve (other.segments.size ());
-    for (const auto &e : other.segments)
-      segments.push_back (e->clone_type_path_segment ());
-
-    return *this;
-  }
+  TypePath &operator= (TypePath const &other);
 
   // move constructors
   TypePath (TypePath &&other) = default;
@@ -739,7 +584,7 @@ public:
   AST::SimplePath as_simple_path () const;
 
   // Creates a trait bound with a clone of this type path as its only element.
-  TraitBound *to_trait_bound (bool in_parens) const override;
+  std::unique_ptr<TraitBound> to_trait_bound (bool in_parens) const override;
 
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRTypeVisitor &vis) override;
@@ -751,10 +596,7 @@ public:
     return segments;
   }
 
-  std::unique_ptr<TypePathSegment> &get_final_segment ()
-  {
-    return segments.back ();
-  }
+  TypePathSegment &get_final_segment () { return *segments.back (); }
 };
 
 class QualifiedPathType
@@ -767,36 +609,16 @@ class QualifiedPathType
 public:
   // Constructor
   QualifiedPathType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type,
-                    std::unique_ptr<TypePath> trait, location_t locus)
-    : type (std::move (type)), trait (std::move (trait)), locus (locus),
-      mappings (mappings)
-  {}
+                    std::unique_ptr<TypePath> trait, location_t locus);
 
   // Copy constructor uses custom deep copy for Type to preserve polymorphism
-  QualifiedPathType (QualifiedPathType const &other)
-    : type (other.type->clone_type ()),
-      trait (other.has_as_clause () ? std::unique_ptr<HIR::TypePath> (
-              new HIR::TypePath (*other.trait))
-                                   : nullptr),
-      locus (other.locus), mappings (other.mappings)
-  {}
+  QualifiedPathType (QualifiedPathType const &other);
 
   // default destructor
   ~QualifiedPathType () = default;
 
   // overload assignment operator to use custom clone method
-  QualifiedPathType &operator= (QualifiedPathType const &other)
-  {
-    type = other.type->clone_type ();
-    locus = other.locus;
-    mappings = other.mappings;
-    trait
-      = other.has_as_clause ()
-         ? std::unique_ptr<HIR::TypePath> (new HIR::TypePath (*other.trait))
-         : nullptr;
-
-    return *this;
-  }
+  QualifiedPathType &operator= (QualifiedPathType const &other);
 
   // move constructor
   QualifiedPathType (QualifiedPathType &&other) = default;
@@ -815,26 +637,9 @@ public:
 
   TypePath &get_trait () { return *trait; }
 
-  bool trait_has_generic_args () const
-  {
-    rust_assert (has_as_clause ());
-    bool is_generic_seg = trait->get_final_segment ()->get_type ()
-                         == TypePathSegment::SegmentType::GENERIC;
-    if (!is_generic_seg)
-      return false;
-
-    TypePathSegmentGeneric *seg = static_cast<TypePathSegmentGeneric *> (
-      trait->get_final_segment ().get ());
-    return seg->has_generic_args ();
-  }
+  bool trait_has_generic_args () const;
 
-  GenericArgs &get_trait_generic_args ()
-  {
-    rust_assert (trait_has_generic_args ());
-    TypePathSegmentGeneric *seg = static_cast<TypePathSegmentGeneric *> (
-      trait->get_final_segment ().get ());
-    return seg->get_generic_args ();
-  }
+  GenericArgs &get_trait_generic_args ();
 };
 
 /* HIR node representing a qualified path-in-expression pattern (path that
@@ -852,11 +657,7 @@ public:
                             std::vector<PathExprSegment> path_segments,
                             location_t locus = UNDEF_LOCATION,
                             std::vector<AST::Attribute> outer_attrs
-                            = std::vector<AST::Attribute> ())
-    : PathPattern (std::move (path_segments)),
-      PathExpr (std::move (mappings), std::move (outer_attrs)),
-      path_type (std::move (qual_path_type)), locus (locus)
-  {}
+                            = std::vector<AST::Attribute> ());
 
   location_t get_locus () const override final { return locus; }
 
@@ -917,40 +718,13 @@ public:
     Analysis::NodeMapping mappings, QualifiedPathType qual_path_type,
     std::unique_ptr<TypePathSegment> associated_segment,
     std::vector<std::unique_ptr<TypePathSegment> > path_segments,
-    location_t locus = UNDEF_LOCATION)
-    : TypeNoBounds (mappings, locus), path_type (std::move (qual_path_type)),
-      associated_segment (std::move (associated_segment)),
-      segments (std::move (path_segments))
-  {}
+    location_t locus = UNDEF_LOCATION);
 
   // Copy constructor with vector clone
-  QualifiedPathInType (QualifiedPathInType const &other)
-    : TypeNoBounds (other.mappings, other.locus), path_type (other.path_type)
-  {
-    auto seg = other.associated_segment->clone_type_path_segment_impl ();
-    associated_segment = std::unique_ptr<TypePathSegment> (seg);
-
-    segments.reserve (other.segments.size ());
-    for (const auto &e : other.segments)
-      segments.push_back (e->clone_type_path_segment ());
-  }
+  QualifiedPathInType (QualifiedPathInType const &other);
 
   // Overloaded assignment operator with vector clone
-  QualifiedPathInType &operator= (QualifiedPathInType const &other)
-  {
-    auto seg = other.associated_segment->clone_type_path_segment_impl ();
-    associated_segment = std::unique_ptr<TypePathSegment> (seg);
-
-    path_type = other.path_type;
-    locus = other.locus;
-    mappings = other.mappings;
-
-    segments.reserve (other.segments.size ());
-    for (const auto &e : other.segments)
-      segments.push_back (e->clone_type_path_segment ());
-
-    return *this;
-  }
+  QualifiedPathInType &operator= (QualifiedPathInType const &other);
 
   // move constructors
   QualifiedPathInType (QualifiedPathInType &&other) = default;
@@ -971,40 +745,6 @@ public:
   }
 };
 
-class SimplePathSegment
-{
-  Analysis::NodeMapping mappings;
-
-public:
-  SimplePathSegment (Analysis::NodeMapping mappings) : mappings (mappings) {}
-
-  const Analysis::NodeMapping &get_mappings () const { return mappings; }
-};
-
-class SimplePath
-{
-  std::vector<SimplePathSegment> segments;
-  Analysis::NodeMapping mappings;
-  location_t locus;
-
-public:
-  SimplePath (std::vector<SimplePathSegment> segments,
-             Analysis::NodeMapping mappings, location_t locus)
-    : segments (std::move (segments)), mappings (mappings), locus (locus)
-  {}
-
-  static HIR::SimplePath create_empty ()
-  {
-    return HIR::SimplePath ({}, Analysis::NodeMapping::get_error (),
-                           UNDEF_LOCATION);
-  }
-
-  bool is_error () const { return segments.empty (); }
-
-  const Analysis::NodeMapping &get_mappings () const { return mappings; }
-  location_t get_locus () const { return locus; }
-};
-
 } // namespace HIR
 } // namespace Rust
 
diff --git a/gcc/rust/hir/tree/rust-hir-pattern-abstract.h b/gcc/rust/hir/tree/rust-hir-pattern-abstract.h
new file mode 100644 (file)
index 0000000..b156a80
--- /dev/null
@@ -0,0 +1,82 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_PATTERN_ABSTRACT_H
+#define RUST_HIR_PATTERN_ABSTRACT_H
+
+#include "rust-hir-visitable.h"
+#include "rust-hir-visitor.h"
+#include "rust-hir-node.h"
+#include "rust-system.h"
+
+namespace Rust {
+namespace HIR {
+
+// Pattern base HIR node
+class Pattern : public Node, virtual public FullVisitable
+{
+public:
+  using FullVisitable::accept_vis;
+
+  enum PatternType
+  {
+    PATH,
+    LITERAL,
+    IDENTIFIER,
+    WILDCARD,
+    RANGE,
+    REFERENCE,
+    STRUCT,
+    TUPLE_STRUCT,
+    TUPLE,
+    GROUPED,
+    SLICE,
+    ALT
+  };
+
+  BaseKind get_hir_kind () override final { return PATTERN; }
+
+  // Unique pointer custom clone function
+  std::unique_ptr<Pattern> clone_pattern () const
+  {
+    return std::unique_ptr<Pattern> (clone_pattern_impl ());
+  }
+
+  // possible virtual methods: is_refutable()
+
+  virtual ~Pattern () {}
+
+  virtual std::string as_string () const = 0;
+
+  virtual void accept_vis (HIRPatternVisitor &vis) = 0;
+
+  virtual const Analysis::NodeMapping &get_mappings () const = 0;
+
+  virtual location_t get_locus () const = 0;
+
+  virtual PatternType get_pattern_type () const = 0;
+
+protected:
+  // Clone pattern implementation as pure virtual method
+  virtual Pattern *clone_pattern_impl () const = 0;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif
index df26a396457654f83c9d33a40255b691a5d66cb0..5cc5c9512ecc406556ec8b379175b2bd1b86f81f 100644 (file)
 #ifndef RUST_HIR_PATTERN_H
 #define RUST_HIR_PATTERN_H
 
+#include "rust-hir-pattern-abstract.h"
 #include "rust-common.h"
-#include "rust-hir.h"
+#include "rust-hir-literal.h"
+#include "rust-hir-path.h"
 
 namespace Rust {
 namespace HIR {
-
 // Literal pattern HIR node (comparing to a literal)
 class LiteralPattern : public Pattern
 {
diff --git a/gcc/rust/hir/tree/rust-hir-simple-path.h b/gcc/rust/hir/tree/rust-hir-simple-path.h
new file mode 100644 (file)
index 0000000..7f832ff
--- /dev/null
@@ -0,0 +1,64 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_SIMPLE_PATH_H
+#define RUST_HIR_SIMPLE_PATH_H
+
+#include "rust-hir-map.h"
+
+namespace Rust {
+namespace HIR {
+
+class SimplePathSegment
+{
+  Analysis::NodeMapping mappings;
+
+public:
+  SimplePathSegment (Analysis::NodeMapping mappings) : mappings (mappings) {}
+
+  const Analysis::NodeMapping &get_mappings () const { return mappings; }
+};
+
+class SimplePath
+{
+  std::vector<SimplePathSegment> segments;
+  Analysis::NodeMapping mappings;
+  location_t locus;
+
+public:
+  SimplePath (std::vector<SimplePathSegment> segments,
+             Analysis::NodeMapping mappings, location_t locus)
+    : segments (std::move (segments)), mappings (mappings), locus (locus)
+  {}
+
+  static HIR::SimplePath create_empty ()
+  {
+    return HIR::SimplePath ({}, Analysis::NodeMapping::get_error (),
+                           UNDEF_LOCATION);
+  }
+
+  bool is_error () const { return segments.empty (); }
+
+  const Analysis::NodeMapping &get_mappings () const { return mappings; }
+  location_t get_locus () const { return locus; }
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-stmt.cc b/gcc/rust/hir/tree/rust-hir-stmt.cc
new file mode 100644 (file)
index 0000000..764ea11
--- /dev/null
@@ -0,0 +1,98 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-stmt.h"
+
+namespace Rust {
+namespace HIR {
+
+LetStmt::LetStmt (Analysis::NodeMapping mappings,
+                 std::unique_ptr<Pattern> variables_pattern,
+                 std::unique_ptr<Expr> init_expr, std::unique_ptr<Type> type,
+                 AST::AttrVec outer_attrs, location_t locus)
+  : Stmt (std::move (mappings)), outer_attrs (std::move (outer_attrs)),
+    variables_pattern (std::move (variables_pattern)), type (std::move (type)),
+    init_expr (std::move (init_expr)), locus (locus)
+{}
+
+LetStmt::LetStmt (LetStmt const &other)
+  : Stmt (other.mappings), outer_attrs (other.outer_attrs), locus (other.locus)
+{
+  // guard to prevent null dereference (only required if error state)
+  if (other.variables_pattern != nullptr)
+    variables_pattern = other.variables_pattern->clone_pattern ();
+
+  // guard to prevent null dereference (always required)
+  if (other.init_expr != nullptr)
+    init_expr = other.init_expr->clone_expr ();
+  if (other.type != nullptr)
+    type = other.type->clone_type ();
+}
+
+LetStmt &
+LetStmt::operator= (LetStmt const &other)
+{
+  outer_attrs = other.outer_attrs;
+  locus = other.locus;
+
+  // guard to prevent null dereference (only required if error state)
+  if (other.variables_pattern != nullptr)
+    variables_pattern = other.variables_pattern->clone_pattern ();
+  else
+    variables_pattern = nullptr;
+
+  // guard to prevent null dereference (always required)
+  if (other.init_expr != nullptr)
+    init_expr = other.init_expr->clone_expr ();
+  else
+    init_expr = nullptr;
+  if (other.type != nullptr)
+    type = other.type->clone_type ();
+  else
+    type = nullptr;
+
+  return *this;
+}
+
+ExprStmt::ExprStmt (Analysis::NodeMapping mappings, std::unique_ptr<Expr> expr,
+                   location_t locus, bool must_be_unit)
+  : Stmt (std::move (mappings)), expr (std::move (expr)), locus (locus),
+    must_be_unit (must_be_unit)
+{}
+
+ExprStmt::ExprStmt (Analysis::NodeMapping mappings, std::unique_ptr<Expr> expr,
+                   location_t locus)
+  : ExprStmt (std::move (mappings), std::move (expr), locus, false)
+{}
+
+ExprStmt::ExprStmt (ExprStmt const &other)
+  : Stmt (other), expr (other.expr->clone_expr ()), locus (other.locus)
+{}
+
+ExprStmt &
+ExprStmt::operator= (ExprStmt const &other)
+{
+  Stmt::operator= (other);
+  expr = other.expr->clone_expr ();
+  locus = other.locus;
+
+  return *this;
+}
+
+} // namespace HIR
+} // namespace Rust
index 7320bb623851de213967319fb4ae44b300b122e7..7540dfaaf348fd9e00f6db9187d2f9d091b65030 100644 (file)
 
 namespace Rust {
 namespace HIR {
+/* Base statement abstract class. Note that most "statements" are not allowed in
+ * top-level module scope - only a subclass of statements called "items" are. */
+class Stmt : public Node, public FullVisitable
+{
+public:
+  using FullVisitable::accept_vis;
+
+  // Unique pointer custom clone function
+  std::unique_ptr<Stmt> clone_stmt () const
+  {
+    return std::unique_ptr<Stmt> (clone_stmt_impl ());
+  }
+
+  BaseKind get_hir_kind () override { return STMT; }
+
+  virtual ~Stmt () {}
+
+  virtual std::string as_string () const = 0;
+
+  virtual void accept_vis (HIRStmtVisitor &vis) = 0;
+
+  virtual location_t get_locus () const = 0;
+
+  virtual bool is_unit_check_needed () const { return false; }
+
+  const Analysis::NodeMapping &get_mappings () const { return mappings; }
+
+  virtual bool is_item () const = 0;
+
+protected:
+  Stmt (Analysis::NodeMapping mappings) : mappings (std::move (mappings)) {}
+
+  // Clone function implementation as pure virtual method
+  virtual Stmt *clone_stmt_impl () const = 0;
+
+  Analysis::NodeMapping mappings;
+};
+
 // Just a semi-colon, which apparently is a statement.
 class EmptyStmt : public Stmt
 {
@@ -82,52 +120,13 @@ public:
   LetStmt (Analysis::NodeMapping mappings,
           std::unique_ptr<Pattern> variables_pattern,
           std::unique_ptr<Expr> init_expr, std::unique_ptr<Type> type,
-          AST::AttrVec outer_attrs, location_t locus)
-    : Stmt (std::move (mappings)), outer_attrs (std::move (outer_attrs)),
-      variables_pattern (std::move (variables_pattern)),
-      type (std::move (type)), init_expr (std::move (init_expr)), locus (locus)
-  {}
+          AST::AttrVec outer_attrs, location_t locus);
 
   // Copy constructor with clone
-  LetStmt (LetStmt const &other)
-    : Stmt (other.mappings), outer_attrs (other.outer_attrs),
-      locus (other.locus)
-  {
-    // guard to prevent null dereference (only required if error state)
-    if (other.variables_pattern != nullptr)
-      variables_pattern = other.variables_pattern->clone_pattern ();
-
-    // guard to prevent null dereference (always required)
-    if (other.init_expr != nullptr)
-      init_expr = other.init_expr->clone_expr ();
-    if (other.type != nullptr)
-      type = other.type->clone_type ();
-  }
+  LetStmt (LetStmt const &other);
 
   // Overloaded assignment operator to clone
-  LetStmt &operator= (LetStmt const &other)
-  {
-    outer_attrs = other.outer_attrs;
-    locus = other.locus;
-
-    // guard to prevent null dereference (only required if error state)
-    if (other.variables_pattern != nullptr)
-      variables_pattern = other.variables_pattern->clone_pattern ();
-    else
-      variables_pattern = nullptr;
-
-    // guard to prevent null dereference (always required)
-    if (other.init_expr != nullptr)
-      init_expr = other.init_expr->clone_expr ();
-    else
-      init_expr = nullptr;
-    if (other.type != nullptr)
-      type = other.type->clone_type ();
-    else
-      type = nullptr;
-
-    return *this;
-  }
+  LetStmt &operator= (LetStmt const &other);
 
   // move constructors
   LetStmt (LetStmt &&other) = default;
@@ -167,15 +166,10 @@ class ExprStmt : public Stmt
 
 public:
   ExprStmt (Analysis::NodeMapping mappings, std::unique_ptr<Expr> expr,
-           location_t locus, bool must_be_unit)
-    : Stmt (std::move (mappings)), expr (std::move (expr)), locus (locus),
-      must_be_unit (must_be_unit)
-  {}
+           location_t locus, bool must_be_unit);
 
   ExprStmt (Analysis::NodeMapping mappings, std::unique_ptr<Expr> expr,
-           location_t locus)
-    : ExprStmt (std::move (mappings), std::move (expr), locus, false)
-  {}
+           location_t locus);
 
   std::string as_string () const override;
 
@@ -189,19 +183,10 @@ public:
   Expr &get_expr () { return *expr; }
 
   // Copy constructor with clone
-  ExprStmt (ExprStmt const &other)
-    : Stmt (other), expr (other.expr->clone_expr ()), locus (other.locus)
-  {}
+  ExprStmt (ExprStmt const &other);
 
   // Overloaded assignment operator to clone
-  ExprStmt &operator= (ExprStmt const &other)
-  {
-    Stmt::operator= (other);
-    expr = other.expr->clone_expr ();
-    locus = other.locus;
-
-    return *this;
-  }
+  ExprStmt &operator= (ExprStmt const &other);
 
   // move constructors
   ExprStmt (ExprStmt &&other) = default;
diff --git a/gcc/rust/hir/tree/rust-hir-trait-bound.h b/gcc/rust/hir/tree/rust-hir-trait-bound.h
new file mode 100644 (file)
index 0000000..d20fa79
--- /dev/null
@@ -0,0 +1,87 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_TRAIT_BOUND_H
+#define RUST_HIR_TRAIT_BOUND_H
+
+#include "rust-hir-bound-abstract.h"
+#include "rust-hir-path.h"
+#include "rust-hir-generic-param.h"
+
+namespace Rust {
+namespace HIR {
+
+// A trait bound
+class TraitBound : public TypeParamBound
+{
+  bool in_parens;
+  BoundPolarity polarity;
+  std::vector<LifetimeParam> for_lifetimes;
+  TypePath type_path;
+  location_t locus;
+
+  Analysis::NodeMapping mappings;
+
+public:
+  // Returns whether trait bound has "for" lifetimes
+  bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
+
+  TraitBound (Analysis::NodeMapping mapping, TypePath type_path,
+             location_t locus, bool in_parens = false,
+             BoundPolarity polarity = BoundPolarity::RegularBound,
+             std::vector<LifetimeParam> for_lifetimes
+             = std::vector<LifetimeParam> ())
+    : in_parens (in_parens), polarity (polarity),
+      for_lifetimes (std::move (for_lifetimes)),
+      type_path (std::move (type_path)), locus (locus), mappings (mapping)
+  {}
+
+  std::string as_string () const override;
+
+  location_t get_locus () const override final { return locus; }
+
+  void accept_vis (HIRFullVisitor &vis) override;
+
+  Analysis::NodeMapping get_mappings () const override final
+  {
+    return mappings;
+  }
+
+  std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
+  bool get_in_parens () { return in_parens; }
+  BoundPolarity get_polarity () { return polarity; }
+
+  BoundType get_bound_type () const final override { return TRAITBOUND; }
+
+  TypePath &get_path () { return type_path; }
+
+  const TypePath &get_path () const { return type_path; }
+
+protected:
+  /* Use covariance to implement clone function as returning this object rather
+   * than base */
+  TraitBound *clone_type_param_bound_impl () const override
+  {
+    return new TraitBound (*this);
+  }
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-type-abstract.cc b/gcc/rust/hir/tree/rust-hir-type-abstract.cc
new file mode 100644 (file)
index 0000000..901c603
--- /dev/null
@@ -0,0 +1,32 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-type-abstract.h"
+#include "rust-hir-trait-bound.h"
+
+namespace Rust {
+namespace HIR {
+
+std::unique_ptr<TraitBound>
+Type::to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const
+{
+  return std::unique_ptr<TraitBound> (nullptr);
+}
+
+} // namespace HIR
+} // namespace Rust
diff --git a/gcc/rust/hir/tree/rust-hir-type-abstract.h b/gcc/rust/hir/tree/rust-hir-type-abstract.h
new file mode 100644 (file)
index 0000000..6142d88
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_TYPE_ABSTRACT_H
+#define RUST_HIR_TYPE_ABSTRACT_H
+
+#include "rust-hir-node.h"
+#include "rust-hir-visitable.h"
+#include "rust-system.h"
+#include "rust-hir-map.h"
+
+namespace Rust {
+namespace HIR {
+
+class TraitBound;
+
+// Base class for types as represented in HIR - abstract
+class Type : public Node, public FullVisitable
+{
+public:
+  using FullVisitable::accept_vis;
+  // Unique pointer custom clone function
+  std::unique_ptr<Type> clone_type () const
+  {
+    return std::unique_ptr<Type> (clone_type_impl ());
+  }
+
+  // virtual destructor
+  virtual ~Type () {}
+
+  BaseKind get_hir_kind () override final { return TYPE; }
+
+  virtual std::string as_string () const = 0;
+
+  /* HACK: convert to trait bound. Virtual method overriden by classes that
+   * enable this. */
+  virtual std::unique_ptr<TraitBound>
+  to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const;
+  /* as pointer, shouldn't require definition beforehand, only forward
+   * declaration. */
+
+  virtual void accept_vis (HIRTypeVisitor &vis) = 0;
+
+  virtual const Analysis::NodeMapping &get_mappings () const
+  {
+    return mappings;
+  }
+  virtual location_t get_locus () const { return locus; }
+
+protected:
+  Type (Analysis::NodeMapping mappings, location_t locus)
+    : mappings (mappings), locus (locus)
+  {}
+
+  // Clone function implementation as pure virtual method
+  virtual Type *clone_type_impl () const = 0;
+
+  Analysis::NodeMapping mappings;
+  location_t locus;
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-type-no-bounds.h b/gcc/rust/hir/tree/rust-hir-type-no-bounds.h
new file mode 100644 (file)
index 0000000..b86ff30
--- /dev/null
@@ -0,0 +1,58 @@
+
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_TYPE_NO_BOUNDS_H
+#define RUST_HIR_TYPE_NO_BOUNDS_H
+
+#include "rust-hir-type-abstract.h"
+
+namespace Rust {
+namespace HIR {
+
+// A type without parentheses? - abstract
+class TypeNoBounds : public Type
+{
+public:
+  // Unique pointer custom clone function
+  std::unique_ptr<TypeNoBounds> clone_type_no_bounds () const
+  {
+    return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ());
+  }
+
+protected:
+  TypeNoBounds (Analysis::NodeMapping mappings, location_t locus)
+    : Type (mappings, locus)
+  {}
+
+  // Clone function implementation as pure virtual method
+  virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;
+
+  /* Save having to specify two clone methods in derived classes by making type
+   * clone return typenobounds clone. Hopefully won't affect performance too
+   * much. */
+  TypeNoBounds *clone_type_impl () const override
+  {
+    return clone_type_no_bounds_impl ();
+  }
+};
+
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-type.cc b/gcc/rust/hir/tree/rust-hir-type.cc
new file mode 100644 (file)
index 0000000..689d86b
--- /dev/null
@@ -0,0 +1,289 @@
+
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-hir-type.h"
+
+namespace Rust {
+namespace HIR {
+
+ImplTraitType::ImplTraitType (
+  Analysis::NodeMapping mappings,
+  std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
+  location_t locus)
+  : Type (mappings, locus), type_param_bounds (std::move (type_param_bounds))
+{}
+
+ImplTraitType::ImplTraitType (ImplTraitType const &other)
+  : Type (other.mappings, other.locus)
+{
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+}
+
+ImplTraitType &
+ImplTraitType::operator= (ImplTraitType const &other)
+{
+  locus = other.locus;
+  mappings = other.mappings;
+
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+
+  return *this;
+}
+
+TraitObjectType::TraitObjectType (
+  Analysis::NodeMapping mappings,
+  std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
+  location_t locus, bool is_dyn_dispatch)
+  : Type (mappings, locus), has_dyn (is_dyn_dispatch),
+    type_param_bounds (std::move (type_param_bounds))
+{}
+
+TraitObjectType::TraitObjectType (TraitObjectType const &other)
+  : Type (other.mappings, other.locus), has_dyn (other.has_dyn)
+{
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+}
+
+TraitObjectType &
+TraitObjectType::operator= (TraitObjectType const &other)
+{
+  mappings = other.mappings;
+  has_dyn = other.has_dyn;
+  locus = other.locus;
+  type_param_bounds.reserve (other.type_param_bounds.size ());
+  for (const auto &e : other.type_param_bounds)
+    type_param_bounds.push_back (e->clone_type_param_bound ());
+
+  return *this;
+}
+
+ParenthesisedType::ParenthesisedType (Analysis::NodeMapping mappings,
+                                     std::unique_ptr<Type> type_inside_parens,
+                                     location_t locus)
+  : TypeNoBounds (mappings, locus),
+    type_in_parens (std::move (type_inside_parens))
+{}
+
+ParenthesisedType::ParenthesisedType (ParenthesisedType const &other)
+  : TypeNoBounds (other.mappings, other.locus),
+    type_in_parens (other.type_in_parens->clone_type ())
+{}
+
+ParenthesisedType &
+ParenthesisedType::operator= (ParenthesisedType const &other)
+{
+  mappings = other.mappings;
+  type_in_parens = other.type_in_parens->clone_type ();
+  locus = other.locus;
+  return *this;
+}
+
+std::unique_ptr<TraitBound>
+ParenthesisedType::to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const
+{
+  /* NOTE: obviously it is unknown whether the internal type is a trait bound
+   * due to polymorphism, so just let the internal type handle it. As
+   * parenthesised type, it must be in parentheses. */
+  return type_in_parens->to_trait_bound (true);
+}
+
+TupleType::TupleType (Analysis::NodeMapping mappings,
+                     std::vector<std::unique_ptr<Type>> elems,
+                     location_t locus)
+  : TypeNoBounds (mappings, locus), elems (std::move (elems))
+{}
+
+TupleType::TupleType (TupleType const &other)
+  : TypeNoBounds (other.mappings, other.locus)
+{
+  mappings = other.mappings;
+  elems.reserve (other.elems.size ());
+  for (const auto &e : other.elems)
+    elems.push_back (e->clone_type ());
+}
+
+TupleType &
+TupleType::operator= (TupleType const &other)
+{
+  locus = other.locus;
+
+  elems.reserve (other.elems.size ());
+  for (const auto &e : other.elems)
+    elems.push_back (e->clone_type ());
+
+  return *this;
+}
+
+NeverType::NeverType (Analysis::NodeMapping mappings, location_t locus)
+  : TypeNoBounds (mappings, locus)
+{}
+
+RawPointerType::RawPointerType (Analysis::NodeMapping mappings, Mutability mut,
+                               std::unique_ptr<Type> type, location_t locus)
+  : TypeNoBounds (mappings, locus), mut (mut), type (std::move (type))
+{}
+
+RawPointerType::RawPointerType (RawPointerType const &other)
+  : TypeNoBounds (other.mappings, other.locus), mut (other.mut),
+    type (other.type->clone_type ())
+{}
+
+RawPointerType &
+RawPointerType::operator= (RawPointerType const &other)
+{
+  mappings = other.mappings;
+  mut = other.mut;
+  type = other.type->clone_type ();
+  locus = other.locus;
+  return *this;
+}
+
+ReferenceType::ReferenceType (Analysis::NodeMapping mappings, Mutability mut,
+                             std::unique_ptr<Type> type_no_bounds,
+                             location_t locus, Lifetime lifetime)
+  : TypeNoBounds (mappings, locus), lifetime (std::move (lifetime)), mut (mut),
+    type (std::move (type_no_bounds))
+{}
+
+ReferenceType::ReferenceType (ReferenceType const &other)
+  : TypeNoBounds (other.mappings, other.locus), lifetime (other.lifetime),
+    mut (other.mut), type (other.type->clone_type ())
+{}
+
+ReferenceType &
+ReferenceType::operator= (ReferenceType const &other)
+{
+  mappings = other.mappings;
+  lifetime = other.lifetime;
+  mut = other.mut;
+  type = other.type->clone_type ();
+  locus = other.locus;
+
+  return *this;
+}
+
+ArrayType::ArrayType (Analysis::NodeMapping mappings,
+                     std::unique_ptr<Type> type,
+                     std::unique_ptr<Expr> array_size, location_t locus)
+  : TypeNoBounds (mappings, locus), elem_type (std::move (type)),
+    size (std::move (array_size))
+{}
+
+ArrayType::ArrayType (ArrayType const &other)
+  : TypeNoBounds (other.mappings, other.locus),
+    elem_type (other.elem_type->clone_type ()), size (other.size->clone_expr ())
+{}
+
+ArrayType &
+ArrayType::operator= (ArrayType const &other)
+{
+  mappings = other.mappings;
+  elem_type = other.elem_type->clone_type ();
+  size = other.size->clone_expr ();
+  locus = other.locus;
+  return *this;
+}
+
+SliceType::SliceType (Analysis::NodeMapping mappings,
+                     std::unique_ptr<Type> type, location_t locus)
+  : TypeNoBounds (mappings, locus), elem_type (std::move (type))
+{}
+
+SliceType::SliceType (SliceType const &other)
+  : TypeNoBounds (other.mappings, other.locus),
+    elem_type (other.elem_type->clone_type ())
+{}
+
+SliceType &
+SliceType::operator= (SliceType const &other)
+{
+  mappings = other.mappings;
+  elem_type = other.elem_type->clone_type ();
+  locus = other.locus;
+
+  return *this;
+}
+
+InferredType::InferredType (Analysis::NodeMapping mappings, location_t locus)
+  : TypeNoBounds (mappings, locus)
+{}
+
+MaybeNamedParam::MaybeNamedParam (Identifier name, ParamKind param_kind,
+                                 std::unique_ptr<Type> param_type,
+                                 location_t locus)
+  : param_type (std::move (param_type)), param_kind (param_kind),
+    name (std::move (name)), locus (locus)
+{}
+
+MaybeNamedParam::MaybeNamedParam (MaybeNamedParam const &other)
+  : param_type (other.param_type->clone_type ()), param_kind (other.param_kind),
+    name (other.name), locus (other.locus)
+{}
+
+MaybeNamedParam &
+MaybeNamedParam::operator= (MaybeNamedParam const &other)
+{
+  name = other.name;
+  param_kind = other.param_kind;
+  param_type = other.param_type->clone_type ();
+  locus = other.locus;
+
+  return *this;
+}
+
+BareFunctionType::BareFunctionType (
+  Analysis::NodeMapping mappings, std::vector<LifetimeParam> lifetime_params,
+  FunctionQualifiers qualifiers, std::vector<MaybeNamedParam> named_params,
+  bool is_variadic, std::unique_ptr<Type> type, location_t locus)
+  : TypeNoBounds (mappings, locus), for_lifetimes (std::move (lifetime_params)),
+    function_qualifiers (std::move (qualifiers)),
+    params (std::move (named_params)), is_variadic (is_variadic),
+    return_type (std::move (type))
+{}
+
+BareFunctionType::BareFunctionType (BareFunctionType const &other)
+  : TypeNoBounds (other.mappings, other.locus),
+    for_lifetimes (other.for_lifetimes),
+    function_qualifiers (other.function_qualifiers), params (other.params),
+    is_variadic (other.is_variadic),
+    return_type (other.return_type->clone_type ())
+{}
+
+BareFunctionType &
+BareFunctionType::operator= (BareFunctionType const &other)
+{
+  mappings = other.mappings;
+  for_lifetimes = other.for_lifetimes;
+  function_qualifiers = other.function_qualifiers;
+  params = other.params;
+  is_variadic = other.is_variadic;
+  return_type = other.return_type->clone_type ();
+  locus = other.locus;
+
+  return *this;
+}
+
+} // namespace HIR
+} // namespace Rust
index 26c3d2dfa49f0d7c4c345a4677c1e799f5f6d2cd..e231d78b2ceddeac29cefe963fbc1a2bdd42c275 100644 (file)
 #ifndef RUST_HIR_TYPE_H
 #define RUST_HIR_TYPE_H
 
+#include "rust-hir-type-abstract.h"
 #include "rust-common.h"
-#include "rust-hir.h"
-#include "rust-hir-path.h"
+#include "rust-hir-trait-bound.h"
+#include "rust-hir-item.h"
 
 namespace Rust {
 namespace HIR {
-// definitions moved to rust-ast.h
-class TypeParamBound;
-class Lifetime;
-
-// A trait bound
-class TraitBound : public TypeParamBound
-{
-  bool in_parens;
-  BoundPolarity polarity;
-  std::vector<LifetimeParam> for_lifetimes;
-  TypePath type_path;
-  location_t locus;
-
-  Analysis::NodeMapping mappings;
-
-public:
-  // Returns whether trait bound has "for" lifetimes
-  bool has_for_lifetimes () const { return !for_lifetimes.empty (); }
-
-  TraitBound (Analysis::NodeMapping mapping, TypePath type_path,
-             location_t locus, bool in_parens = false,
-             BoundPolarity polarity = BoundPolarity::RegularBound,
-             std::vector<LifetimeParam> for_lifetimes
-             = std::vector<LifetimeParam> ())
-    : in_parens (in_parens), polarity (polarity),
-      for_lifetimes (std::move (for_lifetimes)),
-      type_path (std::move (type_path)), locus (locus), mappings (mapping)
-  {}
-
-  std::string as_string () const override;
-
-  location_t get_locus () const override final { return locus; }
-
-  void accept_vis (HIRFullVisitor &vis) override;
-
-  Analysis::NodeMapping get_mappings () const override final
-  {
-    return mappings;
-  }
-
-  std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; }
-  bool get_in_parens () { return in_parens; }
-  BoundPolarity get_polarity () { return polarity; }
-
-  BoundType get_bound_type () const final override { return TRAITBOUND; }
-
-  TypePath &get_path () { return type_path; }
-
-  const TypePath &get_path () const { return type_path; }
-
-protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
-  TraitBound *clone_type_param_bound_impl () const override
-  {
-    return new TraitBound (*this);
-  }
-};
-
-// definition moved to rust-ast.h
-class TypeNoBounds;
 
 // An impl trait? Poor reference material here.
 class ImplTraitType : public Type
@@ -105,31 +45,13 @@ protected:
 public:
   ImplTraitType (Analysis::NodeMapping mappings,
                 std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
-                location_t locus)
-    : Type (mappings, locus), type_param_bounds (std::move (type_param_bounds))
-  {}
+                location_t locus);
 
   // copy constructor with vector clone
-  ImplTraitType (ImplTraitType const &other)
-    : Type (other.mappings, other.locus)
-  {
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-  }
+  ImplTraitType (ImplTraitType const &other);
 
   // overloaded assignment operator to clone
-  ImplTraitType &operator= (ImplTraitType const &other)
-  {
-    locus = other.locus;
-    mappings = other.mappings;
-
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-
-    return *this;
-  }
+  ImplTraitType &operator= (ImplTraitType const &other);
 
   // move constructors
   ImplTraitType (ImplTraitType &&other) = default;
@@ -162,32 +84,13 @@ public:
   TraitObjectType (
     Analysis::NodeMapping mappings,
     std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
-    location_t locus, bool is_dyn_dispatch)
-    : Type (mappings, locus), has_dyn (is_dyn_dispatch),
-      type_param_bounds (std::move (type_param_bounds))
-  {}
+    location_t locus, bool is_dyn_dispatch);
 
   // copy constructor with vector clone
-  TraitObjectType (TraitObjectType const &other)
-    : Type (other.mappings, other.locus), has_dyn (other.has_dyn)
-  {
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-  }
+  TraitObjectType (TraitObjectType const &other);
 
   // overloaded assignment operator to clone
-  TraitObjectType &operator= (TraitObjectType const &other)
-  {
-    mappings = other.mappings;
-    has_dyn = other.has_dyn;
-    locus = other.locus;
-    type_param_bounds.reserve (other.type_param_bounds.size ());
-    for (const auto &e : other.type_param_bounds)
-      type_param_bounds.push_back (e->clone_type_param_bound ());
-
-    return *this;
-  }
+  TraitObjectType &operator= (TraitObjectType const &other);
 
   // move constructors
   TraitObjectType (TraitObjectType &&other) = default;
@@ -233,26 +136,15 @@ protected:
 public:
   // Constructor uses Type pointer for polymorphism
   ParenthesisedType (Analysis::NodeMapping mappings,
-                    std::unique_ptr<Type> type_inside_parens, location_t locus)
-    : TypeNoBounds (mappings, locus),
-      type_in_parens (std::move (type_inside_parens))
-  {}
+                    std::unique_ptr<Type> type_inside_parens,
+                    location_t locus);
 
   /* Copy constructor uses custom deep copy method for type to preserve
    * polymorphism */
-  ParenthesisedType (ParenthesisedType const &other)
-    : TypeNoBounds (other.mappings, other.locus),
-      type_in_parens (other.type_in_parens->clone_type ())
-  {}
+  ParenthesisedType (ParenthesisedType const &other);
 
   // overload assignment operator to use custom clone method
-  ParenthesisedType &operator= (ParenthesisedType const &other)
-  {
-    mappings = other.mappings;
-    type_in_parens = other.type_in_parens->clone_type ();
-    locus = other.locus;
-    return *this;
-  }
+  ParenthesisedType &operator= (ParenthesisedType const &other);
 
   // default move semantics
   ParenthesisedType (ParenthesisedType &&other) = default;
@@ -264,13 +156,9 @@ public:
   }
 
   // Creates a trait bound (clone of this one's trait bound) - HACK
-  TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const override
-  {
-    /* NOTE: obviously it is unknown whether the internal type is a trait bound
-     * due to polymorphism, so just let the internal type handle it. As
-     * parenthesised type, it must be in parentheses. */
-    return type_in_parens->to_trait_bound (true);
-  }
+  std::unique_ptr<TraitBound>
+  to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const override;
+
   Type &get_type_in_parens () { return *type_in_parens; }
   void accept_vis (HIRFullVisitor &vis) override;
   void accept_vis (HIRTypeVisitor &vis) override;
@@ -308,8 +196,6 @@ public:
   void accept_vis (HIRTypeVisitor &vis) override;
 };
 
-class TypePath; // definition moved to "rust-path.h"
-
 /* A type consisting of the "product" of others (the tuple's elements) in a
  * specific order */
 class TupleType : public TypeNoBounds
@@ -321,31 +207,13 @@ public:
   bool is_unit_type () const { return elems.empty (); }
 
   TupleType (Analysis::NodeMapping mappings,
-            std::vector<std::unique_ptr<Type>> elems, location_t locus)
-    : TypeNoBounds (mappings, locus), elems (std::move (elems))
-  {}
+            std::vector<std::unique_ptr<Type>> elems, location_t locus);
 
   // copy constructor with vector clone
-  TupleType (TupleType const &other)
-    : TypeNoBounds (other.mappings, other.locus)
-  {
-    mappings = other.mappings;
-    elems.reserve (other.elems.size ());
-    for (const auto &e : other.elems)
-      elems.push_back (e->clone_type ());
-  }
+  TupleType (TupleType const &other);
 
   // overloaded assignment operator to clone
-  TupleType &operator= (TupleType const &other)
-  {
-    locus = other.locus;
-
-    elems.reserve (other.elems.size ());
-    for (const auto &e : other.elems)
-      elems.push_back (e->clone_type ());
-
-    return *this;
-  }
+  TupleType &operator= (TupleType const &other);
 
   // move constructors
   TupleType (TupleType &&other) = default;
@@ -390,9 +258,7 @@ protected:
   }
 
 public:
-  NeverType (Analysis::NodeMapping mappings, location_t locus)
-    : TypeNoBounds (mappings, locus)
-  {}
+  NeverType (Analysis::NodeMapping mappings, location_t locus);
 
   std::string as_string () const override { return "! (never type)"; }
 
@@ -410,25 +276,13 @@ private:
 public:
   // Constructor requires pointer for polymorphism reasons
   RawPointerType (Analysis::NodeMapping mappings, Mutability mut,
-                 std::unique_ptr<Type> type, location_t locus)
-    : TypeNoBounds (mappings, locus), mut (mut), type (std::move (type))
-  {}
+                 std::unique_ptr<Type> type, location_t locus);
 
   // Copy constructor calls custom polymorphic clone function
-  RawPointerType (RawPointerType const &other)
-    : TypeNoBounds (other.mappings, other.locus), mut (other.mut),
-      type (other.type->clone_type ())
-  {}
+  RawPointerType (RawPointerType const &other);
 
   // overload assignment operator to use custom clone method
-  RawPointerType &operator= (RawPointerType const &other)
-  {
-    mappings = other.mappings;
-    mut = other.mut;
-    type = other.type->clone_type ();
-    locus = other.locus;
-    return *this;
-  }
+  RawPointerType &operator= (RawPointerType const &other);
 
   // default move semantics
   RawPointerType (RawPointerType &&other) = default;
@@ -484,28 +338,13 @@ public:
   // Constructor
   ReferenceType (Analysis::NodeMapping mappings, Mutability mut,
                 std::unique_ptr<Type> type_no_bounds, location_t locus,
-                Lifetime lifetime)
-    : TypeNoBounds (mappings, locus), lifetime (std::move (lifetime)),
-      mut (mut), type (std::move (type_no_bounds))
-  {}
+                Lifetime lifetime);
 
   // Copy constructor with custom clone method
-  ReferenceType (ReferenceType const &other)
-    : TypeNoBounds (other.mappings, other.locus), lifetime (other.lifetime),
-      mut (other.mut), type (other.type->clone_type ())
-  {}
+  ReferenceType (ReferenceType const &other);
 
   // Operator overload assignment operator to custom clone the unique pointer
-  ReferenceType &operator= (ReferenceType const &other)
-  {
-    mappings = other.mappings;
-    lifetime = other.lifetime;
-    mut = other.mut;
-    type = other.type->clone_type ();
-    locus = other.locus;
-
-    return *this;
-  }
+  ReferenceType &operator= (ReferenceType const &other);
 
   // move constructors
   ReferenceType (ReferenceType &&other) = default;
@@ -547,27 +386,13 @@ class ArrayType : public TypeNoBounds
 public:
   // Constructor requires pointers for polymorphism
   ArrayType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type,
-            std::unique_ptr<Expr> array_size, location_t locus)
-    : TypeNoBounds (mappings, locus), elem_type (std::move (type)),
-      size (std::move (array_size))
-  {}
+            std::unique_ptr<Expr> array_size, location_t locus);
 
   // Copy constructor requires deep copies of both unique pointers
-  ArrayType (ArrayType const &other)
-    : TypeNoBounds (other.mappings, other.locus),
-      elem_type (other.elem_type->clone_type ()),
-      size (other.size->clone_expr ())
-  {}
+  ArrayType (ArrayType const &other);
 
   // Overload assignment operator to deep copy pointers
-  ArrayType &operator= (ArrayType const &other)
-  {
-    mappings = other.mappings;
-    elem_type = other.elem_type->clone_type ();
-    size = other.size->clone_expr ();
-    locus = other.locus;
-    return *this;
-  }
+  ArrayType &operator= (ArrayType const &other);
 
   // move constructors
   ArrayType (ArrayType &&other) = default;
@@ -604,25 +429,13 @@ class SliceType : public TypeNoBounds
 public:
   // Constructor requires pointer for polymorphism
   SliceType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type,
-            location_t locus)
-    : TypeNoBounds (mappings, locus), elem_type (std::move (type))
-  {}
+            location_t locus);
 
   // Copy constructor requires deep copy of Type smart pointer
-  SliceType (SliceType const &other)
-    : TypeNoBounds (other.mappings, other.locus),
-      elem_type (other.elem_type->clone_type ())
-  {}
+  SliceType (SliceType const &other);
 
   // Overload assignment operator to deep copy
-  SliceType &operator= (SliceType const &other)
-  {
-    mappings = other.mappings;
-    elem_type = other.elem_type->clone_type ();
-    locus = other.locus;
-
-    return *this;
-  }
+  SliceType &operator= (SliceType const &other);
 
   // move constructors
   SliceType (SliceType &&other) = default;
@@ -669,9 +482,7 @@ protected:
   }
 
 public:
-  InferredType (Analysis::NodeMapping mappings, location_t locus)
-    : TypeNoBounds (mappings, locus)
-  {}
+  InferredType (Analysis::NodeMapping mappings, location_t locus);
 
   std::string as_string () const override;
 
@@ -679,8 +490,6 @@ public:
   void accept_vis (HIRTypeVisitor &vis) override;
 };
 
-class QualifiedPathInType; // definition moved to "rust-path.h"
-
 // A possibly named param used in a BaseFunctionType
 struct MaybeNamedParam
 {
@@ -702,29 +511,15 @@ private:
 
 public:
   MaybeNamedParam (Identifier name, ParamKind param_kind,
-                  std::unique_ptr<Type> param_type, location_t locus)
-    : param_type (std::move (param_type)), param_kind (param_kind),
-      name (std::move (name)), locus (locus)
-  {}
+                  std::unique_ptr<Type> param_type, location_t locus);
 
   // Copy constructor with clone
-  MaybeNamedParam (MaybeNamedParam const &other)
-    : param_type (other.param_type->clone_type ()),
-      param_kind (other.param_kind), name (other.name), locus (other.locus)
-  {}
+  MaybeNamedParam (MaybeNamedParam const &other);
 
   ~MaybeNamedParam () = default;
 
   // Overloaded assignment operator with clone
-  MaybeNamedParam &operator= (MaybeNamedParam const &other)
-  {
-    name = other.name;
-    param_kind = other.param_kind;
-    param_type = other.param_type->clone_type ();
-    locus = other.locus;
-
-    return *this;
-  }
+  MaybeNamedParam &operator= (MaybeNamedParam const &other);
 
   // move constructors
   MaybeNamedParam (MaybeNamedParam &&other) = default;
@@ -777,36 +572,13 @@ public:
                    std::vector<LifetimeParam> lifetime_params,
                    FunctionQualifiers qualifiers,
                    std::vector<MaybeNamedParam> named_params, bool is_variadic,
-                   std::unique_ptr<Type> type, location_t locus)
-    : TypeNoBounds (mappings, locus),
-      for_lifetimes (std::move (lifetime_params)),
-      function_qualifiers (std::move (qualifiers)),
-      params (std::move (named_params)), is_variadic (is_variadic),
-      return_type (std::move (type))
-  {}
+                   std::unique_ptr<Type> type, location_t locus);
 
   // Copy constructor with clone
-  BareFunctionType (BareFunctionType const &other)
-    : TypeNoBounds (other.mappings, other.locus),
-      for_lifetimes (other.for_lifetimes),
-      function_qualifiers (other.function_qualifiers), params (other.params),
-      is_variadic (other.is_variadic),
-      return_type (other.return_type->clone_type ())
-  {}
+  BareFunctionType (BareFunctionType const &other);
 
   // Overload assignment operator to deep copy
-  BareFunctionType &operator= (BareFunctionType const &other)
-  {
-    mappings = other.mappings;
-    for_lifetimes = other.for_lifetimes;
-    function_qualifiers = other.function_qualifiers;
-    params = other.params;
-    is_variadic = other.is_variadic;
-    return_type = other.return_type->clone_type ();
-    locus = other.locus;
-
-    return *this;
-  }
+  BareFunctionType &operator= (BareFunctionType const &other);
 
   // move constructors
   BareFunctionType (BareFunctionType &&other) = default;
diff --git a/gcc/rust/hir/tree/rust-hir-visibility.h b/gcc/rust/hir/tree/rust-hir-visibility.h
new file mode 100644 (file)
index 0000000..a750d88
--- /dev/null
@@ -0,0 +1,80 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_VISIBILITY_H
+#define RUST_HIR_VISIBILITY_H
+
+#include "rust-hir-simple-path.h"
+
+namespace Rust {
+namespace HIR {
+// Visibility of an item
+struct Visibility
+{
+public:
+  enum VisType
+  {
+    PRIVATE,
+    PUBLIC,
+    RESTRICTED,
+    ERROR,
+  };
+
+private:
+  VisType vis_type;
+  HIR::SimplePath path;
+  location_t locus;
+
+  // should this store location info?
+
+public:
+  Visibility (VisType vis_type,
+             HIR::SimplePath path = HIR::SimplePath::create_empty (),
+             location_t locus = UNDEF_LOCATION)
+    : vis_type (vis_type), path (std::move (path)), locus (locus)
+  {}
+
+  // Returns whether visibility is in an error state.
+  bool is_error () const { return vis_type == ERROR; }
+
+  // Does the current visibility refer to a simple `pub <item>` entirely public
+  bool is_public () const { return vis_type == PUBLIC; }
+
+  // Is the current visibility public restricted to a certain path
+  bool is_restricted () const { return vis_type == RESTRICTED; }
+
+  // Creates an error visibility.
+  static Visibility create_error ()
+  {
+    return Visibility (ERROR, HIR::SimplePath::create_empty ());
+  }
+
+  VisType get_vis_type () const { return vis_type; }
+
+  const HIR::SimplePath &get_path () const
+  {
+    rust_assert (!is_error ());
+    return path;
+  }
+
+  std::string as_string () const;
+};
+} // namespace HIR
+} // namespace Rust
+
+#endif
diff --git a/gcc/rust/hir/tree/rust-hir-visitable.h b/gcc/rust/hir/tree/rust-hir-visitable.h
new file mode 100644 (file)
index 0000000..9c05cbf
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+#ifndef RUST_HIR_VISITABLE_H
+#define RUST_HIR_VISITABLE_H
+
+namespace Rust {
+namespace HIR {
+
+class HIRFullVisitor;
+class HIRTraitItemVisitor;
+class HIRImplVisitor;
+class HIRStmtVisitor;
+class HIRExpressionVisitor;
+class HIRTypeVisitor;
+class HIRPatternVisitor;
+
+class FullVisitable
+{
+public:
+  virtual void accept_vis (HIRFullVisitor &vis) = 0;
+};
+} // namespace HIR
+} // namespace Rust
+
+#endif
index 9948a1555b9695e19afecbab7f903b0778ff0787..33e6b7bc70853b7d647b4016de64558b2763cb99 100644 (file)
@@ -19,7 +19,6 @@
 #ifndef RUST_HIR_VISITOR_H
 #define RUST_HIR_VISITOR_H
 
-#include "rust-hir-expr.h"
 #include "rust-hir-full-decls.h"
 
 namespace Rust {
index 9de881f6c9c0b698c0a860244e2d624df4fee22b..ea09111bddcd9e6286e9d573af10eb4cdf637814 100644 (file)
@@ -70,6 +70,33 @@ get_string_in_delims (std::string str_input, AST::DelimType delim_type)
   rust_unreachable ();
 }
 
+Crate::Crate (std::vector<std::unique_ptr<Item>> items,
+             AST::AttrVec inner_attrs, Analysis::NodeMapping mappings)
+  : WithInnerAttrs (std::move (inner_attrs)), items (std::move (items)),
+    mappings (mappings)
+{}
+
+Crate::Crate (Crate const &other)
+  : WithInnerAttrs (other.inner_attrs), mappings (other.mappings)
+{
+  items.reserve (other.items.size ());
+  for (const auto &e : other.items)
+    items.push_back (e->clone_item ());
+}
+
+Crate &
+Crate::operator= (Crate const &other)
+{
+  inner_attrs = other.inner_attrs;
+  mappings = other.mappings;
+
+  items.reserve (other.items.size ());
+  for (const auto &e : other.items)
+    items.push_back (e->clone_item ());
+
+  return *this;
+}
+
 std::string
 Crate::as_string () const
 {
@@ -2677,14 +2704,14 @@ Expr::as_string () const
 }
 
 // hopefully definition here will prevent circular dependency issue
-TraitBound *
+std::unique_ptr<TraitBound>
 TypePath::to_trait_bound (bool in_parens) const
 {
   // create clone FIXME is this required? or is copy constructor automatically
   // called?
   TypePath copy (*this);
-  return new TraitBound (mappings, std::move (copy), copy.get_locus (),
-                        in_parens);
+  return Rust::make_unique<TraitBound> (mappings, std::move (copy),
+                                       copy.get_locus (), in_parens);
 }
 
 std::string
@@ -3012,7 +3039,7 @@ StructExprStructFields::as_string () const
     }
   else
     {
-      str += struct_base->as_string ();
+      str += (*struct_base)->as_string ();
     }
 
   return str;
@@ -3994,6 +4021,12 @@ StructExprStructBase::accept_vis (HIRFullVisitor &vis)
   vis.visit (*this);
 }
 
+void
+StructExprStructBase::accept_vis (HIRExpressionVisitor &vis)
+{
+  vis.visit (*this);
+}
+
 void
 CallExpr::accept_vis (HIRFullVisitor &vis)
 {
@@ -5152,20 +5185,5 @@ StaticItem::accept_vis (HIRVisItemVisitor &vis)
   vis.visit (*this);
 }
 
-std::string
-ConstGenericParam::as_string () const
-{
-  auto result = "ConstGenericParam: " + name + " : " + type->as_string ();
-
-  if (default_expression)
-    result += " = " + default_expression->as_string ();
-
-  return result;
-}
-
-void
-ConstGenericParam::accept_vis (HIRFullVisitor &)
-{}
-
 } // namespace HIR
 } // namespace Rust
index d208122a0ddb97099a320e1992378cf66c2246ab..ffab5ffd6a41ae8d518bd1445f98d422c7abff1b 100644 (file)
 #ifndef RUST_HIR_BASE_H
 #define RUST_HIR_BASE_H
 
-#include "rust-ast.h"
 #include "rust-system.h"
+#include "rust-ast.h"
+#include "rust-hir-visitable.h"
+#include "rust-hir-attrs.h"
+
 #include "rust-token.h"
+
 #include "rust-location.h"
+
 #include "rust-hir-map.h"
 #include "rust-diagnostics.h"
+#include "rust-hir-bound.h"
 
 namespace Rust {
+
 typedef int TupleIndex;
 
 namespace HIR {
-// foward decl: ast visitor
-class HIRFullVisitor;
-class HIRStmtVisitor;
-class HIRTraitItemVisitor;
-class HIRExternalItemVisitor;
-class HIRVisItemVisitor;
-class HIRExpressionVisitor;
-class HIRPatternVisitor;
-class HIRImplVisitor;
-class HIRTypeVisitor;
-
-class WithOuterAttrs
-{
-protected:
-  AST::AttrVec outer_attrs;
-
-public:
-  AST::AttrVec &get_outer_attrs () { return outer_attrs; }
-  const AST::AttrVec &get_outer_attrs () const { return outer_attrs; }
-
-  WithOuterAttrs (AST::AttrVec outer_attrs)
-    : outer_attrs (std::move (outer_attrs)){};
-};
-
-class WithInnerAttrs
-{
-protected:
-  AST::AttrVec inner_attrs;
-
-public:
-  AST::AttrVec get_inner_attrs () const { return inner_attrs; }
-  WithInnerAttrs (AST::AttrVec inner_attrs)
-    : inner_attrs (std::move (inner_attrs)){};
-};
-
-class FullVisitable
-{
-public:
-  virtual void accept_vis (HIRFullVisitor &vis) = 0;
-};
-
-// forward decl for use in token tree method
-class Token;
-
-class Node
-{
-public:
-  // Kind for downcasting various HIR nodes to other base classes when visiting
-  // them
-  enum BaseKind
-  {
-    /* class ExternalItem */
-    EXTERNAL,
-    /* class TraitItem */
-    TRAIT_ITEM,
-    /* class VisItem */
-    VIS_ITEM,
-    /* class Item */
-    ITEM,
-    /* class ImplItem */
-    IMPL,
-    /* class Type */
-    TYPE,
-    /* class Stmt */
-    STMT,
-    /* class Expr */
-    EXPR,
-    /* class Pattern */
-    PATTERN,
-  };
-
-  /**
-   * Get the kind of HIR node we are dealing with. This is useful for
-   * downcasting to more precise types when necessary, i.e going from an `Item*`
-   * to a `VisItem*`
-   */
-  virtual BaseKind get_hir_kind () = 0;
-};
-
-// A literal - value with a type. Used in LiteralExpr and LiteralPattern.
-struct Literal
-{
-public:
-  enum LitType
-  {
-    CHAR,
-    STRING,
-    BYTE,
-    BYTE_STRING,
-    INT,
-    FLOAT,
-    BOOL
-  };
-
-private:
-  std::string value_as_string;
-  LitType type;
-  PrimitiveCoreType type_hint;
-
-public:
-  std::string as_string () const { return value_as_string; }
-
-  LitType get_lit_type () const { return type; }
-
-  PrimitiveCoreType get_type_hint () const { return type_hint; }
-
-  Literal (std::string value_as_string, LitType type,
-          PrimitiveCoreType type_hint)
-    : value_as_string (std::move (value_as_string)), type (type),
-      type_hint (type_hint)
-  {}
-
-  static Literal create_error ()
-  {
-    return Literal ("", CHAR, PrimitiveCoreType::CORETYPE_UNKNOWN);
-  }
-
-  void set_lit_type (LitType lt) { type = lt; }
-
-  // Returns whether literal is in an invalid state.
-  bool is_error () const { return value_as_string == ""; }
-
-  bool is_equal (Literal &other)
-  {
-    return value_as_string == other.value_as_string && type == other.type
-          && type_hint == other.type_hint;
-  }
-};
-
-/* Base statement abstract class. Note that most "statements" are not allowed in
- * top-level module scope - only a subclass of statements called "items" are. */
-class Stmt : public Node, public FullVisitable
-{
-public:
-  using FullVisitable::accept_vis;
-
-  // Unique pointer custom clone function
-  std::unique_ptr<Stmt> clone_stmt () const
-  {
-    return std::unique_ptr<Stmt> (clone_stmt_impl ());
-  }
-
-  BaseKind get_hir_kind () override { return STMT; }
-
-  virtual ~Stmt () {}
-
-  virtual std::string as_string () const = 0;
-
-  virtual void accept_vis (HIRStmtVisitor &vis) = 0;
-
-  virtual location_t get_locus () const = 0;
-
-  virtual bool is_unit_check_needed () const { return false; }
-
-  const Analysis::NodeMapping &get_mappings () const { return mappings; }
-
-  virtual bool is_item () const = 0;
-
-protected:
-  Stmt (Analysis::NodeMapping mappings) : mappings (std::move (mappings)) {}
-
-  // Clone function implementation as pure virtual method
-  virtual Stmt *clone_stmt_impl () const = 0;
-
-  Analysis::NodeMapping mappings;
-};
-
-// Rust "item" HIR node (declaration of top-level/module-level allowed stuff)
-class Item : public Stmt, public WithOuterAttrs
-{
-  // TODO: should outer attrs be defined here or in each derived class?
-public:
-  enum class ItemKind
-  {
-    Static,
-    Constant,
-    TypeAlias,
-    Function,
-    UseDeclaration,
-    ExternBlock,
-    ExternCrate,
-    Struct,
-    Union,
-    Enum,
-    EnumItem, // FIXME: ARTHUR: Do we need that?
-    Trait,
-    Impl,
-    Module,
-  };
-
-  static std::string item_kind_string (ItemKind kind);
-
-  virtual ItemKind get_item_kind () const = 0;
-
-  // Unique pointer custom clone function
-  std::unique_ptr<Item> clone_item () const
-  {
-    return std::unique_ptr<Item> (clone_item_impl ());
-  }
-
-  BaseKind get_hir_kind () override { return ITEM; }
-
-  std::string as_string () const override;
-
-  /* Adds crate names to the vector passed by reference, if it can
-   * (polymorphism). */
-  virtual void
-  add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const
-  {}
-
-  bool is_item () const override final { return true; }
-
-protected:
-  // Constructor
-  Item (Analysis::NodeMapping mappings,
-       AST::AttrVec outer_attribs = AST::AttrVec ())
-    : Stmt (std::move (mappings)), WithOuterAttrs (std::move (outer_attribs))
-  {}
-
-  // Clone function implementation as pure virtual method
-  virtual Item *clone_item_impl () const = 0;
-
-  /* Save having to specify two clone methods in derived classes by making
-   * statement clone return item clone. Hopefully won't affect performance too
-   * much. */
-  Item *clone_stmt_impl () const override { return clone_item_impl (); }
-};
-
-// forward decl of ExprWithoutBlock
-class ExprWithoutBlock;
-
-// Base expression HIR node - abstract
-class Expr : public Node, virtual public FullVisitable
-{
-public:
-  using FullVisitable::accept_vis;
-
-protected:
-  AST::AttrVec outer_attrs;
-  Analysis::NodeMapping mappings;
-
-public:
-  enum BlockType
-  {
-    WITH_BLOCK,
-    WITHOUT_BLOCK,
-  };
-
-  enum ExprType
-  {
-    Lit,
-    Operator,
-    Grouped,
-    Array,
-    ArrayIndex,
-    Tuple,
-    TupleIdx,
-    Struct,
-    Call,
-    MethodCall,
-    FieldAccess,
-    Closure,
-    Block,
-    Continue,
-    Break,
-    Range,
-    Return,
-    UnsafeBlock,
-    BaseLoop,
-    If,
-    Match,
-    Await,
-    AsyncBlock,
-    Path,
-    InlineAsm,
-  };
-
-  BaseKind get_hir_kind () override final { return EXPR; }
-
-  const AST::AttrVec &get_outer_attrs () const { return outer_attrs; }
-
-  // Unique pointer custom clone function
-  std::unique_ptr<Expr> clone_expr () const
-  {
-    return std::unique_ptr<Expr> (clone_expr_impl ());
-  }
-
-  // TODO: make pure virtual if move out outer attributes to derived classes
-  virtual std::string as_string () const;
-
-  virtual ~Expr () {}
-
-  virtual location_t get_locus () const = 0;
-
-  const Analysis::NodeMapping &get_mappings () const { return mappings; }
-
-  // Clone function implementation as pure virtual method
-  virtual Expr *clone_expr_impl () const = 0;
-
-  virtual BlockType get_block_expr_type () const = 0;
-
-  virtual ExprType get_expression_type () const = 0;
-
-  virtual void accept_vis (HIRExpressionVisitor &vis) = 0;
-
-protected:
-  // Constructor
-  Expr (Analysis::NodeMapping mappings,
-       AST::AttrVec outer_attribs = AST::AttrVec ())
-    : outer_attrs (std::move (outer_attribs)), mappings (std::move (mappings))
-  {}
-
-  // TODO: think of less hacky way to implement this kind of thing
-  // Sets outer attributes.
-  void set_outer_attrs (AST::AttrVec outer_attrs_to_set)
-  {
-    outer_attrs = std::move (outer_attrs_to_set);
-  }
-};
-
-// HIR node for an expression without an accompanying block - abstract
-class ExprWithoutBlock : public Expr
-{
-protected:
-  // Constructor
-  ExprWithoutBlock (Analysis::NodeMapping mappings,
-                   AST::AttrVec outer_attribs = AST::AttrVec ())
-    : Expr (std::move (mappings), std::move (outer_attribs))
-  {}
-
-  // pure virtual clone implementation
-  virtual ExprWithoutBlock *clone_expr_without_block_impl () const = 0;
-
-  /* Save having to specify two clone methods in derived classes by making expr
-   * clone return exprwithoutblock clone. Hopefully won't affect performance too
-   * much. */
-  ExprWithoutBlock *clone_expr_impl () const override
-  {
-    return clone_expr_without_block_impl ();
-  }
-
-public:
-  // Unique pointer custom clone function
-  std::unique_ptr<ExprWithoutBlock> clone_expr_without_block () const
-  {
-    return std::unique_ptr<ExprWithoutBlock> (clone_expr_without_block_impl ());
-  }
-
-  BlockType get_block_expr_type () const final override
-  {
-    return BlockType::WITHOUT_BLOCK;
-  };
-};
-
-// Pattern base HIR node
-class Pattern : public Node, virtual public FullVisitable
-{
-public:
-  using FullVisitable::accept_vis;
-
-  enum PatternType
-  {
-    PATH,
-    LITERAL,
-    IDENTIFIER,
-    WILDCARD,
-    RANGE,
-    REFERENCE,
-    STRUCT,
-    TUPLE_STRUCT,
-    TUPLE,
-    GROUPED,
-    SLICE,
-    ALT
-  };
-
-  BaseKind get_hir_kind () override final { return PATTERN; }
-
-  // Unique pointer custom clone function
-  std::unique_ptr<Pattern> clone_pattern () const
-  {
-    return std::unique_ptr<Pattern> (clone_pattern_impl ());
-  }
-
-  // possible virtual methods: is_refutable()
-
-  virtual ~Pattern () {}
-
-  virtual std::string as_string () const = 0;
-
-  virtual void accept_vis (HIRPatternVisitor &vis) = 0;
-
-  virtual const Analysis::NodeMapping &get_mappings () const = 0;
-
-  virtual location_t get_locus () const = 0;
-
-  virtual PatternType get_pattern_type () const = 0;
-
-protected:
-  // Clone pattern implementation as pure virtual method
-  virtual Pattern *clone_pattern_impl () const = 0;
-};
-
-// forward decl for Type
-class TraitBound;
-
-// Base class for types as represented in HIR - abstract
-class Type : public Node, public FullVisitable
-{
-public:
-  using FullVisitable::accept_vis;
-  // Unique pointer custom clone function
-  std::unique_ptr<Type> clone_type () const
-  {
-    return std::unique_ptr<Type> (clone_type_impl ());
-  }
-
-  // virtual destructor
-  virtual ~Type () {}
-
-  BaseKind get_hir_kind () override final { return TYPE; }
-
-  virtual std::string as_string () const = 0;
-
-  /* HACK: convert to trait bound. Virtual method overriden by classes that
-   * enable this. */
-  virtual TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const
-  {
-    return nullptr;
-  }
-  /* as pointer, shouldn't require definition beforehand, only forward
-   * declaration. */
-
-  virtual void accept_vis (HIRTypeVisitor &vis) = 0;
-
-  virtual const Analysis::NodeMapping &get_mappings () const
-  {
-    return mappings;
-  }
-  virtual location_t get_locus () const { return locus; }
-
-protected:
-  Type (Analysis::NodeMapping mappings, location_t locus)
-    : mappings (mappings), locus (locus)
-  {}
-
-  // Clone function implementation as pure virtual method
-  virtual Type *clone_type_impl () const = 0;
-
-  Analysis::NodeMapping mappings;
-  location_t locus;
-};
-
-// A type without parentheses? - abstract
-class TypeNoBounds : public Type
-{
-public:
-  // Unique pointer custom clone function
-  std::unique_ptr<TypeNoBounds> clone_type_no_bounds () const
-  {
-    return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ());
-  }
-
-protected:
-  TypeNoBounds (Analysis::NodeMapping mappings, location_t locus)
-    : Type (mappings, locus)
-  {}
-
-  // Clone function implementation as pure virtual method
-  virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;
-
-  /* Save having to specify two clone methods in derived classes by making type
-   * clone return typenobounds clone. Hopefully won't affect performance too
-   * much. */
-  TypeNoBounds *clone_type_impl () const override
-  {
-    return clone_type_no_bounds_impl ();
-  }
-};
-
-/* Abstract base class representing a type param bound - Lifetime and TraitBound
- * extends it */
-class TypeParamBound : public FullVisitable
-{
-public:
-  using FullVisitable::accept_vis;
-  enum BoundType
-  {
-    LIFETIME,
-    TRAITBOUND
-  };
-
-  virtual ~TypeParamBound () {}
-
-  // Unique pointer custom clone function
-  std::unique_ptr<TypeParamBound> clone_type_param_bound () const
-  {
-    return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
-  }
-
-  virtual std::string as_string () const = 0;
-
-  virtual Analysis::NodeMapping get_mappings () const = 0;
-
-  virtual location_t get_locus () const = 0;
-
-  virtual BoundType get_bound_type () const = 0;
-
-protected:
-  // Clone function implementation as pure virtual method
-  virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
-};
-
-// Represents a lifetime (and is also a kind of type param bound)
-class Lifetime : public TypeParamBound
-{
-private:
-  AST::Lifetime::LifetimeType lifetime_type;
-  std::string lifetime_name;
-  location_t locus;
-  Analysis::NodeMapping mappings;
-
-public:
-  // Constructor
-  Lifetime (Analysis::NodeMapping mapping, AST::Lifetime::LifetimeType type,
-           std::string name, location_t locus)
-    : lifetime_type (type), lifetime_name (std::move (name)), locus (locus),
-      mappings (mapping)
-  {}
-
-  // Returns true if the lifetime is in an error state.
-  bool is_error () const
-  {
-    return lifetime_type == AST::Lifetime::LifetimeType::NAMED
-          && lifetime_name.empty ();
-  }
-
-  static Lifetime error ()
-  {
-    return Lifetime (Analysis::NodeMapping::get_error (),
-                    AST::Lifetime::LifetimeType::NAMED, "", UNDEF_LOCATION);
-  }
-
-  std::string as_string () const override;
-
-  void accept_vis (HIRFullVisitor &vis) override;
-
-  WARN_UNUSED_RESULT const std::string &get_name () const
-  {
-    return lifetime_name;
-  }
-
-  AST::Lifetime::LifetimeType get_lifetime_type () const
-  {
-    return lifetime_type;
-  }
-
-  location_t get_locus () const override final { return locus; }
-
-  Analysis::NodeMapping get_mappings () const override final
-  {
-    return mappings;
-  }
-
-  BoundType get_bound_type () const final override { return LIFETIME; }
-
-protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
-  Lifetime *clone_type_param_bound_impl () const override
-  {
-    return new Lifetime (*this);
-  }
-};
-
-/* Base generic parameter in HIR. Abstract - can be represented by a Lifetime or
- * Type param */
-class GenericParam : public FullVisitable
-{
-public:
-  using FullVisitable::accept_vis;
-
-  virtual ~GenericParam () {}
-
-  enum class GenericKind
-  {
-    TYPE,
-    LIFETIME,
-    CONST,
-  };
-
-  virtual AST::AttrVec &get_outer_attrs () = 0;
-  virtual bool has_outer_attribute () const = 0;
-
-  // Unique pointer custom clone function
-  std::unique_ptr<GenericParam> clone_generic_param () const
-  {
-    return std::unique_ptr<GenericParam> (clone_generic_param_impl ());
-  }
-
-  virtual std::string as_string () const = 0;
-
-  virtual location_t get_locus () const = 0;
-
-  Analysis::NodeMapping get_mappings () const { return mappings; }
-
-  enum GenericKind get_kind () const { return kind; }
-
-protected:
-  // Clone function implementation as pure virtual method
-  virtual GenericParam *clone_generic_param_impl () const = 0;
-
-  Analysis::NodeMapping mappings;
-
-  enum GenericKind kind;
-
-  GenericParam (Analysis::NodeMapping mapping,
-               enum GenericKind kind = GenericKind::TYPE)
-    : mappings (mapping), kind (kind)
-  {}
-};
-
-// A lifetime generic parameter (as opposed to a type generic parameter)
-class LifetimeParam : public GenericParam
-{
-  Lifetime lifetime;
-
-  // bool has_lifetime_bounds;
-  // LifetimeBounds lifetime_bounds;
-  std::vector<Lifetime> lifetime_bounds; // inlined LifetimeBounds
-
-  AST::AttrVec outer_attrs;
-
-  location_t locus;
-
-public:
-  Lifetime get_lifetime () { return lifetime; }
-
-  // Returns whether the lifetime param has any lifetime bounds.
-  bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); }
-
-  std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
-
-  // Returns whether the lifetime param has an outer attribute.
-  bool has_outer_attribute () const override { return outer_attrs.size () > 1; }
-
-  AST::AttrVec &get_outer_attrs () override { return outer_attrs; }
-
-  // Returns whether the lifetime param is in an error state.
-  bool is_error () const { return lifetime.is_error (); }
-
-  // Constructor
-  LifetimeParam (Analysis::NodeMapping mappings, Lifetime lifetime,
-                location_t locus = UNDEF_LOCATION,
-                std::vector<Lifetime> lifetime_bounds
-                = std::vector<Lifetime> (),
-                AST::AttrVec outer_attrs = std::vector<AST::Attribute> ())
-    : GenericParam (mappings, GenericKind::LIFETIME),
-      lifetime (std::move (lifetime)),
-      lifetime_bounds (std::move (lifetime_bounds)),
-      outer_attrs (std::move (outer_attrs)), locus (locus)
-  {}
-
-  // TODO: remove copy and assignment operator definitions - not required
-
-  // Copy constructor with clone
-  LifetimeParam (LifetimeParam const &other)
-    : GenericParam (other.mappings, GenericKind::LIFETIME),
-      lifetime (other.lifetime), lifetime_bounds (other.lifetime_bounds),
-      outer_attrs (other.outer_attrs), locus (other.locus)
-  {}
-
-  // Overloaded assignment operator to clone attribute
-  LifetimeParam &operator= (LifetimeParam const &other)
-  {
-    lifetime = other.lifetime;
-    lifetime_bounds = other.lifetime_bounds;
-    outer_attrs = other.outer_attrs;
-    locus = other.locus;
-    mappings = other.mappings;
-
-    return *this;
-  }
-
-  // move constructors
-  LifetimeParam (LifetimeParam &&other) = default;
-  LifetimeParam &operator= (LifetimeParam &&other) = default;
-
-  std::string as_string () const override;
-
-  void accept_vis (HIRFullVisitor &vis) override;
-
-  location_t get_locus () const override final { return locus; }
-
-protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
-  LifetimeParam *clone_generic_param_impl () const override
-  {
-    return new LifetimeParam (*this);
-  }
-};
-
-class ConstGenericParam : public GenericParam
-{
-public:
-  ConstGenericParam (std::string name, std::unique_ptr<Type> type,
-                    std::unique_ptr<Expr> default_expression,
-                    Analysis::NodeMapping mapping, location_t locus)
-    : GenericParam (mapping, GenericKind::CONST), name (std::move (name)),
-      type (std::move (type)),
-      default_expression (std::move (default_expression)), locus (locus)
-  {}
-
-  ConstGenericParam (const ConstGenericParam &other) : GenericParam (other)
-  {
-    name = other.name;
-    locus = other.locus;
-
-    if (other.type)
-      type = other.type->clone_type ();
-    if (other.default_expression)
-      default_expression = other.default_expression->clone_expr ();
-  }
-
-  bool has_outer_attribute () const override { return false; }
-
-  AST::AttrVec &get_outer_attrs () override { return outer_attrs; }
-
-  std::string as_string () const override final;
-
-  void accept_vis (HIRFullVisitor &vis) override final;
-
-  location_t get_locus () const override final { return locus; };
-
-  bool has_default_expression () { return default_expression != nullptr; }
-
-  std::string get_name () { return name; }
-  Type &get_type () { return *type; }
-  Expr &get_default_expression () { return *default_expression; }
-
-protected:
-  /* Use covariance to implement clone function as returning this object rather
-   * than base */
-  ConstGenericParam *clone_generic_param_impl () const override
-  {
-    return new ConstGenericParam (*this);
-  }
-
-private:
-  std::string name;
-  std::unique_ptr<Type> type;
-
-  /* const params have no outer attrs, should be empty */
-  AST::AttrVec outer_attrs = std::vector<AST::Attribute> ();
-
-  /* Optional - can be a null pointer if there is no default expression */
-  std::unique_ptr<Expr> default_expression;
-
-  location_t locus;
-};
 
 // Item used in trait declarations - abstract base class
 class TraitItem : public Node, public FullVisitable
@@ -891,34 +137,15 @@ class Crate : public WithInnerAttrs
 public:
   // Constructor
   Crate (std::vector<std::unique_ptr<Item>> items, AST::AttrVec inner_attrs,
-        Analysis::NodeMapping mappings)
-    : WithInnerAttrs (std::move (inner_attrs)), items (std::move (items)),
-      mappings (mappings)
-  {}
+        Analysis::NodeMapping mappings);
 
   // Copy constructor with vector clone
-  Crate (Crate const &other)
-    : WithInnerAttrs (other.inner_attrs), mappings (other.mappings)
-  {
-    items.reserve (other.items.size ());
-    for (const auto &e : other.items)
-      items.push_back (e->clone_item ());
-  }
+  Crate (Crate const &other);
 
   ~Crate () = default;
 
   // Overloaded assignment operator with vector clone
-  Crate &operator= (Crate const &other)
-  {
-    inner_attrs = other.inner_attrs;
-    mappings = other.mappings;
-
-    items.reserve (other.items.size ());
-    for (const auto &e : other.items)
-      items.push_back (e->clone_item ());
-
-    return *this;
-  }
+  Crate &operator= (Crate const &other);
 
   // Move constructors
   Crate (Crate &&other) = default;
@@ -931,27 +158,6 @@ public:
   std::vector<std::unique_ptr<Item>> &get_items () { return items; }
 };
 
-// Base path expression HIR node - abstract
-class PathExpr : public ExprWithoutBlock
-{
-protected:
-  PathExpr (Analysis::NodeMapping mappings, AST::AttrVec outer_attribs)
-    : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs))
-  {}
-
-public:
-  /* Replaces the outer attributes of this path expression with the given outer
-   * attributes. */
-  void replace_outer_attrs (AST::AttrVec outer_attrs)
-  {
-    set_outer_attrs (std::move (outer_attrs));
-  }
-
-  ExprType get_expression_type () const final override
-  {
-    return ExprType::Path;
-  }
-};
 } // namespace HIR
 } // namespace Rust
 
index e19925a96ee8359bd0237172abb34aa2a288720f..40c42b279802e78df7cebf1560fded7a168bd647 100644 (file)
@@ -56,17 +56,18 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
   if (struct_expr.has_struct_base ())
     {
       TyTy::BaseType *base_resolved
-       = TypeCheckExpr::Resolve (*struct_expr.struct_base->base_struct);
+       = TypeCheckExpr::Resolve (struct_expr.get_struct_base ().get_base ());
       TyTy::BaseType *base_unify = unify_site (
-       struct_expr.struct_base->base_struct->get_mappings ().get_hirid (),
+       struct_expr.get_struct_base ().get_base ().get_mappings ().get_hirid (),
        TyTy::TyWithLocation (struct_path_resolved),
        TyTy::TyWithLocation (base_resolved),
-       struct_expr.struct_base->base_struct->get_locus ());
+       struct_expr.get_struct_base ().get_base ().get_locus ());
 
       if (base_unify->get_kind () != struct_path_ty->get_kind ())
        {
-         rust_fatal_error (struct_expr.struct_base->base_struct->get_locus (),
-                           "incompatible types for base struct reference");
+         rust_fatal_error (
+           struct_expr.get_struct_base ().get_base ().get_locus (),
+           "incompatible types for base struct reference");
          return;
        }
 
@@ -190,26 +191,29 @@ TypeCheckStructExpr::resolve (HIR::StructExprStructFields &struct_expr)
          for (auto &missing : missing_fields)
            {
              HIR::Expr *receiver
-               = struct_expr.struct_base->base_struct->clone_expr_impl ();
+               = struct_expr.get_struct_base ().get_base ().clone_expr_impl ();
 
              HIR::StructExprField *implicit_field = nullptr;
 
              AST::AttrVec outer_attribs;
              auto crate_num = mappings.get_current_crate ();
-             Analysis::NodeMapping mapping (
-               crate_num,
-               struct_expr.struct_base->base_struct->get_mappings ()
-                 .get_nodeid (),
-               mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
+             Analysis::NodeMapping mapping (crate_num,
+                                            struct_expr.get_struct_base ()
+                                              .get_base ()
+                                              .get_mappings ()
+                                              .get_nodeid (),
+                                            mappings.get_next_hir_id (
+                                              crate_num),
+                                            UNKNOWN_LOCAL_DEFID);
 
              HIR::Expr *field_value = new HIR::FieldAccessExpr (
                mapping, std::unique_ptr<HIR::Expr> (receiver), missing,
                std::move (outer_attribs),
-               struct_expr.struct_base->base_struct->get_locus ());
+               struct_expr.get_struct_base ().get_base ().get_locus ());
 
              implicit_field = new HIR::StructExprFieldIdentifierValue (
                mapping, missing, std::unique_ptr<HIR::Expr> (field_value),
-               struct_expr.struct_base->base_struct->get_locus ());
+               struct_expr.get_struct_base ().get_base ().get_locus ());
 
              size_t field_index;
              bool ok = variant->lookup_field (missing, nullptr, &field_index);
index 32c55cd03f1c68a873c6b70e6462778f46fa4f42..41844ea741a7be3fedf4b505dd1502a4d2631e42 100644 (file)
@@ -16,6 +16,7 @@
 // along with GCC; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
+#include "rust-hir-full-decls.h"
 #include "rust-hir-type-bounds.h"
 #include "rust-hir-trait-resolve.h"
 #include "rust-substitution-mapper.h"
@@ -203,21 +204,21 @@ TypeCheckBase::get_predicate_from_bound (
     = HIR::GenericArgs::create_empty (type_path.get_locus ());
 
   auto &final_seg = type_path.get_final_segment ();
-  switch (final_seg->get_type ())
+  switch (final_seg.get_type ())
     {
       case HIR::TypePathSegment::SegmentType::GENERIC: {
-       auto final_generic_seg
-         = static_cast<HIR::TypePathSegmentGeneric *> (final_seg.get ());
-       if (final_generic_seg->has_generic_args ())
+       auto &final_generic_seg
+         = static_cast<HIR::TypePathSegmentGeneric &> (final_seg);
+       if (final_generic_seg.has_generic_args ())
          {
-           args = final_generic_seg->get_generic_args ();
+           args = final_generic_seg.get_generic_args ();
          }
       }
       break;
 
       case HIR::TypePathSegment::SegmentType::FUNCTION: {
        auto &final_function_seg
-         = static_cast<HIR::TypePathSegmentFunction &> (*final_seg);
+         = static_cast<HIR::TypePathSegmentFunction &> (final_seg);
        auto &fn = final_function_seg.get_function_path ();
 
        // we need to make implicit generic args which must be an implicit
@@ -225,7 +226,7 @@ TypeCheckBase::get_predicate_from_bound (
        auto crate_num = mappings.get_current_crate ();
        HirId implicit_args_id = mappings.get_next_hir_id ();
        Analysis::NodeMapping mapping (crate_num,
-                                      final_seg->get_mappings ().get_nodeid (),
+                                      final_seg.get_mappings ().get_nodeid (),
                                       implicit_args_id, UNKNOWN_LOCAL_DEFID);
 
        std::vector<std::unique_ptr<HIR::Type>> params_copy;
@@ -234,12 +235,10 @@ TypeCheckBase::get_predicate_from_bound (
            params_copy.push_back (p->clone_type ());
          }
 
-       HIR::TupleType *implicit_tuple
-         = new HIR::TupleType (mapping, std::move (params_copy),
-                               final_seg->get_locus ());
-
        std::vector<std::unique_ptr<HIR::Type>> inputs;
-       inputs.push_back (std::unique_ptr<HIR::Type> (implicit_tuple));
+       inputs.push_back (
+         Rust::make_unique<HIR::TupleType> (mapping, std::move (params_copy),
+                                            final_seg.get_locus ()));
 
        // resolve the fn_once_output type which assumes there must be an output
        // set
@@ -249,7 +248,7 @@ TypeCheckBase::get_predicate_from_bound (
        HIR::TraitItem *trait_item
          = mappings
              .lookup_trait_item_lang_item (LangItem::Kind::FN_ONCE_OUTPUT,
-                                           final_seg->get_locus ())
+                                           final_seg.get_locus ())
              .value ();
 
        std::vector<HIR::GenericArgsBinding> bindings;
@@ -263,7 +262,7 @@ TypeCheckBase::get_predicate_from_bound (
        args = HIR::GenericArgs ({} /* lifetimes */,
                                 std::move (inputs) /* type_args*/,
                                 std::move (bindings) /* binding_args*/,
-                                {} /* const_args */, final_seg->get_locus ());
+                                {} /* const_args */, final_seg.get_locus ());
       }
       break;