diff options
Diffstat (limited to 'gcc/rust/util')
-rw-r--r-- | gcc/rust/util/expected.h | 4 | ||||
-rw-r--r-- | gcc/rust/util/rust-attribute-values.h | 27 | ||||
-rw-r--r-- | gcc/rust/util/rust-attributes.cc | 22 | ||||
-rw-r--r-- | gcc/rust/util/rust-attributes.h | 7 | ||||
-rw-r--r-- | gcc/rust/util/rust-edition.cc | 40 | ||||
-rw-r--r-- | gcc/rust/util/rust-edition.h | 41 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.cc | 69 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.h | 17 | ||||
-rw-r--r-- | gcc/rust/util/rust-lang-item.cc | 27 | ||||
-rw-r--r-- | gcc/rust/util/rust-lang-item.h | 29 | ||||
-rw-r--r-- | gcc/rust/util/rust-stacked-contexts.h | 9 | ||||
-rw-r--r-- | gcc/rust/util/rust-unwrap-segment.cc | 61 | ||||
-rw-r--r-- | gcc/rust/util/rust-unwrap-segment.h | 121 |
13 files changed, 455 insertions, 19 deletions
diff --git a/gcc/rust/util/expected.h b/gcc/rust/util/expected.h index a9e3bc2..07ba877 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/rust-attribute-values.h b/gcc/rust/util/rust-attribute-values.h index 9ef5cc5..47e6a17 100644 --- a/gcc/rust/util/rust-attribute-values.h +++ b/gcc/rust/util/rust-attribute-values.h @@ -40,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)] @@ -54,10 +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 03452c7..c77e99c 100644 --- a/gcc/rust/util/rust-attributes.cc +++ b/gcc/rust/util/rust-attributes.cc @@ -57,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}, @@ -72,10 +73,29 @@ static const BuiltinAttrDefinition __definitions[] {Attrs::RUSTC_INHERIT_OVERFLOW_CHECKS, CODE_GENERATION}, {Attrs::STABLE, 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::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 c928c8e..7c7a1fc 100644 --- a/gcc/rust/util/rust-attributes.h +++ b/gcc/rust/util/rust-attributes.h @@ -40,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-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-edition.h b/gcc/rust/util/rust-edition.h new file mode 100644 index 0000000..d034ea0 --- /dev/null +++ b/gcc/rust/util/rust-edition.h @@ -0,0 +1,41 @@ +// 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/>. + +#ifndef RUST_EDITION_H +#define RUST_EDITION_H + +/* + * This header exists to avoid including rust-session-manager.h + * when we only need information on the selected rust edition + */ + +namespace Rust { + +enum class Edition +{ + E2015, + E2018, + E2021 +}; + +Edition +get_rust_edition (); + +} // namespace Rust + +#endif // !RUST_EDITION_H diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index b94591e..eaa640c 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -148,6 +148,16 @@ Mappings::get_crate_name (CrateNum crate_num) const 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; + + return it->second; +} + void Mappings::set_crate_name (CrateNum crate_num, const std::string &name) { @@ -184,13 +194,7 @@ Mappings::crate_num_to_nodeid (const CrateNum &crate_num) const 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 @@ -262,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 @@ -874,7 +879,7 @@ 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}; } tl::optional<AST::MacroRulesDefinition *> @@ -884,7 +889,17 @@ Mappings::lookup_macro_def (NodeId id) if (it == macroMappings.end ()) return tl::nullopt; - return it->second; + 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; + + return it->second.second; } void @@ -1305,8 +1320,40 @@ 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, "failed to find lang item %qs", - LangItem::ToString (item_type).c_str ()); + 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 diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 21e5328..b523a36 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -81,6 +81,8 @@ public: void set_current_crate (CrateNum crateNum); CrateNum get_current_crate () 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); const std::string &get_current_crate_name () const; tl::optional<CrateNum> @@ -269,6 +271,7 @@ public: void insert_macro_def (AST::MacroRulesDefinition *macro); 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); @@ -342,6 +345,11 @@ public: 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 (); @@ -380,6 +388,9 @@ private: 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; @@ -394,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; @@ -428,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 e038e90..9aff31b 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}, @@ -96,11 +97,28 @@ const BiMap<std::string, LangItem::Kind> Rust::LangItem::lang_items = {{ {"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> @@ -239,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 f947f3f..67a5d9c 100644 --- a/gcc/rust/util/rust-lang-item.h +++ b/gcc/rust/util/rust-lang-item.h @@ -61,6 +61,7 @@ public: DEREF, DEREF_MUT, + RECEIVER, // https://github.com/rust-lang/rust/blob/master/library/core/src/ops/index.rs INDEX, @@ -126,22 +127,48 @@ public: 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-stacked-contexts.h b/gcc/rust/util/rust-stacked-contexts.h index fe0bc8a..b263d75 100644 --- a/gcc/rust/util/rust-stacked-contexts.h +++ b/gcc/rust/util/rust-stacked-contexts.h @@ -71,7 +71,14 @@ public: return last; } - const T &peek () + const T &peek () const + { + rust_assert (!stack.empty ()); + + return stack.back (); + } + + T &peek () { rust_assert (!stack.empty ()); 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 |