Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2223274/?format=api
{ "id": 2223274, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2223274/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260414231905.191063-2-arthur.cohen@embecosm.com/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/1.1/projects/17/?format=api", "name": "GNU Compiler Collection", "link_name": "gcc", "list_id": "gcc-patches.gcc.gnu.org", "list_email": "gcc-patches@gcc.gnu.org", "web_url": null, "scm_url": null, "webscm_url": null }, "msgid": "<20260414231905.191063-2-arthur.cohen@embecosm.com>", "date": "2026-04-14T23:18:23", "name": "[COMMITTED,02/43] gccrs: Improve path resolution", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "33489c25c4de83f09cae00a07433e37fa2e17b9b", "submitter": { "id": 83476, "url": "http://patchwork.ozlabs.org/api/1.1/people/83476/?format=api", "name": "Arthur Cohen", "email": "arthur.cohen@embecosm.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260414231905.191063-2-arthur.cohen@embecosm.com/mbox/", "series": [ { "id": 499900, "url": "http://patchwork.ozlabs.org/api/1.1/series/499900/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=499900", "date": "2026-04-14T23:18:24", "name": "[COMMITTED,01/43] gccrs: testsuite:Add a testcase for setup_associated_types", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/499900/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2223274/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2223274/checks/", "tags": {}, "headers": { "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "gcc-patches@gcc.gnu.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=embecosm.com header.i=@embecosm.com header.a=rsa-sha256\n header.s=google header.b=Q0+defBm;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)", "sourceware.org;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=embecosm.com header.i=@embecosm.com header.a=rsa-sha256\n header.s=google header.b=Q0+defBm", "sourceware.org;\n dmarc=none (p=none dis=none) header.from=embecosm.com", "sourceware.org; spf=pass smtp.mailfrom=embecosm.com", "server2.sourceware.org;\n arc=none smtp.remote-ip=209.85.128.67" ], "Received": [ "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fwKtt1GKhz1yHc\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 15 Apr 2026 09:17:42 +1000 (AEST)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 5CCA14BA23C3\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2026 23:17:40 +0000 (GMT)", "from mail-wm1-f67.google.com (mail-wm1-f67.google.com\n [209.85.128.67])\n by sourceware.org (Postfix) with ESMTPS id CCF4C4BA2E07\n for <gcc-patches@gcc.gnu.org>; Tue, 14 Apr 2026 23:14:12 +0000 (GMT)", "by mail-wm1-f67.google.com with SMTP id\n 5b1f17b1804b1-4888375f735so60516025e9.3\n for <gcc-patches@gcc.gnu.org>; Tue, 14 Apr 2026 16:14:12 -0700 (PDT)", "from platypus.localdomain (176-147-231-59.abo.bbox.fr.\n [176.147.231.59]) by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-488f1dd8806sm3325945e9.3.2026.04.14.16.14.09\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 14 Apr 2026 16:14:10 -0700 (PDT)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 5CCA14BA23C3", "OpenDKIM Filter v2.11.0 sourceware.org CCF4C4BA2E07" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org CCF4C4BA2E07", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org CCF4C4BA2E07", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776208453; cv=none;\n b=wNV6zheBhbyE1/NjHxNmY4bWuFVmFaVQ5QC9dRT+3y5BCj8tmP0f4ed3SO2GDn0v5iWht45/GTgZ40IoLHiSn/xYffUQQDZxmh69EspSP5DQAcN1irkZ/FAOSY9EskEcw3u7YGqucyD0hEeCUBSlOCIreEzmHydEEPbJd3vuyIs=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776208453; c=relaxed/simple;\n bh=9Q/+I7F/D4UrpQA+X8NTXv5hUYu4Ibr52xBPUKLg7ZA=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=Tul+g30hdOHjjw/XqKQAYpTrlsjgaVdWzKrpgOJlsERa4Ks9gaaruI7l3whAj9So968yPOJc+mkIOoNWj0s4tCc1bnlSfqETMyACDNFyJuHS76TMy/mF0n0xk/N2Cm95tSYmU8CDWpxDqdckt/ECdKVUwtJoD39DauNJSUuZCg4=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=embecosm.com; s=google; t=1776208451; x=1776813251; darn=gcc.gnu.org;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:from:to:cc:subject:date\n :message-id:reply-to;\n bh=DpCCzydQ4EB2cGFazRaAI6jwq9Sau9s2lROJfIbZ+po=;\n b=Q0+defBmqoRxsCz/AQdAFnoFwUsLN2E/Ygk1ZvF6rs8TaoyazwMtJgtsW8G8BRYGD0\n KsHYF5R8e18IS2F6ErAXBhKPU3gu1bsL3hr/BxCfmqC0L5lGVPVULUbI3X/6xi0slbue\n fp4wKHzDU9VoP1ecBTxLxLB0uHuGPGsnt0yFjdpB9hoNcRJedQ0di9+8r4tIWYtD7ROt\n QUvyUdHNYCFiy/Q/o14WKpfYT9CX/mHL9uBscr74cjrR4PTxKL/XVKv+oLV9AS6b8LjJ\n JqGxHqn4SKFPU23NqYy7T2OyuZT4b03W/e+cC097+aP2ueR1MGbWhHX54eKtexNnN3ns\n y26w==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776208451; x=1776813251;\n h=content-transfer-encoding:mime-version:references:in-reply-to\n :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from\n :to:cc:subject:date:message-id:reply-to;\n bh=DpCCzydQ4EB2cGFazRaAI6jwq9Sau9s2lROJfIbZ+po=;\n b=peuhUVKMX1wxsscQ2KiAg5AEIYK4V84M52F8037dU1jQ4BWRP7eJUfIJsNCs9wGcnO\n 2BPyd/FOlhOmztFkrmzckecpgmtqNVwGy+i9r/aqj8DOgJNLwsT4KwjC4kQ95Y5lru8J\n ogl++PNOEQxvZyKlk2v8MzvmLXBT9SUGC9fjE4I4utH7fp20XG18MDIoLgxKGfrsnnai\n XRJdudyGK2gOrvEsHGm63liG40oq0aA+/ALo5q2MWXFC5oOFwOKYvG4wrOms3nN6tIVy\n XxUKBLLmbQlN1CuwBGv5jyHdiyoLcS4pt+2Glf+hk4dDbJ5RFNroy1jc7JZTALr+wuU3\n qVHw==", "X-Gm-Message-State": "AOJu0YwPq4RH4AuVQ+x9JQtZu4RiB36Ph+MeyMPtFDjrwJj3D/62cRUW\n bV+MHGtNxbKN26Eemawyf2zagrwxl2ijkrSr2yE/iw1XfnzrwS1AZf/pTKaLkLM/L0AkiH3MHZq\n uggsatRS3", "X-Gm-Gg": "AeBDievNH6n74Uga6v7jQ0KE8dqpkPGiTbGhzs8yPNrT7o/CMqElJgP2C6DSN2WtIiY\n HDrJMAFpH5Arvr2sHhcLnDvtlTYldy5BgOWNc9bZFOyytvBkxP3Fb4JuVRY+bW5S6kIve5etYpQ\n /Swv3GMAo1Migu5QGmW+jNbkcCEb1jCXWyxN/SMnkr5dflqnl0kYKBrE/hirAasog1cgDFwnSdA\n GW2w0TDZYHWkJLt9+AV0vnLctbuPqNdXel605NEBYIpcdP9X9eiFGW32CmXsK7Z0AroyGPvfrw+\n rVwrMApr/IDr3ankT38G13odbcoTwkU9cHnfeeR5hlZBypfUZVgpV09T8CHFIz0pgjKrVJ89WHT\n D//hRYzRFPED8p9FoBDGvqpH84iwOMsGL+y8AWsR7OeRPfaAK/cMfujj5PJC0EhO2mi8gRX8wPd\n dkowcxPr+7D7vIuZNYRDl+CTQQ+19EaUpJV7UsUc1fDeHg7p/tq+62yd1Wts27wKmuaCNucrscj\n 1oENA==", "X-Received": "by 2002:a05:600c:c0c8:b0:488:af14:f1de with SMTP id\n 5b1f17b1804b1-488d67b8de8mr194529085e9.4.1776208450985;\n Tue, 14 Apr 2026 16:14:10 -0700 (PDT)", "From": "arthur.cohen@embecosm.com", "To": "gcc-patches@gcc.gnu.org", "Cc": "gcc-rust@gcc.gnu.org,\n\tOwen Avery <powerboat9.gamer@gmail.com>", "Subject": "[COMMITTED 02/43] gccrs: Improve path resolution", "Date": "Wed, 15 Apr 2026 01:18:23 +0200", "Message-ID": "<20260414231905.191063-2-arthur.cohen@embecosm.com>", "X-Mailer": "git-send-email 2.50.1", "In-Reply-To": "<20260414231905.191063-1-arthur.cohen@embecosm.com>", "References": "<20260414231905.191063-1-arthur.cohen@embecosm.com>", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "X-BeenThere": "gcc-patches@gcc.gnu.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>", "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>", "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>", "List-Post": "<mailto:gcc-patches@gcc.gnu.org>", "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>", "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>", "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org" }, "content": "From: Owen Avery <powerboat9.gamer@gmail.com>\n\nThis makes path resolution less dependent on templates for path\nhandling.\n\ngcc/rust/ChangeLog:\n\n\t* resolve/rust-forever-stack.h: Include more headers.\n\t(class ResolutionPath): New class for representing paths.\n\t(ForeverStack::resolve_path): Change function signature.\n\t(ForeverStack::find_starting_point): Likewise.\n\t(ForeverStack::resolve_segments): Likewise.\n\t(ForeverStack::SegIterator): Change type alias.\n\t* resolve/rust-forever-stack.hxx (check_leading_kw_at_start):\n\tChange function signature.\n\t(ForeverStack::find_starting_point): Likewise.\n\t(ForeverStack::resolve_segments): Likewise.\n\t(ForeverStack::resolve_path): Likewise.\n\t* resolve/rust-name-resolution-context.h: Tweak include guard,\n\tinclude \"rust-name-resolution.h\".\n\t(NameResolutionContext::resolve_path): Use ResolutionPath and\n\tResolutionBuilder.\n\t(class NameResolutionContext::ResolutionBuilder): New class.\n\t(class Usage): Move this...\n\t(class Definition): ...and this...\n\t* resolve/rust-name-resolution.h: ...to new file.\n\t* util/rust-unwrap-segment.h: Add include guard.\n\nSigned-off-by: Owen Avery <powerboat9.gamer@gmail.com>\n---\n gcc/rust/resolve/rust-forever-stack.h | 103 ++++++--\n gcc/rust/resolve/rust-forever-stack.hxx | 186 +++++++-------\n .../resolve/rust-name-resolution-context.h | 240 +++++++++++-------\n gcc/rust/resolve/rust-name-resolution.h | 50 ++++\n gcc/rust/util/rust-unwrap-segment.h | 5 +\n 5 files changed, 385 insertions(+), 199 deletions(-)\n create mode 100644 gcc/rust/resolve/rust-name-resolution.h", "diff": "diff --git a/gcc/rust/resolve/rust-forever-stack.h b/gcc/rust/resolve/rust-forever-stack.h\nindex 309a0ccd630..f6e351a1c4f 100644\n--- a/gcc/rust/resolve/rust-forever-stack.h\n+++ b/gcc/rust/resolve/rust-forever-stack.h\n@@ -25,6 +25,8 @@\n #include \"rust-path.h\"\n #include \"optional.h\"\n #include \"expected.h\"\n+#include \"rust-name-resolution.h\"\n+#include \"rust-unwrap-segment.h\"\n \n namespace Rust {\n namespace Resolver2_0 {\n@@ -550,6 +552,74 @@ enum class ResolutionMode\n FromExtern, // extern prelude\n };\n \n+class ResolutionPath\n+{\n+public:\n+ template <typename T>\n+ ResolutionPath (const std::vector<T> &segments_in, NodeId node_id)\n+ : node_id (node_id)\n+ {\n+ segments.clear ();\n+ segments.reserve (segments_in.size ());\n+ for (auto &outer_seg : segments_in)\n+ {\n+\tif (auto lang_item = unwrap_segment_get_lang_item (outer_seg))\n+\t {\n+\t rust_assert (!lang_prefix.has_value ());\n+\t lang_prefix = std::make_pair (lang_item.value (),\n+\t\t\t\t\t unwrap_segment_node_id (outer_seg));\n+\t continue;\n+\t }\n+\n+\tauto &seg = unwrap_type_segment (outer_seg);\n+\n+\tSegment new_seg;\n+\tnew_seg.name = seg.as_string ();\n+\tnew_seg.node_id = unwrap_segment_node_id (outer_seg);\n+\tnew_seg.locus = seg.get_locus ();\n+\tsegments.push_back (std::move (new_seg));\n+ }\n+ }\n+\n+ ResolutionPath () : node_id (UNKNOWN_NODEID) {}\n+\n+ struct Segment\n+ {\n+ std::string name;\n+ NodeId node_id;\n+ location_t locus;\n+\n+ bool is_super_path_seg () const { return name.compare (\"super\") == 0; }\n+ bool is_crate_path_seg () const { return name.compare (\"crate\") == 0; }\n+ bool is_lower_self_seg () const { return name.compare (\"self\") == 0; }\n+ bool is_big_self_seg () const { return name.compare (\"Self\") == 0; }\n+ };\n+\n+ tl::optional<std::pair<LangItem::Kind, NodeId>> get_lang_prefix () const\n+ {\n+ return lang_prefix;\n+ }\n+\n+ const std::vector<Segment> &get_segments () const { return segments; }\n+\n+ NodeId get_node_id () const { return node_id; }\n+\n+ std::string as_string () const\n+ {\n+ std::string ret;\n+ if (lang_prefix)\n+ ret = \"#[lang]::\";\n+ for (auto &seg : segments)\n+ ret += \"::\" + seg.name;\n+ return ret;\n+ }\n+\n+private:\n+ tl::optional<std::pair<LangItem::Kind, NodeId>> lang_prefix;\n+ std::vector<Segment> segments;\n+ NodeId node_id;\n+};\n+\n template <Namespace N> class ForeverStack\n {\n public:\n@@ -687,15 +757,13 @@ public:\n * @return a valid option with the Definition if the path is present in the\n * current map, an empty one otherwise.\n */\n- template <typename S>\n tl::optional<Rib::Definition> resolve_path (\n- const std::vector<S> &segments, ResolutionMode mode,\n- std::function<void (const S &, NodeId)> insert_segment_resolution,\n+ const ResolutionPath &path, ResolutionMode mode,\n+ std::function<void (Usage, Definition)> insert_segment_resolution,\n std::vector<Error> &collect_errors);\n- template <typename S>\n tl::optional<Rib::Definition> resolve_path (\n- const std::vector<S> &segments, ResolutionMode mode,\n- std::function<void (const S &, NodeId)> insert_segment_resolution,\n+ const ResolutionPath &path, ResolutionMode mode,\n+ std::function<void (Usage, Definition)> insert_segment_resolution,\n std::vector<Error> &collect_errors, NodeId starting_point_id);\n \n // FIXME: Documentation\n@@ -764,10 +832,9 @@ private:\n \n tl::optional<Rib::Definition> get (Node &start, const Identifier &name);\n \n- template <typename S>\n tl::optional<Rib::Definition> resolve_path (\n- const std::vector<S> &segments, ResolutionMode mode,\n- std::function<void (const S &, NodeId)> insert_segment_resolution,\n+ const ResolutionPath &path, ResolutionMode mode,\n+ std::function<void (Usage, Definition)> insert_segment_resolution,\n std::vector<Error> &collect_errors,\n std::reference_wrapper<Node> starting_point);\n \n@@ -817,23 +884,21 @@ private:\n \n /* Helper types and functions for `resolve_path` */\n \n- template <typename S>\n- using SegIterator = typename std::vector<S>::const_iterator;\n+ using SegIterator =\n+ typename std::vector<ResolutionPath::Segment>::const_iterator;\n \n Node &find_closest_module (Node &starting_point);\n \n- template <typename S>\n- tl::optional<SegIterator<S>> find_starting_point (\n- const std::vector<S> &segments,\n+ tl::optional<SegIterator> find_starting_point (\n+ const std::vector<ResolutionPath::Segment> &segments,\n std::reference_wrapper<Node> &starting_point,\n- std::function<void (const S &, NodeId)> insert_segment_resolution,\n+ std::function<void (Usage, Definition)> insert_segment_resolution,\n std::vector<Error> &collect_errors);\n \n- template <typename S>\n tl::optional<Node &> resolve_segments (\n- Node &starting_point, const std::vector<S> &segments,\n- SegIterator<S> iterator,\n- std::function<void (const S &, NodeId)> insert_segment_resolution,\n+ Node &starting_point, const std::vector<ResolutionPath::Segment> &segments,\n+ SegIterator iterator,\n+ std::function<void (Usage, Definition)> insert_segment_resolution,\n std::vector<Error> &collect_errors);\n \n tl::optional<Rib::Definition> resolve_final_segment (Node &final_node,\ndiff --git a/gcc/rust/resolve/rust-forever-stack.hxx b/gcc/rust/resolve/rust-forever-stack.hxx\nindex 0f92a7f332a..c7c5c9439e4 100644\n--- a/gcc/rust/resolve/rust-forever-stack.hxx\n+++ b/gcc/rust/resolve/rust-forever-stack.hxx\n@@ -431,16 +431,15 @@ ForeverStack<N>::find_closest_module (Node &starting_point)\n \n /* If a the given condition is met, emit an error about misused leading path\n * segments */\n-template <typename S>\n static inline bool\n-check_leading_kw_at_start (std::vector<Error> &collect_errors, const S &segment,\n+check_leading_kw_at_start (std::vector<Error> &collect_errors,\n+\t\t\t const ResolutionPath::Segment &segment,\n \t\t\t bool condition)\n {\n if (condition)\n collect_errors.emplace_back (\n- segment.get_locus (), ErrorCode::E0433,\n- \"%qs in paths can only be used in start position\",\n- segment.as_string ().c_str ());\n+ segment.locus, ErrorCode::E0433,\n+ \"%qs in paths can only be used in start position\", segment.name.c_str ());\n \n return condition;\n }\n@@ -451,23 +450,19 @@ check_leading_kw_at_start (std::vector<Error> &collect_errors, const S &segment,\n // `super` segment, we go back to the cursor's parent until we reach the\n // correct one or the root.\n template <Namespace N>\n-template <typename S>\n-tl::optional<typename std::vector<S>::const_iterator>\n+tl::optional<typename std::vector<ResolutionPath::Segment>::const_iterator>\n ForeverStack<N>::find_starting_point (\n- const std::vector<S> &segments, std::reference_wrapper<Node> &starting_point,\n- std::function<void (const S &, NodeId)> insert_segment_resolution,\n+ const std::vector<ResolutionPath::Segment> &segments,\n+ std::reference_wrapper<Node> &starting_point,\n+ std::function<void (Usage, Definition)> insert_segment_resolution,\n std::vector<Error> &collect_errors)\n {\n auto iterator = segments.begin ();\n \n for (; !is_last (iterator, segments); iterator++)\n {\n- auto &outer_seg = *iterator;\n+ auto &seg = *iterator;\n \n- if (unwrap_segment_get_lang_item (outer_seg).has_value ())\n-\tbreak;\n-\n- auto &seg = unwrap_type_segment (outer_seg);\n bool is_self_or_crate\n \t= seg.is_crate_path_seg () || seg.is_lower_self_seg ();\n \n@@ -481,7 +476,8 @@ ForeverStack<N>::find_starting_point (\n if (seg.is_crate_path_seg ())\n \t{\n \t starting_point = root;\n-\t insert_segment_resolution (outer_seg, starting_point.get ().id);\n+\t insert_segment_resolution (Usage (seg.node_id),\n+\t\t\t\t Definition (starting_point.get ().id));\n \t iterator++;\n \t break;\n \t}\n@@ -489,7 +485,8 @@ ForeverStack<N>::find_starting_point (\n \t{\n \t // insert segment resolution and exit\n \t starting_point = find_closest_module (starting_point);\n-\t insert_segment_resolution (outer_seg, starting_point.get ().id);\n+\t insert_segment_resolution (Usage (seg.node_id),\n+\t\t\t\t Definition (starting_point.get ().id));\n \t iterator++;\n \t break;\n \t}\n@@ -499,7 +496,7 @@ ForeverStack<N>::find_starting_point (\n \t if (starting_point.get ().is_root ())\n \t {\n \t collect_errors.emplace_back (\n-\t\tseg.get_locus (), ErrorCode::E0433,\n+\t\tseg.locus, ErrorCode::E0433,\n \t\t\"too many leading %<super%> keywords\");\n \t return tl::nullopt;\n \t }\n@@ -507,7 +504,8 @@ ForeverStack<N>::find_starting_point (\n \t starting_point\n \t = find_closest_module (starting_point.get ().parent.value ());\n \n-\t insert_segment_resolution (outer_seg, starting_point.get ().id);\n+\t insert_segment_resolution (Usage (seg.node_id),\n+\t\t\t\t Definition (starting_point.get ().id));\n \t continue;\n \t}\n \n@@ -521,31 +519,19 @@ ForeverStack<N>::find_starting_point (\n }\n \n template <Namespace N>\n-template <typename S>\n tl::optional<typename ForeverStack<N>::Node &>\n ForeverStack<N>::resolve_segments (\n- Node &starting_point, const std::vector<S> &segments,\n- typename std::vector<S>::const_iterator iterator,\n- std::function<void (const S &, NodeId)> insert_segment_resolution,\n+ Node &starting_point, const std::vector<ResolutionPath::Segment> &segments,\n+ typename std::vector<ResolutionPath::Segment>::const_iterator iterator,\n+ std::function<void (Usage, Definition)> insert_segment_resolution,\n std::vector<Error> &collect_errors)\n {\n Node *current_node = &starting_point;\n for (; !is_last (iterator, segments); iterator++)\n {\n- auto &outer_seg = *iterator;\n-\n- if (auto lang_item = unwrap_segment_get_lang_item (outer_seg))\n-\t{\n-\t NodeId seg_id = Analysis::Mappings::get ().get_lang_item_node (\n-\t lang_item.value ());\n-\t current_node = &dfs_node (root, seg_id).value ();\n+ auto &seg = *iterator;\n \n-\t insert_segment_resolution (outer_seg, seg_id);\n-\t continue;\n-\t}\n-\n- auto &seg = unwrap_type_segment (outer_seg);\n- std::string str = seg.as_string ();\n+ std::string str = seg.name;\n rust_debug (\"[ARTHUR]: resolving segment part: %s\", str.c_str ());\n \n // check that we don't encounter *any* leading keywords afterwards\n@@ -607,7 +593,7 @@ ForeverStack<N>::resolve_segments (\n \t break;\n \t }\n \n-\t auto rib_lookup = current_node->rib.get (seg.as_string ());\n+\t auto rib_lookup = current_node->rib.get (seg.name);\n \t if (rib_lookup && !rib_lookup->is_ambiguous ())\n \t {\n \t if (Analysis::Mappings::get ()\n@@ -619,8 +605,9 @@ ForeverStack<N>::resolve_segments (\n \t\t}\n \t else\n \t\t{\n-\t\t insert_segment_resolution (outer_seg,\n-\t\t\t\t\t rib_lookup->get_node_id ());\n+\t\t insert_segment_resolution (Usage (seg.node_id),\n+\t\t\t\t\t Definition (\n+\t\t\t\t\t rib_lookup->get_node_id ()));\n \t\t return tl::nullopt;\n \t\t}\n \t }\n@@ -645,7 +632,8 @@ ForeverStack<N>::resolve_segments (\n // if child didn't point to a value\n // the while loop above would have returned or kept looping\n current_node = &child->get ();\n- insert_segment_resolution (outer_seg, current_node->id);\n+ insert_segment_resolution (Usage (seg.node_id),\n+\t\t\t\t Definition (current_node->id));\n }\n \n return *current_node;\n@@ -672,11 +660,10 @@ ForeverStack<N>::resolve_final_segment (Node &final_node, std::string &seg_name,\n }\n \n template <Namespace N>\n-template <typename S>\n tl::optional<Rib::Definition>\n ForeverStack<N>::resolve_path (\n- const std::vector<S> &segments, ResolutionMode mode,\n- std::function<void (const S &, NodeId)> insert_segment_resolution,\n+ const ResolutionPath &path, ResolutionMode mode,\n+ std::function<void (Usage, Definition)> insert_segment_resolution,\n std::vector<Error> &collect_errors, NodeId starting_point_id)\n {\n auto starting_point = dfs_node (root, starting_point_id);\n@@ -686,34 +673,56 @@ ForeverStack<N>::resolve_path (\n if (!starting_point)\n return tl::nullopt;\n \n- return resolve_path (segments, mode, insert_segment_resolution,\n-\t\t collect_errors, *starting_point);\n+ return resolve_path (path, mode, insert_segment_resolution, collect_errors,\n+\t\t *starting_point);\n }\n \n template <Namespace N>\n-template <typename S>\n tl::optional<Rib::Definition>\n ForeverStack<N>::resolve_path (\n- const std::vector<S> &segments, ResolutionMode mode,\n- std::function<void (const S &, NodeId)> insert_segment_resolution,\n+ const ResolutionPath &path, ResolutionMode mode,\n+ std::function<void (Usage, Definition)> insert_segment_resolution,\n std::vector<Error> &collect_errors)\n {\n std::reference_wrapper<Node> starting_point = cursor ();\n \n- return resolve_path (segments, mode, insert_segment_resolution,\n-\t\t collect_errors, starting_point);\n+ return resolve_path (path, mode, insert_segment_resolution, collect_errors,\n+\t\t starting_point);\n }\n \n template <Namespace N>\n-template <typename S>\n tl::optional<Rib::Definition>\n ForeverStack<N>::resolve_path (\n- const std::vector<S> &segments, ResolutionMode mode,\n- std::function<void (const S &, NodeId)> insert_segment_resolution,\n+ const ResolutionPath &path, ResolutionMode mode,\n+ std::function<void (Usage, Definition)> insert_segment_resolution,\n std::vector<Error> &collect_errors,\n std::reference_wrapper<Node> starting_point)\n {\n- rust_assert (!segments.empty ());\n+ bool can_descend = true;\n+\n+ rust_debug (\"resolving %s\", path.as_string ().c_str ());\n+\n+ if (auto lang_item = path.get_lang_prefix ())\n+ {\n+ NodeId seg_id\n+\t= Analysis::Mappings::get ().get_lang_item_node (lang_item->first);\n+\n+ insert_segment_resolution (Usage (lang_item->second),\n+\t\t\t\t Definition (seg_id));\n+\n+ if (path.get_segments ().empty ())\n+\treturn Rib::Definition::NonShadowable (seg_id);\n+\n+ auto new_start = dfs_node (root, seg_id);\n+ rust_assert (new_start.has_value ());\n+ starting_point = new_start.value ();\n+\n+ can_descend = false;\n+ }\n+ else\n+ {\n+ rust_assert (!path.get_segments ().empty ());\n+ }\n \n switch (mode)\n {\n@@ -729,40 +738,31 @@ ForeverStack<N>::resolve_path (\n rust_unreachable ();\n }\n \n+ auto &segments = path.get_segments ();\n+\n // if there's only one segment, we just use `get`\n- if (segments.size () == 1)\n+ if (can_descend && segments.size () == 1)\n {\n- auto &outer_seg = segments.front ();\n- if (auto lang_item = unwrap_segment_get_lang_item (outer_seg))\n-\t{\n-\t NodeId seg_id = Analysis::Mappings::get ().get_lang_item_node (\n-\t lang_item.value ());\n-\n-\t insert_segment_resolution (outer_seg, seg_id);\n-\t // TODO: does NonShadowable matter?\n-\t return Rib::Definition::NonShadowable (seg_id);\n-\t}\n+ auto &seg = segments.front ();\n \n- auto &seg = unwrap_type_segment (outer_seg);\n-\n- tl::optional<Rib::Definition> res\n-\t= get (starting_point.get (), seg.as_string ());\n+ tl::optional<Rib::Definition> res = get (starting_point.get (), seg.name);\n \n if (!res)\n-\tres = get_lang_prelude (seg.as_string ());\n+\tres = get_lang_prelude (seg.name);\n \n if (N == Namespace::Types && !res)\n \t{\n \t if (seg.is_crate_path_seg ())\n \t {\n-\t insert_segment_resolution (outer_seg, root.id);\n+\t insert_segment_resolution (Usage (seg.node_id),\n+\t\t\t\t\t Definition (root.id));\n \t // TODO: does NonShadowable matter?\n \t return Rib::Definition::NonShadowable (root.id);\n \t }\n \t else if (seg.is_lower_self_seg ())\n \t {\n \t NodeId id = find_closest_module (starting_point.get ()).id;\n-\t insert_segment_resolution (outer_seg, id);\n+\t insert_segment_resolution (Usage (seg.node_id), Definition (id));\n \t // TODO: does NonShadowable matter?\n \t return Rib::Definition::NonShadowable (id);\n \t }\n@@ -772,14 +772,14 @@ ForeverStack<N>::resolve_path (\n \t\t= find_closest_module (starting_point.get ());\n \t if (closest_module.is_root ())\n \t\t{\n-\t\t rust_error_at (seg.get_locus (), ErrorCode::E0433,\n+\t\t rust_error_at (seg.locus, ErrorCode::E0433,\n \t\t\t\t \"too many leading %<super%> keywords\");\n \t\t return tl::nullopt;\n \t\t}\n \n \t NodeId id\n \t\t= find_closest_module (closest_module.parent.value ()).id;\n-\t insert_segment_resolution (outer_seg, id);\n+\t insert_segment_resolution (Usage (seg.node_id), Definition (id));\n \t // TODO: does NonShadowable matter?\n \t return Rib::Definition::NonShadowable (id);\n \t }\n@@ -794,11 +794,12 @@ ForeverStack<N>::resolve_path (\n \t\t if (link.path.map_or (\n \t\t\t[&seg] (Identifier path) {\n \t\t\t auto &path_str = path.as_string ();\n-\t\t\t return path_str == seg.as_string ();\n+\t\t\t return path_str == seg.name;\n \t\t\t},\n \t\t\tfalse))\n \t\t {\n-\t\t insert_segment_resolution (outer_seg, kv.second.id);\n+\t\t insert_segment_resolution (Usage (seg.node_id),\n+\t\t\t\t\t\t Definition (kv.second.id));\n \t\t return Rib::Definition::NonShadowable (kv.second.id);\n \t\t }\n \t\t}\n@@ -806,28 +807,33 @@ ForeverStack<N>::resolve_path (\n \t}\n \n if (res && !res->is_ambiguous ())\n-\tinsert_segment_resolution (outer_seg, res->get_node_id ());\n+\tinsert_segment_resolution (Usage (seg.node_id),\n+\t\t\t\t Definition (res->get_node_id ()));\n return res;\n }\n \n- return find_starting_point (segments, starting_point,\n-\t\t\t insert_segment_resolution, collect_errors)\n- .and_then (\n- [this, &segments, &starting_point, &insert_segment_resolution,\n- &collect_errors] (typename std::vector<S>::const_iterator iterator) {\n-\treturn resolve_segments (starting_point.get (), segments, iterator,\n-\t\t\t\t insert_segment_resolution, collect_errors);\n- })\n+ auto iterator = segments.begin ();\n+ if (can_descend)\n+ {\n+ if (auto res\n+\t = find_starting_point (segments, starting_point,\n+\t\t\t\t insert_segment_resolution, collect_errors))\n+\titerator = *res;\n+ else\n+\treturn tl::nullopt;\n+ }\n+\n+ return resolve_segments (starting_point.get (), segments, iterator,\n+\t\t\t insert_segment_resolution, collect_errors)\n .and_then ([this, &segments, &insert_segment_resolution] (\n \t\t Node &final_node) -> tl::optional<Rib::Definition> {\n // leave resolution within impl blocks to type checker\n if (final_node.rib.kind == Rib::Kind::TraitOrImpl)\n \treturn tl::nullopt;\n \n- auto &seg = unwrap_type_segment (segments.back ());\n- std::string seg_name = seg.as_string ();\n+ auto &seg = segments.back ();\n+ std::string seg_name = seg.name;\n \n- // assuming this can't be a lang item segment\n tl::optional<Rib::Definition> res\n \t= resolve_final_segment (final_node, seg_name,\n \t\t\t\t seg.is_lower_self_seg ());\n@@ -849,14 +855,16 @@ ForeverStack<N>::resolve_path (\n \t\t },\n \t\t false))\n \t\t{\n-\t\t insert_segment_resolution (segments.back (), kv.second.id);\n+\t\t insert_segment_resolution (Usage (seg.node_id),\n+\t\t\t\t\t Definition (kv.second.id));\n \t\t return Rib::Definition::NonShadowable (kv.second.id);\n \t\t}\n \t }\n \t}\n \n if (res && !res->is_ambiguous ())\n-\tinsert_segment_resolution (segments.back (), res->get_node_id ());\n+\tinsert_segment_resolution (Usage (seg.node_id),\n+\t\t\t\t Definition (res->get_node_id ()));\n \n return res;\n });\ndiff --git a/gcc/rust/resolve/rust-name-resolution-context.h b/gcc/rust/resolve/rust-name-resolution-context.h\nindex 2d1ce3117b5..91eb0dcde75 100644\n--- a/gcc/rust/resolve/rust-name-resolution-context.h\n+++ b/gcc/rust/resolve/rust-name-resolution-context.h\n@@ -16,8 +16,8 @@\n // along with GCC; see the file COPYING3. If not see\n // <http://www.gnu.org/licenses/>.\n \n-#ifndef RUST_NAME_RESOLVER_2_0_H\n-#define RUST_NAME_RESOLVER_2_0_H\n+#ifndef RUST_NAME_RESOLVER_2_0_CTX_H\n+#define RUST_NAME_RESOLVER_2_0_CTX_H\n \n #include \"optional.h\"\n #include \"rust-forever-stack.h\"\n@@ -25,6 +25,7 @@\n #include \"rust-rib.h\"\n #include \"rust-stacked-contexts.h\"\n #include \"rust-item.h\"\n+#include \"rust-name-resolution.h\"\n \n namespace Rust {\n namespace Resolver2_0 {\n@@ -136,28 +137,6 @@ change?\n correct\n */\n \n-// FIXME: Documentation\n-class Usage\n-{\n-public:\n- explicit Usage (NodeId id) : id (id) {}\n-\n- // TODO: move to name-resolution-ctx.cc\n- // storing it as a key in a map\n- bool operator< (const Usage other) const { return other.id < id; }\n-\n- NodeId id;\n-};\n-\n-// FIXME: Documentation\n-class Definition\n-{\n-public:\n- explicit Definition (NodeId id) : id (id) {}\n-\n- NodeId id;\n-};\n-\n struct IdentifierMode\n {\n bool is_ref;\n@@ -549,16 +528,14 @@ public:\n return canonical_ctx.get_path (id);\n }\n \n- template <typename S>\n tl::optional<Rib::Definition>\n- resolve_path (const std::vector<S> &segments, ResolutionMode mode,\n+ resolve_path (const ResolutionPath &path, ResolutionMode mode,\n \t\tstd::vector<Error> &collect_errors, Namespace ns)\n {\n- std::function<void (const S &, NodeId)> insert_segment_resolution\n- = [this] (const S &seg, NodeId id) {\n-\t auto seg_id = unwrap_segment_node_id (seg);\n-\t if (resolved_nodes.find (Usage (seg_id)) == resolved_nodes.end ())\n-\t map_usage (Usage (seg_id), Definition (id));\n+ std::function<void (Usage, Definition)> insert_segment_resolution\n+ = [this] (Usage seg_id, Definition id) {\n+\t if (resolved_nodes.find (seg_id) == resolved_nodes.end ())\n+\t map_usage (seg_id, id);\n \t};\n \n tl::optional<Rib::Definition> resolved = tl::nullopt;\n@@ -566,24 +543,20 @@ public:\n switch (ns)\n {\n case Namespace::Values:\n-\tresolved\n-\t = values.resolve_path (segments, mode, insert_segment_resolution,\n-\t\t\t\t collect_errors);\n+\tresolved = values.resolve_path (path, mode, insert_segment_resolution,\n+\t\t\t\t\tcollect_errors);\n \tbreak;\n case Namespace::Types:\n-\tresolved\n-\t = types.resolve_path (segments, mode, insert_segment_resolution,\n-\t\t\t\tcollect_errors);\n+\tresolved = types.resolve_path (path, mode, insert_segment_resolution,\n+\t\t\t\t collect_errors);\n \tbreak;\n case Namespace::Macros:\n-\tresolved\n-\t = macros.resolve_path (segments, mode, insert_segment_resolution,\n-\t\t\t\t collect_errors);\n+\tresolved = macros.resolve_path (path, mode, insert_segment_resolution,\n+\t\t\t\t\tcollect_errors);\n \tbreak;\n case Namespace::Labels:\n-\tresolved\n-\t = labels.resolve_path (segments, mode, insert_segment_resolution,\n-\t\t\t\t collect_errors);\n+\tresolved = labels.resolve_path (path, mode, insert_segment_resolution,\n+\t\t\t\t\tcollect_errors);\n \tbreak;\n default:\n \trust_unreachable ();\n@@ -596,20 +569,16 @@ public:\n \tswitch (ns)\n \t {\n \t case Namespace::Values:\n-\t return values.resolve_path (segments, mode,\n-\t\t\t\t\tinsert_segment_resolution,\n+\t return values.resolve_path (path, mode, insert_segment_resolution,\n \t\t\t\t\tcollect_errors, *prelude);\n \t case Namespace::Types:\n-\t return types.resolve_path (segments, mode,\n-\t\t\t\t insert_segment_resolution,\n+\t return types.resolve_path (path, mode, insert_segment_resolution,\n \t\t\t\t collect_errors, *prelude);\n \t case Namespace::Macros:\n-\t return macros.resolve_path (segments, mode,\n-\t\t\t\t\tinsert_segment_resolution,\n+\t return macros.resolve_path (path, mode, insert_segment_resolution,\n \t\t\t\t\tcollect_errors, *prelude);\n \t case Namespace::Labels:\n-\t return labels.resolve_path (segments, mode,\n-\t\t\t\t\tinsert_segment_resolution,\n+\t return labels.resolve_path (path, mode, insert_segment_resolution,\n \t\t\t\t\tcollect_errors, *prelude);\n \t default:\n \t rust_unreachable ();\n@@ -619,37 +588,122 @@ public:\n return resolved;\n }\n \n+ class ResolutionBuilder\n+ {\n+ public:\n+ ResolutionBuilder (NameResolutionContext &ctx) : ctx (&ctx) {}\n+\n+ template <typename S>\n+ void set_path (const std::vector<S> &path_segments, NodeId node_id,\n+\t\t bool has_opening_scope)\n+ {\n+ path = ResolutionPath (path_segments, node_id);\n+ mode = ResolutionMode::Normal;\n+ if (has_opening_scope)\n+\t{\n+\t if (get_rust_edition () == Edition::E2015)\n+\t mode = ResolutionMode::FromRoot;\n+\t else\n+\t mode = ResolutionMode::FromExtern;\n+\t}\n+ has_path_set = true;\n+ }\n+\n+ template <typename S>\n+ void set_path (const std::vector<S> &path_segments, NodeId node_id,\n+\t\t ResolutionMode mode)\n+ {\n+ path = ResolutionPath (path_segments, node_id);\n+ this->mode = mode;\n+ has_path_set = true;\n+ }\n+\n+ void set_path (const AST::SimplePath &path)\n+ {\n+ set_path (path.get_segments (), path.get_node_id (),\n+\t\tpath.has_opening_scope_resolution ());\n+ }\n+\n+ void set_path (const AST::PathInExpression &path)\n+ {\n+ set_path (path.get_segments (), path.get_node_id (),\n+\t\tpath.opening_scope_resolution ());\n+ }\n+\n+ void set_path (const AST::TypePath &path)\n+ {\n+ set_path (path.get_segments (), path.get_node_id (),\n+\t\tpath.has_opening_scope_resolution_op ());\n+ }\n+\n+ void set_mode (ResolutionMode mode) { this->mode = mode; }\n+\n+ void add_namespaces (Namespace ns) { namespace_list.push_back (ns); }\n+\n+ template <typename... Args> void add_namespaces (Namespace ns, Args... rest)\n+ {\n+ add_namespaces (ns);\n+ add_namespaces (rest...);\n+ }\n+\n+ void set_collect_errors (tl::optional<std::vector<Error> &> collect_errors)\n+ {\n+ this->collect_errors = collect_errors;\n+ }\n+\n+ tl::optional<Rib::Definition> resolve ()\n+ {\n+ rust_assert (has_path_set);\n+\n+ for (auto ns : namespace_list)\n+\t{\n+\t std::vector<Error> collect_errors_inner;\n+\t if (auto ret\n+\t = ctx->resolve_path (path, mode, collect_errors_inner, ns))\n+\t return ret;\n+\t if (!collect_errors_inner.empty ())\n+\t {\n+\t if (collect_errors.has_value ())\n+\t\t{\n+\t\t std::move (collect_errors_inner.begin (),\n+\t\t\t collect_errors_inner.end (),\n+\t\t\t std::back_inserter (collect_errors.value ()));\n+\t\t}\n+\t else\n+\t\t{\n+\t\t for (auto &e : collect_errors_inner)\n+\t\t e.emit ();\n+\t\t}\n+\t }\n+\t}\n+\n+ return tl::nullopt;\n+ }\n+\n+ private:\n+ ResolutionPath path;\n+ ResolutionMode mode;\n+ bool has_path_set;\n+\n+ std::vector<Namespace> namespace_list;\n+\n+ tl::optional<std::vector<Error> &> collect_errors;\n+\n+ NameResolutionContext *ctx;\n+ };\n+\n template <typename S, typename... Args>\n tl::optional<Rib::Definition>\n- resolve_path (const std::vector<S> &segments, ResolutionMode mode,\n+ resolve_path (const std::vector<S> &path_segments, ResolutionMode mode,\n \t\ttl::optional<std::vector<Error> &> collect_errors,\n \t\tNamespace ns_first, Args... ns_args)\n {\n- std::initializer_list<Namespace> namespaces = {ns_first, ns_args...};\n+ ResolutionBuilder builder (*this);\n+ builder.set_path (path_segments, UNKNOWN_NODEID, mode);\n+ builder.add_namespaces (ns_first, ns_args...);\n+ builder.set_collect_errors (collect_errors);\n \n- for (auto ns : namespaces)\n- {\n-\tstd::vector<Error> collect_errors_inner;\n-\tif (auto ret = resolve_path (segments, mode, collect_errors_inner, ns))\n-\t return ret;\n-\tif (!collect_errors_inner.empty ())\n-\t {\n-\t if (collect_errors.has_value ())\n-\t {\n-\t\tstd::move (collect_errors_inner.begin (),\n-\t\t\t collect_errors_inner.end (),\n-\t\t\t std::back_inserter (collect_errors.value ()));\n-\t }\n-\t else\n-\t {\n-\t\tfor (auto &e : collect_errors_inner)\n-\t\t e.emit ();\n-\t }\n-\t return tl::nullopt;\n-\t }\n- }\n-\n- return tl::nullopt;\n+ return builder.resolve ();\n }\n \n template <typename S, typename... Args>\n@@ -659,16 +713,13 @@ public:\n \t\ttl::optional<std::vector<Error> &> collect_errors,\n \t\tNamespace ns_first, Args... ns_args)\n {\n- auto mode = ResolutionMode::Normal;\n- if (has_opening_scope_resolution)\n- {\n-\tif (get_rust_edition () == Edition::E2015)\n-\t mode = ResolutionMode::FromRoot;\n-\telse\n-\t mode = ResolutionMode::FromExtern;\n- }\n- return resolve_path (path_segments, mode, collect_errors, ns_first,\n-\t\t\t ns_args...);\n+ ResolutionBuilder builder (*this);\n+ builder.set_path (path_segments, UNKNOWN_NODEID,\n+\t\t has_opening_scope_resolution);\n+ builder.add_namespaces (ns_first, ns_args...);\n+ builder.set_collect_errors (collect_errors);\n+\n+ return builder.resolve ();\n }\n \n template <typename S, typename... Args>\n@@ -677,8 +728,12 @@ public:\n \t\tbool has_opening_scope_resolution, Namespace ns_first,\n \t\tArgs... ns_args)\n {\n- return resolve_path (path_segments, has_opening_scope_resolution,\n-\t\t\t tl::nullopt, ns_first, ns_args...);\n+ ResolutionBuilder builder (*this);\n+ builder.set_path (path_segments, UNKNOWN_NODEID,\n+\t\t has_opening_scope_resolution);\n+ builder.add_namespaces (ns_first, ns_args...);\n+\n+ return builder.resolve ();\n }\n \n template <typename S, typename... Args>\n@@ -686,8 +741,11 @@ public:\n resolve_path (const std::vector<S> &path_segments, ResolutionMode mode,\n \t\tNamespace ns_first, Args... ns_args)\n {\n- return resolve_path (path_segments, mode, tl::nullopt, ns_first,\n-\t\t\t ns_args...);\n+ ResolutionBuilder builder (*this);\n+ builder.set_path (path_segments, UNKNOWN_NODEID, mode);\n+ builder.add_namespaces (ns_first, ns_args...);\n+\n+ return builder.resolve ();\n }\n \n template <typename... Args>\n@@ -727,4 +785,4 @@ private:\n } // namespace Resolver2_0\n } // namespace Rust\n \n-#endif // ! RUST_NAME_RESOLVER_2_0_H\n+#endif // ! RUST_NAME_RESOLVER_2_0_CTX_H\ndiff --git a/gcc/rust/resolve/rust-name-resolution.h b/gcc/rust/resolve/rust-name-resolution.h\nnew file mode 100644\nindex 00000000000..6d5b4ec874d\n--- /dev/null\n+++ b/gcc/rust/resolve/rust-name-resolution.h\n@@ -0,0 +1,50 @@\n+// Copyright (C) 2026 Free Software Foundation, Inc.\n+\n+// This file is part of GCC.\n+\n+// GCC is free software; you can redistribute it and/or modify it under\n+// the terms of the GNU General Public License as published by the Free\n+// Software Foundation; either version 3, or (at your option) any later\n+// version.\n+\n+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY\n+// WARRANTY; without even the implied warranty of MERCHANTABILITY or\n+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License\n+// for more details.\n+\n+// You should have received a copy of the GNU General Public License\n+// along with GCC; see the file COPYING3. If not see\n+// <http://www.gnu.org/licenses/>.\n+\n+#ifndef RUST_NAME_RESOLVER_2_0_H\n+#define RUST_NAME_RESOLVER_2_0_H\n+\n+namespace Rust {\n+namespace Resolver2_0 {\n+\n+// FIXME: Documentation\n+class Usage\n+{\n+public:\n+ explicit Usage (NodeId id) : id (id) {}\n+\n+ // TODO: move to name-resolution-ctx.cc\n+ // storing it as a key in a map\n+ bool operator< (const Usage other) const { return other.id < id; }\n+\n+ NodeId id;\n+};\n+\n+// FIXME: Documentation\n+class Definition\n+{\n+public:\n+ explicit Definition (NodeId id) : id (id) {}\n+\n+ NodeId id;\n+};\n+\n+} // namespace Resolver2_0\n+} // namespace Rust\n+\n+#endif // RUST_NAME_RESOLVER_2_0_H\ndiff --git a/gcc/rust/util/rust-unwrap-segment.h b/gcc/rust/util/rust-unwrap-segment.h\nindex 7181bd25379..0bebe287152 100644\n--- a/gcc/rust/util/rust-unwrap-segment.h\n+++ b/gcc/rust/util/rust-unwrap-segment.h\n@@ -16,6 +16,9 @@\n // along with GCC; see the file COPYING3. If not see\n // <http://www.gnu.org/licenses/>.\n \n+#ifndef RUST_UNWRAP_SEGMENT_H\n+#define RUST_UNWRAP_SEGMENT_H\n+\n #include \"rust-system.h\"\n #include \"optional.h\"\n #include \"rust-lang-item.h\"\n@@ -136,3 +139,5 @@ unwrap_segment_error_string (const AST::PathInExpression &path)\n }\n \n } // namespace Rust\n+\n+#endif // RUST_UNWRAP_SEGMENT_H\n", "prefixes": [ "COMMITTED", "02/43" ] }