From: Philip Herron <[email protected]>
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]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/cbf530387eaad3a200962a0937fea59fb0fca0a8
The commit has NOT been mentioned in any issue.
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4665
.../typecheck/rust-hir-type-check-expr.cc | 46 ++++++++++++++-----
gcc/testsuite/rust/compile/issue-4538.rs | 22 +++++++++
2 files changed, 57 insertions(+), 11 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/issue-4538.rs
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 8ed04d635..62f419766 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 000000000..fedc4f193
--- /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
+}
base-commit: 520f9e075285ee1759f99f88a0fa3b3506e95615
--
2.54.0