aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/util
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/util')
-rw-r--r--gcc/rust/util/expected.h4
-rw-r--r--gcc/rust/util/optional.h86
-rw-r--r--gcc/rust/util/rust-attribute-values.h32
-rw-r--r--gcc/rust/util/rust-attributes.cc36
-rw-r--r--gcc/rust/util/rust-attributes.h13
-rw-r--r--gcc/rust/util/rust-canonical-path.h12
-rw-r--r--gcc/rust/util/rust-common.h1
-rw-r--r--gcc/rust/util/rust-edition.cc40
-rw-r--r--gcc/rust/util/rust-edition.h (renamed from gcc/rust/util/rust-make-unique.h)26
-rw-r--r--gcc/rust/util/rust-hir-map.cc385
-rw-r--r--gcc/rust/util/rust-hir-map.h140
-rw-r--r--gcc/rust/util/rust-lang-item.cc84
-rw-r--r--gcc/rust/util/rust-lang-item.h45
-rw-r--r--gcc/rust/util/rust-operators.h8
-rw-r--r--gcc/rust/util/rust-stacked-contexts.h14
-rw-r--r--gcc/rust/util/rust-token-converter.cc3
-rw-r--r--gcc/rust/util/rust-token-converter.h2
-rw-r--r--gcc/rust/util/rust-unwrap-segment.cc61
-rw-r--r--gcc/rust/util/rust-unwrap-segment.h121
19 files changed, 855 insertions, 258 deletions
diff --git a/gcc/rust/util/expected.h b/gcc/rust/util/expected.h
index a7ddd55..6f5ef1c 100644
--- a/gcc/rust/util/expected.h
+++ b/gcc/rust/util/expected.h
@@ -212,10 +212,8 @@ template <typename E>
throw std::forward<E>(e);
#else
(void)e;
-#ifdef _MSC_VER
gcc_unreachable();
#endif
-#endif
}
#ifndef TL_TRAITS_MUTEX
@@ -2437,4 +2435,4 @@ void swap(expected<T, E> &lhs,
}
} // namespace tl
-#endif \ No newline at end of file
+#endif
diff --git a/gcc/rust/util/optional.h b/gcc/rust/util/optional.h
index 4518b42..a8ef545 100644
--- a/gcc/rust/util/optional.h
+++ b/gcc/rust/util/optional.h
@@ -1249,19 +1249,56 @@ public:
/// Returns a pointer to the stored value
constexpr const T *operator->() const {
+ // constexpr function must only contain a return statement in C++11
+#ifdef TL_OPTIONAL_CXX14
+ // undefined behavior if we don't have a value
+ rust_assert(has_value ());
+#endif
+
return std::addressof(this->m_value);
}
TL_OPTIONAL_11_CONSTEXPR T *operator->() {
+ // constexpr function must only contain a return statement in C++11
+#ifdef TL_OPTIONAL_CXX14
+ // undefined behavior if we don't have a value
+ rust_assert(has_value ());
+#endif
+
return std::addressof(this->m_value);
}
/// Returns the stored value
- TL_OPTIONAL_11_CONSTEXPR T &operator*() & { return this->m_value; }
+ TL_OPTIONAL_11_CONSTEXPR T &operator*() &
+ {
+ // constexpr function must only contain a return statement in C++11
+#ifdef TL_OPTIONAL_CXX14
+ // undefined behavior if we don't have a value
+ rust_assert(has_value ());
+#endif
- constexpr const T &operator*() const & { return this->m_value; }
+ return this->m_value;
+ }
+
+ constexpr const T &operator*() const &
+ {
+ // constexpr function must only contain a return statement in C++11
+#ifdef TL_OPTIONAL_CXX14
+ // undefined behavior if we don't have a value
+ rust_assert(has_value ());
+#endif
+
+ return this->m_value;
+ }
+
+ TL_OPTIONAL_11_CONSTEXPR T &&operator*() &&
+ {
+ // constexpr function must only contain a return statement in C++11
+#ifdef TL_OPTIONAL_CXX14
+ // undefined behavior if we don't have a value
+ rust_assert(has_value ());
+#endif
- TL_OPTIONAL_11_CONSTEXPR T &&operator*() && {
return std::move(this->m_value);
}
@@ -1988,14 +2025,49 @@ public:
void swap(optional &rhs) noexcept { std::swap(m_value, rhs.m_value); }
/// Returns a pointer to the stored value
- constexpr const T *operator->() const noexcept { return m_value; }
+ constexpr const T *operator->() const noexcept
+ {
+ // constexpr function must only contain a return statement in C++11
+#ifdef TL_OPTIONAL_CXX14
+ // undefined behavior if we don't have a value
+ rust_assert(has_value ());
+#endif
+
+ return m_value;
+ }
- TL_OPTIONAL_11_CONSTEXPR T *operator->() noexcept { return m_value; }
+ TL_OPTIONAL_11_CONSTEXPR T *operator->() noexcept
+ {
+ // constexpr function must only contain a return statement in C++11
+#ifdef TL_OPTIONAL_CXX14
+ // undefined behavior if we don't have a value
+ rust_assert(has_value ());
+#endif
+
+ return m_value;
+ }
/// Returns the stored value
- TL_OPTIONAL_11_CONSTEXPR T &operator*() noexcept { return *m_value; }
+ TL_OPTIONAL_11_CONSTEXPR T &operator*() noexcept {
+ // constexpr function must only contain a return statement in C++11
+#ifdef TL_OPTIONAL_CXX14
+ // undefined behavior if we don't have a value
+ rust_assert(has_value ());
+#endif
+
+ return *m_value;
+ }
- constexpr const T &operator*() const noexcept { return *m_value; }
+ constexpr const T &operator*() const noexcept
+ {
+ // constexpr function must only contain a return statement in C++11
+#ifdef TL_OPTIONAL_CXX14
+ // undefined behavior if we don't have a value
+ rust_assert(has_value ());
+#endif
+
+ return *m_value;
+ }
constexpr bool has_value() const noexcept { return m_value != nullptr; }
diff --git a/gcc/rust/util/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h
index a8551c0..6e0aa48 100644
--- a/gcc/rust/util/rust-attribute-values.h
+++ b/gcc/rust/util/rust-attribute-values.h
@@ -29,6 +29,7 @@ public:
static constexpr auto &COLD = "cold";
static constexpr auto &CFG = "cfg";
static constexpr auto &CFG_ATTR = "cfg_attr";
+ static constexpr auto &DERIVE_ATTR = "derive";
static constexpr auto &DEPRECATED = "deprecated";
static constexpr auto &ALLOW = "allow";
static constexpr auto &ALLOW_INTERNAL_UNSTABLE = "allow_internal_unstable";
@@ -39,12 +40,14 @@ public:
static constexpr auto &NO_MANGLE = "no_mangle";
static constexpr auto &REPR = "repr";
static constexpr auto &RUSTC_BUILTIN_MACRO = "rustc_builtin_macro";
+ static constexpr auto &RUSTC_MACRO_TRANSPARENCY = "rustc_macro_transparency";
static constexpr auto &PATH = "path";
static constexpr auto &MACRO_USE = "macro_use";
static constexpr auto &MACRO_EXPORT = "macro_export";
static constexpr auto &PROC_MACRO = "proc_macro";
static constexpr auto &PROC_MACRO_DERIVE = "proc_macro_derive";
static constexpr auto &PROC_MACRO_ATTRIBUTE = "proc_macro_attribute";
+
static constexpr auto &TARGET_FEATURE = "target_feature";
// From now on, these are reserved by the compiler and gated through
// #![feature(rustc_attrs)]
@@ -53,6 +56,35 @@ public:
= "rustc_inherit_overflow_checks";
static constexpr auto &STABLE = "stable";
static constexpr auto &UNSTABLE = "unstable";
+
+ static constexpr auto &RUSTC_PROMOTABLE = "rustc_promotable";
+ static constexpr auto &RUSTC_CONST_STABLE = "rustc_const_stable";
+ static constexpr auto &RUSTC_CONST_UNSTABLE = "rustc_const_unstable";
+
+ static constexpr auto &RUSTC_SPECIALIZATION_TRAIT
+ = "rustc_specialization_trait";
+ static constexpr auto &RUSTC_UNSAFE_SPECIALIZATION_MARKER
+ = "rustc_unsafe_specialization_marker";
+ static constexpr auto &RUSTC_RESERVATION_IMPL = "rustc_reservation_impl";
+ static constexpr auto &RUSTC_PAREN_SUGAR = "rustc_paren_sugar";
+ static constexpr auto &RUSTC_NONNULL_OPTIMIZATION_GUARANTEED
+ = "rustc_nonnull_optimization_guaranteed";
+
+ static constexpr auto &RUSTC_LAYOUT_SCALAR_VALID_RANGE_START
+ = "rustc_layout_scalar_valid_range_start";
+
+ static constexpr auto &MAY_DANGLE = "may_dangle";
+ static constexpr auto &PRELUDE_IMPORT = "prelude_import";
+ static constexpr auto &TRACK_CALLER = "track_caller";
+
+ static constexpr auto &RUSTC_DIAGNOSTIC_ITEM = "rustc_diagnostic_item";
+ static constexpr auto &RUSTC_ON_UNIMPLEMENTED = "rustc_on_unimplemented";
+
+ static constexpr auto &FUNDAMENTAL = "fundamental";
+
+ static constexpr auto &NON_EXHAUSTIVE = "non_exhaustive";
+
+ static constexpr auto &RUSTFMT = "rustfmt";
};
} // namespace Values
} // namespace Rust
diff --git a/gcc/rust/util/rust-attributes.cc b/gcc/rust/util/rust-attributes.cc
index 84d1781..2c1bd19 100644
--- a/gcc/rust/util/rust-attributes.cc
+++ b/gcc/rust/util/rust-attributes.cc
@@ -29,6 +29,15 @@
namespace Rust {
namespace Analysis {
+bool
+Attributes::is_known (const std::string &attribute_path)
+{
+ const auto &lookup
+ = BuiltinAttributeMappings::get ()->lookup_builtin (attribute_path);
+
+ return !lookup.is_error ();
+}
+
using Attrs = Values::Attributes;
// https://doc.rust-lang.org/stable/nightly-rustc/src/rustc_feature/builtin_attrs.rs.html#248
@@ -37,6 +46,7 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::COLD, CODE_GENERATION},
{Attrs::CFG, EXPANSION},
{Attrs::CFG_ATTR, EXPANSION},
+ {Attrs::DERIVE_ATTR, EXPANSION},
{Attrs::DEPRECATED, STATIC_ANALYSIS},
{Attrs::ALLOW, STATIC_ANALYSIS},
{Attrs::ALLOW_INTERNAL_UNSTABLE, STATIC_ANALYSIS},
@@ -47,6 +57,7 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::NO_MANGLE, CODE_GENERATION},
{Attrs::REPR, CODE_GENERATION},
{Attrs::RUSTC_BUILTIN_MACRO, EXPANSION},
+ {Attrs::RUSTC_MACRO_TRANSPARENCY, EXPANSION},
{Attrs::PATH, EXPANSION},
{Attrs::MACRO_USE, NAME_RESOLUTION},
{Attrs::MACRO_EXPORT, NAME_RESOLUTION},
@@ -61,7 +72,30 @@ static const BuiltinAttrDefinition __definitions[]
{Attrs::RUSTC_DEPRECATED, STATIC_ANALYSIS},
{Attrs::RUSTC_INHERIT_OVERFLOW_CHECKS, CODE_GENERATION},
{Attrs::STABLE, STATIC_ANALYSIS},
- {Attrs::UNSTABLE, STATIC_ANALYSIS}};
+ {Attrs::UNSTABLE, STATIC_ANALYSIS},
+
+ // assuming we keep these for static analysis
+ {Attrs::RUSTC_PROMOTABLE, CODE_GENERATION},
+ {Attrs::RUSTC_CONST_STABLE, STATIC_ANALYSIS},
+ {Attrs::RUSTC_CONST_UNSTABLE, STATIC_ANALYSIS},
+ {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
+ {Attrs::TRACK_CALLER, CODE_GENERATION},
+ {Attrs::RUSTC_SPECIALIZATION_TRAIT, TYPE_CHECK},
+ {Attrs::RUSTC_UNSAFE_SPECIALIZATION_MARKER, TYPE_CHECK},
+ {Attrs::RUSTC_RESERVATION_IMPL, TYPE_CHECK},
+ {Attrs::RUSTC_PAREN_SUGAR, TYPE_CHECK},
+ {Attrs::RUSTC_NONNULL_OPTIMIZATION_GUARANTEED, TYPE_CHECK},
+
+ {Attrs::RUSTC_LAYOUT_SCALAR_VALID_RANGE_START, CODE_GENERATION},
+
+ {Attrs::PRELUDE_IMPORT, NAME_RESOLUTION},
+
+ {Attrs::RUSTC_DIAGNOSTIC_ITEM, STATIC_ANALYSIS},
+ {Attrs::RUSTC_ON_UNIMPLEMENTED, STATIC_ANALYSIS},
+
+ {Attrs::FUNDAMENTAL, TYPE_CHECK},
+ {Attrs::NON_EXHAUSTIVE, TYPE_CHECK},
+ {Attrs::RUSTFMT, EXTERNAL}};
BuiltinAttributeMappings *
BuiltinAttributeMappings::get ()
diff --git a/gcc/rust/util/rust-attributes.h b/gcc/rust/util/rust-attributes.h
index f557b2d..16e4847 100644
--- a/gcc/rust/util/rust-attributes.h
+++ b/gcc/rust/util/rust-attributes.h
@@ -25,6 +25,12 @@
namespace Rust {
namespace Analysis {
+class Attributes
+{
+public:
+ static bool is_known (const std::string &attribute_path);
+};
+
enum CompilerPass
{
UNKNOWN,
@@ -34,7 +40,12 @@ enum CompilerPass
HIR_LOWERING,
TYPE_CHECK,
STATIC_ANALYSIS,
- CODE_GENERATION
+ CODE_GENERATION,
+
+ // External Rust tooling attributes, like #[rustfmt::skip]
+ EXTERNAL,
+
+ // Do we need to add something here for const fns?
};
struct BuiltinAttrDefinition
diff --git a/gcc/rust/util/rust-canonical-path.h b/gcc/rust/util/rust-canonical-path.h
index 969ac7f..33fead9 100644
--- a/gcc/rust/util/rust-canonical-path.h
+++ b/gcc/rust/util/rust-canonical-path.h
@@ -46,7 +46,9 @@ namespace Resolver {
class CanonicalPath
{
public:
- CanonicalPath (const CanonicalPath &other) : segs (other.segs) {}
+ CanonicalPath (const CanonicalPath &other)
+ : segs (other.segs), crate_num (other.crate_num)
+ {}
CanonicalPath &operator= (const CanonicalPath &other)
{
@@ -66,14 +68,18 @@ public:
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 "
+ // https://doc.rust-lang.org/reference/paths.html#canonical-paths
+ // should be "<X>"?
+ return CanonicalPath::new_seg (id, "<impl " + 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 () + ">");
+ // https://doc.rust-lang.org/reference/paths.html#canonical-paths
+ // should be "<X as Y>"?
+ return CanonicalPath::new_seg (id, "<impl " + impl_type_seg.get () + ">");
}
std::string get () const
diff --git a/gcc/rust/util/rust-common.h b/gcc/rust/util/rust-common.h
index 299ae71..c4222d2 100644
--- a/gcc/rust/util/rust-common.h
+++ b/gcc/rust/util/rust-common.h
@@ -21,7 +21,6 @@
#ifndef RUST_COMMON
#define RUST_COMMON
#include "rust-system.h"
-#include <string>
namespace Rust {
diff --git a/gcc/rust/util/rust-edition.cc b/gcc/rust/util/rust-edition.cc
new file mode 100644
index 0000000..4e44a91
--- /dev/null
+++ b/gcc/rust/util/rust-edition.cc
@@ -0,0 +1,40 @@
+// Copyright (C) 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
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-edition.h"
+#include "rust-session-manager.h"
+
+namespace Rust {
+
+Edition
+get_rust_edition ()
+{
+ switch (Session::get_instance ().options.get_edition ())
+ {
+ case CompileOptions::Edition::E2015:
+ return Edition::E2015;
+ case CompileOptions::Edition::E2018:
+ return Edition::E2018;
+ case CompileOptions::Edition::E2021:
+ return Edition::E2021;
+ default:
+ rust_unreachable ();
+ }
+}
+
+} // namespace Rust
diff --git a/gcc/rust/util/rust-make-unique.h b/gcc/rust/util/rust-edition.h
index 09c1d4b..d034ea0 100644
--- a/gcc/rust/util/rust-make-unique.h
+++ b/gcc/rust/util/rust-edition.h
@@ -1,4 +1,4 @@
-// Copyright (C) 2020-2024 Free Software Foundation, Inc.
+// Copyright (C) 2025 Free Software Foundation, Inc.
// This file is part of GCC.
@@ -16,20 +16,26 @@
// along with GCC; see the file COPYING3. If not see
// <http://www.gnu.org/licenses/>.
-#ifndef RUST_MAKE_UNIQUE_H
-#define RUST_MAKE_UNIQUE_H
+#ifndef RUST_EDITION_H
+#define RUST_EDITION_H
-#include "rust-system.h"
+/*
+ * This header exists to avoid including rust-session-manager.h
+ * when we only need information on the selected rust edition
+ */
namespace Rust {
-template <typename T, typename... Ts>
-std::unique_ptr<T>
-make_unique (Ts &&... params)
+enum class Edition
{
- return std::unique_ptr<T> (new T (std::forward<Ts> (params)...));
-}
+ E2015,
+ E2018,
+ E2021
+};
+
+Edition
+get_rust_edition ();
} // namespace Rust
-#endif // RUST_MAKE_UNIQUE_H
+#endif // !RUST_EDITION_H
diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc
index 05b26d6..0917828 100644
--- a/gcc/rust/util/rust-hir-map.cc
+++ b/gcc/rust/util/rust-hir-map.cc
@@ -110,14 +110,11 @@ Mappings::Mappings ()
Mappings::~Mappings () { delete builtinMarker; }
-Mappings *
+Mappings &
Mappings::get ()
{
- static std::unique_ptr<Mappings> instance;
- if (!instance)
- instance = std::unique_ptr<Mappings> (new Mappings ());
-
- return instance.get ();
+ static Mappings instance{};
+ return instance;
}
CrateNum
@@ -141,15 +138,24 @@ Mappings::get_current_crate () const
return currentCrateNum;
}
-bool
-Mappings::get_crate_name (CrateNum crate_num, std::string &name) const
+tl::optional<const std::string &>
+Mappings::get_crate_name (CrateNum crate_num) const
{
auto it = crate_names.find (crate_num);
if (it == crate_names.end ())
- return false;
+ return tl::nullopt;
+
+ return it->second;
+}
+
+tl::optional<CrateNum>
+Mappings::lookup_crate_num (NodeId node_id) const
+{
+ auto it = crate_node_to_crate_num.find (node_id);
+ if (it == crate_node_to_crate_num.end ())
+ return tl::nullopt;
- name.assign (it->second);
- return true;
+ return it->second;
}
void
@@ -158,51 +164,37 @@ Mappings::set_crate_name (CrateNum crate_num, const std::string &name)
crate_names[crate_num] = name;
}
-std::string
+const std::string &
Mappings::get_current_crate_name () const
{
- std::string name;
- bool ok = get_crate_name (get_current_crate (), name);
- rust_assert (ok);
- return name;
+ return get_crate_name (get_current_crate ()).value ();
}
-bool
-Mappings::lookup_crate_name (const std::string &crate_name,
- CrateNum &resolved_crate_num) const
+tl::optional<CrateNum>
+Mappings::lookup_crate_name (const std::string &crate_name) const
{
for (const auto &it : crate_names)
{
if (it.second.compare (crate_name) == 0)
- {
- resolved_crate_num = it.first;
- return true;
- }
+ return it.first;
}
- return false;
+ return tl::nullopt;
}
-bool
-Mappings::crate_num_to_nodeid (const CrateNum &crate_num, NodeId &node_id) const
+tl::optional<NodeId>
+Mappings::crate_num_to_nodeid (const CrateNum &crate_num) const
{
auto it = ast_crate_mappings.find (crate_num);
if (it == ast_crate_mappings.end ())
- return false;
+ return tl::nullopt;
- node_id = it->second->get_node_id ();
- return true;
+ return it->second->get_node_id ();
}
bool
Mappings::node_is_crate (NodeId node_id) const
{
- for (const auto &it : ast_crate_mappings)
- {
- NodeId crate_node_id = it.second->get_node_id ();
- if (crate_node_id == node_id)
- return true;
- }
- return false;
+ return lookup_crate_num (node_id).has_value ();
}
NodeId
@@ -274,6 +266,7 @@ Mappings::insert_ast_crate (std::unique_ptr<AST::Crate> &&crate,
rust_assert (it == ast_crate_mappings.end ());
// store it
+ crate_node_to_crate_num.insert ({crate->get_node_id (), crate_num});
ast_crate_mappings.insert ({crate_num, crate.release ()});
// return the reference to it
@@ -324,20 +317,20 @@ Mappings::insert_defid_mapping (DefId id, HIR::Item *item)
CrateNum crate_num = id.crateNum;
LocalDefId local_def_id = id.localDefId;
- rust_assert (lookup_defid (id) == nullptr);
- rust_assert (lookup_local_defid (crate_num, local_def_id) == nullptr);
- rust_assert (lookup_trait_item_defid (id) == nullptr);
+ rust_assert (!lookup_defid (id));
+ rust_assert (!lookup_local_defid (crate_num, local_def_id));
+ rust_assert (!lookup_trait_item_defid (id));
defIdMappings[id] = item;
insert_local_defid_mapping (crate_num, local_def_id, item);
}
-HIR::Item *
+tl::optional<HIR::Item *>
Mappings::lookup_defid (DefId id)
{
auto it = defIdMappings.find (id);
if (it == defIdMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -348,19 +341,19 @@ Mappings::insert_defid_mapping (DefId id, HIR::TraitItem *item)
CrateNum crate_num = id.crateNum;
LocalDefId local_def_id = id.localDefId;
- rust_assert (lookup_defid (id) == nullptr);
- rust_assert (lookup_local_defid (crate_num, local_def_id) == nullptr);
- rust_assert (lookup_trait_item_defid (id) == nullptr);
+ rust_assert (!lookup_defid (id));
+ rust_assert (!lookup_local_defid (crate_num, local_def_id));
+ rust_assert (!lookup_trait_item_defid (id));
defIdTraitItemMappings[id] = item;
}
-HIR::TraitItem *
+tl::optional<HIR::TraitItem *>
Mappings::lookup_trait_item_defid (DefId id)
{
auto it = defIdTraitItemMappings.find (id);
if (it == defIdTraitItemMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -369,19 +362,18 @@ void
Mappings::insert_hir_item (HIR::Item *item)
{
auto id = item->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_item (id) == nullptr);
+ rust_assert (!lookup_hir_item (id).has_value ());
hirItemMappings[id] = item;
insert_node_to_hir (item->get_mappings ().get_nodeid (), id);
}
-HIR::Item *
+tl::optional<HIR::Item *>
Mappings::lookup_hir_item (HirId id)
{
auto it = hirItemMappings.find (id);
if (it == hirItemMappings.end ())
- return nullptr;
-
+ return tl::nullopt;
return it->second;
}
@@ -410,18 +402,18 @@ void
Mappings::insert_hir_trait_item (HIR::TraitItem *item)
{
auto id = item->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_trait_item (id) == nullptr);
+ rust_assert (!lookup_hir_trait_item (id).has_value ());
hirTraitItemMappings[id] = item;
insert_node_to_hir (item->get_mappings ().get_nodeid (), id);
}
-HIR::TraitItem *
+tl::optional<HIR::TraitItem *>
Mappings::lookup_hir_trait_item (HirId id)
{
auto it = hirTraitItemMappings.find (id);
if (it == hirTraitItemMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -430,18 +422,18 @@ void
Mappings::insert_hir_extern_block (HIR::ExternBlock *block)
{
auto id = block->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_extern_block (id) == nullptr);
+ rust_assert (!lookup_hir_extern_block (id).has_value ());
hirExternBlockMappings[id] = block;
insert_node_to_hir (block->get_mappings ().get_nodeid (), id);
}
-HIR::ExternBlock *
+tl::optional<HIR::ExternBlock *>
Mappings::lookup_hir_extern_block (HirId id)
{
auto it = hirExternBlockMappings.find (id);
if (it == hirExternBlockMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -450,73 +442,70 @@ void
Mappings::insert_hir_extern_item (HIR::ExternalItem *item, HirId parent_block)
{
auto id = item->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_extern_item (id, nullptr) == nullptr);
+ rust_assert (!lookup_hir_extern_item (id));
hirExternItemMappings[id] = {item, parent_block};
insert_node_to_hir (item->get_mappings ().get_nodeid (), id);
}
-HIR::ExternalItem *
-Mappings::lookup_hir_extern_item (HirId id, HirId *parent_block)
+tl::optional<std::pair<HIR::ExternalItem *, HirId>>
+Mappings::lookup_hir_extern_item (HirId id)
{
auto it = hirExternItemMappings.find (id);
if (it == hirExternItemMappings.end ())
- return nullptr;
-
- *parent_block = it->second.second;
+ return tl::nullopt;
- return it->second.first;
+ return it->second;
}
void
Mappings::insert_hir_impl_block (HIR::ImplBlock *item)
{
auto id = item->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_impl_block (id) == nullptr);
+ rust_assert (!lookup_hir_impl_block (id));
- HirId impl_type_id = item->get_type ()->get_mappings ().get_hirid ();
+ HirId impl_type_id = item->get_type ().get_mappings ().get_hirid ();
hirImplBlockMappings[id] = item;
hirImplBlockTypeMappings[impl_type_id] = item;
insert_node_to_hir (item->get_mappings ().get_nodeid (), id);
}
-HIR::ImplBlock *
+tl::optional<HIR::ImplBlock *>
Mappings::lookup_hir_impl_block (HirId id)
{
auto it = hirImplBlockMappings.find (id);
if (it == hirImplBlockMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
-bool
-Mappings::lookup_impl_block_type (HirId id, HIR::ImplBlock **impl_block)
+tl::optional<HIR::ImplBlock *>
+Mappings::lookup_impl_block_type (HirId id)
{
auto it = hirImplBlockTypeMappings.find (id);
if (it == hirImplBlockTypeMappings.end ())
- return false;
+ return tl::nullopt;
- *impl_block = it->second;
- return true;
+ return it->second;
}
void
Mappings::insert_module (HIR::Module *module)
{
auto id = module->get_mappings ().get_hirid ();
- rust_assert (lookup_module (id) == nullptr);
+ rust_assert (!lookup_module (id));
hirModuleMappings[id] = module;
insert_node_to_hir (module->get_mappings ().get_nodeid (), id);
}
-HIR::Module *
+tl::optional<HIR::Module *>
Mappings::lookup_module (HirId id)
{
auto it = hirModuleMappings.find (id);
if (it == hirModuleMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -525,25 +514,21 @@ void
Mappings::insert_hir_implitem (HirId parent_impl_id, HIR::ImplItem *item)
{
auto id = item->get_impl_mappings ().get_hirid ();
- rust_assert (lookup_hir_implitem (id, nullptr) == nullptr);
+ rust_assert (!lookup_hir_implitem (id));
hirImplItemMappings[id]
= std::pair<HirId, HIR::ImplItem *> (parent_impl_id, item);
insert_node_to_hir (item->get_impl_mappings ().get_nodeid (), id);
}
-HIR::ImplItem *
-Mappings::lookup_hir_implitem (HirId id, HirId *parent_impl_id)
+tl::optional<std::pair<HIR::ImplItem *, HirId>>
+Mappings::lookup_hir_implitem (HirId id)
{
auto it = hirImplItemMappings.find (id);
if (it == hirImplItemMappings.end ())
- return nullptr;
-
- std::pair<HirId, HIR::ImplItem *> &ref = it->second;
- if (parent_impl_id != nullptr)
- *parent_impl_id = ref.first;
+ return tl::nullopt;
- return ref.second;
+ return std::make_pair (it->second.second, it->second.first);
}
void
@@ -556,12 +541,12 @@ Mappings::insert_hir_expr (HIR::Expr *expr)
insert_location (id, expr->get_locus ());
}
-HIR::Expr *
+tl::optional<HIR::Expr *>
Mappings::lookup_hir_expr (HirId id)
{
auto it = hirExprMappings.find (id);
if (it == hirExprMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -570,19 +555,19 @@ void
Mappings::insert_hir_path_expr_seg (HIR::PathExprSegment *expr)
{
auto id = expr->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_path_expr_seg (id) == nullptr);
+ rust_assert (!lookup_hir_path_expr_seg (id));
hirPathSegMappings[id] = expr;
insert_node_to_hir (expr->get_mappings ().get_nodeid (), id);
insert_location (id, expr->get_locus ());
}
-HIR::PathExprSegment *
+tl::optional<HIR::PathExprSegment *>
Mappings::lookup_hir_path_expr_seg (HirId id)
{
auto it = hirPathSegMappings.find (id);
if (it == hirPathSegMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -591,19 +576,19 @@ void
Mappings::insert_hir_generic_param (HIR::GenericParam *param)
{
auto id = param->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_generic_param (id) == nullptr);
+ rust_assert (!lookup_hir_generic_param (id));
hirGenericParamMappings[id] = param;
insert_node_to_hir (param->get_mappings ().get_nodeid (), id);
insert_location (id, param->get_locus ());
}
-HIR::GenericParam *
+tl::optional<HIR::GenericParam *>
Mappings::lookup_hir_generic_param (HirId id)
{
auto it = hirGenericParamMappings.find (id);
if (it == hirGenericParamMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -612,18 +597,18 @@ void
Mappings::insert_hir_type (HIR::Type *type)
{
auto id = type->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_type (id) == nullptr);
+ rust_assert (!lookup_hir_type (id));
hirTypeMappings[id] = type;
insert_node_to_hir (type->get_mappings ().get_nodeid (), id);
}
-HIR::Type *
+tl::optional<HIR::Type *>
Mappings::lookup_hir_type (HirId id)
{
auto it = hirTypeMappings.find (id);
if (it == hirTypeMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -632,18 +617,18 @@ void
Mappings::insert_hir_stmt (HIR::Stmt *stmt)
{
auto id = stmt->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_stmt (id) == nullptr);
+ rust_assert (!lookup_hir_stmt (id));
hirStmtMappings[id] = stmt;
insert_node_to_hir (stmt->get_mappings ().get_nodeid (), id);
}
-HIR::Stmt *
+tl::optional<HIR::Stmt *>
Mappings::lookup_hir_stmt (HirId id)
{
auto it = hirStmtMappings.find (id);
if (it == hirStmtMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -652,18 +637,18 @@ void
Mappings::insert_hir_param (HIR::FunctionParam *param)
{
auto id = param->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_param (id) == nullptr);
+ rust_assert (!lookup_hir_param (id));
hirParamMappings[id] = param;
insert_node_to_hir (param->get_mappings ().get_nodeid (), id);
}
-HIR::FunctionParam *
+tl::optional<HIR::FunctionParam *>
Mappings::lookup_hir_param (HirId id)
{
auto it = hirParamMappings.find (id);
if (it == hirParamMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -672,18 +657,18 @@ void
Mappings::insert_hir_self_param (HIR::SelfParam *param)
{
auto id = param->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_self_param (id) == nullptr);
+ rust_assert (!lookup_hir_self_param (id));
hirSelfParamMappings[id] = param;
insert_node_to_hir (param->get_mappings ().get_nodeid (), id);
}
-HIR::SelfParam *
+tl::optional<HIR::SelfParam *>
Mappings::lookup_hir_self_param (HirId id)
{
auto it = hirSelfParamMappings.find (id);
if (it == hirSelfParamMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -692,18 +677,18 @@ void
Mappings::insert_hir_struct_field (HIR::StructExprField *field)
{
auto id = field->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_struct_field (id) == nullptr);
+ rust_assert (!lookup_hir_struct_field (id));
hirStructFieldMappings[id] = field;
insert_node_to_hir (field->get_mappings ().get_nodeid (), id);
}
-HIR::StructExprField *
+tl::optional<HIR::StructExprField *>
Mappings::lookup_hir_struct_field (HirId id)
{
auto it = hirStructFieldMappings.find (id);
if (it == hirStructFieldMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -712,18 +697,18 @@ void
Mappings::insert_hir_pattern (HIR::Pattern *pattern)
{
auto id = pattern->get_mappings ().get_hirid ();
- rust_assert (lookup_hir_pattern (id) == nullptr);
+ rust_assert (!lookup_hir_pattern (id));
hirPatternMappings[id] = pattern;
insert_node_to_hir (pattern->get_mappings ().get_nodeid (), id);
}
-HIR::Pattern *
+tl::optional<HIR::Pattern *>
Mappings::lookup_hir_pattern (HirId id)
{
auto it = hirPatternMappings.find (id);
if (it == hirPatternMappings.end ())
- return nullptr;
+ return tl::nullopt;
return it->second;
}
@@ -732,20 +717,20 @@ void
Mappings::insert_local_defid_mapping (CrateNum crateNum, LocalDefId id,
HIR::Item *item)
{
- rust_assert (lookup_local_defid (crateNum, id) == nullptr);
+ rust_assert (!lookup_local_defid (crateNum, id));
localDefIdMappings[crateNum][id] = item;
}
-HIR::Item *
+tl::optional<HIR::Item *>
Mappings::lookup_local_defid (CrateNum crateNum, LocalDefId id)
{
auto it = localDefIdMappings.find (crateNum);
if (it == localDefIdMappings.end ())
- return nullptr;
+ return tl::nullopt;
auto iy = it->second.find (id);
if (iy == it->second.end ())
- return nullptr;
+ return tl::nullopt;
return iy->second;
}
@@ -772,26 +757,24 @@ Mappings::insert_node_to_hir (NodeId id, HirId ref)
hirIdToNodeMappings[ref] = id;
}
-bool
-Mappings::lookup_node_to_hir (NodeId id, HirId *ref)
+tl::optional<HirId>
+Mappings::lookup_node_to_hir (NodeId id)
{
auto it = nodeIdToHirMappings.find (id);
if (it == nodeIdToHirMappings.end ())
- return false;
+ return tl::nullopt;
- *ref = it->second;
- return true;
+ return {it->second};
}
-bool
-Mappings::lookup_hir_to_node (HirId id, NodeId *ref)
+tl::optional<NodeId>
+Mappings::lookup_hir_to_node (HirId id)
{
auto it = hirIdToNodeMappings.find (id);
if (it == hirIdToNodeMappings.end ())
- return false;
+ return tl::nullopt;
- *ref = it->second;
- return true;
+ return {it->second};
}
void
@@ -810,17 +793,15 @@ Mappings::lookup_location (HirId id)
return it->second;
}
-bool
-Mappings::resolve_nodeid_to_stmt (NodeId id, HIR::Stmt **stmt)
+tl::optional<HIR::Stmt *>
+Mappings::resolve_nodeid_to_stmt (NodeId id)
{
auto it = nodeIdToHirMappings.find (id);
if (it == nodeIdToHirMappings.end ())
- return false;
+ return tl::nullopt;
HirId resolved = it->second;
- auto resolved_stmt = lookup_hir_stmt (resolved);
- *stmt = resolved_stmt;
- return resolved_stmt != nullptr;
+ return lookup_hir_stmt (resolved);
}
void
@@ -898,18 +879,27 @@ Mappings::insert_macro_def (AST::MacroRulesDefinition *macro)
auto it = macroMappings.find (macro->get_node_id ());
rust_assert (it == macroMappings.end ());
- macroMappings[macro->get_node_id ()] = macro;
+ macroMappings[macro->get_node_id ()] = {macro, currentCrateNum};
}
-bool
-Mappings::lookup_macro_def (NodeId id, AST::MacroRulesDefinition **def)
+tl::optional<AST::MacroRulesDefinition *>
+Mappings::lookup_macro_def (NodeId id)
{
auto it = macroMappings.find (id);
if (it == macroMappings.end ())
- return false;
+ return tl::nullopt;
+
+ return it->second.first;
+}
+
+tl::optional<CrateNum>
+Mappings::lookup_macro_def_crate (NodeId id)
+{
+ auto it = macroMappings.find (id);
+ if (it == macroMappings.end ())
+ return tl::nullopt;
- *def = it->second;
- return true;
+ return it->second.second;
}
void
@@ -922,16 +912,14 @@ Mappings::insert_macro_invocation (AST::MacroInvocation &invoc,
macroInvocations[invoc.get_macro_node_id ()] = def;
}
-bool
-Mappings::lookup_macro_invocation (AST::MacroInvocation &invoc,
- AST::MacroRulesDefinition **def)
+tl::optional<AST::MacroRulesDefinition *>
+Mappings::lookup_macro_invocation (AST::MacroInvocation &invoc)
{
auto it = macroInvocations.find (invoc.get_macro_node_id ());
if (it == macroInvocations.end ())
- return false;
+ return tl::nullopt;
- *def = it->second;
- return true;
+ return it->second;
}
void
@@ -1129,15 +1117,14 @@ Mappings::insert_visibility (NodeId id, Privacy::ModuleVisibility visibility)
visibility_map.insert ({id, visibility});
}
-bool
-Mappings::lookup_visibility (NodeId id, Privacy::ModuleVisibility &def)
+tl::optional<Privacy::ModuleVisibility &>
+Mappings::lookup_visibility (NodeId id)
{
auto it = visibility_map.find (id);
if (it == visibility_map.end ())
- return false;
+ return tl::nullopt;
- def = it->second;
- return true;
+ return it->second;
}
void
@@ -1253,15 +1240,14 @@ Mappings::insert_ast_item (AST::Item *item)
ast_item_mappings[item->get_node_id ()] = item;
}
-bool
-Mappings::lookup_ast_item (NodeId id, AST::Item **result)
+tl::optional<AST::Item *>
+Mappings::lookup_ast_item (NodeId id)
{
auto it = ast_item_mappings.find (id);
if (it == ast_item_mappings.end ())
- return false;
+ return tl::nullopt;
- *result = it->second;
- return true;
+ return it->second;
}
HIR::ImplBlock *
@@ -1270,24 +1256,105 @@ Mappings::lookup_builtin_marker ()
return builtinMarker;
}
+// FIXME: Before merging: Should we remove the `locus` parameter here? since
+// lang items are looked up mostly for code generation, it doesn't make sense to
+// error out on the locus of the node trying to access an inexistant lang item
DefId
Mappings::get_lang_item (LangItem::Kind item_type, location_t locus)
{
- DefId item = UNKNOWN_DEFID;
- bool ok = lookup_lang_item (item_type, &item);
- if (!ok)
- rust_fatal_error (locus, "failed to find lang item %s",
- LangItem::ToString (item_type).c_str ());
+ if (auto item = lookup_lang_item (item_type))
+ return *item;
- return item;
+ rust_fatal_error (locus, "failed to find lang item %s",
+ LangItem::ToString (item_type).c_str ());
}
-HIR::TraitItem *
+tl::optional<HIR::TraitItem *>
Mappings::lookup_trait_item_lang_item (LangItem::Kind item, location_t locus)
{
DefId trait_item_id = get_lang_item (item, locus);
return lookup_trait_item_defid (trait_item_id);
}
+void
+Mappings::insert_lang_item (LangItem::Kind item_type, DefId id)
+{
+ auto it = lang_item_mappings.find (item_type);
+ rust_assert (it == lang_item_mappings.end ());
+
+ lang_item_mappings[item_type] = id;
+}
+
+tl::optional<DefId &>
+Mappings::lookup_lang_item (LangItem::Kind item_type)
+{
+ auto it = lang_item_mappings.find (item_type);
+ if (it == lang_item_mappings.end ())
+ return tl::nullopt;
+
+ return it->second;
+}
+
+void
+Mappings::insert_lang_item_node (LangItem::Kind item_type, NodeId node_id)
+{
+ auto it = lang_item_nodes.find (item_type);
+ rust_assert (it == lang_item_nodes.end ());
+
+ lang_item_nodes.insert ({item_type, node_id});
+}
+
+tl::optional<NodeId &>
+Mappings::lookup_lang_item_node (LangItem::Kind item_type)
+{
+ auto it = lang_item_nodes.find (item_type);
+ if (it == lang_item_nodes.end ())
+ return tl::nullopt;
+
+ return it->second;
+}
+
+NodeId
+Mappings::get_lang_item_node (LangItem::Kind item_type)
+{
+ if (auto lookup = lookup_lang_item_node (item_type))
+ return *lookup;
+
+ rust_fatal_error (UNKNOWN_LOCATION, "undeclared lang item: %qs",
+ LangItem::PrettyString (item_type).c_str ());
+}
+
+void
+Mappings::insert_auto_trait (HIR::Trait *trait)
+{
+ auto_traits.emplace_back (trait);
+}
+
+std::vector<HIR::Trait *> &
+Mappings::get_auto_traits ()
+{
+ return auto_traits;
+}
+
+void
+Mappings::add_capture (NodeId closure, NodeId definition)
+{
+ auto cap = captures.find (closure);
+ if (cap == captures.end ())
+ captures[closure] = {definition};
+ else
+ cap->second.push_back (definition);
+}
+
+tl::optional<std::vector<NodeId>>
+Mappings::lookup_captures (NodeId closure)
+{
+ auto cap = captures.find (closure);
+ if (cap == captures.end ())
+ return tl::nullopt;
+ else
+ return cap->second;
+}
+
} // namespace Analysis
} // namespace Rust
diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h
index 92af067..86191f6 100644
--- a/gcc/rust/util/rust-hir-map.h
+++ b/gcc/rust/util/rust-hir-map.h
@@ -74,18 +74,20 @@ private:
class Mappings
{
public:
- static Mappings *get ();
+ static Mappings &get ();
~Mappings ();
CrateNum get_next_crate_num (const std::string &name);
void set_current_crate (CrateNum crateNum);
CrateNum get_current_crate () const;
- bool get_crate_name (CrateNum crate_num, std::string &name) const;
+ tl::optional<const std::string &> get_crate_name (CrateNum crate_num) const;
+
+ tl::optional<CrateNum> lookup_crate_num (NodeId node_id) const;
void set_crate_name (CrateNum crate_num, const std::string &name);
- std::string get_current_crate_name () const;
- bool lookup_crate_name (const std::string &crate_name,
- CrateNum &resolved_crate_num) const;
- bool crate_num_to_nodeid (const CrateNum &crate_num, NodeId &node_id) const;
+ const std::string &get_current_crate_name () const;
+ tl::optional<CrateNum>
+ lookup_crate_name (const std::string &crate_name) const;
+ tl::optional<NodeId> crate_num_to_nodeid (const CrateNum &crate_num) const;
bool node_is_crate (NodeId node_id) const;
NodeId get_next_node_id ();
@@ -106,77 +108,83 @@ public:
bool is_local_hirid_crate (HirId crateNum);
void insert_defid_mapping (DefId id, HIR::Item *item);
- HIR::Item *lookup_defid (DefId id);
+ tl::optional<HIR::Item *> lookup_defid (DefId id);
void insert_defid_mapping (DefId id, HIR::TraitItem *item);
- HIR::TraitItem *lookup_trait_item_defid (DefId id);
+ tl::optional<HIR::TraitItem *> lookup_trait_item_defid (DefId id);
void insert_local_defid_mapping (CrateNum crateNum, LocalDefId id,
HIR::Item *item);
- HIR::Item *lookup_local_defid (CrateNum crateNum, LocalDefId id);
+ tl::optional<HIR::Item *> lookup_local_defid (CrateNum crateNum,
+ LocalDefId id);
void insert_hir_item (HIR::Item *item);
- HIR::Item *lookup_hir_item (HirId id);
+ tl::optional<HIR::Item *> lookup_hir_item (HirId id);
void insert_hir_enumitem (HIR::Enum *parent, HIR::EnumItem *item);
std::pair<HIR::Enum *, HIR::EnumItem *> lookup_hir_enumitem (HirId id);
void insert_hir_trait_item (HIR::TraitItem *item);
- HIR::TraitItem *lookup_hir_trait_item (HirId id);
+ tl::optional<HIR::TraitItem *> lookup_hir_trait_item (HirId id);
void insert_hir_extern_block (HIR::ExternBlock *block);
- HIR::ExternBlock *lookup_hir_extern_block (HirId id);
+ tl::optional<HIR::ExternBlock *> lookup_hir_extern_block (HirId id);
void insert_hir_extern_item (HIR::ExternalItem *item, HirId parent_block);
- HIR::ExternalItem *lookup_hir_extern_item (HirId id, HirId *parent_block);
+
+ // std::pair<hir_extern_item, parent hirid>
+ tl::optional<std::pair<HIR::ExternalItem *, HirId>>
+ lookup_hir_extern_item (HirId id);
void insert_hir_impl_block (HIR::ImplBlock *item);
- HIR::ImplBlock *lookup_hir_impl_block (HirId id);
- bool lookup_impl_block_type (HirId id, HIR::ImplBlock **impl_block);
+ tl::optional<HIR::ImplBlock *> lookup_hir_impl_block (HirId id);
+ tl::optional<HIR::ImplBlock *> lookup_impl_block_type (HirId id);
void insert_module (HIR::Module *module);
- HIR::Module *lookup_module (HirId id);
+ tl::optional<HIR::Module *> lookup_module (HirId id);
void insert_hir_implitem (HirId parent_impl_id, HIR::ImplItem *item);
- HIR::ImplItem *lookup_hir_implitem (HirId id, HirId *parent_impl_id);
+ // Optional<ImpItem, ParentImpl Hir id>
+ tl::optional<std::pair<HIR::ImplItem *, HirId>>
+ lookup_hir_implitem (HirId id);
void insert_hir_expr (HIR::Expr *expr);
- HIR::Expr *lookup_hir_expr (HirId id);
+ tl::optional<HIR::Expr *> lookup_hir_expr (HirId id);
void insert_hir_path_expr_seg (HIR::PathExprSegment *expr);
- HIR::PathExprSegment *lookup_hir_path_expr_seg (HirId id);
+ tl::optional<HIR::PathExprSegment *> lookup_hir_path_expr_seg (HirId id);
void insert_hir_generic_param (HIR::GenericParam *expr);
- HIR::GenericParam *lookup_hir_generic_param (HirId id);
+ tl::optional<HIR::GenericParam *> lookup_hir_generic_param (HirId id);
void insert_hir_type (HIR::Type *type);
- HIR::Type *lookup_hir_type (HirId id);
+ tl::optional<HIR::Type *> lookup_hir_type (HirId id);
void insert_hir_stmt (HIR::Stmt *stmt);
- HIR::Stmt *lookup_hir_stmt (HirId id);
+ tl::optional<HIR::Stmt *> lookup_hir_stmt (HirId id);
void insert_hir_param (HIR::FunctionParam *type);
- HIR::FunctionParam *lookup_hir_param (HirId id);
+ tl::optional<HIR::FunctionParam *> lookup_hir_param (HirId id);
void insert_hir_self_param (HIR::SelfParam *type);
- HIR::SelfParam *lookup_hir_self_param (HirId id);
+ tl::optional<HIR::SelfParam *> lookup_hir_self_param (HirId id);
void insert_hir_struct_field (HIR::StructExprField *type);
- HIR::StructExprField *lookup_hir_struct_field (HirId id);
+ tl::optional<HIR::StructExprField *> lookup_hir_struct_field (HirId id);
void insert_hir_pattern (HIR::Pattern *pattern);
- HIR::Pattern *lookup_hir_pattern (HirId id);
+ tl::optional<HIR::Pattern *> lookup_hir_pattern (HirId id);
void walk_local_defids_for_crate (CrateNum crateNum,
std::function<bool (HIR::Item *)> cb);
void insert_node_to_hir (NodeId id, HirId ref);
- bool lookup_node_to_hir (NodeId id, HirId *ref);
- bool lookup_hir_to_node (HirId id, NodeId *ref);
+ tl::optional<HirId> lookup_node_to_hir (NodeId id);
+ tl::optional<NodeId> lookup_hir_to_node (HirId id);
void insert_location (HirId id, location_t locus);
location_t lookup_location (HirId id);
- bool resolve_nodeid_to_stmt (NodeId id, HIR::Stmt **stmt);
+ tl::optional<HIR::Stmt *> resolve_nodeid_to_stmt (NodeId id);
std::set<HirId> &get_hirids_within_crate (CrateNum crate)
{
@@ -205,11 +213,7 @@ public:
void iterate_trait_items (
std::function<bool (HIR::TraitItem *item, HIR::Trait *)> cb);
- bool is_impl_item (HirId id)
- {
- HirId parent_impl_block_id = UNKNOWN_HIRID;
- return lookup_hir_implitem (id, &parent_impl_block_id) != nullptr;
- }
+ bool is_impl_item (HirId id) { return lookup_hir_implitem (id).has_value (); }
void insert_trait_item_mapping (HirId trait_item_id, HIR::Trait *trait)
{
@@ -227,8 +231,7 @@ public:
void insert_canonical_path (NodeId id, const Resolver::CanonicalPath path)
{
- const Resolver::CanonicalPath *p = nullptr;
- if (lookup_canonical_path (id, &p))
+ if (auto p = lookup_canonical_path (id))
{
// if we have already stored a canonical path this is ok so long as
// this new path is equal or is smaller that the existing one but in
@@ -245,45 +248,35 @@ public:
paths.emplace (id, std::move (path));
}
- bool lookup_canonical_path (NodeId id, const Resolver::CanonicalPath **path)
+ tl::optional<const Resolver::CanonicalPath &>
+ lookup_canonical_path (NodeId id)
{
auto it = paths.find (id);
if (it == paths.end ())
- return false;
+ return tl::nullopt;
- *path = &it->second;
- return true;
+ return it->second;
}
- void insert_lang_item (LangItem::Kind item_type, DefId id)
- {
- auto it = lang_item_mappings.find (item_type);
- rust_assert (it == lang_item_mappings.end ());
-
- lang_item_mappings[item_type] = id;
- }
+ void insert_lang_item (LangItem::Kind item_type, DefId id);
+ tl::optional<DefId &> lookup_lang_item (LangItem::Kind item_type);
- bool lookup_lang_item (LangItem::Kind item_type, DefId *id)
- {
- auto it = lang_item_mappings.find (item_type);
- if (it == lang_item_mappings.end ())
- return false;
-
- *id = it->second;
- return true;
- }
+ void insert_lang_item_node (LangItem::Kind item_type, NodeId node_id);
+ tl::optional<NodeId &> lookup_lang_item_node (LangItem::Kind item_type);
+ NodeId get_lang_item_node (LangItem::Kind item_type);
// This will fatal_error when this lang item does not exist
DefId get_lang_item (LangItem::Kind item_type, location_t locus);
void insert_macro_def (AST::MacroRulesDefinition *macro);
- bool lookup_macro_def (NodeId id, AST::MacroRulesDefinition **def);
+ tl::optional<AST::MacroRulesDefinition *> lookup_macro_def (NodeId id);
+ tl::optional<CrateNum> lookup_macro_def_crate (NodeId id);
void insert_macro_invocation (AST::MacroInvocation &invoc,
AST::MacroRulesDefinition *def);
- bool lookup_macro_invocation (AST::MacroInvocation &invoc,
- AST::MacroRulesDefinition **def);
+ tl::optional<AST::MacroRulesDefinition *>
+ lookup_macro_invocation (AST::MacroInvocation &invoc);
void insert_exported_macro (AST::MacroRulesDefinition &def);
std::vector<NodeId> &get_exported_macros ();
@@ -326,7 +319,7 @@ public:
AttributeProcMacro def);
void insert_visibility (NodeId id, Privacy::ModuleVisibility visibility);
- bool lookup_visibility (NodeId id, Privacy::ModuleVisibility &def);
+ tl::optional<Privacy::ModuleVisibility &> lookup_visibility (NodeId id);
void insert_ast_module (AST::Module *);
tl::optional<AST::Module *> lookup_ast_module (NodeId id);
@@ -345,12 +338,17 @@ public:
bool node_is_module (NodeId query);
void insert_ast_item (AST::Item *item);
- bool lookup_ast_item (NodeId id, AST::Item **result);
+ tl::optional<AST::Item *> lookup_ast_item (NodeId id);
HIR::ImplBlock *lookup_builtin_marker ();
- HIR::TraitItem *lookup_trait_item_lang_item (LangItem::Kind item,
- location_t locus);
+ tl::optional<HIR::TraitItem *>
+ lookup_trait_item_lang_item (LangItem::Kind item, location_t locus);
+
+ void insert_auto_trait (HIR::Trait *trait);
+ std::vector<HIR::Trait *> &get_auto_traits ();
+ void add_capture (NodeId closure, NodeId definition);
+ tl::optional<std::vector<NodeId>> lookup_captures (NodeId closure);
private:
Mappings ();
@@ -389,8 +387,16 @@ private:
std::map<HirId, HIR::GenericParam *> hirGenericParamMappings;
std::map<HirId, HIR::Trait *> hirTraitItemsToTraitMappings;
std::map<HirId, HIR::Pattern *> hirPatternMappings;
+
+ // FIXME: Add documentation
+ std::vector<HIR::Trait *> auto_traits;
+
+ // We need to have two maps here, as lang-items need to be used for both AST
+ // passes and HIR passes. Thus those two maps are created at different times.
std::map<LangItem::Kind, DefId> lang_item_mappings;
- std::map<NodeId, const Resolver::CanonicalPath> paths;
+ std::map<LangItem::Kind, NodeId> lang_item_nodes;
+
+ std::map<NodeId, Resolver::CanonicalPath> paths;
std::map<NodeId, location_t> locations;
std::map<NodeId, HirId> nodeIdToHirMappings;
std::map<HirId, NodeId> hirIdToNodeMappings;
@@ -399,7 +405,8 @@ private:
std::map<CrateNum, std::set<HirId>> hirNodesWithinCrate;
// MBE macros
- std::map<NodeId, AST::MacroRulesDefinition *> macroMappings;
+ std::map<NodeId, std::pair<AST::MacroRulesDefinition *, CrateNum>>
+ macroMappings;
std::map<NodeId, AST::MacroRulesDefinition *> macroInvocations;
std::vector<NodeId> exportedMacros;
@@ -433,6 +440,9 @@ private:
// AST mappings
std::map<NodeId, AST::Item *> ast_item_mappings;
+
+ // Closure AST NodeId -> vector of Definition node ids
+ std::unordered_map<NodeId, std::vector<NodeId>> captures;
};
} // namespace Analysis
diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc
index 0d8a98077..0bd74b2 100644
--- a/gcc/rust/util/rust-lang-item.cc
+++ b/gcc/rust/util/rust-lang-item.cc
@@ -46,6 +46,7 @@ const BiMap<std::string, LangItem::Kind> Rust::LangItem::lang_items = {{
{"shr_assign", Kind::SHR_ASSIGN},
{"deref", Kind::DEREF},
{"deref_mut", Kind::DEREF_MUT},
+ {"receiver", Kind::RECEIVER},
{"index", Kind::INDEX},
{"index_mut", Kind::INDEX_MUT},
{"RangeFull", Kind::RANGE_FULL},
@@ -62,6 +63,7 @@ const BiMap<std::string, LangItem::Kind> Rust::LangItem::lang_items = {{
{"copy", Kind::COPY},
{"clone", Kind::CLONE},
{"sized", Kind::SIZED},
+ {"sync", Kind::SYNC},
{"slice_alloc", Kind::SLICE_ALLOC},
{"slice_u8_alloc", Kind::SLICE_U8_ALLOC},
{"str_alloc", Kind::STR_ALLOC},
@@ -91,6 +93,32 @@ const BiMap<std::string, LangItem::Kind> Rust::LangItem::lang_items = {{
{"str", Kind::STR},
{"f32_runtime", Kind::F32_RUNTIME},
{"f64_runtime", Kind::F64_RUNTIME},
+
+ {"Some", Kind::OPTION_SOME},
+ {"None", Kind::OPTION_NONE},
+
+ {"Ok", Kind::RESULT_OK},
+ {"Err", Kind::RESULT_ERR},
+
+ {"into_iter", Kind::INTOITER_INTOITER},
+ {"next", Kind::ITERATOR_NEXT},
+
+ {"eq", Kind::EQ},
+ {"partial_ord", Kind::PARTIAL_ORD},
+
+ {"try", Kind::TRY},
+ {"into_result", Kind::TRY_INTO_RESULT},
+ {"from_error", Kind::TRY_FROM_ERROR},
+ {"from_ok", Kind::TRY_FROM_OK},
+
+ {"from", Kind::FROM_FROM},
+
+ {"structural_peq", Kind::STRUCTURAL_PEQ},
+ {"structural_teq", Kind::STRUCTURAL_TEQ},
+
+ {"discriminant_kind", Kind::DISCRIMINANT_KIND},
+ {"discriminant_type", Kind::DISCRIMINANT_TYPE},
+ {"manually_drop", Kind::MANUALLY_DROP},
}};
tl::optional<LangItem::Kind>
@@ -108,6 +136,12 @@ LangItem::ToString (LangItem::Kind type)
return str.value ();
}
+std::string
+LangItem::PrettyString (LangItem::Kind type)
+{
+ return "#[lang = \"" + LangItem::ToString (type) + "\"]";
+}
+
LangItem::Kind
LangItem::OperatorToLangItem (ArithmeticOrLogicalOperator op)
{
@@ -139,6 +173,47 @@ LangItem::OperatorToLangItem (ArithmeticOrLogicalOperator op)
}
LangItem::Kind
+LangItem::ComparisonToLangItem (ComparisonOperator op)
+{
+ switch (op)
+ {
+ case ComparisonOperator::NOT_EQUAL:
+ case ComparisonOperator::EQUAL:
+ return LangItem::Kind::EQ;
+
+ case ComparisonOperator::GREATER_THAN:
+ case ComparisonOperator::LESS_THAN:
+ case ComparisonOperator::GREATER_OR_EQUAL:
+ case ComparisonOperator::LESS_OR_EQUAL:
+ return LangItem::Kind::PARTIAL_ORD;
+ }
+
+ rust_unreachable ();
+}
+
+std::string
+LangItem::ComparisonToSegment (ComparisonOperator op)
+{
+ switch (op)
+ {
+ case ComparisonOperator::NOT_EQUAL:
+ return "ne";
+ case ComparisonOperator::EQUAL:
+ return "eq";
+ case ComparisonOperator::GREATER_THAN:
+ return "gt";
+ case ComparisonOperator::LESS_THAN:
+ return "lt";
+ case ComparisonOperator::GREATER_OR_EQUAL:
+ return "ge";
+ case ComparisonOperator::LESS_OR_EQUAL:
+ return "le";
+ }
+
+ rust_unreachable ();
+}
+
+LangItem::Kind
LangItem::CompoundAssignmentOperatorToLangItem (ArithmeticOrLogicalOperator op)
{
switch (op)
@@ -182,4 +257,13 @@ LangItem::NegationOperatorToLangItem (NegationOperator op)
rust_unreachable ();
}
+bool
+LangItem::IsEnumVariant (LangItem::Kind type)
+{
+ const static std::set<LangItem::Kind> enum_variants
+ = {Kind::OPTION_NONE, Kind::OPTION_SOME, Kind::RESULT_OK, Kind::RESULT_ERR};
+
+ return enum_variants.find (type) != enum_variants.end ();
+}
+
} // namespace Rust
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index 414436f..c7dff93 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -23,12 +23,15 @@
namespace Rust {
-// https://github.com/rust-lang/rust/blob/master/library/core/src/ops/arith.rs
class LangItem
{
public:
+ // FIXME: We should clean up that enum to make it more inline with the list of
+ // lang-items in Rust 1.49
+ // https://github.com/rust-lang/rust/blob/1.49.0/compiler/rustc_hir/src/lang_items.rs
enum class Kind
{
+ // https://github.com/rust-lang/rust/blob/master/library/core/src/ops/arith.rs
ADD,
SUBTRACT,
MULTIPLY,
@@ -42,6 +45,8 @@ public:
NEGATION,
NOT,
+ EQ,
+ PARTIAL_ORD,
ADD_ASSIGN,
SUB_ASSIGN,
@@ -56,6 +61,7 @@ public:
DEREF,
DEREF_MUT,
+ RECEIVER,
// https://github.com/rust-lang/rust/blob/master/library/core/src/ops/index.rs
INDEX,
@@ -82,6 +88,7 @@ public:
COPY,
CLONE,
SIZED,
+ SYNC,
// https://github.com/Rust-GCC/gccrs/issues/1896
// https://github.com/rust-lang/rust/commit/afbecc0f68c4dcfc4878ba5bcb1ac942544a1bdc
@@ -116,16 +123,52 @@ public:
STR,
F32_RUNTIME,
F64_RUNTIME,
+
+ OPTION_SOME,
+ OPTION_NONE,
+
+ RESULT_OK,
+ RESULT_ERR,
+
+ INTOITER_INTOITER,
+ ITERATOR_NEXT,
+
+ // NOTE: These lang items are *not* necessarily present in later versions of
+ // Rust (I am unsure at which point they have been removed as the `Try`
+ // trait is unstable). They will need to be changed when updating the
+ // targeted Rust version of gccrs
+ TRY,
+ TRY_INTO_RESULT,
+ TRY_FROM_ERROR,
+ TRY_FROM_OK,
+
+ // NOTE: This is not a lang item in later versions of Rust
+ FROM_FROM,
+
+ STRUCTURAL_PEQ,
+ STRUCTURAL_TEQ,
+
+ DISCRIMINANT_TYPE,
+ DISCRIMINANT_KIND,
+
+ MANUALLY_DROP,
};
static const BiMap<std::string, Kind> lang_items;
static tl::optional<Kind> Parse (const std::string &item);
+
static std::string ToString (Kind type);
+ static std::string PrettyString (Kind type);
+
static Kind OperatorToLangItem (ArithmeticOrLogicalOperator op);
static Kind
CompoundAssignmentOperatorToLangItem (ArithmeticOrLogicalOperator op);
static Kind NegationOperatorToLangItem (NegationOperator op);
+ static Kind ComparisonToLangItem (ComparisonOperator op);
+ static std::string ComparisonToSegment (ComparisonOperator op);
+
+ static bool IsEnumVariant (Kind type);
};
} // namespace Rust
diff --git a/gcc/rust/util/rust-operators.h b/gcc/rust/util/rust-operators.h
index e3d6205..f460f4f 100644
--- a/gcc/rust/util/rust-operators.h
+++ b/gcc/rust/util/rust-operators.h
@@ -43,10 +43,10 @@ enum class ComparisonOperator
{
EQUAL, // std::cmp::PartialEq::eq
NOT_EQUAL, // std::cmp::PartialEq::ne
- GREATER_THAN, // std::cmp::PartialEq::gt
- LESS_THAN, // std::cmp::PartialEq::lt
- GREATER_OR_EQUAL, // std::cmp::PartialEq::ge
- LESS_OR_EQUAL // std::cmp::PartialEq::le
+ GREATER_THAN, // std::cmp::PartialOrd::gt
+ LESS_THAN, // std::cmp::PartialOrd::lt
+ GREATER_OR_EQUAL, // std::cmp::PartialOrd::ge
+ LESS_OR_EQUAL // std::cmp::PartialOrd::le
};
enum class LazyBooleanOperator
diff --git a/gcc/rust/util/rust-stacked-contexts.h b/gcc/rust/util/rust-stacked-contexts.h
index 86cdf9f..cabc65d 100644
--- a/gcc/rust/util/rust-stacked-contexts.h
+++ b/gcc/rust/util/rust-stacked-contexts.h
@@ -71,6 +71,20 @@ public:
return last;
}
+ const T &peek () const
+ {
+ rust_assert (!stack.empty ());
+
+ return stack.back ();
+ }
+
+ T &peek ()
+ {
+ rust_assert (!stack.empty ());
+
+ return stack.back ();
+ }
+
/**
* Are we currently inside of a special context?
*/
diff --git a/gcc/rust/util/rust-token-converter.cc b/gcc/rust/util/rust-token-converter.cc
index 220e891..fc34adb 100644
--- a/gcc/rust/util/rust-token-converter.cc
+++ b/gcc/rust/util/rust-token-converter.cc
@@ -18,8 +18,7 @@
#include "rust-token-converter.h"
#include "bi-map.h"
#include "line-map.h"
-
-#include <string>
+#include "rust-system.h"
namespace Rust {
diff --git a/gcc/rust/util/rust-token-converter.h b/gcc/rust/util/rust-token-converter.h
index 0498041..5405d6e 100644
--- a/gcc/rust/util/rust-token-converter.h
+++ b/gcc/rust/util/rust-token-converter.h
@@ -17,7 +17,7 @@
#ifndef RUST_TOKEN_CONVERTER_H
#define RUST_TOKEN_CONVERTER_H
-#include <vector>
+#include "rust-system.h"
#include "rust-token.h"
#include "libproc_macro_internal/proc_macro.h"
diff --git a/gcc/rust/util/rust-unwrap-segment.cc b/gcc/rust/util/rust-unwrap-segment.cc
new file mode 100644
index 0000000..083a0e5
--- /dev/null
+++ b/gcc/rust/util/rust-unwrap-segment.cc
@@ -0,0 +1,61 @@
+// Copyright (C) 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
+// <http://www.gnu.org/licenses/>.
+
+#include "ast/rust-path.h"
+
+namespace Rust {
+
+NodeId
+unwrap_segment_node_id (const AST::TypePathSegment &seg)
+{
+ return seg.get_node_id ();
+}
+
+NodeId
+unwrap_segment_node_id (const AST::SimplePathSegment &seg)
+{
+ return seg.get_node_id ();
+}
+
+NodeId
+unwrap_segment_node_id (const AST::PathExprSegment &seg)
+{
+ return seg.get_node_id ();
+}
+
+tl::optional<LangItem::Kind>
+unwrap_segment_get_lang_item (const AST::TypePathSegment &seg)
+{
+ if (seg.is_lang_item ())
+ return seg.get_lang_item ();
+ return tl::nullopt;
+}
+
+tl::optional<LangItem::Kind>
+unwrap_segment_get_lang_item (const AST::SimplePathSegment &seg)
+{
+ return tl::nullopt;
+}
+
+tl::optional<LangItem::Kind>
+unwrap_segment_get_lang_item (const AST::PathExprSegment &seg)
+{
+ return tl::nullopt;
+}
+
+} // namespace Rust
diff --git a/gcc/rust/util/rust-unwrap-segment.h b/gcc/rust/util/rust-unwrap-segment.h
new file mode 100644
index 0000000..bebdc3a
--- /dev/null
+++ b/gcc/rust/util/rust-unwrap-segment.h
@@ -0,0 +1,121 @@
+// Copyright (C) 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
+// <http://www.gnu.org/licenses/>.
+
+#include <ast/rust-ast-full-decls.h>
+
+namespace Rust {
+
+/*
+ * Used to convert different path segment object references
+ * into SimplePathSegment/PathIdentSegment references
+ *
+ * unwrap_type_segment:
+ * expands to a call to unwrap_type_segment_inner::unwrap,
+ * used for type inference
+ */
+#define unwrap_type_segment(x) \
+ (unwrap_type_segment_inner<typename std::remove_const< \
+ typename std::remove_reference<decltype (x)>::type>::type>::unwrap (x))
+
+template <class T> class unwrap_type_segment_inner;
+
+/* base case */
+template <> class unwrap_type_segment_inner<AST::SimplePathSegment>
+{
+public:
+ /* The return type of unwrap */
+ using ret = AST::SimplePathSegment;
+
+ /* non-const qualified unwrap */
+ static AST::SimplePathSegment &unwrap (AST::SimplePathSegment &x)
+ {
+ return x;
+ }
+
+ /* const qualified unwrap */
+ static const AST::SimplePathSegment &unwrap (const AST::SimplePathSegment &x)
+ {
+ return x;
+ }
+};
+
+/* case which dereferences unique_ptr */
+template <class T> class unwrap_type_segment_inner<std::unique_ptr<T>>
+{
+public:
+ using ret = typename unwrap_type_segment_inner<T>::ret;
+
+ static ret &unwrap (std::unique_ptr<T> &x)
+ {
+ return unwrap_type_segment (*x);
+ }
+ static const ret &unwrap (const std::unique_ptr<T> &x)
+ {
+ return unwrap_type_segment (*x);
+ }
+};
+
+/* case which handles objects with a get_ident_segment member function */
+template <class T> class unwrap_type_segment_inner
+{
+public:
+ using ret = AST::PathIdentSegment;
+
+ static ret &unwrap (T &x) { return x.get_ident_segment (); }
+ static const ret &unwrap (const T &x) { return x.get_ident_segment (); }
+};
+
+/*
+ * Used to get the node id of a path segment object
+ */
+NodeId
+unwrap_segment_node_id (const AST::TypePathSegment &seg);
+
+NodeId
+unwrap_segment_node_id (const AST::SimplePathSegment &seg);
+
+NodeId
+unwrap_segment_node_id (const AST::PathExprSegment &seg);
+
+template <class T>
+NodeId
+unwrap_segment_node_id (const std::unique_ptr<T> &ptr)
+{
+ return unwrap_segment_node_id (*ptr);
+}
+
+/**
+ * Used to check if a path segment is associated with a lang item
+ */
+tl::optional<LangItem::Kind>
+unwrap_segment_get_lang_item (const AST::TypePathSegment &seg);
+
+tl::optional<LangItem::Kind>
+unwrap_segment_get_lang_item (const AST::SimplePathSegment &seg);
+
+tl::optional<LangItem::Kind>
+unwrap_segment_get_lang_item (const AST::PathExprSegment &seg);
+
+template <class T>
+tl::optional<LangItem::Kind>
+unwrap_segment_get_lang_item (const std::unique_ptr<T> &ptr)
+{
+ return unwrap_segment_get_lang_item (*ptr);
+}
+
+} // namespace Rust