https://gcc.gnu.org/g:c37c865fa87a5997fcf6578a4fc42784c660d0dc

commit r17-2260-gc37c865fa87a5997fcf6578a4fc42784c660d0dc
Author: Philip Herron <[email protected]>
Date:   Mon Jun 29 19:22:53 2026 +0100

    gccrs: Fix typechecking of block expression and labels
    
    Tail expressions were always ignoring the context here and returning
    unit-type. This patch respects the label context here properly.
    
    Fixes Rust-GCC#4538
    
    gcc/rust/ChangeLog:
    
            * typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit): 
respect context for labels
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/issue-4538.rs: New test.
    
    Signed-off-by: Philip Herron <[email protected]>

Diff:
---
 gcc/rust/typecheck/rust-hir-type-check-expr.cc | 46 ++++++++++++++++++++------
 gcc/testsuite/rust/compile/issue-4538.rs       | 22 ++++++++++++
 2 files changed, 57 insertions(+), 11 deletions(-)

diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc 
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 8ed04d635fe9..62f4197668f0 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -692,6 +692,7 @@ TypeCheckExpr::visit (HIR::UnsafeBlockExpr &expr)
 void
 TypeCheckExpr::visit (HIR::BlockExpr &expr)
 {
+  bool has_label = expr.has_label ();
   if (expr.has_label ())
     context->push_new_loop_context (expr.get_mappings ().get_hirid (),
                                    expr.get_locus ());
@@ -718,6 +719,8 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
        {
          rust_error_at (s->get_locus (), "failure to resolve type");
          context->pop_expected_type ();
+         if (has_label)
+           context->pop_loop_context ();
          return;
        }
 
@@ -732,27 +735,48 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr)
 
   context->pop_expected_type ();
 
+  TyTy::BaseType *tail_expr_type = nullptr;
   if (expr.has_expr ())
     {
       context->push_expected_type (outer_expected);
-      infered = TypeCheckExpr::Resolve (expr.get_final_expr ())->clone ();
+      tail_expr_type = TypeCheckExpr::Resolve (expr.get_final_expr ());
       context->pop_expected_type ();
     }
-  else if (expr.is_tail_reachable ())
-    infered = TyTy::TupleType::get_unit_type ();
-  else if (expr.has_label ())
+
+  TyTy::BaseType *label_context_type = nullptr;
+  bool label_context_type_infered = false;
+  if (has_label)
     {
-      TyTy::BaseType *loop_context_type = context->pop_loop_context ();
+      label_context_type = context->pop_loop_context ();
 
-      bool loop_context_type_infered
-       = (loop_context_type->get_kind () != TyTy::TypeKind::INFER)
-         || ((loop_context_type->get_kind () == TyTy::TypeKind::INFER)
-             && (((TyTy::InferType *) loop_context_type)->get_infer_kind ()
+      label_context_type_infered
+       = (label_context_type->get_kind () != TyTy::TypeKind::INFER)
+         || ((label_context_type->get_kind () == TyTy::TypeKind::INFER)
+             && (((TyTy::InferType *) label_context_type)->get_infer_kind ()
                  != TyTy::InferType::GENERAL));
+    }
 
-      infered = loop_context_type_infered ? loop_context_type
-                                         : TyTy::TupleType::get_unit_type ();
+  if (tail_expr_type != nullptr)
+    {
+      if (label_context_type_infered)
+       {
+         if (tail_expr_type->get_kind () == TyTy::TypeKind::NEVER)
+           infered = label_context_type;
+         else
+           infered = unify_site (
+             expr.get_mappings ().get_hirid (),
+             TyTy::TyWithLocation (label_context_type),
+             TyTy::TyWithLocation (tail_expr_type,
+                                   expr.get_final_expr ().get_locus ()),
+             expr.get_locus ());
+       }
+      else
+       infered = tail_expr_type;
     }
+  else if (label_context_type_infered)
+    infered = label_context_type;
+  else if (expr.is_tail_reachable ())
+    infered = TyTy::TupleType::get_unit_type ();
   else
     {
       // FIXME this seems wrong
diff --git a/gcc/testsuite/rust/compile/issue-4538.rs 
b/gcc/testsuite/rust/compile/issue-4538.rs
new file mode 100644
index 000000000000..fedc4f193a91
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4538.rs
@@ -0,0 +1,22 @@
+#![feature(no_core)]
+#![no_core]
+
+extern "C" {
+    fn printf(s: *const i8, ...);
+}
+
+fn dump_number(num: i32) {
+    unsafe {
+        let a = "%i\n\0";
+        let c = a as *const str as *const i8;
+        printf(c, num);
+    }
+}
+
+fn main() -> i32 {
+    let c = 'block_c: {
+        break 'block_c 555;
+    };
+    dump_number(c);
+    0
+}

Reply via email to