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

ast: Check if the #[derive] attribute is used on a compatible item #2904

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
22 changes: 22 additions & 0 deletions gcc/rust/ast/rust-ast.h
Original file line number Diff line number Diff line change
Expand Up @@ -1139,6 +1139,26 @@ class Stmt : public Node
class Item : public Stmt
{
public:
enum class Kind
{
Static = 0,
Constant,
TypeAlias,
Function,
UseDeclaration,
ExternBlock,
ExternCrate,
Struct,
Union,
Enum,
EnumItem,
Trait,
Impl,
Module,
MacroRules,
MacroInvocation,
};

// Unique pointer custom clone function
std::unique_ptr<Item> clone_item () const
{
Expand All @@ -1151,6 +1171,8 @@ class Item : public Stmt
add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const
{}

virtual Kind get_item_kind () const = 0;

Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Item; }

// FIXME: ARTHUR: Is it okay to have removed that final? Is it *required*
Expand Down
28 changes: 28 additions & 0 deletions gcc/rust/ast/rust-item.h
Original file line number Diff line number Diff line change
Expand Up @@ -732,6 +732,8 @@ class Module : public VisItem
UNLOADED,
};

Item::Kind get_item_kind () const { return Item::Kind::Module; }

Identifier get_name () const { return module_name; }

AST::Kind get_ast_kind () const override { return AST::Kind::MODULE; }
Expand Down Expand Up @@ -898,6 +900,8 @@ class ExternCrate : public VisItem
"extern crate foo"
"extern crate std as cool_std" */
public:
Item::Kind get_item_kind () const { return Item::Kind::ExternCrate; }

std::string as_string () const override;

// Returns whether extern crate declaration has an as clause.
Expand Down Expand Up @@ -1227,6 +1231,8 @@ class UseDeclaration : public VisItem
location_t locus;

public:
Item::Kind get_item_kind () const { return Item::Kind::UseDeclaration; }

std::string as_string () const override;

UseDeclaration (std::unique_ptr<UseTree> use_tree, Visibility visibility,
Expand Down Expand Up @@ -1302,6 +1308,8 @@ class Function : public VisItem, public AssociatedItem
bool is_default;

public:
Item::Kind get_item_kind () const { return Item::Kind::Function; }

std::string as_string () const override;

// Returns whether function has generic parameters.
Expand Down Expand Up @@ -1452,6 +1460,8 @@ class TypeAlias : public VisItem, public AssociatedItem
location_t locus;

public:
Item::Kind get_item_kind () const { return Item::Kind::TypeAlias; }

std::string as_string () const override;

// Returns whether type alias has generic parameters.
Expand Down Expand Up @@ -1577,6 +1587,8 @@ class Struct : public VisItem
location_t locus;

public:
Item::Kind get_item_kind () const { return Item::Kind::Struct; }

// Returns whether struct has generic parameters.
bool has_generics () const { return !generic_params.empty (); }

Expand Down Expand Up @@ -1946,6 +1958,8 @@ class EnumItem : public VisItem
variant_name (std::move (variant_name)), locus (locus)
{}

Item::Kind get_item_kind () const { return Item::Kind::EnumItem; }

// Unique pointer custom clone function
std::unique_ptr<EnumItem> clone_enum_item () const
{
Expand Down Expand Up @@ -2115,6 +2129,8 @@ class Enum : public VisItem
location_t locus;

public:
Item::Kind get_item_kind () const { return Item::Kind::Enum; }

std::string as_string () const override;

// Returns whether "enum" has generic parameters.
Expand Down Expand Up @@ -2230,6 +2246,8 @@ class Union : public VisItem
location_t locus;

public:
Item::Kind get_item_kind () const { return Item::Kind::Union; }

std::string as_string () const override;

// Returns whether union has generic params.
Expand Down Expand Up @@ -2327,6 +2345,8 @@ class ConstantItem : public VisItem, public AssociatedItem
location_t locus;

public:
Item::Kind get_item_kind () const { return Item::Kind::Constant; }

std::string as_string () const override;

ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
Expand Down Expand Up @@ -2442,6 +2462,8 @@ class StaticItem : public VisItem
location_t locus;

public:
Item::Kind get_item_kind () const { return Item::Kind::Static; }

std::string as_string () const override;

StaticItem (Identifier name, bool is_mut, std::unique_ptr<Type> type,
Expand Down Expand Up @@ -2740,6 +2762,8 @@ class Trait : public VisItem
location_t locus;

public:
Item::Kind get_item_kind () const { return Item::Kind::Trait; }

std::string as_string () const override;

// Returns whether trait has generic parameters.
Expand Down Expand Up @@ -2912,6 +2936,8 @@ class Impl : public VisItem
location_t locus;

public:
Item::Kind get_item_kind () const { return Item::Kind::Impl; }

// Returns whether impl has generic parameters.
bool has_generics () const { return !generic_params.empty (); }

Expand Down Expand Up @@ -3718,6 +3744,8 @@ class ExternBlock : public VisItem
bool marked_for_strip = false;

public:
Item::Kind get_item_kind () const { return Item::Kind::ExternBlock; }

std::string as_string () const override;

// Returns whether extern block has inner attributes.
Expand Down
4 changes: 4 additions & 0 deletions gcc/rust/ast/rust-macro.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,8 @@ class MacroRulesDefinition : public VisItem
DeclMacro,
};

Item::Kind get_item_kind () const { return Item::Kind::MacroRules; }

private:
std::vector<Attribute> outer_attrs;
Identifier rule_name;
Expand Down Expand Up @@ -608,6 +610,8 @@ class MacroInvocation : public TypeNoBounds,
Builtin,
};

Item::Kind get_item_kind () const { return Item::Kind::MacroInvocation; }

std::string as_string () const override;

/**
Expand Down
26 changes: 23 additions & 3 deletions gcc/rust/expand/rust-derive.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,30 @@ DeriveVisitor::DeriveVisitor (location_t loc)
: loc (loc), builder (AstBuilder (loc))
{}

bool
check_if_can_derive (const Item &item, const Attribute &attr)
{
switch (item.get_item_kind ())
{
case Item::Kind::Struct:
case Item::Kind::Union:
case Item::Kind::Enum:
return true;
default:
rust_error_at (
attr.get_locus (),
"the %<#[derive]%> attribute can only be used on struct, union and "
"enum declaration");
return false;
}
}

std::unique_ptr<Item>
DeriveVisitor::derive (Item &item, const Attribute &attr,
BuiltinMacro to_derive)
derive (Item &item, const Attribute &attr, BuiltinMacro to_derive)
{
if (!check_if_can_derive (item, attr))
return nullptr;

switch (to_derive)
{
case BuiltinMacro::Clone:
Expand All @@ -45,7 +65,7 @@ DeriveVisitor::derive (Item &item, const Attribute &attr,
case BuiltinMacro::PartialOrd:
case BuiltinMacro::Hash:
default:
rust_sorry_at (attr.get_locus (), "uninmplemented builtin derive macro");
rust_sorry_at (attr.get_locus (), "unimplemented builtin derive macro");
return nullptr;
};
}
Expand Down
20 changes: 16 additions & 4 deletions gcc/rust/expand/rust-derive.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,28 @@
namespace Rust {
namespace AST {


std::unique_ptr<Item> derive (Item &item, const Attribute &derive,
BuiltinMacro to_derive);
bool check_if_can_derive (const Item &item, const Attribute &attr);

template <typename T>
bool
check_if_can_derive (const T &_item, const Attribute &attr)
{
rust_error_at (
attr.get_locus (),
"the %<#[derive]%> attribute can only be used on struct, union and "
"enum declaration");
return false;
}

/**
* The goal of this class is to accumulate and create the required items from a
* builtin `#[derive]` macro applied on a struct, enum or union.
*/
class DeriveVisitor : public AST::ASTVisitor
{
public:
static std::unique_ptr<Item> derive (Item &item, const Attribute &derive,
BuiltinMacro to_derive);

protected:
DeriveVisitor (location_t loc);

Expand Down
15 changes: 10 additions & 5 deletions gcc/rust/expand/rust-expand-visitor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ static std::unique_ptr<AST::Item>
builtin_derive_item (AST::Item &item, const AST::Attribute &derive,
BuiltinMacro to_derive)
{
return AST::DeriveVisitor::derive (item, derive, to_derive);
return AST::derive (item, derive, to_derive);
}

static std::vector<std::unique_ptr<AST::Item>>
Expand Down Expand Up @@ -191,9 +191,12 @@ ExpandVisitor::expand_inner_items (
auto new_item
= builtin_derive_item (*item, current,
maybe_builtin.value ());
// this inserts the derive *before* the item - is it a
// problem?
it = items.insert (it, std::move (new_item));
if (new_item != nullptr)
{
// this inserts the derive *before* the item - is
// it a problem?
it = items.insert (it, std::move (new_item));
}
}
else
{
Expand Down Expand Up @@ -368,7 +371,9 @@ void
ExpandVisitor::expand_tuple_fields (std::vector<AST::TupleField> &fields)
{
for (auto &field : fields)
maybe_expand_type (field.get_field_type ());
{
maybe_expand_type (field.get_field_type ());
}
}

// FIXME: This can definitely be refactored with the method above
Expand Down
5 changes: 5 additions & 0 deletions gcc/rust/expand/rust-expand-visitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,11 @@ class ExpandVisitor : public AST::DefaultASTVisitor
void expand_closure_params (std::vector<AST::ClosureParam> &params);
void expand_where_clause (AST::WhereClause &where_clause);

/**
* Checks if there is a `#[derive]` attribute and emit an error if so.
*/
void check_derive (std::vector<AST::Attribute> &attrs);

/**
* Expand a set of values, erasing them if they are marked for strip, and
* replacing them with expanded macro nodes if necessary.
Expand Down
Loading