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]>
---
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 431cd9bb891..b2a3e5e9774 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 12ac3986567..f2a40c6c7df 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 32b13714154..d6117c38f78 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 d640d55d8c0..ca8e9f6b1a8 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 e27577e311d..69ee43c2750 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 4072b2f0bcd..516f460e625 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 5664c21b421..bc2dd43a65d 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 => ()
+ }
+}
--
2.50.1