[gccrs COMMIT] Improve unit struct matching

gerris.rs@gmail.com gerris.rs@gmail.com
Mon Mar 23 03:48:48 GMT 2026


From: Owen Avery <powerboat9.gamer@gmail.com>

Unit structs weren't *actually* working in match statements -- we don't
currently handle identifier pattern vs path pattern disambiguation.

gcc/rust/ChangeLog:

	* checks/errors/rust-hir-pattern-analysis.cc
	(PlaceInfo::specialize): Handle VariantType::UNIT.
	(WitnessPat::to_string): Likewise.
	(WitnessMatrix::apply_constructor): Likewise.
	* typecheck/rust-hir-type-check-item.cc (TypeCheckItem::visit):
	Conditionally create VariantType::UNIT variants.
	* typecheck/rust-hir-type-check-pattern.cc
	(TypeCheckPattern::visit): Fix typo, handle VariantType::UNIT.
	* typecheck/rust-tyty-variance-analysis.cc
	(GenericTyVisitorCtx::process_type): Handle VariantType::UNIT.
	* typecheck/rust-tyty.cc (BaseType::contains_infer): Likewise.
	(BaseType::is_concrete): Likewise.
	(VariantDef::variant_type_string): Likewise.
	(VariantDef::VariantDef): Likewise.
	* typecheck/rust-tyty.h (VariantDef::VariantType::UNIT): New
	enumerator.

gcc/testsuite/ChangeLog:

	* rust/compile/match-struct-path.rs: Increase test coverage.

Signed-off-by: Owen Avery <powerboat9.gamer@gmail.com>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.


Commit on github: https://github.com/Rust-GCC/gccrs/commit/cd8412c8f899fc4c2ef063dfe5a01ed772de3cca

The commit has been mentioned in the following pull-request(s):
 - https://github.com/Rust-GCC/gccrs/pull/4499

 gcc/rust/checks/errors/rust-hir-pattern-analysis.cc |  8 ++++++--
 gcc/rust/typecheck/rust-hir-type-check-item.cc      |  6 ++++--
 gcc/rust/typecheck/rust-hir-type-check-pattern.cc   |  6 ++++--
 gcc/rust/typecheck/rust-tyty-variance-analysis.cc   |  3 ++-
 gcc/rust/typecheck/rust-tyty.cc                     | 13 ++++++++++---
 gcc/rust/typecheck/rust-tyty.h                      |  3 ++-
 gcc/testsuite/rust/compile/match-struct-path.rs     |  6 ++++++
 7 files changed, 34 insertions(+), 11 deletions(-)

diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index 431cd9bb8..b2a3e5e97 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -936,7 +936,9 @@ PlaceInfo::specialize (const Constructor &c) const
 	      TyTy::VariantDef *variant
 		= adt->get_variants ().at (c.get_variant_index ());
 	      if (variant->get_variant_type ()
-		  == TyTy::VariantDef::VariantType::NUM)
+		    == TyTy::VariantDef::VariantType::NUM
+		  || variant->get_variant_type ()
+		       == TyTy::VariantDef::VariantType::UNIT)
 		return {};
 
 	      std::vector<PlaceInfo> new_place_infos;
@@ -1050,6 +1052,7 @@ WitnessPat::to_string () const
 
 	switch (variant->get_variant_type ())
 	  {
+	  case TyTy::VariantDef::VariantType::UNIT:
 	  case TyTy::VariantDef::VariantType::NUM:
 	    {
 	      return buf;
@@ -1145,7 +1148,8 @@ WitnessMatrix::apply_constructor (const Constructor &ctor,
 	    TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (ty);
 	    TyTy::VariantDef *variant
 	      = adt->get_variants ().at (ctor.get_variant_index ());
-	    if (variant->get_variant_type () == TyTy::VariantDef::NUM)
+	    if (variant->get_variant_type () == TyTy::VariantDef::NUM
+		|| variant->get_variant_type () == TyTy::VariantDef::UNIT)
 	      arity = 0;
 	    else
 	      arity = variant->get_fields ().size ();
diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.cc b/gcc/rust/typecheck/rust-hir-type-check-item.cc
index 12ac39865..f2a40c6c7 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-item.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-item.cc
@@ -283,13 +283,15 @@ TypeCheckItem::visit (HIR::StructStruct &struct_decl)
   RustIdent ident{path, struct_decl.get_locus ()};
 
   // its a single variant ADT
+  auto variant_type = struct_decl.is_unit_struct ()
+			? TyTy::VariantDef::VariantType::UNIT
+			: TyTy::VariantDef::VariantType::STRUCT;
   std::vector<TyTy::VariantDef *> variants;
   variants.push_back (
     new TyTy::VariantDef (struct_decl.get_mappings ().get_hirid (),
 			  struct_decl.get_mappings ().get_defid (),
 			  struct_decl.get_identifier ().as_string (), ident,
-			  TyTy::VariantDef::VariantType::STRUCT, tl::nullopt,
-			  std::move (fields)));
+			  variant_type, tl::nullopt, std::move (fields)));
 
   // Process #[repr(X)] attribute, if any
   const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 32b137141..d6117c38f 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -73,7 +73,7 @@ TypeCheckPattern::visit (HIR::PathInExpression &pattern)
       HirId def_id = definition_id.value ();
 
       tl::optional<HIR::Item *> hir_item = mappings.lookup_hir_item (def_id);
-      // If the path refrerences an item, it must be constants or structs.
+      // If the path references an item, it must be constants or structs.
       if (hir_item.has_value ())
 	{
 	  HIR::Item *item = hir_item.value ();
@@ -127,7 +127,9 @@ TypeCheckPattern::visit (HIR::PathInExpression &pattern)
 	  rust_assert (ok);
 	}
 
-      if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM)
+      if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM
+	  && variant->get_variant_type ()
+	       != TyTy::VariantDef::VariantType::UNIT)
 	{
 	  std::string variant_type = TyTy::VariantDef::variant_type_string (
 	    variant->get_variant_type ());
diff --git a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
index d640d55d8..ca8e9f6b1 100644
--- a/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
+++ b/gcc/rust/typecheck/rust-tyty-variance-analysis.cc
@@ -241,7 +241,8 @@ GenericTyVisitorCtx::process_type (ADTType &ty)
 
   for (const auto &variant : ty.get_variants ())
     {
-      if (variant->get_variant_type () != VariantDef::NUM)
+      if (variant->get_variant_type () != VariantDef::NUM
+	  && variant->get_variant_type () != VariantDef::UNIT)
 	{
 	  for (const auto &field : variant->get_fields ())
 	    add_constraints_from_ty (field->get_field_type (),
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index e27577e31..69ee43c27 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -726,7 +726,9 @@ BaseType::contains_infer () const
 	{
 	  bool is_num_variant
 	    = variant->get_variant_type () == VariantDef::VariantType::NUM;
-	  if (is_num_variant)
+	  bool is_unit_variant
+	    = variant->get_variant_type () == VariantDef::VariantType::UNIT;
+	  if (is_num_variant || is_unit_variant)
 	    continue;
 
 	  for (auto &field : variant->get_fields ())
@@ -831,7 +833,9 @@ BaseType::is_concrete () const
 	{
 	  bool is_num_variant
 	    = variant->get_variant_type () == VariantDef::VariantType::NUM;
-	  if (is_num_variant)
+	  bool is_unit_variant
+	    = variant->get_variant_type () == VariantDef::VariantType::UNIT;
+	  if (is_num_variant || is_unit_variant)
 	    continue;
 
 	  for (auto &field : variant->get_fields ())
@@ -1508,6 +1512,8 @@ VariantDef::variant_type_string (VariantType type)
       return "tuple";
     case STRUCT:
       return "struct";
+    case UNIT:
+      return "unit struct";
     }
   rust_unreachable ();
   return "";
@@ -1532,7 +1538,8 @@ VariantDef::VariantDef (HirId id, DefId defid, std::string identifier,
     discriminant (std::move (discriminant)), fields (fields)
 {
   rust_assert ((type == VariantType::NUM && fields.empty ())
-	       || (type == VariantType::TUPLE || type == VariantType::STRUCT));
+	       || (type == VariantType::UNIT && fields.empty ())
+	       || type == VariantType::TUPLE || type == VariantType::STRUCT);
 }
 
 VariantDef &
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 4072b2f0b..516f460e6 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -828,7 +828,8 @@ public:
   {
     NUM,
     TUPLE,
-    STRUCT
+    STRUCT,
+    UNIT
   };
 
   static std::string variant_type_string (VariantType type);
diff --git a/gcc/testsuite/rust/compile/match-struct-path.rs b/gcc/testsuite/rust/compile/match-struct-path.rs
index 5664c21b4..bc2dd43a6 100644
--- a/gcc/testsuite/rust/compile/match-struct-path.rs
+++ b/gcc/testsuite/rust/compile/match-struct-path.rs
@@ -8,3 +8,9 @@ pub fn foo(v: S) {
         S => ()
     }
 }
+
+pub fn bar(v: S) {
+    match v {
+        crate::S => ()
+    }
+}

base-commit: 4af91dba01b7c2894bcef9d7a82378b952415dd1
-- 
2.53.0



More information about the Gcc-rust mailing list