Skip to content

gccrs: Run block cleanup for unlabeled break and continue - #4710

Open
Lishin1215 wants to merge 1 commit into
Rust-GCC:masterfrom
Lishin1215:drop-unlabeled-break-continue
Open

gccrs: Run block cleanup for unlabeled break and continue#4710
Lishin1215 wants to merge 1 commit into
Rust-GCC:masterfrom
Lishin1215:drop-unlabeled-break-continue

Conversation

@Lishin1215

@Lishin1215 Lishin1215 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

This PR builds on the existing HIR::BlockExpr TRY_FINALLY_EXPR cleanup infrastructure.
It keeps unlabeled break and continue inside the block body, so block cleanup
can run when they leave scopes.

It covers these unlabeled cases:

  1. continue
loop {
    let _x = Droppable;
    continue;
}
  1. tail-position continue
loop {
    let _x = Droppable;
    continue
}
  1. break
loop {
    let _x = Droppable;
    break;
}
  1. tail-position break
loop {
    let _x = Droppable;
    break
}
  1. break with a value
let x = loop {
    let _x = Droppable;
    break 123;
};

The tests use loop instead of while to keep the coverage focused on cleanup behavior.


Follow-up work:

  • Labeled break / continue
  • Tail-position return cleanup

While testing this change, I also found a separate issue that should be
tracked outside this PR:

  1. A loop-body local can be dropped twice in some cases. This likely needs
    drop/initialized flags.
fn test_continue_double_drop() {
    let mut done = false;

    loop {
        if done {
            break;
        }

        let _outer = Droppable;

        {
            let _inner = Droppable;
            done = true;
            continue;
        }
    }
}

@Lishin1215
Lishin1215 force-pushed the drop-unlabeled-break-continue branch from a503c0a to 487ed1d Compare July 16, 2026 13:03
expr.get_locus ());
ctx->add_statement (assignment);
}
else if (compiled_expr != nullptr && is_control_flow_expr (final_expr)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This handles tail-position control flow like { break } and { continue }.
The generated jump still needs to be added to the block body, otherwise it is
created but never emitted into the final block.

Make unlabeled break return its translated tree, matching continue.

Emit tail-position break and continue expressions as statements so
they stay inside the TRY_FINALLY_EXPR body and run block cleanup.

gcc/rust/ChangeLog:

	* backend/rust-compile-block.cc (is_control_flow_expr): New helper.
	(CompileBlock::visit): Emit tail-position break and continue
	expressions as statements.
	* backend/rust-compile-expr.cc (CompileExpr::visit): Return the
	translated expression for unlabeled break instead of emitting it
	directly.

gcc/testsuite/ChangeLog:

	* rust/execute/drop-unlabeled-break-continue.rs: New test.

Signed-off-by: Lishin <lishin1008@gmail.com>
@Lishin1215
Lishin1215 force-pushed the drop-unlabeled-break-continue branch from 487ed1d to c1150be Compare July 21, 2026 16:36
@Lishin1215

Copy link
Copy Markdown
Contributor Author

I also opened an issue for the double-drop case I mentioned in the PR description:
#4717

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant