public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] ast: Rename ConstGenericArg -> GenericArg
@ 2022-07-07 11:35 Thomas Schwinge
  0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-07-07 11:35 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:1f32e5b4558126d872f455c65a94d9640a93c285

commit 1f32e5b4558126d872f455c65a94d9640a93c285
Author: Arthur Cohen <arthur.cohen@embecosm.com>
Date:   Tue Jul 5 16:40:38 2022 +0200

    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.

Diff:
---
 gcc/rust/ast/rust-ast-full-test.cc             |  47 ++++---
 gcc/rust/ast/rust-path.h                       | 172 ++++++++++++++-----------
 gcc/rust/expand/rust-attribute-visitor.cc      |  21 ++-
 gcc/rust/hir/rust-ast-lower-base.cc            |  41 ++++--
 gcc/rust/hir/rust-ast-lower-type.h             |   2 +-
 gcc/rust/parse/rust-parse-impl.h               |  83 ++++++------
 gcc/rust/parse/rust-parse.h                    |   2 +-
 gcc/rust/resolve/rust-ast-resolve-type.cc      |  47 ++++++-
 gcc/testsuite/rust/compile/const_generics_2.rs |   1 +
 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 d98a7cfeedb..6c41d138bb8 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 c6485c07bba..722ed93ec57 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)
   {}
 
   /**
@@ -235,9 +271,15 @@ 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 90d91eedbe1..bec6a9d138b 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 7e80f811092..6afbbe2b828 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 2bcf0ee23c4..a897c031444 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 6a1a3a58693..446df13ab92 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 fa88f8eff9d..23a1e7c6e93 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 910468ed729..e875688dc28 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 82d2676f7ee..98495cf404d 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 }


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2022-07-07 11:35 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-07 11:35 [gcc/devel/rust/master] ast: Rename ConstGenericArg -> GenericArg Thomas Schwinge

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).