https://gcc.gnu.org/g:63023c032845b5d01e25c1f2e443e43d938337b0

commit r15-8619-g63023c032845b5d01e25c1f2e443e43d938337b0
Author: Arthur Cohen <arthur.co...@embecosm.com>
Date:   Thu Dec 26 21:46:03 2024 +0000

    gccrs: ast: Refactor how lang item paths are handled.
    
    Lang item typepaths were not handled properly, and required a complete 
overhaul.
    All old classes that concerned lang item paths are now modified to use a 
simpler
    version of `AST::LangItemPath`, which has been removed. TypePath segments 
can now
    be lang items, as this is requied for having generic lang item paths such as
    PhantomData<T>.
    
    gcc/rust/ChangeLog:
    
            * ast/rust-path.h: Rework how lang item paths are represented.
            * ast/rust-path.cc: Likewise.
            * ast/rust-item.h: Likewise.
            * ast/rust-ast.cc: Likewise.
            * ast/rust-ast-collector.cc: Adapt to new lang item path system.
            * ast/rust-ast-collector.h: Likewise.
            * ast/rust-ast-visitor.cc (DefaultASTVisitor::visit): Likewise.
            * ast/rust-ast-visitor.h: Likewise.
            * expand/rust-derive-copy.cc: Likewise.
            * expand/rust-derive.h: Likewise.
            * hir/rust-ast-lower-base.cc (ASTLoweringBase::visit): Likewise.
            * hir/rust-ast-lower-base.h: Likewise.
            * hir/rust-ast-lower-type.cc (ASTLowerTypePath::translate): 
Likewise.
            (ASTLowerTypePath::visit): Likewise.
            * hir/rust-ast-lower-type.h: Likewise.
            * resolve/rust-ast-resolve-base.cc (ResolverBase::visit): Likewise.
            * resolve/rust-ast-resolve-base.h: Likewise.
            * resolve/rust-ast-resolve-item.cc (ResolveItem::visit): Likewise.
            * resolve/rust-ast-resolve-type.h: Likewise.
            * resolve/rust-ast-resolve-type.cc (ResolveRelativeTypePath::go): 
Likewise.
            * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Likewise.
            * resolve/rust-late-name-resolver-2.0.h: Likewise.
            * hir/tree/rust-hir-path.cc (TypePathSegment::TypePathSegment): 
Likewise.
            (TypePathSegmentGeneric::TypePathSegmentGeneric): Likewise.
            * hir/tree/rust-hir-path.h: Likewise.
            * typecheck/rust-hir-type-check-type.cc 
(TypeCheckType::resolve_root_path): Likewise.
            * ast/rust-ast-builder.cc: Likewise.
            * ast/rust-ast-builder.h: Likewise.

Diff:
---
 gcc/rust/ast/rust-ast-builder.cc                |  20 +-
 gcc/rust/ast/rust-ast-builder.h                 |   4 -
 gcc/rust/ast/rust-ast-collector.cc              |  13 -
 gcc/rust/ast/rust-ast-collector.h               |   2 -
 gcc/rust/ast/rust-ast-visitor.cc                |  11 -
 gcc/rust/ast/rust-ast-visitor.h                 |   4 -
 gcc/rust/ast/rust-ast.cc                        |   4 +-
 gcc/rust/ast/rust-item.h                        |  40 +--
 gcc/rust/ast/rust-path.cc                       |  31 +-
 gcc/rust/ast/rust-path.h                        | 405 +++++++++---------------
 gcc/rust/expand/rust-derive-copy.cc             |   4 +-
 gcc/rust/expand/rust-derive.h                   |   2 -
 gcc/rust/hir/rust-ast-lower-base.cc             |   6 -
 gcc/rust/hir/rust-ast-lower-base.h              |   2 -
 gcc/rust/hir/rust-ast-lower-type.cc             |  75 +++--
 gcc/rust/hir/rust-ast-lower-type.h              |   6 +-
 gcc/rust/hir/tree/rust-hir-path.cc              |  21 +-
 gcc/rust/hir/tree/rust-hir-path.h               |  38 ++-
 gcc/rust/resolve/rust-ast-resolve-base.cc       |   8 -
 gcc/rust/resolve/rust-ast-resolve-base.h        |   2 -
 gcc/rust/resolve/rust-ast-resolve-item.cc       |  27 +-
 gcc/rust/resolve/rust-ast-resolve-type.cc       |  79 +++--
 gcc/rust/resolve/rust-ast-resolve-type.h        |  31 --
 gcc/rust/resolve/rust-late-name-resolver-2.0.cc |  19 --
 gcc/rust/resolve/rust-late-name-resolver-2.0.h  |   1 -
 gcc/rust/typecheck/rust-hir-type-check-type.cc  |   2 +-
 26 files changed, 311 insertions(+), 546 deletions(-)

diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc
index 22fb0d83f979..f6d0f0dc4aed 100644
--- a/gcc/rust/ast/rust-ast-builder.cc
+++ b/gcc/rust/ast/rust-ast-builder.cc
@@ -42,15 +42,6 @@ Builder::call (std::unique_ptr<Expr> &&path,
     new CallExpr (std::move (path), std::move (args), {}, loc));
 }
 
-std::unique_ptr<Expr>
-Builder::call (std::unique_ptr<Path> &&path,
-              std::vector<std::unique_ptr<Expr>> &&args) const
-{
-  return call (std::unique_ptr<Expr> (
-                new PathInExpression (std::move (path), {}, loc)),
-              std::move (args));
-}
-
 std::unique_ptr<Expr>
 Builder::call (std::unique_ptr<Expr> &&path, std::unique_ptr<Expr> &&arg) const
 {
@@ -60,15 +51,6 @@ Builder::call (std::unique_ptr<Expr> &&path, 
std::unique_ptr<Expr> &&arg) const
   return call (std::move (path), std::move (args));
 }
 
-std::unique_ptr<Expr>
-Builder::call (std::unique_ptr<Path> &&path, std::unique_ptr<Expr> &&arg) const
-{
-  auto args = std::vector<std::unique_ptr<Expr>> ();
-  args.emplace_back (std::move (arg));
-
-  return call (std::move (path), std::move (args));
-}
-
 std::unique_ptr<Expr>
 Builder::array (std::vector<std::unique_ptr<Expr>> &&members) const
 {
@@ -242,7 +224,7 @@ Builder::wildcard () const
 std::unique_ptr<Path>
 Builder::lang_item_path (LangItem::Kind kind) const
 {
-  return std::unique_ptr<Path> (new LangItemPath (kind, loc));
+  return std::unique_ptr<Path> (new PathInExpression (kind, {}, loc));
 }
 
 std::unique_ptr<Expr>
diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h
index 6e07df6e1824..aaf05c6d1fb1 100644
--- a/gcc/rust/ast/rust-ast-builder.h
+++ b/gcc/rust/ast/rust-ast-builder.h
@@ -72,12 +72,8 @@ public:
    */
   std::unique_ptr<Expr> call (std::unique_ptr<Expr> &&path,
                              std::vector<std::unique_ptr<Expr>> &&args) const;
-  std::unique_ptr<Expr> call (std::unique_ptr<Path> &&path,
-                             std::vector<std::unique_ptr<Expr>> &&args) const;
   std::unique_ptr<Expr> call (std::unique_ptr<Expr> &&path,
                              std::unique_ptr<Expr> &&arg) const;
-  std::unique_ptr<Expr> call (std::unique_ptr<Path> &&path,
-                             std::unique_ptr<Expr> &&arg) const;
 
   /**
    * Create an array expression (`[member0, member1, member2]`)
diff --git a/gcc/rust/ast/rust-ast-collector.cc 
b/gcc/rust/ast/rust-ast-collector.cc
index 320611614e92..f493da3fa3fc 100644
--- a/gcc/rust/ast/rust-ast-collector.cc
+++ b/gcc/rust/ast/rust-ast-collector.cc
@@ -538,19 +538,6 @@ TokenCollector::visit (PathInExpression &path)
   visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION);
 }
 
-void
-TokenCollector::visit (RegularPath &path)
-{
-  // FIXME: We probably want to have a proper implementation here, and call 
this
-  // function from things like the PathInExpression visitor
-}
-
-void
-TokenCollector::visit (LangItemPath &path)
-{
-  // TODO: Implement proper token collection for lang item paths
-}
-
 void
 TokenCollector::visit (TypePathSegment &segment)
 {
diff --git a/gcc/rust/ast/rust-ast-collector.h 
b/gcc/rust/ast/rust-ast-collector.h
index 30aff9851051..b014c23ed0b8 100644
--- a/gcc/rust/ast/rust-ast-collector.h
+++ b/gcc/rust/ast/rust-ast-collector.h
@@ -233,8 +233,6 @@ public:
   void visit (PathExprSegment &segment);
   void visit (PathIdentSegment &segment);
   void visit (PathInExpression &path);
-  void visit (RegularPath &path);
-  void visit (LangItemPath &path);
   void visit (TypePathSegment &segment);
   void visit (TypePathSegmentGeneric &segment);
   void visit (TypePathSegmentFunction &segment);
diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc
index 6959c49d66a5..e2e2d9dda37b 100644
--- a/gcc/rust/ast/rust-ast-visitor.cc
+++ b/gcc/rust/ast/rust-ast-visitor.cc
@@ -85,17 +85,6 @@ DefaultASTVisitor::visit (AST::ConstGenericParam 
&const_param)
     visit (const_param.get_default_value ());
 }
 
-void
-DefaultASTVisitor::visit (AST::RegularPath &path)
-{
-  for (auto &segment : path.get_segments ())
-    visit (segment);
-}
-
-void
-DefaultASTVisitor::visit (AST::LangItemPath &path)
-{}
-
 void
 DefaultASTVisitor::visit (AST::PathInExpression &path)
 {
diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h
index a7c1cc9c62bb..51661df76b49 100644
--- a/gcc/rust/ast/rust-ast-visitor.h
+++ b/gcc/rust/ast/rust-ast-visitor.h
@@ -60,8 +60,6 @@ public:
   // virtual void visit(TraitImplItem& trait_impl_item) = 0;
 
   // rust-path.h
-  virtual void visit (RegularPath &path) = 0;
-  virtual void visit (LangItemPath &path) = 0;
   virtual void visit (PathInExpression &path) = 0;
   virtual void visit (TypePathSegment &segment) = 0;
   virtual void visit (TypePathSegmentGeneric &segment) = 0;
@@ -252,8 +250,6 @@ public:
   virtual void visit (AST::Lifetime &lifetime) override;
   virtual void visit (AST::LifetimeParam &lifetime_param) override;
   virtual void visit (AST::ConstGenericParam &const_param) override;
-  virtual void visit (AST::RegularPath &path) override;
-  virtual void visit (AST::LangItemPath &path) override;
   virtual void visit (AST::PathInExpression &path) override;
   virtual void visit (AST::TypePathSegment &segment) override;
   virtual void visit (AST::TypePathSegmentGeneric &segment) override;
diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc
index 45189a1a4b37..ab82303879c9 100644
--- a/gcc/rust/ast/rust-ast.cc
+++ b/gcc/rust/ast/rust-ast.cc
@@ -1299,7 +1299,7 @@ TraitImpl::as_string () const
   else
     str += "false";
 
-  str += "\n TypePath (to trait): " + trait_path->as_string ();
+  str += "\n TypePath (to trait): " + trait_path.as_string ();
 
   str += "\n Type (struct to impl on): " + trait_type->as_string ();
 
@@ -1561,7 +1561,7 @@ QualifiedPathType::as_string () const
   str += type_to_invoke_on->as_string ();
 
   if (has_as_clause ())
-    str += " as " + trait_path->as_string ();
+    str += " as " + trait_path.as_string ();
 
   return str + ">";
 }
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index 261e64e4242b..8eb0cc51d5db 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -3254,7 +3254,7 @@ class TraitImpl : public Impl
 {
   bool has_unsafe;
   bool has_exclam;
-  std::unique_ptr<Path> trait_path;
+  TypePath trait_path;
 
   // bool has_impl_items;
   std::vector<std::unique_ptr<AssociatedItem>> impl_items;
@@ -3266,7 +3266,7 @@ public:
   bool has_impl_items () const { return !impl_items.empty (); }
 
   // Mega-constructor
-  TraitImpl (std::unique_ptr<Path> trait_path, bool is_unsafe, bool has_exclam,
+  TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
             std::vector<std::unique_ptr<AssociatedItem>> impl_items,
             std::vector<std::unique_ptr<GenericParam>> generic_params,
             std::unique_ptr<Type> trait_type, WhereClause where_clause,
@@ -3275,29 +3275,14 @@ public:
     : Impl (std::move (generic_params), std::move (trait_type),
            std::move (where_clause), std::move (vis), std::move (inner_attrs),
            std::move (outer_attrs), locus),
-      has_unsafe (is_unsafe), has_exclam (has_exclam),
-      trait_path (std::move (trait_path)), impl_items (std::move (impl_items))
-  {}
-
-  // Delegating constructor for TypePath
-  TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
-            std::vector<std::unique_ptr<AssociatedItem>> impl_items,
-            std::vector<std::unique_ptr<GenericParam>> generic_params,
-            std::unique_ptr<Type> trait_type, WhereClause where_clause,
-            Visibility vis, std::vector<Attribute> inner_attrs,
-            std::vector<Attribute> outer_attrs, location_t locus)
-    : TraitImpl (std::unique_ptr<Path> (new TypePath (trait_path)), is_unsafe,
-                has_exclam, std::move (impl_items), std::move (generic_params),
-                std::move (trait_type), std::move (where_clause),
-                std::move (vis), std::move (inner_attrs),
-                std::move (outer_attrs), locus)
+      has_unsafe (is_unsafe), has_exclam (has_exclam), trait_path (trait_path),
+      impl_items (std::move (impl_items))
   {}
 
   // Copy constructor with vector clone
   TraitImpl (TraitImpl const &other)
     : Impl (other), has_unsafe (other.has_unsafe),
-      has_exclam (other.has_exclam),
-      trait_path (other.trait_path->clone_path ())
+      has_exclam (other.has_exclam), trait_path (other.trait_path)
   {
     impl_items.reserve (other.impl_items.size ());
     for (const auto &e : other.impl_items)
@@ -3308,7 +3293,7 @@ public:
   TraitImpl &operator= (TraitImpl const &other)
   {
     Impl::operator= (other);
-    trait_path = other.trait_path->clone_path ();
+    trait_path = other.trait_path;
     has_unsafe = other.has_unsafe;
     has_exclam = other.has_exclam;
 
@@ -3339,18 +3324,7 @@ public:
   }
 
   // TODO: is this better? Or is a "vis_block" better?
-  Path &get_trait_path ()
-  {
-    // TODO: assert that trait path is not empty?
-    return *trait_path;
-  }
-
-  Type &get_trait_path_type ()
-  {
-    rust_assert (trait_path->get_path_kind () == Path::Kind::Type);
-
-    return (AST::Type &) static_cast<AST::TypePath &> (*trait_path);
-  }
+  TypePath &get_trait_path () { return trait_path; }
 
 protected:
   /* Use covariance to implement clone function as returning this object
diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc
index 94cf2bb15141..69627be81af3 100644
--- a/gcc/rust/ast/rust-path.cc
+++ b/gcc/rust/ast/rust-path.cc
@@ -136,8 +136,11 @@ PathExprSegment::as_string () const
 }
 
 std::string
-RegularPath::as_string () const
+Path::as_string () const
 {
+  // FIXME: Impl for lang items
+  rust_assert (kind == Kind::Regular);
+
   std::string str;
 
   for (const auto &segment : segments)
@@ -149,15 +152,11 @@ RegularPath::as_string () const
   return str;
 }
 
-std::string
-LangItemPath::as_string () const
-{
-  return "#[lang = \"" + LangItem::ToString (kind) + "\"]";
-}
-
 SimplePath
-RegularPath::convert_to_simple_path (bool with_opening_scope_resolution) const
+Path::convert_to_simple_path (bool with_opening_scope_resolution) const
 {
+  rust_assert (kind == Kind::Regular);
+
   if (!has_segments ())
     return SimplePath::create_empty ();
 
@@ -190,18 +189,6 @@ RegularPath::convert_to_simple_path (bool 
with_opening_scope_resolution) const
                     locus);
 }
 
-void
-RegularPath::accept_vis (ASTVisitor &vis)
-{
-  vis.visit (*this);
-}
-
-void
-LangItemPath::accept_vis (ASTVisitor &vis)
-{
-  vis.visit (*this);
-}
-
 void
 PathInExpression::accept_vis (ASTVisitor &vis)
 {
@@ -216,7 +203,7 @@ PathInExpression::as_string () const
   if (has_opening_scope_resolution)
     str = "::";
 
-  return str + path->as_string ();
+  return str + Path::as_string ();
 }
 
 std::string
@@ -316,7 +303,7 @@ TypePathFunction::as_string () const
 std::string
 QualifiedPathInExpression::as_string () const
 {
-  return path_type.as_string () + "::" + path->as_string ();
+  return path_type.as_string () + "::" + Path::as_string ();
 }
 
 std::string
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index b7eba446540c..2a76acc48c3d 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -21,6 +21,7 @@
 /* "Path" (identifier within namespaces, essentially) handling. Required 
include
  * for virtually all AST-related functionality. */
 
+#include "optional.h"
 #include "rust-ast.h"
 #include "rust-hir-map.h"
 #include "rust-mapping-common.h"
@@ -589,115 +590,75 @@ public:
   {
     LangItem,
     Regular,
-    Type,
   };
 
-  virtual Kind get_path_kind () const = 0;
-
-  Pattern::Kind get_pattern_kind () override final
-  {
-    return Pattern::Kind::Path;
-  }
-
-  std::unique_ptr<Path> clone_path ()
-  {
-    return std::unique_ptr<Path> (clone_path_impl ());
-  }
-
-  Pattern *clone_pattern_impl () const override final
-  {
-    return clone_path_impl ();
-  }
-
-protected:
-  virtual Path *clone_path_impl () const = 0;
-};
-
-class RegularPath : public Path
-{
-  std::vector<PathExprSegment> segments;
-  NodeId node_id;
-  location_t locus;
-
-public:
-  explicit RegularPath (std::vector<PathExprSegment> &&segments,
-                       location_t locus, NodeId node_id)
-    : segments (std::move (segments)), node_id (node_id), locus (locus)
+  Path (std::vector<PathExprSegment> segments)
+    : segments (std::move (segments)), lang_item (tl::nullopt),
+      kind (Kind::Regular)
   {}
 
-  std::string as_string () const override;
+  Path (LangItem::Kind lang_item)
+    : segments ({}), lang_item (lang_item), kind (Kind::LangItem)
+  {}
 
   // Returns whether path has segments.
-  bool has_segments () const { return !segments.empty (); }
-
-  std::vector<PathExprSegment> &get_segments () { return segments; }
-
-  const std::vector<PathExprSegment> &get_segments () const { return segments; 
}
-
-  /* Returns whether the path is a single segment (excluding qualified path
-   * initial as segment). */
-  bool is_single_segment () const { return segments.size () == 1; }
+  bool has_segments () const
+  {
+    rust_assert (kind == Kind::Regular);
+    return !segments.empty ();
+  }
 
   /* Converts path segments to their equivalent SimplePath segments if
    * possible, and creates a SimplePath from them. */
   SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const;
 
-  Path::Kind get_path_kind () const override { return Path::Kind::Regular; }
-
-  void accept_vis (ASTVisitor &vis) override;
-
-  Path *clone_path_impl () const override
+  /* Returns whether the path is a single segment (excluding qualified path
+   * initial as segment). */
+  bool is_single_segment () const
   {
-    return new RegularPath (std::vector<PathExprSegment> (segments), locus,
-                           node_id);
+    rust_assert (kind == Kind::Regular);
+    return segments.size () == 1;
   }
 
-  NodeId get_node_id () const override { return node_id; }
-  location_t get_locus () const override { return locus; }
-};
-
-class LangItemPath : public Path
-{
-  LangItem::Kind kind;
-  NodeId node_id;
-  location_t locus;
-
-  LangItemPath (LangItem::Kind kind, NodeId node_id, location_t locus)
-    : kind (kind), node_id (node_id), locus (locus)
-  {}
-
-public:
-  explicit LangItemPath (LangItem::Kind kind, location_t locus)
-    : kind (kind), node_id (Analysis::Mappings::get ().get_next_node_id ()),
-      locus (locus)
-  {}
-
-  Path::Kind get_path_kind () const override { return Path::Kind::LangItem; }
+  std::string as_string () const override;
 
-  void accept_vis (ASTVisitor &vis) override;
+  // TODO: this seems kinda dodgy
+  std::vector<PathExprSegment> &get_segments ()
+  {
+    rust_assert (kind == Kind::Regular);
+    return segments;
+  }
+  const std::vector<PathExprSegment> &get_segments () const
+  {
+    rust_assert (kind == Kind::Regular);
+    return segments;
+  }
 
-  Path *clone_path_impl () const override
+  LangItem::Kind get_lang_item () const
   {
-    return new LangItemPath (kind, node_id, locus);
+    rust_assert (kind == Kind::LangItem);
+    return *lang_item;
   }
 
-  std::string as_string () const override;
+  Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
+  Path::Kind get_path_kind () { return kind; }
 
-  LangItem::Kind get_lang_item_kind () { return kind; }
+protected:
+  std::vector<PathExprSegment> segments;
+  tl::optional<LangItem::Kind> lang_item;
 
-  NodeId get_node_id () const override { return node_id; }
-  location_t get_locus () const override { return locus; }
+  Path::Kind kind;
 };
 
 /* AST node representing a path-in-expression pattern (path that allows
  * generic arguments) */
-class PathInExpression : public Pattern, public ExprWithoutBlock
+class PathInExpression : public Path, public ExprWithoutBlock
 {
   std::vector<Attribute> outer_attrs;
   bool has_opening_scope_resolution;
   location_t locus;
   NodeId _node_id;
-  std::unique_ptr<Path> path;
+
   bool marked_for_strip;
 
 public:
@@ -707,52 +668,20 @@ public:
   PathInExpression (std::vector<PathExprSegment> path_segments,
                    std::vector<Attribute> outer_attrs, location_t locus,
                    bool has_opening_scope_resolution = false)
-    : outer_attrs (std::move (outer_attrs)),
+    : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
       has_opening_scope_resolution (has_opening_scope_resolution),
       locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()),
-      path (std::make_unique<RegularPath> (std::move (path_segments), locus,
-                                          _node_id)),
       marked_for_strip (false)
   {}
 
-  PathInExpression (LangItem::Kind lang_item_kind,
+  PathInExpression (LangItem::Kind lang_item,
                    std::vector<Attribute> outer_attrs, location_t locus)
-    : outer_attrs (std::move (outer_attrs)),
+    : Path (lang_item), outer_attrs (std::move (outer_attrs)),
       has_opening_scope_resolution (false), locus (locus),
       _node_id (Analysis::Mappings::get ().get_next_node_id ()),
-      path (std::make_unique<LangItemPath> (lang_item_kind, locus)),
       marked_for_strip (false)
   {}
 
-  PathInExpression (std::unique_ptr<Path> path,
-                   std::vector<Attribute> outer_attrs, location_t locus,
-                   bool has_opening_scope_resolution = false)
-    : outer_attrs (std::move (outer_attrs)),
-      has_opening_scope_resolution (has_opening_scope_resolution),
-      locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()),
-      path (std::move (path)), marked_for_strip (false)
-  {}
-
-  PathInExpression (const PathInExpression &other)
-    : outer_attrs (other.outer_attrs),
-      has_opening_scope_resolution (other.has_opening_scope_resolution),
-      locus (other.locus), _node_id (other._node_id),
-      path (other.path->clone_path ()),
-      marked_for_strip (other.marked_for_strip)
-  {}
-
-  PathInExpression &operator= (const PathInExpression &other)
-  {
-    outer_attrs = other.outer_attrs;
-    has_opening_scope_resolution = other.has_opening_scope_resolution;
-    locus = other.locus;
-    _node_id = other._node_id;
-    path = other.path->clone_path ();
-    marked_for_strip = other.marked_for_strip;
-
-    return *this;
-  }
-
   // Creates an error state path in expression.
   static PathInExpression create_error ()
   {
@@ -761,25 +690,19 @@ public:
   }
 
   // Returns whether path in expression is in an error state.
-  bool is_error () const
-  {
-    if (path->get_path_kind () == Path::Kind::Regular)
-      return !static_cast<RegularPath &> (*path).has_segments ();
-
-    rust_unreachable ();
-  }
+  bool is_error () const { return !has_segments (); }
 
   /* Converts PathInExpression to SimplePath if possible (i.e. no generic
    * arguments). Otherwise returns an empty SimplePath. */
   SimplePath as_simple_path () const
   {
-    // FIXME: Cleanup
-    if (path->get_path_kind () == Path::Kind::Regular)
-      return static_cast<RegularPath &> (*path).convert_to_simple_path (
-       has_opening_scope_resolution);
-    else
-      // FIXME: lang item to simple path?
-      rust_unreachable ();
+    /* delegate to parent class as can't access segments. however,
+     * QualifiedPathInExpression conversion to simple path wouldn't make
+     * sense, so the method in the parent class should be protected, not
+     * public. Have to pass in opening scope resolution as parent class has no
+     * access to it.
+     */
+    return convert_to_simple_path (has_opening_scope_resolution);
   }
 
   location_t get_locus () const override final { return locus; }
@@ -806,66 +729,18 @@ public:
 
   NodeId get_pattern_node_id () const { return get_node_id (); }
 
-  PathExprSegment &get_final_segment ()
-  {
-    if (path->get_path_kind () == Path::Kind::Regular)
-      return static_cast<RegularPath &> (*path).get_segments ().back ();
-
-    // lang item segment?
-    rust_unreachable ();
-  }
-
+  PathExprSegment &get_final_segment () { return get_segments ().back (); }
   const PathExprSegment &get_final_segment () const
   {
-    if (path->get_path_kind () == Path::Kind::Regular)
-      return static_cast<RegularPath &> (*path).get_segments ().back ();
-
-    // lang item segment?
-    rust_unreachable ();
+    return get_segments ().back ();
   }
 
-  const std::vector<PathExprSegment> &get_segments () const
-  {
-    if (path->get_path_kind () == Path::Kind::Regular)
-      return static_cast<RegularPath &> (*path).get_segments ();
-
-    rust_unreachable ();
-  }
-
-  std::vector<PathExprSegment> &get_segments ()
-  {
-    if (path->get_path_kind () == Path::Kind::Regular)
-      return static_cast<RegularPath &> (*path).get_segments ();
-
-    rust_unreachable ();
-  }
-
-  bool is_single_segment () const
-  {
-    if (path->get_path_kind () == Path::Kind::Regular)
-      return static_cast<RegularPath &> (*path).get_segments ().size () == 1;
-
-    rust_unreachable ();
-  }
-
-  Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
-
   Expr::Kind get_expr_kind () const override
   {
     return Expr::Kind::PathInExpression;
   }
 
 protected:
-  PathInExpression (std::vector<Attribute> &&outer_attrs,
-                   bool has_opening_scope_resolution, location_t locus,
-                   NodeId node_id, std::unique_ptr<Path> &&path,
-                   bool marked_for_strip)
-    : outer_attrs (std::move (outer_attrs)),
-      has_opening_scope_resolution (has_opening_scope_resolution),
-      locus (locus), _node_id (node_id), path (std::move (path)),
-      marked_for_strip (marked_for_strip)
-  {}
-
   /* Use covariance to implement clone function as returning this object
    * rather than base */
   PathInExpression *clone_pattern_impl () const final override
@@ -899,7 +774,8 @@ public:
   };
 
 private:
-  PathIdentSegment ident_segment;
+  tl::optional<LangItem::Kind> lang_item;
+  tl::optional<PathIdentSegment> ident_segment;
   location_t locus;
 
 protected:
@@ -929,21 +805,30 @@ public:
 
   TypePathSegment (PathIdentSegment ident_segment,
                   bool has_separating_scope_resolution, location_t locus)
-    : ident_segment (std::move (ident_segment)), locus (locus),
+    : lang_item (tl::nullopt), ident_segment (std::move (ident_segment)),
+      locus (locus),
       has_separating_scope_resolution (has_separating_scope_resolution),
       node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
+  TypePathSegment (LangItem::Kind lang_item, location_t locus)
+    : lang_item (lang_item), ident_segment (tl::nullopt), locus (locus),
+      has_separating_scope_resolution (false),
+      node_id (Analysis::Mappings::get ().get_next_node_id ())
+  {}
+
   TypePathSegment (std::string segment_name,
                   bool has_separating_scope_resolution, location_t locus)
-    : ident_segment (PathIdentSegment (std::move (segment_name), locus)),
+    : lang_item (tl::nullopt),
+      ident_segment (PathIdentSegment (std::move (segment_name), locus)),
       locus (locus),
       has_separating_scope_resolution (has_separating_scope_resolution),
       node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
   TypePathSegment (TypePathSegment const &other)
-    : ident_segment (other.ident_segment), locus (other.locus),
+    : lang_item (other.lang_item), ident_segment (other.ident_segment),
+      locus (other.locus),
       has_separating_scope_resolution (other.has_separating_scope_resolution),
       node_id (other.node_id)
   {}
@@ -951,6 +836,7 @@ public:
   TypePathSegment &operator= (TypePathSegment const &other)
   {
     ident_segment = other.ident_segment;
+    lang_item = other.lang_item;
     locus = other.locus;
     has_separating_scope_resolution = other.has_separating_scope_resolution;
     node_id = other.node_id;
@@ -961,16 +847,28 @@ public:
   TypePathSegment (TypePathSegment &&other) = default;
   TypePathSegment &operator= (TypePathSegment &&other) = default;
 
-  virtual std::string as_string () const { return ident_segment.as_string (); }
+  virtual std::string as_string () const
+  {
+    if (lang_item.has_value ())
+      return LangItem::PrettyString (*lang_item);
+
+    return ident_segment->as_string ();
+  }
 
   /* Returns whether the type path segment is in an error state. May be
    * virtual in future. */
-  bool is_error () const { return ident_segment.is_error (); }
+  bool is_error () const
+  {
+    rust_assert (ident_segment);
+    return ident_segment->is_error ();
+  }
 
   /* Returns whether segment is identifier only (as opposed to generic args or
    * function). Overridden in derived classes with other segments. */
   virtual bool is_ident_only () const { return true; }
 
+  bool is_lang_item () const { return lang_item.has_value (); }
+
   location_t get_locus () const { return locus; }
 
   // not pure virtual as class not abstract
@@ -981,8 +879,23 @@ public:
     return has_separating_scope_resolution;
   }
 
-  PathIdentSegment &get_ident_segment () { return ident_segment; };
-  const PathIdentSegment &get_ident_segment () const { return ident_segment; };
+  PathIdentSegment &get_ident_segment ()
+  {
+    rust_assert (!is_lang_item ());
+    return *ident_segment;
+  };
+
+  const PathIdentSegment &get_ident_segment () const
+  {
+    rust_assert (!is_lang_item ());
+    return *ident_segment;
+  };
+
+  LangItem::Kind get_lang_item () const
+  {
+    rust_assert (is_lang_item ());
+    return *lang_item;
+  }
 
   NodeId get_node_id () const { return node_id; }
 
@@ -1025,6 +938,12 @@ public:
       generic_args (std::move (generic_args))
   {}
 
+  TypePathSegmentGeneric (LangItem::Kind lang_item, GenericArgs generic_args,
+                         location_t locus)
+    : TypePathSegment (lang_item, locus),
+      generic_args (std::move (generic_args))
+  {}
+
   // Constructor from segment name and all args
   TypePathSegmentGeneric (std::string segment_name,
                          bool has_separating_scope_resolution,
@@ -1082,7 +1001,7 @@ private:
   /*bool has_inputs;
   TypePathFnInputs inputs;*/
   // inlined from TypePathFnInputs
-  std::vector<std::unique_ptr<Type> > inputs;
+  std::vector<std::unique_ptr<Type>> inputs;
 
   // bool has_type;
   std::unique_ptr<Type> return_type;
@@ -1115,8 +1034,8 @@ public:
   }
 
   // Constructor
-  TypePathFunction (std::vector<std::unique_ptr<Type> > inputs,
-                   location_t locus, std::unique_ptr<Type> type = nullptr)
+  TypePathFunction (std::vector<std::unique_ptr<Type>> inputs, location_t 
locus,
+                   std::unique_ptr<Type> type = nullptr)
     : inputs (std::move (inputs)), return_type (std::move (type)),
       is_invalid (false), locus (locus)
   {}
@@ -1161,11 +1080,11 @@ public:
   std::string as_string () const;
 
   // TODO: this mutable getter seems really dodgy. Think up better way.
-  const std::vector<std::unique_ptr<Type> > &get_params () const
+  const std::vector<std::unique_ptr<Type>> &get_params () const
   {
     return inputs;
   }
-  std::vector<std::unique_ptr<Type> > &get_params () { return inputs; }
+  std::vector<std::unique_ptr<Type>> &get_params () { return inputs; }
 
   // TODO: is this better? Or is a "vis_pattern" better?
   Type &get_return_type ()
@@ -1229,10 +1148,10 @@ public:
   }
 };
 
-class TypePath : public TypeNoBounds, public Path
+class TypePath : public TypeNoBounds
 {
   bool has_opening_scope_resolution;
-  std::vector<std::unique_ptr<TypePathSegment> > segments;
+  std::vector<std::unique_ptr<TypePathSegment>> segments;
   location_t locus;
 
 protected:
@@ -1257,12 +1176,20 @@ public:
   // Creates an error state TypePath.
   static TypePath create_error ()
   {
-    return TypePath (std::vector<std::unique_ptr<TypePathSegment> > (),
+    return TypePath (std::vector<std::unique_ptr<TypePathSegment>> (),
                     UNDEF_LOCATION);
   }
 
   // Constructor
-  TypePath (std::vector<std::unique_ptr<TypePathSegment> > segments,
+  TypePath (std::vector<std::unique_ptr<TypePathSegment>> segments,
+           location_t locus, bool has_opening_scope_resolution = false)
+    : TypeNoBounds (),
+      has_opening_scope_resolution (has_opening_scope_resolution),
+      segments (std::move (segments)), locus (locus)
+  {}
+
+  TypePath (LangItem::Kind lang_item,
+           std::vector<std::unique_ptr<TypePathSegment>> segments,
            location_t locus, bool has_opening_scope_resolution = false)
     : TypeNoBounds (),
       has_opening_scope_resolution (has_opening_scope_resolution),
@@ -1308,7 +1235,7 @@ public:
   TraitBound *to_trait_bound (bool in_parens) const override;
 
   location_t get_locus () const override final { return locus; }
-  NodeId get_node_id () const override final { return node_id; }
+  NodeId get_node_id () const { return node_id; }
 
   void mark_for_strip () override {}
   bool is_marked_for_strip () const override { return false; }
@@ -1316,27 +1243,23 @@ public:
   void accept_vis (ASTVisitor &vis) override;
 
   // TODO: this seems kinda dodgy
-  std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
+  std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
   {
     return segments;
   }
-  const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const
+  const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
   {
     return segments;
   }
 
   size_t get_num_segments () const { return segments.size (); }
-
-  Path::Kind get_path_kind () const override { return Path::Kind::Type; }
-
-  Path *clone_path_impl () const override { return new TypePath (*this); }
 };
 
 struct QualifiedPathType
 {
 private:
   std::unique_ptr<Type> type_to_invoke_on;
-  std::unique_ptr<Path> trait_path;
+  TypePath trait_path;
   location_t locus;
   NodeId node_id;
 
@@ -1345,14 +1268,13 @@ public:
   QualifiedPathType (std::unique_ptr<Type> invoke_on_type,
                     location_t locus = UNDEF_LOCATION,
                     TypePath trait_path = TypePath::create_error ())
-    : type_to_invoke_on (std::move (invoke_on_type)),
-      trait_path (std::unique_ptr<TypePath> (new TypePath (trait_path))),
+    : type_to_invoke_on (std::move (invoke_on_type)), trait_path (trait_path),
       locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
   // Copy constructor uses custom deep copy for Type to preserve polymorphism
   QualifiedPathType (QualifiedPathType const &other)
-    : trait_path (other.trait_path->clone_path ()), locus (other.locus)
+    : trait_path (other.trait_path), locus (other.locus)
   {
     node_id = other.node_id;
     // guard to prevent null dereference
@@ -1367,7 +1289,7 @@ public:
   QualifiedPathType &operator= (QualifiedPathType const &other)
   {
     node_id = other.node_id;
-    trait_path = other.trait_path->clone_path ();
+    trait_path = other.trait_path;
     locus = other.locus;
 
     // guard to prevent null dereference
@@ -1384,11 +1306,7 @@ public:
   QualifiedPathType &operator= (QualifiedPathType &&other) = default;
 
   // Returns whether the qualified path type has a rebind as clause.
-  bool has_as_clause () const
-  {
-    rust_assert (trait_path->get_path_kind () == Path::Kind::Type);
-    return !static_cast<TypePath &> (*trait_path).is_error ();
-  }
+  bool has_as_clause () const { return !trait_path.is_error (); }
 
   // Returns whether the qualified path type is in an error state.
   bool is_error () const { return type_to_invoke_on == nullptr; }
@@ -1417,10 +1335,10 @@ public:
   }
 
   // TODO: is this better? Or is a "vis_pattern" better?
-  Path &get_as_type_path ()
+  TypePath &get_as_type_path ()
   {
     rust_assert (has_as_clause ());
-    return *trait_path;
+    return trait_path;
   }
 
   NodeId get_node_id () const { return node_id; }
@@ -1428,12 +1346,12 @@ public:
 
 /* AST node representing a qualified path-in-expression pattern (path that
  * allows specifying trait functions) */
-class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock
+class QualifiedPathInExpression : public Path, public ExprWithoutBlock
 {
   std::vector<Attribute> outer_attrs;
   QualifiedPathType path_type;
-
-  std::unique_ptr<Path> path;
+  location_t locus;
+  NodeId _node_id;
 
 public:
   std::string as_string () const override;
@@ -1442,16 +1360,9 @@ public:
                             std::vector<PathExprSegment> path_segments,
                             std::vector<Attribute> outer_attrs,
                             location_t locus)
-    : outer_attrs (std::move (outer_attrs)),
-      path_type (std::move (qual_path_type)),
-      path (std::make_unique<RegularPath> (
-       std::move (path_segments), locus,
-       Analysis::Mappings::get ().get_next_node_id ()))
-  {}
-
-  QualifiedPathInExpression (const QualifiedPathInExpression &other)
-    : outer_attrs (other.outer_attrs), path_type (other.path_type),
-      path (other.path->clone_path ())
+    : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)),
+      path_type (std::move (qual_path_type)), locus (locus),
+      _node_id (Analysis::Mappings::get ().get_next_node_id ())
   {}
 
   /* TODO: maybe make a shortcut constructor that has QualifiedPathType
@@ -1467,9 +1378,7 @@ public:
                                      {}, UNDEF_LOCATION);
   }
 
-  Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
-
-  location_t get_locus () const override final { return path->get_locus (); }
+  location_t get_locus () const override final { return locus; }
 
   void accept_vis (ASTVisitor &vis) override;
 
@@ -1495,31 +1404,7 @@ public:
     outer_attrs = std::move (new_attrs);
   }
 
-  NodeId get_node_id () const override { return path->get_node_id (); }
-
-  const std::vector<PathExprSegment> &get_segments () const
-  {
-    if (path->get_path_kind () == Path::Kind::Regular)
-      return static_cast<RegularPath &> (*path).get_segments ();
-
-    rust_unreachable ();
-  }
-
-  std::vector<PathExprSegment> &get_segments ()
-  {
-    if (path->get_path_kind () == Path::Kind::Regular)
-      return static_cast<RegularPath &> (*path).get_segments ();
-
-    rust_unreachable ();
-  }
-
-  bool is_single_segment () const
-  {
-    if (path->get_path_kind () == Path::Kind::Regular)
-      return static_cast<RegularPath &> (*path).get_segments ().size () == 1;
-
-    rust_unreachable ();
-  }
+  NodeId get_node_id () const override { return _node_id; }
 
   Expr::Kind get_expr_kind () const override
   {
@@ -1555,7 +1440,7 @@ class QualifiedPathInType : public TypeNoBounds
 {
   QualifiedPathType path_type;
   std::unique_ptr<TypePathSegment> associated_segment;
-  std::vector<std::unique_ptr<TypePathSegment> > segments;
+  std::vector<std::unique_ptr<TypePathSegment>> segments;
   location_t locus;
 
 protected:
@@ -1570,7 +1455,7 @@ public:
   QualifiedPathInType (
     QualifiedPathType qual_path_type,
     std::unique_ptr<TypePathSegment> associated_segment,
-    std::vector<std::unique_ptr<TypePathSegment> > path_segments,
+    std::vector<std::unique_ptr<TypePathSegment>> path_segments,
     location_t locus)
     : path_type (std::move (qual_path_type)),
       associated_segment (std::move (associated_segment)),
@@ -1617,7 +1502,7 @@ public:
   {
     return QualifiedPathInType (
       QualifiedPathType::create_error (), nullptr,
-      std::vector<std::unique_ptr<TypePathSegment> > (), UNDEF_LOCATION);
+      std::vector<std::unique_ptr<TypePathSegment>> (), UNDEF_LOCATION);
   }
 
   std::string as_string () const override;
@@ -1637,11 +1522,11 @@ public:
   }
 
   // TODO: this seems kinda dodgy
-  std::vector<std::unique_ptr<TypePathSegment> > &get_segments ()
+  std::vector<std::unique_ptr<TypePathSegment>> &get_segments ()
   {
     return segments;
   }
-  const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const
+  const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const
   {
     return segments;
   }
diff --git a/gcc/rust/expand/rust-derive-copy.cc 
b/gcc/rust/expand/rust-derive-copy.cc
index f8007abd575e..bcfe1db6b4a1 100644
--- a/gcc/rust/expand/rust-derive-copy.cc
+++ b/gcc/rust/expand/rust-derive-copy.cc
@@ -46,7 +46,9 @@ DeriveCopy::copy_impl (
   // `$crate::core::marker::Copy` instead
   auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
   segments.emplace_back (builder.type_path_segment ("Copy"));
-  auto copy = std::make_unique<LangItemPath> (LangItem::Kind::COPY, loc);
+
+  auto copy = TypePath (std::move (segments), loc);
+  // auto copy = TypePath (LangItem::Kind::COPY, loc);
 
   // we need to build up the generics for this impl block which will be just a
   // clone of the types specified ones
diff --git a/gcc/rust/expand/rust-derive.h b/gcc/rust/expand/rust-derive.h
index 967064c04208..1924432d8ed1 100644
--- a/gcc/rust/expand/rust-derive.h
+++ b/gcc/rust/expand/rust-derive.h
@@ -81,8 +81,6 @@ private:
   virtual void visit (Lifetime &lifetime) override final{};
   virtual void visit (LifetimeParam &lifetime_param) override final{};
   virtual void visit (ConstGenericParam &const_param) override final{};
-  virtual void visit (RegularPath &path) override final{};
-  virtual void visit (LangItemPath &path) override final{};
   virtual void visit (PathInExpression &path) override final{};
   virtual void visit (TypePathSegment &segment) override final{};
   virtual void visit (TypePathSegmentGeneric &segment) override final{};
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc 
b/gcc/rust/hir/rust-ast-lower-base.cc
index f6d7f0caf5b8..35a25093b73a 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -64,12 +64,6 @@ ASTLoweringBase::visit (AST::ConstGenericParam &)
 
 // rust-path.h
 void
-ASTLoweringBase::visit (AST::RegularPath &)
-{}
-void
-ASTLoweringBase::visit (AST::LangItemPath &)
-{}
-void
 ASTLoweringBase::visit (AST::PathInExpression &)
 {}
 void
diff --git a/gcc/rust/hir/rust-ast-lower-base.h 
b/gcc/rust/hir/rust-ast-lower-base.h
index 4cb098b7ab8e..1bd1343bd166 100644
--- a/gcc/rust/hir/rust-ast-lower-base.h
+++ b/gcc/rust/hir/rust-ast-lower-base.h
@@ -84,8 +84,6 @@ public:
   //  virtual void visit(TraitImplItem& trait_impl_item);
 
   // rust-path.h
-  virtual void visit (AST::RegularPath &path);
-  virtual void visit (AST::LangItemPath &path);
   virtual void visit (AST::PathInExpression &path);
   virtual void visit (AST::TypePathSegment &segment);
   virtual void visit (AST::TypePathSegmentGeneric &segment);
diff --git a/gcc/rust/hir/rust-ast-lower-type.cc 
b/gcc/rust/hir/rust-ast-lower-type.cc
index d1f95edc3456..e78c1307523d 100644
--- a/gcc/rust/hir/rust-ast-lower-type.cc
+++ b/gcc/rust/hir/rust-ast-lower-type.cc
@@ -27,22 +27,10 @@ namespace Rust {
 namespace HIR {
 
 HIR::TypePath *
-ASTLowerTypePath::translate (AST::Path &type)
+ASTLowerTypePath::translate (AST::TypePath &type)
 {
   ASTLowerTypePath resolver;
-
-  switch (type.get_path_kind ())
-    {
-    case AST::Path::Kind::LangItem:
-      resolver.visit (static_cast<AST::LangItemPath &> (type));
-      break;
-    case AST::Path::Kind::Type:
-      resolver.visit (static_cast<AST::TypePath &> (type));
-      break;
-    default:
-      rust_unreachable ();
-    }
-
+  type.accept_vis (resolver);
   rust_assert (resolver.translated != nullptr);
   return resolver.translated;
 }
@@ -98,10 +86,6 @@ ASTLowerTypePath::visit (AST::TypePathSegmentGeneric 
&segment)
 {
   std::vector<HIR::GenericArgsBinding> binding_args; // TODO
 
-  std::string segment_name = segment.get_ident_segment ().as_string ();
-  bool has_separating_scope_resolution
-    = segment.get_separating_scope_resolution ();
-
   auto generic_args = lower_generic_args (segment.get_generic_args ());
 
   auto crate_num = mappings.get_current_crate ();
@@ -109,10 +93,24 @@ ASTLowerTypePath::visit (AST::TypePathSegmentGeneric 
&segment)
   Analysis::NodeMapping mapping (crate_num, segment.get_node_id (), hirid,
                                 UNKNOWN_LOCAL_DEFID);
 
-  translated_segment
-    = new HIR::TypePathSegmentGeneric (std::move (mapping), segment_name,
-                                      has_separating_scope_resolution,
-                                      generic_args, segment.get_locus ());
+  if (segment.is_lang_item ())
+    {
+      translated_segment
+       = new HIR::TypePathSegmentGeneric (std::move (mapping),
+                                          segment.get_lang_item (),
+                                          generic_args, segment.get_locus ());
+    }
+  else
+    {
+      std::string segment_name = segment.get_ident_segment ().as_string ();
+      bool has_separating_scope_resolution
+       = segment.get_separating_scope_resolution ();
+
+      translated_segment
+       = new HIR::TypePathSegmentGeneric (std::move (mapping), segment_name,
+                                          has_separating_scope_resolution,
+                                          generic_args, segment.get_locus ());
+    }
 }
 
 void
@@ -141,25 +139,26 @@ ASTLowerTypePath::visit (AST::TypePath &path)
                         path.has_opening_scope_resolution_op ());
 }
 
-void
-ASTLowerTypePath::visit (AST::LangItemPath &path)
-{
-  auto crate_num = mappings.get_current_crate ();
-  auto hirid = mappings.get_next_hir_id (crate_num);
+// void
+// ASTLowerTypePath::visit (AST::LangItemPath &path)
+// {
+//   auto crate_num = mappings.get_current_crate ();
+//   auto hirid = mappings.get_next_hir_id (crate_num);
 
-  Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid,
-                                mappings.get_next_localdef_id (crate_num));
+//   Analysis::NodeMapping mapping (crate_num, path.get_node_id (), hirid,
+//                              mappings.get_next_localdef_id (crate_num));
 
-  std::vector<std::unique_ptr<HIR::TypePathSegment>> translated_segments;
-  translated_segments.emplace_back (std::unique_ptr<HIR::TypePathSegment> (
-    new HIR::TypePathSegment (mapping,
-                             LangItem::ToString (path.get_lang_item_kind ()),
-                             false, path.get_locus ())));
+//   std::vector<std::unique_ptr<HIR::TypePathSegment>> translated_segments;
+//   translated_segments.emplace_back (std::unique_ptr<HIR::TypePathSegment> (
+//     new HIR::TypePathSegment (mapping,
+//                           LangItem::ToString (path.get_lang_item_kind ()),
+//                           false, path.get_locus ())));
 
-  translated
-    = new HIR::TypePath (std::move (mapping), std::move (translated_segments),
-                        path.get_locus ());
-}
+//   translated
+//     = new HIR::TypePath (std::move (mapping), std::move
+//     (translated_segments),
+//                      path.get_locus ());
+// }
 
 HIR::QualifiedPathInType *
 ASTLowerQualifiedPathInType::translate (AST::QualifiedPathInType &type)
diff --git a/gcc/rust/hir/rust-ast-lower-type.h 
b/gcc/rust/hir/rust-ast-lower-type.h
index 26ca8684083c..af0b4bec9194 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -33,22 +33,18 @@ protected:
   using Rust::HIR::ASTLoweringBase::visit;
 
 public:
-  static HIR::TypePath *translate (AST::Path &type);
+  static HIR::TypePath *translate (AST::TypePath &type);
 
   void visit (AST::TypePathSegmentFunction &segment) override;
   void visit (AST::TypePathSegment &segment) override;
   void visit (AST::TypePathSegmentGeneric &segment) override;
   void visit (AST::TypePath &path) override;
-  void visit (AST::LangItemPath &path) override;
 
 protected:
   HIR::TypePathSegment *translated_segment;
 
 private:
   HIR::TypePath *translated;
-
-  static HIR::TypePath *translate_type_path (AST::TypePath &type);
-  static HIR::TypePath *translate_lang_item_type_path (AST::LangItemPath 
&type);
 };
 
 class ASTLowerQualifiedPathInType : public ASTLowerTypePath
diff --git a/gcc/rust/hir/tree/rust-hir-path.cc 
b/gcc/rust/hir/tree/rust-hir-path.cc
index c8d3079a85e3..7db2b25b5aaf 100644
--- a/gcc/rust/hir/tree/rust-hir-path.cc
+++ b/gcc/rust/hir/tree/rust-hir-path.cc
@@ -17,6 +17,7 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-hir-path.h"
+#include "optional.h"
 #include "rust-hir-bound.h"
 
 namespace Rust {
@@ -164,17 +165,25 @@ TypePathSegment::TypePathSegment (Analysis::NodeMapping 
mappings,
                                  bool has_separating_scope_resolution,
                                  location_t locus)
   : mappings (std::move (mappings)), ident_segment (std::move (ident_segment)),
-    locus (locus),
+    lang_item (tl::nullopt), locus (locus),
     has_separating_scope_resolution (has_separating_scope_resolution),
     type (SegmentType::REG)
 {}
 
+TypePathSegment::TypePathSegment (Analysis::NodeMapping mappings,
+                                 LangItem::Kind lang_item, location_t locus)
+  : mappings (std::move (mappings)), ident_segment (tl::nullopt),
+    lang_item (lang_item), locus (locus),
+    has_separating_scope_resolution (false), 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),
+    ident_segment (PathIdentSegment (std::move (segment_name))),
+    lang_item (tl::nullopt), locus (locus),
     has_separating_scope_resolution (has_separating_scope_resolution),
     type (SegmentType::REG)
 {}
@@ -188,6 +197,14 @@ TypePathSegmentGeneric::TypePathSegmentGeneric (
     generic_args (std::move (generic_args))
 {}
 
+TypePathSegmentGeneric::TypePathSegmentGeneric (Analysis::NodeMapping mappings,
+                                               LangItem::Kind lang_item,
+                                               GenericArgs generic_args,
+                                               location_t locus)
+  : TypePathSegment (std::move (mappings), lang_item, 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,
diff --git a/gcc/rust/hir/tree/rust-hir-path.h 
b/gcc/rust/hir/tree/rust-hir-path.h
index 7ef66b86ab0e..bbb9c2d60773 100644
--- a/gcc/rust/hir/tree/rust-hir-path.h
+++ b/gcc/rust/hir/tree/rust-hir-path.h
@@ -355,7 +355,8 @@ public:
 
 private:
   Analysis::NodeMapping mappings;
-  PathIdentSegment ident_segment;
+  tl::optional<PathIdentSegment> ident_segment;
+  tl::optional<LangItem::Kind> lang_item;
   location_t locus;
 
 protected:
@@ -384,14 +385,27 @@ public:
                   PathIdentSegment ident_segment,
                   bool has_separating_scope_resolution, location_t locus);
 
+  TypePathSegment (Analysis::NodeMapping mappings, LangItem::Kind lang_item,
+                  location_t locus);
+
   TypePathSegment (Analysis::NodeMapping mappings, std::string segment_name,
                   bool has_separating_scope_resolution, location_t locus);
 
-  virtual std::string as_string () const { return ident_segment.as_string (); }
+  virtual std::string as_string () const
+  {
+    if (ident_segment)
+      return ident_segment->as_string ();
+
+    return LangItem::PrettyString (*lang_item);
+  }
 
   /* Returns whether the type path segment is in an error state. May be virtual
    * in future. */
-  bool is_error () const { return ident_segment.is_error (); }
+  bool is_error () const
+  {
+    rust_assert (ident_segment);
+    return ident_segment->is_error ();
+  }
 
   /* Returns whether segment is identifier only (as opposed to generic args or
    * function). Overriden in derived classes with other segments. */
@@ -404,12 +418,24 @@ public:
 
   const Analysis::NodeMapping &get_mappings () const { return mappings; }
 
-  const PathIdentSegment &get_ident_segment () const { return ident_segment; }
+  const PathIdentSegment &get_ident_segment () const
+  {
+    rust_assert (ident_segment);
+    return *ident_segment;
+  }
+
+  const LangItem::Kind &get_lang_item () const
+  {
+    rust_assert (lang_item);
+    return *lang_item;
+  }
 
   bool is_generic_segment () const
   {
     return get_type () == SegmentType::GENERIC;
   }
+
+  bool is_lang_item () const { return lang_item.has_value (); }
 };
 
 // Segment used in type path with generic args
@@ -428,6 +454,10 @@ public:
                          bool has_separating_scope_resolution,
                          GenericArgs generic_args, location_t locus);
 
+  TypePathSegmentGeneric (Analysis::NodeMapping mappings,
+                         LangItem::Kind lang_item, GenericArgs generic_args,
+                         location_t locus);
+
   // Constructor from segment name and all args
   TypePathSegmentGeneric (Analysis::NodeMapping mappings,
                          std::string segment_name,
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.cc 
b/gcc/rust/resolve/rust-ast-resolve-base.cc
index b23c1eba1121..6c35a22b7f64 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-base.cc
@@ -71,14 +71,6 @@ void
 ResolverBase::visit (AST::ConstGenericParam &)
 {}
 
-void
-ResolverBase::visit (AST::RegularPath &)
-{}
-
-void
-ResolverBase::visit (AST::LangItemPath &)
-{}
-
 void
 ResolverBase::visit (AST::PathInExpression &)
 {}
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h 
b/gcc/rust/resolve/rust-ast-resolve-base.h
index 703460ad0d93..0d497f81eacc 100644
--- a/gcc/rust/resolve/rust-ast-resolve-base.h
+++ b/gcc/rust/resolve/rust-ast-resolve-base.h
@@ -40,8 +40,6 @@ public:
   void visit (AST::Lifetime &);
   void visit (AST::LifetimeParam &);
   void visit (AST::ConstGenericParam &);
-  void visit (AST::RegularPath &);
-  void visit (AST::LangItemPath &);
   void visit (AST::PathInExpression &);
   void visit (AST::TypePathSegment &);
   void visit (AST::TypePathSegmentGeneric &);
diff --git a/gcc/rust/resolve/rust-ast-resolve-item.cc 
b/gcc/rust/resolve/rust-ast-resolve-item.cc
index 33b4fc9b9792..b26ac340e926 100644
--- a/gcc/rust/resolve/rust-ast-resolve-item.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-item.cc
@@ -682,28 +682,15 @@ ResolveItem::visit (AST::TraitImpl &impl_block)
 
   // setup paths
   CanonicalPath canonical_trait_type = CanonicalPath::create_empty ();
-  if (impl_block.get_trait_path ().get_path_kind ()
-      == AST::Path::Kind::LangItem)
-    {
-      auto &lang_item
-       = static_cast<AST::LangItemPath &> (impl_block.get_trait_path ());
 
-      canonical_trait_type
-       = CanonicalPath::new_seg (lang_item.get_node_id (),
-                                 LangItem::ToString (
-                                   lang_item.get_lang_item_kind ()));
-    }
-  else
+  ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path (),
+                                      canonical_trait_type);
+  if (!ok)
     {
-      ok = ResolveTypeToCanonicalPath::go (impl_block.get_trait_path_type (),
-                                          canonical_trait_type);
-      if (!ok)
-       {
-         resolver->get_name_scope ().pop ();
-         resolver->get_type_scope ().pop ();
-         resolver->get_label_scope ().pop ();
-         return;
-       }
+      resolver->get_name_scope ().pop ();
+      resolver->get_type_scope ().pop ();
+      resolver->get_label_scope ().pop ();
+      return;
     }
 
   rust_debug ("AST::TraitImpl resolve trait type: {%s}",
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc 
b/gcc/rust/resolve/rust-ast-resolve-type.cc
index 1d004b1ba9bb..63c9daca565f 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -20,6 +20,7 @@
 #include "rust-ast-resolve-expr.h"
 #include "rust-canonical-path.h"
 #include "rust-type.h"
+#include "rust-hir-map.h"
 
 namespace Rust {
 namespace Resolver {
@@ -99,45 +100,57 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId 
&resolved_node_id)
   for (size_t i = 0; i < path.get_segments ().size (); i++)
     {
       auto &segment = path.get_segments ().at (i);
-      const AST::PathIdentSegment &ident_seg = segment->get_ident_segment ();
       bool is_first_segment = i == 0;
-      resolved_node_id = UNKNOWN_NODEID;
+      NodeId crate_scope_id = resolver->peek_crate_module_scope ();
+      auto ident_string = segment->is_lang_item ()
+                           ? LangItem::PrettyString (segment->get_lang_item ())
+                           : segment->get_ident_segment ().as_string ();
 
-      bool in_middle_of_path = i > 0;
-      if (in_middle_of_path && segment->is_lower_self_seg ())
-       {
-         rust_error_at (segment->get_locus (), ErrorCode::E0433,
-                        "failed to resolve: %qs in paths can only be used "
-                        "in start position",
-                        segment->as_string ().c_str ());
-         return false;
-       }
+      resolved_node_id = UNKNOWN_NODEID;
 
-      NodeId crate_scope_id = resolver->peek_crate_module_scope ();
-      if (segment->is_crate_path_seg ())
+      if (segment->is_lang_item ())
        {
-         // what is the current crate scope node id?
-         module_scope_id = crate_scope_id;
-         previous_resolved_node_id = module_scope_id;
-         resolver->insert_resolved_name (segment->get_node_id (),
-                                         module_scope_id);
-
-         continue;
+         resolved_node_id = Analysis::Mappings::get ().get_lang_item_node (
+           segment->get_lang_item ());
+         previous_resolved_node_id = resolved_node_id;
        }
-      else if (segment->is_super_path_seg ())
+      else
        {
-         if (module_scope_id == crate_scope_id)
+         bool in_middle_of_path = i > 0;
+         if (in_middle_of_path && segment->is_lower_self_seg ())
            {
-             rust_error_at (segment->get_locus (),
-                            "cannot use super at the crate scope");
+             rust_error_at (segment->get_locus (), ErrorCode::E0433,
+                            "failed to resolve: %qs in paths can only be used "
+                            "in start position",
+                            segment->as_string ().c_str ());
              return false;
            }
 
-         module_scope_id = resolver->peek_parent_module_scope ();
-         previous_resolved_node_id = module_scope_id;
-         resolver->insert_resolved_name (segment->get_node_id (),
-                                         module_scope_id);
-         continue;
+         if (segment->is_crate_path_seg ())
+           {
+             // what is the current crate scope node id?
+             module_scope_id = crate_scope_id;
+             previous_resolved_node_id = module_scope_id;
+             resolver->insert_resolved_name (segment->get_node_id (),
+                                             module_scope_id);
+
+             continue;
+           }
+         else if (segment->is_super_path_seg ())
+           {
+             if (module_scope_id == crate_scope_id)
+               {
+                 rust_error_at (segment->get_locus (),
+                                "cannot use super at the crate scope");
+                 return false;
+               }
+
+             module_scope_id = resolver->peek_parent_module_scope ();
+             previous_resolved_node_id = module_scope_id;
+             resolver->insert_resolved_name (segment->get_node_id (),
+                                             module_scope_id);
+             continue;
+           }
        }
 
       switch (segment->get_type ())
@@ -177,8 +190,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId 
&resolved_node_id)
          // name scope first
          NodeId resolved_node = UNKNOWN_NODEID;
          const CanonicalPath path
-           = CanonicalPath::new_seg (segment->get_node_id (),
-                                     ident_seg.as_string ());
+           = CanonicalPath::new_seg (segment->get_node_id (), ident_string);
          if (resolver->get_type_scope ().lookup (path, &resolved_node))
            {
              resolver->insert_resolved_type (segment->get_node_id (),
@@ -191,7 +203,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId 
&resolved_node_id)
                                              resolved_node);
              resolved_node_id = resolved_node;
            }
-         else if (segment->is_lower_self_seg ())
+         else if (!segment->is_lang_item () && segment->is_lower_self_seg ())
            {
              // what is the current crate scope node id?
              module_scope_id = crate_scope_id;
@@ -207,8 +219,7 @@ ResolveRelativeTypePath::go (AST::TypePath &path, NodeId 
&resolved_node_id)
          && previous_resolved_node_id == module_scope_id)
        {
          tl::optional<CanonicalPath &> resolved_child
-           = mappings.lookup_module_child (module_scope_id,
-                                           ident_seg.as_string ());
+           = mappings.lookup_module_child (module_scope_id, ident_string);
          if (resolved_child.has_value ())
            {
              NodeId resolved_node = resolved_child->get_node_id ();
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h 
b/gcc/rust/resolve/rust-ast-resolve-type.h
index 5e8cdb11b2d7..662f2f5a6683 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.h
+++ b/gcc/rust/resolve/rust-ast-resolve-type.h
@@ -61,37 +61,6 @@ class ResolveType : public ResolverBase
   using Rust::Resolver::ResolverBase::visit;
 
 public:
-  static NodeId go (AST::TypePath &type_path)
-  {
-    return ResolveType::go ((AST::Type &) type_path);
-  }
-
-  static NodeId go (AST::Path &type_path)
-  {
-    if (type_path.get_path_kind () == AST::Path::Kind::LangItem)
-      {
-       auto &type = static_cast<AST::LangItemPath &> (type_path);
-
-       auto lang_item = Analysis::Mappings::get ()
-                          .lookup_lang_item_node (type.get_lang_item_kind ())
-                          .value ();
-
-       auto resolver = Resolver::get ();
-       resolver->insert_resolved_type (type.get_node_id (), lang_item);
-
-       return lang_item;
-      }
-
-    rust_assert (type_path.get_path_kind () == AST::Path::Kind::Type);
-
-    // We have to do this dance to first downcast to a typepath, and then 
upcast
-    // to a Type. The altnernative is to split `go` into `go` and `go_inner` or
-    // something, but eventually this will need to change as we'll need
-    // `ResolveType::` to resolve other kinds of `Path`s as well.
-    return ResolveType::go (
-      (AST::Type &) static_cast<AST::TypePath &> (type_path));
-  }
-
   static NodeId go (AST::Type &type)
   {
     ResolveType resolver;
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
index bb099ab68aec..9da56ea3214d 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -248,25 +248,6 @@ Late::visit (AST::PathInExpression &expr)
                 Definition (resolved->get_node_id ()));
 }
 
-void
-Late::visit (AST::LangItemPath &type)
-{
-  auto &mappings = Rust::Analysis::Mappings::get ();
-  auto lang_item = mappings.lookup_lang_item_node (type.get_lang_item_kind ());
-
-  if (!lang_item)
-    {
-      rust_fatal_error (
-       type.get_locus (), "use of undeclared lang item %qs",
-       LangItem::ToString (type.get_lang_item_kind ()).c_str ());
-      return;
-    }
-
-  ctx.map_usage (Usage (type.get_node_id ()), Definition (lang_item.value ()));
-
-  DefaultResolver::visit (type);
-}
-
 void
 Late::visit (AST::TypePath &type)
 {
diff --git a/gcc/rust/resolve/rust-late-name-resolver-2.0.h 
b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
index 2af73c382869..ade78c5bc5f0 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.h
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.h
@@ -46,7 +46,6 @@ public:
   // resolutions
   void visit (AST::IdentifierExpr &) override;
   void visit (AST::PathInExpression &) override;
-  void visit (AST::LangItemPath &) override;
   void visit (AST::TypePath &) override;
   void visit (AST::Trait &) override;
   void visit (AST::StructExprStruct &) override;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc 
b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index bb23f8441edd..9f19facdffe3 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -410,7 +410,7 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, 
size_t *offset,
            {
              rust_error_at (seg->get_locus (),
                             "unknown reference for resolved name: %qs",
-                            seg->get_ident_segment ().as_string ().c_str ());
+                            seg->as_string ().c_str ());
              return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
            }
          return root_tyty;

Reply via email to