From: Owen Avery <[email protected]>

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 <[email protected]>
---
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

Reply via email to