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