blob: a1229adc06c5ff361db576be6c92a1d9d4c8d98f [file] [log] [blame]
// 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