@@ -1638,101 +1638,154 @@ Parser<ManagedTokenSource>::parse_function (AST::Visibility vis,
16381638 }
16391639
16401640 return std::unique_ptr<AST::Function> (new AST::Function (
1641- std::move (function_name), std::move (* qualifiers.value ()),
1641+ std::move (function_name), std::move (qualifiers.value ()),
16421642 std::move (generic_params), std::move (function_params),
16431643 std::move (return_type), std::move (where_clause), std::move (body),
16441644 std::move (vis), std::move (outer_attrs), locus, is_external));
16451645}
16461646
16471647// Parses function or method qualifiers (i.e. const, unsafe, and extern).
16481648template <typename ManagedTokenSource>
1649- tl::expected<std::unique_ptr< AST::FunctionQualifiers> , Parse::Error::Node>
1649+ tl::expected<AST::FunctionQualifiers, Parse::Error::Node>
16501650Parser<ManagedTokenSource>::parse_function_qualifiers ()
1651+ {
1652+ location_t locus = lexer.peek_token ()->get_locus ();
1653+
1654+ auto parsed = parse_function_qualifiers_raw (locus);
1655+ if (!parsed)
1656+ return tl::unexpected<Parse::Error::Node> (parsed.error ());
1657+
1658+ return function_qualifiers_from_keywords (locus, std::move (parsed->first ),
1659+ std::move (parsed->second ));
1660+ }
1661+
1662+ // Take the list of parsed function qualifiers and convert it to
1663+ // the corrresponding flags to pass to the AST item constructor.
1664+ //
1665+ // This assumes ``keywords`` contains only those tokens that
1666+ // map to qualifiers.
1667+ template <typename ManagedTokenSource>
1668+ tl::expected<AST::FunctionQualifiers, Parse::Error::Node>
1669+ Parser<ManagedTokenSource>::function_qualifiers_from_keywords (
1670+ location_t locus, const std::vector<TokenId> keywords, std::string abi)
16511671{
16521672 Default default_status = Default::No;
16531673 Async async_status = Async::No;
16541674 Const const_status = Const::No;
16551675 Unsafety unsafe_status = Unsafety::Normal;
16561676 bool has_extern = false ;
1657- std::string abi;
16581677
1659- // collect all qualifiers before checking the order to allow for a better
1660- // error message
1661- std::vector<TokenId> found_order;
1678+ for (auto qualifier : keywords)
1679+ {
1680+ switch (qualifier)
1681+ {
1682+ case IDENTIFIER:
1683+ // only "default" is valid in this context
1684+ default_status = Default::Yes;
1685+ continue ;
1686+ case CONST:
1687+ const_status = Const::Yes;
1688+ continue ;
1689+ case ASYNC:
1690+ async_status = Async::Yes;
1691+ continue ;
1692+ case UNSAFE:
1693+ unsafe_status = Unsafety::Unsafe;
1694+ continue ;
1695+ case EXTERN_KW:
1696+ has_extern = true ;
1697+ continue ;
1698+ default :
1699+ // non-qualifier token in input
1700+ rust_unreachable ();
1701+ }
1702+ }
16621703
1663- const_TokenPtr t;
1664- location_t locus = lexer.peek_token ()->get_locus ();
1704+ return AST::FunctionQualifiers (locus, default_status, async_status,
1705+ const_status, unsafe_status, has_extern,
1706+ std::move (abi));
1707+ }
1708+
1709+ // this consumes as many function qualifier tokens while ensuring
1710+ // uniqueness.
1711+ template <typename ManagedTokenSource>
1712+ tl::expected<std::pair<std::vector<TokenId>, std::string>, Parse::Error::Node>
1713+ Parser<ManagedTokenSource>::parse_function_qualifiers_raw (location_t locus)
1714+ {
1715+ std::vector<TokenId> found_order;
1716+ std::string abi;
16651717
16661718 // this will terminate on duplicates or the first non-qualifier token
16671719 while (true )
16681720 {
1669- const TokenId token_id = lexer.peek_token ()->get_id ();
1670-
1671- if (std::find (found_order.cbegin (), found_order.cend (), token_id)
1672- != found_order.cend ())
1673- {
1674- // qualifiers mustn't appear twice
1675- Error error (lexer.peek_token ()->get_locus (),
1676- " encountered duplicate function qualifier %qs" ,
1677- lexer.peek_token ()->get_token_description ());
1678- add_error (std::move (error));
1679-
1680- return tl::unexpected<Parse::Error::Node> (
1681- Parse::Error::Node::MALFORMED);
1682- }
1721+ auto token = lexer.peek_token ();
1722+ const TokenId token_id = token->get_id ();
1723+ location_t locus = lexer.peek_token ()->get_locus ();
16831724
16841725 switch (token_id)
16851726 {
16861727 case IDENTIFIER:
1687- if (lexer. peek_token () ->get_str () != Values::WeakKeywords::DEFAULT)
1728+ if (token ->get_str () != Values::WeakKeywords::DEFAULT)
16881729 {
1689- // only "default" is valid in this context
1730+ // only "default" is valid in this context, so this must
1731+ // be a non-qualifier keyword
16901732 goto done;
16911733 }
1692- default_status = Default::Yes;
1693- break ;
1734+ // fallthrough
16941735 case CONST:
1695- const_status = Const::Yes;
1696- break ;
16971736 case ASYNC:
1698- async_status = Async::Yes;
1699- break ;
17001737 case UNSAFE:
1701- unsafe_status = Unsafety::Unsafe;
1738+ found_order.push_back (token_id);
1739+ lexer.skip_token ();
17021740 break ;
17031741 case EXTERN_KW:
17041742 {
1705- has_extern = true ;
1706- // detect optional abi name
1743+ found_order.push_back (token_id);
17071744 lexer.skip_token ();
1745+
1746+ // detect optional abi name
17081747 const_TokenPtr next_tok = lexer.peek_token ();
17091748 if (next_tok->get_id () == STRING_LITERAL)
17101749 {
17111750 abi = next_tok->get_str ();
1751+ lexer.skip_token ();
17121752 }
17131753 }
17141754 break ;
17151755 default :
1756+ // non-qualifier keyword
17161757 goto done;
17171758 }
1718- found_order.push_back (token_id);
1719- lexer.skip_token ();
1759+
1760+ if (std::count (found_order.cbegin (), found_order.cend (), token_id) > 1 )
1761+ {
1762+ // qualifiers mustn't appear twice
1763+ Error error (locus, " encountered duplicate function qualifier %qs" ,
1764+ token->get_token_description ());
1765+ add_error (std::move (error));
1766+
1767+ return tl::unexpected<Parse::Error::Node> (
1768+ Parse::Error::Node::MALFORMED);
1769+ }
17201770 }
17211771done:
17221772
1723- if (!ensure_function_qualifier_order (locus, std::move ( found_order) ))
1773+ if (!ensure_function_qualifier_order (locus, found_order))
17241774 return tl::unexpected<Parse::Error::Node> (Parse::Error::Node::MALFORMED);
17251775
1726- return std::unique_ptr<AST::FunctionQualifiers> (
1727- new AST::FunctionQualifiers (locus, default_status, async_status,
1728- const_status, unsafe_status, has_extern,
1729- std::move (abi)));
1776+ return make_pair (found_order, abi);
17301777}
17311778
1779+ // Validate the order of the list of function qualifiers; this assumes that
1780+ // ``found_order`` consists only of function qualifier tokens.
1781+ //
1782+ // If the order is illegal, the generated error message gives both the wrong
1783+ // order as found in the source and the correct order according to Rust syntax
1784+ // rules.
17321785template <typename ManagedTokenSource>
17331786bool
17341787Parser<ManagedTokenSource>::ensure_function_qualifier_order (
1735- location_t locus, std::vector<TokenId> found_order)
1788+ location_t locus, const std::vector<TokenId> & found_order)
17361789{
17371790 // Check in order of default, const, async, unsafe, extern
17381791 auto token_priority = [] (const TokenId id) {
@@ -1759,62 +1812,65 @@ Parser<ManagedTokenSource>::ensure_function_qualifier_order (
17591812 const size_t priority = token_priority (token_id);
17601813 if (priority <= last_priority)
17611814 {
1762- auto qualifiers_to_str = [] (const std::vector<TokenId> &token_ids) {
1763- std::ostringstream ss;
1815+ emit_function_qualifier_order_error_msg (locus, found_order);
1816+ return false ;
1817+ }
17641818
1765- for (auto id : token_ids)
1766- {
1767- if (ss.tellp () != 0 )
1768- ss << ' ' ;
1819+ last_priority = priority;
1820+ }
17691821
1770- if (id == IDENTIFIER)
1771- ss << Values::WeakKeywords::DEFAULT;
1772- else
1773- ss << token_id_keyword_string (id);
1774- }
1822+ return true ;
1823+ }
17751824
1776- return ss.str ();
1777- };
1825+ template <typename ManagedTokenSource>
1826+ void
1827+ Parser<ManagedTokenSource>::emit_function_qualifier_order_error_msg (
1828+ location_t locus, const std::vector<TokenId> &found_order)
1829+ {
1830+ std::vector<TokenId> expected_order
1831+ = {IDENTIFIER, CONST, ASYNC, UNSAFE, EXTERN_KW};
17781832
1779- std::vector<TokenId> expected_order
1780- = {IDENTIFIER, CONST, ASYNC, UNSAFE, EXTERN_KW};
1833+ // we only keep the qualifiers actually used in the offending code
1834+ std::vector<TokenId>::iterator token_id = expected_order.begin ();
1835+ while (token_id != expected_order.end ())
1836+ {
1837+ if (std::find (found_order.cbegin (), found_order.cend (), *token_id)
1838+ == found_order.cend ())
1839+ {
1840+ token_id = expected_order.erase (token_id);
1841+ }
1842+ else
1843+ {
1844+ ++token_id;
1845+ }
1846+ }
17811847
1782- // we only keep the qualifiers actually used in the offending code
1783- std::vector<TokenId>::const_iterator token_id
1784- = expected_order.cbegin ();
1785- while (token_id != expected_order.cend ())
1786- {
1787- if (std::find (found_order.cbegin (), found_order.cend (),
1788- *token_id)
1789- == found_order.cend ())
1790- {
1791- token_id = expected_order.erase (token_id);
1792- }
1793- else
1794- {
1795- ++token_id;
1796- }
1797- }
1848+ auto qualifiers_to_str = [] (const std::vector<TokenId> &token_ids) {
1849+ std::ostringstream ss;
17981850
1799- const std::string found_qualifiers = qualifiers_to_str (found_order);
1800- const std::string expected_qualifiers
1801- = qualifiers_to_str (expected_order);
1851+ for (auto id : token_ids)
1852+ {
1853+ if (ss.tellp () != 0 )
1854+ ss << ' ' ;
18021855
1803- location_t error_locus
1804- = make_location (locus, locus, lexer.peek_token ()->get_locus ());
1805- Error error (
1806- error_locus,
1807- " invalid order of function qualifiers; found %qs, expected %qs" ,
1808- found_qualifiers.c_str (), expected_qualifiers.c_str ());
1809- add_error (std::move (error));
1856+ if (id == IDENTIFIER)
1857+ ss << Values::WeakKeywords::DEFAULT;
1858+ else
1859+ ss << token_id_keyword_string (id);
1860+ }
18101861
1811- return false ;
1812- }
1862+ return ss. str () ;
1863+ };
18131864
1814- last_priority = priority ;
1815- }
1865+ const std::string found_qualifiers = qualifiers_to_str (found_order) ;
1866+ const std::string expected_qualifiers = qualifiers_to_str (expected_order);
18161867
1817- return true ;
1868+ location_t error_locus
1869+ = make_location (locus, locus, lexer.peek_token ()->get_locus ());
1870+ Error error (error_locus,
1871+ " invalid order of function qualifiers; found %qs, expected %qs" ,
1872+ found_qualifiers.c_str (), expected_qualifiers.c_str ());
1873+ add_error (std::move (error));
18181874}
18191875
18201876// Parses generic (lifetime or type) params inside angle brackets (optional).
@@ -4479,7 +4535,7 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method (
44794535 }
44804536
44814537 return std::unique_ptr<AST::Function> (
4482- new AST::Function (std::move (ident), std::move (* qualifiers.value ()),
4538+ new AST::Function (std::move (ident), std::move (qualifiers.value ()),
44834539 std::move (generic_params), std::move (function_params),
44844540 std::move (return_type), std::move (where_clause),
44854541 std::move (body), std::move (vis),
@@ -4709,7 +4765,7 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method (
47094765 }
47104766
47114767 return std::unique_ptr<AST::Function> (
4712- new AST::Function (std::move (ident), std::move (* qualifiers.value ()),
4768+ new AST::Function (std::move (ident), std::move (qualifiers.value ()),
47134769 std::move (generic_params), std::move (function_params),
47144770 std::move (return_type), std::move (where_clause),
47154771 std::move (body), std::move (vis),
@@ -6407,7 +6463,7 @@ Parser<ManagedTokenSource>::parse_bare_function_type (
64076463 }
64086464
64096465 return std::unique_ptr<AST::BareFunctionType> (new AST::BareFunctionType (
6410- std::move (for_lifetimes), std::move (* qualifiers.value ()),
6466+ std::move (for_lifetimes), std::move (qualifiers.value ()),
64116467 std::move (params), is_variadic, std::move (variadic_attrs),
64126468 std::move (return_type), best_try_locus));
64136469}
0 commit comments