[][src]Attribute Macro forward_goto::rewrite_forward_goto

#[rewrite_forward_goto]

This macro will rewrite the annotated function so that the control-flow will go from a goto forward_goto!('label) directly to a corresponding label forward_label!('label).

This is achieved by wrapping necessary statements into loops and jump to their ends via break. Because of this implementation it is only possible to jump forward in the control-flow and not backwards. This, however, implies that all normal rust features — especially the borrow checker — work as expected.

For gotos and labels apply multiple restrictions:

  1. Every goto has at most one corresponding label, but multiple gotos can go to the same label.
  2. Only forward jumps are allowed, meaning that the goto must come before the label. in the code. Backward jumps are not allowed. 'Side jumps' (i.e. from a then-branch into an else-branch) are possible, as long as the goto is physically before the label.
  3. Any statement after a label in the control-flow may not be the result statement of a block until all current labels are rewired to their corresponding gotos.
This example is not tested
#[rewrite_forward_goto]
fn test() -> i32 {
    forward_goto!('into_block);
     
    let result = {
        forward_label!('into_block);
        "the result" // <- error
    }
 
    42 // would be allowed, because it's outside of 'into_block influence
}

Because of they way the rewriting is done, it is only possible to use definitions that are reachable on all code paths.

#[rewrite_forward_goto]
fn test(b: bool) {
    fn f1() {}
 
    if b {
        forward_goto!('jump);
    }
 
    fn f2() {}
     
    {
        f2(); // f2 can be used here
        forward_label!('jump);
        f1();
        // f2 cannot be used here
    };
 
    f1();
}