From: Arthur Cohen <[email protected]>

gcc/rust/ChangeLog:

        * ast/rust-ast.h: Add Type::Kind.
        * ast/rust-macro.h: Use it.
        * ast/rust-path.h: Likewise.
        * ast/rust-type.h: Likewise.
        * resolve/rust-default-resolver.cc (is_lang_impl): New method.
        (DefaultResolver::visit): Collect lang item implementations in the
        prelude.
        * resolve/rust-forever-stack.h: Add new method for lang prelude 
injection.
        * resolve/rust-forever-stack.hxx: Define it.
        * resolve/rust-late-name-resolver-2.0.cc (Late::visit): Identifier 
patterns
        can resolve to empty structs or variants.
        * resolve/rust-name-resolution-context.h: Improve resolution.
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: 
https://github.com/Rust-GCC/gccrs/commit/457a44e399c359e0bdc176422eb48bbcab393ca7

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4346

 gcc/rust/ast/rust-ast.h                       | 22 +++++++++++
 gcc/rust/ast/rust-macro.h                     |  5 +++
 gcc/rust/ast/rust-path.h                      |  7 ++++
 gcc/rust/ast/rust-type.h                      | 38 +++++++++++++++++++
 gcc/rust/resolve/rust-default-resolver.cc     | 25 ++++++++++++
 gcc/rust/resolve/rust-forever-stack.h         |  8 ++++
 gcc/rust/resolve/rust-forever-stack.hxx       |  8 ++++
 .../resolve/rust-late-name-resolver-2.0.cc    | 28 +++++++++++++-
 .../resolve/rust-name-resolution-context.h    | 12 +++---
 9 files changed, 144 insertions(+), 9 deletions(-)

diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h
index 4d5eddc6a..65d1c3f0a 100644
--- a/gcc/rust/ast/rust-ast.h
+++ b/gcc/rust/ast/rust-ast.h
@@ -1450,6 +1450,28 @@ class TraitBound;
 class Type : public Visitable
 {
 public:
+  enum Kind
+  {
+    MacroInvocation,
+    TypePath,
+    QualifiedPathInType,
+    ImplTrait,
+    TraitObject,
+    Parenthesised,
+    ImplTraitTypeOneBound,
+    TraitObjectTypeOneBound,
+    Tuple,
+    Never,
+    RawPointer,
+    Reference,
+    Array,
+    Slice,
+    Inferred,
+    BareFunction,
+  };
+
+  virtual Kind get_type_kind () const = 0;
+
   // Unique pointer custom clone function
   std::unique_ptr<Type> clone_type () const
   {
diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h
index 3cb3a0049..2fe190e1d 100644
--- a/gcc/rust/ast/rust-macro.h
+++ b/gcc/rust/ast/rust-macro.h
@@ -818,6 +818,11 @@ public:
     return Item::Kind::MacroInvocation;
   }
 
+  Type::Kind get_type_kind () const override
+  {
+    return Type::Kind::MacroInvocation;
+  }
+
 protected:
   Item *clone_item_impl () const override
   {
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index ddc82c66c..b6c6263e0 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -1273,6 +1273,8 @@ public:
   }
 
   size_t get_num_segments () const { return segments.size (); }
+
+  Type::Kind get_type_kind () const override { return Type::Kind::TypePath; }
 };
 
 struct QualifiedPathType
@@ -1558,6 +1560,11 @@ public:
   }
 
   location_t get_locus () const override final { return locus; }
+
+  Type::Kind get_type_kind () const override
+  {
+    return Type::Kind::QualifiedPathInType;
+  }
 };
 } // namespace AST
 } // namespace Rust
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index 9979c17ae..0e774c8da 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -186,6 +186,8 @@ public:
   {
     return type_param_bounds;
   }
+
+  Type::Kind get_type_kind () const override { return Type::Kind::ImplTrait; }
 };
 
 // An opaque value of another type that implements a set of traits
@@ -258,6 +260,8 @@ public:
   {
     return type_param_bounds;
   }
+
+  Type::Kind get_type_kind () const override { return Type::Kind::TraitObject; 
}
 };
 
 // A type with parentheses around it, used to avoid ambiguity.
@@ -326,6 +330,11 @@ public:
     rust_assert (type_in_parens != nullptr);
     return type_in_parens;
   }
+
+  Type::Kind get_type_kind () const override
+  {
+    return Type::Kind::Parenthesised;
+  }
 };
 
 // Impl trait with a single bound? Poor reference material here.
@@ -361,6 +370,11 @@ public:
   {
     return new ImplTraitTypeOneBound (trait_bound->reconstruct (), locus);
   }
+
+  Type::Kind get_type_kind () const override
+  {
+    return Type::Kind::ImplTraitTypeOneBound;
+  }
 };
 
 /* A trait object with a single trait bound. The "trait bound" is really just
@@ -412,6 +426,11 @@ public:
   }
 
   bool is_dyn () const { return has_dyn; }
+
+  Type::Kind get_type_kind () const override
+  {
+    return Type::Kind::TraitObjectTypeOneBound;
+  }
 };
 
 class TypePath; // definition moved to "rust-path.h"
@@ -478,6 +497,8 @@ protected:
   {
     return new TupleType (reconstruct_vec (elems), locus);
   }
+
+  Type::Kind get_type_kind () const override { return Type::Kind::Tuple; }
 };
 
 /* A type with no values, representing the result of computations that never
@@ -507,6 +528,8 @@ public:
   location_t get_locus () const override final { return locus; }
 
   void accept_vis (ASTVisitor &vis) override;
+
+  Type::Kind get_type_kind () const override { return Type::Kind::Never; }
 };
 
 // A type consisting of a pointer without safety or liveness guarantees
@@ -588,6 +611,8 @@ protected:
   {
     return new RawPointerType (pointer_type, type->reconstruct (), locus);
   }
+
+  Type::Kind get_type_kind () const override { return Type::Kind::RawPointer; }
 };
 
 // A type pointing to memory owned by another value
@@ -682,6 +707,8 @@ protected:
                                lifetime->get_locus ())
                                              : tl::nullopt);
   }
+
+  Type::Kind get_type_kind () const override { return Type::Kind::Reference; }
 };
 
 // A fixed-size sequence of elements of a specified type
@@ -758,6 +785,8 @@ protected:
                          size /* FIXME: This should be `reconstruct_expr()` */,
                          locus);
   }
+
+  Type::Kind get_type_kind () const override { return Type::Kind::Array; }
 };
 
 /* A dynamically-sized type representing a "view" into a sequence of elements 
of
@@ -818,6 +847,8 @@ protected:
   {
     return new SliceType (elem_type->reconstruct (), locus);
   }
+
+  Type::Kind get_type_kind () const override { return Type::Kind::Slice; }
 };
 
 /* Type used in generic arguments to explicitly request type inference 
(wildcard
@@ -851,6 +882,8 @@ public:
   location_t get_locus () const override final { return locus; }
 
   void accept_vis (ASTVisitor &vis) override;
+
+  Type::Kind get_type_kind () const override { return Type::Kind::Inferred; }
 };
 
 class QualifiedPathInType; // definition moved to "rust-path.h"
@@ -1086,6 +1119,11 @@ protected:
   {
     return new BareFunctionType (*this);
   }
+
+  Type::Kind get_type_kind () const override
+  {
+    return Type::Kind::BareFunction;
+  }
 };
 
 // Forward decl - defined in rust-macro.h
diff --git a/gcc/rust/resolve/rust-default-resolver.cc 
b/gcc/rust/resolve/rust-default-resolver.cc
index 2f8ca8736..9b4f15822 100644
--- a/gcc/rust/resolve/rust-default-resolver.cc
+++ b/gcc/rust/resolve/rust-default-resolver.cc
@@ -17,9 +17,13 @@
 // <http://www.gnu.org/licenses/>.
 
 #include "rust-default-resolver.h"
+#include "optional.h"
 #include "rust-ast-full.h"
 #include "rust-ast-visitor.h"
+#include "rust-ast.h"
+#include "rust-attribute-values.h"
 #include "rust-item.h"
+#include "rust-path.h"
 
 namespace Rust {
 namespace Resolver2_0 {
@@ -149,6 +153,16 @@ DefaultResolver::visit (AST::Trait &trait)
              trait.get_identifier () /* FIXME: Is that valid?*/);
 }
 
+static bool
+is_lang_impl (std::vector<AST::Attribute> &outer_attrs)
+{
+  for (auto &attr : outer_attrs)
+    if (attr.get_path ().as_string () == Values::Attributes::LANG)
+      return true;
+
+  return false;
+}
+
 void
 DefaultResolver::visit (AST::InherentImpl &impl)
 {
@@ -177,6 +191,17 @@ DefaultResolver::visit (AST::InherentImpl &impl)
   };
 
   ctx.scoped (Rib::Kind::Generics, impl.get_node_id (), inner_fn_3);
+
+  if (is_lang_impl (impl.get_outer_attrs ()))
+    {
+      if (impl.get_type ().get_type_kind () == AST::Type::Kind::TypePath)
+       {
+         auto type = static_cast<AST::TypePath &> (impl.get_type ());
+         auto type_name = type.as_string ();
+
+         ctx.types.insert_lang_prelude (type_name, impl.get_node_id ());
+       }
+    }
 }
 
 void
diff --git a/gcc/rust/resolve/rust-forever-stack.h 
b/gcc/rust/resolve/rust-forever-stack.h
index cca98b55c..309a0ccd6 100644
--- a/gcc/rust/resolve/rust-forever-stack.h
+++ b/gcc/rust/resolve/rust-forever-stack.h
@@ -649,6 +649,14 @@ public:
   tl::expected<NodeId, DuplicateNameError> insert_at_root (Identifier name,
                                                           NodeId id);
 
+  /**
+   * Insert an item within the lang prelude
+   *
+   * @param name The name of the definition
+   * @param id Its NodeId
+   */
+  void insert_lang_prelude (Identifier name, NodeId id);
+
   /* Access the innermost `Rib` in this map */
   Rib &peek ();
   const Rib &peek () const;
diff --git a/gcc/rust/resolve/rust-forever-stack.hxx 
b/gcc/rust/resolve/rust-forever-stack.hxx
index 1093646eb..6cecece30 100644
--- a/gcc/rust/resolve/rust-forever-stack.hxx
+++ b/gcc/rust/resolve/rust-forever-stack.hxx
@@ -199,6 +199,14 @@ ForeverStack<Namespace::Types>::insert_variant (Identifier 
name, NodeId node)
                       Rib::Definition::NonShadowable (node, true));
 }
 
+template <Namespace N>
+inline void
+ForeverStack<N>::insert_lang_prelude (Identifier name, NodeId id)
+{
+  insert_inner (lang_prelude.rib, name.as_string (),
+               Rib::Definition::NonShadowable (id, false));
+}
+
 template <Namespace N>
 Rib &
 ForeverStack<N>::peek ()
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 9a7c2f8a0..1de0ad3a8 100644
--- a/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
+++ b/gcc/rust/resolve/rust-late-name-resolver-2.0.cc
@@ -238,6 +238,16 @@ Late::visit_function_params (AST::Function &function)
 void
 Late::visit (AST::StructPatternFieldIdent &field)
 {
+  // We need to check if the Identifier resolves to a variant or empty struct
+  auto path = AST::SimplePath (field.get_identifier ());
+
+  if (auto resolved = ctx.resolve_path (path, Namespace::Types))
+    {
+      ctx.map_usage (Usage (field.get_node_id ()),
+                    Definition (resolved->get_node_id ()));
+      return;
+    }
+
   visit_identifier_as_pattern (ctx, field.get_identifier (), field.get_locus 
(),
                               field.get_node_id (), field.is_ref (),
                               field.is_mut ());
@@ -324,6 +334,7 @@ Late::visit (AST::IdentifierExpr &expr)
   // TODO: same thing as visit(PathInExpression) here?
 
   tl::optional<Rib::Definition> resolved = tl::nullopt;
+
   if (auto value = ctx.values.get (expr.get_ident ()))
     {
       resolved = value;
@@ -613,13 +624,26 @@ Late::visit (AST::StructExprStructFields &s)
 {
   visit_outer_attrs (s);
   visit_inner_attrs (s);
-  DefaultResolver::visit (s.get_struct_name ());
+
+  auto &path = s.get_struct_name ();
+
+  DefaultResolver::visit (path);
   if (s.has_struct_base ())
     visit (s.get_struct_base ());
   for (auto &field : s.get_fields ())
     visit (field);
 
-  resolve_type_path_like (ctx, block_big_self, s.get_struct_name ());
+  auto resolved = ctx.resolve_path (path, Namespace::Types);
+
+  if (!resolved)
+    {
+      rust_error_at (path.get_locus (), ErrorCode::E0433,
+                    "could not resolve path %qs", path.as_string ().c_str ());
+      return;
+    }
+
+  ctx.map_usage (Usage (path.get_node_id ()),
+                Definition (resolved->get_node_id ()));
 }
 
 // needed because Late::visit (AST::GenericArg &) is non-virtual
diff --git a/gcc/rust/resolve/rust-name-resolution-context.h 
b/gcc/rust/resolve/rust-name-resolution-context.h
index 4284ea8de..2d1ce3117 100644
--- a/gcc/rust/resolve/rust-name-resolution-context.h
+++ b/gcc/rust/resolve/rust-name-resolution-context.h
@@ -592,27 +592,25 @@ public:
     // If it fails, switch to std prelude resolution if it exists
     if (prelude && !resolved)
       {
-       std::vector<Error> ignore_errors = {};
-
        // TODO: Factor this with the above
        switch (ns)
          {
          case Namespace::Values:
            return values.resolve_path (segments, mode,
                                        insert_segment_resolution,
-                                       ignore_errors, *prelude);
+                                       collect_errors, *prelude);
          case Namespace::Types:
            return types.resolve_path (segments, mode,
-                                      insert_segment_resolution, ignore_errors,
-                                      *prelude);
+                                      insert_segment_resolution,
+                                      collect_errors, *prelude);
          case Namespace::Macros:
            return macros.resolve_path (segments, mode,
                                        insert_segment_resolution,
-                                       ignore_errors, *prelude);
+                                       collect_errors, *prelude);
          case Namespace::Labels:
            return labels.resolve_path (segments, mode,
                                        insert_segment_resolution,
-                                       ignore_errors, *prelude);
+                                       collect_errors, *prelude);
          default:
            rust_unreachable ();
          }

base-commit: 49d68147fbf03d9f602fc400d00a83f02ed753ae
-- 
2.52.0

Reply via email to