aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/parse/rust-parse-impl.h
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-06-17 16:11:19 +0000
committerGitHub <noreply@github.com>2022-06-17 16:11:19 +0000
commitc0f11672d760513256997f325da678016d13f677 (patch)
treeec8da7465f391924e34855f3f2ae812e6ad811e3 /gcc/rust/parse/rust-parse-impl.h
parentb711799e3eb450463a9f3be3b082b3ced9356358 (diff)
parent5f3c8286b225f3c87bed920f3c3e003a90d98722 (diff)
downloadgcc-c0f11672d760513256997f325da678016d13f677.zip
gcc-c0f11672d760513256997f325da678016d13f677.tar.gz
gcc-c0f11672d760513256997f325da678016d13f677.tar.bz2
Merge #1317
1317: AST for const generic arguments/const application r=CohenArthur a=CohenArthur This commit adds a new type to the AST which contains const generic arguments. The `GenericArgs` structure now also keeps a vector of them, and the parser was modified accordingly. We need to handle these extra arguments in the various resolvers and type-checking phase. As pointed out before, const generic arguments are ambiguous at the AST level. Which is why this "sum type" contains a "Clear" variant when there is no ambiguity at all (`<5>`, `<{ 5 }>`, `<{ 5 + 15 }>` or `<{ N }>`) and an "Ambiguous" one if the value in question might be referring to a type argument (`<N>`) instead of a const generic argument. Co-authored-by: Arthur Cohen <arthur.cohen@embecosm.com>
Diffstat (limited to 'gcc/rust/parse/rust-parse-impl.h')
-rw-r--r--gcc/rust/parse/rust-parse-impl.h57
1 files changed, 34 insertions, 23 deletions
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index b9f031d..c2efd53 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -2878,25 +2878,28 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
return nullptr;
// optional default value
- std::unique_ptr<AST::Expr> default_expr = nullptr;
+ auto default_expr = AST::ConstGenericArg::create_error ();
if (lexer.peek_token ()->get_id () == EQUAL)
{
lexer.skip_token ();
auto tok = lexer.peek_token ();
default_expr = parse_const_generic_expression ();
- if (!default_expr)
+ if (default_expr.is_error ())
rust_error_at (tok->get_locus (),
"invalid token for start of default value for "
"const generic parameter: expected %<block%>, "
"%<identifier%> or %<literal%>, got %qs",
token_id_to_str (tok->get_id ()));
+
+ // TODO: At this point, we *know* that we are parsing a const
+ // expression. We should figure out how to disambiguate the default
+ // expr in the case of `const N: usize = M`
}
param = std::unique_ptr<AST::ConstGenericParam> (
new AST::ConstGenericParam (name_token->get_str (), std::move (type),
- std::move (default_expr),
- std::move (outer_attrs),
+ nullptr, std::move (outer_attrs),
token->get_locus ()));
break;
@@ -6162,25 +6165,26 @@ Parser<ManagedTokenSource>::parse_type_path ()
}
template <typename ManagedTokenSource>
-std::unique_ptr<AST::Expr>
+AST::ConstGenericArg
Parser<ManagedTokenSource>::parse_const_generic_expression ()
{
auto tok = lexer.peek_token ();
+ std::unique_ptr<AST::Expr> expr = nullptr;
+
switch (tok->get_id ())
{
- case LEFT_CURLY:
- return parse_block_expr ();
- case IDENTIFIER: {
- lexer.skip_token ();
+ case IDENTIFIER:
+ lexer.skip_token ();
- // TODO: This is ambiguous with regular generic types. We probably need
- // to differentiate later on during type checking, and thus keep a
- // special variant here
+ // TODO: This is ambiguous with regular generic types. We probably need
+ // to differentiate later on during type checking, and thus keep a
+ // special variant here
- // return this
- return std::unique_ptr<AST::IdentifierExpr> (
- new AST::IdentifierExpr (tok->get_str (), {}, tok->get_locus ()));
- }
+ // FIXME: We need locus here as well
+ return AST::ConstGenericArg (tok->get_str ());
+ case LEFT_CURLY:
+ expr = parse_block_expr ();
+ break;
case MINUS:
case STRING_LITERAL:
case CHAR_LITERAL:
@@ -6188,10 +6192,16 @@ Parser<ManagedTokenSource>::parse_const_generic_expression ()
case FLOAT_LITERAL:
case TRUE_LITERAL:
case FALSE_LITERAL:
- return parse_literal_expr ();
+ expr = parse_literal_expr ();
+ break;
default:
- return nullptr;
+ expr = nullptr;
}
+
+ if (!expr)
+ return AST::ConstGenericArg::create_error ();
+
+ return AST::ConstGenericArg (std::move (expr));
}
// Parses the generic arguments in each path segment.
@@ -6237,7 +6247,7 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
// try to parse types second
std::vector<std::unique_ptr<AST::Type>> type_args;
- std::vector<std::unique_ptr<AST::Expr>> const_args;
+ std::vector<AST::ConstGenericArg> const_args;
// TODO: Keep list of const expressions as well
@@ -6261,10 +6271,10 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
else
{
auto const_generic_expr = parse_const_generic_expression ();
- if (const_generic_expr)
- const_args.emplace_back (std::move (const_generic_expr));
- else
+ if (const_generic_expr.is_error ())
break;
+ else
+ const_args.emplace_back (std::move (const_generic_expr));
}
// if next token isn't comma, then it must be end of list
@@ -6315,7 +6325,8 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
binding_args.shrink_to_fit ();
return AST::GenericArgs (std::move (lifetime_args), std::move (type_args),
- std::move (binding_args), locus);
+ std::move (binding_args), std::move (const_args),
+ locus);
}
// Parses a binding in a generic args path segment.