aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorRaiki Tamura <tamaron1203@gmail.com>2024-08-09 23:56:55 +0900
committerCohenArthur <arthur.cohen@embecosm.com>2024-08-28 18:19:41 +0000
commit5da381ffd112693836b4532f680a5bd512552837 (patch)
treeabfd755c13e22c8efc8fd6cc8f67217a03dfe687 /gcc
parentaf7e8fda83d8b34170f4fdf3371b67cd6b4e72f1 (diff)
downloadgcc-5da381ffd112693836b4532f680a5bd512552837.zip
gcc-5da381ffd112693836b4532f680a5bd512552837.tar.gz
gcc-5da381ffd112693836b4532f680a5bd512552837.tar.bz2
gccrs: Add typecheck for path patterns.
gcc/rust/ChangeLog: * hir/tree/rust-hir.cc (Item::item_kind_string): New function. * hir/tree/rust-hir.h: New function. * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): Modify to check all arms in match expressions even if some of them has errors. * typecheck/rust-hir-type-check-pattern.cc (TypeCheckPattern::visit): Add and fix check for path patterns. gcc/testsuite/ChangeLog: * rust/compile/issue-2324-2.rs: Fix error message. * rust/compile/match9.rs: New test. Signed-off-by: Raiki Tamura <tamaron1203@gmail.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/hir/tree/rust-hir.cc38
-rw-r--r--gcc/rust/hir/tree/rust-hir.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc13
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-pattern.cc118
-rw-r--r--gcc/testsuite/rust/compile/issue-2324-2.rs2
-rw-r--r--gcc/testsuite/rust/compile/match9.rs30
6 files changed, 175 insertions, 28 deletions
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 35aa585..797a7fb 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -213,6 +213,44 @@ Module::as_string () const
}
std::string
+Item::item_kind_string (Item::ItemKind kind)
+{
+ switch (kind)
+ {
+ case Item::ItemKind::Static:
+ return "static";
+ case Item::ItemKind::Constant:
+ return "constant";
+ case Item::ItemKind::TypeAlias:
+ return "type alias";
+ case Item::ItemKind::Function:
+ return "function";
+ case Item::ItemKind::UseDeclaration:
+ return "use declaration";
+ case Item::ItemKind::ExternBlock:
+ return "extern block";
+ case Item::ItemKind::ExternCrate:
+ return "extern crate";
+ case Item::ItemKind::Struct:
+ return "struct";
+ case Item::ItemKind::Union:
+ return "union";
+ case Item::ItemKind::Enum:
+ return "enum";
+ case Item::ItemKind::EnumItem:
+ return "enum item";
+ case Item::ItemKind::Trait:
+ return "trait";
+ case Item::ItemKind::Impl:
+ return "impl";
+ case Item::ItemKind::Module:
+ return "module";
+ default:
+ rust_unreachable ();
+ }
+}
+
+std::string
StaticItem::as_string () const
{
std::string str = VisItem::as_string ();
diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h
index 3fb97b2..e612499 100644
--- a/gcc/rust/hir/tree/rust-hir.h
+++ b/gcc/rust/hir/tree/rust-hir.h
@@ -220,6 +220,8 @@ public:
Module,
};
+ static std::string item_kind_string (ItemKind kind);
+
virtual ItemKind get_item_kind () const = 0;
// Unique pointer custom clone function
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 8a1460b..12a8b65 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -1465,6 +1465,7 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
TyTy::BaseType *scrutinee_tyty
= TypeCheckExpr::Resolve (expr.get_scrutinee_expr ().get ());
+ bool saw_error = false;
std::vector<TyTy::BaseType *> kase_block_tys;
for (auto &kase : expr.get_match_cases ())
{
@@ -1475,7 +1476,10 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
TyTy::BaseType *kase_arm_ty
= TypeCheckPattern::Resolve (pattern.get (), scrutinee_tyty);
if (kase_arm_ty->get_kind () == TyTy ::TypeKind::ERROR)
- return;
+ {
+ saw_error = true;
+ continue;
+ }
TyTy::BaseType *checked_kase = unify_site (
expr.get_mappings ().get_hirid (),
@@ -1484,7 +1488,10 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
TyTy::TyWithLocation (kase_arm_ty, pattern->get_locus ()),
expr.get_locus ());
if (checked_kase->get_kind () == TyTy::TypeKind::ERROR)
- return;
+ {
+ saw_error = true;
+ continue;
+ }
}
// check the kase type
@@ -1492,6 +1499,8 @@ TypeCheckExpr::visit (HIR::MatchExpr &expr)
= TypeCheckExpr::Resolve (kase.get_expr ().get ());
kase_block_tys.push_back (kase_block_ty);
}
+ if (saw_error)
+ return;
if (kase_block_tys.size () == 0)
{
diff --git a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
index 811e329..b0e4ca5 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-pattern.cc
@@ -43,32 +43,100 @@ TypeCheckPattern::Resolve (HIR::Pattern *pattern, TyTy::BaseType *parent)
void
TypeCheckPattern::visit (HIR::PathInExpression &pattern)
{
- infered = TypeCheckExpr::Resolve (&pattern);
-
- /*
- * We are compiling a PathInExpression, which can't be a Struct or Tuple
- * pattern. We should check that the declaration we are referencing IS NOT a
- * struct pattern or tuple with values.
- */
+ // Pattern must be enum variants, sturcts, constants, or associated constansts
+ TyTy::BaseType *pattern_ty = TypeCheckExpr::Resolve (&pattern);
+
+ NodeId ref_node_id = UNKNOWN_NODEID;
+ bool maybe_item = false;
+ maybe_item
+ |= resolver->lookup_resolved_name (pattern.get_mappings ().get_nodeid (),
+ &ref_node_id);
+ maybe_item
+ |= resolver->lookup_resolved_type (pattern.get_mappings ().get_nodeid (),
+ &ref_node_id);
+ bool path_is_const_item = false;
+
+ if (maybe_item)
+ {
+ tl::optional<HirId> definition_id
+ = mappings.lookup_node_to_hir (ref_node_id);
+ rust_assert (definition_id.has_value ());
+ 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 (hir_item.has_value ())
+ {
+ HIR::Item *item = hir_item.value ();
+ if (item->get_item_kind () == HIR::Item::ItemKind::Constant)
+ {
+ path_is_const_item = true;
+ }
+ else if (item->get_item_kind () != HIR::Item::ItemKind::Struct)
+ {
+ HIR::Item *item = hir_item.value ();
+ std::string item_kind
+ = HIR::Item::item_kind_string (item->get_item_kind ());
+
+ std::string path_buf;
+ for (size_t i = 0; i < pattern.get_segments ().size (); i++)
+ {
+ HIR::PathExprSegment &seg = pattern.get_segments ().at (i);
+ path_buf += seg.as_string ();
+ if (i != pattern.get_segments ().size () - 1)
+ path_buf += "::";
+ }
+
+ rich_location rich_locus (
+ line_table, pattern.get_final_segment ().get_locus ());
+ rich_locus.add_fixit_replace (
+ "not a unit struct, unit variant or constatnt");
+ rust_error_at (rich_locus, ErrorCode::E0532,
+ "expected unit struct, unit variant or constant, "
+ "found %s %<%s%>",
+ item_kind.c_str (), path_buf.c_str ());
+ return;
+ }
+ }
+ }
- rust_assert (infered->get_kind () == TyTy::TypeKind::ADT);
- TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
+ // If the path is a constructor, it must be a unit struct or unit variants.
+ if (!path_is_const_item && pattern_ty->get_kind () == TyTy::TypeKind::ADT)
+ {
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (pattern_ty);
+ rust_assert (adt->get_variants ().size () > 0);
- HirId variant_id = UNKNOWN_HIRID;
- bool ok
- = context->lookup_variant_definition (pattern.get_mappings ().get_hirid (),
- &variant_id);
- rust_assert (ok);
+ TyTy::VariantDef *variant = adt->get_variants ().at (0);
+ if (adt->is_enum ())
+ {
+ HirId variant_id = UNKNOWN_HIRID;
+ bool ok = context->lookup_variant_definition (
+ pattern.get_mappings ().get_hirid (), &variant_id);
+ rust_assert (ok);
- TyTy::VariantDef *variant = nullptr;
- ok = adt->lookup_variant_by_id (variant_id, &variant);
+ ok = adt->lookup_variant_by_id (variant_id, &variant);
+ rust_assert (ok);
+ }
- TyTy::VariantDef::VariantType vty = variant->get_variant_type ();
+ if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM)
+ {
+ std::string variant_type = TyTy::VariantDef::variant_type_string (
+ variant->get_variant_type ());
+
+ rich_location rich_locus (line_table,
+ pattern.get_final_segment ().get_locus ());
+ rich_locus.add_fixit_replace (
+ "not a unit struct, unit variant or constatnt");
+ rust_error_at (rich_locus, ErrorCode::E0532,
+ "expected unit struct, unit variant or constant, "
+ "found %s variant %<%s::%s%>",
+ variant_type.c_str (), adt->get_name ().c_str (),
+ variant->get_identifier ().c_str ());
+ return;
+ }
- if (vty != TyTy::VariantDef::VariantType::NUM)
- rust_error_at (
- pattern.get_final_segment ().get_locus (), ErrorCode::E0532,
- "expected unit struct, unit variant or constant, found tuple variant");
+ infered = pattern_ty;
+ }
}
void
@@ -100,8 +168,8 @@ TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
rust_assert (ok);
}
- // error[E0532]: expected tuple struct or tuple variant, found struct variant
- // `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0
+ // error[E0532]: expected tuple struct or tuple variant, found struct
+ // variant `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0
if (variant->get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
{
std::string variant_type
@@ -203,8 +271,8 @@ TypeCheckPattern::visit (HIR::StructPattern &pattern)
rust_assert (ok);
}
- // error[E0532]: expected tuple struct or tuple variant, found struct variant
- // `Foo::D`
+ // error[E0532]: expected tuple struct or tuple variant, found struct
+ // variant `Foo::D`
if (variant->get_variant_type () != TyTy::VariantDef::VariantType::STRUCT)
{
std::string variant_type
diff --git a/gcc/testsuite/rust/compile/issue-2324-2.rs b/gcc/testsuite/rust/compile/issue-2324-2.rs
index 5ef4014..1530b00 100644
--- a/gcc/testsuite/rust/compile/issue-2324-2.rs
+++ b/gcc/testsuite/rust/compile/issue-2324-2.rs
@@ -6,7 +6,7 @@ enum State {
fn print_on_failure(state: &State) {
match *state {
State::Succeeded => (),
- State::Failed => (), // { dg-error "expected unit struct, unit variant or constant, found tuple variant" }
+ State::Failed => (), // { dg-error "expected unit struct, unit variant or constant, found struct variant" }
_ => ()
}
}
diff --git a/gcc/testsuite/rust/compile/match9.rs b/gcc/testsuite/rust/compile/match9.rs
new file mode 100644
index 0000000..115d458
--- /dev/null
+++ b/gcc/testsuite/rust/compile/match9.rs
@@ -0,0 +1,30 @@
+enum E {
+ A(),
+ B,
+}
+
+const CONST_E: E = E::A();
+
+static static_e: E = E::A();
+
+type type_alias = E;
+
+fn f(e: E) {
+ match e {
+ E::A => {}
+ // { dg-error "expected unit struct, unit variant or constant, found tuple variant .E::A." "" { target *-*-* } .-1 }
+ E::B => {}
+ crate::CONST_E => {}
+ crate::type_alias => {}
+ // { dg-error "expected unit struct, unit variant or constant, found type alias .crate::type_alias." "" { target *-*-* } .-1 }
+ crate::E => {}
+ // { dg-error "expected unit struct, unit variant or constant, found enum .crate::E." "" { target *-*-* } .-1 }
+ crate::static_e => {}
+ // { dg-error "expected unit struct, unit variant or constant, found static .crate::static_e." "" { target *-*-* } .-1 }
+ crate::f => {}
+ // { dg-error "expected unit struct, unit variant or constant, found function .crate::f." "" { target *-*-* } .-1 }
+ _ => {}
+ }
+}
+
+fn main() {}