aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2022-07-05 16:40:38 +0200
committerArthur Cohen <arthur.cohen@embecosm.com>2022-07-07 11:35:06 +0200
commit1f32e5b4558126d872f455c65a94d9640a93c285 (patch)
tree46593ffd2c9b242b801f7cf021a4b9d380baf55a /gcc
parentad0e01dfbba94c0a10019db7c11b13fa0758c1fb (diff)
downloadgcc-1f32e5b4558126d872f455c65a94d9640a93c285.zip
gcc-1f32e5b4558126d872f455c65a94d9640a93c285.tar.gz
gcc-1f32e5b4558126d872f455c65a94d9640a93c285.tar.bz2
ast: Rename ConstGenericArg -> GenericArg
This makes the class clearer and exposes the fact that it may contain a type OR a const value clearer. Because we now run in ambiguous cases later in the compiler pipeline, this commit also adds horrible hacks to simply ignore ambiguous generic arguments and treat them as type arguments.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/ast/rust-ast-full-test.cc47
-rw-r--r--gcc/rust/ast/rust-path.h172
-rw-r--r--gcc/rust/expand/rust-attribute-visitor.cc21
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.cc41
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h2
-rw-r--r--gcc/rust/parse/rust-parse-impl.h83
-rw-r--r--gcc/rust/parse/rust-parse.h2
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.cc47
-rw-r--r--gcc/testsuite/rust/compile/const_generics_2.rs1
9 files changed, 253 insertions, 163 deletions
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc
index d98a7cf..6c41d13 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -2598,28 +2598,14 @@ GenericArgs::as_string () const
}
// type args
- if (!type_args.empty ())
+ if (!generic_args.empty ())
{
- auto i = type_args.begin ();
- auto e = type_args.end ();
+ auto i = generic_args.begin ();
+ auto e = generic_args.end ();
for (; i != e; i++)
{
- args += (*i)->as_string ();
- if (e != i + 1)
- args += ", ";
- }
- }
-
- // const args
- if (!const_args.empty ())
- {
- auto i = const_args.begin ();
- auto e = const_args.end ();
-
- for (; i != e; i++)
- {
- args += i->as_string ();
+ args += (*i).as_string ();
if (e != i + 1)
args += ", ";
}
@@ -5800,15 +5786,28 @@ MetaWord::accept_vis (ASTVisitor &vis)
vis.visit (*this);
}
-ConstGenericArg
-ConstGenericArg::disambiguate_to_const () const
+GenericArg
+GenericArg::disambiguate_to_const () const
{
- rust_assert (get_kind () == Kind::Ambiguous);
+ rust_assert (get_kind () == Kind::Either);
// FIXME: is it fine to have no outer attributes?
- return ConstGenericArg (std::unique_ptr<Expr> (
- new IdentifierExpr (path, {}, locus)),
- locus);
+ return GenericArg::create_const (
+ std::unique_ptr<Expr> (new IdentifierExpr (path, {}, locus)));
+}
+
+GenericArg
+GenericArg::disambiguate_to_type () const
+{
+ rust_assert (get_kind () == Kind::Either);
+
+ auto segment = std::unique_ptr<TypePathSegment> (
+ new TypePathSegment (path, false, locus));
+ auto segments = std::vector<std::unique_ptr<TypePathSegment>> ();
+ segments.emplace_back (std::move (segment));
+
+ return GenericArg::create_type (
+ std::unique_ptr<Type> (new TypePath (std::move (segments), locus)));
}
} // namespace AST
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index c6485c0..722ed93 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -132,7 +132,7 @@ public:
};
/* Class representing a const generic application */
-class ConstGenericArg
+class GenericArg
{
public:
/**
@@ -152,32 +152,43 @@ public:
enum class Kind
{
Error,
- Clear,
- Ambiguous,
+ Const, // A const value
+ Type, // A type argument (not discernable during parsing)
+ Either, // Either a type or a const value, cleared up during resolving
};
- static ConstGenericArg create_error ()
+ static GenericArg create_error ()
{
- return ConstGenericArg (nullptr, "", Kind::Error, Location ());
+ return GenericArg (nullptr, nullptr, "", Kind::Error, Location ());
}
- ConstGenericArg (std::unique_ptr<Expr> expression, Location locus)
- : expression (std::move (expression)), path (""), kind (Kind::Clear),
- locus (locus)
- {}
+ static GenericArg create_const (std::unique_ptr<Expr> expression)
+ {
+ return GenericArg (std::move (expression), nullptr, "", Kind::Const,
+ expression->get_locus ());
+ }
- ConstGenericArg (Identifier path, Location locus)
- : expression (nullptr), path (path), kind (Kind::Ambiguous), locus (locus)
- {}
+ static GenericArg create_type (std::unique_ptr<Type> type)
+ {
+ return GenericArg (nullptr, std::move (type), "", Kind::Type,
+ type->get_locus ());
+ }
- ConstGenericArg (const ConstGenericArg &other)
+ static GenericArg create_ambiguous (Identifier path, Location locus)
+ {
+ return GenericArg (nullptr, nullptr, std::move (path), Kind::Either, locus);
+ }
+
+ GenericArg (const GenericArg &other)
: path (other.path), kind (other.kind), locus (other.locus)
{
if (other.expression)
expression = other.expression->clone_expr ();
+ if (other.type)
+ type = other.type->clone_type ();
}
- ConstGenericArg operator= (const ConstGenericArg &other)
+ GenericArg operator= (const GenericArg &other)
{
kind = other.kind;
path = other.path;
@@ -185,6 +196,8 @@ public:
if (other.expression)
expression = other.expression->clone_expr ();
+ if (other.type)
+ type = other.type->clone_type ();
return *this;
}
@@ -192,40 +205,63 @@ public:
bool is_error () const { return kind == Kind::Error; }
Kind get_kind () const { return kind; }
+ const Location &get_locus () const { return locus; }
- const std::unique_ptr<AST::Expr> &get_expression () const
+ std::unique_ptr<Expr> &get_expression ()
{
- rust_assert (kind == Kind::Clear);
+ rust_assert (kind == Kind::Const);
return expression;
}
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (kind == Kind::Type);
+
+ return type;
+ }
+
+ const std::string &get_path () const
+ {
+ rust_assert (kind == Kind::Either);
+
+ return path;
+ }
+
std::string as_string () const
{
switch (get_kind ())
{
case Kind::Error:
gcc_unreachable ();
- case Kind::Ambiguous:
+ case Kind::Either:
return "Ambiguous: " + path;
- case Kind::Clear:
- return "Clear: { " + expression->as_string () + " }";
+ case Kind::Const:
+ return "Const: { " + expression->as_string () + " }";
+ case Kind::Type:
+ return "Type: " + type->as_string ();
}
return "";
}
/**
- * Disambiguate an amibguous const generic argument or generic type argument
- * to a const generic argument, unequivocally
+ * Disambiguate an ambiguous generic argument to a const generic argument,
+ * unequivocally
*/
- ConstGenericArg disambiguate_to_const () const;
+ GenericArg disambiguate_to_const () const;
+
+ /**
+ * Disambiguate an ambiguous generic argument to a type argument,
+ * unequivocally
+ */
+ GenericArg disambiguate_to_type () const;
private:
- ConstGenericArg (std::unique_ptr<AST::Expr> expression, Identifier path,
- Kind kind, Location locus)
- : expression (std::move (expression)), path (std::move (path)), kind (kind),
- locus (locus)
+ GenericArg (std::unique_ptr<Expr> expression, std::unique_ptr<Type> type,
+ Identifier path, Kind kind, Location locus)
+ : expression (std::move (expression)), type (std::move (type)),
+ path (std::move (path)), kind (kind), locus (locus)
{}
/**
@@ -236,8 +272,14 @@ private:
std::unique_ptr<Expr> expression;
/**
+ * If the argument ends up being a type argument instead. A null pointer will
+ * be present here until the resolving phase.
+ */
+ std::unique_ptr<Type> type;
+
+ /**
* Optional path which cannot be differentiated between a constant item and
- * a type. Only used for `Ambiguous` const generic arguments, otherwise
+ * a type. Only used for ambiguous const generic arguments, otherwise
* empty.
*/
Identifier path;
@@ -262,14 +304,14 @@ class ConstGenericParam : public GenericParam
/**
* Default value for the const generic parameter
*/
- ConstGenericArg default_value;
+ GenericArg default_value;
Attribute outer_attr;
Location locus;
public:
ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type,
- ConstGenericArg default_value, Attribute outer_attr,
+ GenericArg default_value, Attribute outer_attr,
Location locus)
: name (name), type (std::move (type)),
default_value (std::move (default_value)), outer_attr (outer_attr),
@@ -294,7 +336,14 @@ public:
return type;
}
- const ConstGenericArg &get_default_value () const
+ GenericArg &get_default_value ()
+ {
+ rust_assert (has_default_value ());
+
+ return default_value;
+ }
+
+ const GenericArg &get_default_value () const
{
rust_assert (has_default_value ());
@@ -322,39 +371,32 @@ protected:
struct GenericArgs
{
std::vector<Lifetime> lifetime_args;
- std::vector<std::unique_ptr<Type> > type_args;
+ std::vector<GenericArg> generic_args;
std::vector<GenericArgsBinding> binding_args;
- std::vector<ConstGenericArg> const_args;
Location locus;
public:
// Returns true if there are any generic arguments
bool has_generic_args () const
{
- return !(lifetime_args.empty () && type_args.empty ()
- && binding_args.empty () && const_args.empty ());
+ return !(lifetime_args.empty () && generic_args.empty ()
+ && binding_args.empty ());
}
GenericArgs (std::vector<Lifetime> lifetime_args,
- std::vector<std::unique_ptr<Type> > type_args,
+ std::vector<GenericArg> generic_args,
std::vector<GenericArgsBinding> binding_args,
- std::vector<ConstGenericArg> const_args,
Location locus = Location ())
: lifetime_args (std::move (lifetime_args)),
- type_args (std::move (type_args)),
- binding_args (std::move (binding_args)),
- const_args (std::move (const_args)), locus (locus)
+ generic_args (std::move (generic_args)),
+ binding_args (std::move (binding_args)), locus (locus)
{}
// copy constructor with vector clone
GenericArgs (GenericArgs const &other)
- : lifetime_args (other.lifetime_args), binding_args (other.binding_args),
- const_args (other.const_args), locus (other.locus)
- {
- type_args.reserve (other.type_args.size ());
- for (const auto &e : other.type_args)
- type_args.push_back (e->clone_type ());
- }
+ : lifetime_args (other.lifetime_args), generic_args (other.generic_args),
+ binding_args (other.binding_args), locus (other.locus)
+ {}
~GenericArgs () = default;
@@ -362,14 +404,10 @@ public:
GenericArgs &operator= (GenericArgs const &other)
{
lifetime_args = other.lifetime_args;
+ generic_args = other.generic_args;
binding_args = other.binding_args;
- const_args = other.const_args;
locus = other.locus;
- type_args.reserve (other.type_args.size ());
- for (const auto &e : other.type_args)
- type_args.push_back (e->clone_type ());
-
return *this;
}
@@ -378,26 +416,18 @@ public:
GenericArgs &operator= (GenericArgs &&other) = default;
// Creates an empty GenericArgs (no arguments)
- static GenericArgs create_empty ()
- {
- return GenericArgs (std::vector<Lifetime> (),
- std::vector<std::unique_ptr<Type> > (),
- std::vector<GenericArgsBinding> (),
- std::vector<ConstGenericArg> ());
- }
+ static GenericArgs create_empty () { return GenericArgs ({}, {}, {}); }
std::string as_string () const;
// TODO: is this better? Or is a "vis_pattern" better?
- std::vector<std::unique_ptr<Type> > &get_type_args () { return type_args; }
+ std::vector<GenericArg> &get_generic_args () { return generic_args; }
// TODO: is this better? Or is a "vis_pattern" better?
std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; }
std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; };
- std::vector<ConstGenericArg> &get_const_args () { return const_args; };
-
Location get_locus () { return locus; }
};
@@ -427,13 +457,12 @@ public:
* args) */
PathExprSegment (std::string segment_name, Location locus,
std::vector<Lifetime> lifetime_args = {},
- std::vector<std::unique_ptr<Type> > type_args = {},
- std::vector<GenericArgsBinding> binding_args = {},
- std::vector<ConstGenericArg> const_args = {})
+ std::vector<GenericArg> generic_args = {},
+ std::vector<GenericArgsBinding> binding_args = {})
: segment_name (PathIdentSegment (std::move (segment_name), locus)),
- generic_args (
- GenericArgs (std::move (lifetime_args), std::move (type_args),
- std::move (binding_args), std::move (const_args))),
+ generic_args (GenericArgs (std::move (lifetime_args),
+ std::move (generic_args),
+ std::move (binding_args))),
locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ())
{}
@@ -724,15 +753,14 @@ public:
TypePathSegmentGeneric (std::string segment_name,
bool has_separating_scope_resolution,
std::vector<Lifetime> lifetime_args,
- std::vector<std::unique_ptr<Type> > type_args,
+ std::vector<GenericArg> generic_args,
std::vector<GenericArgsBinding> binding_args,
- std::vector<ConstGenericArg> const_args,
Location locus)
: TypePathSegment (std::move (segment_name),
has_separating_scope_resolution, locus),
- generic_args (
- GenericArgs (std::move (lifetime_args), std::move (type_args),
- std::move (binding_args), std::move (const_args)))
+ generic_args (GenericArgs (std::move (lifetime_args),
+ std::move (generic_args),
+ std::move (binding_args)))
{}
std::string as_string () const override;
diff --git a/gcc/rust/expand/rust-attribute-visitor.cc b/gcc/rust/expand/rust-attribute-visitor.cc
index 90d91ee..bec6a9d 100644
--- a/gcc/rust/expand/rust-attribute-visitor.cc
+++ b/gcc/rust/expand/rust-attribute-visitor.cc
@@ -130,14 +130,23 @@ AttrVisitor::expand_generic_args (AST::GenericArgs &args)
expander.push_context (MacroExpander::ContextType::TYPE);
// expand type args - strip sub-types only
- for (auto &type : args.get_type_args ())
+ for (auto &arg : args.get_generic_args ())
{
- type->accept_vis (*this);
- maybe_expand_type (type);
+ // FIXME: Arthur: Another ugly hack while waiting for disambiguation
+ if (arg.get_kind () == AST::GenericArg::Kind::Either)
+ arg = arg.disambiguate_to_type ();
- if (type->is_marked_for_strip ())
- rust_error_at (type->get_locus (),
- "cannot strip type in this position");
+ if (arg.get_kind () == AST::GenericArg::Kind::Type)
+ {
+ auto &type = arg.get_type ();
+
+ type->accept_vis (*this);
+ maybe_expand_type (type);
+
+ if (type->is_marked_for_strip ())
+ rust_error_at (type->get_locus (),
+ "cannot strip type in this position");
+ }
}
expander.pop_context ();
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc b/gcc/rust/hir/rust-ast-lower-base.cc
index 7e80f81..6afbbe2 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -606,22 +606,37 @@ ASTLoweringBase::lower_generic_args (AST::GenericArgs &args)
}
std::vector<std::unique_ptr<HIR::Type>> type_args;
- for (auto &type : args.get_type_args ())
+ std::vector<HIR::ConstGenericArg> const_args;
+
+ for (auto &arg : args.get_generic_args ())
{
- HIR::Type *t = ASTLoweringType::translate (type.get ());
- type_args.push_back (std::unique_ptr<HIR::Type> (t));
+ switch (arg.get_kind ())
+ {
+ case AST::GenericArg::Kind::Type: {
+ auto type = ASTLoweringType::translate (arg.get_type ().get ());
+ type_args.emplace_back (std::unique_ptr<HIR::Type> (type));
+ break;
+ }
+ case AST::GenericArg::Kind::Const: {
+ auto expr
+ = ASTLoweringExpr::translate (arg.get_expression ().get ());
+ const_args.emplace_back (
+ HIR::ConstGenericArg (std::unique_ptr<HIR::Expr> (expr),
+ expr->get_locus ()));
+ break;
+ }
+ // FIXME: Arthur: Other horrible hack waiting for disambiguation
+ case AST::GenericArg::Kind::Either: {
+ arg = arg.disambiguate_to_type ();
+ auto type = ASTLoweringType::translate (arg.get_type ().get ());
+ type_args.emplace_back (std::unique_ptr<HIR::Type> (type));
+ break;
+ }
+ default:
+ gcc_unreachable ();
+ }
}
- std::vector<HIR::ConstGenericArg> const_args;
- for (auto &const_arg : args.get_const_args ())
- const_args.emplace_back (HIR::ConstGenericArg (
- std::unique_ptr<HIR::Expr> (
- ASTLoweringExpr::translate (const_arg.get_expression ().get ())),
- Location ()));
-
- // FIXME:
- // const_arg.get_locus ());
-
return HIR::GenericArgs (std::move (lifetime_args), std::move (type_args),
std::move (binding_args), std::move (const_args),
args.get_locus ());
diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h
index 2bcf0ee..a897c03 100644
--- a/gcc/rust/hir/rust-ast-lower-type.h
+++ b/gcc/rust/hir/rust-ast-lower-type.h
@@ -381,7 +381,7 @@ public:
HIR::Expr *default_expr = nullptr;
if (param.has_default_value ()
&& param.get_default_value ().get_kind ()
- == AST::ConstGenericArg::Kind::Clear)
+ == AST::GenericArg::Kind::Const)
default_expr = ASTLoweringExpr::translate (
param.get_default_value ().get_expression ().get ());
diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h
index 6a1a3a5..446df13 100644
--- a/gcc/rust/parse/rust-parse-impl.h
+++ b/gcc/rust/parse/rust-parse-impl.h
@@ -2878,12 +2878,12 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
return nullptr;
// optional default value
- auto default_expr = AST::ConstGenericArg::create_error ();
+ auto default_expr = AST::GenericArg::create_error ();
if (lexer.peek_token ()->get_id () == EQUAL)
{
lexer.skip_token ();
auto tok = lexer.peek_token ();
- default_expr = parse_const_generic_expression ();
+ default_expr = parse_generic_arg ();
if (default_expr.is_error ())
rust_error_at (tok->get_locus (),
@@ -2894,8 +2894,7 @@ Parser<ManagedTokenSource>::parse_generic_param (EndTokenPred is_end_token)
// At this point, we *know* that we are parsing a const
// expression
- if (default_expr.get_kind ()
- == AST::ConstGenericArg::Kind::Ambiguous)
+ if (default_expr.get_kind () == AST::GenericArg::Kind::Either)
default_expr = default_expr.disambiguate_to_const ();
}
@@ -6167,23 +6166,31 @@ Parser<ManagedTokenSource>::parse_type_path ()
}
template <typename ManagedTokenSource>
-AST::ConstGenericArg
-Parser<ManagedTokenSource>::parse_const_generic_expression ()
+AST::GenericArg
+Parser<ManagedTokenSource>::parse_generic_arg ()
{
auto tok = lexer.peek_token ();
std::unique_ptr<AST::Expr> expr = nullptr;
switch (tok->get_id ())
{
- 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
-
- // FIXME: We need locus here as well
- return AST::ConstGenericArg (tok->get_str (), tok->get_locus ());
+ case IDENTIFIER: {
+ // This is a bit of a weird situation: With an identifier token, we
+ // could either have a valid type or a macro (FIXME: anything else?). So
+ // we need one bit of lookahead to differentiate if this is really
+ auto next_tok = lexer.peek_token (1);
+ if (next_tok->get_id () == EXCLAM)
+ {
+ auto type = parse_type ();
+ if (type)
+ return AST::GenericArg::create_type (std::move (type));
+ else
+ return AST::GenericArg::create_error ();
+ }
+ lexer.skip_token ();
+ return AST::GenericArg::create_ambiguous (tok->get_str (),
+ tok->get_locus ());
+ }
case LEFT_CURLY:
expr = parse_block_expr ();
break;
@@ -6196,14 +6203,22 @@ Parser<ManagedTokenSource>::parse_const_generic_expression ()
case FALSE_LITERAL:
expr = parse_literal_expr ();
break;
- default:
- expr = nullptr;
+ // FIXME: Because of this, error reporting is garbage for const generic
+ // parameter's default values
+ default: {
+ auto type = parse_type ();
+ // FIXME: Find a better way to do this?
+ if (type)
+ return AST::GenericArg::create_type (std::move (type));
+ else
+ return AST::GenericArg::create_error ();
+ }
}
if (!expr)
- return AST::ConstGenericArg::create_error ();
+ return AST::GenericArg::create_error ();
- return AST::ConstGenericArg (std::move (expr), tok->get_locus ());
+ return AST::GenericArg::create_const (std::move (expr));
}
// Parses the generic arguments in each path segment.
@@ -6247,11 +6262,8 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
t = lexer.peek_token ();
}
- // try to parse types second
- std::vector<std::unique_ptr<AST::Type>> type_args;
- std::vector<AST::ConstGenericArg> const_args;
-
- // TODO: Keep list of const expressions as well
+ // try to parse types and const generics second
+ std::vector<AST::GenericArg> generic_args;
// TODO: think of better control structure
t = lexer.peek_token ();
@@ -6265,20 +6277,14 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
&& lexer.peek_token (1)->get_id () == EQUAL)
break;
- auto type = parse_type (false);
- if (type)
+ auto arg = parse_generic_arg ();
+ if (!arg.is_error ())
{
- type_args.emplace_back (std::move (type));
- }
- else
- {
- auto const_generic_expr = parse_const_generic_expression ();
- if (const_generic_expr.is_error ())
- break;
- else
- const_args.emplace_back (std::move (const_generic_expr));
+ generic_args.emplace_back (std::move (arg));
}
+ // FIXME: Do we need to break if we encounter an error?
+
// if next token isn't comma, then it must be end of list
if (lexer.peek_token ()->get_id () != COMMA)
break;
@@ -6323,12 +6329,11 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
return AST::GenericArgs::create_empty ();
lifetime_args.shrink_to_fit ();
- type_args.shrink_to_fit ();
+ generic_args.shrink_to_fit ();
binding_args.shrink_to_fit ();
- return AST::GenericArgs (std::move (lifetime_args), std::move (type_args),
- std::move (binding_args), std::move (const_args),
- locus);
+ return AST::GenericArgs (std::move (lifetime_args), std::move (generic_args),
+ std::move (binding_args), locus);
}
// Parses a binding in a generic args path segment.
diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h
index fa88f8e..23a1e7c 100644
--- a/gcc/rust/parse/rust-parse.h
+++ b/gcc/rust/parse/rust-parse.h
@@ -177,7 +177,7 @@ private:
AST::TypePath parse_type_path ();
std::unique_ptr<AST::TypePathSegment> parse_type_path_segment ();
AST::PathIdentSegment parse_path_ident_segment ();
- AST::ConstGenericArg parse_const_generic_expression ();
+ AST::GenericArg parse_generic_arg ();
AST::GenericArgs parse_path_generic_args ();
AST::GenericArgsBinding parse_generic_args_binding ();
AST::TypePathFunction parse_type_path_function (Location locus);
diff --git a/gcc/rust/resolve/rust-ast-resolve-type.cc b/gcc/rust/resolve/rust-ast-resolve-type.cc
index 910468e..e875688 100644
--- a/gcc/rust/resolve/rust-ast-resolve-type.cc
+++ b/gcc/rust/resolve/rust-ast-resolve-type.cc
@@ -384,12 +384,35 @@ ResolveTypeToCanonicalPath::visit (AST::TypePath &path)
std::vector<CanonicalPath> args;
if (s->has_generic_args ())
{
- for (auto &gt : s->get_generic_args ().get_type_args ())
+ for (auto &generic : s->get_generic_args ().get_generic_args ())
{
- CanonicalPath arg = CanonicalPath::create_empty ();
- bool ok = ResolveTypeToCanonicalPath::go (gt.get (), arg);
- if (ok)
- args.push_back (std::move (arg));
+ // FIXME: What do we want to do here in case there is a
+ // constant or an ambiguous const generic?
+ // TODO: At that point, will all generics have been
+ // disambiguated? Can we thus canonical resolve types and
+ // const and `gcc_unreachable` on ambiguous types?
+ //
+ // FIXME: Arthur: This is an ugly hack to resolve just as
+ // much as before despite not handling ambiguity yet. The
+ // calls to `clone_type` will be removed.
+ std::unique_ptr<AST::Type> gt = nullptr;
+
+ if (generic.get_kind () == AST::GenericArg::Kind::Type)
+ gt = generic.get_type ()->clone_type ();
+ else if (generic.get_kind ()
+ == AST::GenericArg::Kind::Either)
+ gt = generic.disambiguate_to_type ()
+ .get_type ()
+ ->clone_type ();
+
+ if (gt)
+ {
+ CanonicalPath arg = CanonicalPath::create_empty ();
+ bool ok
+ = ResolveTypeToCanonicalPath::go (gt.get (), arg);
+ if (ok)
+ args.push_back (std::move (arg));
+ }
}
}
@@ -472,8 +495,18 @@ ResolveTypeToCanonicalPath::ResolveTypeToCanonicalPath ()
void
ResolveGenericArgs::go (AST::GenericArgs &args)
{
- for (auto &gt : args.get_type_args ())
- ResolveType::go (gt.get ());
+ for (auto &arg : args.get_generic_args ())
+ {
+ // FIXME: Arthur: Ugly hack while waiting for disambiguation
+ if (arg.get_kind () == AST::GenericArg::Kind::Either)
+ arg = arg.disambiguate_to_type ();
+
+ if (arg.get_kind () == AST::GenericArg::Kind::Type)
+ ResolveType::go (arg.get_type ().get ());
+
+ // else...
+ // We need to use a switch instead
+ }
}
} // namespace Resolver
diff --git a/gcc/testsuite/rust/compile/const_generics_2.rs b/gcc/testsuite/rust/compile/const_generics_2.rs
index 82d2676..98495cf 100644
--- a/gcc/testsuite/rust/compile/const_generics_2.rs
+++ b/gcc/testsuite/rust/compile/const_generics_2.rs
@@ -1,3 +1,4 @@
struct Foo<const N>; // { dg-error "expecting .:. but .>. found" }
struct Bar<const N: >; // { dg-error "unrecognised token .>. in type" }
struct Baz<const N: usize = >; // { dg-error "invalid token for start of default value for const generic parameter" }
+// { dg-error "unrecognised token .>. in type" "" { target *-*-* } .-1 }