| // Copyright (C) 2020-2023 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 |
| // <http://www.gnu.org/licenses/>. |
| |
| #include "rust-hir-trait-reference.h" |
| |
| namespace Rust { |
| namespace Resolver { |
| |
| std::string |
| TraitItemReference::as_string () const |
| { |
| return "(" + trait_item_type_as_string (type) + " " + identifier + " " + ")"; |
| } |
| |
| bool |
| TraitItemReference::is_error () const |
| { |
| return type == ERROR; |
| } |
| |
| bool |
| TraitItemReference::is_optional () const |
| { |
| return optional_flag; |
| }; |
| |
| std::string |
| TraitItemReference::get_identifier () const |
| { |
| return identifier; |
| } |
| |
| TraitItemReference::TraitItemType |
| TraitItemReference::get_trait_item_type () const |
| { |
| return type; |
| } |
| |
| HIR::TraitItem * |
| TraitItemReference::get_hir_trait_item () const |
| { |
| return hir_trait_item; |
| } |
| |
| Location |
| TraitItemReference::get_locus () const |
| { |
| return locus; |
| } |
| |
| const Analysis::NodeMapping |
| TraitItemReference::get_mappings () const |
| { |
| return hir_trait_item->get_mappings (); |
| } |
| |
| TyTy::BaseType * |
| TraitItemReference::get_tyty () const |
| { |
| rust_assert (hir_trait_item != nullptr); |
| |
| switch (type) |
| { |
| case CONST: |
| return get_type_from_constant ( |
| static_cast</*const*/ HIR::TraitItemConst &> (*hir_trait_item)); |
| break; |
| |
| case TYPE: |
| return get_type_from_typealias ( |
| static_cast</*const*/ HIR::TraitItemType &> (*hir_trait_item)); |
| |
| case FN: |
| return get_type_from_fn ( |
| static_cast</*const*/ HIR::TraitItemFunc &> (*hir_trait_item)); |
| break; |
| |
| default: |
| return get_error (); |
| } |
| |
| gcc_unreachable (); |
| return get_error (); |
| } |
| |
| TyTy::ErrorType * |
| TraitItemReference::get_error () const |
| { |
| return new TyTy::ErrorType (get_mappings ().get_hirid ()); |
| } |
| |
| TraitReference::TraitReference ( |
| const HIR::Trait *hir_trait_ref, std::vector<TraitItemReference> item_refs, |
| std::vector<const TraitReference *> super_traits, |
| std::vector<TyTy::SubstitutionParamMapping> substs) |
| : hir_trait_ref (hir_trait_ref), item_refs (item_refs), |
| super_traits (super_traits) |
| { |
| trait_substs.clear (); |
| trait_substs.reserve (substs.size ()); |
| for (const auto &p : substs) |
| trait_substs.push_back (p.clone ()); |
| } |
| |
| TraitReference::TraitReference (TraitReference const &other) |
| : hir_trait_ref (other.hir_trait_ref), item_refs (other.item_refs), |
| super_traits (other.super_traits) |
| { |
| trait_substs.clear (); |
| trait_substs.reserve (other.trait_substs.size ()); |
| for (const auto &p : other.trait_substs) |
| trait_substs.push_back (p.clone ()); |
| } |
| |
| TraitReference & |
| TraitReference::operator= (TraitReference const &other) |
| { |
| hir_trait_ref = other.hir_trait_ref; |
| item_refs = other.item_refs; |
| super_traits = other.super_traits; |
| |
| trait_substs.clear (); |
| trait_substs.reserve (other.trait_substs.size ()); |
| for (const auto &p : other.trait_substs) |
| trait_substs.push_back (p.clone ()); |
| |
| return *this; |
| } |
| |
| bool |
| TraitReference::is_error () const |
| { |
| return hir_trait_ref == nullptr; |
| } |
| |
| Location |
| TraitReference::get_locus () const |
| { |
| return hir_trait_ref->get_locus (); |
| } |
| |
| std::string |
| TraitReference::get_name () const |
| { |
| rust_assert (!is_error ()); |
| return hir_trait_ref->get_name (); |
| } |
| |
| std::string |
| TraitReference::as_string () const |
| { |
| if (is_error ()) |
| return "<trait-ref-error-node>"; |
| |
| std::string item_buf; |
| for (auto &item : item_refs) |
| { |
| item_buf += item.as_string () + ", "; |
| } |
| return "HIR Trait: " + get_name () + "->" |
| + hir_trait_ref->get_mappings ().as_string () + " [" + item_buf + "]"; |
| } |
| |
| const HIR::Trait * |
| TraitReference::get_hir_trait_ref () const |
| { |
| return hir_trait_ref; |
| } |
| |
| const Analysis::NodeMapping & |
| TraitReference::get_mappings () const |
| { |
| return hir_trait_ref->get_mappings (); |
| } |
| |
| DefId |
| TraitReference::get_defid () const |
| { |
| return get_mappings ().get_defid (); |
| } |
| |
| bool |
| TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item, |
| TraitItemReference **ref) |
| { |
| return lookup_trait_item (item.trait_identifier (), ref); |
| } |
| |
| bool |
| TraitReference::lookup_trait_item (const std::string &ident, |
| TraitItemReference **ref) |
| { |
| for (auto &item : item_refs) |
| { |
| if (ident.compare (item.get_identifier ()) == 0) |
| { |
| *ref = &item; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool |
| TraitReference::lookup_trait_item_by_type ( |
| const std::string &ident, TraitItemReference::TraitItemType type, |
| TraitItemReference **ref) |
| { |
| for (auto &item : item_refs) |
| { |
| if (item.get_trait_item_type () != type) |
| continue; |
| |
| if (ident.compare (item.get_identifier ()) == 0) |
| { |
| *ref = &item; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool |
| TraitReference::lookup_trait_item_by_type ( |
| const std::string &ident, TraitItemReference::TraitItemType type, |
| const TraitItemReference **ref) const |
| { |
| for (auto &item : item_refs) |
| { |
| if (item.get_trait_item_type () != type) |
| continue; |
| |
| if (ident.compare (item.get_identifier ()) == 0) |
| { |
| *ref = &item; |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| bool |
| TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item, |
| const TraitItemReference **ref) const |
| { |
| return lookup_trait_item (item.trait_identifier (), ref); |
| } |
| |
| bool |
| TraitReference::lookup_trait_item (const std::string &ident, |
| const TraitItemReference **ref) const |
| { |
| for (auto &item : item_refs) |
| { |
| if (ident.compare (item.get_identifier ()) == 0) |
| { |
| *ref = &item; |
| return true; |
| } |
| } |
| |
| // lookup super traits |
| for (const auto &super_trait : super_traits) |
| { |
| bool found = super_trait->lookup_trait_item (ident, ref); |
| if (found) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| const TraitItemReference * |
| TraitReference::lookup_trait_item (const std::string &ident, |
| TraitItemReference::TraitItemType type) const |
| { |
| for (auto &item : item_refs) |
| { |
| if (item.get_trait_item_type () != type) |
| continue; |
| |
| if (ident.compare (item.get_identifier ()) == 0) |
| return &item; |
| } |
| |
| // lookup super traits |
| for (const auto &super_trait : super_traits) |
| { |
| const TraitItemReference *res |
| = super_trait->lookup_trait_item (ident, type); |
| if (!res->is_error ()) |
| return res; |
| } |
| |
| return &TraitItemReference::error_node (); |
| } |
| |
| size_t |
| TraitReference::size () const |
| { |
| return item_refs.size (); |
| } |
| |
| const std::vector<TraitItemReference> & |
| TraitReference::get_trait_items () const |
| { |
| return item_refs; |
| } |
| |
| void |
| TraitReference::get_trait_items_and_supers ( |
| std::vector<const TraitItemReference *> &result) const |
| { |
| for (const auto &item : item_refs) |
| result.push_back (&item); |
| |
| for (const auto &super_trait : super_traits) |
| super_trait->get_trait_items_and_supers (result); |
| } |
| |
| void |
| TraitReference::on_resolved () |
| { |
| for (auto &item : item_refs) |
| { |
| item.on_resolved (); |
| } |
| } |
| |
| void |
| TraitReference::clear_associated_types () const |
| { |
| for (const auto &item : item_refs) |
| { |
| bool is_assoc_type = item.get_trait_item_type () |
| == TraitItemReference::TraitItemType::TYPE; |
| if (is_assoc_type) |
| item.associated_type_reset (false); |
| } |
| } |
| |
| void |
| TraitReference::clear_associated_type_projections () const |
| { |
| for (const auto &item : item_refs) |
| { |
| bool is_assoc_type = item.get_trait_item_type () |
| == TraitItemReference::TraitItemType::TYPE; |
| if (is_assoc_type) |
| item.associated_type_reset (true); |
| } |
| } |
| |
| bool |
| TraitReference::is_equal (const TraitReference &other) const |
| { |
| DefId this_id = get_mappings ().get_defid (); |
| DefId other_id = other.get_mappings ().get_defid (); |
| return this_id == other_id; |
| } |
| |
| const std::vector<const TraitReference *> |
| TraitReference::get_super_traits () const |
| { |
| return super_traits; |
| } |
| |
| bool |
| TraitReference::is_object_safe (bool emit_error, Location locus) const |
| { |
| // https: // doc.rust-lang.org/reference/items/traits.html#object-safety |
| std::vector<const TraitReference *> non_object_super_traits; |
| for (auto &item : super_traits) |
| { |
| if (!item->is_object_safe (false, Location ())) |
| non_object_super_traits.push_back (item); |
| } |
| |
| std::vector<const Resolver::TraitItemReference *> non_object_safe_items; |
| for (auto &item : get_trait_items ()) |
| { |
| if (!item.is_object_safe ()) |
| non_object_safe_items.push_back (&item); |
| } |
| |
| bool is_safe |
| = non_object_super_traits.empty () && non_object_safe_items.empty (); |
| if (emit_error && !is_safe) |
| { |
| RichLocation r (locus); |
| for (auto &item : non_object_super_traits) |
| r.add_range (item->get_locus ()); |
| for (auto &item : non_object_safe_items) |
| r.add_range (item->get_locus ()); |
| |
| rust_error_at (r, "trait bound is not object safe"); |
| } |
| |
| return is_safe; |
| } |
| |
| bool |
| TraitReference::trait_has_generics () const |
| { |
| return !trait_substs.empty (); |
| } |
| |
| std::vector<TyTy::SubstitutionParamMapping> |
| TraitReference::get_trait_substs () const |
| { |
| return trait_substs; |
| } |
| |
| bool |
| TraitReference::satisfies_bound (const TraitReference &reference) const |
| { |
| if (is_equal (reference)) |
| return true; |
| |
| for (const auto &super_trait : super_traits) |
| { |
| if (super_trait->satisfies_bound (reference)) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| AssociatedImplTrait::AssociatedImplTrait (TraitReference *trait, |
| HIR::ImplBlock *impl, |
| TyTy::BaseType *self, |
| Resolver::TypeCheckContext *context) |
| : trait (trait), impl (impl), self (self), context (context) |
| {} |
| |
| TraitReference * |
| AssociatedImplTrait::get_trait () |
| { |
| return trait; |
| } |
| |
| HIR::ImplBlock * |
| AssociatedImplTrait::get_impl_block () |
| { |
| return impl; |
| } |
| |
| TyTy::BaseType * |
| AssociatedImplTrait::get_self () |
| { |
| return self; |
| } |
| const TyTy::BaseType * |
| AssociatedImplTrait::get_self () const |
| { |
| return self; |
| } |
| |
| } // namespace Resolver |
| } // namespace Rust |