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 +}
