From af7f140f2f17b5290ec09266329bd719a7d49d99 Mon Sep 17 00:00:00 2001 From: Arthur Cohen Date: Mon, 20 Jun 2022 11:22:11 +0200 Subject: ast: Allow disambiguation of ConstGenericArgs to const generic arguments At the AST level, we might encounter situations where const generic arguments are ambiguous: They could be resolved to either a type or a const expression, as shown in this example: ```rust let a: Foo; // what is N? A type? A const? The parser doesn't know ``` However, when parsing default expressions for const generic parameters, we need to be able to disambiguate to const expressions early: ```rust struct Foo { /* ... */ } ``` In that code, `M` could be considered ambiguous: Is it a type? a const? A random non-const variable? What matters is that we disambiguate it to a const generic argument, so that it errors out appropriately in later phases of the compiler. In that case, we need to go from a `ConstArg::Ambiguous("M")` to a `ConstArg::Clear(IdentifierExpr("M"))`. In later passes of the compiler, we will also need to disambiguate to types. But that will be done at the HIR/Resolving level. --- gcc/rust/ast/rust-ast-full-test.cc | 38 +++++++++++++++++++++++++------------- gcc/rust/ast/rust-path.h | 6 ++++++ 2 files changed, 31 insertions(+), 13 deletions(-) (limited to 'gcc/rust/ast') diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index 7f66ee4..0d4d36b 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -4096,10 +4096,10 @@ DelimTokenTree::parse_to_meta_item () const /* assume top-level delim token tree in attribute - convert all nested ones * to token stream */ - std::vector > token_stream = to_token_stream (); + std::vector> token_stream = to_token_stream (); AttributeParser parser (std::move (token_stream)); - std::vector > meta_items ( + std::vector> meta_items ( parser.parse_meta_item_seq ()); return new AttrInputMetaItemContainer (std::move (meta_items)); @@ -4282,7 +4282,7 @@ AttributeParser::parse_path_meta_item () switch (peek_token ()->get_id ()) { case LEFT_PAREN: { - std::vector > meta_items + std::vector> meta_items = parse_meta_item_seq (); return std::unique_ptr ( @@ -4320,11 +4320,11 @@ AttributeParser::parse_path_meta_item () /* Parses a parenthesised sequence of meta item inners. Parentheses are * required here. */ -std::vector > +std::vector> AttributeParser::parse_meta_item_seq () { int vec_length = token_stream.size (); - std::vector > meta_items; + std::vector> meta_items; if (peek_token ()->get_id () != LEFT_PAREN) { @@ -4364,13 +4364,13 @@ AttributeParser::parse_meta_item_seq () /* Collects any nested token trees into a flat token stream, suitable for * parsing. */ -std::vector > +std::vector> DelimTokenTree::to_token_stream () const { - std::vector > tokens; + std::vector> tokens; for (const auto &tree : token_trees) { - std::vector > stream = tree->to_token_stream (); + std::vector> stream = tree->to_token_stream (); tokens.insert (tokens.end (), std::make_move_iterator (stream.begin ()), std::make_move_iterator (stream.end ())); @@ -4711,12 +4711,12 @@ MetaItemPathLit::check_cfg_predicate (const Session &session) const lit.as_string ()); } -std::vector > +std::vector> Token::to_token_stream () const { /* initialisation list doesn't work as it needs copy constructor, so have to * do this */ - std::vector > dummy_vector; + std::vector> dummy_vector; dummy_vector.reserve (1); dummy_vector.push_back (std::unique_ptr (clone_token_impl ())); return dummy_vector; @@ -4744,7 +4744,7 @@ MetaItemPath::to_attribute () const Attribute MetaItemSeq::to_attribute () const { - std::vector > new_seq; + std::vector> new_seq; new_seq.reserve (seq.size ()); for (const auto &e : seq) new_seq.push_back (e->clone_meta_item_inner ()); @@ -4768,7 +4768,7 @@ MetaListPaths::to_attribute () const * no longer known). If conversions back are required, might have to do a * "check all are paths" pass or something. */ - std::vector > new_seq; + std::vector> new_seq; new_seq.reserve (paths.size ()); for (const auto &e : paths) new_seq.push_back (std::unique_ptr (new MetaItemPath (e))); @@ -4782,7 +4782,7 @@ MetaListPaths::to_attribute () const Attribute MetaListNameValueStr::to_attribute () const { - std::vector > new_seq; + std::vector> new_seq; new_seq.reserve (strs.size ()); for (const auto &e : strs) new_seq.push_back ( @@ -5792,5 +5792,17 @@ MetaWord::accept_vis (ASTVisitor &vis) { vis.visit (*this); } + +ConstGenericArg +ConstGenericArg::disambiguate_to_const () const +{ + rust_assert (get_kind () == Kind::Ambiguous); + + // FIXME: is it fine to have no outer attributes? + return ConstGenericArg (std::unique_ptr ( + new IdentifierExpr (path, {}, locus)), + locus); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 6e2b020..d2d925a 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -208,6 +208,12 @@ public: return ""; } + /** + * Disambiguate an amibguous const generic argument or generic type argument + * to a const generic argument, unequivocally + */ + ConstGenericArg disambiguate_to_const () const; + private: ConstGenericArg (std::unique_ptr expression, Identifier path, Kind kind, Location locus) -- cgit v1.1