aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 }