| //@ run-pass | |
| #![allow(dead_code)] | |
| #![allow(unused_assignments)] | |
| // Test control flow to follow label_break_value semantics | |
| fn label_break(a: bool, b: bool) -> u32 { | |
| let mut v = 0; | |
| 'b: { | |
| v = 1; | |
| if a { | |
| break 'b; | |
| } | |
| v = 2; | |
| if b { | |
| break 'b; | |
| } | |
| v = 3; | |
| } | |
| return v; | |
| } | |
| // Test that values can be returned | |
| fn break_value(a: bool, b: bool) -> u32 { | |
| let result = 'block: { | |
| if a { break 'block 1; } | |
| if b { break 'block 2; } | |
| 3 | |
| }; | |
| result | |
| } | |
| // Test nesting of labeled blocks | |
| // here we only check that it compiles | |
| fn label_break_nested() { | |
| 'b: { | |
| println!("hi"); | |
| if false { | |
| break 'b; | |
| } | |
| 'c: { | |
| if false { | |
| break 'b; | |
| } | |
| break 'c; | |
| } | |
| println!("hello"); | |
| if true { | |
| break 'b; | |
| } | |
| } | |
| } | |
| // Tests for mixing labeled blocks with loop constructs | |
| // This function should be the identity function | |
| fn label_break_mixed(v: u32) -> u32 { | |
| let mut r = 0; | |
| 'b: { | |
| // Unlabeled break still works | |
| // (only crossing boundaries is an error) | |
| loop { | |
| break; | |
| } | |
| if v == 0 { | |
| break 'b; | |
| } | |
| // Labeled breaking an inner loop still works | |
| 'c: loop { | |
| if r == 1 { | |
| break 'c; | |
| } | |
| r += 1; | |
| } | |
| assert_eq!(r, 1); | |
| if v == 1 { | |
| break 'b; | |
| } | |
| // Labeled breaking an outer loop still works | |
| 'd: loop { | |
| { | |
| if v == r { | |
| break 'b; | |
| } | |
| if r == 5 { | |
| break 'd; | |
| } | |
| r += 1; | |
| } | |
| } | |
| assert_eq!(r, 5); | |
| assert!(v > r); | |
| // Here we test return from inside a labeled block | |
| return v; | |
| } | |
| r | |
| } | |
| fn label_break_match(c: u8, xe: u8, ye: i8) { | |
| let mut x = 0; | |
| let y = 'a: { | |
| match c { | |
| 0 => break 'a 0, | |
| v if { if v % 2 == 0 { break 'a 1; }; v % 3 == 0 } => { x += 1; }, | |
| v if { 'b: { break 'b v == 5; } } => { x = 41; }, | |
| _ => 'b: { | |
| break 'b (); | |
| }, | |
| } | |
| x += 1; | |
| -1 | |
| }; | |
| assert_eq!(x, xe); | |
| assert_eq!(y, ye); | |
| } | |
| #[allow(unused_labels)] | |
| fn label_break_macro() { | |
| macro_rules! mac1 { | |
| ($target:lifetime, $val:expr) => { | |
| break $target $val; | |
| }; | |
| } | |
| let x: u8 = 'a: { | |
| 'b: { | |
| mac1!('b, 1); | |
| }; | |
| 0 | |
| }; | |
| assert_eq!(x, 0); | |
| let x: u8 = 'a: { | |
| 'b: { | |
| if true { | |
| mac1!('a, 1); | |
| } | |
| }; | |
| 0 | |
| }; | |
| assert_eq!(x, 1); | |
| } | |
| pub fn main() { | |
| assert_eq!(label_break(true, false), 1); | |
| assert_eq!(label_break(false, true), 2); | |
| assert_eq!(label_break(false, false), 3); | |
| assert_eq!(break_value(true, false), 1); | |
| assert_eq!(break_value(false, true), 2); | |
| assert_eq!(break_value(false, false), 3); | |
| assert_eq!(label_break_mixed(0), 0); | |
| assert_eq!(label_break_mixed(1), 1); | |
| assert_eq!(label_break_mixed(2), 2); | |
| assert_eq!(label_break_mixed(3), 3); | |
| assert_eq!(label_break_mixed(4), 4); | |
| assert_eq!(label_break_mixed(5), 5); | |
| assert_eq!(label_break_mixed(6), 6); | |
| label_break_match(0, 0, 0); | |
| label_break_match(1, 1, -1); | |
| label_break_match(2, 0, 1); | |
| label_break_match(3, 2, -1); | |
| label_break_match(5, 42, -1); | |
| label_break_match(7, 1, -1); | |
| label_break_macro(); | |
| } |