}
/**
- * Returns a list of all the derive macros to apply, as well as the Attribute
- * they are from.
+ * Returns a list of traits to derive from within a given attribute.
*
- * ```rust
- * #[derive(Clone, Copy)] // attr1
- * struct S;
- *
- * // returns [{Clone, &attr1}, {Copy, &attr1}]
- *
- * #[derive(Clone)] // attr1
- * #[derive(Copy, PartialEq, Ord)] // attr2
- * struct S;
- *
- * // returns [{Clone, &attr1}, {Copy, &attr2}, {PartialEq, &attr2}, {Ord,
- * &attr2}]
- * ```
- *
- * @param outer_attrs The list of attributes on the item to derive
+ * @param attrs The attributes on the item to derive
*/
-static std::vector<
- std::pair<std::string, std::reference_wrapper<const AST::Attribute>>>
-get_traits_to_derive (std::vector<AST::Attribute> &outer_attrs)
-{
- std::vector<
- std::pair<std::string, std::reference_wrapper<const AST::Attribute>>>
- to_derive;
- for (auto it = outer_attrs.begin (); it != outer_attrs.end ();)
- {
- auto &attr = *it;
-
- if (is_derive (attr))
- {
- auto &input = attr.get_attr_input ();
- switch (input.get_attr_input_type ())
- {
- // isn't there a better way to do this?? like parse it or
- // something idk. some function I'm not thinking of?
- case AST::AttrInput::TOKEN_TREE: {
- auto &tokens = static_cast<AST::DelimTokenTree &> (input)
- .get_token_trees ();
-
- // erase the delimiters
- rust_assert (tokens.size () >= 3);
- tokens.erase (tokens.begin ());
- tokens.pop_back ();
-
- for (auto &token : tokens)
- {
- // skip commas, as they are part of the token stream
- if (token->as_string () == ",")
- continue;
-
- to_derive.emplace_back (token->as_string (), attr);
- }
- break;
- }
- case AST::AttrInput::LITERAL:
- case AST::AttrInput::META_ITEM:
- case AST::AttrInput::MACRO:
- gcc_unreachable ();
- break;
- }
+static std::vector<std::string>
+get_traits_to_derive (AST::Attribute &attr)
+{
+ std::vector<std::string> to_derive;
- it = outer_attrs.erase (it);
- }
- else
- {
- it++;
- }
+ auto &input = attr.get_attr_input ();
+ switch (input.get_attr_input_type ())
+ {
+ // isn't there a better way to do this?? like parse it or
+ // something idk. some function I'm not thinking of?
+ case AST::AttrInput::TOKEN_TREE: {
+ auto &tokens
+ = static_cast<AST::DelimTokenTree &> (input).get_token_trees ();
+
+ // erase the delimiters
+ rust_assert (tokens.size () >= 3);
+ tokens.erase (tokens.begin ());
+ tokens.pop_back ();
+
+ for (auto &token : tokens)
+ {
+ // skip commas, as they are part of the token stream
+ if (token->as_string () == ",")
+ continue;
+
+ to_derive.emplace_back (token->as_string ());
+ }
+ break;
+ }
+ case AST::AttrInput::LITERAL:
+ case AST::AttrInput::META_ITEM:
+ case AST::AttrInput::MACRO:
+ gcc_unreachable ();
+ break;
}
return to_derive;
auto &item = *it;
if (item->has_outer_attrs ())
{
- auto traits_to_derive
- = get_traits_to_derive (item->get_outer_attrs ());
+ auto &attrs = item->get_outer_attrs ();
- for (auto &to_derive : traits_to_derive)
+ for (auto attr_it = attrs.begin (); attr_it != attrs.end ();
+ /* erase => No increment*/)
{
- auto &name = to_derive.first;
- auto &attr = to_derive.second;
+ auto current = *attr_it;
- auto maybe_builtin = MacroBuiltin::builtins.lookup (name);
- if (MacroBuiltin::builtins.is_iter_ok (maybe_builtin))
+ if (is_derive (current))
{
- auto new_item
- = builtin_derive_item (item, attr, maybe_builtin->second);
- // this inserts the derive *before* the item - is it a
- // problem?
- it = items.insert (it, std::move (new_item));
+ attr_it = attrs.erase (attr_it);
+ // Get traits to derive in the current attribute
+ auto traits_to_derive = get_traits_to_derive (current);
+ for (auto &to_derive : traits_to_derive)
+ {
+ auto maybe_builtin
+ = MacroBuiltin::builtins.lookup (to_derive);
+ if (MacroBuiltin::builtins.is_iter_ok (maybe_builtin))
+ {
+ auto new_item
+ = builtin_derive_item (item, current,
+ maybe_builtin->second);
+ // this inserts the derive *before* the item - is it a
+ // problem?
+ it = items.insert (it, std::move (new_item));
+ }
+ else
+ {
+ auto new_items
+ = derive_item (item, to_derive, expander);
+ std::move (new_items.begin (), new_items.end (),
+ std::inserter (items, it));
+ }
+ }
}
- else
+ else /* Attribute */
{
- auto new_items = derive_item (item, name, expander);
- std::move (new_items.begin (), new_items.end (),
- std::inserter (items, it));
+ // Ignore for now
+ attr_it++;
}
}
}
{
for (auto &field : fields)
{
- visit_outer_attrs (field);
maybe_expand_type (field.get_field_type ());
}
}
{
for (auto ¶m : params)
{
- visit_outer_attrs (param);
maybe_expand_type (param.get_type ());
}
}
{
for (auto ¶m : params)
{
- visit_outer_attrs (param);
if (param.has_type_given ())
maybe_expand_type (param.get_type ());
}
void
ExpandVisitor::visit (AST::IdentifierExpr &ident_expr)
-{
- visit_outer_attrs (ident_expr);
-}
+{}
void
ExpandVisitor::visit (AST::Lifetime &)
void
ExpandVisitor::visit (AST::PathInExpression &path)
{
- visit_outer_attrs (path);
for (auto &segment : path.get_segments ())
if (segment.has_generic_args ())
expand_generic_args (segment.get_generic_args ());
void
ExpandVisitor::visit (AST::QualifiedPathInExpression &path)
{
- visit_outer_attrs (path);
expand_qualified_path_type (path.get_qualified_path_type ());
for (auto &segment : path.get_segments ())
void
ExpandVisitor::visit (AST::LiteralExpr &expr)
-{
- visit_outer_attrs (expr);
-}
+{}
void
ExpandVisitor::visit (AST::AttrInputLiteral &)
void
ExpandVisitor::visit (AST::BorrowExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_borrowed_expr ());
}
void
ExpandVisitor::visit (AST::DereferenceExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_dereferenced_expr ());
}
void
ExpandVisitor::visit (AST::ErrorPropagationExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_propagating_expr ());
}
void
ExpandVisitor::visit (AST::NegationExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_negated_expr ());
}
void
ExpandVisitor::visit (AST::ArithmeticOrLogicalExpr &expr)
{
- visit_outer_attrs (expr);
maybe_expand_expr (expr.get_left_expr ());
maybe_expand_expr (expr.get_right_expr ());
}
void
ExpandVisitor::visit (AST::ComparisonExpr &expr)
{
- visit_outer_attrs (expr);
maybe_expand_expr (expr.get_left_expr ());
maybe_expand_expr (expr.get_right_expr ());
}
void
ExpandVisitor::visit (AST::LazyBooleanExpr &expr)
{
- visit_outer_attrs (expr);
maybe_expand_expr (expr.get_left_expr ());
maybe_expand_expr (expr.get_right_expr ());
}
void
ExpandVisitor::visit (AST::TypeCastExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_casted_expr ());
visit (expr.get_type_to_cast_to ());
void
ExpandVisitor::visit (AST::AssignmentExpr &expr)
{
- visit_outer_attrs (expr);
maybe_expand_expr (expr.get_left_expr ());
maybe_expand_expr (expr.get_right_expr ());
}
void
ExpandVisitor::visit (AST::CompoundAssignmentExpr &expr)
{
- visit_outer_attrs (expr);
maybe_expand_expr (expr.get_left_expr ());
maybe_expand_expr (expr.get_right_expr ());
}
void
ExpandVisitor::visit (AST::GroupedExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_expr_in_parens ());
}
void
ExpandVisitor::visit (AST::ArrayExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_array_elems ());
}
void
ExpandVisitor::visit (AST::ArrayIndexExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_array_expr ());
visit (expr.get_index_expr ());
}
void
ExpandVisitor::visit (AST::TupleExpr &expr)
{
- visit_outer_attrs (expr);
for (auto &element : expr.get_tuple_elems ())
visit (element);
}
void
ExpandVisitor::visit (AST::TupleIndexExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_tuple_expr ());
// We can't have macro invocations for tuple indexes, right? Need a test!
void
ExpandVisitor::visit (AST::StructExprStruct &expr)
-{
- visit_outer_attrs (expr);
-}
+{}
void
ExpandVisitor::visit (AST::StructExprFieldIdentifier &)
void
ExpandVisitor::visit (AST::CallExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_function_expr ());
for (auto ¶m : expr.get_params ())
void
ExpandVisitor::visit (AST::MethodCallExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_receiver_expr ());
for (auto ¶m : expr.get_params ())
void
ExpandVisitor::visit (AST::FieldAccessExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_receiver_expr ());
}
void
ExpandVisitor::visit (AST::ClosureExprInner &expr)
{
- visit_outer_attrs (expr);
expand_closure_params (expr.get_params ());
visit (expr.get_definition_expr ());
void
ExpandVisitor::visit (AST::ClosureExprInnerTyped &expr)
{
- visit_outer_attrs (expr);
expand_closure_params (expr.get_params ());
maybe_expand_type (expr.get_return_type ());
void
ExpandVisitor::visit (AST::ContinueExpr &expr)
-{
- visit_outer_attrs (expr);
-}
+{}
void
ExpandVisitor::visit (AST::BreakExpr &expr)
{
- visit_outer_attrs (expr);
if (expr.has_break_expr ())
visit (expr.get_break_expr ());
}
void
ExpandVisitor::visit (AST::ReturnExpr &expr)
{
- visit_outer_attrs (expr);
if (expr.has_returned_expr ())
visit (expr.get_returned_expr ());
}
void
ExpandVisitor::visit (AST::UnsafeBlockExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_block_expr ());
}
void
ExpandVisitor::visit (AST::LoopExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_loop_block ());
}
void
ExpandVisitor::visit (AST::WhileLetLoopExpr &expr)
{
- visit_outer_attrs (expr);
for (auto &pattern : expr.get_patterns ())
visit (pattern);
void
ExpandVisitor::visit (AST::ForLoopExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_pattern ());
visit (expr.get_iterator_expr ());
visit (expr.get_loop_block ());
void
ExpandVisitor::visit (AST::IfExpr &expr)
{
- visit_outer_attrs (expr);
maybe_expand_expr (expr.get_condition_expr ());
visit (expr.get_if_block ());
void
ExpandVisitor::visit (AST::IfLetExpr &expr)
{
- visit_outer_attrs (expr);
maybe_expand_expr (expr.get_value_expr ());
visit (expr.get_if_block ());
void
ExpandVisitor::visit (AST::MatchExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_scrutinee_expr ());
for (auto &match_case : expr.get_match_cases ())
{
auto &arm = match_case.get_arm ();
- visit_outer_attrs (arm);
for (auto &pattern : arm.get_patterns ())
visit (pattern);
void
ExpandVisitor::visit (AST::AwaitExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_awaited_expr ());
}
void
ExpandVisitor::visit (AST::AsyncBlockExpr &expr)
{
- visit_outer_attrs (expr);
visit (expr.get_block_expr ());
}
void
ExpandVisitor::visit (AST::Method &method)
{
- visit_outer_attrs (method);
for (auto ¶m : method.get_generic_params ())
visit (param);
void
ExpandVisitor::visit (AST::Module &module)
{
- visit_outer_attrs (module);
if (module.get_kind () == AST::Module::ModuleKind::LOADED)
{
visit_inner_attrs (module);
void
ExpandVisitor::visit (AST::ExternCrate &crate)
-{
- visit_outer_attrs (crate);
-}
+{}
void
ExpandVisitor::visit (AST::UseTreeGlob &)
void
ExpandVisitor::visit (AST::UseDeclaration &use_decl)
-{
- visit_outer_attrs (use_decl);
-}
+{}
void
ExpandVisitor::visit (AST::Function &function)
{
- visit_outer_attrs (function);
visit_inner_using_attrs (function,
function.get_definition ()->get_inner_attrs ());
for (auto ¶m : function.get_generic_params ())
void
ExpandVisitor::visit (AST::TypeAlias &type_alias)
{
- visit_outer_attrs (type_alias);
visit (type_alias.get_type_aliased ());
}
void
ExpandVisitor::visit (AST::StructStruct &struct_item)
{
- visit_outer_attrs (struct_item);
for (auto &generic : struct_item.get_generic_params ())
visit (generic);
void
ExpandVisitor::visit (AST::TupleStruct &tuple_struct)
{
- visit_outer_attrs (tuple_struct);
for (auto &generic : tuple_struct.get_generic_params ())
visit (generic);
void
ExpandVisitor::visit (AST::EnumItem &item)
-{
- visit_outer_attrs (item);
-}
+{}
void
ExpandVisitor::visit (AST::EnumItemTuple &item)
void
ExpandVisitor::visit (AST::Enum &enum_item)
{
- visit_outer_attrs (enum_item);
for (auto &generic : enum_item.get_generic_params ())
visit (generic);
void
ExpandVisitor::visit (AST::Union &union_item)
{
- visit_outer_attrs (union_item);
for (auto &generic : union_item.get_generic_params ())
visit (generic);
void
ExpandVisitor::visit (AST::ConstantItem &const_item)
{
- visit_outer_attrs (const_item);
maybe_expand_type (const_item.get_type ());
visit (const_item.get_expr ());
void
ExpandVisitor::visit (AST::StaticItem &static_item)
{
- visit_outer_attrs (static_item);
maybe_expand_type (static_item.get_type ());
visit (static_item.get_expr ());
void
ExpandVisitor::visit (AST::Trait &trait)
{
- visit_outer_attrs (trait);
for (auto &generic : trait.get_generic_params ())
visit (generic);
void
ExpandVisitor::visit (AST::InherentImpl &impl)
{
- visit_outer_attrs (impl);
visit_inner_attrs (impl);
// just expand sub-stuff - can't actually strip generic params themselves
for (auto &generic : impl.get_generic_params ())
void
ExpandVisitor::visit (AST::TraitImpl &impl)
{
- visit_outer_attrs (impl);
visit_inner_attrs (impl);
// just expand sub-stuff - can't actually strip generic params themselves
for (auto ¶m : impl.get_generic_params ())
void
ExpandVisitor::visit (AST::ExternBlock &block)
{
- visit_outer_attrs (block);
visit_inner_attrs (block);
std::function<std::unique_ptr<AST::ExternalItem> (AST::SingleASTNode)>
extractor
void
ExpandVisitor::visit (AST::MacroRulesDefinition &rules_def)
-{
- visit_outer_attrs (rules_def);
-}
+{}
void
ExpandVisitor::visit (AST::MetaItemPath &)
{
for (auto ¶m : type.get_function_params ())
{
- visit_outer_attrs (param);
maybe_expand_type (param.get_type ());
}
visit (type.get_return_type ());
}
-template <typename T>
-void
-ExpandVisitor::expand_outer_attribute (T &item, AST::SimplePath &path)
-{
- // FIXME: Retrieve path from segments + local use statements instead of string
- expander.expand_attribute_proc_macro (item, path);
-}
-
-template <typename T>
-void
-ExpandVisitor::visit_outer_attrs (T &item, std::vector<AST::Attribute> &attrs)
-{
- for (auto it = attrs.begin (); it != attrs.end (); /* erase => No increment*/)
- {
- auto ¤t = *it;
-
- if (!is_builtin (current) && !is_derive (current))
- {
- it = attrs.erase (it);
- expand_outer_attribute (item, current.get_path ());
- }
- else
- {
- it++;
- }
- }
-}
-
-template <typename T>
-void
-ExpandVisitor::visit_outer_attrs (T &item)
-{
- visit_outer_attrs (item, item.get_outer_attrs ());
-}
-
template <typename T>
void
ExpandVisitor::expand_inner_attribute (T &item, AST::SimplePath &path)