]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: Fix ICE by adding check for enum candidate's in TypePath resolution
authorPhilip Herron <herron.philip@googlemail.com>
Sun, 30 Jul 2023 17:59:06 +0000 (18:59 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:56:04 +0000 (18:56 +0100)
Fixes #2479

gcc/rust/ChangeLog:

* typecheck/rust-hir-trait-resolve.cc (TraitItemReference::resolve_item):
always resolve the type even when its an a mandatory trait item
* typecheck/rust-hir-type-check-type.cc (TypeCheckType::resolve_root_path):
Add check for enum candidates otherwise you get undefined behaviour

gcc/testsuite/ChangeLog:

* rust/compile/issue-2479.rs: New test.

Signed-off-by: Philip Herron <herron.philip@googlemail.com>
gcc/rust/typecheck/rust-hir-trait-resolve.cc
gcc/rust/typecheck/rust-hir-type-check-type.cc
gcc/testsuite/rust/compile/issue-2479.rs [new file with mode: 0644]

index 17827753198ce72d1a224ccb4519a439abc8b0bc..b99fe2341af5ed10a65d07d5e4b91487cfbd8d93 100644 (file)
@@ -339,13 +339,13 @@ TraitItemReference::resolve_item (HIR::TraitItemConst &constant)
 void
 TraitItemReference::resolve_item (HIR::TraitItemFunc &func)
 {
-  if (!is_optional ())
-    return;
-
   TyTy::BaseType *item_tyty = get_tyty ();
   if (item_tyty->get_kind () == TyTy::TypeKind::ERROR)
     return;
 
+  if (!is_optional ())
+    return;
+
   // check the block and return types
   rust_assert (item_tyty->get_kind () == TyTy::TypeKind::FNDEF);
 
index 03ee74aeb1057a923ce2cf5e46d32ea0cc666d28..b3125f7e1a5e95015d9a5d0be94569b44edbea51 100644 (file)
@@ -440,6 +440,16 @@ TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
       *root_resolved_node_id = ref_node_id;
       *offset = *offset + 1;
       root_tyty = lookup;
+
+      // this enforces the proper get_segments checks to take place
+      bool is_adt = root_tyty->get_kind () == TyTy::TypeKind::ADT;
+      if (is_adt)
+       {
+         const TyTy::ADTType &adt
+           = *static_cast<const TyTy::ADTType *> (root_tyty);
+         if (adt.is_enum ())
+           return root_tyty;
+       }
     }
 
   return root_tyty;
@@ -498,6 +508,14 @@ TypeCheckType::resolve_segments (
       prev_segment = tyseg;
       tyseg = candidate.ty;
 
+      if (candidate.is_enum_candidate ())
+       {
+         rust_error_at (seg->get_locus (),
+                        "expected type, found variant of %s",
+                        tyseg->get_name ().c_str ());
+         return new TyTy::ErrorType (expr_id);
+       }
+
       if (candidate.is_impl_candidate ())
        {
          resolved_node_id
diff --git a/gcc/testsuite/rust/compile/issue-2479.rs b/gcc/testsuite/rust/compile/issue-2479.rs
new file mode 100644 (file)
index 0000000..4a0d354
--- /dev/null
@@ -0,0 +1,22 @@
+#![allow(unused)]
+fn main() {
+enum Dragon {
+    Born,
+}
+
+fn oblivion() -> Dragon::Born {
+// { dg-error "expected type, found variant of Dragon" "" { target *-*-* } .-1 }
+// { dg-error "failed to resolve return type" "" { target *-*-* } .-2 }
+    Dragon::Born
+}
+
+enum Wizard {
+    Gandalf,
+    Saruman,
+}
+
+trait Isengard {
+    fn wizard(_: Wizard::Saruman);
+    // { dg-error "expected type, found variant of Wizard" "" { target *-*-* } .-1 }
+}
+}