Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use lang items as paths #3290

Merged
merged 7 commits into from
Dec 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions gcc/rust/ast/rust-ast.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 ();

Expand Down Expand Up @@ -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 + ">";
}
Expand Down
35 changes: 29 additions & 6 deletions gcc/rust/ast/rust-item.h
Original file line number Diff line number Diff line change
Expand Up @@ -3172,7 +3172,7 @@ class TraitImpl : public Impl
{
bool has_unsafe;
bool has_exclam;
TypePath trait_path;
std::unique_ptr<Path> trait_path;

// bool has_impl_items;
std::vector<std::unique_ptr<AssociatedItem>> impl_items;
Expand All @@ -3184,7 +3184,7 @@ class TraitImpl : public Impl
bool has_impl_items () const { return !impl_items.empty (); }

// Mega-constructor
TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
TraitImpl (std::unique_ptr<Path> 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,
Expand All @@ -3197,10 +3197,26 @@ class TraitImpl : public Impl
trait_path (std::move (trait_path)), impl_items (std::move (impl_items))
{}

// Helper constructor with a 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)
: 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::unique_ptr<TypePath> (new TypePath (trait_path))),
impl_items (std::move (impl_items))
{}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could probably use a delegating constructor

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not against that, I think that's a good idea. What did you have in mind exactly?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This constructor could become a delegating constructor, with this constructor as the target constructor.

https://en.cppreference.com/w/cpp/language/constructor#Delegating_constructor

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can probably turn this into a good first PR as it's a nice cleanup but not functionally any different

// 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)
has_exclam (other.has_exclam),
trait_path (other.trait_path->clone_path ())
{
impl_items.reserve (other.impl_items.size ());
for (const auto &e : other.impl_items)
Expand All @@ -3211,7 +3227,7 @@ class TraitImpl : public Impl
TraitImpl &operator= (TraitImpl const &other)
{
Impl::operator= (other);
trait_path = other.trait_path;
trait_path = other.trait_path->clone_path ();
has_unsafe = other.has_unsafe;
has_exclam = other.has_exclam;

Expand Down Expand Up @@ -3242,10 +3258,17 @@ class TraitImpl : public Impl
}

// TODO: is this better? Or is a "vis_block" better?
TypePath &get_trait_path ()
Path &get_trait_path ()
{
// TODO: assert that trait path is not empty?
return trait_path;
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);
}

protected:
Expand Down
3 changes: 1 addition & 2 deletions gcc/rust/ast/rust-path.cc
Original file line number Diff line number Diff line change
Expand Up @@ -152,8 +152,7 @@ RegularPath::as_string () const
std::string
LangItemPath::as_string () const
{
// FIXME: Handle #[lang] paths
rust_unreachable ();
return "#[lang = \"" + LangItem::ToString (kind) + "\"]";
}

SimplePath
Expand Down
77 changes: 48 additions & 29 deletions gcc/rust/ast/rust-path.h
Original file line number Diff line number Diff line change
Expand Up @@ -589,6 +589,7 @@ class Path : public Pattern
{
LangItem,
Regular,
Type,
};

virtual Kind get_path_kind () const = 0;
Expand All @@ -598,9 +599,6 @@ class Path : public Pattern
return Pattern::Kind::Path;
}

location_t get_locus () const override final { return locus; }
NodeId get_node_id () const override final { return node_id; }

std::unique_ptr<Path> clone_path ()
{
return std::unique_ptr<Path> (clone_path_impl ());
Expand All @@ -612,22 +610,19 @@ class Path : public Pattern
}

protected:
location_t locus;
NodeId node_id;

Path (location_t locus, NodeId node_id) : locus (locus), node_id (node_id) {}

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)
: Path (locus, node_id), segments (std::move (segments))
: segments (std::move (segments)), node_id (node_id), locus (locus)
{}

std::string as_string () const override;
Expand Down Expand Up @@ -656,16 +651,25 @@ class RegularPath : public Path
return new RegularPath (std::vector<PathExprSegment> (segments), locus,
node_id);
}

NodeId get_node_id () const override { return node_id; }
location_t get_locus () const override { return locus; }
};

class LangItemPath : public Path
{
NodeId lang_item;
// TODO: Add LangItemKind or w/ever here as well
LangItem::Kind kind;
NodeId node_id;
location_t locus;

// TODO: This constructor is wrong
explicit LangItemPath (NodeId lang_item, location_t locus)
: Path (locus, lang_item), lang_item (lang_item)
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; }
Expand All @@ -674,10 +678,15 @@ class LangItemPath : public Path

Path *clone_path_impl () const override
{
return new LangItemPath (lang_item, locus);
return new LangItemPath (kind, node_id, locus);
}

std::string as_string () const override;

LangItem::Kind get_lang_item_kind () { return kind; }

NodeId get_node_id () const override { return node_id; }
location_t get_locus () const override { return locus; }
};

/* AST node representing a path-in-expression pattern (path that allows
Expand Down Expand Up @@ -735,11 +744,10 @@ class PathInExpression : public Pattern, public ExprWithoutBlock
// Returns whether path in expression is in an error state.
bool is_error () const
{
// FIXME: Cleanup
if (path->get_path_kind () == Path::Kind::Regular)
return !static_cast<RegularPath &> (*path).has_segments ();

return false;
rust_unreachable ();
}

/* Converts PathInExpression to SimplePath if possible (i.e. no generic
Expand Down Expand Up @@ -818,7 +826,7 @@ class PathInExpression : public Pattern, public ExprWithoutBlock
if (path->get_path_kind () == Path::Kind::Regular)
return static_cast<RegularPath &> (*path).get_segments ().size () == 1;

return false;
rust_unreachable ();
}

Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; }
Expand Down Expand Up @@ -1197,8 +1205,7 @@ class TypePathSegmentFunction : public TypePathSegment
}
};

// Path used inside types
class TypePath : public TypeNoBounds
class TypePath : public TypeNoBounds, public Path
{
bool has_opening_scope_resolution;
std::vector<std::unique_ptr<TypePathSegment> > segments;
Expand Down Expand Up @@ -1277,6 +1284,10 @@ class TypePath : public TypeNoBounds
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; }

void mark_for_strip () override {}
bool is_marked_for_strip () const override { return false; }

void accept_vis (ASTVisitor &vis) override;

Expand All @@ -1291,13 +1302,17 @@ class TypePath : public TypeNoBounds
}

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;
TypePath trait_path;
std::unique_ptr<Path> trait_path;
location_t locus;
NodeId node_id;

Expand All @@ -1307,13 +1322,13 @@ struct QualifiedPathType
location_t locus = UNDEF_LOCATION,
TypePath trait_path = TypePath::create_error ())
: type_to_invoke_on (std::move (invoke_on_type)),
trait_path (std::move (trait_path)), locus (locus),
node_id (Analysis::Mappings::get ().get_next_node_id ())
trait_path (std::unique_ptr<TypePath> (new TypePath (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), locus (other.locus)
: trait_path (other.trait_path->clone_path ()), locus (other.locus)
{
node_id = other.node_id;
// guard to prevent null dereference
Expand All @@ -1328,7 +1343,7 @@ struct QualifiedPathType
QualifiedPathType &operator= (QualifiedPathType const &other)
{
node_id = other.node_id;
trait_path = other.trait_path;
trait_path = other.trait_path->clone_path ();
locus = other.locus;

// guard to prevent null dereference
Expand All @@ -1345,7 +1360,11 @@ struct QualifiedPathType
QualifiedPathType &operator= (QualifiedPathType &&other) = default;

// Returns whether the qualified path type has a rebind as clause.
bool has_as_clause () const { return !trait_path.is_error (); }
bool has_as_clause () const
{
rust_assert (trait_path->get_path_kind () == Path::Kind::Type);
return !static_cast<TypePath &> (*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; }
Expand Down Expand Up @@ -1374,10 +1393,10 @@ struct QualifiedPathType
}

// TODO: is this better? Or is a "vis_pattern" better?
TypePath &get_as_type_path ()
Path &get_as_type_path ()
{
rust_assert (has_as_clause ());
return trait_path;
return *trait_path;
}

NodeId get_node_id () const { return node_id; }
Expand Down Expand Up @@ -1475,7 +1494,7 @@ class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock
if (path->get_path_kind () == Path::Kind::Regular)
return static_cast<RegularPath &> (*path).get_segments ().size () == 1;

return false;
rust_unreachable ();
}

protected:
Expand Down
6 changes: 4 additions & 2 deletions gcc/rust/expand/rust-derive-copy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@

#include "rust-derive-copy.h"
#include "rust-ast-full.h"
#include "rust-mapping-common.h"
#include "rust-path.h"

namespace Rust {
namespace AST {
Expand All @@ -44,7 +46,7 @@ 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 = TypePath (std::move (segments), loc);
auto copy = Rust::make_unique<LangItemPath> (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
Expand Down Expand Up @@ -116,7 +118,7 @@ DeriveCopy::copy_impl (
: builder.single_generic_type_path (name, generic_args_for_self);

return std::unique_ptr<Item> (
new TraitImpl (copy, /* unsafe */ false,
new TraitImpl (std::move (copy), /* unsafe */ false,
/* exclam */ false, /* trait items */ {},
std::move (impl_generics), std::move (self_type_path),
WhereClause::create_empty (), Visibility::create_private (),
Expand Down
Loading
Loading