[gcc r17-2260] gccrs: Fix typechecking of block expression and labels

Arthur Cohen via Gcc-cvs <[email protected]>
Newsgroups gmane.comp.gcc.cvs
Message-ID <[email protected]>
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
+}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.