[COMMITTED] gccrs: const generics: Forbid default values in Functions, Traits and Impls

Message ID 20230131132613.663060-1-arthur.cohen@embecosm.com
State Repeat Merge
Headers
Series [COMMITTED] gccrs: const generics: Forbid default values in Functions, Traits and Impls |

Checks

Context Check Description
snail/gcc-patch-check warning Git am fail log

Commit Message

Arthur Cohen Jan. 31, 2023, 1:26 p.m. UTC
  gcc/rust/ChangeLog:

	* checks/errors/rust-const-checker.cc (ConstChecker::ctx_to_str): Allow
	getting an error string from a specific constant context.
	(ConstChecker::ctx_allows_default): New function, check if a context
	allows default values for Const generics.
	(ConstChecker::visit): Call into `ctx_allows_default`.
	* checks/errors/rust-const-checker.h: Declare `ctx_allows_default`.

gcc/testsuite/ChangeLog:

	* rust/compile/const_generics_8.rs: New test.

Tested on x86_64-pc-linux-gnu, committed on master.

---
 gcc/rust/checks/errors/rust-const-checker.cc  | 97 +++++++++++++++++--
 gcc/rust/checks/errors/rust-const-checker.h   | 25 +++++
 .../rust/compile/const_generics_8.rs          | 12 +++
 3 files changed, 128 insertions(+), 6 deletions(-)
 create mode 100644 gcc/testsuite/rust/compile/const_generics_8.rs
  

Patch

diff --git a/gcc/rust/checks/errors/rust-const-checker.cc b/gcc/rust/checks/errors/rust-const-checker.cc
index 0c1b743cfaf..2fa9614abf1 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -52,6 +52,67 @@  ConstChecker::is_const_extern_fn (HIR::ExternalFunctionItem &fn)
     });
 }
 
+const char *
+ConstChecker::ctx_to_str (ConstGenericCtx ctx)
+{
+  switch (ctx)
+    {
+    case ConstGenericCtx::Function:
+      return "function";
+    case ConstGenericCtx::TypeAlias:
+      return "type alias";
+    case ConstGenericCtx::Struct:
+      return "struct";
+    case ConstGenericCtx::Enum:
+      return "enum";
+    case ConstGenericCtx::Union:
+      return "union";
+    case ConstGenericCtx::Trait:
+      return "trait";
+    case ConstGenericCtx::Impl:
+      return "impl";
+    default:
+      gcc_unreachable ();
+    }
+}
+
+bool
+ConstChecker::ctx_allows_default (ConstGenericCtx ctx)
+{
+  switch (ctx)
+    {
+    case ConstGenericCtx::TypeAlias:
+    case ConstGenericCtx::Struct:
+    case ConstGenericCtx::Enum:
+    case ConstGenericCtx::Trait:
+      return true;
+    default:
+      return false;
+    }
+}
+
+void
+ConstChecker::check_default_const_generics (
+  std::vector<std::unique_ptr<GenericParam>> &params, ConstGenericCtx context)
+{
+  if (ctx_allows_default (context))
+    return;
+
+  for (auto &param : params)
+    {
+      if (param->get_kind () == GenericParam::GenericKind::CONST)
+	{
+	  auto const_param = static_cast<ConstGenericParam *> (param.get ());
+	  if (const_param->has_default_expression ())
+	    rust_error_at (
+	      param->get_locus (),
+	      "default values for const generic parameters are not "
+	      "allowed in %qs items",
+	      ctx_to_str (context));
+	}
+    }
+}
+
 void
 ConstChecker::visit (Lifetime &lifetime)
 {}
@@ -560,6 +621,9 @@  ConstChecker::visit (Function &function)
   if (const_fn)
     const_context.enter (function.get_mappings ().get_hirid ());
 
+  check_default_const_generics (function.get_generic_params (),
+				ConstGenericCtx::Function);
+
   for (auto &param : function.get_function_params ())
     param.get_type ()->accept_vis (*this);
 
@@ -571,18 +635,27 @@  ConstChecker::visit (Function &function)
 
 void
 ConstChecker::visit (TypeAlias &type_alias)
-{}
+{
+  check_default_const_generics (type_alias.get_generic_params (),
+				ConstGenericCtx::TypeAlias);
+}
 
 void
 ConstChecker::visit (StructStruct &struct_item)
-{}
+{
+  check_default_const_generics (struct_item.get_generic_params (),
+				ConstGenericCtx::Struct);
+}
 
 void
 ConstChecker::visit (TupleStruct &tuple_struct)
-{}
+{
+  check_default_const_generics (tuple_struct.get_generic_params (),
+				ConstGenericCtx::Struct);
+}
 
 void
-ConstChecker::visit (EnumItem &item)
+ConstChecker::visit (EnumItem &enum_item)
 {}
 
 void
@@ -605,11 +678,17 @@  ConstChecker::visit (EnumItemDiscriminant &item)
 
 void
 ConstChecker::visit (Enum &enum_item)
-{}
+{
+  check_default_const_generics (enum_item.get_generic_params (),
+				ConstGenericCtx::Enum);
+}
 
 void
 ConstChecker::visit (Union &union_item)
-{}
+{
+  check_default_const_generics (union_item.get_generic_params (),
+				ConstGenericCtx::Union);
+}
 
 void
 ConstChecker::visit (ConstantItem &const_item)
@@ -652,6 +731,9 @@  ConstChecker::visit (TraitItemType &item)
 void
 ConstChecker::visit (Trait &trait)
 {
+  check_default_const_generics (trait.get_generic_params (),
+				ConstGenericCtx::Trait);
+
   for (auto &item : trait.get_trait_items ())
     item->accept_vis (*this);
 }
@@ -659,6 +741,9 @@  ConstChecker::visit (Trait &trait)
 void
 ConstChecker::visit (ImplBlock &impl)
 {
+  check_default_const_generics (impl.get_generic_params (),
+				ConstGenericCtx::Impl);
+
   for (auto &item : impl.get_impl_items ())
     item->accept_vis (*this);
 }
diff --git a/gcc/rust/checks/errors/rust-const-checker.h b/gcc/rust/checks/errors/rust-const-checker.h
index ca86b490130..13cf44b1273 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -46,6 +46,31 @@  private:
    */
   void check_function_call (HirId fn_id, Location locus);
 
+  /* All possible const contexts */
+  enum class ConstGenericCtx
+  {
+    Function,
+    TypeAlias,
+    Struct,
+    Enum,
+    Union,
+    Trait,
+    Impl
+  };
+
+  /* Get the string representation of a const context */
+  const char *ctx_to_str (ConstGenericCtx ctx);
+
+  /* Check if a const context allows default values */
+  bool ctx_allows_default (ConstGenericCtx ctx);
+
+  /**
+   * Check that const generic parameters only contains defaults in allowed
+   * contexts
+   */
+  void check_default_const_generics (
+    std::vector<std::unique_ptr<GenericParam>> &param, ConstGenericCtx context);
+
   StackedContexts<HirId> const_context;
   Resolver::Resolver &resolver;
   Analysis::Mappings &mappings;
diff --git a/gcc/testsuite/rust/compile/const_generics_8.rs b/gcc/testsuite/rust/compile/const_generics_8.rs
new file mode 100644
index 00000000000..b0bb2624a2c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/const_generics_8.rs
@@ -0,0 +1,12 @@ 
+struct Bidule<const N: i32 = 15> {}
+enum Bidoule<const N: i32 = 15> {}
+
+// Note - missing generic parameter - needs name resolution on const generics
+type Bipboupe<const N: i32 = 15> = Bidule;
+trait Fooable<const N: i32 = 15> {}
+
+union Bidoulepe<const N: i32 = 15> {} // { dg-error "default values for const generic parameters are not allowed in .union. items" }
+fn const_default<const N: i32 = 15>() {} // { dg-error "default values for const generic parameters are not allowed in .function. items" }
+
+// Note - missing generic parameter - needs name resolution on const generics
+impl<const N: i32 = 15> Bidule {} // { dg-error "default values for const generic parameters are not allowed in .impl. items" }