// Copyright (C) 2020-2024 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 // . #ifndef RUST_CANONICAL_PATH #define RUST_CANONICAL_PATH #include "rust-system.h" #include "rust-mapping-common.h" namespace Rust { namespace Resolver { // https://doc.rust-lang.org/reference/paths.html#canonical-paths // // struct X - path X // impl X { fn test - path X::test } // // struct X - path X // // impl X { fn test - path X::test} // impl X { fn test - path X::test } // impl X { fn test - path X::test } // // pub trait Trait { // ::a::Trait // fn f(&self); // ::a::Trait::f // } // // impl Trait for Struct { // fn f(&self) {} // <::a::Struct as ::a::Trait>::f // } class CanonicalPath { public: CanonicalPath (const CanonicalPath &other) : segs (other.segs) {} CanonicalPath &operator= (const CanonicalPath &other) { segs = other.segs; return *this; } static CanonicalPath new_seg (NodeId id, const std::string &path) { rust_assert (!path.empty ()); return CanonicalPath ({std::pair (id, path)}, UNKNOWN_CRATENUM); } static CanonicalPath trait_impl_projection_seg (NodeId id, const CanonicalPath &trait_seg, const CanonicalPath &impl_type_seg) { return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + " as " + trait_seg.get () + ">"); } static CanonicalPath inherent_impl_seg (NodeId id, const CanonicalPath &impl_type_seg) { return CanonicalPath::new_seg (id, "<" + impl_type_seg.get () + ">"); } std::string get () const { std::string buf; for (size_t i = 0; i < segs.size (); i++) { bool have_more = (i + 1) < segs.size (); const std::string &seg = segs.at (i).second; buf += seg + (have_more ? "::" : ""); } return buf; } static CanonicalPath get_big_self (NodeId id) { return CanonicalPath::new_seg (id, "Self"); } static CanonicalPath create_empty () { return CanonicalPath ({}, UNKNOWN_CRATENUM); } bool is_empty () const { return segs.size () == 0; } CanonicalPath append (const CanonicalPath &other) const { rust_assert (!other.is_empty ()); if (is_empty ()) return CanonicalPath (other.segs, crate_num); std::vector> copy (segs); for (auto &s : other.segs) copy.push_back (s); return CanonicalPath (copy, crate_num); } // if we have the path A::B::C this will give a callback for each segment // including the prefix, example: // // path: // A::B::C // // iterate: // A // A::B // A::B::C void iterate (std::function cb) const { std::vector> buf; for (auto &seg : segs) { buf.push_back (seg); if (!cb (CanonicalPath (buf, crate_num))) return; } } // if we have the path A::B::C this will give a callback for each segment // example: // // path: // A::B::C // // iterate: // A // B // C void iterate_segs (std::function cb) const { for (auto &seg : segs) { std::vector> buf; buf.push_back ({seg.first, seg.second}); if (!cb (CanonicalPath (buf, crate_num))) return; } } size_t size () const { return segs.size (); } NodeId get_node_id () const { rust_assert (!segs.empty ()); return segs.back ().first; } const std::pair &get_seg_at (size_t index) const { rust_assert (index < size ()); return segs.at (index); } bool is_equal (const CanonicalPath &b) const { return get ().compare (b.get ()) == 0; } void set_crate_num (CrateNum n) { crate_num = n; } CrateNum get_crate_num () const { rust_assert (crate_num != UNKNOWN_CRATENUM); return crate_num; } bool operator== (const CanonicalPath &b) const { return is_equal (b); } bool operator< (const CanonicalPath &b) const { return get () < b.get (); } private: explicit CanonicalPath (std::vector> path, CrateNum crate_num) : segs (path), crate_num (crate_num) {} std::vector> segs; CrateNum crate_num; }; } // namespace Resolver } // namespace Rust #endif // RUST_CANONICAL_PATH