| // run-pass |
| #![allow(dead_code)] |
| #![allow(unused_assignments)] |
| #![feature(label_break_value)] |
| |
| // 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 |
| } |
| |
| 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); |
| |
| // FIXME: ensure that labeled blocks work if produced by macros and in match arms |
| } |