Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2223300/?format=api
{ "id": 2223300, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2223300/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260414231905.191063-36-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-36-arthur.cohen@embecosm.com>", "date": "2026-04-14T23:18:57", "name": "[COMMITTED,36/43] gccrs: refactor function qualifier parsing", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "b00b8af12d7b43009444d14a8b9c912aac5672b2", "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-36-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/2223300/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2223300/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=HEBkUJRo;\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=HEBkUJRo", "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.52" ], "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 4fwL8W62Ljz1yCv\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 15 Apr 2026 09:29:31 +1000 (AEST)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 138BF4BA23F4\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 14 Apr 2026 23:29:30 +0000 (GMT)", "from mail-wm1-f52.google.com (mail-wm1-f52.google.com\n [209.85.128.52])\n by sourceware.org (Postfix) with ESMTPS id CE0B34BA23C2\n for <gcc-patches@gcc.gnu.org>; Tue, 14 Apr 2026 23:15:06 +0000 (GMT)", "by mail-wm1-f52.google.com with SMTP id\n 5b1f17b1804b1-483487335c2so67915415e9.2\n for <gcc-patches@gcc.gnu.org>; Tue, 14 Apr 2026 16:15:06 -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.15.03\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 14 Apr 2026 16:15:03 -0700 (PDT)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 138BF4BA23F4", "OpenDKIM Filter v2.11.0 sourceware.org CE0B34BA23C2" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org CE0B34BA23C2", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org CE0B34BA23C2", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776208507; cv=none;\n b=LOe4NjiuBrGlE2EQStjeUWwPKmsZcQdGGgFbGZfFGVYEzf50lx1p6CpPz4IJQImQdpt0LcDDHcLei7NvvTgSfEav2frr4CrSK1ifzwxVl4CL1L3BAUy5WkL3VJvvodEnMSD2Qr1OZTUoT3GYcBEJsUuoLV2Z2ohrO1wCIAJUrF0=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776208507; c=relaxed/simple;\n bh=Z/lqOfohV4qOAN8NbDuXYIhDeDliU5lKQCbcgZpoX4g=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=RlQXTlSyBhbhC8NuReJgpdtOX9Hd53V5MEyXXMkXbcLIJ6ydivrbVLeERUta87ZAQOa1pqvfD+8i+RnmESG9Brq4qkJ3gzSrVrif0WJ8UVcl+/WfIk+5CYWMHAmwBBImtSfiYjo1poo/ou4sVB9wE5/5SogMPJRXCOcz5wV+FZA=", "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=1776208505; x=1776813305; 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=V/8YcMqOf2uaCnwHMAhzAwRBeN/FDPKEv7rv/FoIAmQ=;\n b=HEBkUJRoy2s5lofUf8QLki0wCokiSLcja8GVpZaarkjwPoOYamGs3W97A+YqceY2a4\n AA3SgzNwy5TsyGx3PoS0lQqxZptObMY0+/8RIbbcC2h4f2lpo8ciWSbi8IfYFYK68cYN\n E4KVowYHSS5ruVTGM5z8s/wlp4fcuFHXVOks3Z8d4Jcg/n550zV5tQ7jpSdFvtA09Qem\n evhsDg4zJxbn1uNR0Z6ynlD/SvAzfT4japhj/qC5bj+gsMGbzUkPM6rzW79qbFIzBFxb\n FqjyKdMzh5juxRBNd1H81TXcea6G+N+tmtmfp0dK6AVIzcEFLrQl9ENZWFPgwFgIPfNl\n D7Dw==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776208505; x=1776813305;\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=V/8YcMqOf2uaCnwHMAhzAwRBeN/FDPKEv7rv/FoIAmQ=;\n b=D3xvh32hXEjX3bwLJEg63crtmXHzezbqs78vhf5ttQVQIr+BAqSuS2yf8lqf/pPnXJ\n NOjG/LH9xaXJaPF0s3nPRsG4ZFREG1NbkDTwBXCz5S8vyQfh/drsh7CWNpfjysGO3Uv2\n bH6RN45m/q3EjSnQp+Sdcckn4WHywB7pbRfkEC5voEwOf8qkG9JT1/81/saGvPNQHGtf\n 49WEvBXHrGXhU7YUHm3/pbw/vd4C7KzSaeJhyaefQXpQaXdi6w1I86CYXGdj8ScWpqOp\n HVR5Smbk/ANRqUjI/e+fh2nbzLIWeqTkVeN812+5mJx6AJeDLiqbYB9TaRXghZxzBN4m\n Q9Cg==", "X-Gm-Message-State": "AOJu0YxQX8/NIOuFJQZ54NRcbkrSta+cnw98tJBXl63YFJiUbBu5J3fg\n m+wUnzWilh995lsYeF6zfnT21kdG1nn6yJcdi7MRU1Tl9u/ukzaWisvv92A0zPxjeBzie6Fixjh\n wbY8IPg==", "X-Gm-Gg": "AeBDiescLUJODVyFdqM2NJUAm6YJkbgQUmvLH9ceviuUqs/w3FeRdPfpUt6S1jBsHof\n uQukSwLKZBcpzSxoLbrCj1aXfw8/mdFJTNYPMuMpf8gCAziYbVnV/5tfmTi6KU1kbu8V517mEuC\n cDh8nuX6fG7RbKYsekwHsyzBdyET8GY5TG7yB1tuWlcRGj2IfZo37Y9KjQnPr0ayIQsF6PvOKl4\n lREa85ykaon4dJjmbSQ4DG7wasKQKaFBD0D18JDxYsM3yiGrk7S4sT1i8KRJ4/XLD9RyvLjg0rM\n 3F2rNbu6WjD+KY5+Til9OYTKC75PXRC9PfUBeCzsGl7qVNrHzXjoS7qlrmZOQ1AcbGbXFJUmbZW\n lL6ylzbXVsOYLauTV3MGU7tI36wNlF2bdtetc0mwpVkUegYIpFBfjdqMV0ZnGQq93OiO8ijx8Ra\n Q2OGpBIIpc7LlT7sdThRAGLRmi6RwAkH4gRY55uvtLe9QlULwZjZFHmeAdqCdLsw3FPnAplwYhu\n k+Kow==", "X-Received": "by 2002:a05:600c:8284:b0:488:d228:a133 with SMTP id\n 5b1f17b1804b1-488d683d280mr252479375e9.14.1776208505486;\n Tue, 14 Apr 2026 16:15:05 -0700 (PDT)", "From": "arthur.cohen@embecosm.com", "To": "gcc-patches@gcc.gnu.org", "Cc": "gcc-rust@gcc.gnu.org,\n\tPhilipp Gesang <phg@phi-gamma.net>", "Subject": "[COMMITTED 36/43] gccrs: refactor function qualifier parsing", "Date": "Wed, 15 Apr 2026 01:18:57 +0200", "Message-ID": "<20260414231905.191063-36-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: Philipp Gesang <phg@phi-gamma.net>\n\ngcc/rust/ChangeLog\n\t* parse/rust-parse-impl.hxx: Refactor qualifier parsing\n\t* parse/rust-parse.h: (parse_function_qualifiers) Likewise\n\nSigned-off-by: Philipp Gesang <phg@phi-gamma.net>\n---\n gcc/rust/parse/rust-parse-impl.hxx | 236 ++++++++++++++++++-----------\n gcc/rust/parse/rust-parse.h | 16 +-\n 2 files changed, 159 insertions(+), 93 deletions(-)", "diff": "diff --git a/gcc/rust/parse/rust-parse-impl.hxx b/gcc/rust/parse/rust-parse-impl.hxx\nindex fc9f45a8e5c..97bd5b15e1f 100644\n--- a/gcc/rust/parse/rust-parse-impl.hxx\n+++ b/gcc/rust/parse/rust-parse-impl.hxx\n@@ -1638,7 +1638,7 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,\n }\n \n return std::unique_ptr<AST::Function> (new AST::Function (\n- std::move (function_name), std::move (*qualifiers.value ()),\n+ std::move (function_name), std::move (qualifiers.value ()),\n std::move (generic_params), std::move (function_params),\n std::move (return_type), std::move (where_clause), std::move (body),\n std::move (vis), std::move (outer_attrs), locus, is_external));\n@@ -1646,93 +1646,146 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,\n \n // Parses function or method qualifiers (i.e. const, unsafe, and extern).\n template <typename ManagedTokenSource>\n-tl::expected<std::unique_ptr<AST::FunctionQualifiers>, Parse::Error::Node>\n+tl::expected<AST::FunctionQualifiers, Parse::Error::Node>\n Parser<ManagedTokenSource>::parse_function_qualifiers ()\n+{\n+ location_t locus = lexer.peek_token ()->get_locus ();\n+\n+ auto parsed = parse_function_qualifiers_raw (locus);\n+ if (!parsed)\n+ return tl::unexpected<Parse::Error::Node> (parsed.error ());\n+\n+ return function_qualifiers_from_keywords (locus, std::move (parsed->first),\n+\t\t\t\t\t std::move (parsed->second));\n+}\n+\n+// Take the list of parsed function qualifiers and convert it to\n+// the corrresponding flags to pass to the AST item constructor.\n+//\n+// This assumes ``keywords`` contains only those tokens that\n+// map to qualifiers.\n+template <typename ManagedTokenSource>\n+tl::expected<AST::FunctionQualifiers, Parse::Error::Node>\n+Parser<ManagedTokenSource>::function_qualifiers_from_keywords (\n+ location_t locus, const std::vector<TokenId> keywords, std::string abi)\n {\n Default default_status = Default::No;\n Async async_status = Async::No;\n Const const_status = Const::No;\n Unsafety unsafe_status = Unsafety::Normal;\n bool has_extern = false;\n- std::string abi;\n \n- // collect all qualifiers before checking the order to allow for a better\n- // error message\n- std::vector<TokenId> found_order;\n+ for (auto qualifier : keywords)\n+ {\n+ switch (qualifier)\n+\t{\n+\tcase IDENTIFIER:\n+\t // only \"default\" is valid in this context\n+\t default_status = Default::Yes;\n+\t continue;\n+\tcase CONST:\n+\t const_status = Const::Yes;\n+\t continue;\n+\tcase ASYNC:\n+\t async_status = Async::Yes;\n+\t continue;\n+\tcase UNSAFE:\n+\t unsafe_status = Unsafety::Unsafe;\n+\t continue;\n+\tcase EXTERN_KW:\n+\t has_extern = true;\n+\t continue;\n+\tdefault:\n+\t // non-qualifier token in input\n+\t rust_unreachable ();\n+\t}\n+ }\n \n- const_TokenPtr t;\n- location_t locus = lexer.peek_token ()->get_locus ();\n+ return AST::FunctionQualifiers (locus, default_status, async_status,\n+\t\t\t\t const_status, unsafe_status, has_extern,\n+\t\t\t\t std::move (abi));\n+}\n+\n+// this consumes as many function qualifier tokens while ensuring\n+// uniqueness.\n+template <typename ManagedTokenSource>\n+tl::expected<std::pair<std::vector<TokenId>, std::string>, Parse::Error::Node>\n+Parser<ManagedTokenSource>::parse_function_qualifiers_raw (location_t locus)\n+{\n+ std::vector<TokenId> found_order;\n+ std::string abi;\n \n // this will terminate on duplicates or the first non-qualifier token\n while (true)\n {\n- const TokenId token_id = lexer.peek_token ()->get_id ();\n-\n- if (std::find (found_order.cbegin (), found_order.cend (), token_id)\n-\t != found_order.cend ())\n-\t{\n-\t // qualifiers mustn't appear twice\n-\t Error error (lexer.peek_token ()->get_locus (),\n-\t\t \"encountered duplicate function qualifier %qs\",\n-\t\t lexer.peek_token ()->get_token_description ());\n-\t add_error (std::move (error));\n-\n-\t return tl::unexpected<Parse::Error::Node> (\n-\t Parse::Error::Node::MALFORMED);\n-\t}\n+ auto token = lexer.peek_token ();\n+ const TokenId token_id = token->get_id ();\n+ location_t locus = lexer.peek_token ()->get_locus ();\n \n switch (token_id)\n \t{\n \tcase IDENTIFIER:\n-\t if (lexer.peek_token ()->get_str () != Values::WeakKeywords::DEFAULT)\n+\t if (token->get_str () != Values::WeakKeywords::DEFAULT)\n \t {\n-\t // only \"default\" is valid in this context\n+\t // only \"default\" is valid in this context, so this must\n+\t // be a non-qualifier keyword\n \t goto done;\n \t }\n-\t default_status = Default::Yes;\n-\t break;\n+\t // fallthrough\n \tcase CONST:\n-\t const_status = Const::Yes;\n-\t break;\n \tcase ASYNC:\n-\t async_status = Async::Yes;\n-\t break;\n \tcase UNSAFE:\n-\t unsafe_status = Unsafety::Unsafe;\n+\t found_order.push_back (token_id);\n+\t lexer.skip_token ();\n \t break;\n \tcase EXTERN_KW:\n \t {\n-\t has_extern = true;\n-\t // detect optional abi name\n+\t found_order.push_back (token_id);\n \t lexer.skip_token ();\n+\n+\t // detect optional abi name\n \t const_TokenPtr next_tok = lexer.peek_token ();\n \t if (next_tok->get_id () == STRING_LITERAL)\n \t {\n \t\tabi = next_tok->get_str ();\n+\t\tlexer.skip_token ();\n \t }\n \t }\n \t break;\n \tdefault:\n+\t // non-qualifier keyword\n \t goto done;\n \t}\n- found_order.push_back (token_id);\n- lexer.skip_token ();\n+\n+ if (std::count (found_order.cbegin (), found_order.cend (), token_id) > 1)\n+\t{\n+\t // qualifiers mustn't appear twice\n+\t Error error (locus, \"encountered duplicate function qualifier %qs\",\n+\t\t token->get_token_description ());\n+\t add_error (std::move (error));\n+\n+\t return tl::unexpected<Parse::Error::Node> (\n+\t Parse::Error::Node::MALFORMED);\n+\t}\n }\n done:\n \n- if (!ensure_function_qualifier_order (locus, std::move (found_order)))\n+ if (!ensure_function_qualifier_order (locus, found_order))\n return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);\n \n- return std::unique_ptr<AST::FunctionQualifiers> (\n- new AST::FunctionQualifiers (locus, default_status, async_status,\n-\t\t\t\t const_status, unsafe_status, has_extern,\n-\t\t\t\t std::move (abi)));\n+ return make_pair (found_order, abi);\n }\n \n+// Validate the order of the list of function qualifiers; this assumes that\n+// ``found_order`` consists only of function qualifier tokens.\n+//\n+// If the order is illegal, the generated error message gives both the wrong\n+// order as found in the source and the correct order according to Rust syntax\n+// rules.\n template <typename ManagedTokenSource>\n bool\n Parser<ManagedTokenSource>::ensure_function_qualifier_order (\n- location_t locus, std::vector<TokenId> found_order)\n+ location_t locus, const std::vector<TokenId> &found_order)\n {\n // Check in order of default, const, async, unsafe, extern\n auto token_priority = [] (const TokenId id) {\n@@ -1759,62 +1812,65 @@ Parser<ManagedTokenSource>::ensure_function_qualifier_order (\n const size_t priority = token_priority (token_id);\n if (priority <= last_priority)\n \t{\n-\t auto qualifiers_to_str = [] (const std::vector<TokenId> &token_ids) {\n-\t std::ostringstream ss;\n+\t emit_function_qualifier_order_error_msg (locus, found_order);\n+\t return false;\n+\t}\n \n-\t for (auto id : token_ids)\n-\t {\n-\t\tif (ss.tellp () != 0)\n-\t\t ss << ' ';\n+ last_priority = priority;\n+ }\n \n-\t\tif (id == IDENTIFIER)\n-\t\t ss << Values::WeakKeywords::DEFAULT;\n-\t\telse\n-\t\t ss << token_id_keyword_string (id);\n-\t }\n+ return true;\n+}\n \n-\t return ss.str ();\n-\t };\n+template <typename ManagedTokenSource>\n+void\n+Parser<ManagedTokenSource>::emit_function_qualifier_order_error_msg (\n+ location_t locus, const std::vector<TokenId> &found_order)\n+{\n+ std::vector<TokenId> expected_order\n+ = {IDENTIFIER, CONST, ASYNC, UNSAFE, EXTERN_KW};\n \n-\t std::vector<TokenId> expected_order\n-\t = {IDENTIFIER, CONST, ASYNC, UNSAFE, EXTERN_KW};\n+ // we only keep the qualifiers actually used in the offending code\n+ std::vector<TokenId>::iterator token_id = expected_order.begin ();\n+ while (token_id != expected_order.end ())\n+ {\n+ if (std::find (found_order.cbegin (), found_order.cend (), *token_id)\n+\t == found_order.cend ())\n+\t{\n+\t token_id = expected_order.erase (token_id);\n+\t}\n+ else\n+\t{\n+\t ++token_id;\n+\t}\n+ }\n \n-\t // we only keep the qualifiers actually used in the offending code\n-\t std::vector<TokenId>::const_iterator token_id\n-\t = expected_order.cbegin ();\n-\t while (token_id != expected_order.cend ())\n-\t {\n-\t if (std::find (found_order.cbegin (), found_order.cend (),\n-\t\t\t *token_id)\n-\t\t == found_order.cend ())\n-\t\t{\n-\t\t token_id = expected_order.erase (token_id);\n-\t\t}\n-\t else\n-\t\t{\n-\t\t ++token_id;\n-\t\t}\n-\t }\n+ auto qualifiers_to_str = [] (const std::vector<TokenId> &token_ids) {\n+ std::ostringstream ss;\n \n-\t const std::string found_qualifiers = qualifiers_to_str (found_order);\n-\t const std::string expected_qualifiers\n-\t = qualifiers_to_str (expected_order);\n+ for (auto id : token_ids)\n+ {\n+\tif (ss.tellp () != 0)\n+\t ss << ' ';\n \n-\t location_t error_locus\n-\t = make_location (locus, locus, lexer.peek_token ()->get_locus ());\n-\t Error error (\n-\t error_locus,\n-\t \"invalid order of function qualifiers; found %qs, expected %qs\",\n-\t found_qualifiers.c_str (), expected_qualifiers.c_str ());\n-\t add_error (std::move (error));\n+\tif (id == IDENTIFIER)\n+\t ss << Values::WeakKeywords::DEFAULT;\n+\telse\n+\t ss << token_id_keyword_string (id);\n+ }\n \n-\t return false;\n-\t}\n+ return ss.str ();\n+ };\n \n- last_priority = priority;\n- }\n+ const std::string found_qualifiers = qualifiers_to_str (found_order);\n+ const std::string expected_qualifiers = qualifiers_to_str (expected_order);\n \n- return true;\n+ location_t error_locus\n+ = make_location (locus, locus, lexer.peek_token ()->get_locus ());\n+ Error error (error_locus,\n+\t \"invalid order of function qualifiers; found %qs, expected %qs\",\n+\t found_qualifiers.c_str (), expected_qualifiers.c_str ());\n+ add_error (std::move (error));\n }\n \n // Parses generic (lifetime or type) params inside angle brackets (optional).\n@@ -4479,7 +4535,7 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (\n }\n \n return std::unique_ptr<AST::Function> (\n- new AST::Function (std::move (ident), std::move (*qualifiers.value ()),\n+ new AST::Function (std::move (ident), std::move (qualifiers.value ()),\n \t\t std::move (generic_params), std::move (function_params),\n \t\t std::move (return_type), std::move (where_clause),\n \t\t std::move (body), std::move (vis),\n@@ -4709,7 +4765,7 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (\n }\n \n return std::unique_ptr<AST::Function> (\n- new AST::Function (std::move (ident), std::move (*qualifiers.value ()),\n+ new AST::Function (std::move (ident), std::move (qualifiers.value ()),\n \t\t std::move (generic_params), std::move (function_params),\n \t\t std::move (return_type), std::move (where_clause),\n \t\t std::move (body), std::move (vis),\n@@ -6407,7 +6463,7 @@ Parser<ManagedTokenSource>::parse_bare_function_type (\n }\n \n return std::unique_ptr<AST::BareFunctionType> (new AST::BareFunctionType (\n- std::move (for_lifetimes), std::move (*qualifiers.value ()),\n+ std::move (for_lifetimes), std::move (qualifiers.value ()),\n std::move (params), is_variadic, std::move (variadic_attrs),\n std::move (return_type), best_try_locus));\n }\ndiff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h\nindex 8df9904766a..dac39da3660 100644\n--- a/gcc/rust/parse/rust-parse.h\n+++ b/gcc/rust/parse/rust-parse.h\n@@ -364,10 +364,20 @@ private:\n std::unique_ptr<AST::Function> parse_function (AST::Visibility vis,\n \t\t\t\t\t\t AST::AttrVec outer_attrs,\n \t\t\t\t\t\t bool is_external = false);\n- tl::expected<std::unique_ptr<AST::FunctionQualifiers>, Parse::Error::Node>\n+ tl::expected<AST::FunctionQualifiers, Parse::Error::Node>\n parse_function_qualifiers ();\n- bool ensure_function_qualifier_order (location_t locus,\n-\t\t\t\t\tstd::vector<TokenId> found_order);\n+ tl::expected<std::pair<std::vector<TokenId>, std::string>, Parse::Error::Node>\n+ parse_function_qualifiers_raw (location_t locus);\n+ bool\n+ ensure_function_qualifier_order (location_t locus,\n+\t\t\t\t const std::vector<TokenId> &found_order);\n+ tl::expected<AST::FunctionQualifiers, Parse::Error::Node>\n+ function_qualifiers_from_keywords (location_t locus,\n+\t\t\t\t std::vector<TokenId> keywords,\n+\t\t\t\t std::string abi);\n+ void emit_function_qualifier_order_error_msg (\n+ location_t locus, const std::vector<TokenId> &found_order);\n+\n std::vector<std::unique_ptr<AST::GenericParam>>\n parse_generic_params_in_angles ();\n template <typename EndTokenPred>\n", "prefixes": [ "COMMITTED", "36/43" ] }