// Copyright (C) 2020-2025 Free Software Foundation, Inc. // This file is part of GCC. // GCC is free software; you can redistribute it and/or modify it under // the terms of the GNU General Public License as published by the Free // Software Foundation; either version 3, or (at your option) any later // version. // GCC is distributed in the hope that it will be useful, but WITHOUT ANY // WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // You should have received a copy of the GNU General Public License // along with GCC; see the file COPYING3. If not see // . #include "rust-derive-copy.h" #include "rust-ast-full.h" namespace Rust { namespace AST { DeriveCopy::DeriveCopy (location_t loc) : DeriveVisitor (loc), expanded (nullptr) {} std::unique_ptr DeriveCopy::go (Item &item) { item.accept_vis (*this); rust_assert (expanded); return std::move (expanded); } std::unique_ptr DeriveCopy::copy_impl ( std::string name, const std::vector> &type_generics) { // `$crate::core::marker::Copy` instead auto segments = std::vector> (); segments.emplace_back (builder.type_path_segment ("Copy")); auto copy = TypePath (std::move (segments), loc); // we need to build up the generics for this impl block which will be just a // clone of the types specified ones // // for example: // // #[derive(Copy)] // struct Be { ... } // // we need to generate the impl block: // // impl Clone for Be std::vector lifetime_args; std::vector generic_args; std::vector> impl_generics; for (const auto &generic : type_generics) { switch (generic->get_kind ()) { case GenericParam::Kind::Lifetime: { LifetimeParam &lifetime_param = (LifetimeParam &) *generic.get (); Lifetime l = builder.new_lifetime (lifetime_param.get_lifetime ()); lifetime_args.push_back (std::move (l)); auto impl_lifetime_param = builder.new_lifetime_param (lifetime_param); impl_generics.push_back (std::move (impl_lifetime_param)); } break; case GenericParam::Kind::Type: { TypeParam &type_param = (TypeParam &) *generic.get (); std::unique_ptr associated_type = builder.single_type_path ( type_param.get_type_representation ().as_string ()); GenericArg type_arg = GenericArg::create_type (std::move (associated_type)); generic_args.push_back (std::move (type_arg)); auto impl_type_param = builder.new_type_param (type_param); impl_generics.push_back (std::move (impl_type_param)); } break; case GenericParam::Kind::Const: { rust_unreachable (); // TODO // const ConstGenericParam *const_param // = (const ConstGenericParam *) generic.get (); // std::unique_ptr const_expr = nullptr; // GenericArg type_arg // = GenericArg::create_const (std::move (const_expr)); // generic_args.push_back (std::move (type_arg)); } break; } } GenericArgs generic_args_for_self (lifetime_args, generic_args, {} /*binding args*/, loc); std::unique_ptr self_type_path = impl_generics.empty () ? builder.single_type_path (name) : builder.single_generic_type_path (name, generic_args_for_self); return std::unique_ptr ( new TraitImpl (copy, /* unsafe */ false, /* exclam */ false, /* trait items */ {}, std::move (impl_generics), std::move (self_type_path), WhereClause::create_empty (), Visibility::create_private (), {}, {}, loc)); } void DeriveCopy::visit_struct (StructStruct &item) { expanded = copy_impl (item.get_struct_name ().as_string (), item.get_generic_params ()); } void DeriveCopy::visit_tuple (TupleStruct &item) { expanded = copy_impl (item.get_struct_name ().as_string (), item.get_generic_params ()); } void DeriveCopy::visit_enum (Enum &item) { expanded = copy_impl (item.get_identifier ().as_string (), item.get_generic_params ()); } void DeriveCopy::visit_union (Union &item) { expanded = copy_impl (item.get_identifier ().as_string (), item.get_generic_params ()); } } // namespace AST } // namespace Rust